12 Create Custom Data Action Plug-ins

You can create custom data action plug-ins to use in Oracle Analytics.

Data action plug-ins extend Oracle Analytics and enable users to select data-points in visualizations and to invoke specific actions. Oracle Analytics provides a core set of data actions that cover many common use cases, but by writing your own data action plug-in, you can extend this functionality even further.

You must have a basic understanding of the following to create custom data action plug-ins:

  • JavaScript
  • RequireJS
  • JQuery
  • KnockoutJS

Generate Data Action Plug-ins from a Template

You use a series of commands to generate a development environment and populate it with a HTTP API Data Action along with the necessary folders and files that you need to create a custom data action plug-in.

All plug-in files follow the same basic structure. You can manually create the files and folders or you can generate them from a template. The tools to do this are part of the Oracle Analytics Desktop software development kit (SDK) which is included with Oracle Analytics Desktop. See Oracle Analytics Desktop SDK Reference.

Use these commands to generate your development environment and populate it with a HTTP API data action.

  1. At a command prompt, specify the root folder of your Oracle Analytics Desktop installation:
    set DVDESKTOP_SDK_HOME=C:\Program Files\Oracle Analytics Desktop
  2. Specify the location to store your custom plug-ins:
    set PLUGIN_DEV_DIR=C:\temp\dv-custom-plugins
  3. Add the SDK command line tools to your path using:
    set PATH=%DVDESKTOP_SDK_HOME%\tools\bin;%PATH%
  4. Create a folder for the directory used to store the custom plug-ins using:
    mkdir %PLUGIN_DEV_DIR%
  5. Change the directory to the folder for storing custom plug-ins:
    cd %PLUGIN_DEV_DIR%
  6. Create the environment variables:
    bicreateenv
  7. Create the template files needed to start developing a custom HTTP API data action, for example:
    bicreateplugin -pluginxml dataaction -id company.mydataaction -subType httpapi

    Use the -subType option to specify the data action type that you want to create from: httpapi, urlNavigation, canvasNavigation, event, or advanced. The advanced option extends from the AbstractDataAction base class.

Generated Folders and Files

Your newly generated data action development environment contains these folders and files:


1    %PLUGIN_DEV_DIR%\src\customdataaction
2       company-mydataaction\
3          extensions\
4             oracle.bi.tech.plugin.dataaction\
5                company.mydataaction.json
6          nls\
7             root\
8                messages.js
9             messages.js
10          mydataaction.js
11          mydataactionstyles.css
12          plugin.xml
  • Line 2: The company-mydataaction folder is the ID that you specify.
  • Line 6: The nls folder contains the files for externalizing strings that enable your plug-in to provide Native Language Support.
  • Line 7: The strings in the files under the nls\root folder are the default strings used when translations for a requested language aren't available.
  • Line 8: The messages.js file contains externalized strings for your plug-in that you can add.
  • Line 9: The messages.js file must contain an entry that you add for each additional language that you want to provide localized strings for. You must add a corresponding folder under the nls folder for each locale that you want to add translations for. Each folder must contain the same set of files, with the same file names as those added under the nls\root folder.
  • Line 10: The mydataaction.js file is the newly generated JavaScript module template that provides a starting point to develop your custom data action.
  • Line 11: The mydataactionstyles.css file can contain any CSS styles that you want to add, and which your data action's user interface can use.
  • Line 12: The plugin.xml file registers your plug-in and its files with Oracle Analytics.

Extend a Data Action Base Class

Once you've chosen the subclass of data action that you want to extend and have generated the necessary folders and files, you're ready to start writing the code specific to your new data action.

You can find your newly generated data action code under %PLUGIN_DEV_DIR%\src\dataaction. See Generated Folders and Files for an explanation of the files and folder structure. The main file you must edit is the JavaScript file. For example, if your custom data action ID is company.MyDataaction, then the file you're looking for is %PLUGIN_DEV_DIR%\src\dataaction\company-mydataaction\mydataaction.js.

Extending Your Data Action's Knockout Model

If your data action has additional properties that need to be stored, then you must add them as observable properties to the Knockout Model. If your data action is given the ID company.MyDataaction, then the Knockout Model is called mydataaction.MyDataActionKOModel which is located near the top of mydataaction.js. By default, this Knockout Model is configured to extend the Knockout Model used by your data action's superclass so you only need to add additional properties to the model.

