Hello World Widget Plugin
Download: HelloWorldWidget
Introduction
This plugin is a sample for how to get started creating new widget types in Sisense. It contains only the basic widget elements: data panels, query building, data processing, and rendering. This plugin also shows a simple example of how to create your design panel for the widget. Check out the file structure of this widget, as well as an overview of the most commonly used properties for defining a widget. Of course, there are more event handlers and properties you can set, but this sample shows the basics.
File Structure
HelloWorldWidget: Plugin folder
- plugin.json: This file is the basis of all plugins, as it defines what JavaScript and CSS files to load.
- widget.js: Contains the code used to create the new chart type
- styler.html: The HTML template of how to display the widget's Design Panel
- stylerController.js: The angular controller that binds data from your widget to the design panel
- icon-24.png: The icon that appears in the widget editor's chart selector menu
plugin.json
{
"name": "HelloWorldWidget", // Name of the plugin
"version": "1", // (optional) version # of the plugin
"source": [], // Array of Javascript files used in the plugin
"style": [] // (optional) Array of CSS files to load with the plugin
}
widget.js
prism.registerWidget("pluginname", {
name: "pluginname", // Same as text used to register widget (must match)
title: "My Widget", // Widget's display name
hideNoResults: true, // Flag for whether to hide the "No Results" diaglog, when query returns no data
iconSmall: "/plugins/HelloWorldWidget/icon-24.png", // Full path to the icon
styleEditorTemplate: "/plugins/HelloWorldWidget/styler.html", // Full path to the design panel's HTML template
style: { // Object to hold style properties of the widget, referenced by the design panel
textAlign:"left" // You can add whatever properties you like here
},
data: {
selection: [], // (optional) Placeholder to store filter selections
defaultQueryResult: {}, // (optional) Data to use, when no results from Elasticube query
panels: [
{
name: 'category', // Name of the panel, which will be visible in the widget editor
type: 'visible', // Panel types can be 'visible', 'series', or 'filter'
metadata: {
types: ['dimensions','measures'], // Data types acceptable for this panel (options are dimensions and measures)
maxitems: 1 // How many items are allowed in this panel? Use -1 for unlimited
}
}
],
// Function to build a JAQL query for this widget
buildQuery: function (widget) {
// Build a query object from this widget's metadata
var query = {
datasource: widget.datasource, // Define which Elasticube should process this query (get it from the widget)
format: "json", // Options here are 'json' or 'csv'
isMaskedResult: true, // Should the output of the query include formatting masks? ( for example, 123.00 => $123 )
offset: 0, // Should the results of this query get offset? This is used for paging, so query for the first 10k records
count: 10000, // How many results should be returned by this query?
metadata: [] // Array that will contain the metadata items to include in this query
};
// Add categories to the query, from the panels
widget.metadata.panel("category").items.forEach(function(item){
query.metadata.push(item);
})
// Add widget filters to the query
widget.metadata.panel('filters').items.forEach(function (item) {
// Create a copy of the item, $$.object.clone is a jquery function to create a clone of a given object
item = $$.object.clone(item, true);
// Specify that this is a filter, by setting the panel attribute = "scope"
item.panel = "scope";
// Add to query
query.metadata.push(item);
});
// Dashboard filters are added automatically to the query
return query;
},
// Function to transform the data returned from the query
processResult: function (widget, queryResult) {
/*
This is an optional block which allows you to transform the raw
query results into an object that's easier for the visualization
to work with. If you do no wish to transform the query result,
you can just pass along the raw queryResult
*/
return queryResult;
},
// Function to take the transformed data, and render to the widget
render: function (widget, args) {
/*
This block allows you to render content into the DOM, based on the
data from the query result.
*/
},
// (optional) Function that runs when the widget is removed from a dashboard or when a dashboard is unloaded
destroy: function (widget, args) { }
});
The data panels array contains 0 or more panels, which are displayed within the widget editor. Each panel can have one of the following types
- visible: This is the standard panel type, which just displays each item within the panel
- series: This type displays all members of each item with a color picker, so the dashboard designer can pick a specific color for each member. This type must have a metadata.type = ['dimensions']
- filter: This means the panel is for widget filters, so it will appear on the right side of the widget editor
Each data panel contains a metadata object, which includes a types array. This array lists what datatypes are acceptable for this panel, and can include any combination of the following:
- dimensions: Allows for getting a list of all unique values from an Elasticube field
- measures: Allows for aggregations (sum, count, etc) as well as calculated formulas
Each of the event handlers of this widget receive some parameters from the plugin framework. The widget object is passed to every event, and matches the outline described in the Sisense documentation. Additional parameters are listed below:
processResult.queryResult: This object contains the raw results of the query
- rows(): Function to return the data as an array of rows, each containing an array of columns
- columns(): Function to return the data as an array of columns, each containing an array of rows
- metadata(): Function to return the original query
render.args
- $scope: The Angular scope of the widget
- element: The HTML element, in which to render your visualization
- query: The original query sent to the Elasticube
- reason: The reason why the widget is being rendered (refresh, resize, etc)
- widget: The widget's object model
- widget.queryResult: Where to find the object returned from the processResult event handler.
stylerController.js
// Leave this part as is
mod.controller('stylerController', ['$scope', function ($scope) {
// Code that binds the widget's style property, to this controller's scope
$scope.$watch('widget', function (val) {
$scope.model = $$get($scope, 'widget.style');
});
// Function to allow the design panel to set style properties of the widget
$scope.setStyle = function (propertyName, propertyValue) {
// Set the style property
$scope.model[propertyName] = propertyValue;
// Wait for the property to be set, then redraw widget
_.defer(function () {
$scope.$root.widget.redraw();
});
};
}]);
styler.html
<!--
Assigns the HTML template to use the plugin's controller.
Change the 'mypluginname' part of this to match the name you choose in plugin.json
Also note that angularjs convert camelcase names to kebab-case (ex. MyPlugin -> my-plugin)
-->
<div data-ng-controller="plugin-mypluginname.controllers.stylerController">
<div class="settings-pane-host">
<!-- A single UI block in the design panel -->
<div class="pane-row">
<div class="pane-row-title">Text Align</div>
<div class="positions-holder">
<!-- UI Elements to display in each design panel block -->
</div>
</div>
</div>
</div>
Please sign in to leave a comment.
Comments
1 comment