This is a translation of the original English documentation page. Help us make it better.

Créer un widget (tutoriel)

Il s'agit d'un didacticiel étape par étape qui montre comment créer un simple widget de tableau de bord.

La version minimale requise de Zabbix pour ce tutoriel est 6.4.4.

Vous pouvez télécharger tous les fichiers de ce widget sous forme d'archive ZIP : lesson_gauge_chart.zip.

Ce que vous construirez

Au cours de ce didacticiel, vous allez d'abord créer un basic "Hello, world!" widget, puis convertissez-le en un widget plus avancé qui affiche la valeur d'un élément sous forme de graphique à jauge. Voici à quoi ressemblera le widget fini :

Partie I - "Bonjour tout le monde !"

Dans cette section, vous apprendrez comment créer les éléments de widget minimum requis et ajouter un nouveau widget à l'interface Zabbix.

Ajouter un widget vierge à l'interface Zabbix

  1. Créez un répertoire lesson_gauge_chart dans le répertoire modules de votre installation Zabbix (par exemple, zabbix/ui/modules).

Tous les widgets personnalisés sont traités comme des modules externes et doivent être ajoutés au répertoire modules de votre installation Zabbix (par exemple, zabbix/ui/modules). Le répertoire zabbix/ui/widgets est réservé aux widgets intégrés de Zabbix et est mis à jour avec l'interface utilisateur de Zabbix.

  1. Créez un fichier manifest.json avec les métadonnées de base du widget (voir la description des paramètres pris en charge).

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Tableau de jauge",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "author": "Zabbix SIA"
       }
  1. Dans l'interface Zabbix, accédez à la section Administration → Général → Modules et cliquez sur le bouton Analyser le répertoire.

  1. Localisez le nouveau module Gauge chart dans la liste et cliquez sur le lien hypertexte « Désactivé » pour changer l'état du module de « Désactivé » à « Activé ».

  1. Ouvrez un tableau de bord, passez-le en mode édition et ajoutez un nouveau widget. Dans le champ Type, sélectionnez « Graphique de jauge ».

  1. À ce stade, la configuration du widget Gauge chart contient uniquement les champs de widget courants Nom et Refresh interval. Cliquez sur Ajouter pour ajouter le widget au tableau de bord.

  1. Un widget vide devrait apparaître sur le tableau de bord. Cliquez sur Enregistrer les modifications dans le coin supérieur droit pour enregistrer le tableau de bord.

Ajouter une vue widget

