Crea un widget (tutorial)

Questo è un tutorial passo passo che mostra come creare un semplice widget per la dashboard. Puoi scaricare tutti i file di questo widget in un archivio ZIP: lesson_gauge_chart.zip.

Cosa realizzerai

Durante questo tutorial, prima creerai un widget base "Hello, world!" e poi lo convertirai in un widget più avanzato che visualizza il valore di un elemento come un grafico a indicatori. Ecco come apparirà il widget finito:

Parte I - "Hello, world!"

In questa sezione imparerai come creare gli elementi widget minimi richiesti e aggiungere un nuovo widget al frontend di Zabbix.

Aggiungere un widget vuoto al frontend di Zabbix

  1. Creare una directory lesson_gauge_chart nella directory modules dell'installazione del frontend di Zabbix (ad esempio, zabbix/ui/modules).

Tutti i widget personalizzati sono trattati come moduli esterni e devono essere aggiunti alla directory modules dell'installazione del frontend di Zabbix (ad esempio, zabbix/ui/modules). La directory zabbix/ui/widgets è riservata ai widget integrati di Zabbix e viene aggiornata insieme alla UI di Zabbix.

  1. Creare un file manifest.json con i metadati di base del widget (vedere la descrizione dei parametri supportati).

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. Nel frontend di Zabbix, andare alla sezione Administration → General → Modules e fare clic sul pulsante Scan directory.

  1. Individuare il nuovo modulo Gauge chart nell'elenco e fare clic sul collegamento ipertestuale "Disabled" per cambiare lo stato del modulo da "Disabled" a "Enabled" (se il modulo non è elencato, vedere la sezione troubleshooting).

  1. Aprire una dashboard, passare alla modalità di modifica e aggiungere un nuovo widget. Nel campo Type, selezionare "Gauge chart".

  1. A questo punto, la configurazione del widget Gauge chart contiene solo i campi comuni del widget Name e Refresh interval. Fare clic su Add per aggiungere il widget alla dashboard.

  1. Sulla dashboard dovrebbe apparire un widget vuoto. Fare clic su Save changes nell'angolo superiore destro per salvare la dashboard.

Aggiungere una vista del widget

Il file view del widget deve trovarsi nella directory views (per questo tutorial, ui/modules/lesson_gauge_chart/views/). Se il file ha il nome predefinito widget.view.php, non è necessario registrarlo nel file manifest.json. Se il file ha un nome diverso, specificarlo nella sezione actions/widget.lesson_gauge_chart.view del file manifest.json.

  1. Creare una directory views nella directory lesson_gauge_chart.

  2. Creare un file widget.view.php nella directory views.

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, 'Hello, world!')
    )
    ->show();
  1. Aggiornare la dashboard. Il widget Gauge chart ora visualizza "Hello, world!".

Parte II - Grafico degli indicatori

Aggiungere impostazioni a una vista di configurazione e usarle in una vista widget

In questa sezione, imparerai come aggiungere un campo di configurazione del widget e mostrare il valore inserito nella vista del widget come testo.

La configurazione del widget è composta da un modulo (Zabbix\Widgets\CWidgetForm) e da una vista del modulo del widget (widget.edit.php). Per aggiungere campi (Zabbix\Widgets\CWidgetField), è necessario creare una classe WidgetForm, che estenderà Zabbix\Widgets\CWidgetForm.

Il modulo contiene un insieme di campi (Zabbix\Widgets\CWidgetField) di vari tipi, utilizzati per convalidare i valori immessi dall'utente. Il campo del modulo (Zabbix\Widgets\CWidgetField) per ciascun tipo di elemento di input converte il valore in un unico formato per memorizzarlo nel database.

Il file form del widget deve trovarsi nella directory includes (per questo tutorial, ui/modules/lesson_gauge_chart/includes/). Se il file ha il nome predefinito WidgetForm.php, non è necessario registrarlo nel file manifest.json. Se il file ha un nome diverso, specificarlo nella sezione widget/form_class del file manifest.json.

  1. Crea una nuova directory includes nella directory lesson_gauge_chart.

  2. Crea un file WidgetForm.php nella directory includes.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

class WidgetForm extends CWidgetForm {
}
  1. Aggiungi un campo Description al modulo di configurazione del widget. Si tratta di un normale campo di testo, in cui un utente può inserire qualsiasi set di caratteri. Per questo puoi usare la classe CWidgetFieldTextBox.

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. Nella directory views, crea un file di vista della configurazione del widget widget.edit.php e aggiungi una vista per il nuovo campo Description. Per la classe di campo CWidgetFieldTextBox, la vista è 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. Vai alla dashboard e fai clic sull'icona dell'ingranaggio nel widget per aprire il modulo di configurazione del widget.

  2. Il modulo di configurazione del widget ora contiene un nuovo campo di testo Description. Inserisci un valore qualsiasi, ad esempio Gauge chart description.

  1. Fai clic su Apply nel modulo di configurazione del widget. Quindi fai clic su Save changes nell'angolo superiore destro per salvare la dashboard. Nota che la nuova descrizione non è visibile da nessuna parte e il widget continua a visualizzare "Hello, world!".

