Crie um widget (tutorial)

Este é um tutorial passo a passo que mostra como criar um widget de dashboard simples.

A versão mínima exigida do Zabbix para este tutorial é a 6.4.4.

Você pode baixar todos os arquivos desse widget como um arquivo ZIP: lesson_gauge_chart.zip.

O que você criará

Durante este tutorial, você primeiro criará um widget basic "Hello, world!" e, em seguida, o converterá em um widget more advanced que exibe o valor de um item como um gráfico de indicador. Veja a seguir a aparência do widget finalizado:

Parte I - "Hello, world!"

Nesta seção, você aprenderá a criar os elementos mínimos necessários do widget e a adicionar um novo widget ao front-end do Zabbix.

Adicionar um widget em branco ao frontend do Zabbix

  1. Crie um diretório lesson_gauge_chart em zabbix/ui/modules.

Todos os widgets personalizados são tratados como módulos externos e devem ser adicionados ao diretório modules do seu Zabbix frontend (por exemplo, zabbix/ui/modules). O diretório zabbix/ui/widgets é reservado para os widgets internos do Zabbix e é atualizado junto com a interface do usuário do Zabbix.

  1. Crie um arquivo manifest.json com os metadados básicos do widget (consulte a descrição dos parameters).

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Gauge chart",
           "namespace": "LessonGaugeChart",
           "versão": "1.0",
           "autor": "Zabbix SIA"
       }
  1. No front-end do Zabbix, vá para a seção Administration → General → Modules e clique no botão Scan directory.

  1. Localize o novo módulo Gauge chart na lista e clique no hiperlink "Disabled" (Desativado) para alterar o status do módulo de "Disabled" (Desativado) para "Enabled" (Ativado).

  1. Abra um painel, passe-o para o modo de edição e adicione um novo widget. No campo Type, selecione "Gauge chart".

  1. Neste ponto, a configuração do widget Gauge chart contém apenas os campos comuns do widget Name e Refresh interval. Clique em Add para adicionar o widget ao painel.

  1. Um widget em branco deve aparecer no painel. Clique em Save changes no canto superior direito para salvar o painel.

Adicionar uma visualização de widget

O arquivo view do widget deve estar localizado no diretório views (para este tutorial, ui/modules/lesson_gauge_chart/views/). Se o arquivo tiver o nome padrão widget.view.php, não será necessário registrá-lo no arquivo manifest.json. Se o arquivo tiver um nome diferente, especifique-o na seção actions/widget.lesson_gauge_chart.view do arquivo [manifest.json] (devel/modules/file_structure/manifest).

  1. Crie um diretório views no diretório lesson_gauge_chart.

  2. Crie um arquivo widget.view.php no diretório views.

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

