Erstellen eines Widgets (Tutorial)

Dies ist ein Schritt-für-Schritt Tutorial, welches dir zeigt, wie man ein einfaches Zabbix-Frontend-Modul erstellt. Sie können alle Dateien dieses Moduls als ZIP-Archiv herunterladen: MyAddress.zip.

Was Sie erstellen werden

In diesem Tutorial erstellen Sie zunächst ein einfaches „Hello, world!“-Widget und wandeln es anschließend in ein fortgeschritteneres Widget um, das einen Datenpunktwert als Tachodiagramm anzeigt. So wird das fertige Widget aussehen:

Teil I – "Hallo Welt!“

In diesem Abschnitt erfahren Sie, wie Sie die minimal erforderlichen Widget-Elemente erstellen und ein neues Widget zum Zabbix-Frontend hinzufügen.

Ein leeres Widget zum Zabbix Frontend hinzufügen

  1. Erstellen Sie ein Verzeichnis lesson_gauge_chart im Verzeichnis modules Ihrer Zabbix Frontend-Installation (zum Beispiel zabbix/ui/modules).

Alle benutzerdefinierten Widgets werden als externe Module behandelt und müssen dem Verzeichnis modules Ihrer Zabbix Frontend-Installation hinzugefügt werden (zum Beispiel zabbix/ui/modules). Das Verzeichnis zabbix/ui/widgets ist für die integrierten Zabbix-Widgets reserviert und wird zusammen mit der Zabbix-UI aktualisiert.

  1. Erstellen Sie eine Datei manifest.json mit den grundlegenden Widget-Metadaten (siehe die Beschreibung der unterstützten Parameter).

ui/modules/lesson_gauge_chart/manifest.json

{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.1",
    "author": "Zabbix"
}
  1. Gehen Sie im Zabbix Frontend zum Abschnitt Administration → Allgemein → Module und klicken Sie auf die Schaltfläche Verzeichnis scannen.

  1. Suchen Sie in der Liste nach dem neuen Modul Gauge chart und klicken Sie auf den Hyperlink "Disabled", um den Status des Moduls von "Disabled" auf "Enabled" zu ändern (falls das Modul nicht aufgeführt ist, siehe Abschnitt Fehlerbehebung).

  1. Öffnen Sie ein Dashboard, wechseln Sie in den Bearbeitungsmodus und fügen Sie ein neues Widget hinzu. Wählen Sie im Feld Type "Gauge chart" aus.

  1. Zu diesem Zeitpunkt enthält die Konfiguration des Widgets Gauge chart nur die allgemeinen Widget-Felder Name und Aktualisierungsintervall. Klicken Sie auf Add, um das Widget zum Dashboard hinzuzufügen.

  1. Ein leeres Widget sollte auf dem Dashboard erscheinen. Klicken Sie oben rechts auf Änderungen speichern, um das Dashboard zu speichern.

Eine widget-Ansicht hinzufügen

Die Ansichts-Datei des Widgets sollte sich im Verzeichnis views befinden (für dieses Tutorial: ui/modules/lesson_gauge_chart/views/). Wenn die Datei den Standardnamen widget.view.php hat, müssen Sie sie nicht in der Datei manifest.json registrieren. Wenn die Datei einen anderen Namen hat, geben Sie ihn im Abschnitt actions/widget.lesson_gauge_chart.view der Datei manifest.json an.

  1. Erstellen Sie im Verzeichnis lesson_gauge_chart ein Verzeichnis views.

  2. Erstellen Sie im Verzeichnis views eine Datei widget.view.php.

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

<?php

