Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
maxLevel2

...


...

Anchor

...

developing_

...

dashboard_

...

plugins_

...

for_the_

...

monitoring_framework
developing_dashboard_plugins_for

...

_the_

...

monitoring_framework
Developing Dashboard Plugins for the Monitoring Framework


Panel
borderColor#0081C0
titleColor#0081C0

The following applies to XperienCentral versions R29 R24.1 and higher.

To ensure that the Is Used in functionality can detect whether the following content is being used, follow the instructions given.

Custom Elements

Implement the method getReferencedContentItems() defined in the nl.gx.webmanager.cms.element.Element interface. Return an array of all content items that are being referenced by the custom element.

Custom Media Items

Implement the method getReferencedContentItems() defined in the nl.gx.webmanager.cms.mediarepository.MediaItemVersion interface. Return an array of all content items that are being referenced by the custom media item.

Custom Page Metadata

Implement the method getReferencedContentItems() defined in the nl.gx.webmanager.cms.core.PageMetaData interface. Return an array of all content items that are being referenced by the custom page metadata.

HTML
<br /><br />
Panel
borderColor#0081C0
titleColor#0081C0

The following applies to XperienCentral versions 10.22.0 and higher.

The Is Used In widget shows an overview of content items that are using the currently selected content item. In XperienCentral versions 10.22.0 and earlier, the usage of content items referring to a custom content type was not detected for content items from a custom content type, The widget would only show a count of 0 used content items. The API of several content items in XperienCentral has been extended with a method for implementing this used-in relationship for custom content types. This functionality is available via the new abstract method:

Code Block
themeEclipse
ContentItem<?>[] getReferencedContentItems();

For all custom content items that implement or extend one of the following interfaces and classes:

  • Element
  • ElementImpl
  • MediaItemVersion
  • MediaItemVersionImpl
  • TemporaryRichTextInlineElement

The result of this method is the list of used content items (as defined by the projects requirements). The following is a code snippet from a custom content type (extending MediaItemVersion) which implements the method getReferencedContentItems().

Code Block
themeEclipse
@Override
   @Property
   public String getReferencedContentIds() {
   return JcrUtil.getString(getPrivateNode(), WCBConstants.NAMESPACE_PREFIX + ":referencedcontentids");
   }
@Override
   public void setReferencedContentIds(String contentids) {
   JcrUtil.setString(getPrivateNode(), WCBConstants.NAMESPACE_PREFIX + ":referencedcontentids", contentids);
   }
public ContentItem<?>[] getReferencedContentItems() { List<ContentItem<?>> result = new ArrayList<ContentItem<?>>();
   if (getReferencedContentIds() != null && !"".equals(getReferencedContentIds())) {
   Session session = getSessionManager().getActiveSession();
   if (session != null) {
   for (String contentid : getReferencedContentIds().split(",")) {
   try {
   result.add((MediaItem) session.getWrapper(new Integer(contentid).intValue(), MediaItem.class));
   } catch (NumberFormatException e) {}
   }
   }
   }
   return result.toArray(new ContentItem[result.size()]);
}

Use in Page Metadata

It is also possible to define this method for custom page metadata. The method must be added to the page metadata class. Additionally, an adapter must be implemented that supplies the result of the method to the indexer service. The following are examples of implementations of both the method definition and the adapter:

Method Implementation

Code Block
themeEclipse
/**
   * Returns the content items that this element refers to.
   *
   * @return List of referred content items, or <code>null</code> if no content item is referenced.
   */
   @ReferField(stored = false, indexed = true, adapter = ContentReferenceFieldAdapter.class) ContentItem<?>[] getReferencedContentItems();

Adapter Implementation

Code Block
themeEclipse
package com.gxwebmanager.helloworld.helloworldpagemetadata.pagemetadata;
import java.util.Collections;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import nl.gx.webmanager.cms.core.RelatedDownloadLink;
import nl.gx.webmanager.cms.core.RelatedInternalLink;
import nl.gx.webmanager.cms.core.RelatedLink;
import nl.gx.webmanager.cms.core.RelatedMediaItemLink;
import nl.gx.webmanager.cms.core.RelatedResourceLink;
import nl.gx.webmanager.cms.mediarepository.MediaItemDownloadVersion;
import nl.gx.webmanager.services.contentdomain.api.ContentDomainException;
import nl.gx.webmanager.services.contentdomain.api.ContentDomainResolver;
import nl.gx.webmanager.services.contentindex.adapter.FieldAdapter;
import nl.gx.webmanager.services.framework.spi.FrameworkException;
import nl.gx.webmanager.services.framework.spi.FrameworkFactory;
   /**
   * Adapter that takes a content item, and returns a String-reference to it, e.g. page-32423. Logs
   * a warning and returns null if the given item could not be resolved.
   *
   * @see ContentDomainResolver
   */