Per fare in modo che la nuova descrizione appaia nel widget, il valore del campo Description deve essere recuperato dal database e passato alla vista del widget. Per farlo, è necessario creare una classe action.

  1. Crea una nuova directory actions nella directory lesson_gauge_chart.

  2. Crea un file WidgetView.php nella directory actions. La classe action WidgetView estenderà la classe CControllerDashboardWidgetView.

I valori dei campi di configurazione del widget sono memorizzati nella proprietà $fields_values della classe 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. Apri manifest.json e registra WidgetView come classe action nella sezione 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. Ora puoi usare il valore del campo description, contenuto in $data['description'], nella vista del widget. Apri views/widget.view.php e sostituisci il testo statico "Hello, world!" con $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. Aggiorna la pagina della dashboard. Ora dovresti vedere il testo della descrizione del widget al posto di "Hello, world!".

Recuperare un valore di item tramite API

Il widget deve mostrare l’ultimo valore di un item scelto dall’utente. Per farlo, è necessario aggiungere la possibilità di selezionare gli item nella configurazione del widget.

In questa sezione, imparerai come aggiungere un campo di selezione item al modulo del widget e come aggiungere la parte visiva di questo campo alla vista di configurazione. Successivamente, il controller del widget sarà in grado di recuperare i dati dell’item e il relativo valore tramite una richiesta API. Una volta ricevuto, il valore potrà essere visualizzato nella vista del widget.

  1. Apri includes/WidgetForm.php e aggiungi il campo CWidgetFieldMultiSelectItem. Questo consentirà di selezionare un item nel modulo di configurazione.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\{
    CWidgetField,
    CWidgetForm
};

use Zabbix\Widgets\Fields\{
    CWidgetFieldMultiSelectItem,
    CWidgetFieldTextBox
};

/**
 * Modulo del widget Gauge chart.
 */
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. Apri views/widget.edit.php e aggiungi il componente visivo del campo alla vista di configurazione.

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

<?php

