Core
IoT Platform v2.x
2

Dashboard Builder #

The Dashboard Builder allows you to create personalized dashboards to visualize data from the Kuzzle IoT platform.

A dashboard is made up of widgets that can be of different types. By default, the Dashboard Builder offers 3 types of widgets:

  • Chart: allows you to visualize data sources in the form of a graph
  • Map: allows you to view assets and devices on a map or position history
  • Table: displays information in a spreadsheet type table

Dashboards implements a widgetsAreReady custom event that can be listened in DOM it will let 500ms to widgets to subscribe to loading wait queue. In case no widget send loading event, the custom event is triggered. Usage :

document.addEventListener('widgetsAreReady', callback, { once: true });

Widgets should implements specifics events described in next section to delay this event from beiing triggered.

By default, it will wait 30s before considering an error occured in widget loading, you can override this by setting : maxWidgetWaitingMs flag in dashboard document.

Custom Widgets #

It is possible to create new widgets and make them available to users of the IoT platform to create dashboards.

Widgets are fairly simple. They are constituted by two components:

  • a widget, e.g. MyWidget.vue
  • a form, e.g. MyWidgetForm.vue

Keep in mind that the Dashboard Widget will provide the Kuzzle SDK, which you can inject in these components.

Widgets have natives events that can be implemented to use them, you have to defineEmits like this:

interface EmitTypes {
  (name: 'error', error: unknown): void;
  (name: 'loading'): void;
  (name: 'loaded'): void;
}

const emit = defineEmits<EmitTypes>();
  • error event: Print the error to client in a toast. Usage : emit('error', error)
  • loading event: Ask dashboard to wait widget loading before sending widgetsAreReady custom Event
  • loaded event: Inform Dashboard that widget is fully loaded

The Widget #

The widget is nothing more than a Vuejs component that will receive the following props

// Types
interface MyWidgetSettings {
  color: string;
  dateField: string;
}

// Props
export interface MyWidgetProps {
  // Widget ID
  widgetId: string;
  // The settings, created by the Form
  widgetSettings: MyWidgetSettings;
  // The height, expressed in Vue Grid slots
  widgetHeight: number;
  // The width, expressed in Vue Grid slots
  widgetWidth: number;
  // The index name where the Dashboard engine is installed
  engineIndex: string;
}

The shape of the widgetSettings prop is up to you, it is an object where you can store all the settings you widget needs to work. This object is created and edited by the widget form.

Example:

<template>
  <div class="tw-h-full tw-w-full">
    <h1>Hello World</h1>
  </div>
</template>

<script setup lang="ts">
// Types
interface MyWidgetSettings {
  color: string;
  dateField: string;
}

// Props
export interface MyWidgetProps {
  widgetSettings: MyWidgetSettings;
  widgetHeight: number;
  widgetWidth: number;
  engineIndex: string;
  widgetId: string;
}
const props = defineProps<MyWidgetProps>();
</script>

The Form #

The form is a Vuejs component that is included in the New/Edit Widget Modal, accepting the following props:

In Typescript

interface MyWidgetSettings {
  color: string;
  dateField: string;
}

export interface MyWidgetFormProps {
  // The index name where the Dashboard engine is installed
  engineIndex: string;
  // The collections of the engine-index
  collections: string[];
  // The settings, passed to the widget
  editedWidgetSettings?: MyWidgetSettings;
}

It is a good practice to define the shape of the widget settings object in an empty-state constant, like the following one:

const props = withDefaults(defineProps<MyWidgetFormProps>(), {
  editedWidgetSettings: () => ({
    color: string;
    dateField: string;
  }),
});

Example:

<template>
  <div>
    <h1>Widget form</h1>
  </div>
</template>

<script setup lang="ts">
// Types
interface MyWidgetSettings {
  color: string;
  dateField: string;
}

export interface MyWidgetFormProps {
  // The index name where the Dashboard engine is installed
  engineIndex: string;
  // The collections of the engine-index
  collections: string[];
  // The settings, passed to the widget
  editedWidgetSettings?: MyWidgetSettings;
}
const props = withDefaults(defineProps<MyWidgetFormProps>(), {
  editedWidgetSettings: () => ({
    color: string;
    dateField: string;
  }),
});
</script>

Pass data from the Form to the Widget #

The Form should emit an change event containing the widget settings object when a setting is modified by the form.

The Dashboard Builder will then pass the updated settings object to the Widget component in the widgetSettings props.

The definition #

Once you have created your widget and form components, you can define the custom widget as follows

In main.ts

import DemoWidget from './widgets/demo/DemoWidget.vue';
import DemoWidgetForm from './widgets/demo/DemoWidgetForm.vue';

app.widgets.set('demo', {
  label: 'path.to.locale.translation', // ex: `myWidget.label
  component: DemoWidget,
  formComponent: DemoWidgetForm,
  // name of icon in fontawesome (free)
  icon: 'toggle-on',
});

If you do not use I18n, you can also use whatever string for label.
To use I18n you can define in locales/en.json and/or locales/fr.json (according to language)

{
  "myWidget": {
    "label": "My widget label"
  }
}

Dashboard Events #

Custom events can be use to interact with dashboards on create and update :

export type EventDashboardCreateBefore = {
  name: 'dashboard:create:before';
  args: [
    {
      dashboard: DashboardContent;
    },
  ];
};

export type EventDashboardCreateAfter = {
  name: 'dashboard:create:after';
  args: [
    {
      dashboard: DashboardDocument;
    },
  ];
};

export type EventDashboardUpdateBefore = {
  name: 'dashboard:update:before';
  args: [
    {
      dashboard: DashboardContent;
    },
  ];
};

export type EventDashboardUpdateAfter = {
  name: 'dashboard:update:after';
  args: [
    {
      dashboard: DashboardDocument;
    },
  ];
};