public class ContentReferenceFieldAdapter implements FieldAdapter<Object> {
private static final Logger LOG = Logger.getLogger(ContentReferenceFieldAdapter.class.getName());
@Override
   public boolean isLanguageSpecific() {
   return false;
   }
@Override
   public Object adapt(Object item, Locale forLocale) {
   if (item == null) {
   return null;
   }
if (item instanceof RelatedLink) {
   return adaptLinkReference(item, forLocale);
   }
return getItemId(item);
   }
private String getItemId(Object item) {
   try {
   ContentDomainResolver resolver = (ContentDomainResolver) FrameworkFactory.getInstance().getFramework().getService(ContentDomainResolver.class.getName());
   return resolver.entityToId(item);
   } catch (FrameworkException | ContentDomainException e) {
   LOG.log(Level.WARNING, "Failed to retrieve content reference for " + item, e);
   }
   return null;
   }
private Object adaptLinkReference(Object link, Locale forLocale) {
   if (link instanceof RelatedInternalLink) {
   return adapt(((RelatedInternalLink) link).getPage(), forLocale);
   } else if (link instanceof RelatedMediaItemLink) {
   return adapt(((RelatedMediaItemLink) link).getMediaItem(), forLocale);
   } else if (link instanceof RelatedDownloadLink) {
   MediaItemDownloadVersion downloadVersion = ((RelatedDownloadLink) link).getInContextDownloadMediaItemDownloadVersion();
   if (downloadVersion != null) {
   String itemId = getItemId(downloadVersion.getContentItem());
   if (itemId != null) {
   return Collections.singletonMap("download", itemId);
   }
   }
   } else if (link instanceof RelatedResourceLink) {
   return adapt(((RelatedResourceLink) link).getResourceInstance(), forLocale);
   }
return null;
   }
}

Back to top

...

Panel
borderColor#0081C0
titleColor#0081C0

The following applies to XperienCentral versions R24.1 and higher.

In the wm-addon-monitoring Git repository there is sample code that shows how to develop your own dashboard plugin. This demo code is located in the wmaxmfdashboardplugindemo folder. This code (mainly written in Angular Typescript) will, when deployed,show up as a separate tab in the Monitoring Dashboard. You can use this project to get started creating your own plugin(s).

  • The main pom.xml of the bunde contains all the logic needed to build the Angular code for your plugin. It is a variant on the code that can be found in other bundles that use Angular-based code.

The code in the bundle is split into separate Java and Angular parts:

  • The Java part that implements the XMFDashboardPluginsProvider interface via the OSGI Activator.
  • The Angular part that implements an Angular library that can be loaded at runtime.

Java XMFDashboardPluginsProvider

This class implements the getDashboardPlugins() method that is called to by the monitoring framework on bundle load to determine which dashboard plugin(s) are contained within the bundle and how to load them correctly. The following information about the dashboard plugin has to be supplied here:

  • jsresource — The full filename (including path) of the Angular library Javascript resource that is built.
  • exportedModule — The module name that this library exports as a bootstrap (case-sensitive).
  • routedpath — The path under which the the Angular router should add the dashboard plugin in the main menu of the Monitoring Dashboard. Note that no conflicting paths are allowed so be sure to use an exclusive name for your plugin.
  • translationPath — The path where i18n JSON files for the ngx-translate mechanism are located. These translation files can be used for static translations in the tab you add.
  • menuNames — A set of names for your dashboard plugins, one for each locale you support (typically en_US, and nl_NL).
  • menuIcon — The icon to display in the main menu of the Monitoring Dashboard. It is the technical name of the Google material icon to use.

Angular Library