Le fichier view du widget doit se trouver dans le répertoire views (pour ce tutoriel, ui/modules/lesson_gauge_chart/views/). Si le fichier porte le nom par défaut widget.view.php, vous n'avez pas besoin de l'enregistrer dans le fichier manifest.json. Si le fichier a un nom différent, spécifiez-le dans la section actions/widget.lesson_gauge_chart.view du fichier manifest.json.

  1. Créez un répertoire views dans le répertoire lesson_gauge_chart.

  2. Créez un fichier widget.view.php dans le répertoire views.

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
       
       /**
        * Vue du widget de graphique de jauge.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, 'Hello, world!')
           )
           ->show();
  1. Actualisez le tableau de bord. Le widget Gauge chart affiche désormais "Bonjour tout le monde !".

Partie II - Tableau des jauges

Ajoutez des paramètres à une vue de configuration et utilisez-les dans une vue widget

Dans cette section, vous apprendrez comment ajouter un champ de configuration de widget et afficher la valeur saisie dans la vue du widget sous forme de texte.

La configuration du widget se compose d'un formulaire (Zabbix\Widgets\CWidgetForm) et d'une vue de formulaire de widget (widget.edit.php). Pour ajouter des champs (Zabbix\Widgets\CWidgetField), vous devez créer une classe WidgetForm, qui étendra Zabbix\Widgets\CWidgetForm.

Le formulaire contient l'ensemble des champs (Zabbix\Widgets\CWidgetField) de différents types, qui sont utilisés pour valider les valeurs saisies par l'utilisateur. Le champ de formulaire (Zabbix\Widgets\CWidgetField) pour chaque type d'élément d'entrée convertit la valeur dans un format unique pour la stocker dans la base de données.

Le fichier form du widget doit être situé dans le répertoire includes (pour ce didacticiel, ui/modules/lesson_gauge_chart/includes/). Si le fichier porte le nom par défaut WidgetForm.php, vous n'avez pas besoin de l'enregistrer dans le fichier manifest.json. Si le fichier a un nom différent, spécifiez-le dans la section widget/form_class du fichier manifest.json.

  1. Créez un nouveau répertoire includes dans le répertoire lesson_gauge_chart.

  2. Créez un fichier WidgetForm.php dans le répertoire includes.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       class WidgetForm extends CWidgetForm {
       }
  1. Ajoutez un champ Description au formulaire de configuration du widget. Il s'agit d'un champ de texte normal, dans lequel un utilisateur peut saisir n'importe quel jeu de caractères. Vous pouvez utiliser la classe CWidgetFieldTextBox pour cela.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Include
       
       use Zabbix\Widgets\CWidgetForm;
       
       use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
       
       class WidgetForm extends CWidgetForm {
       
           public function addFields(): self {
               return $this
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Description'))
                   );
          }
       }
  1. Dans le répertoire views, créez un fichier de vue de configuration du widget widget.edit.php et ajoutez une vue pour le nouveau champ Description. Pour la classe de champ CWidgetFieldTextBox, la vue est CWidgetFieldTextBoxView.

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
       
       /**
        * Vue du formulaire du widget de graphique de jauge.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetFormView($data))
          ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. Accédez au tableau de bord et cliquez sur l'icône d'engrenage dans le widget pour ouvrir le formulaire de configuration du widget.

  2. Le formulaire de configuration du widget contient désormais un nouveau champ de texte Description. Saisissez n'importe quelle valeur, par exemple Description du graphique de jauge.

  1. Cliquez sur Appliquer dans le formulaire de configuration du widget. Cliquez ensuite sur Enregistrer les modifications dans le coin supérieur droit pour enregistrer le tableau de bord. Notez que la nouvelle description n'est visible nulle part et que le widget affiche toujours "Hello, world!".

Pour que la nouvelle description apparaisse dans le widget, la valeur du champ Description doit être récupérée de la base de données et transmise à la vue du widget. Pour cela, vous devez créer une classe d'action.

  1. Créez un nouveau répertoire actions dans le répertoire lesson_gauge_chart.

  2. Créez un fichier WidgetView.php dans le répertoire actions. La classe d'action WidgetView étendra la classe CControllerDashboardWidgetView.

Les valeurs des champs de configuration du widget sont stockées dans la propriété $fields_values de la classe d'action.

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use CControllerDashboardWidgetView,
           CControllerResponseData;
       
       class WidgetView extends CControllerDashboardWidgetView {
       
           protected function doAction(): void {
               $this->setResponse(new CControllerResponseData([
                   'name' => $this->getInput('name', $this->widget->getName()),
                   'description' => $this->fields_values['description'],
                   'user' => [
                       'debug_mode' => $this->getDebugMode()
                   ]
               ]));
           }
       }
  1. Ouvrez manifest.json et enregistrez WidgetView en tant que classe d'action dans la section actions/widget.lesson_gauge_chart.view.

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Tableau de jauge",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "auteur": "Zabbix SIA",
           "Actions": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           }
       }
  1. Vous pouvez maintenant utiliser la valeur du champ de description, contenu dans $data['description'], dans la vue widget. Ouvrez views/widget.view.php et remplacez le texte statique « Hello, world ! » avec $data['description'].

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
       
       /**
        * Vue du widget de graphique de jauge.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
          ->addItem(
               new CTag('h1', true, $data['description'])
           )
           ->show();
  1. Actualisez la page du tableau de bord. Vous devriez maintenant voir le texte de description du widget au lieu de "Bonjour tout le monde !".

Retrieve an item value via API

This widget should show the last value of an item of user's choice. For that, you need to add the ability to select items in the widget configuration.

In this section, you will learn how to add item selection field to the widget form and add the visual part of this field to the configuration view. Then, the widget controller will be able to retrieve item data and its value via an API request. Once received, the value can be displayed in the widget view.

  1. Open /includes/WidgetForm.php and add the CWidgetFieldMultiSelectItem field. This will allow selecting an item in the form.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
           
       namespace Modules\LessonGaugeChart\Includes;
           
       use Zabbix\Widgets\CWidgetField;
       use Zabbix\Widgets\CWidgetForm;
           
       use Zabbix\Widgets\Fields\CWidgetFieldMultiSelectItem;
       use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
           
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends CWidgetForm {
           
           public function addFields(): self {
               return $this
                   ->addField(
                       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                           ->setMultiple(false)
                   )
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Description'))
                   );
           }
       }
  1. Open views/widget.edit.php and add the field visual component to the configuration view.

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
           
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
           
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldMultiSelectItemView($data['fields']['itemid'], $data['captions']['ms']['items']['itemid'])
           )
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
            ->show();
  1. Return to the Dashboard and press on the gear icon to open widget configuration.

  2. The widget configuration now contains a new input field Item. Select the host Zabbix server and the item Load average (1m avg).

  1. Press Apply in the widget configuration. Then press Save changes to save the dashboard.

  2. Open and modify /actions/WidgetView.php.

From now on, the item ID will be available in the widget controller in $this->fields_values['itemid']. The doAction() controller method collects the item data (name, value type, units) using the API method item.get and item last value using the API method history.get.

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
           
       namespace Modules\LessonGaugeChart\Actions;
           
       use API;
       use CControllerDashboardWidgetView;
       use CControllerResponseData;
           
       class WidgetView extends CControllerDashboardWidgetView {
           
           protected function doAction(): void {
               $db_items = API::Item()->get([
                   'output' => ['itemid', 'value_type', 'name', 'units'],
                   'itemids' => $this->fields_values['itemid'],
                   'webitems' => true,
                   'filter' => [
                       'value_type' => [ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_FLOAT]
                   ]
               ]);
           
               $value = null;
           
               if ($db_items) {
                   $item = $db_items[0];
           
                   $history = API::History()->get([
                       'output' => API_OUTPUT_EXTEND,
                       'itemids' => $item['itemid'],
                       'history' => $item['value_type'],
                       'sortfield' => 'clock',
                       'sortorder' => ZBX_SORT_DOWN,
                       'limit' => 1
                   ]);     
           
                   if ($history) {
                       $value = convertUnitsRaw([
                           'value' => $history[0]['value'],
                           'units' => $item['units']
                       ]);
                   }   
               }
           
               $this->setResponse(new CControllerResponseData([
                   'name' => $this->getInput('name', $this->widget->getName()),
                   'value' => $value,
                   'description' => $this->fields_values['description'],
                   'user' => [
                       'debug_mode' => $this->getDebugMode()
                   ]
               ]));
           }
       }
  1. Open /views/widget.view.php and add the item value to the widget view.

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
           
       /**
        * Gauge chart widget view.
        *
        * @var CView $this
        * @var array $data
        */
           
       (new CWidgetView($data))
           ->addItem([
               new CTag('h1', true, $data['description']),
               new CDiv($data['value'] !== null ? $data['value']['value'] : _('No data'))
           ])
           ->show();
  1. Refresh the Dashboard page. The widget will display the latest item value.