<?php
       
       /**
        * Visualização do widget do gráfico de medidores.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
           ->addItem(
               new CTag('h1', true, 'Hello, world!')
           )
           ->show();
  1. Atualize o dashboard. O widget Gauge chart agora exibe "Hello, world!".

Parte II - Gráfico de medidores

Adicionar configurações a uma visualização de configuração e usá-las em uma visualização de widget

Nesta seção, você aprenderá a adicionar um campo de configuração de widget e a mostrar o valor inserido na visualização do widget como texto.

A configuração do widget consiste em um formulário (Zabbix\Widgets\CWidgetForm) e uma visualização de formulário de widget (widget.edit.php). Para adicionar campos (Zabbix\Widgets\), você precisa criar uma classe WidgetForm, que estenderá Zabbix\Widgets\CWidgetForm*.

O formulário contém o conjunto de campos (Zabbix\Widgets\CWidgetField) de vários tipos, que são usados para validar os valores inseridos pelo usuário. O campo do formulário (*Zabbix\Widgets\) para cada tipo de elemento de entrada converte o valor em um único formato para armazená-lo no banco de dados.

O arquivo form do widget deve estar localizado no diretório includes (para este tutorial, ui/modules/lesson_gauge_chart/includes/). Se o arquivo tiver o nome padrão WidgetForm.php, não será necessário registrá-lo no arquivo manifest.json. Se o arquivo tiver um nome diferente, especifique-o na seção widget/form_class do arquivo [manifest.json] (devel/modules/file_structure/manifest).

  1. Crie um novo diretório includes no diretório lesson_gauge_chart.

  2. Crie um arquivo WidgetForm.php no diretório includes.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Zabbix\Widgets\CWidgetForm;
       
       class WidgetForm extends CWidgetForm {
       }
  1. Adicione um campo Description ao formulário de configuração do widget. Esse é um campo de texto comum, no qual o usuário pode inserir qualquer conjunto de caracteres. Você pode usar a classe CWidgetFieldTextBox para isso.

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. No diretório views, crie um arquivo de visualização de configuração de widget widget.edit.php e adicione uma visualização para o novo campo Description. Para a classe de campo CWidgetFieldTextBox, a visualização é CWidgetFieldTextBoxView.

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

<?php
       
       /**
        * Visualização do formulário do widget do gráfico de medidores.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description'])
           )
           ->show();
  1. Vá para o painel e clique no ícone de engrenagem no widget para abrir o formulário de configuração do widget.

  2. O formulário de configuração do widget agora contém um novo campo de texto Description. Insira qualquer valor, por exemplo, Gauge chart description.

  1. Clique em Apply no formulário de configuração do widget. Em seguida, clique em Save changes no canto superior direito para salvar o painel. Observe que a nova descrição não está visível em lugar algum e o widget ainda exibe "Hello, world!".

Para que a nova descrição apareça no widget, o valor do campo Description precisa ser recuperado do banco de dados e passado para a visualização do widget. Para isso, você precisa criar uma classe de ação.

  1. Crie um novo diretório actions no diretório lesson_gauge_chart.

  2. Crie um arquivo WidgetView.php no diretório actions. A classe de ação WidgetView estenderá a classe CControllerDashboardWidgetView.

Os valores dos campos de configuração do widget são armazenados na propriedade $fields_values da classe de ação.

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. Abra o arquivo manifest.json e registre o WidgetView como uma classe de ação na seção 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 SIA",
           "actions": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           }
       }
  1. Agora você pode usar o valor do campo de descrição, contido em $data['description'], na exibição do widget. Abra views/widget.view.php e substitua o texto estático "Hello, world!".

Recuperar o valor de um item via API

O widget deve mostrar o último valor de um item da escolha do usuário. Para isso, você precisa adicionar a capacidade de selecionar itens na configuração do widget.

Nesta seção, você aprenderá como adicionar um campo de seleção de item ao formulário do widget e como adicionar a parte visual desse campo à exibição de configuração. Em seguida, o controlador do widget poderá recuperar os dados do item e seu valor por meio de uma solicitação de API. Uma vez recebido, o valor poderá ser exibido na visualização do widget.

  1. Abra o arquivo includes/WidgetForm.php e adicione o campo CWidgetFieldMultiSelectItem. Isso permitirá a seleção de um item no formulário de configuração.

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(
                       (novo CWidgetFieldMultiSelectItem('itemid', _('Item')))
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                           ->setMultiple(false)
                   )
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Description'))
                   );
           }
       }
  1. Abra views/widget.edit.php e adicione o componente visual do campo à visualização de configuração.

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

<?php
       
       /**
        * Visualização do formulário do widget do gráfico do medidor.
        *
        * @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. Volte ao painel e clique no ícone de engrenagem no widget para abrir o formulário de configuração do widget.

  2. O formulário de configuração do widget agora contém um novo campo de entrada Item. Selecione o host "Zabbix server" e o item "Load average (1m avg)".

  1. Clique em Apply no formulário de configuração do widget. Em seguida, clique em Save changes no canto superior direito para salvar o painel.

  2. Abra e modifique o arquivo actions/WidgetView.php.

De agora em diante, o ID do item estará disponível no controlador do widget em $this->fields_values['itemid']. O método do controlador doAction() coleta os dados do item (nome, tipo de valor, unidades) usando o método da API item.get e o último valor do item usando o método da 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;
       
               se ($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
                   ]);
       
                   se ($history) {
                       $value = convertUnitsRaw([
                           'valor' => $history[0]['valor'],
                           '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. Abra views/widget.view.php e adicione o valor do item à visualização do widget.

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

<?php
       
       /**
        * Visualização do widget do gráfico do medidor.
        *
        * @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. Atualize a página do painel. O widget exibirá o valor mais recente do item.

Adicionar JavaScript ao widget

Nesta seção, você aprenderá a adicionar elementos Javascript ao widget.

Você adicionará:

  • Um gráfico de indicador feito com JavaScript - para mostrar rapidamente se o valor mais recente é normal ou muito alto/ muito baixo.
  • Uma seção de Advanced configuration para parâmetros opcionais, como cor, valores mínimo e máximo, unidades e o campo Description criado anteriormente.
  1. Crie um arquivo widget.edit.js.php no diretório views.

O JavaScript será responsável por ocultar os campos opcionais atrás da caixa de seleção Advanced configuration e por inicializar o seletor de cores na exibição de configuração. Você pode adicioná-lo ao mesmo diretório que a visualização de configuração.

Como o JavaScript da visualização de configuração deve ser carregado com o formulário, você precisará incluí-lo no arquivo widget.edit.php, conforme mostrado nas próximas etapas.

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. Crie um arquivo Widget.php no diretório principal do widget lesson_gauge_chart para criar uma nova classe Widget.

A classe Widget estenderá a classe base CWidget para adicionar/substituir as configurações padrão do widget (neste caso - traduções). O JavaScript, fornecido abaixo, exibe a string "No data" (Sem dados) no caso de dados ausentes. A string "No data" está presente nos arquivos de tradução da interface do usuário do Zabbix.

Se houver alguma constante de widget, é recomendável especificá-la também na 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. Abra o arquivo includes/WidgetForm.php e adicione os novos campos: Advanced configuration (caixa de seleção), Color (seletor de cores), Min (campo numérico), Max (campo numérico) e Units (seleção).

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php
       
       namespace Modules\LessonGaugeChart\Includes;
       
       use Modules\LessonGaugeChart\Widget;
       
       use Zabbix\Widgets\{
           CWidgetField,
           CWidgetForm
       };
       
       use Zabbix\Widgets\Fields\{
           CWidgetFieldCheckBox,
           CWidgetFieldColor,
           CWidgetFieldMultiSelectItem,
           CWidgetFieldNumericBox,
           CWidgetFieldSelect,
           CWidgetFieldTextBox
       };
       
       /**
        * Gauge chart widget form.
        */
       class WidgetForm extends CWidgetForm {
       
           public function addFields(): self {
               return $this
                   ->addField(
                       (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                           ->setMultiple(false)
                           ->setFilterParameter('numeric', true)
                   )
                   ->addField(
                       new CWidgetFieldCheckBox('adv_conf', _('Advanced configuration'))
                   )
                   ->addField(
                       (new CWidgetFieldColor('chart_color', _('Color')))->setDefault('FF0000')
                   )
                   ->addField(
                       (new CWidgetFieldNumericBox('value_min', _('Min')))
                           ->setDefault(0)
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                   )
                   ->addField(
                       (new CWidgetFieldNumericBox('value_max', _('Max')))
                           ->setDefault(100)
                           ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                   )
                   ->addField(
                       (new CWidgetFieldSelect('value_units', _('Units'), [
                           Widget::UNIT_AUTO => _x('Auto', 'history source selection method'),
                           Widget::UNIT_STATIC => _x('Static', 'history source selection method')
                       ]))->setDefault(Widget::UNIT_AUTO)
                   )
                   ->addField(
                       (new CWidgetFieldTextBox('value_static_units'))
                   )
                   ->addField(
                       new CWidgetFieldTextBox('description', _('Description'))
                   );
           }
       }
  1. Abra views/widget.edit.php e adicione os componentes visuais do campo à visualização de configuração.

O método addField() da classe CWidgetFormView recebe uma string de classe CSS como segundo parâmetro. Adicione a string js-advanced-configuration a esses campos e a seus rótulos, que devem ficar ocultos se a opção Advanced configuration não estiver selecionada.

Para adicionar um arquivo JavaScript à exibição de configuração, use o método includeJsFile(). Para adicionar JavaScript em linha, use o método addJavaScript().

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

<?php
       
       /**
        * Gauge chart widget form view.
        *
        * @var CView $this
        * @var array $data
        */
       
       use Zabbix\Widgets\Fields\CWidgetFieldGraphDataSet;
       
       $lefty_units = new CWidgetFieldSelectView($data['fields']['value_units']);
       $lefty_static_units = (new CWidgetFieldTextBoxView($data['fields']['value_static_units']))
           ->setPlaceholder(_('value'))
           ->setWidth(ZBX_TEXTAREA_TINY_WIDTH);
       
       (new CWidgetFormView($data))
           ->addField(
               new CWidgetFieldMultiSelectItemView($data['fields']['itemid'], $data['captions']['items']['itemid'])
           )
           ->addField(
               new CWidgetFieldCheckBoxView($data['fields']['adv_conf'])
           )
           ->addField(
               new CWidgetFieldColorView($data['fields']['chart_color']),
               'js-advanced-configuration'
           )
           ->addField(
               new CWidgetFieldNumericBoxView($data['fields']['value_min']),
               'js-advanced-configuration'
           )
           ->addField(
               new CWidgetFieldNumericBoxView($data['fields']['value_max']),
               'js-advanced-configuration'
           )
           ->addItem([
               $lefty_units->getLabel()->addClass('js-advanced-configuration'),
               (new CFormField([
                   $lefty_units->getView()->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
                   $lefty_static_units->getView()
               ]))->addClass('js-advanced-configuration')
           ])
           ->addField(
               new CWidgetFieldTextBoxView($data['fields']['description']),
               'js-advanced-configuration'
           )
           ->includeJsFile('widget.edit.js.php')
           ->addJavaScript('widget_lesson_gauge_chart_form.init('.json_encode([
               'color_palette' => CWidgetFieldGraphDataSet::DEFAULT_COLOR_PALETTE
           ], JSON_THROW_ON_ERROR).');')
           ->show();
  1. Volte ao painel e clique no ícone de engrenagem no widget para abrir o formulário de configuração do widget. O formulário de configuração do widget agora contém uma nova caixa de seleção Advanced configuration.

  1. Marque a caixa de seleção Advanced configuration (Configuração avançada) para ver campos adicionais de configuração do widget. Preencha os campos com valores e selecione uma cor para o widget.

  1. Clique em Apply no formulário de configuração do widget. Em seguida, clique em Save changes no canto superior direito para salvar o painel.

  2. Abra o arquivo actions/WidgetView.php e atualize o controlador.

A propriedade $this->fields_values agora contém os valores de todos os campos de Configuração avançada. Finalize o controlador para permitir a passagem da configuração e do valor do item selecionado para a exibição do 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. Abra e modifique views/widget.view.php.

Você precisa criar um contêiner para o gráfico do medidor, que será desenhado nas próximas etapas, e um contêiner para a descrição.

Para passar valores para o JavaScript como um objeto JSON, use o método 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. Crie um novo diretório assets no diretório lesson_gauge_chart. Esse diretório será usado para armazenar JavaScript, CSS e, possivelmente, quaisquer outros ativos, como fontes ou imagens.

  2. Para o JavaScript de exibição de widget, crie um diretório js no diretório assets.

  3. Crie um arquivo class.widget.js no diretório assets/js.

Essa classe de widget JavaScript estenderá a classe JavaScript básica de todos os widgets do painel: CWidget.

O painel depende de uma implementação correta de um widget e comunica qualquer informação relevante ao widget por meio da chamada dos respectivos métodos JavaScript. O painel também espera que o widget gere eventos quando ocorrer alguma interação. Assim, a classe CWidget contém um conjunto de métodos com a implementação padrão do comportamento do widget, que pode ser personalizado por meio da extensão da classe.

Nesse caso, é necessária alguma personalização, portanto, a lógica personalizada será implementada para o seguinte comportamento do widget:

  • inicialização do widget, que é responsável por definir o estado inicial do widget (consulte o método _init());
  • exibição do conteúdo do widget (ou seja, desenho do gráfico do medidor) se o processo de atualização do widget tiver sido bem-sucedido e sem erros (consulte o método _processUpdateResponse(response) e os métodos relacionados _resizeChart() e _updatedChart())
  • redimensionamento do widget (consulte o método resize() e o método relacionado _resizeChart())

Para outros aspectos do widget de gráfico de medidor, será usada a implementação padrão do comportamento do widget. Para saber mais sobre os métodos JavaScript da classe CWidget, consulte: JavaScript.

Como esse JavaScript é necessário para a exibição do widget, ele deve ser carregado com a página do painel. Para ativar o carregamento do JavaScript, você precisará atualizar os parâmetros assets/js e js_class do manifest.json, conforme mostrado na próxima etapa. *** Translated with www.DeepL.com/Translator (free version) ***

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. Abra o arquivo manifest.json e adicione:
  • nome do arquivo (class.widget.js) à matriz na seção assets/js;
  • nome da classe (WidgetLessonGaugeChart) ao parâmetro js_class na seção widget.

A classe WidgetLessonGaugeChart agora será carregada automaticamente com o painel.

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"]
           }
       }

