Using the Embedded Dashboard Editor in Your Application

Recently, Cumul.io released the Embedded Dashboard Editor. It is a sandbox branded analytics environment in your core application. Here, your product users can create, design, and edit their own dashboards. It exposes capabilities to your end users within the scope of control you decide to grant them. The rights access range from view only to cloning and editing existing dashboards or creating new ones.

The Embedded Dashboard Editor empowers your users with their own data analytics playground. In other words, citizen developers can now take charge of their own data! As a developer or data scientist, you can now focus on the most complex and urgent tasks.

Follow the steps in this article to integrate the Embedded Dashboard Editor into your application. We’ve also provided sample code for you on GitHub.

For detailed instructions on configuration and user management, check out the Academy Course.

Let’s dive in! Here’s the structure we will follow, so feel free to skip to the section that’s relevant to you!

  1. A sneak peek At The End Result
  2. Enable Embedded Dashboard Editor in Your Application
  3. Advanced – Retrieving User Roles from Auth0
  4. Resources

A Sneak Peek At The End Result

For use with this tutorial, we’ve published an open repo. This repo allows you to locally run an application that includes the Embedded Dashboard Editor. Let’s see what it looks like.

Example Application

For this demo, we’ve used dashboards about beer 🍻 – because who doesn’t like beer! The demo application embeds Cumul.io dashboards the same way you normally would. Users would see and interact with a dashboard when they log in and that’s it. Users can switch to Edit Mode by clicking a button on the bottom left corner of the application. This turns the application into a sandboxed Cumul.io dashboard editor.

Let’s look at what happens when someone who has the role designer logs into the application. We will look deeper into roles later!

The user can switch to ‘Editor Mode’. In this example, we provide the user the freedom to switch between two edit modes: editFull and editLimited. More on edit modes coming in the next section.

In edit mode, the user has access to either all or some of the following, depending on the edit mode and the rights the user has for a specific dashboard:

  • Create and/or edit a dashboard
  • Create and/or edit a variant of an existing dashboard
  • Set a variant of a dashboard as their favorite
  • Share dashboards and variants with others in their organization

However, if a user with role viewer were to log in, they won’t be able to switch to any of the edit modes.

The owner role is similar to a designer. Except the owner can also set a variant as the default for others in their organization (favoriting).

We provide a lot more detail on the different roles and what they mean in our Academy Article.

Enable Embedded Dashboard Editor in Your Application

Let’s have a look at how we get this set up. To follow along, you can clone the example repo on which this tutorial is based. The README.md has explanations on how to locally run the project as well.  

We will also have a brief overview of what the different rights and roles mean in practice. For a detailed description of how to manage different roles and access rights, please visit our in-depth Academy Course.

Integration Rights

First, we have to set up the backbone of any embedding that takes place with Cumul.io; the Integration. For the Embedded Dashboard Editor to work, we first need to set the permissions on the Integration we wish to use.

An Integration has two main components: dashboards and datasets. Users will have access to all dashboards and datasets associated with the Integrations they have access to via SSO tokens. When associating a dashboard or dataset to the Integration, specify the rights the user will get to that dashboard or dataset. The user will be bound to these access rights, even if they are using the resource in the Embedded Dashboard Editor.

For example, a dashboard set to ‘Can view’ can’t be edited, even if it’s in an integration you use for the Embedded Dashboard Editor. You can set the following dashboard rights in your Integration:

Can view: The user can view and interact with the dashboard, but can not edit or create dashboard variants.

Can use: Next to being able to view and interact with the dashboard, the user can duplicate and create a variant of this dashboard.

Can edit: Besides viewing, interacting, duplicating, and creating a variant of the dashboard, the user can directly modify the original dashboard.

In most cases, ‘Can use’ will probably be the most appropriate permission for dashboards that you want to use in the Embedded Dashboard Editor. This will allow the user to use the original dashboard as a starting point of which they can create variants and edit themselves. They will, however, not have access to edit the original one. Only a designer or owner with ‘Can edit’ permissions will be able to edit the original dashboard.