/**
 * Gauge-chart-widget-Ansicht.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem(
        new CTag('h1', true, 'Hello, world!')
    )
    ->show();
  1. Aktualisieren Sie das Dashboard. Das Widget Gauge chart zeigt jetzt „Hello, world!“ an.

Teil II – Gauge Chart (Messgerätetabelle)

Einstellungen zu einer Konfigurationsansicht hinzufügen und in einer Widget-Ansicht verwenden

In diesem Abschnitt erfahren Sie, wie Sie ein Widget-Konfigurationsfeld hinzufügen und den eingegebenen Wert in der Widget-Ansicht als Text anzeigen.

Die Widget-Konfiguration besteht aus einem Formular (Zabbix\Widgets\CWidgetForm) und einer Widget-Formularansicht (widget.edit.php). Um Felder (Zabbix\Widgets\CWidgetField) hinzuzufügen, müssen Sie eine WidgetForm-Klasse erstellen, die von Zabbix\Widgets\CWidgetForm erbt.

Das Formular enthält eine Reihe von Feldern (Zabbix\Widgets\CWidgetField) verschiedener Typen, die zur Validierung der vom Benutzer eingegebenen Werte verwendet werden. Das Formularfeld (Zabbix\Widgets\CWidgetField) für jeden Eingabeelementtyp konvertiert den Wert in ein einheitliches Format, um ihn in der Datenbank zu speichern.

Die Formular-Datei des Widgets sollte sich im Verzeichnis includes befinden (für dieses Tutorial: ui/modules/lesson_gauge_chart/includes/). Wenn die Datei den Standardnamen WidgetForm.php hat, müssen Sie sie nicht in der Datei manifest.json registrieren. Wenn die Datei einen anderen Namen hat, geben Sie sie im Abschnitt widget/form_class der Datei manifest.json an.

  1. Erstellen Sie im Verzeichnis lesson_gauge_chart ein neues Verzeichnis includes.

  2. Erstellen Sie im Verzeichnis includes eine Datei WidgetForm.php.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

class WidgetForm extends CWidgetForm {
}
  1. Fügen Sie dem Widget-Konfigurationsformular ein Feld Description hinzu. Dies ist ein normales Textfeld, in das ein Benutzer beliebige Zeichen eingeben kann. Dafür können Sie die Klasse CWidgetFieldTextBox verwenden.

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', _('Description'))
            );
   }
}
  1. Erstellen Sie im Verzeichnis views eine Widget-Konfigurationsansichtsdatei widget.edit.php und fügen Sie eine Ansicht für das neue Feld Description hinzu. Für die Feldklasse CWidgetFieldTextBox lautet die Ansicht CWidgetFieldTextBoxView.

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 CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
  1. Gehen Sie zum Dashboard und klicken Sie im Widget auf das Zahnradsymbol, um das Widget-Konfigurationsformular zu öffnen.

  2. Das Widget-Konfigurationsformular enthält nun ein neues Textfeld Description. Geben Sie einen beliebigen Wert ein, zum Beispiel Gauge chart description.

  1. Klicken Sie im Widget-Konfigurationsformular auf Apply. Klicken Sie anschließend oben rechts auf Save changes, um das Dashboard zu speichern. Beachten Sie, dass die neue Beschreibung nirgendwo sichtbar ist und das Widget weiterhin "Hello, world!" anzeigt.

Damit die neue Beschreibung im Widget angezeigt wird, muss der Wert des Felds Description aus der Datenbank abgerufen und an die Widget-Ansicht übergeben werden. Dazu müssen Sie eine Aktionsklasse erstellen.

  1. Erstellen Sie im Verzeichnis lesson_gauge_chart ein neues Verzeichnis actions.

  2. Erstellen Sie im Verzeichnis actions eine Datei WidgetView.php. Die Aktionsklasse WidgetView erbt von der Klasse CControllerDashboardWidgetView.

Die Werte der Widget-Konfigurationsfelder werden in der Eigenschaft $fields_values der Aktionsklasse gespeichert.

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. Öffnen Sie manifest.json und registrieren Sie WidgetView als Aktionsklasse im Abschnitt actions/widget.lesson_gauge_chart.view.

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",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    }
}
  1. Jetzt können Sie den Wert des Felds description, der in $data['description'] enthalten ist, in der Widget-Ansicht verwenden. Öffnen Sie views/widget.view.php und ersetzen Sie den statischen Text "Hello, world!" durch $data['description'].

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'])
    )
    ->show();
  1. Aktualisieren Sie die Dashboard-Seite. Sie sollten nun den Beschreibungstext des Widgets anstelle von "Hello, world!" sehen.

Einen Datenpunktwert über die API abrufen

Das Widget sollte den letzten Wert eines Datenpunkts nach Wahl des Benutzers anzeigen. Dafür müssen Sie die Möglichkeit hinzufügen, Datenpunkte in der Widget-Konfiguration auszuwählen.

In diesem Abschnitt erfahren Sie, wie Sie dem Widget-Formular ein Feld zur Auswahl eines Datenpunkts hinzufügen und wie Sie den visuellen Teil dieses Feldes in der Konfigurationsansicht ergänzen. Anschließend kann der Widget-Controller die Datenpunktdaten und deren Wert über eine API-Anfrage abrufen. Sobald der Wert empfangen wurde, kann er in der Widget-Ansicht angezeigt werden.

  1. Öffnen Sie includes/WidgetForm.php und fügen Sie das Feld CWidgetFieldMultiSelectItem hinzu. Dies ermöglicht die Auswahl eines Datenpunkts im Konfigurationsformular.

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', _('Datenpunkt')))
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                    ->setMultiple(false)
            )
            ->addField(
                new CWidgetFieldTextBox('description', _('Description'))
            );
    }
}
  1. Öffnen Sie views/widget.edit.php und fügen Sie die visuelle Komponente des Feldes zur Konfigurationsansicht hinzu.

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'])
    )
    ->addField(
        new CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
  1. Kehren Sie zum Dashboard zurück und klicken Sie auf das Zahnradsymbol im Widget, um das Konfigurationsformular zu öffnen.

  2. Das Widget-Konfigurationsformular enthält nun ein neues Eingabefeld Datenpunkt. Wählen Sie den Host "Zabbix server" und den Datenpunkt "Load average (1m avg)" aus.

  1. Klicken Sie im Widget-Konfigurationsformular auf Apply. Klicken Sie anschließend oben rechts auf Save changes, um das Dashboard zu speichern.

  2. Öffnen und ändern Sie actions/WidgetView.php.

Ab jetzt ist die Datenpunkt-ID im Widget-Controller in $this->fields_values['itemid'] verfügbar. Die Controller-Methode doAction() ermittelt die Datenpunktdaten (Name, Wertetyp, Einheiten) mithilfe der API-Methode item.get und den letzten Datenpunktwert mithilfe der 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. Öffnen Sie views/widget.view.php und fügen Sie den Datenpunktwert zur Widget-Ansicht hinzu.

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. Aktualisieren Sie die Dashboard-Seite. Das Widget zeigt den neuesten Datenpunktwert an.

Erweiterte Konfigurationseinstellungen zu einer Konfigurationsansicht hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie einen ein- und ausklappbaren Abschnitt Erweiterte Konfiguration mit optionalen Parametern hinzufügen, z. B. Farbe, Mindest- und Höchstwerte, Einheiten und das zuvor erstellte Feld Description.

  1. Erstellen Sie im Hauptverzeichnis des Widgets lesson_gauge_chart eine Datei Widget.php, um eine neue Klasse Widget zu erstellen.

Die Klasse Widget erweitert die Basisklasse CWidget, um die Standard-Widget-Einstellungen zu ergänzen bzw. zu überschreiben (in diesem Fall - Übersetzungen). Das unten bereitgestellte JavaScript zeigt die Zeichenfolge "No data" an, wenn keine Daten vorhanden sind. Die Zeichenfolge "No data" ist in den Zabbix-UI-Übersetzungsdateien enthalten.

Wenn es Widget-Konstanten gibt, wird empfohlen, diese ebenfalls in der Klasse Widget anzugeben.

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. Öffnen Sie includes/WidgetForm.php und fügen Sie die neuen Felder Color (Farbwähler), Min (numerisches Feld), Max (numerisches Feld) und Units (Auswahl) hinzu, und definieren Sie die Standard-Farbpalette für den Farbwähler, damit sie in den nächsten Schritten verwendet werden kann.

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. Öffnen Sie views/widget.edit.php und fügen Sie die visuellen Feldkomponenten zur Konfigurationsansicht hinzu.

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();

Die Methode addField() der Klasse CWidgetFormView nimmt als zweites Parameter eine CSS-Klassenzeichenfolge entgegen.

  1. Kehren Sie zum Dashboard zurück, wechseln Sie in den Bearbeitungsmodus und klicken Sie auf das Zahnradsymbol im Widget, um das Widget-Konfigurationsformular zu öffnen. Das Widget-Konfigurationsformular enthält nun einen neuen ein- und ausklappbaren Abschnitt Erweiterte Konfiguration.

  1. Erweitern Sie den Abschnitt Erweiterte Konfiguration, um zusätzliche Widget-Konfigurationsfelder anzuzeigen. Beachten Sie, dass das Feld Color noch keinen Farbwähler hat. Dies liegt daran, dass der Farbwähler mit JavaScript initialisiert werden muss, das im nächsten Abschnitt hinzugefügt wird - JavaScript zum Widget hinzufügen.

JavaScript zum Widget hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie ein Gauge-Diagramm hinzufügen - erstellt mit JavaScript -, das anzeigt, ob der letzte Wert normal oder zu hoch/zu niedrig ist.

  1. Erstellen Sie eine Datei widget.edit.js.php im Verzeichnis views.

JavaScript ist für die Initialisierung des Farbwählers in der Konfigurationsansicht zuständig.

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._unit_select = document.getElementById('value_units');
        this._unit_value = document.getElementById('value_static_units');

        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() {
        this._unit_value.disabled = this._unit_select.value == <?= Widget::UNIT_AUTO ?>;
    }
};
  1. Öffnen Sie views/widget.edit.php und fügen Sie die Datei widget.edit.js.php mit dem JavaScript zur Konfigurationsansicht hinzu. Verwenden Sie dazu die Methode includeJsFile(). Um inline-JavaScript hinzuzufügen, verwenden Sie die Methode addJavaScript().

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

<?php

/**
 * Gauge chart widget form view.
 *
 * @var CView $this
 * @var array $data
 */