The project for the Angular library that makes up the visual part of the plugin is a standard Angular library that can be created via the Angular CLI (see https://angular.io/guide/creating-libraries).

It consists of

  • One module that ensures static translations via ngx-translate can be accessed (in the demo: demoplugin.module.ts).
  • One main component that is rendered by Angular as the content of your added tab in the dashboard (the demoplugin.component in the example).

In the main component you can add new custom indicators.

Generic code for the Monitoring Dashboard is located in the xmfdashboardframework package (version 1.0.1) which is installed via npm (the package is published on our local Nexus server). When changes in the generic code are required, this should be done in the xmfdashboardframework package and the build result should be published to NPM with a new version number. Normally this should not be required in order to create a plugin for the Monitoring Dashboard.

Two indicators are added by the example (http-backend-request-multinode-card and clusterinfo-card) which shows you how you could create indicator cards.

All the indicator cards are developed in the Angular Material style for the cards themselves, Angular Flex layout is used to place them on the canvas (see https://material.angular.io/ and https://github.com/angular/flex-layout). Please note since you are developing in an Angular library that is loaded at run-time by the main Monitoring Dashboard panel, you do not have the freedom to import anything from the npm. The main dashboard must be able to resolve the imports required. The following are supported:

'@angular/core'
'@angular/common'
'@angular/router'
'@angular/flex-layout'
'@angular/material'
'@ngx-translate/core'
'@angular/cdk/overlay'
'@angular/common/http'
'ngx-cookie-service'
'rxjs'
'rxjs/operators'
'chart.js'
'ng2-charts'
'@ngx-translate/http-loader'
'xmfdashboardframework'

Translation files for ngx-translate should be added under the assets folder (in the demo found under project/demoplugin/assets).

REST Services

The following REST services are offered by the xmfdashboardframework:

  • ClusterEventRestService — Retrieves the available cluster nodes in the installation.

  • IndicatorSetRestService — Retrieves indicator sets and the measured values in these sets as offered by the xmfframework.
  • IndicatorSetConfigurationRestService — Retrieves and updates the configuration parameters of indicator sets as offered by the xmfframework.
  • LocaleRestService — Retrieves the current locale in the edit environment.
  • WebsitesRestService — Retrieves the available websites in the installation.

Components

The following Angular/web-components are offered by the xmfdashboardframework:

...


In the wm-addon-monitoring Git repository there is sample code that shows how to develop your own dashboard plugin. This demo code is located in the wmaxmfdashboardplugindemo folder. This code (mainly written in Angular Typescript) will, when deployed,show up as a separate tab in the Monitoring Dashboard. You can use this project to get started creating your own plugin(s).

  • The main pom.xml of the bunde contains all the logic needed to build the Angular code for your plugin. It is a variant on the code that can be found in other bundles that use Angular-based code.

The code in the bundle is split into separate Java and Angular parts:

  • The Java part that implements the XMFDashboardPluginsProvider interface via the OSGI Activator.
  • The Angular part that implements an Angular library that can be loaded at runtime.

Java XMFDashboardPluginsProvider

This class implements the getDashboardPlugins() method that is called to by the monitoring framework on bundle load to determine which dashboard plugin(s) are contained within the bundle and how to load them correctly. The following information about the dashboard plugin has to be supplied here:

  • jsresource — The full filename (including path) of the Angular library Javascript resource that is built.
  • exportedModule — The module name that this library exports as a bootstrap (case-sensitive).
  • routedpath — The path under which the the Angular router should add the dashboard plugin in the main menu of the Monitoring Dashboard. Note that no conflicting paths are allowed so be sure to use an exclusive name for your plugin.
  • translationPath — The path where i18n JSON files for the ngx-translate mechanism are located. These translation files can be used for static translations in the tab you add.
  • menuNames — A set of names for your dashboard plugins, one for each locale you support (typically en_US, and nl_NL).
  • menuIcon — The icon to display in the main menu of the Monitoring Dashboard. It is the technical name of the Google material icon to use.

Angular Library

The project for the Angular library that makes up the visual part of the plugin is a standard Angular library that can be created via the Angular CLI (see https://angular.io/guide/creating-libraries).

It consists of

  • One module that ensures static translations via ngx-translate can be accessed (in the demo: demoplugin.module.ts).
  • One main component that is rendered by Angular as the content of your added tab in the dashboard (the demoplugin.component in the example).

In the main component you can add new custom indicators.

Generic code for the Monitoring Dashboard is located in the xmfdashboardframework package (version 1.0.1) which is installed via npm (the package is published on our local Nexus server). When changes in the generic code are required, this should be done in the xmfdashboardframework package and the build result should be published to NPM with a new version number. Normally this should not be required in order to create a plugin for the Monitoring Dashboard.

Two indicators are added by the example (http-backend-request-multinode-card and clusterinfo-card) which shows you how you could create indicator cards.

All the indicator cards are developed in the Angular Material style for the cards themselves, Angular Flex layout is used to place them on the canvas (see https://material.angular.io/ and https://github.com/angular/flex-layout). Please note since you are developing in an Angular library that is loaded at run-time by the main Monitoring Dashboard panel, you do not have the freedom to import anything from the npm. The main dashboard must be able to resolve the imports required. The following are supported:

'@angular/core'
'@angular/common'
'@angular/router'
'@angular/flex-layout'
'@angular/material'
'@ngx-translate/core'
'@angular/cdk/overlay'
'@angular/common/http'
'ngx-cookie-service'
'rxjs'
'rxjs/operators'
'chart.js'
'ng2-charts'
'@ngx-translate/http-loader'
'xmfdashboardframework'

Translation files for ngx-translate should be added under the assets folder (in the demo found under project/demoplugin/assets).

REST Services

The following REST services are offered by the xmfdashboardframework:

  • ClusterEventRestService — Retrieves the available cluster nodes in the installation.

  • IndicatorSetRestService — Retrieves indicator sets and the measured values in these sets as offered by the xmfframework.
  • IndicatorSetConfigurationRestService — Retrieves and updates the configuration parameters of indicator sets as offered by the xmfframework.
  • LocaleRestService — Retrieves the current locale in the edit environment.
  • WebsitesRestService — Retrieves the available websites in the installation.

Components

The following Angular/web-components are offered by the xmfdashboardframework:

  • AbstractMultiValueCard — The base-class that implements a basic pattern for handling indicator data
  • DoughnutGraphComponent (xmf-doughnut-graph) — Used to draw a doughnut graph
  • PieGraphComponent (xmf-pie-graph) — Used to draw a pie graph
  • IndicatorCardContentComponent (xmf-indicatorcard-content) —Used as a wrapper for the actual card content with a conforming height and look-and-feel
  • IndicatorCardHeaderComponent (xmf-indicatorcard-header) —Used as the default header for a card showing settings and refresh icons
  • MultiValueCardComponent (xmf-multivalue-card) — Used to display a default styled card with a row or column of indicators
  • MultiValueContentComponent (xmf-multivalue-content) —Used to display a row or column of indicators
  • SingleValueContentComponent (xmf-singlevalue-content) —Used to display a single indicators

When developing a new card the following pattern can be followed. This is a class that implements the data layer of the indicator set to be visualized and it extends AbstractMultiValueCard:

<mat-card>
  <xmf-indicatorcard-header></xmf-indicatorcard-header>
  <xmf-indicatorcard-content>
     <Specific content of the card>
  </xmf-indicatorcard-content>
</mat-card>

In the wmaxmfdashboard main dashboard, several examples can be found on how to use the xmfdashboardframework.

Developing Your Own Indicators

The explanation above only describes how to create a Monitoring Dashboard plugin but does not cover how to develop your own indicator set(s). That is done entirely in Java. See the wmaxmfindicators bundle for an example of how to create your own custom indicators. As a starting point you should implement an XMFIndicatorProvider that enables the registration of your custom indicators. See the file DefaultIndicatorsServiceImpl.java in wmaxmfindicators. Refer to the Javadoc for wmaxmfapi in the wm-addon-monitoring package for the interfaces offered by the framework.


Back to top



...

Custom Content and the Is Used in Widget
Anchor
custom_media_items_and_the_is_used_in_widget
custom_media_items_and_the_is_used_in_widget


Panel
borderColor#0081C0
titleColor#0081C0

The following applies to XperienCentral versions 10.22.0 and higher.


The Is Used In widget shows an overview of content items that are using the currently selected content item. In XperienCentral versions 10.22.0 and earlier, the usage of content items referring to a custom content type was not detected for content items from a custom content type, The widget would only show a count of 0 used content items. The API of several content items in XperienCentral has been extended with a method for implementing this used-in relationship for custom content types. This functionality is available via the new abstract method:


Code Block
themeEclipse
ContentItem<?>[] getReferencedContentItems();


For all custom content items that implement or extend one of the following interfaces and classes:

  • Element
  • ElementImpl
  • MediaItemVersion
  • MediaItemVersionImpl
  • TemporaryRichTextInlineElement

The result of this method is the list of used content items (as defined by the projects requirements). The following is a code snippet from a custom content type (extending MediaItemVersion) which implements the method getReferencedContentItems().


Code Block
themeEclipse
@Override
   @Property
   public String getReferencedContentIds() {
   return JcrUtil.getString(getPrivateNode(), WCBConstants.NAMESPACE_PREFIX + ":referencedcontentids");
   }
@Override
   public void setReferencedContentIds(String contentids) {
   JcrUtil.setString(getPrivateNode(), WCBConstants.NAMESPACE_PREFIX + ":referencedcontentids", contentids);
   }
public ContentItem<?>[] getReferencedContentItems() { List<ContentItem<?>> result = new ArrayList<ContentItem<?>>();
   if (getReferencedContentIds() != null && !"".equals(getReferencedContentIds())) {
   Session session = getSessionManager().getActiveSession();
   if (session != null) {
   for (String contentid : getReferencedContentIds().split(",")) {
   try {
   result.add((MediaItem) session.getWrapper(new Integer(contentid).intValue(), MediaItem.class));
   } catch (NumberFormatException e) {}
   }
   }
   }
   return result.toArray(new ContentItem[result.size()]);
}


Use in Page Metadata

It is also possible to define this method for custom page metadata. The method must be added to the page metadata class. Additionally, an adapter must be implemented that supplies the result of the method to the indexer service. The following are examples of implementations of both the method definition and the adapter:


Method Implementation


Code Block
themeEclipse
/**
   * Returns the content items that this element refers to.
   *
   * @return List of referred content items, or <code>null</code> if no content item is referenced.
   */
   @ReferField(stored = false, indexed = true, adapter = ContentReferenceFieldAdapter.class) ContentItem<?>[] getReferencedContentItems();


Adapter Implementation


Code Block
themeEclipse
package com.gxwebmanager.helloworld.helloworldpagemetadata.pagemetadata;
import java.util.Collections;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;
import nl.gx.webmanager.cms.core.RelatedDownloadLink;
import nl.gx.webmanager.cms.core.RelatedInternalLink;
import nl.gx.webmanager.cms.core.RelatedLink;
import nl.gx.webmanager.cms.core.RelatedMediaItemLink;
import nl.gx.webmanager.cms.core.RelatedResourceLink;
import nl.gx.webmanager.cms.mediarepository.MediaItemDownloadVersion;
import nl.gx.webmanager.services.contentdomain.api.ContentDomainException;
import nl.gx.webmanager.services.contentdomain.api.ContentDomainResolver;
import nl.gx.webmanager.services.contentindex.adapter.FieldAdapter;
import nl.gx.webmanager.services.framework.spi.FrameworkException;
import nl.gx.webmanager.services.framework.spi.FrameworkFactory;
   /**
   * Adapter that takes a content item, and returns a String-reference to it, e.g. page-32423. Logs
   * a warning and returns null if the given item could not be resolved.
   *
   * @see ContentDomainResolver
   */
public class ContentReferenceFieldAdapter implements FieldAdapter<Object> {
private static final Logger LOG = Logger.getLogger(ContentReferenceFieldAdapter.class.getName());
@Override
   public boolean isLanguageSpecific() {
   return false;
   }
@Override
   public Object adapt(Object item, Locale forLocale) {
   if (item == null) {
   return null;
   }
if (item instanceof RelatedLink) {
   return adaptLinkReference(item, forLocale);
   }
return getItemId(item);
   }
private String getItemId(Object item) {
   try {
   ContentDomainResolver resolver = (ContentDomainResolver) FrameworkFactory.getInstance().getFramework().getService(ContentDomainResolver.class.getName());
   return resolver.entityToId(item);
   } catch (FrameworkException | ContentDomainException e) {
   LOG.log(Level.WARNING, "Failed to retrieve content reference for " + item, e);
   }
   return null;
   }
private Object adaptLinkReference(Object link, Locale forLocale) {
   if (link instanceof RelatedInternalLink) {
   return adapt(((RelatedInternalLink) link).getPage(), forLocale);
   } else if (link instanceof RelatedMediaItemLink) {
   return adapt(((RelatedMediaItemLink) link).getMediaItem(), forLocale);
   } else if (link instanceof RelatedDownloadLink) {
   MediaItemDownloadVersion downloadVersion = ((RelatedDownloadLink) link).getInContextDownloadMediaItemDownloadVersion();
   if (downloadVersion != null) {
   String itemId = getItemId(downloadVersion.getContentItem());
   if (itemId != null) {
   return Collections.singletonMap("download", itemId);
   }
   }
   } else if (link instanceof RelatedResourceLink) {
   return adapt(((RelatedResourceLink) link).getResourceInstance(), forLocale);
   }
return null;
   }
}

...

Developing Your Own Indicators

...


Back to top



...

Developing Custom Bulk Actions

...

In a standard installation, XperienCentral users are managed in the Authorization component. Along with the Authorization component, there are two types of credentials sets that are not targeted at the editorial tasks but are infrastructure-related. By default these credential sets are managed by the following properties in the XperienCentral Setup Tool (General (R30 and older) tab):

These credentials sets are for:

...

This can be accomplished via your own integration component by creating a plugin that implements the Credentials Service Provider. When there is no plugin active that implements the credentials services, a look-up is done on the settings internal_http_use_authentication or internal_http_use_form_authentication in the "application_settings" section in the General (R30 and older) tab of the Setup Tool. If a plugin is active that implements the XperienCentral credentials service, the username/password combination from the plugin is used to authorize the user.

...