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

Maak een widget (handleiding)

Dit is een stapsgewijze handleiding die laat zien hoe je een eenvoudige dashboardwidget kunt maken.

De vereiste minimale Zabbix-versie voor deze tutorial is 6.4.4.

Je kunt alle bestanden van deze widget downloaden als een ZIP-archief: lesson_gauge_chart.zip.

Wat je gaat bouwen

Tijdens deze tutorial ga je eerst een basis "Hallo, wereld!" widget maken en vervolgens deze omzetten naar een geavanceerdere widget die een itemwaarde weergeeft als een metergrafiek. Zo ziet de afgewerkte widget eruit:

Deel I - "Hallo, wereld!"

In deze sectie leert u hoe u de minimaal vereiste widget-elementen maakt en een nieuwe widget toevoegt aan de Zabbix-frontend.

Voeg een lege widget toe aan de Zabbix-frontend

  1. Maak een map genaamd lesson_gauge_chart aan in zabbix/ui/modules.

Alle aangepaste widgets worden behandeld als externe modules en moeten worden toegevoegd aan de map ui/modules. De map ui/widgets is gereserveerd voor de ingebouwde widgets van Zabbix en wordt bijgewerkt samen met de Zabbix-UI.

  1. Maak een bestand genaamd manifest.json aan met de basisgegevens van de widget (zie de beschrijving van ondersteunde parameters).

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Metergrafiek",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "author": "Zabbix SIA"
       }
  1. Ga in de Zabbix-frontend naar de sectie Beheer → Algemeen → Modules en klik op de knop Map scannen.

  1. Zoek de nieuwe module Metergrafiek in de lijst en klik op de hyperlink "Uitgeschakeld" om de status van de module te wijzigen van "Uitgeschakeld" naar "Ingeschakeld".

  1. Open een dashboard, schakel over naar de bewerkingsmodus en voeg een nieuwe widget toe. Selecteer bij het veld Type "Metergrafiek".

  1. Op dit punt bevat de configuratie van de Metergrafiek widget alleen gemeenschappelijke widgetvelden Naam en Vernieuwingsinterval. Klik op Toevoegen om de widget aan het dashboard toe te voegen.

  1. Er zou nu een lege widget op het dashboard moeten verschijnen. Klik op Wijzigingen opslaan in de rechterbovenhoek om het dashboard op te slaan.

Voeg een widget-weergave toe

Het weergave-bestand van de widget moet zich bevinden in de views-map (voor deze tutorial ui/modules/lesson_gauge_chart/views/). Als het bestand de standaardnaam widget.view.php heeft, hoef je het niet te registreren in het manifest.json-bestand. Als het bestand een andere naam heeft, specificeer deze dan in de sectie actions/widget.lesson_gauge_chart.view van het manifest.json-bestand.

  1. Maak een map genaamd views aan in de lesson_gauge_chart-map.

  2. Maak een bestand genaamd widget.view.php aan in de views-map.

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