Adicionar estilos CSS ao widget

Nesta seção, você aprenderá a adicionar estilos CSS personalizados para tornar o widget mais atraente.

  1. Para estilos de widget, crie um novo diretório css no diretório assets.

  2. Crie um arquivo widget.css no diretório assets/css. Para estilizar os elementos do widget, use o seletor div.dashboard-widget-{widget id}. Para configurar o CSS de todo o widget, use o seletor 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;
           tamanho da fonte: 1.750em;
           altura da linha: 1,2;
           text-align: center; 
       }
       
       .dashboard-grid-widget-hidden-header div.dashboard-widget-lesson_gauge_chart .chart {
           margin-top: 8px; 
       }
  1. Abra o arquivo manifest.json e adicione o nome do arquivo CSS (widget.css) à matriz na seção assets/css. Isso permitirá que os estilos CSS definidos em widget.css sejam carregados com a página do painel.

ui/modules/lesson_gauge_chart/manifest.json

{
           "manifest_version": 2.0,
           "id": "lesson_gauge_chart",
           "type": "widget",
           "name": "Gauge chart",
           "namespace": "LessonGaugeChart",
           "versão": "1.0",
           "autor": "Zabbix SIA",
           "ações": {
               "widget.lesson_gauge_chart.view": {
                   "class": "WidgetView"
               }
           },
           "widget": {
               "js_class": "WidgetLessonGaugeChart"
           },
           "assets" (ativos): {
               "css": ["widget.css"],
               "js": ["class.widget.js"]
           }
       }
  1. Atualize a página do painel para ver a versão finalizada do widget.

*** Translated with www.DeepL.com/Translator (free version) ***