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 !".

Récupérer une valeur d'un élément depuis l'API

Le Widget devrait montrer la dernière valeur de l'élément choisit par l'utilisateur Pour cela, vous devrez ajouter la possibilité de sélectionner l'élément dans la configuration du Widget.

Dans cette section, vous apprendrez comment ajouter un champs de sélection d'un élément dans la configuration du Widget et comment ajouter la partie visuelle de ce champ à la vue de configuration. Ensuite, le contrôleur du Widget sera capable de récupérer les données des éléments et ses valeurs via une requête API. Une fois reçue, la valeur peut être affichée dans la vue du Widget.

  1. Ouvrir includes/WidgetForm.php et ajoutez le champ CWidgetFieldMultiSelectItem. Cela permettra la sélection d'un élément dans le formulaire de configuration

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldMultiSelectItem,
           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. Ouvrez views/widget.edit.php et ajoutez le composant visuel du champ à la vue de configuration.

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']['items']['itemid'])
           )
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. Retournez au tableau de bord et cliquez sur l’icône de l’engrenage dans le Widget afin d’ouvrir le formulaire de configuration.

  2. Le formulaire de configuration du Widget contient maintenant un nouveau champ d'entré Élément. Sélectionnez l’hôte "Serveur Zabbix" et l'élément "Load average (1m avg)".

  1. Cliquez sur Appliquer dans le formulaire de configuration du Widget. Puis cliquer sur Sauvegarder les modifications en haut a droite afin de sauvegarder les modifications du tableau de bord.

  2. Ouvrez et modifiez actions/WidgetView.php.

Désormais, l'ID de l'élément sera disponible dans le contrôleur de widget dans $this->fields_values['itemid']. La méthode du contrôleur doAction() va collecter les données des éléments (nom, type de valeur, unité) en utilisant la méthode de l'API item.get et la valeur de la dernière valeur en utilisant la méthode de l'API history.get.

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use API,
           CControllerDashboardWidgetView,
           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. Ouvrir views/widget.view.php et ajoutez la valeur de l'élément dans la vue du Widget.

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. Rafraichir la page du tableau de bord. Le Widget va maintenant afficher la valeur du dernier élément.

Ajouter du JavaScript au widget

Dans cette section, vous apprendrez à ajouter des éléments Javascript au widget.

Vous ajouterez:

  • Un graphique de jauge réalisé en JavaScript - pour montrer d'un coup d'œil si la dernière valeur est normale ou trop élevée/trop basse.
  • Une section Configuration avancée pour les paramètres facultatifs, tels que la couleur, les valeurs minimales et maximales, les unités et le champ Description créé précédemment.
  1. Créez un fichier widget.edit.js.php dans le répertoire views.

JavaScript sera chargé de masquer les champs facultatifs derrière la case à cocher Configuration avancée et d'initialiser le sélecteur de couleurs dans la vue de configuration. Vous pouvez l'ajouter au même répertoire que la vue de configuration.

Étant donné que le JavaScript de la vue de configuration doit être chargé avec le formulaire, vous devrez l'inclure dans le fichier widget.edit.php comme indiqué dans les étapes suivantes.

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. Créez un fichier Widget.php dans le répertoire principal des widgets lesson_gauge_chart pour créer une nouvelle classe Widget.

La classe Widget étend la classe de base CWidget pour ajouter ou remplacer les paramètres par défaut du widget (dans ce cas, les traductions). Le JavaScript, fourni ci-dessous, affiche la chaîne de caractères "No data" en cas de données manquantes. La chaîne de caractères "No data" est présente dans les fichiers de traduction de l'interface utilisateur Zabbix.

S'il existe des constantes de widget, il est recommandé de les spécifier également dans la classe Widget.

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. Ouvrez includes/WidgetForm.php et ajoutez les nouveaux champs : Configuration avancée (case à cocher), Couleur (sélecteur de couleur), Min (champ numérique), Max (champ numérique), et Unités (sélection).

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Modules\LessonGaugeChart\Widget;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldCheckBox,
           CWidgetFieldColor,
           CWidgetFieldMultiSelectItem,
           CWidgetFieldNumericBox,
           CWidgetFieldSelect,
           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('FF0000')
                   )
                   ->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. Ouvrez views/widget.edit.php et ajoutez les composants visuels du champ à la vue de configuration.

La méthode addField() de la classe CWidgetFormView prend une chaîne de caractères de classe CSS comme deuxième paramètre. Ajoutez la chaîne de caractères js-advanced-configuration à ces champs et à leurs étiquettes, qui doivent être cachés si Advanced configuration n'est pas sélectionné.