use Modules\LessonGaugeChart\Includes\WidgetForm;

$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'])
            )
    )
    ->includeJsFile('widget.edit.js.php')
    ->addJavaScript('widget_lesson_gauge_chart_form.init('.json_encode([
        'color_palette' => WidgetForm::DEFAULT_COLOR_PALETTE
    ], JSON_THROW_ON_ERROR).');')
    ->show();
  1. Kehren Sie zum Dashboard zurück und klicken Sie im Widget auf das Zahnradsymbol, um das Konfigurationsformular des Widgets zu öffnen. Erweitern Sie nun den Abschnitt Advanced configuration, um den initialisierten Farbwähler zu sehen. Füllen Sie die Felder mit Werten aus und wählen Sie eine Farbe für das Gauge-Diagramm aus.

  1. Klicken Sie im Konfigurationsformular des Widgets auf Apply. Klicken Sie anschließend oben rechts auf Save changes, um das Dashboard zu speichern.

  2. Öffnen Sie actions/WidgetView.php und aktualisieren Sie den Controller.

Die Eigenschaft $this->fields_values enthält jetzt die Werte aller Felder der Advanced configuration. Vervollständigen Sie den Controller, damit die Konfiguration und der ausgewählte Item-Wert an die Widget-Ansicht übergeben werden können.

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. Öffnen und ändern Sie views/widget.view.php.

