Examples

The following are some examples of how to use the Siren API to achieve different results.

Creating a "Hello World" script

You can create a very simple script as follows:

const version = 1;
const type = 'custom';
console.log("Hello World")

Accessing the current dashboard

You can get the object representing the current dashboard by using the following script:

sirenapi.Dashboard.getCurrentDashboard().then(dash => {
 // your code here
});

Registering an event handler

You can register an event handler when the count changes on a dashboard search by using the following script:

sirenapi.Dashboard.getCurrentDashboard().then(dash => {
  dash.on(sirenapi.Dashboard.EVENTS.SEARCH_COUNT_CHANGED, event => {
    // your code here
    // the event will give more information about which count was changed
    // as there could be multiple counts on a single dashboard (dashboard 360)
  });
});

Finding a visualization

You can find a visualization on the current dashboard by its title by using the following script:

const title = 'My visualization';
let vis;
const visualizations = dash.getVisualizationByTitle(title);
if (visualizations.length ==== 1) {
  vis = visualizations[0];
} else if (visualizations.length ==== 0) {
  throw new Error('Visualization "' + title + '" not found');
} else {
  throw new Error('More than one visualization with the title "' + title + '" found');
}

You can find a dashboard data model search by its title by using the following script:

const title = 'My search';
let mySearch;
const searches = dash.getDashboardDataModelSearchByTitle(title);
if (searches.length ==== 1) {
  mySearch = searches[0];
} else if (searches.length ==== 0) {
  throw new Error('Search "' + title + '" not found');
} else {
  throw new Error(
    'More than one node in dashboard datamodel with search "' + title + '"'. +
    'Use getDashboardDataModelSearchByNodeId instead'
  );
}

Using special variables

When the script is attached to a visualization, you can use a special variable currentVisualization to access the Visualization object representing visualization to which the script was attached.

You can also use the special variable currentDashboard to access the Dashboard object representing the current dashboard on which the script is executed.

const dash = currentDashboard;
const vis = currentVisualization;

Using methods registered by visualizations

Any custom method that is registered by a visualization is exposed on the Visualization object.

For example, a visualization called MapX registered a custom method called reloadMap(). The script is attached to an instance of the MapX visualization. The method can be accessed by using the following script:

...
const myMapX = currentVisualization;
myMapX.reloadMap();
...

Adding a filter to current filters

You can add a filter to current filters by using the following script:

...
const myFilter = {
  meta: {
    alias: "My filter"
  },
  match_all: {}
};
dash.addFilters(myFilter);
dash.applyState();
...

Replacing current filters

You can replace current filters by using the following script:

...
const filters = dash.filters;
...
// manipulate filters
...
dash.setFilters(filters);
dash.applyState();
...

Getting the current time of the dashboard

You can get the current time of the dashboard and create a time filter by using the following script:

...
const title = "my search";
const searches = dash.getDashboardDataModelSearchByTitle(title);
let mySearch;
if (searches.length ==== 1) {
  mySearch = searches[0];
} else if (searches.length ==== 0) {
  throw new Error('Search "' + title + '" not found');
} else {
  throw new Error(
    'More than one node in dashboard datamodel with search "' + title + '"'. +
    'Use getDashboardDataModelSearchByNodeId instead'
  );
}
const time = dash.getTime();
sirenapi.getTimeFilter(time, mySearch.indexPatternId)
.then(timeFilter => {
  // here we can use the timefilter created on correct field
})

Web services integration

You can integrate Web services by using the following script:

...
sirenapi.invokeWebService(groupName, serviceName, params, options)
.then(data => {

});
...

Building simple forms

The scripted panel API allows for a rapid creation of simple HTML forms.

The script below is an example of a form that takes two inputs and executes a function when the user presses a Submit button.

...
function onSubmit(formData) {
    console.log(formData);
}

const info = currentVisualization.getHtmlElement(
  '<div>' +
  '<p>Enter data and press the button.</p>' +
  '</div>'
);
const input1 = currentVisualization.getHtmlTextInputElement('name', 'Name', 'Enter your name', "");
const input2 = currentVisualization.getHtmlTextInputElement('itemsNo', 'Items Number', 'Enter number of items', "3");
const submit = currentVisualization.getHtmlSubmitButtonElement('Find');
const form = currentVisualization.getHtmlFormElement(onSubmit);
form.appendChild(info);
form.appendChild(input1);
form.appendChild(input2);
form.appendChild(submit);
currentVisualization.appendHtmlElement(form);

Results of the above script

image

Building an interactive table

One of the components provided by the scripted panel API is an interactive table.

The script below shows how this table is created, with a callback that handles rows being selected.

...
// Adds interactive table to panel
const columns = [
  { name: 'Column 1', field: 'field1' },
  { name: 'Column 2', field: 'field2' }
];
const data = [
  { field1: 'value1', field2: 'value2' },
  { field1: 'value3', field2: 'value4' }
];
table = currentVisualization.getInteractiveTable({ columns, data, onSelect });
currentVisualization.appendHtmlElement(table);

// Updates dashboard filter when rows are selected
function onSelect(selectedItems) {
  currentDashboard.setFilters([{
    meta: {
      alias: 'Selected items'
    },
    query: {
      bool: {
        minimum_should_match: 1,
        should: selectedItems.map(item => ({
          match_phrase: {
            'label': item.field1
          }
        }))
      }
    }
  }]);
  currentDashboard.applyState();
}

Results of the above script

image

Developing plug-ins that are compatibile with sirenAPI

First, you must register an interface with definitions of all custom methods that are used by your plug-in. This will tell the sirenAPI which versions of the API are supported by your plug-in.

import scriptingInterfaces from 'scripting-interfaces';
...
if ($injector.has('actionRegistry')) {
  const actionRegistry = $injector.get('actionRegistry');
  const apiVersion = '1';
  actionRegistry.registerInterfaceForType(
    apiVersion,
    'my_plugin_id',
    scriptingInterfaces.v1.visualizations.my_visualization
  );
}

To enable a visualization to interact with SirenAPI, a plug-in developer must register the required actions by using SirenAPI.

To register methods, use the actionRegister service in your visualization controller.

...
if ($injector.has('actionRegistry')) {
  const actionRegistry = $injector.get('actionRegistry');
  const apiVersion = '1';

  actionRegistry.register(apiVersion, $scope.vis.id, 'myMethod', async (param1, param2) => {
    // should ALWAYS return a promise !!!
  });
}
...

The plug-in developer can also emit custom events that scripts can listen to.

To emit a custom event, use the following script:

...
if ($injector.has('sirenAPI')) {
  const sirenAPI = $injector.get('sirenAPI');
  const data = {
    name: 'my-custom-event',
    ...
  }
  sirenapi.emit(sirenapi.EVENTS.CUSTOM, data);
};
...

In the script, you register event handlers and call methods as follows:

...
sirenapi.on(sirenapi.EVENTS.CUSTOM, event => {
  if (event.data.name ==== 'my-custom-event') {
    vis.myMethod();
  }
});
...

sirenAPI.es

The Elasticsearch client. For more information, see the Elasticsearch API reference documentation.

Example:

const { body } = await sirenapi.es.search({
  index: 'companies',
  // type: '_doc', // uncomment this line if you are using Elasticsearch ≤ 6
  body: {
    query: {
      match: { name: 'acme' }
  }
})