/**
 * Vista del modulo del widget Gauge chart.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetFormView($data))
    ->addField(
        new CWidgetFieldMultiSelectItemView($data['fields']['itemid'])
    )
    ->addField(
        new CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
  1. Torna alla dashboard e fai clic sull’icona dell’ingranaggio nel widget per aprire il modulo di configurazione del widget.

  2. Il modulo di configurazione del widget ora contiene un nuovo campo di input Item. Seleziona l’host "Zabbix server" e l’item "Load average (1m avg)".

  1. Fai clic su Apply nel modulo di configurazione del widget. Quindi fai clic su Save changes nell’angolo in alto a destra per salvare la dashboard.

  2. Apri e modifica actions/WidgetView.php.

Da questo momento in poi, l’ID dell’item sarà disponibile nel controller del widget in $this->fields_values['itemid']. Il metodo del controller doAction() raccoglie i dati dell’item (nome, tipo di valore, unità) usando il metodo API item.get e l’ultimo valore dell’item usando il metodo 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. Apri views/widget.view.php e aggiungi il valore dell’item alla vista del widget.

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

<?php

/**
 * Vista del widget Gauge chart.
 *
 * @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. Aggiorna la pagina della dashboard. Il widget visualizzerà l’ultimo valore dell’item.

Aggiungere impostazioni di configurazione avanzate a una vista di configurazione

In questa sezione, imparerai come aggiungere una sezione Configurazione avanzata espandibile/comprimibile con parametri opzionali, come colore, valori minimo e massimo, unità e il campo Descrizione creato in precedenza.

  1. Crea un file Widget.php nella directory principale del widget lesson_gauge_chart per creare una nuova classe Widget.

La classe Widget estenderà la classe base CWidget per aggiungere/sovrascrivere le impostazioni predefinite del widget (in questo caso - le traduzioni). JavaScript, fornito di seguito, visualizza la stringa "No data" in caso di dati mancanti. La stringa "No data" è presente nei file di traduzione della UI di Zabbix.

Se sono presenti costanti del widget, si consiglia di specificarle anch'esse nella 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. Apri includes/WidgetForm.php e aggiungi i nuovi campi Color (selettore colore), Min (campo numerico), Max (campo numerico) e Units (selezione), e definisci la tavolozza di colori predefinita per il selettore colore, in modo che possa essere utilizzata nei passaggi successivi.

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. Apri views/widget.edit.php e aggiungi i componenti visivi dei campi alla vista di configurazione.

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

Il metodo addField() della classe CWidgetFormView accetta una stringa di classe CSS come secondo parametro.

  1. Torna alla dashboard, passa alla modalità di modifica e fai clic sull'icona dell'ingranaggio nel widget per aprire il modulo di configurazione del widget. Il modulo di configurazione del widget ora contiene una nuova sezione espandibile/comprimibile Configurazione avanzata.

  1. Espandi la sezione Configurazione avanzata per visualizzare ulteriori campi di configurazione del widget. Nota che il campo Color non ha ancora un selettore colore. Questo perché il selettore colore deve essere inizializzato con JavaScript, che verrà aggiunto nella sezione successiva - Aggiungere JavaScript al widget.

Aggiungere JavaScript al widget

In questa sezione imparerai come aggiungere un grafico gauge, realizzato con JavaScript, che mostra se l’ultimo valore è normale oppure troppo alto/troppo basso.

  1. Crea un file widget.edit.js.php nella directory views.

JavaScript sarà responsabile dell’inizializzazione del selettore di colore nella vista di configurazione.

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. Apri views/widget.edit.php e aggiungi il file widget.edit.js.php con il JavaScript alla vista di configurazione. Per farlo, usa il metodo includeJsFile(). Per aggiungere JavaScript inline, usa il metodo 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. Torna alla dashboard, fai clic sull’icona dell’ingranaggio nel widget per aprire il modulo di configurazione del widget. Ora espandi la sezione Advanced configuration per vedere il selettore di colore inizializzato. Compila i campi con i valori e seleziona un colore per il grafico gauge.

  1. Fai clic su Apply nel modulo di configurazione del widget. Quindi fai clic su Save changes nell’angolo in alto a destra per salvare la dashboard.

  2. Apri actions/WidgetView.php e aggiorna il controller.

La proprietà $this->fields_values ora contiene i valori di tutti i campi di Advanced configuration. Completa il controller per consentire il passaggio della configurazione e del valore dell’item selezionato alla vista del 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. Apri e modifica views/widget.view.php.

Devi creare un contenitore per il grafico gauge, che disegnerai nei passaggi successivi, e un contenitore per la descrizione.

Per passare valori a JavaScript come oggetto JSON, usa il metodo 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. Crea una nuova directory assets nella directory lesson_gauge_chart. Questa directory verrà usata per archiviare JavaScript, CSS e potenzialmente qualsiasi altra risorsa, come font o immagini.

  2. Per il JavaScript della vista del widget, crea una directory js nella directory assets.

  3. Crea un file class.widget.js nella directory assets/js.

Questa classe JavaScript del widget estenderà la classe JavaScript di base di tutti i widget della dashboard, CWidget.

La dashboard si basa su una corretta implementazione di un widget e comunica al widget tutte le informazioni rilevanti chiamando i rispettivi metodi JavaScript. La dashboard si aspetta inoltre che il widget generi eventi quando si verifica qualche interazione. Per questo motivo, la classe CWidget contiene un insieme di metodi con l’implementazione predefinita del comportamento del widget, che può essere personalizzata estendendo la classe.

In questo caso è necessaria una certa personalizzazione, pertanto verrà implementata una logica personalizzata per il seguente comportamento del widget:

  • inizializzazione del widget, responsabile della definizione dello stato iniziale del widget (vedi il metodo onInitialize());
  • visualizzazione del contenuto del widget (cioè il disegno del grafico gauge) se il processo di aggiornamento del widget è andato a buon fine e senza errori (vedi il metodo processUpdateResponse(response) e i relativi metodi _resizeChart() e _updatedChart())
  • ridimensionamento del widget (vedi il metodo onResize() e il relativo metodo _resizeChart())

Per gli altri aspetti del widget del grafico gauge verrà usata l’implementazione predefinita del comportamento del widget. Per saperne di più sui metodi JavaScript della classe CWidget, vedi: JavaScript.

Poiché questo JavaScript è richiesto per la vista del widget, deve essere caricato con la pagina della dashboard. Per abilitare il caricamento di JavaScript, dovrai aggiornare i parametri assets/js e js_class nel file manifest.json come mostrato nel passaggio 10.

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. Apri manifest.json e aggiungi:
  • il nome del file (class.widget.js) all’array nella sezione assets/js;
  • il nome della classe (WidgetLessonGaugeChart) al parametro js_class nella sezione widget.

La classe WidgetLessonGaugeChart verrà ora caricata automaticamente con la 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",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "js": ["class.widget.js"]
    }
}

Aggiungere stili CSS al widget

In questa sezione imparerai come aggiungere stili CSS personalizzati per rendere il widget più accattivante.

  1. Per gli stili del widget, crea una nuova directory css nella directory assets.

  2. Crea un file widget.css nella directory assets/css. Per applicare lo stile agli elementi del widget, usa il selettore div.dashboard-widget-{widget id}. Per configurare il CSS per l'intero widget, usa il selettore 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. Apri manifest.json e aggiungi il nome del file CSS (widget.css) all'array nella sezione assets/css. Questo consentirà agli stili CSS definiti in widget.css di essere caricati con la pagina della 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",
    "actions": {
        "widget.lesson_gauge_chart.view": {
            "class": "WidgetView"
        }
    },
    "widget": {
        "js_class": "WidgetLessonGaugeChart"
    },
    "assets": {
        "css": ["widget.css"],
        "js": ["class.widget.js"]
    }
}
  1. Aggiorna la pagina della dashboard per vedere la versione finale del widget.