For a data action that's extending the HTTPAPIDataAction base class, use code similar to the following:

1 - mydataaction.MydataactionKOModel = function (sClass, sID, sName, sVersion, sScopeID, aAnchorToColumns, eValuePassingMode, sURL,
        eHTTPMethod, sPOSTParams)
2 - {   
3 - mydataaction.MydataactionKOModel.baseConstructor.call(this, sClass, sID, sName, sVersion, sScopeID, aAnchorToColumns, eValuePassingMode, sURL, eHTTPMethod, sPOSTParams);
4 - };
5 - jsx.extend(mydataaction.MydataactionKOModel, dataaction.HTTPAPIDataActionKOModel);
  • Line 1: This is the constructor for your Knockout Model. It accepts the properties that the model needs to store.
  • Line 3: This is the superclass's constructor, otherwise known as the baseConstructor to which you pass the values for all of the properties that are handled by one of the Knockout Model's superclasses.
  • Line 5: This sets the superclass for this Knockout Model class.

Use code similar to the following to add a string and an array to set properties that are persisted by the data action.

1   mydataaction.MydataactionKOModel = function (sClass, sID, sName, sVersion, sScopeID, aAnchorToColumns, eValuePassingMode, sURL, eHTTPMethod, sPOSTParams)
2   {   
3   mydataaction.MydataactionKOModel.baseConstructor.call(this, sClass, sID, sName, sVersion, sScopeID, aAnchorToColumns, eValuePassingMode, sURL, eHTTPMethod, sPOSTParams);
4   
5  
6   // Set Defaults   
7   sMyString = sMyString || "My default string value";   
8   aMyArray = aMyArray || [];     
9  
10
11  // Asserts   
12  jsx.assertString(sMyString, "sMyString");   
13  jsx.assertArray(aMyArray, "aMyArray");
14 
15
16  // Add observable properties   
17  this.sMyString = ko.observable(sMyString);   
18  this.aMyArray = ko.observableArray(aMyArray);
19  };
20  jsx.extend(mydataaction.MydataactionKOModel, dataaction.HTTPAPIDataActionKOModel);

Choose Which Data Action Inherited Methods to Override

Each data action must implement various methods in order to function properly, so you only need to override those methods that implement behavior that you want to change.

Generic Methods

If you're extending one of the concrete data actions classes, for example HTTPAPIDataAction, then most of the required methods are already implemented and you only need to override the methods that implement the behavior you want to change.

This section describes the various methods and what's expected of them.

All types of data action must implement the methods that are described here.

create(sID, sName)

The create() static method is called when you're creating a new data action and select a Data Action Type from the drop-down menu. This method is responsible for:

  • Constructing the Knockout Model class that your data action uses.

    The Knockout Model class must have the ID and name that's passed to the create() method along with sensible defaults for all other properties. For example, for a currency conversion data action you might want to set the default currency to convert into Dollars. The Knockout Model is the correct place to provide your default values.

  • Constructing an instance of your data action from the Knockout Model.
  • Returning the instance of your data action.

invoke(oActionContext, oDataActionContext)

The invoke() method is called when the user invokes your data action from the context menu for a data point in a visualization. The method passes the DataActionContext argument which contains metadata describing the selected data points, visualization, filters, workbook, and session. See Data Action Service Classes.

validate()

The validate() method is called on each data action when the user clicks OK in the Data Actions dialog. The validate() method returns a null to indicate that everything is valid or a DataActionError if something is invalid. If there's an error in one of the data actions in the dialog, the error prevents the dialog from closing and an error message is displayed to the user. This method validates the name of the data action using the this.validateName() method.

getGadgetInfos(oReport)

The getGadgetInfos() method is called to enable the user interface to display data action property fields. The method returns an array of GadgetInfos in the order you want them to appear in the user interface. Gadgets are provided for all of the most common types of fields (for example, text, drop-down, password, multi-select, radio button, check box) but you can create custom gadgets if you want more complicated fields (for example, where multiple gadgets are grouped together, or where different gadget fields display depending on which option you select). It's a best practice to create a method that constructs each GadgetInfo you want in your array, as it makes it easier for potential subclasses to pick and choose from the GadgetInfos you've provided. If you follow this best practice there are already various methods implemented by the different data action base classes that can return a GadgetInfo for each of the fields that they use in their user interfaces. If you also need one of these GadgetInfos then you call the corresponding create****GadgetInfo() method and push its return value into your array of gadgets.

