Develop BPC widgets

This page describes the development of individual BPC widgets. A widget represents a specific view of a module that can be displayed and configured in the dashboard.

Definition

For a widget to be recognized as such by the BPC, it must be referenced in the interface class of the BPC module (see Frontend Interface module).

Ausschnitt der Interface-Klasse
Ext.define("template.BpcInterface", {
   extend : "BpcCommon.BpcInterface",
...
   requires : [
      "template.view.widget.TemplateWidget",
   ],
...
   config : {
...
      widgets : [
         "template.view.widget.TemplateWidget",
        ],
...
   }
});

The main class of the widget must contain the following attribute:

Ausschnitt aus der der Widget.js-Klasse
{
    "mixins" : [
          "BpcCommon.mixin.Widget"
   ]
}

The widget is thus given to the user for selection, see Add widget.

Examples of widget implementations can be viewed under Widgets in the Template Module.

Best Practice Tip

We recommend separating widgets into different subcomponents. A widget could therefore consist of 4 subcomponents:

  • A main class in which the widget’s views are managed (Widget.js).

  • A view in which the widget’s content is displayed (ContentPanel.js).

  • A view in which the widget can be configured (ConfigurationPanel.js).

  • A view in which the user is informed that the configuration is invalid or incomplete (WrongConfigurationPanel.js).

Main widget class (widget)

The default settings of the widget are located under the attribute statics.

  • WIDGET_NAME:
    The name that is offered to the user in the widget list (see Add widget). The name also serves as the title of the widget.
    The user can be given the option to customize this subsequently.

  • WIDGET_DESCRIPTION:
    The description that is offered to the user in the widget list (see Add widget).

    • WIDGET_ICON_CLS:
      The icon that is offered to the user in the widget list (see Add widget).

    • WIDGET_ADDITIONAl_ACTIONS:
      Additional buttons in the widget header.
      An array of objects with the attributes handler, iconCls and/or text can be specified.

The methods this.getWidgetConfiguration and this.setWidgetConfiguration are defined in the mixin and enable access to the widget settings.

When saving the settings, the event widgetConfigurationChange should be thrown so that the dashboard is aware of the change.

Beispiel Haupt-Widget-Klasse:
Ext.define("template.view.widget.TemplateWidget", {
   extend : "Ext.panel.Panel",

   mixins : [
      "BpcCommon.mixin.Widget"
   ],
   moduleId : "templateWidget",

   statics : {
      WIDGET_NAME               : "Template Widget",
      WIDGET_DESCRIPTION        : "Template Widget Description",
      WIDGET_ICON_CLS           : "x-fal fa-bar-chart",
      /* zusätzliche Aktionen können in den Widget-Header konfiguriert werden.*/
      WIDGET_ADDITIONAl_ACTIONS : [
         {
            iconCls : BpcCommon.Icons.EDIT,
            handler : function () {
               alert("additional Action");
            },
            text :"additional Action"
         }
      ]
   },
   additionalActionScope : true,
   /*Das Layout Card bietet sich an, da mit der Methode this.getLayout.setActiveItem(cmp)
    verschiedene Ansichten eingeblendet werden können.*/
   layout    : "card",
   minHeight : 300,


   initComponent : function () {
      const me  = this;

      /*Methode aus dem Mixin, die die WidgetKonfiguration aus den Settings zurückliefert */
      const widgetConfiguration =  me.getWidgetConfiguration();
      me.configuration = widgetConfiguration;

      me.callParent();

      /*Erzeugen der Konfigurations-Ansicht*/
      this.settingPanel = this.add({
         xtype               : "templateWidgetConfigurationPanel",
         widgetConfiguration : widgetConfiguration,
         listeners           : {
            saveWidgetConfiguration : me.onSaveConfiguration.bind(me),
         }
      });
      /*Erzeugen der falschen Konfigurations-Ansicht*/
      this.wrongConfigPanel = this.add({
         xtype     : "templateWidgetWrongConfigurationPanel",
         listeners : {
            showSettingPanel : me.onShowSettingPanel.bind(me),
         }
      });

      this.checkConfiguration();
   },

   onShowSettingPanel : function() {
      this.getLayout().setActiveItem(this.settingPanel);
   },

   configureWidget : function () {
      if (this.settingPanel.isVisible(true)) {
         this.getLayout().setActiveItem(this.contentPanel);
      } else {
         this.onShowSettingPanel();
      }
   },

/**
 *  Method die aus dem Widget header heraus aufgerufen werden kann.
 *  */
   refreshWidget : function () {
      console.log("refreshWidget");
   },

/**
 * Überprüfen der Widget-Settings auf ihre Gültigkeit
 * */
   checkConfiguration : function () {
      if (this.configuration.demoSetting === undefined || this.configuration.demoSetting === "") {
         this.getLayout().setActiveItem(this.wrongConfigPanel);
      } else {
         this.showContent();
      }
   },
/**
 *  Erzeugen und Anzeigen der Content View
 *  */
   showContent : function () {
      if (this.contentPanel === undefined) {
         this.remove(this.contentPanel);
      }
      this.contentPanel = this.add({
         xtype               : "templateWidgetContentPanel",
         widgetConfiguration : this.configuration,
      });
      this.getLayout().setActiveItem(this.contentPanel);
   },

/**
 * Speichern der Widget konfiguration
 * */
   onSaveConfiguration : function(newConfiguration) {
      /*methode aus dem mixin*/
      this.setWidgetConfiguration(newConfiguration);
      /*das Dashboard bekommt den Hinweis, dass sich etwas an den Settings geändert hat*/
      this.fireEvent("widgetConfigurationChange", this);
      this.checkConfiguration();
   }
});

