Widget Implementation

Source: This article refers to Widget Implementation


Attention: Custom widgets are implemented at your own risk and may result in application latencies and other issues. Widget support is currently in development and is subject to change. At this time, backward compatibility is NOT supported, which may result in compatibility issues between the application and the custom widget with subsequent releases.

Introduction

Widgets enable you to implement a self-contained function into the Planning Board of the Workforce Management app.

Current Limitations

  • Widgets can only be implemented in the Planning Board view of the Workforce Management app.
  • Translations are not currently possible for custom widget labels.
  • The title of the widget cannot be translated.
  • No styling can be reused from the application. A stylesheet must be provided within the custom widget.
  • Events that occur within the Workforce Management app cannot be registered.
  • There is no user interface available for managing widgets. It is recommended to use Postman or another API management tool to manage widgets for the Workforce Management app.

Widget Description

The following is a JSON and tabular description of a widget:

{ id: string; title: string; template: string; controller: Function; pages: string[]; companies: string[]; controllerAs: string; dataAs: string; }
Field Description
id Unique widget identifier.
title Widget title. This title will be displayed on widget header. The widget title cannot be translated.
template Widget template to be rendered
controller Name of controller written in JavaScript ES5
pages Where the widget is displayed (example: planner).
companies The company account for which the widget is implemented. Value should be equal to CompanyInfo_DTO.name field.
controllerAs Controller alias (access to functions and variables).
dataAs Property name of binded data to controller (dafault value: data)

Data Passed to Widget

The following data is passed from the application to the widget:

data= "{ grid: { fields: plannerCtrl.fields, columns: plannerCtrl.columns }, serviceCallFilter: { selectedItems: plannerCtrl.selectedServiceFilter }, techFilter: { selectedItems: plannerCtrl.scheduler.selectedFilter } }"
Page Field Object
planner serviceCall {id: 12}
activity {id: 34}  

Implementation Requirements

Compliance with ES5

ECMAScript (or ES) is a trademarked scripting-language specification standardized by ECMA. Widgets must be compliant with the ECMAScript 5.


Write Widget in IIFE

It is recommended tht widgets be written in IIFE (immediately-invoked function expression) of JavaScript, which creates a lexical scope for the widget using JavaScript’s function scoping.

The following is an example of a widget utilizing an IIFE expression:

(function() {
  return {
    id: 'my-widget-hello-world',
    title: 'Hello-world widget',
    template: '<h1>Hello !</h1>',
    controller: function($scope, myData) {
      this.getName = function() {
        return 'coresystems.ch'
      }
      
      // if data changes it binds to property myData (as defined in widget
      // config. see dataAs property)
      console.log(this.myData);
      // use collection watchers to track data changes
      // $scope.$watchCollection('<controllerAs>.<dataAs>', ...)
      $scope.$watchCollection('vm.myData', function(newData, oldData) {
        // do some useful stuff
      });
    },
    controllerAs: 'vm',
    dataAs: 'myData',
    pages: ['planner'],
    companies: ['exampleco', 'coresystems']
  }
})()

Widget Implementation

Note: There is currently no user interface to manage widgets. It is recommended to use an API management solution like Postman to upload and manage custom widgets for the Planning Board of the Workforce Management app. You must be familiar with the Data Model and the Query API in order to complete the widget implementation.
  1. Ensure user has permissions to Create and Update the Plugin and Attachment DTOs.
  2. Create new entry in Plugin DTO (type = widget) and keep track of the PLugin id number which will be used in the Attachment DTO.
  3. Convert JS code to Base 64.
  4. POST an Attachment object referencing the newly-created Plugin DTO to Attachment DTO:
    • In the fileContent you will copy/paste the Base 64-converted code generated in the previous step.
    • object.objectType= PLUGIN
    • In the obhectId field you will enter the Plugin ID.
  5. Change default screen configuration for CSPlanningBoard to include id of Plugin created in step 2:
"plugins": { "widgets": { "leftColumn": [], "centerColumn": [], "rightColumn": [ "4BCFB1A8035249FC97EE7215A44A6F82" ] } }

Appendix

Plugin DTO Example

{ "data": [ { "plugin": { "lastChanged": 123456786431, "createPerson": "ABC124564FD", "externalID": null, "groups": null, "owners": null, "title": "Example Widget", "type": "widget", "branches": null, "createDataTime": "2017-04-04T19:07:56Z", "syncObjectKPIs": null, "inactive": false, "udfMetaGroups": null, "location": null, "id": "51DC0E1234MNQRP546421234", // !important. Referenced in Attachment DTO. "udfValues": null, "lastChangedBy": "ABC124564FD", "syncStatus": "IN_CLOUD" } } ] } 

Example Widget

The following is an example of a widget for a Todo List:



(function() {
  var template = [
    '<md-card-content>',
      '<ul>',
        '<li ng-repeat="task in myCtrl.getTodoItems()">',
          '<input type="checkbox" ng-model="task.done">',
          '<span ng-style="myCtrl.getStyles(task)"></span>',
        '</li>',
      '</ul>',
    '</md-card-content>',
    '<md-card-actions layout="column" layout-align="start">',
      '<input ng-model="myCtrl.newTask" ng-enter="myCtrl.addTask()" />',
      '<md-button ng-click="myCtrl.addTask()">Add task</md-button>',
    '</md-card-actions>'
  ].join('');

  MyController.$inject = ['$interval', '$scope', 'data'];
  function MyController($interval, $scope, data) {
    this.$interval = $interval;
    this.$scope = $scope;
    this.data = data;
    this.newTask = '';
    this.todoItems = [
      {title: 'Create evaluated widget', done: true},
      {title: 'Get widgets via API', done: false}
    ];
  }
  
  MyController.prototype.getTodoItems = function getTodoItems() {
    return this.todoItems;
  };

  MyController.prototype.getStyles = function getStyles(task) {
    return !task.done ? {} : { 'text-decoration': 'line-through' };
  };

  MyController.prototype.addTask = function addTask() {
    if (this.newTask && this.newTask.trim()) {
      this.todoItems.push({
        title: this.newTask,
        done: false
      });
      this.newTask = '';
    }
  };

  MyController.prototype.getItems = function getItems() {
    return this.data && this.data.items ? this.data.items : [];
  };
  
  return {
    id: 'todo-list-widget',
    title: 'TODO LIST',
    template: template,
    controller: MyController,
    controllerAs: 'myCtrl',
    pages: ['planner'],
    companies: ['exampleco', 'SAP_uniQservice']
  }
})();

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

0 comments

Article is closed for comments.