isAllowedHere(oReport)

The isAllowedHere() method is called when the user right-clicks on a data-point in a visualization and the user interface starts to generate the context menu. If a data action exists that's relevant to the selected data-points, then the method returns true and the data action appears in the context menu. If the method returns false, then the data action doesn't appear in the context menu. Consider accepting the default behavior inherited from the superclass.

upgrade(oOldDataActionJS)

If you're creating your first data action then don't use the upgrade(oOldDataActionJS) method. Only use this method after you've created your first Knockout Model and are making significant changes to properties for a second version of your Knockout Model. For example, if the first version of your data action stores a URL in its Knockout Model, but you decide that the next version will store URL component parts in separate properties (for example, protocol, hostname, port, path, queryString and bookmark).

The second version of your Knockout Model code would request to open a data action that had been saved with the first version of your Knockout Model code which can cause problems. To resolve this issue, the system identifies that your current data action code version is newer than that of the data action being opened and it calls the upgrade() method on your new data action class and passes in the old data action Knockout Model (serialized to a JSON object). You can then use the old JSON object to populate your new Knockout Model and return an upgraded version of the JSON object. This ensures that old data action metadata continues to work as you improve your data action code.

HTTPAPIDataAction Methods

If you're extending the HTTPAPIDataAction class, then it provides the following additional method that you may choose to override:

getAJAXOptions(oDataActionContext)

The getAJAXOptions() method is called by the data action's invoke() method. The getAJAXOptions() method creates the AJAX Options object that describes the HTTP request that you want your data action to make. The getAJAXOptions() method is passed the oDataActionContext object that contains the metadata describing the selected data-points, visualization, filters, workbook, and session. Set the AJAX Options as required by the HTTP API you're trying to integrate with and specify the functions you want to be called when the HTTPRequest is successful or results in an error. See the JQuery website for an explanation of the jQuery.ajax object and its properties.

The following implementation is inherited from the HTTPAPIDataAction class. You need to rewrite the inherited method to specify requirements. For example, forming the HTTP request, and the code that handles the HTTP response. This implementation is useful as it shows the parameters passed to the getAJAXOptions() function, the object that it's expected to return, and gives a clear example of how to structure the code inside the method.

1 /**
2  * This method returns an object containing the AJAX settings used when the data action is invoked. 
3  * Subclasses may wish to override this method to provide their own behavior. 
4  * @param {module:obitech-reportservices/dataactionmanager.DataActionContext} oDataActionContext The context metadata describing where the data action was invoked from.  
5  * @returns {?object} A JQuery AJAX settings object (see http://api.jquery.com/jQuery.ajax/ for details) - returns null if there is a problem. 
6  */
7 dataaction.HTTPAPIDataAction.prototype.getAJAXOptions = function (oDataActionContext)
8 {
9    jsx.assertInstanceOfModule(oDataActionContext, "oDataActionContext", "obitech-reportservices/dataactionmanager", "DataActionContext");
10   
11   var oAJAXOptions = null;   
12   var oKOViewModel = this.getKOViewModel();
13   var sURL = oKOViewModel.sURL();
14   if (sURL)
15   {
16      // Parse the URL
17      var sResultURL = this._parseURL(sURL, oDataActionContext);
18      if (sResultURL)
19      {
20         // Parse the POST parameters (if required)
21         var eHTTPMethod = oKOViewModel.eHTTPMethod()[0];
22         var sData = null;
23         if (eHTTPMethod === dataaction.HTTPDataActionKOModel.HTTPMethod.POST)
24         {
25            var sPOSTParams = oKOViewModel.sPOSTParams();
26            sData = sPOSTParams.replace(dataaction.AbstractHTTPDataAction.RegularExpressions.LINE_END, "&");
27            sData = this._parseURL(sData, oDataActionContext, false);
28         }
29         oAJAXOptions = {
30            type: eHTTPMethod,
31            url: sResultURL,
32            async: true,
33            cache: false,
34            success: function (/*oData, sTextStatus, oJQXHR*/)
35            {
36               oDataActionContext.getReport().displaySuccessMessage(messages.HTTP_API_DATA_ACTION_INVOCATION_SUCCESSFUL.format(oKOViewModel.sName()));
37            },
38            error: function (oJQXHR/*, sTextStatus, sError*/)
39            {
40               oDataActionContext.getReport().displayErrorMessage(messages.HTTP_API_DATA_ACTION_INVOCATION_FAILED.format(oKOViewModel.sName(), oJQXHR.statusText, oJQXHR.status));
41            }
42         };
43         if (sData)
44         {
45            oAJAXOptions.data = sData;
46         }
47      }
48   }
49   return oAJAXOptions;
50 };