<?php
       
       /**
        * Weergave van de metergrafiek-widget.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, 'Hallo, wereld!')
           )
           ->show();
  1. Vernieuw het dashboard. De Metergrafiek widget toont nu "Hallo, wereld!".

Deel II - Grafiek met meterindicatie

Voeg instellingen toe aan een configuratieweergave en gebruik ze in een widgetweergave

In dit gedeelte leer je hoe je een configuratieveld aan een widget kunt toevoegen en de ingevoerde waarde in de widgetweergave kunt tonen als tekst.

De configuratie van de widget bestaat uit een formulier (Zabbix\Widgets\CWidgetForm) en een weergave voor het widgetformulier (widget.edit.php). Om velden (Zabbix\Widgets\CWidgetField) toe te voegen, moet je een klasse WidgetForm maken, die Zabbix\Widgets\CWidgetForm uitbreidt.

Het formulier bevat een reeks velden (Zabbix\Widgets\CWidgetField) van verschillende typen, die worden gebruikt om de door de gebruiker ingevoerde waarden te valideren. Het formulierveld (Zabbix\Widgets\CWidgetField) voor elk invoerelementtype converteert de waarde naar een enkel formaat om deze op te slaan in de database.

Het formulier-bestand van de widget moet zich bevinden in de includes-map (voor deze tutorial ui/modules/lesson_gauge_chart/includes/). Als het bestand de standaardnaam WidgetForm.php heeft, hoef je het niet te registreren in het manifest.json-bestand. Als het bestand een andere naam heeft, specificeer deze dan in de sectie widget/form_class van het manifest.json-bestand.

  1. Maak een nieuwe map genaamd includes aan in de lesson_gauge_chart-map.

  2. Maak een bestand genaamd WidgetForm.php aan in de includes-map.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       class WidgetForm extends CWidgetForm {
       }
  1. Voeg een veld Beschrijving toe aan het configuratieformulier van de widget. Dit is een gewoon tekstveld, waarin een gebruiker een willekeurige tekenreeks kan invoeren. Je kunt hiervoor de klasse CWidgetFieldTextBox gebruiken.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
       
       class WidgetForm extends CWidgetForm {
       
           public function addFields(): self {
               return $this
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Beschrijving'))
                   );
          }
       }
  1. Maak in de views-map een weergavebestand voor het configuratieformulier van het widget aan met de naam widget.edit.php en voeg een weergave toe voor het nieuwe Beschrijving-veld. Voor de klasse CWidgetFieldTextBox is de weergaveklasse CWidgetFieldTextBoxView.

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

<?php
       
       /**
        * Weergave van het formulier voor de metergrafiek-widget.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. Ga naar het dashboard en klik op het tandwielicoon in de widget om het configuratieformulier van het widget te openen.

  2. Het configuratieformulier van het widget bevat nu een nieuw tekstveld Beschrijving. Voer een willekeurige waarde in, bijvoorbeeld Beschrijving van de metergrafiek.

  1. Klik op Toepassen in het configuratieformulier van het widget. Klik vervolgens op Wijzigingen opslaan in de rechterbovenhoek om het dashboard op te slaan. Merk op dat de nieuwe beschrijving nergens zichtbaar is en dat het widget nog steeds "Hallo, wereld!" weergeeft.

Om de nieuwe beschrijving in het widget te laten verschijnen, moet de waarde van het veld Beschrijving uit de database worden opgehaald en doorgegeven aan de weergave van het widget. Hiervoor moet je een actieklasse maken.

  1. Maak een nieuwe map genaamd actions aan in de lesson_gauge_chart-map.

  2. Maak een bestand genaamd WidgetView.php aan in de actions-map. De actieklasse WidgetView zal de klasse CControllerDashboardWidgetView uitbreiden.

Waarden van de velden in de configuratie van het widget worden opgeslagen in de eigenschap $fields_values van de actieklasse.

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. Open manifest.json en registreer WidgetView als een actieklasse in de sectie actions/widget.lesson_gauge_chart.view.

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Metergrafiek",
           "namespace": "LessonGaugeChart",
           "version": "1.0",
           "author": "Zabbix SIA",
       
       
           "actions": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           }
       }
  1. Nu kun je de waarde van het beschrijvingsveld, die is opgeslagen in $data['description'], gebruiken in de weergave van het widget. Open views/widget.view.php en vervang de statische tekst "Hallo, wereld!" door $data['description'].

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

<?php
       
       /**
        * Weergave van de metergrafiek-widget.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, $data['description'])
           )
           ->show();
  1. Vernieuw de dashboardpagina. Je zou nu de beschrijvingstekst van het widget moeten zien in plaats van "Hallo, wereld!".

Haal een itemwaarde op via de API

Het widget zou de laatste waarde van een item naar keuze van de gebruiker moeten tonen. Hiervoor moet je de mogelijkheid toevoegen om items te selecteren in de configuratie van het widget.

In dit gedeelte leer je hoe je een itemselectieveld aan het widgetformulier kunt toevoegen en hoe je het visuele deel van dit veld kunt toevoegen aan de configuratieweergave. Daarna kan de widgetcontroller itemgegevens en de waarde van het item ophalen via een API-aanvraag. Zodra deze ontvangen is, kan de waarde worden weergegeven in de widgetweergave.

  1. Open includes/WidgetForm.php en voeg het veld CWidgetFieldMultiSelectItem toe. Dit maakt het mogelijk om een item te selecteren in het configuratieformulier.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldMultiSelectItem,
           CWidgetFieldTextBox
       };
       
       /**
        * Formulier van de metergrafiek-widget.
        */
       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', _('Beschrijving'))
                   );
           }
       }
  1. Open views/widget.edit.php en voeg het visuele component van het veld toe aan de configuratieweergave.

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