Add JavaScript to the widget.

In this section, you will learn how to add Javascript elements to the widget.

You will add:

  • a gauge chart made using JavaScript - to show at a glance if the latest value is normal or too high/too low.
  • Advanced configuration section for optional parameters, such as color, minimum and maximum values, units and the Description field created earlier.
  1. Create widget.edit.js.php file inside the views directory.

JavaScript will be responsible for hiding optional fields behind the Advanced configuration checkbox and initializing the colorpicker in the configuration view. You can add it to the same directory as the configuration view.

Since the JavaScript for configuration view should be loaded with the form, you will need to include it into widget.edit.php as shown in the next steps.

ui/modules/lesson_gauge_chart/views/widget.edit.js.php

<?php
           
       use Modules\LessonGaugeChart\Widget;
           
       ?>
           
       window.widget_lesson_gauge_chart_form = new class {
           
           init({color_palette}) {
               this._form = document.getElementById('widget-dialogue-form');
           
               this._advanced_configuration = document.getElementById('adv_conf');
               this._unit_select = document.getElementById('value_units');
               this._unit_value = document.getElementById('value_static_units');
           
               this._advanced_configuration.addEventListener('change', () => this.updateForm());
               this._unit_select.addEventListener('change', () => this.updateForm());
           
               colorPalette.setThemeColors(color_palette);
           
               for (const colorpicker of jQuery('.<?= ZBX_STYLE_COLOR_PICKER ?> input')) {
                   jQuery(colorpicker).colorpicker();
               }
           
               const overlay = overlays_stack.getById('widget_properties');
           
               for (const event of ['overlay.reload', 'overlay.close']) {
                   overlay.$dialogue[0].addEventListener(event, () => { jQuery.colorpicker('hide'); });
               }
           
               this.updateForm();
           }
           
           updateForm() {
               const show_advanced_configuration = this._advanced_configuration.checked;
           
               for (const element of this._form.querySelectorAll('.js-advanced-configuration')) {
                   element.style.display = show_advanced_configuration ? '' : 'none';
               }
           
               this._unit_value.disabled = this._unit_select.value == <?= Widget::UNIT_AUTO ?>;
           }
       };   
  1. Add Widget.php file to the main widget directory lesson_gauge_chart to create a new class Widget.

