# 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 V8.1.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 update the Sisense.js file path to its new location and file name:

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

The original version of the file is still available at the existing 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

# 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.

# 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 undesireable effect on certain widgets if the add-on attempts to invoke APIs or components that are not available.

For example: The Funnel Widget 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 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.

# Including the Sisense.js Library

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

<script type="text/javascript" src="http://localhost/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('http://localhost:8081', false)
.then((app) => {
    // your code here
})
.catch((e) => {
    console.error(e);
});

# 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:

http://localhost/app/main#/dashboards/{dashboard_id}/widgets/{widget_id}

Example:

http://localhost/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);
});

# 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.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 Support in SisenseJS

TIP

Sisense.js supports Angular 1.x and 2.x.

Angular 2.x heavily emphasizes loading templates asynchronously, which means some HTML content is loaded until later on. For Sisense.js to work, this HTML content should be loaded prior to connecting to the Sisense server through the Sisense.connect function.

Sisense.js bootstraps a div element with the ID "sisenseApp" to ensure the sisenseApp element and other container elements are loaded before using the Sisense.connect function.

<div id="sisenseApp">
        Code...
</div>

# 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://yourcompany.com/sisense/sso?return_to=https://sisense.yourcompany.com/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.yourcompany.com/access/jwt?jwt=<payload>&return_to=https://sisense.yourcompany.com/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="http://localhost:8081/js/sisense.js"></script> <!-- replace with your Sisense server address -->
        <script type = "text/javascript">
            Sisense.connect('http://localhost:8081') // 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>

# Additional References