Skip to content

Developer Guide: Widget customization on Insights

Martin Peeters edited this page Jan 16, 2024 · 8 revisions

Manager UI

The Insights page allows you to create multiple dashboards within the Manager UI.
Using widgets you are able to customize what data to visualize, and how it should appear on the dashboard.
Currently we have several built-in widgets available:

Widget Description
image An attribute field with the ability to edit its value within the dashboard itself.
It works similar to the asset page, where the control changes depending on the attribute type.
image Measuring instrument to compare the current value of an attribute with some predefined thresholds.
image Background image with attribute value labels that can be placed anywhere.
image Displays the current value of an attribute, and shows the trend in a chart.
image Chart with history and/or predicted data of unlimited attributes.
Uses data decimation algorithms, and supports multi-axis.
image Map with locations of all assets that correspond with the selected asset type.
Optionally it can show a color based on thresholds, or a label with the current value of an attribute.
image Table showing multiple attribute values of the assets you select.
It is very useful for gaining insights in a larger number of assets with a single look.

We might add more widgets over time, so this list can become longer.
Feel free to develop new widgets yourself; there is functionality to create them with ease.

Building custom widgets

The widget architecture is structured to support the additions of custom widgets, whereof a short tutorial is shown below.
To know more about the dashboard builder and it's terminology, check the README of the or-dashboard-builder component.

All widget code is located under /ui/components/or-dashboard-builder/widgets/.

Working in a OpenRemote custom project?
Unfortunately this is very tricky, since all widget code is located in the or-dashboard-builder component,
but not linked to a class at all. You might need to apply inheritance to make it work for custom projects.
Take a look at the codebase and check the registerWidgetTypes() method, and references to the widgetTypes object.
We want to improve this in the future.


Creating your own Widget

All widget code is located under /ui/components/or-dashboard-builder/widgets/.
Create a new TypeScript file, and define a WidgetManifest to set up your widget.
It includes options like its display name, minimum width of columns, and a reference to the HTML content.
You can write the HTML/CSS code in the same file, or reference it from somewhere else. See the example below.

Before continuing, you are required register the widget.
This can be done by adding a link to the manifest in the registerWidgetTypes() function in the index.ts file.
It will add your widget to the 'widget browser', and handle all functions automatically.

export function registerWidgetTypes() {
    widgetTypes.set("linechart", ChartWidget.getManifest());
    widgetTypes.set("gauge", GaugeWidget.getManifest());
    ...
    // add here
}

From there, you can add your custom class to the /widgets folder and build your HTMLElements.
It is required to inherit from or-widget, (or an extended class of it such as or-asset-widget)
and your custom config is required to extend on WidgetConfig

Example of a custom Widget

Here is a code example of how to create custom widgets. Feel free to copy, and adjust it to your needs.
Looking into our existing widgets also helps understanding the codebase.

export interface CustomWidgetConfig extends WidgetConfig {
    attributeRefs: AttributeRef[];
    customFieldOne: string;
    customFieldTwo: number;
}

function getDefaultWidgetConfig(): CustomWidgetConfig {
    return {
        attributeRefs: [],
        customFieldOne: "default text",
        customFieldTwo: 0
    };
}

@customElement("custom-widget")
export class CustomWidget extends OrWidget {

    // Override of widgetConfig with extended type
    protected readonly widgetConfig!: CustomWidgetConfig;

    static getManifest(): WidgetManifest {
        return {
            displayName: "Custom widget", // name to display in widget browser
            displayIcon: "gauge", // icon to display in widget browser. Uses <or-icon> and https://materialdesignicons.com
            minColumnWidth: 1,
            minColumnHeight: 1,
            getContentHtml(config: CustomWidgetConfig): OrWidget {
                return new CustomWidget(config);
            },
            getSettingsHtml(config: CustomWidgetConfig): WidgetSettings {
                return new CustomSettings(config);
            },
            getDefaultConfig(): CustomWidgetConfig {
                return getDefaultWidgetConfig();
            }
        }
    }

    public refreshContent(force: boolean) {
        // function that executes on refresh of the widget.
        // It's normally a 'silent' function that, for example, fetches the data of assets again.
    }

    protected render(): TemplateResult {
        return html`
            <span>Custom field one: </span>
            <span>${this.widgetConfig.customFieldOne}</span>
        `;
    }

}

// Settings element
// This can be placed in a seperate file if preferred.
@customElement("custom-settings")
export class CustomSettings extends WidgetSettings {

    // Override of widgetConfig with extended type
    protected readonly widgetConfig!: CustomWidgetConfig;

    protected render(): TemplateResult {
        return html`
            <span>Custom settings</span>
            <button @click="${() => this.onButtonClick()}">Click to customize text</button>
        `;
    }

    protected onButtonClick() {
        this.widgetConfig.customFieldOne = "custom text";
        this.notifyConfigUpdate();
    }
}

User Guide

Deploying

Manager UI

Assets & Attributes

Agents/Protocols

Disabled Protocols

Manager APIs

Rules & forecasting

Identity & Security

Gateways & Devices

Domains

Tutorials

Developer Guide

Architecture

Clone this wiki locally