Pour ajouter un fichier JavaScript a la vue de configuration, utilisez la méthode includeJsFile(). Pour ajouter du JavaScript en ligne, utilisez la méthode addJavaScript().

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']['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. Retournez au tableau de bord, cliquez sur l'icone d'engrenage dans le widget pour ouvrir le formulaire de configuration du widget. Le formulaire de configuration des widget contient désormais une nouvelle case a cocher Advanced configuration.

  1. Coché la case Advanced configuration pour afficher des champs de configuration supplémentaires pour les widgets. Remplissez les champs avec des valeurs et sélectionnez une couleur de widget.

  1. Cliquez sur Apply dans le formulaire de configuration du widget. Cliquer ensuite sur Save changes dans le coin supérieur droit pour enregistrer le tableau de bord.

  2. Ouvrez actions/WidgetView.php et mettez a jour le contrôleur.

La propriété $this->fields_values contient désormais les valeurs de tous les champs de la Configuration avancée. Finaliser le contrôleur pour activer la transmissions de la configuration et la valeur de l'item sélectionner a la vue du widget.

ui/modules/lesson_gauge_chart/actions/WidgetView.php

<?php
       
       namespace Modules\LessonGaugeChart\Actions;
       
       use API,
           CControllerDashboardWidgetView,
           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. Ouvrez et modifiez views/widget.view.php.

Vous devez créer un conteneur pour le graphique de jauge, que vous dessinerez dans les étapes suivantes, et un conteneur pour la description.

Pour transmettre des valeurs à JavaScript sous la forme d'un objet JSON, utiliser la méthode setVar().

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. Créez un nouveau répertoire assets dans le répertoire lesson_gauge_chart . Ce répertoire sera utilisé pour stocker le JavaScript, CSS, et éventuellement d'autres ressources , telles que des polices d'écritures ou des images.

  2. Pour le JavaScript de la vue widget, créez un répertoire js dans le répertoire assets.

  3. Créez un fichier class.widget.js dans le répertoire assets/js.

Cette classe de widget JavaScript étend la classe JavaScript de base de tous les widgets du tableau de bord - CWidget.

Le tableau de bord s'appuie sur une implémentation correcte d'un widget et communique toute information pertinente au widget en appelant les méthodes JavaScript correspondantes. Le tableau de bord attend également du widget qu'il génère des événements en cas d'interaction. Ainsi, la classe CWidget contient un ensemble de méthodes avec l'implémentation par défaut du comportement du widget, qui peut être personnalisé en étendant la classe.

Dans ce cas, une certaine personnalisation est nécessaire, c'est pourquoi une logique personnalisée sera mise en œuvre pour le comportement du widget suivant :

  • l'initialisation du widget qui est responsable de la définition de l'état initial du widget (voir la méthode _init());
  • affichage du contenu des widgets (c'est-à-dire dessiner le graphique de jauge)si le processus de mise à jour du widget s'est déroulé avec succès et sans erreur (voir la méthode _processUpdateResponse(response) et les méthodes associées _resizeChart() et _updatedChart())
  • redimensionner le widget (voir la méthode resize() et la méthode apparenté _resizeChart())

Pour d'autres aspects du widget de la jauge, l'implémentation par défaut du comportement du widget sera utilisée. Pour en savoir plus sur les méthodes JavaScript de la classe CWidget, voir: JavaScript.

Comme ce JavaScript est nécessaire pour l'affichage du widget, il doit être chargé avec la page du tableau de bord. Pour activer le chargement du JavaScript, vous devez mettre a jour les assets/js et les paramètres js_class du fichier manifest.json comme indiqué dans l'étape suivante.

ui/modules/lesson_gauge_chart/assets/js/class.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. Ouvrez le fichier manifest.json et ajouter:
  • nom du fichier (class.widget.js) dans le tableau de la section assets/js ;
  • nom de classe (WidgetLessonGaugeChart) au paramètres js_class dans la séction widget.

La classe WidgetLessonGaugeChart sera désormais automatiquement chargée avec le tableau de bord.

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": ["class.widget.js"]
           }
       }

Ajouter des styles CSS au Widget

Dans cette section, vous apprendrez a ajouter des styles CSS personnalisés afin de rendre vos Widgets plus attrayant.

  1. Pour les styles de Widgets, créez un nouveau répertoire css dans le répertoire assets.

  2. Créez un fichier widget.css dans le répertoire assets/css. Pour styliser les éléments du widget, utilisez le sélecteur div.dashboard-widget-{widget id}. Pour configurer le CSS a l’ensemble du Widget, utilisez le sélecteur 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. Ouvrir manifest.json et ajoutez le nom du fichier CSS (widget.css) au tableau dans la section assets/css. Cela permettra aux styles CSS définis dans widget.css de se charger avec la page du tableau de bord.

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": ["class.widget.js"]
           }
       }
  1. Rafraichir la page du tableau de bord afin de voir la version finale du Widget.