The rights for datasets follow the same principle. You can read all about it in more detail in our Academy Course

So first, we set the dashboards and datasets to ‘Can use’.

User Roles

There are 3 user roles:

  • Viewer: This user will never be able to switch to edit mode. Not even within an application which enables the Embedded Dashboard Editor. They can, however, view dashboards shared with them.

  • Designer: This user can view, edit and create dashboards. They can create variants of dashboards and set them as their favorite. They will see the favorited variant by default, instead of the original dashboard. They can share dashboards or variants with others in their organization too.

  • Owner: This user is much like a designer, but with a crucial difference. An owner can also set dashboards or variants of dashboards as ‘favorites’ for others in their organization.

Again, all of these capabilities are bound to the rights you defined in the Integration. The set of capabilities a user will get also depends on the edit mode, selected either by the user or pre-defined by you. We discuss this below. 

For more detail on user roles, please visit the Academy Article about creating the correct SSO tokens for different roles.

Edit Modes

There are 2 edit modes available: editFull and editLimited.

Only designers or owners can switch between edit modes. In this demo application, designers and owners can pick which edit mode they want to be in. However, in reality, you may want to define this in your application yourself based on your use case.

  • editFull: The user can access all dashboards in the Integration, all other dashboards they’ve created or that were shared with them. They can also create new ones, duplicates, or variants of existing dashboards (depending on their role). If you use this mode, you don’t need to use getAccessibleDashboards to provide navigation to your user. The Embedded Dashboard Editor will already provide this functionality. Use this mode to have one sandbox location in your app where users can freely create, edit, and navigate between dashboards.
  • editLimited: Users can create variants and edit the dashboard(s) you’ve provided them. They can also see and edit other variants they’ve created or that have been shared with them. That is if the person who shared it gave the proper rights. The users can’t create new dashboards. They can only access the dashboards in the Integration that the application provides. This is because there is no navigation within the Embedded Dashboard Editor. Use this mode if you have your own dashboard navigation in your application. This could be a sidebar containing dashboard tabs or a dropdown.

Creating the Cumul.io Client and  SSO token

First, you need to create an SSO token for the user. This is where we will tell Cumul.io what role the user has. To do so, we need to create a Cumul.io client in server.js. This is done the usual way we know and love:

const Cumulio = require('cumulio');
 
const client = new Cumulio({
  api_key: *Your_API_key*,
  api_token: *Your_API_token*
});

Don’t forget to create an API key and token in your Cumul.io account for this step.

The next step of creating an SSO token is much the same as before the Embedded Dashboard Editor was introduced. The only difference here is that you have to provide the role of the user. So, we create an /authorization endpoint in server.js:

app.get('/authorization', (req, res) => {
  client.create('authorization', {
    integration_id: process.env.INTEGRATION_ID,
    type: 'sso',
    expiry: '24 hours',
    inactivity_interval: '24 hours',
    username: 'JohnDoe',
    name: 'John Doe',
    email: 'johndoe@cumul.io',
    suborganization: 'Sample Integration',
    role: 'viewer',
    feature_overrides: [] /*Optional - see Academy Article (link below)*/
  })
    .then(result => res.status(200).json(result))
    .catch(error => res.status(400).json(error));
});

You can provide a few flags to enable feature_overrides. For example, to allow users to create alerts or exports. You can use feature flags to modularly control which elements of the editor are visible to the user. For a detailed run-through of these options, check out this Academy Article.

Note that if you have cloned the example repo and are running this locally, you can provide the Integration ID in the .env variables. 

This creates an authorization token for the user ‘John Doe’ with the role designer. If you run the application at this point, you will see that John Doe can switch to Edit Mode freely.

Try changing the role to viewer and rerun the application. You will notice that John Doe can no longer switch to Edit Mode.

Enabling Edit Mode

Great, so we created a user with a certain role. But how does the switching of modes actually work in the UI?
The Embedded Dashboard Editor is an additional capability of the existing Cumul.io Embed Library. We have introduced a new property and corresponding function to our Embed API: editMode and setEditMode. And that’s all!