Test, Package, and Install Your Data Action

You use Oracle Analytics Desktop to test your data action from its source location before you install it.

  1. If Oracle Analytics Desktop is currently running, close it.
  2. If you're working behind a proxy, set the proxy settings in %PLUGIN_DEV_DIR%\gradle.properties. For information about accessing the web through HTTP proxy, see Gradle User Manual.
  3. Run Oracle Analytics Desktop in SDK mode by using the command prompt you started in Choose Which Data Action Inherited Methods to Override and enter the following commands:
    cd %PLUGIN_DEV_DIR%
    .\gradlew run

    Oracle Analytics Desktop starts in SDK mode. Your data action plug-in appears in the Console | Extensions page.

    Create a workbook and test your data action. If you find any issues, you can debug your code using your browser's built-in developer tools.

  4. If you created an HTTP API data action:
    1. Go to the Console and display the Safe Domains page.
    2. Add each domain that you want to access.
      For example, if you need access to the apilayer.com APIs, add apilayer.net to the list of safe domains.
    3. Click the Connect column checkbox for the selected domain.
    4. Reload the Safe Domains page in your browser for the changes to take effect.
  5. If you want to prepare your data action plug-in to distribute to other people or to install in Oracle Analytics:
    • Package all of the files into a single ZIP file containing the %PLUGIN_DEV_DIR%\src\customdataaction folder and its contents.
    • Name the zip using the same ID you gave to your data action plug-in when you created it.
  6. Install your data action plug-in. See Manage Custom Plug-ins.

Use an Upgrade Handler for Knockout Model Changes

For some Knockout Model changes you need to upgrade your data action plug-in using an upgrade handler.

When you're making improvements to your data action plug-in without making changes to the Knockout Model you normally edit your JavaScript or CSS files, create a new ZIP file, and replace the existing data action plug-in with the new ZIP file. However, if you've made changes to your data action's Knockout Model then you might need to change the data action VERSION property and provide an upgrade handler.

Decide whether you need to use an upgrade handler:

Upgrade Handler Required
  • If you rename a property in your Knockout Model.
  • If you combine multiple properties into a single property in your Knockout Model.
  • If you split a single property into multiple properties in your Knockout Model.
  • If you add a new property to the Knockout Model and the correct default value for it depends on other values in the Knockout Model.
Upgrade Handler Not Required
  • If you add a new property to the Knockout Model and can provide a default value that's correct for all existing usages of your data action.
  • If you remove a property from the Knockout Model because it's no longer used by your data action code.

Upgrade Data Action Plug-ins

Upgrade your data action plug-ins to improve the data action code or upgrade the metadata to enable existing data actions to work with new data action code.

Use an upgrade handler to upgrade a data action plug-in.
  1. Increase the version number of your data action.

    For example, if your data action is called company.MyDataAction, then search mydataaction.js for the mydataaction.MyDataAction.VERSION property. If it's currently set to 1.0.0 then change it to 1.0.1.

  2. Add a static upgrade(oOldDataActionJS) method to your data action's class.

    If the VERSION property differs from the sVersion value stored in the data action metadata then the Data Action Manager calls the static upgrade() method on your data action's class.

  3. Implement your upgrade() method by calling the upgrade() method on the superclass and capture its response.
  4. Continue to implement your upgrade() method by making further edits to the partially upgraded data action JSON returned by the superclass, until the object matches the correct set of properties required by your latest Knockout Model.
  5. To finish call var oUpgradedDataAction = dataaction.AbstractDataAction.createFromJS(fDataActionClass, sFullyQualifiedDataActionClassName, oUpgradedDataActionJS).

    This command constructs a new instance of your data action from the upgraded data action JSON and returns oUpgradedDataAction.getSettings().