<?php
       
       /**
        * Weergave van het formulier voor de metergrafiek-widget.
        *
        * @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. Ga terug naar het dashboard en klik op het tandwielicoon in de widget om het configuratieformulier van het widget te openen.

  2. Het configuratieformulier van het widget bevat nu een nieuw invoerveld Item. Selecteer de host "Zabbix server" en het item "Load average (1m avg)".

  1. Klik op Toepassen in het configuratieformulier van het widget. Klik vervolgens op Wijzigingen opslaan in de rechterbovenhoek om het dashboard op te slaan.

  2. Open actions/WidgetView.php en pas dit aan.

Vanaf nu zal het item-ID beschikbaar zijn in de widgetcontroller in $this->fields_values['itemid']. De methode doAction() van de controller verzamelt de itemgegevens (naam, waarde type, eenheden) met behulp van de API-methode item.get en de laatste itemwaarde met behulp van de API-methode 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. Open views/widget.view.php en voeg de itemwaarde toe aan de weergave van het widget.

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

<?php
       
       /**
        * Weergave van de metergrafiek-widget.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem([
               new CTag('h1', true, $data['description']),
               new CDiv($data['value'] !== null ? $data['value']['value'] : _('Geen gegevens'))
           ])
           ->show();
  1. Vernieuw de dashboardpagina. Het widget zal de laatste itemwaarde tonen.

Add advanced configuration settings to a configuration view

In this section, you will learn how to add an expandable/collapsible Advanced configuration section with optional parameters, such as color, minimum and maximum values, units and the Description field created earlier.

  1. Create a Widget.php file in 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 - translations). JavaScript, provided below, 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 Color (color picker), Min (numeric field), Max (numeric field), and Units (select), and define the default color palette for the color picker, so that it can be used in the next steps.

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\{
           CWidgetFieldColor,
           CWidgetFieldMultiSelectItem,
           CWidgetFieldNumericBox,
           CWidgetFieldSelect,
           CWidgetFieldTextBox
       };
       
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends CWidgetForm {
       
           public const DEFAULT_COLOR_PALETTE = [
               'FF465C', 'B0AF07', '0EC9AC', '524BBC', 'ED1248', 'D1E754', '2AB5FF', '385CC7', 'EC1594', 'BAE37D',
               '6AC8FF', 'EE2B29', '3CA20D', '6F4BBC', '00A1FF', 'F3601B', '1CAE59', '45CFDB', '894BBC', '6D6D6D'
           ];
       
           public function addFields(): self {
               return $this
                   ->addField(
                       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                           ->setMultiple(false)
                   )
                   ->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. Open views/widget.edit.php and add the field visual components 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
        */
       
       $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']))
                   ->setPopupParameter('numeric', true)
           )
           ->addFieldset(
               (new CWidgetFormFieldsetCollapsibleView(_('Advanced configuration')))
                   ->addField(
                       new CWidgetFieldColorView($data['fields']['chart_color'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_min'])
                   )
                   ->addField(
                       new CWidgetFieldNumericBoxView($data['fields']['value_max'])
                   )
                   ->addItem([
                       $lefty_units->getLabel(),
                       (new CFormField([
                           $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                           $lefty_static_units->getView()
                       ]))
                   ])
                   ->addField(
                       new CWidgetFieldTextBoxView($data['fields']['description'])
                   )
           )
           ->show();

The addField() method of the CWidgetFormView class takes a CSS class string as the second parameter.

  1. Return to the dashboard, switch to the edit mode and click on the gear icon in the widget to open the widget configuration form. The widget configuration form now contains a new expandable/collapsible section Advanced configuration.

  1. Expand the Advanced configuration section to see additional widget configuration fields. Note that the field Color has no color picker yet. This is because the color picker must be initialized with JavaScript, which will be added in the next section - Add JavaScript to the widget.

JavaScript aan de widget toevoegen

In deze sectie leer je hoe je JavaScript-elementen aan de widget kunt toevoegen.

Je voegt het volgende toe:

  • Een metergrafiek gemaakt met behulp van JavaScript - om in één oogopslag te laten zien of de laatste waarde normaal is, te hoog of te laag.
  • Een Geavanceerde configuratie sectie voor optionele parameters, zoals kleur, minimale en maximale waarden, eenheden en het eerder aangemaakte Beschrijvings veld.
  1. Maak een widget.edit.js.php bestand aan in de views map.

JavaScript zal verantwoordelijk zijn voor het verbergen van optionele velden achter de Geavanceerde configuratie checkbox en voor het initialiseren van de kleurkiezer in de configuratie weergave. Je kunt het toevoegen aan dezelfde map als de configuratie weergave.

Aangezien de JavaScript voor de configuratie weergave geladen moet worden met het formulier, dien je het op te nemen in het widget.edit.php bestand zoals getoond in de volgende stappen.

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. Maak een Widget.php bestand aan in de hoofdwidgetmap lesson_gauge_chart om een nieuwe klasse Widget aan te maken.

De Widget klasse zal de basis klasse CWidget uitbreiden om de standaard widgetinstellingen toe te voegen/te overschrijven (in dit geval - vertalingen). De onderstaande JavaScript toont de string "Geen gegevens" in het geval van ontbrekende data. De string "Geen gegevens" is aanwezig in de Zabbix UI vertalingsbestanden.

Als er widgetconstanten zijn, wordt het ook aanbevolen om ze in de Widget klasse te specificeren.

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' => _('Geen gegevens')
                   ]
               ];
           }
       }
  1. Open includes/WidgetForm.php en voeg de nieuwe velden toe: Geavanceerde configuratie (checkbox), Kleur (kleurkiezer), Min (numeriek veld), Max (numeriek veld) en Eenheden (select).

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
       };
       
       /**
        * Formulier voor de metergrafiek widget.
        */
       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', _('Geavanceerde configuratie'))
                   )
                   ->addField(
                       (new CWidgetFieldColor('chart_color', _('Kleur')))->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', _('Eenheden'), [
                           Widget::UNIT_AUTO => _x('Automatisch', 'methode voor selectie van geschiedenisbron'),
                           Widget::UNIT_STATIC => _x('Statisch', 'methode voor selectie van geschiedenisbron')
                       ]))->setDefault(Widget::UNIT_AUTO)
                   )
                   ->addField(
                       (new CWidgetFieldTextBox('value_static_units'))
                   )
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Beschrijving'))
                   );
           }
       }
  1. Open views/widget.edit.php en voeg de visuele componenten van het veld toe aan de configuratieweergave.