Embedding the Dashboard(s)

Skip to TL;DR
In the example repo, we use the Cumul.io Web Component. So first, we add the cumulio-dashboard element to index.html in the frontend:

<cumulio-dashboard
    loaderBackground="#f1f5f8"
    loaderFontColor="#333"
    loaderSpinnerColor="rgb(255, 83, 84)"
    mainColor="rgb(255, 83, 84)"
    accentColor="rgb(255, 83, 84)"
    editMode="view">
</cumulio-dashboard>

The options we’ve filled in here are largely cosmetic and aren’t necessary. What’s new is the editMode option that has been set to view here. If you don’t provide a value for the editMode, it will be set to view by default.

The dashboard element is now set to view mode, but the element hasn’t been filled yet with a dashboard. To do so, we use the usual embedding steps of setting the authKey, authToken, and dashboardId of the cumulio-dashboard component. In main.mjs, we retrieve the authorization key and token from the /authorization endpoint we created in the previous step:

const dashboardElement = document.querySelector('cumulio-dashboard');
 
fetch('/authorization')
  .then(async (response) => {
    const parsedResponse =  await response.json();
    // We can now set the key and token to the dashboard component.
    dashboardElement.authKey = parsedResponse.id;
    dashboardElement.authToken = parsedResponse.token;
    // retrieve the accessible dashboards from the Integration
    dashboardElement.getAccessibleDashboards()
      .then(dashboards => {
        populateMenu(dashboards);
      });
  });

In this example, we provide a sidebar with all available dashboards in the Integration. However, this is not necessary. If you expose the Embedded Dashboard Editor in editFull mode, designers and owners can navigate between the available dashboards in the UI anyway. This step depends entirely on your use case and UI preferences. In our demo, we set the dashboardElement.dashboardId via a populateMenu function in ui.mjs, where we set the id of the dashboard as follows:

export function populateMenu(dashboards) {
  const menu = document.getElementById('dashboard-menu');
  if (dashboards.length > 0) {
    dashboardElement.dashboardId = dashboards[0].id;
    dashboards.forEach((dashboard, i) => {
      /*Set up the side menu buttons for each available dashboard*/
    });
  }
}

[TL;DR]
To embed the dashboards, we have to set the authKey, authToken, and dashboardId (or dashboardSlug) of the cumulio-dashboard component:

const dashboardElement = document.querySelector('cumulio-dashboard');
 
dashboardElement.authKey = /*Get key from authorization request*/;
dashboardElement.authToken = /*Get token from authorization request*/;
dashboardElement.dashboardId = /*Get dashboard id*/;

Setting the Edit Mode

Skip to TL;DR
Finally, we set up the ‘To Edit Mode’ button to call a function that will change the editMode of the dashboard element. This function uses the new setEditMode function in ui.mjs:

document.getElementById('toggle-edit-mode').onclick = () => {
  if (currentMode === 'view') setMode('editFull');
  else setMode('view');
};
 
 
document.getElementById('toggle-edit-limited-mode').onclick = () => {
  setMode('editLimited');
};
 
document.getElementById('toggle-edit-full-mode').onclick = () => {
  setMode('editFull');
};

And in main.mjs:

export let currentMode = 'view';
 
export const setMode = (requestedEditMode) => {
  if (!['view', 'editFull', 'editLimited'].includes(requestedEditMode)) return;
  if (currentMode !== requestedEditMode){
    dashboardElement.setEditMode(requestedEditMode).then(() => {
      /*Change the edit mode buttons accordingly*/      
      currentMode = requestedEditMode;
    }).catch(e => {
      console.log(e.msg);
      /*Display unauthorized message on button*/  
    });
  }
};

Note: You can also change the editMode property directly in the dashboard component (dashboardElement) while providing a dashboardId/dashboardSlug. This will automatically load the new dashboard in the specified editMode.

[TL;DR]
We retrieve the requested mode from the frontend (or you predefine it in your application) and call the setEditMode() function on the dashboard element:

dashboardElement.setEditMode(requestedEditMode)