Content view (ContentPanel)

These are components that are generated and rendered in HTML from the demoSetting setting.

Beispiel ContentPanel :
Ext.define("widget.templateWidget.ContentPanel", {
   extend  : "Ext.panel.Panel",
   html    : "ContentPanel",
   alias   : "widget.templateWidgetContentPanel",
   padding : 10,


   initComponent : function() {
      this.callParent(arguments);
      this.setHtml(`<h1>${ this.widgetConfiguration.demoSetting   }</h1>`);
   }
});
Content view

Configuration view (ConfigurationPanel)

This is the component that generates a UI for the widget settings and passes new configurations up to the widget main class when saving.

Beispiel Konfigurations-Panel:
Ext.define("widget.templateWidget.ConfigurationPanel", {
   extend  : "Ext.panel.Panel",
   alias   : "widget.templateWidgetConfigurationPanel",
   padding : "10",

   // should be set by parent
   widgetConfiguration : undefined,

   initComponent : function() {
      const me = this;
      me.dockedItems  = {
         xtype           : "toolbar",
         dock            : "bottom",
         ui              : "footer",
         overflowHandler : "scroller",

         items : [
            "->",
            {
               xtype     : "button",
               ui        : "primary",
               localized : {
                  text : "CORE_SAVE"
               },
               iconCls : "fal fa-save",
               handler : me.onSaveConfiguration.bind(me)
            }
         ],
      };
      me.items = [
         {
            xtype : "container",
            items : [
               {
                  xtype      : "bpcTextField",
                  fieldLabel : "Demo Setting",
                  value      : me.widgetConfiguration.demoSetting,
                  listeners  : {
                     change : me.setDemoSetting.bind(me)
                  }
               }
            ]
         }
      ];
      this.callParent(arguments);
   },
   setDemoSetting : function (e, value) {
      const me = this;
      me.widgetConfiguration.demoSetting  = value;
   },
   onSaveConfiguration : function () {
      const me = this;
      me.fireEvent("saveWidgetConfiguration", me.widgetConfiguration);
   }
});
Configuration view

Invalid configuration view (WrongConfigurationPanel)

This is the component that is displayed if the configuration is not valid. It contains a button that can be used to switch to the configuration view.

Beispiel Haupt-Widget-Klasse:
Ext.define("widget.templateWidget.WrongConfigurationPanel", {
   alias  : "widget.templateWidgetWrongConfigurationPanel",
   extend : "Ext.panel.Panel",

   layout : {
      type  : "vbox",
      pack  : "center",
      align : "middle"
   },
   padding : 10,

   initComponent : function() {
      const me = this;
      me.items = [
         {
            xtype     : "box",
            localized : {
               html : "CORE_INVALID_WIDGET_CONFIG"
            }
         },
         {
            xtype     : "button",
            localized : {
               text : "CORE_CONFIGURATION_SHOW"
            },
            iconCls : "x-fal fa-cog",
            handler : me.showSettingPanel.bind(me)
         }
      ];
      this.callParent(arguments);
   },

   showSettingPanel : function() {
      const me = this;
      me.fireEvent("showSettingPanel");
   }
});
Invalid configuration

Keywords: