10 Adding Custom Plugins

You can extend the BI Mobile App Designer functionality by adding custom plugins to integrate content generated by other applications into BI Mobile Apps. We provide an SDK to help you get started.

Topics:

10.1 What Are BI Mobile App Designer Custom Plugins?

You can add your own JavaScript plugin extensions to the app editor to add custom visualizations to your apps. After you add a plugin, an icon for your plugin displays in the Designer Insert menu. You can then drag and drop the custom component to the app page as you do any other app component.

Figure 10-1 Custom Plugins Shown in the Insert Menu

Surrounding text describes Figure 10-1 .

The Mobile App Designer Plugin SDK contains an environment to develop Oracle BI Mobile App Designer plugin components. The kit contains the plugin JavaScript file, the development server, and sample data. You can develop and test a plugin from your desktop.

Follow these guidelines to include a custom plugin:

  1. Setting Up Your Development Environment.

  2. Coding the Custom Plugin

  3. Testing Your Plugin

  4. Preparing Your Plugin for Upload

  5. Uploading to the Plugin Gallery

After you upload to the Plugin Gallery your plugin is immediately available within the App Designer.

10.2 Setting Up Your Development Environment

This section describes the tasks required to set up your environment and the files included in the SDK.

10.2.1 Download and Install the Prerequisites

To work with the SDK environment, you must install the following software. These steps are only required the first time you work with the SDK:

Node.js

Download Node.js from the Node.js website:

http://nodejs.org/

The Plugin SDK was developed with version v0.10.18; ensure that you install v0.10.0 or later.

Grunt

After installing Node.js, run the following node package manager (npm) command to install the Grunt command:

$ (sudo) npm install -g lru-cache grunt-cli
 

If you are behind a firewall, then provide the https proxy server setting to run the command as follows:

For Linux or Mac:

$ (sudo) https_proxy=http://<your https proxy server>:<proxy port>/ npm install -g lru-cache grunt-cli

For Windows:

c:\> set HTTPS_PROXY=http://<https proxy server>:<proxy port>/c:\> npm install lru-cache grunt-cli

10.2.2 Download the SDK with Sample Data

Now that your environment is set up, the next step is to download the SDK from the Mobile App Designer with some sample data. You download the SDK from within the Mobile App Designer. You can either create a new app or open an existing app. The key is to ensure that the data used by the app you choose is appropriate for the plugin that you are designing:

To download the SDK:

  1. Create a new app or open an app in edit mode that uses sample data appropriate for your plugin.

    For example, if your plugin creates a map visualization that requires country and city codes in the data source, ensure that the app data source includes these fields.

  2. Click Add Component and choose Plugins.

  3. Under Plugin SDK, click Create Plugin.

    Create Plugin
  4. In the Create Plugin dialog, enter the following

    • Plugin Name

    • Label fields - click + to select fields from your data source to provide sample data for label fields

    • Measure fields - click + to select fields from your data source to provide sample data for measure fields. When you add a measure field, you must also select an aggregation formula: Sum, Count, Count Distinct, Min, Max, or Average.

    • Data Format - select the format your plugin requires: Array of arrays, CSV, or D3 JSON.

    Download SDK dialog
  5. Click bimadplugin.zip to download the SDK to your local environment.

10.2.3 Files Included in the SDK

The following items are included in the SDK download:

Plugin file (<your_plugin_name>.js)

Your plugin file is located under the top level of the current directory. When you download the SDK from the Mobile App Designer, the data fields and data structure that you selected are coded in the Sample.js file. Use any text editor to finish coding the sample plugin file. Once you start the development server, the changes are immediately applied.

Gruntfile.js

Gruntfile.js controls the development server.

You do not need to make any changes to this file unless you want to rename your plugin file or start with a different .js file in another location. To specify a new file name or location, rename the pluginFile variable value in the gruntfile.js.

data Folder (data/data01.csv)

The sample data that you chose during the download the step is put in this folder.

If you wish to test additional sample data with your plugin, you can put csv files in the data folder to use for testing. Although the BI Mobile App Designer supports data from various sources, in the SDK environment, the data must be provided through a csv file.

Note that each data file must contain the same data that your plugin specifies. If the plugin definition contains two data field entries, then the csv file must be two columns in the same order as the field entries.This SDK server does not provide any sorting, reordering or regrouping at the time of serving data.

node_modules, package.json

These files are required to maintain the environment; do not edit or delete them.

assets

Use this folder to include any images, cascading style sheets (.css files), or JavaScript files that your plugin requires.

10.3 Coding the Custom Plugin

This section provides the specification of the plugin structure and describes the APIs provided for use with the plugin.

10.3.1 Plugin Structure

The plugin file is a simple JavaScript file. It has a basic structure that must be followed to ensure Mobile App Designer can use it. The following table shows the basic structure. Detailed descriptions of the objects and functions follow the sample.

Table 10-1 Overview of the plugin file

Component Description

id

(Required) Unique ID for the plugin

component

(Required) Comprises the plugin name, tooltip and icon

remoteFiles

(Optional) Supported .css and JavaScript files

properties

(Required) The plugin's defined properties, for example, the fields and data that are used for rendering

fields

The data fields you selected from the data source

dataType

Defines the data structure based on your choice of d3hierachy, CSV, or arrayOfArrays

render

(Required) the main function of the plugin

refresh

(Optional) Function called to refresh the data when data changed by click event


Here is a basic sample plugin file:

{
  id: 'com.oracle.xdo.Sample', //Change this default id to unique value before development
  component: {
    'name': 'Sample',
    'tooltip': 'Insert Sample'
  },
  properties: [
    {key: "width", label: "Width", type: "length", value: "500px"},
    {key: "height", label: "Height", type: "length", value: "400px"}
  ],
//These are the fields you selected from your data source
  fields: [
    {name: "Brand", caption: "Drop Brand Field Here", fieldType: "label", dataType: "string"},
    {name: "LOB", caption: "Drop LOB Field Here", fieldType: "label", dataType: "string"},
    {name: "Product Type", caption: "Drop Product Type Field Here", fieldType: "label", dataType: "string"},
    {name: "Revenue", caption: "Drop Revenue Field Here", fieldType: "measure", dataType: "number", formula: "summation"}
  ],
//dataType can be d3hierarchy or 'arrayOfArrays' depending on your selection
  dataType: 'd3hierarchy',
  render: function (context, containerElem, data, fields, props) {
    containerElem.innerHTML = '<h1>My First Plugin</h1>';
 
    var tableStr = '<div id="'+this.id+'_table">';
    tableStr += '<table>';
 
    data.forEach(function(row, rowNo, rows) {
      tableStr += '<tr>';
      row.forEach(function(col, colNo, cols) {
        tableStr += '<td>'+col+'<td>';
      });
      tableStr += '<tr>';
    });
    tableStr += '</table>';
    tableStr += '</div>';
 
    containerElem.innerHTML += tableStr;
  },
  refresh: function (context, containerElem, data, fields, props) {
    var tableStr = '<table>';
 
    data.forEach(function(row, rowNo, rows) {
      tableStr += '<tr>';
      row.forEach(function(col, colNo, cols) {
        tableStr += '<td>'+col+'<td>';
      });
      tableStr += '<tr>';
    });
    tableStr += '</table>';
 
    // update table with a bit of fancy transition
    $(document.getElementById(this.id+"_table")).html(tableStr).hide().fadeIn(1000);
  }
}

Following are more detailed descriptions of the JavaScript object fields:

id

The id is an identification string. Oracle recommends using the reverse domain name to avoid any naming conflicts, for example: "com.example.helloworld".

component

The following fields comprise the component object:

name

The name of the component. Example: "Hello World"

icon

The icon is the image that displays in the app designer Insert menu to represent the plugin. This field takes a URL that points to the icon image. Example: "http://www.example.com/img/smile.gif". If stored in the assets folder, use "asset://myicon.png"

tooltip

The tooltip message to display for the icon image. Example: "Hello World Plugin".

description

Optional description of the plugin. The description displays in the Plugin Gallery.

author

Optional author entry. The author displays in the Plugin Gallery.

cssClass

(Optional) Component CSS class selector to identify the plugin components.

render

The render function renders the plugin contents. The render function passes the following parameters:

context

Object containing the following information:

id

The id is an assigned instantiated component ID string. The system assures this ID is unique in the same template. Oracle recommends using this ID as a prefix or suffix to the HTML element that the plugin code generates. This practice prevents ID conflicts.

reportLocale

The locale assigned to the app layout.

containerElem

The container HTML element. The contents must be set to this element. This provides the Mobile App Designer the pointer to where your plugin visualization is to be rendered.

data

The variable that data is loaded into depending on the data structure you chose.

fields

See Fields Support.

props

Current properties. See Property Support.

10.3.2 Property Support

To add optional custom properties that display and can be set on the Properties pane of the App Designer, define them under the properties component. Array of property definition object can be set to this field. Construct the properties definition object from the following values.

key

A string value that specifies the property key. This value must be unique.

label

A string value that specifies the label displayed for this property in the Mobile App Designer Properties pane.

type

A string value that specifies the property type. The App Designer uses this value to open the appropriate editor to edit the property. The following values are supported for type:

  • string - creates a text entry box to enter string data.

  • number - creates a text entry box to enter numeric data.

  • bool - creates a True/False (boolean) choice option.

  • length - creates text entry box to enter length data and select units in px, in, cm, or pt.

  • color - displays a color-chooser for color selection.

  • font - displays the list of supported fonts for selection.

  • fontsize - displays the font size selector.

  • lov - creates a list of values. See options for creating the name-value pairs.

value

The initial value of the property. The value must follow the format of the type specified.

options

This parameter is valid only when the property type is "lov". The options parameter contains label-value pairs to define the list of values.

  • label - the label for each list item

  • value - the value for the label

10.3.2.1 Predefined Properties

The app editor sets the following property settings:

  • width: set based on available space

  • height: set based on available space

  • padding: 0px 0px 0px 0px

  • margin: 0px 0px 0px 0px

  • border-top: 0px none #000000

  • border-left: 0px none #000000

  • border-right: 0px none #000000

  • border-bottom: 0px none #000000

These properties can be updated within the app editor at design time.

10.3.3 Fields Support

The sample JavaScript file generated by the SDK includes the fields definitions for the fields that you specified in the download dialog.

These fields enable users to drag-and-drop data columns from the data source to your plugin for custom visualizations of the data. The field information is specified in the fields component of the plugin structure. The field definition consists of name, caption, fieldType, and dataType. A field can have a fieldType of label or measure. For measure fields, additionally specify a formula.

10.3.3.1 Defining the Data Fields

The following example shows data field definitions:

{
  id: "com.oracle.xdo...",
  component: {
    name: "Field Test"
  }
  fields:
  [
    {name: "labelField", caption: "Drop Label Field Here", fieldType:"label", dataType:"string"},
    {name: "dataField", caption: "Drop Data Field Here", fieldType:"measure", dataType: "number", formula: "summation"}                  
  ],
}

For each field the following is defined. You can update these attributes in the plugin file.

  • name

  • caption - text that the app editor displays for the field. For example: "Drop Label Field Here".

  • fieldType - valid values are "label" and "measure".

  • dataType - the following data types are supported:

    • string (text string, default)

    • number (number, including integer and float)

    • date (XML date format)

    The data type of the element that you drag and drop from the data model structure in the app editor must match the dataType defined here.

  • formula - when the fieldType is "measure" specify a default formula. The following are supported:

    • count

    • count-distinct

    • summation

    • average

    • maximum

    • minimum

    • first

    • last

Field

Users can update Field properties in the App Designer's property editor. This information can then be accessed by the fields variable in the render function arguments at run time.

  • field - path to the field in the data source

  • fieldFormula - the field formula; must be null when fieldType="label"

  • fieldType - the field type: "label" or "measure" (copied from the definition)

  • dataType - the data type: "string", "number", or "date" (copied from the definition)

  • label - the label string specified n the Property editor

10.3.4 Formatting Data

You can add data formatting option to your plugin using an API. This method enables designers using your plugin to format date and numeric data into localized strings.The data formatting option is exposed in the designer on the Properties pane when the data field is clicked. The app designer can choose a predefined format or enter a custom Java mask. This information is then available in the plugin's field metadata with the property field.formatMask. This information is required for the xdo.api.format.

Figure 10-2 Data Formatting Feature for Plugin Shown in the Properties Pane

Surrounding text describes Figure 10-2 .

10.3.4.1 Method Summary

The method returns a function that can be used to format the data. If a bad parameter is passed, or no formatMask is provided, the formatter will return a toString method.

10.3.4.2 Method Parameters

The method parameters are described in the following table:

Table 10-2 Parameters for xdo.api.format

Data Type Parameter Name Description

String

dataType

Can be numeric or date, other data types are ignored

String

formatMask

Java style format mask. If no mask is provided the method returns an identity function.


10.3.4.3 Method Signature

      var formatter = xdo.api.format(dataType, formatMask);

10.3.4.4 Method Usage

      render: function (context, container, data, fields, props) {
        var formatter = d3.format('.2f');
        var numericField = field[2];
        //security check for method availability.
        if (xdo.api.format)
          formatter = xdo.api.format(numericField.dataType, numericField.formatMask);
        container.innerHTML = formatter(data[1][2]);
      }

10.3.4.5 Alternative Usage

Format API can also be used by hard-coding the first two parameters. Use this approach when you want to provide a default format for the data.

Example:

      //Numeric format will produce $ 1,300.00
      var numericFormat = xdo.api.format('numeric', '$ #,##0.00');
      //Date formatter will produce 12/1/15
      var dateFormat = xdo.api.format('date', 'M/d/yy');

10.3.5 JavaScript APIs That Can Be Used in Custom Plugins

The following JavaScript APIs are available to use in custom plugins:

  • handleClickEvent Method

    Captures tapped (selected) field information to send to the system.

  • getPixelValue Method

    Returns the pixel value from the length string value. The system uses 96 dots per inch (dpi), which is the same as most browsers.

10.3.5.1 handleClickEvent Method

This method captures the tapped (or selected) field information to send to the system.

Signature

xdo.api.handleClickEvent(info)

This method takes the following parameter:

info

Clicked field information object.

The structure of the object is:

Object Structure
{
  id: [component id],
  [
    {
      field: [xpath to the element],
      value: [filter value]
    },
    {
      field: [xpath to the element],
      value: [filter value]
    },
  ]

10.3.5.2 getPixelValue Method

This method returns the pixel value from the length string value. The system uses 96 dpi, which is the same as most browsers.

Signature

xdo.api.getPixelValue(lengthString)

The method takes one parameter:

lengthString

A string value that specifies the length. Supported units are "px", "pt", "in", and "cm".

10.4 Accessing Data at Run Time

Typically, calculated data is stored in the rows variable of the render function. To leverage D3.js libraries, use a JavaScript object.

10.4.1 Accessing Data Stored in rows Array

At runtime, calculated data is stored in the rows variable of the render function. The rows variable is an array type and each rows element has another array for keeping column information. The following render function implementation displays data in HTML:

 render: function(context, containerElem, rows, fields, props) {
   // setup column
   var html = '<table>';
   for (var i=0, rowCount=rows.length; i<rowCount; i++)
   {
     html += "<tr>";
     var col = rows[i];
     for (var j=0, colCount=col.length; j<colCount; j++)
     {
       html += "<td>";
       html += col[j];
       html += "</td>";
     }
     html += "</tr>";
   }
  html += '</table>';
  containerElem.innerHTML = html;
 }

10.4.2 Accessing Data Through a JavaScript Object

To support visualizations using the D3.js JavaScript library, pass data using the "d3hierarchy" datatype. With this data type, the render function is called with a JavaScript object instead of arrays of rows. The JavaScript object has obj.node and obj.children for node or obj.value and obj.value for leaf.

For example:

node example
{
  name: "root"
  children: [
     {name: "child A", value: 1}
     {name: "child B", value: 2}
  ]
}

To use this data type, add dataType: "d3hierarchy" to the plugin definition.

For example:

{
  id: "com.oracle.xdo...",
  component: {
    name: "Field Test"
  }
  dataType: "d3hierarchy",
  fields:
  [
    {name: "labelField", caption: "Drop Label Field Here", fieldType:"label", dataType:"string"},
    {name: "dataField", caption: "Drop Data Field Here", fieldType:"measure", dataType: "number", formula: "summation"}                  
  ],
  render: function(context, containerElem, node, fields, props) {
    // setup column
    var html = node.value
    ....

If no data field information is defined in the plugin definition, null is passed to the node (or rows) argument.

10.4.3 Including Images at Run-time

To include images in your plugin at run-time, for example to display a background image in the app for your component:

  1. Place the image file in the assets folder.

    You must add the image file to the SDK's assets folder before you deploy your plugin.

  2. Set the URL in your plugin code as follows:

    io/viewer/get-plugin-asset/<your plugin id>/<image file>
    

    For example:

    io/viewer/get-plugin-asset/com.oracle.bimad.Donut/donut.png
    

10.5 Testing Your Plugin

To start the development server, run the following command:

$ grunt server

This command starts the Web server with port 9000 and opens the plugin simulator page.

10.6 Preparing Your Plugin for Upload

To create the archive file appropriate for uploading to the Plugin Gallery, run the following command:

$ grunt archive

This command packages up the required files and creates a .xmp file that can be uploaded to the Plugin gallery.

10.7 Uploading to the Plugin Gallery

To make your plugin available in the BI Mobile App Designer, upload it to the plugin gallery. You also manage your plugins from the Plugin Gallery. Access the plugin gallery from the BI Mobile App Designer Administration page. You must have Administrator privileges to access the Administration page.

Alternative Upload Method:

If you prefer to upload from your development session, you can run the command
$ grunt deploy

At the prompts, enter:

  • server URL

  • administrator username and password

  • the destination plugin directory on the server

The deploy command deploys the plugin to the destination folder and creates a .session file in your project. The .session captures the session information you entered enabling you to run the deploy command again without re-entering this information.

10.7.1 Accessing the Plugin Gallery

To access the BI Mobile App Designer Administration page and the Plugin Gallery:

  1. From Oracle BI EE, click Administration.

  2. On the Oracle Business Intelligence Administration page, click Manage BI Mobile App Designer.

    Click Manage BI Mobile App Designer
  3. On the Mobile App Designer Administration page click Plugin Gallery as shown in Figure 10-3.

    Figure 10-3 Administration Page

    Administration page showing Plugin Gallery

10.7.2 Uploading Plugins

To upload a new plugin to the Plugin Gallery:

  1. On the Plugin Gallery page, click Add Plugin.

    Surrounding text describes plugin_gallery.gif.
  2. In the Add Plugin dialog drag the plugin file from your file system to the dialog, or use the Browse button to locate and select it. from your file system.

  3. Click Upload.

  4. The plugin is now visible in the Plugin Gallery and available in the Mobile App Designer.

10.7.3 Managing Plugins

The Plugin Gallery displays all the plugins that are available in your system.

To delete a plugin from the gallery, click the Delete icon next to the plugin name.

To get more information about a plugin, click the plugin name to view the Plugin Details.