Advanced – Retrieving User Roles from Auth0

That’s all you need to set up the Embedded Dashboard Editor in your application. However, the above scenario won’t necessarily (and probably shouldn’t) translate to what your real-world setup would be.

For starters, you probably don’t want everyone to have a designer role. Or allow everyone to switch between all the different edit modes to their will. You will most likely want to manage this via an authentication layer. So in this section, I will show you how to achieve this with Auth0

To set up your application with authentication enabled, we’ve provided some example code in the repository. You will find this in the same repo as the above section, but on the authentication branch. The README.md has instructions on how to install and run this version of the application.

Note: Everything in this step is much the same as the Multi-Tenancy on Cumul.io Dashboard with Auth0 Tutorial. If you are completely new to Auth0, we suggest you do the Create an Application and Users with Auth0 step first. 

Define User Role in app_metadata

In Auth0 User Management, we first need to set the users’ roles in their app_metadata. In this version of the demo app, we stick to our usual mascots Brad Pots and Angelina Julie. Here is what their app_metadata looks like:

{
 "cumulio": {
     "username": "bradpotts",
     "name": "Brad Pots",
     "firstName": "Brad",
     "role": "designer",
     "email": "bradpots@exampleapp.com",
     "department": "Quadbase",
  }
}

{
 "cumulio": {
     "username": "angelinajulie",
     "name": "Angelina Julie",
     "firstName": "Angelina",
     "role": "viewer",
     "email": "angelinajulie@exampleapp.com",
     "department": "Linedoncon",
  }
}

Note: If you already have a Login Rule set up in the Auth Pipeline, you can ignore the next step. You can also remove everything above outside of the cumulio property.

Create a Login Flow

Auth0 moved from using Rule- to Action-based flow. Cumul.io now also has an Auth0 Integration which you can install to avoid writing an Action yourself. We will go through the two options of either installing the integration or creating your own action.

In Auth0 Actions, select the Login Flow as seen below:

Here, you can drag and drop your pre-installed Cumul.io Integration as follows:

Or, you can create your custom Action which could look like the following:

exports.onExecutePostLogin = async (event, api) => {
  const namespace = 'https://cumulio/';
  const cumulioMetadata = event.user.app_metadata.cumulio || {};
  Object.keys(cumulioMetadata).forEach((k) => {
    api.idToken.setCustomClaim(namespace + k, cumulioMetadata[k]);
    api.accessToken.setCustomClaim(namespace + k, cumulioMetadata[k]);
  });
}

Finally, don’t forget to hit Apply!

Notice how we include everything in user.app_metadata.cumulio. This is why we put everything we need in a cumulio object in app_metadata. This Action might have to look different for you if you want to have a custom structure for your users’ app_metadata.

Retrieve User Information from Auth0

Finally, we need to retrieve user information from Auth0. The authentication branch of the example repo gives instructions on how to set up auth_config.json. Once done, you can change your /authorization endpoint to the following:

const checkJwt = jwt({
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: `https://${authConfig.domain}/.well-known/jwks.json`,
  }),
 
  audience: authConfig.audience,
  issuer: `https://${authConfig.domain}/`,
  algorithms: ['RS256'],
});
 
app.get('/authorization',checkJwt, (req, res) => {
  const authNamespace = 'https://cumulio/';
  client.create('authorization', {
    integration_id: process.env.INTEGRATION_ID,
    type: 'sso',
    expiry: '24 hours',
    inactivity_interval: '24 hours',
    role: req.user[authNamespace + 'role'],
    name: req.user[authNamespace + 'name'],
    username: req.user[authNamespace + 'username'],
    email: req.user[authNamespace + 'email'],
    suborganization: req.user[authNamespace + 'department']
  })
    .then(result => res.status(200).json(result))
    .catch(error =>{
      console.log('API Error: ' + JSON.stringify(error));
    });
});

Notice how you could also provide integration_id through app_metadata instead.

And that’s all! You’ve successfully added the Embedded Dashboard Editor to your application, with a multi-tenant setup. 🎉 

Resources

Add a Comment