Sie müssen einen Container für das Gauge-Diagramm erstellen, das Sie in den nächsten Schritten zeichnen, sowie einen Container für die Beschreibung.

Um Werte als JSON-Objekt an JavaScript zu übergeben, verwenden Sie die Methode 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. Erstellen Sie im Verzeichnis lesson_gauge_chart ein neues Verzeichnis assets. Dieses Verzeichnis wird zum Speichern von JavaScript, CSS und möglicherweise weiteren Ressourcen wie Schriftarten oder Bildern verwendet.

  2. Erstellen Sie für das JavaScript der Widget-Ansicht im Verzeichnis assets ein Verzeichnis js.

  3. Erstellen Sie im Verzeichnis assets/js eine Datei class.widget.js.

Diese JavaScript-Widget-Klasse erweitert die grundlegende JavaScript-Klasse aller Dashboard-Widgets - CWidget.

Das Dashboard ist auf eine korrekte Implementierung eines Widgets angewiesen und kommuniziert alle relevanten Informationen an das Widget, indem die entsprechenden JavaScript-Methoden aufgerufen werden. Außerdem erwartet das Dashboard, dass das Widget Ereignisse erzeugt, wenn eine Interaktion stattfindet. Daher enthält die Klasse CWidget eine Reihe von Methoden mit der Standardimplementierung des Widget-Verhaltens, die durch Vererbung der Klasse angepasst werden können.