De addField()-methode van de klasse CWidgetFormView neemt een CSS-klassenreeks als tweede parameter. Voeg de tekenreeks js-advanced-configuration toe aan die velden en hun labels die verborgen moeten zijn als Geavanceerde configuratie niet is geselecteerd.

Om een JavaScript-bestand aan de configuratieweergave toe te voegen, gebruik je de methode includeJsFile(). Gebruik de methode addJavaScript() voor inline JavaScript.

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

<?php
       
       /**
        * Weergaveformulier voor de metergrafiek widget.
        *
        * @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(_('waarde'))
           ->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. Keer terug naar het dashboard en klik op het tandwielpictogram in de widget om het widget configuratieformulier te openen. Het widget configuratieformulier bevat nu een nieuwe Geavanceerde configuratie checkbox.

  1. Vink de Geavanceerde configuratie checkbox aan om extra widget configuratievelden te zien. Vul de velden in met waarden en selecteer een widget kleur.

  1. Klik op Toepassen in het widget configuratieformulier. Klik vervolgens rechtsboven op Wijzigingen opslaan om het dashboard op te slaan.

  2. Open actions/WidgetView.php en update de controller.

De $this->fields_values eigenschap bevat nu de waarden van alle Geavanceerde configuratie velden. Rond de controller af om het doorgeven van de configuratie en de geselecteerde itemwaarde naar de widget weergave mogelijk te maken.

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. Open en bewerk views/widget.view.php.

Je moet een container maken voor de metergrafiek die je in de volgende stappen zult tekenen, en een container voor de beschrijving.

Om waarden door te geven aan JavaScript als een JSON-object, gebruik de setVar()-methode.

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

<?php
       
       /**
        * Weergave van de metergrafiek widget.
        *
        * @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. Maak een nieuwe map assets aan in de lesson_gauge_chart map. Deze map wordt gebruikt voor het opslaan van JavaScript, CSS en mogelijk andere bronnen, zoals lettertypen of afbeeldingen.

  2. Maak voor de JavaScript van de widgetweergave een map js aan in de assets map.

  3. Maak een class.widget.js bestand aan in de assets/js map.

Deze JavaScript-widgetklasse zal de basis JavaScript-klasse van alle dashboardwidgets uitbreiden - CWidget.

Het dashboard vertrouwt op een juiste implementatie van een widget en communiceert alle relevante informatie naar de widget door de respectievelijke JavaScript-methoden aan te roepen. Het dashboard verwacht ook dat de widget gebeurtenissen genereert wanneer er interactie plaatsvindt. Daarom bevat de CWidget klasse een reeks methoden met de standaardimplementatie van widgetgedrag, die kan worden aangepast door de klasse uit te breiden.

In dit geval is enige aanpassing nodig, daarom zal aangepaste logica worden geïmplementeerd voor het volgende widgetgedrag:

  • initialisatie van de widget die verantwoordelijk is voor het definiëren van de initiële staat van de widget (zie de _init() methode);
  • weergeven van de widgetinhoud (dat wil zeggen, het tekenen van de metergrafiek) als het updateproces van de widget succesvol is verlopen en zonder fouten (zie de _processUpdateResponse(response) methode en de gerelateerde _resizeChart() en _updatedChart() methoden);
  • grootte van de widget aanpassen (zie de resize() methode en de gerelateerde _resizeChart() methode).

Voor andere aspecten van de metergrafiek widget zal de standaardimplementatie voor widgetgedrag worden gebruikt. Om meer te weten te komen over de JavaScript-methoden van de CWidget klasse, zie: JavaScript.

Aangezien deze JavaScript vereist is voor de widgetweergave, moet deze worden geladen met de dashboardpagina. Om het laden van JavaScript mogelijk te maken, moet je de assets/js en js_class parameters van manifest.json bijwerken, zoals getoond in de volgende stap.

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. Open manifest.json en voeg toe:
  • de bestandsnaam (class.widget.js) aan de array in de assets/js sectie;
  • de klassenaam (WidgetLessonGaugeChart) aan de js_class parameter in de widget sectie.

De WidgetLessonGaugeChart klasse wordt nu automatisch geladen met het 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": ["class.widget.js"]
           }
       }

Voeg CSS-stijlen toe aan de widget

In dit gedeelte leer je hoe je aangepaste CSS-stijlen kunt toevoegen om de widget er aantrekkelijker uit te laten zien.

  1. Maak voor widget-stijlen een nieuwe map genaamd css aan in de assets directory.

  2. Maak een bestand genaamd widget.css in de assets/css directory. Gebruik de selector div.dashboard-widget-{widget id} om elementen van de widget te stylen. Gebruik de selector form.dashboard-widget-{widget id} om CSS voor de hele widget te configureren.

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 en voeg de naam van het CSS-bestand (widget.css) toe aan de array in de assets/css sectie. Hierdoor worden de in widget.css gedefinieerde CSS-stijlen geladen op de dashboardpagina.

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. Vernieuw de dashboardpagina om de voltooide versie van de widget te zien.