The Widget class will extend the CWidget base class to add/override the default widget settings. In this case, these are translations. JavaScript, provided above, displays the string "No data" in case of missing data. The "No data" string is present in the Zabbix UI translation files.

If there are any widget constants, it is recommended to also specify them in the Widget class.

ui/modules/lesson_gauge_chart/Widget.php

<?php 
           
       namespace Modules\LessonGaugeChart;
           
       use Zabbix\Core\CWidget;
           
       class Widget extends CWidget {
           
           public const UNIT_AUTO = 0;
           public const UNIT_STATIC = 1;
           
           public function getTranslationStrings(): array {
               return [
                   'class.widget.js' => [
                       'No data' => _('No data')
                   ]
               ];
           }
       }
  1. Open includes/WidgetForm.php and add the new fields Advanced configuration (checkbox), Color (color picker), Min (numeric field), Max (numeric field), Units (select).

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
           
       namespace Modules\LessonGaugeChart\Includes;
           
       use Modules\LessonGaugeChart\Widget;
       use Zabbix\Widgets\CWidgetField;
       use Zabbix\Widgets\CWidgetForm;
           
       use Zabbix\Widgets\Fields\CWidgetFieldCheckBox;
       use Zabbix\Widgets\Fields\CWidgetFieldColor;
       use Zabbix\Widgets\Fields\CWidgetFieldMultiSelectItem;
       use Zabbix\Widgets\Fields\CWidgetFieldNumericBox;
       use Zabbix\Widgets\Fields\CWidgetFieldSelect;
       use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
           
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends CWidgetForm {
           
           public function addFields(): self {
               return $this
                   ->addField(
                       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                           ->setMultiple(false)
                           ->setFilterParameter('numeric', true)
                   )
                   ->addField(
                       new CWidgetFieldCheckBox('adv_conf', _('Advanced configuration'))
                   )
                   ->addField(
                       (new CWidgetFieldColor('chart_color', _('Color')))->setDefault('666666')
                   )
                   ->addField(
                       (new CWidgetFieldNumericBox('value_min', _('Min')))
                           ->setDefault(0)
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                   )
                   ->addField(
                       (new CWidgetFieldNumericBox('value_max', _('Max')))
                           ->setDefault(100)
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                   )
                   ->addField(
                       (new CWidgetFieldSelect('value_units', _('Units'), [
                           Widget::UNIT_AUTO => _x('Auto', 'history source selection method'),
                           Widget::UNIT_STATIC => _x('Static', 'history source selection method')
                       ]))->setDefault(Widget::UNIT_AUTO)
                   )
                   ->addField(
                       (new CWidgetFieldTextBox('value_static_units'))
                   )
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Description'))
                   );
           }
       }
  1. Open views/widget.edit.php and add the field visual components to the configuration view.

The addField() method of the CWidgetFormView class takes a CSS class string as the second parameter. Add the js-advanced-configuration string to those fields and their labels, which should be hidden if Advanced configuration is not selected.

