# Sisense.JS - Getting Started

Sisense.js is a JavaScript library that enables you to embed Sisense components in web pages without the use of iFrames.

By embedding the SisenseJS library, you can:

  • Load Sisense runtime anywhere, without iFrames
  • Load dashboards in runtime
  • Render all/part/new widgets in any DOM container
  • Embed Sisense visualizations into your mobile applications

This page describes the SisenseJS library’s functionality and how you can leverage it to embed widgets into your site or application.

# Dependencies

SisenseJS has the following dependencies

  • Highcharts
  • D3.js
  • JQuery

TIP

Starting from Sisense versions 8.1.1 & L8.2.1, a new version of Sisense.js is available. It provides the following improvements:

  • Isolated scope: SisenseJS will not override any globals on the window and can work alongside other versions of the aforementioned libraries
  • Isolated CSS classes: SisenseJS will not override or collide with any of your CSS classes or rules

To utilize the new version, all you have to do is modify the Sisense.js file path to its new location and file name:

 <script type="text/javascript" src="https://example.com/js/sisense.v1.js"></script>

The original version of the file is still available at the original file path.

# Overview

A widget is a dynamic visualization of your data with its own unique ID. Through the SisenseJS library, you define which widgets appear in the dashboard. In Sisense, a dashboard is a collection of one or more widgets that visualize the data that you select and design. However, in SisenseJS, the dashboard represents a JavaScript object that you can embed into your site or application.

The dashboard object is a container for widget objects. As a container of dashboards, and not a dashboard itself, it provides you with more flexibility by allowing you to add existing widgets from various dashboards to the dashboard object you embed on your site. After including the SisenseJS library into your site or application, you embed dashboard objects and populate those objects with your widgets.

# Prerequisites and Limitations

SameSite Cookie Policy

Some browsers, such as Chrome 80 (and newer), have implemented stricter policies regarding cookies that affect embedding.

For an embedded application to work in these browsers, SSL must be enabled and some additional configuration must be done in Sisense.

Please refer to Product Documentation: Security Settings (opens new window)

# CORS

As the application in which you are embedding Sisense elements most likely resides on a different domain than where Sisense is installed, you must enable CORS (Cross-Origin Resource Sharing) to access the JavaScript resources needed. For more information, see Cross Origin Resource Sharing (opens new window).

# Add-on support

When embedding Sisense using the Sisense.js SDK, only widgets are being embedded. Thus, only add-ons (plugins) that apply to the widget level are supported.

Add-ons that affect the system UI or other scopes may have no effect, or have an undesirable effect on certain widgets if the add-on attempts to invoke APIs or components that are not available.

For example: The Funnel Widget (opens new window) add-on is compatible with Sisense.js because it is a widget type and can be embedded like any other widget; The Jump To Dashboard (opens new window) add-on is not compatible with Sisense.js because it is built to navigate to other dashboards, which do not exist in the Sisense.js scope.

# SAML SSO

This section applies to Sisense for Windows v8.2.5 or higher, and Sisense for Linux L8.2.4 or higher.

If you use SisenseJS and SAML SSO, to avoid redirection errors when logging in, you will need to open the Sisense Advanced Configuration panel and make the following configuration changes:

# In Windows 8.2.5

  1. Connect to your Sisense server via RDP.
  2. Open a browser and navigate to http://localhost:3030.
  3. Click on the Sisense logo 5 times to switch to advanced mode.
  4. In the left-hand side navigation menu, click on Base Configuration.
  5. Scroll down to the Security section and click on it to expand.
  6. Toggle on security.redirectToAnyUrl.
  7. Click Save Base.

# In Linux L8.2.4

  1. Log in to Sisense as an admin.
  2. Open the Sisense Admin page.
  3. Open the System Management screen.
  4. Click on the Configuration button at the top-right corner.
  5. Click on the Sisense logo 5 times to switch to advanced mode.
  6. In the left-hand side navigation menu, click on Base Configuration.
  7. Scroll down to the Security section and click on it to expand.
  8. Toggle on Allow SAML to redirect to any URL.
  9. Click Save Base.

# Including the Sisense.js Library

You must include the sisense.js runtime file in your page as defined below where https://example.com should be your Sisense installation's URL and port.

<script type="text/javascript" src="https://example.com/js/sisense.js"></script>

# Connecting to Sisense

After you have included the Sisense.js library in your site, you must connect to Sisense.

The connect(url, saveChanges) method is a static method of the Sisense.js library that takes the URL of your Sisense server as an argument, and supports an optional second argument for persisting changes done by the user.

The connect method returns a promise that resolves to app object. The app objects contains your dashboards and defines how your widgets are embedded.

Sisense.connect('https://example.com', false)
.then((app) => {
    // your code here
})
.catch((e) => {
    console.error(e);
});

# Using Web Access Tokens L2022.1

In Sisense for Linux versions L2022.1 or newer, you can use Web Access Tokens together with SisenseJS as an alternative to standard authentication methods such as SSO.

Web Access Token

For more information, please refer to the Web Access Token documentation (opens new window)

In order to use WAT for embedding with SisenseJS, you'll need to:

  1. Append the query parameter ?wat=true to the SisenseJS library's URL when loading it:
<script type="text/javascript" src="https://example.com/js/sisense.js?wat=true"></script>
  1. Pass the WAT as an argument to the SDK upon initiating the connection to the Sisense server:
const wat = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';

Sisense.connect('https://example.com/', false, wat).then(function(app) {
    // your code here
});

# Embedding Dashboards

There are two ways to embed dashboards through the Sisense.JS library. You can create an empty dashboard object in which you add existing widgets to the dashboard object. The second way is to embed an existing dashboard where you retrieve the existing dashboard with its filters and embed them into the page.

# Retrieving Dashboard and Widget IDs

Regardless of how you embed your dashboard, you will need to provide the IDs of dashboards and widgets. These IDs are visible in the URL when you are viewing a dashboard or widget.

To view the full URL structure, open the relevant widget in Edit mode:

https://example.com/app/main#/dashboards/{dashboard_id}/widgets/{widget_id}

Example:

https://example.com/app/main#/dashboards/574eb8cd92be9b504b000006/widgets/574eb8d892be9b504b000009

# Creating a New Dashboard

To create a new temporary dashboard object, you construct a dashboard object, which is an empty container for widgets. After constructing the dashboard object, you can load existing widgets that you have defined in the Sisense Web Application to your new dashboard.

You can create an empty dashboard object through the Dashboard() object constructor:

let myEmptyDashboard = new Dashboard();
app.dashboards.add(myEmptyDashboard);

Once you have added your dashboard, you can add existing widgets to the dashboard object using the load() method:

myEmptyDashboard.widgets.load('570a1cd5d814c6245b000014')
.then((widget) => {
    // your code here
})
.catch((e) => {
    console.error(e);
});

Filters and Blank Dashboards

By default, a "blank" dashboard as described above does not have a data source associated with it, and as such cannot support dashboard filters.
This makes it impossible to render the filters panel correctly.

To use dashboard filters and/or the filters panel with a "blank" dashboard, initialize it with a datasource and an empty widget array:

// You can get a list of available datasources via GET /api/datasources
var datasource = {
    "title": "Sample Healthcare",
    "address": "localHost",
    "fullname": "LocalHost/Sample Healthcare"
};
// Create a blank dashboard object that supports filters
var myEmptyDashboard = new Dashboard({ datasource: datasource, widgets: [] });

# Embedding an Existing Dashboard

If you already have an existing dashboard and you want to embed it, you can load the existing dashboard through the load() method. The load() method takes the dashboard ID as an argument:

app.dashboards.load('574603d5fc726c3430000037')
.then((dashboard) => {
    // your code here
})
.catch((e) => {
    console.error(e);
});

After loading the dashboard, all of your existing widgets are loaded into memory. You can use the get() method to retrieve and display the widget.

# Rendering Widgets

Once you have a dashboard object with widgets loaded into memory, you can render them to your page.

First, you must set the DOM element that contains each widget:

// if you have the widget available as a variable, you can set it directly
widget.container = document.getElementById("widget1");

// if you have loaded the widget previously, you can use the get method
dashboard.widgets.get('3563564603ffc726c34300918').container = document.getElementById("widget2");

Then once all the widgets you wish to display have been assigned their containers, refresh the dashboard:

dashboard.refresh();

# Rendering Filters

After you have loaded a dashboard, you can load its filters through the renderFilters() method.

Note: A dashboard object can only contain filters if it's datasource property is set. When loading existing dashboards, they are always loaded with a datasource. When creating a new object, you must set it yourself.

dashboard.renderFilters(document.getElementById("filters"));

# AngularJS/React Support in SisenseJS

Frameworks such as AngularJS/Angular2 and React have a heavy emphasis on async/lazy-loading of their DOM, which means certain DOM elements that Sisense.js requires to function might not exist at the time they are needed by Sisense.js. Make sure that all required container elements exist in the DOM before calling Sisense.connect.

Sisense.js bootstraps a div element with the ID "sisenseApp" which in turn enables the creation of various overlay DOM elements, such as tooltips.

Make sure the sisenseApp element and other container elements are loaded before using the Sisense.connect function, by explicitly creating it as an empty container within your page.

<!-- Your Sisense container elements and other DOM here -->
<div id="sisenseApp"></div>

Please note

There can be only one sisenseApp element on a given page.

SisenseJS Component Wrapper - Beta

The sisensejs-components library is a component-based wrapper for SisenseJS, built for use with React as well as vanilla JavaScript or TypeScript applications. It is now available as a BETA release on our GitHub: https://github.com/sisense/sisensejs-components (opens new window)

# Working with Sisense SimplyAsk NLQ L8.2.1

Starting with Sisense for Linux L8.2.1, the SimplyAsk NLQ feature is available in Sisense.js, in two modes.

To use this feature you will need to follow the SimplyAsk NLQ Documentation (opens new window) first.

Limitations

  • The renderSimplyAsk and popSimplyAsk methods cannot be used concurrently on the same page
  • When using the renderSimplyAsk method, the SimplyAsk UI will not display the "Available Fields" button

# As a popup

Using the popSimplyAsk method (available on the dashboard object) will display a modal dialog with the NLQ interface.

You can style the popup by providing a CSS class in the optional containerClass setting.

// With a container CSS class
Sisense.connect('https://example.com/').then(function (app) {
    app.dashboards.load('5e9edfedf52f45002d5a6844').then(function (dashboard) {
        dashboard.popSimplyAsk({containerClass: 'custom-class-name'});
    });
});

# In a container

Using the renderSimplyAsk method (available on the dashboard object) will render the NLQ interface into a container element on the page, allowing you full control over the location and look of this interface.

Sisense.connect('https://example.com/').then(function (app) {
    app.dashboards.load('5e9edfedf52f45002d5a6844').then(function (dashboard) {
        dashboard.renderSimplyAsk(document.getElementById("simplyAskContainer"));
    });
});

# Working with UI Themes L2021.3

As part of the UI Customization & Themes (opens new window) feature available on Sisense for Linux L2021.3 or newer, you can apply any existing theme to the embedded UI components (widgets, filters) using the desired theme's oid.

To get the available theme oids, you can use the

GET /api/v1/themes
REST API endpoint.

Then, use the oid field from the response as a parameter for the app.setTheme(themeOid) method of the SisenseJS SisenseApp Class, which will apply the theme to all UI elements rendered with the same instance of SisenseJS SDK on the page:

Sisense.connect('https://example.com', false).then((app) => {
    // Set a theme
    app.setTheme('605b633dc24bb7001ae42fbb').then(function() {
        console.log('theme has been applied');
    });
});

You can apply a theme before the widgets are rendered (before the first call to dashboard.refresh()) to make widgets render with the desired theme, or apply a new theme at any point after render to modify the appearance of the existing rendered widgets without having to reload the page.

You can also clear the set theme using app.clearTheme() which will revert all rendered UI elements to the user's default theme.

# SSO and SisenseJS

When embedding Sisense.JS into your site, you should implement Single Sign On.

Sisense implements SSO by redirecting users to a script/application that creates a login token for the user, and redirects them back to the destination or resource they were trying to access. If the resource requested is a dashboard, that's where the user will be redirected back to. For Sisense.JS the resource requested will be a JavaScript file, so you need to ensure the redirect takes you back to this file.

When Sisense redirects your customers to your login script, Sisense passes a return_to parameter in the URL. This parameter defines the page that Sisense redirects your customer after authenticating them. For example:

  1. A customer visits your site opens a page containing Sisense.JS code
  2. The page requests the Sisense.js library file from the Sisense server
  3. Sisense recognizes that the user is not authenticated (the HTTP request has no cookie)
  4. Sisense redirects the user to:
https://www.example.com/sisense/sso?return_to=/js/sisense.js

All your SSO handler needs to do, is take the return_to value from the invoked URL and pass it back to Sisense when submitting the JWT token. In other words, upon authentication on your side, your script redirects the user to:

https://sisense.example.com/jwt?jwt=<payload>&return_to=/js/sisense.js

For more information regarding SSO and Sisense, click here.

# Example

The following is an example of an HTML page that has implemented SisenseJS to display a dashboard with three widgets inside.

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
    </head>
    <body> 
        <div id = "sisenseApp">
            <div id = "widget1" style = "height: 400px; width: 35%; float: left; top: 500px; display: inline; margin-top:30px;"></div>
            <div id = "widget2" style = "height: 400px; width: 40%; float: left; top: 500px; display: inline; margin-top:30px;"></div>
            <div id = "widget3" style = "height: 400px; width: 100%; float: left; top: 500px; display: block; margin-top:30px;"></div>
            <div id = "filters" style = "height: 400px; width: 25%; float: left; top: 80px; left: 0px; display: inline; margin-top:80px;"></div>
        </div>
        <script type="text/javascript" src="https://example.com/js/sisense.js"></script> <!-- replace with your Sisense server address -->
        <script type = "text/javascript">
            Sisense.connect('https://example.com') // replace with your Sisense server address
            .then((app) => {
                app.dashboards.load('5829b46b3452420000047') //replace with your dashboard id
                .then((dash) => {
                    dash.widgets.get('58b45b4ce6ef16b0b4000041').container = document.getElementById("widget1"); //replace with one of your widgets' id.
                    dash.widgets.get('58b45b4ce6ef16b0b4000042').container = document.getElementById("widget2"); //replace with another of your widgets' id.
                    dash.widgets.get('58b45b4ce6ef16b0b4000043').container = document.getElementById("widget3"); //replace with another of your widgets' id.
                    dash.renderFilters(document.getElementById("filters"));
                    dash.refresh();
                })
                .catch((e) => {
                    console.error(e);
                });
            })
            .catch((e) => {
                console.error(e);
            });
        </script>
    </body>
</html>