In diesem Fall ist eine gewisse Anpassung erforderlich, daher wird benutzerdefinierte Logik für das folgende Widget-Verhalten implementiert:

  • Initialisierung des Widgets, die für die Definition des Anfangszustands des Widgets verantwortlich ist (siehe die Methode onInitialize());
  • Anzeige des Widget-Inhalts (also das Zeichnen des Gauge-Diagramms), wenn der Aktualisierungsvorgang des Widgets erfolgreich und ohne Fehler abgeschlossen wurde (siehe die Methode processUpdateResponse(response) und die zugehörigen Methoden _resizeChart() und _updatedChart())
  • Größenänderung des Widgets (siehe die Methode onResize() und die zugehörige Methode _resizeChart())

Für andere Aspekte des Gauge-Diagramm-Widgets wird die Standardimplementierung des Widget-Verhaltens verwendet. Weitere Informationen zu den JavaScript-Methoden der Klasse CWidget finden Sie unter: JavaScript.

Da dieses JavaScript für die Widget-Ansicht erforderlich ist, sollte es mit der Dashboard-Seite geladen werden. Um das Laden von JavaScript zu aktivieren, müssen Sie die Parameter assets/js und js_class in der Datei manifest.json wie in Schritt 10 gezeigt aktualisieren.

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

class WidgetLessonGaugeChart extends CWidget {

    static UNIT_AUTO = 0;
    static UNIT_STATIC = 1;

    onInitialize() {
        super.onInitialize();

        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);

        super.processUpdateResponse(response);
    }

    setContents(response) {
        if (this._canvas === null) {
            super.setContents(response);

            this._chart_container = this._body.querySelector('.chart');
            this._chart_container.style.height =
                `${this._getContentsSize().height - this._body.querySelector('.description').clientHeight}px`;
            this._canvas = document.createElement('canvas');

            this._chart_container.appendChild(this._canvas);

            this._resizeChart();
        }

        this._updatedChart();
    }

    onResize() {
        super.onResize();

        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. Öffnen Sie manifest.json und fügen Sie hinzu:
  • den Dateinamen (class.widget.js) zum Array im Abschnitt assets/js;
  • den Klassennamen (WidgetLessonGaugeChart) zum Parameter js_class im Abschnitt widget.

Die Klasse WidgetLessonGaugeChart wird nun automatisch mit dem Dashboard geladen.

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",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "js": ["class.widget.js"]
    }
}

CSS-Stile zum Widget hinzufügen

In diesem Abschnitt erfahren Sie, wie Sie benutzerdefinierte CSS-Stile hinzufügen können, um das Widget ansprechender zu gestalten.

  1. Für Widget-Stile erstellen Sie ein neues Verzeichnis css im Verzeichnis assets..

  2. Erstellen Sie eine Datei widget.css im Verzeichnis assets/css. Zur Gestaltung von Widget-Elementen verwenden Sie den Selektor div.dashboard-widget-{widget id}. Um CSS für das gesamte Widget zu konfigurieren, verwenden Sie den Selektor 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. Öffnen Sie manifest.json und fügen Sie den Namen der CSS-Datei (widget.css) in das Array im Abschnitt assets/css ein. Dadurch können die in widget.css definierten CSS-Stile mit der Dashboard-Seite geladen werden.

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",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "css": ["widget.css"],
        "js": ["class.widget.js"]
    }
}
  1. Aktualisieren Sie die Dashboard-Seite, um die fertige Version des Widgets zu sehen.