To add JavaScript file to the configuration view, use the includeJsFile() method. To add inline JavaScript, use the addJavaScript() method.

ui/modules/lesson_gauge_chart/views/widget.edit.php

<?php
           
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
           
       use Zabbix\Widgets\Fields\CWidgetFieldGraphDataSet;
           
       $lefty_units = new CWidgetFieldSelectView($data['fields']['value_units']);
       $lefty_static_units = (new CWidgetFieldTextBoxView($data['fields']['value_static_units']))
           ->setPlaceholder(_('value'))
           ->setWidth(ZBX_TEXTAREA_TINY_WIDTH);
           
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldMultiSelectItemView($data['fields']['itemid'], $data['captions']['ms']['items']['itemid'])
           )
           ->addField(
               new CWidgetFieldCheckBoxView($data['fields']['adv_conf'])
           )
           ->addField(
               new CWidgetFieldColorView($data['fields']['chart_color']),
               'js-advanced-configuration'
           )
           ->addField(
               new CWidgetFieldNumericBoxView($data['fields']['value_min']),
               'js-advanced-configuration'
           )
           ->addField(
               new CWidgetFieldNumericBoxView($data['fields']['value_max']),
               'js-advanced-configuration'
           )
           ->addItem([
               $lefty_units->getLabel()->addClass('js-advanced-configuration'),
               (new CFormField([
                   $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                   $lefty_static_units->getView()
               ]))->addClass('js-advanced-configuration')
           ])
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description']),
               'js-advanced-configuration'
           )
           ->includeJsFile('widget.edit.js.php')
           ->addJavaScript('widget_lesson_gauge_chart_form.init('.json_encode([
                   'color_palette' => CWidgetFieldGraphDataSet::DEFAULT_COLOR_PALETTE
               ], JSON_THROW_ON_ERROR).');')
           ->show();   
  1. Return to the Dashboard, switch to the edit mode and press on the gear icon to open widget configuration. The widget configuration now contains a new checkbox Advanced options.

  1. Mark the Advanced configuration checkbox to see additional widget configuration fields. Fill in the fields with values and select a widget color.

  1. Press Apply in the widget configuration. Then press Save changes to save the dashboard.

  2. Open actions/WidgetView.php and update the controller.

The $this->fields_values property now contain the values of all the Advanced configuration fields. Finalize the controller to enable passing the configuration and selected item value to the widget view.

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
           
       namespace Modules\LessonGaugeChart\Actions;
           
       use API;
       use CControllerDashboardWidgetView;
       use CControllerResponseData;
           
       class WidgetView extends CControllerDashboardWidgetView {
           
           protected function doAction(): void {
               $db_items = API::Item()->get([
                   'output' => ['itemid', 'value_type', 'name', 'units'],
                   'itemids' => $this->fields_values['itemid'],
                   'webitems' => true,
                   'filter' => [
                       'value_type' => [ITEM_VALUE_TYPE_UINT64, ITEM_VALUE_TYPE_FLOAT]
                   ]
               ]);
           
               $history_value = null;
           
               if ($db_items) {
                   $item = $db_items[0];
           
                   $history = API::History()->get([
                       'output' => API_OUTPUT_EXTEND,
                       'itemids' => $item['itemid'],
                       'history' => $item['value_type'],
                       'sortfield' => 'clock',
                       'sortorder' => ZBX_SORT_DOWN,
                       'limit' => 1
                   ]);
           
                   if ($history) {
                       $history_value = convertUnitsRaw([
                           'value' => $history[0]['value'],
                           'units' => $item['units']
                       ]);
                   }
               }
           
               $this->setResponse(new CControllerResponseData([
                   'name' => $this->getInput('name', $this->widget->getName()),
                   'history' => $history_value,
                   'fields_values' => $this->fields_values,
                   'user' => [
                       'debug_mode' => $this->getDebugMode()
                   ]
               ]));
           }
       }
  1. Open and modify views/widget.view.php

You need to create a container for the gauge chart, which you will draw in the next steps, and a container for the description.

To pass values to JavaScript as a JSON object, use the setVar() method.

ui/modules/lesson_gauge_chart/views/widget.view.php

<?php
           
       /**
        * Gauge chart widget view.
        *
        * @var CView $this
        * @var array $data
        */
           
       (new CWidgetView($data))
           ->addItem([
               (new CDiv())->addClass('chart'),
               $data['fields_values']['description']
                   ? (new CDiv($data['fields_values']['description']))->addClass('description')
                   : null
           ])
           ->setVar('history', $data['history'])
           ->setVar('fields_values', $data['fields_values'])
           ->show();
  1. Create a directory assets in the lesson_gauge_chart. This directory will be used for storing Javascript, CSS and potentially any other assets, such as fonts or images.

  2. For widget view JavaScript, create a directory js inside the assets directory.

  3. Create widget.js file in the assets/js directory.

This JavaScript widget class will handle updating the data, resizing the widget, and drawing the gauge chart. Learn more about the JavaScript methods of the CWidget class {link to documentation}

Since this JavaScript is required for the widget view, it should be loaded with the dashboard page. To enable JavaScript loading, you will need to update assets/js and js_class parameters of manifest.json as shown in the next step.

ui/modules/lesson_gauge_chart/assets/js/widget.js

class WidgetLessonGaugeChart extends CWidget {
           
           static UNIT_AUTO = 0;
           static UNIT_STATIC = 1;
           
           _init() {
               super._init();
           
               this._refresh_frame = null;
               this._chart_container = null;
               this._canvas = null;
               this._chart_color = null;
               this._min = null;
               this._max = null;
               this._value = null;
               this._last_value = null;
               this._units = '';
           }
           
           _processUpdateResponse(response) {
               if (response.history === null) {
                   this._value = null;
                   this._units = '';
               }
               else {
                   this._value = Number(response.history.value);
                   this._units = response.fields_values.value_units == WidgetLessonGaugeChart.UNIT_AUTO
                       ? response.history.units
                       : response.fields_values.value_static_units;
               }
           
               this._chart_color = response.fields_values.chart_color;
               this._min = Number(response.fields_values.value_min);
               this._max = Number(response.fields_values.value_max);
           
               if (this._canvas === null) {
                   super._processUpdateResponse(response);
           
                   this._chart_container = this._content_body.querySelector('.chart');
                   this._canvas = document.createElement('canvas');
           
                   this._chart_container.appendChild(this._canvas);
           
                   this._resizeChart();
               }
               else {
                   this._updatedChart();
               }
           }
           
           resize() {
               super.resize();
           
               if (this._state === WIDGET_STATE_ACTIVE) {
                   this._resizeChart();
               }
           }
           
           _resizeChart() {
               const ctx = this._canvas.getContext('2d');
               const dpr = window.devicePixelRatio;
           
               this._canvas.style.display = 'none';
               const size = Math.min(this._chart_container.offsetWidth, this._chart_container.offsetHeight);
               this._canvas.style.display = '';
           
               this._canvas.width = size * dpr;
               this._canvas.height = size * dpr;
           
               ctx.scale(dpr, dpr);
           
               this._canvas.style.width = `${size}px`;
               this._canvas.style.height = `${size}px`;
           
               this._refresh_frame = null;
           
               this._updatedChart();
           }
           
           _updatedChart() {
               if (this._last_value === null) {
                   this._last_value = this._min;
               }
           
               const start_time = Date.now();
               const end_time = start_time + 400;
           
               const animate = () => {
                   const time = Date.now();
           
                   if (time <= end_time) {
                       const progress = (time - start_time) / (end_time - start_time);
                       const smooth_progress = 0.5 + Math.sin(Math.PI * (progress - 0.5)) / 2;
                       let value = this._value !== null ? this._value : this._min;
                       value = (this._last_value + (value - this._last_value) * smooth_progress - this._min) / (this._max - this._min);
           
                       const ctx = this._canvas.getContext('2d');
                       const size = this._canvas.width;
                       const char_weight = size / 12;
                       const char_shadow = 3;
                       const char_x = size / 2;
                       const char_y = size / 2;
                       const char_radius = (size - char_weight) / 2 - char_shadow;
           
                       const font_ratio = 32 / 100;
           
                       ctx.clearRect(0, 0, size, size);
           
                       ctx.beginPath();
                       ctx.shadowBlur = char_shadow;
                       ctx.shadowColor = '#bbb';
                       ctx.strokeStyle = '#eee';
                       ctx.lineWidth = char_weight;
                       ctx.lineCap = 'round';
                       ctx.arc(char_x, char_y, char_radius, Math.PI * 0.749, Math.PI * 2.251, false);
                       ctx.stroke();
           
                       ctx.beginPath();
                       ctx.strokeStyle = `#${this._chart_color}`;
                       ctx.lineWidth = char_weight - 2;
                       ctx.lineCap = 'round';
                       ctx.arc(char_x, char_y, char_radius, Math.PI * 0.75,
                           Math.PI * (0.75 + (1.5 * Math.min(1, Math.max(0, value)))), false
                           );
                       ctx.stroke();
           
                       ctx.shadowBlur = 2;
                       ctx.fillStyle = '#1f2c33';
                       ctx.font = `${(char_radius * font_ratio)|0}px Arial`;
                       ctx.textAlign = 'center';
                       ctx.textBaseline = 'middle';
                       ctx.fillText(`${this._value !== null ? this._value : t('No data')}${this._units}`,
                           char_x, char_y, size - char_shadow * 4 - char_weight * 2
                       );
           
                       ctx.fillStyle = '#768d99';
                       ctx.font = `${(char_radius * font_ratio * .5)|0}px Arial`;
                       ctx.textBaseline = 'top';
           
                       ctx.textAlign = 'left';
                       ctx.fillText(`${this._min}${this._min != '' ? this._units : ''}`,
                           char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                       );
           
                       ctx.textAlign = 'right';
                       ctx.fillText(`${this._max}${this._max != '' ? this._units : ''}`,
                           size - char_weight * .75, size - char_weight * 1.25, size / 2 - char_weight
                       );
           
                       requestAnimationFrame(animate);
                   }
                   else {
                       this._last_value = this._value;
                   }
               };
           
               requestAnimationFrame(animate);
           }
       }
  1. Open manifest.json and add:
  • file name (widget.js) to the array in the assets/js section.
  • class name (WidgetLessonGaugeChart) to the js_class parameter in the widget section.

WidgetLessonGaugeChart class will now be automatically loaded with the dashboard.

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Gauge chart",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "author": "Zabbix SIA",
           "actions": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           },
           "widget": {
               "js_class": "WidgetLessonGaugeChart"
           },
           "assets": {
               "js": ["widget.js"]
           }
       }

Add CSS styles to the widget.

In this section you will learn how to add custom CSS styles to make the widget look more appealing.

  1. For widget styles, create a new directory css inside the assets directory.

  2. Add widget.css file to the assets/css. To style widget elements, use the selector div.dashboard-widget-{widget id}. To configure CSS for the whole widget, use the selector form.dashboard-widget-{widget id}

ui/modules/lesson_gauge_chart/assets/css/widget.css

div.dashboard-widget-lesson_gauge_chart {
           display: grid;
           grid-template-rows: 1fr;
           padding: 0; 
       }
             
       div.dashboard-widget-lesson_gauge_chart .chart {
           display: grid;
           align-items: center;
           justify-items: center; 
       }
               
       div.dashboard-widget-lesson_gauge_chart .chart canvas {
           background: white; 
       }
             
       div.dashboard-widget-lesson_gauge_chart .description {
           padding-bottom: 8px;
           font-size: 1.750em;
           line-height: 1.2;
           text-align: center; 
       }
           
       .dashboard-grid-widget-hidden-header div.dashboard-widget-lesson_gauge_chart .chart {
           margin-top: 8px; 
       }
  1. Open manifest.json and add the file name (widget.css) to the array in the assets/css section. This will allow CSS styles defined in the widget.css to load with the dashboard page.

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Gauge chart",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "author": "Zabbix SIA",
           "actions": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           },
           "widget": {
               "js_class": "WidgetLessonGaugeChart"
           },
           "assets": {
               "css": ["widget.css"],
               "js": ["widget.js"]
           }
       }
  1. Refresh the dashboard page to see finished version of the widget.