Crear un widget (tutorial)

Este es un tutorial paso a paso que muestra cómo crear un widget de panel simple. Puede descargar todos los archivos de este widget como un archivo ZIP: lesson_gauge_chart.zip.

Qué vas a construir

Durante este tutorial, primero crearás un widget básico de "¡Hola, mundo!" y luego lo convertirás en un widget más avanzado que muestra el valor de una métrica como un gráfico de tipo gauge. Así es como se verá el widget terminado:

Parte I - "¡Hola, mundo!"

En esta sección aprenderá cómo crear los elementos mínimos requeridos de un widget y añadir un nuevo widget al frontend de Zabbix.

Añadir un widget en blanco al frontend de Zabbix

  1. Cree un directorio lesson_gauge_chart en el directorio modules de su instalación del frontend de Zabbix (por ejemplo, zabbix/ui/modules).

Todos los widgets personalizados se tratan como módulos externos y deben añadirse al directorio modules de su instalación del frontend de Zabbix (por ejemplo, zabbix/ui/modules). El directorio zabbix/ui/widgets está reservado para los widgets integrados de Zabbix y se actualiza junto con la interfaz de usuario de Zabbix.

  1. Cree un archivo manifest.json con los metadatos básicos del widget (consulte la descripción de los parámetros soportados).

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. En el frontend de Zabbix, vaya a la sección Administración → General → Módulos y haga clic en el botón Escanear directorio.

  1. Localice el nuevo módulo Gauge chart en la lista y haga clic en el hipervínculo "Deshabilitado" para cambiar el estado del módulo de "Deshabilitado" a "Habilitado" (si el módulo no aparece en la lista, consulte la sección de solución de problemas).

  1. Abra un dashboard, cámbielo al modo de edición y añada un nuevo widget. En el campo Tipo, seleccione "Gauge chart".

  1. En este punto, la configuración del widget Gauge chart sólo contiene los campos comunes de widget Nombre e Intervalo de actualización. Haga clic en Añadir para añadir el widget al dashboard.

  1. Debería aparecer un widget en blanco en el dashboard. Haga clic en Guardar cambios en la esquina superior derecha para guardar el dashboard.

Añadir una vista de widget

El archivo view del widget debe estar ubicado en el directorio views (para este tutorial, ui/modules/lesson_gauge_chart/views/). Si el archivo tiene el nombre por defecto widget.view.php, no es necesario registrarlo en el archivo manifest.json. Si el archivo tiene un nombre diferente, especifíquelo en la sección actions/widget.lesson_gauge_chart.view del archivo manifest.json.

  1. Cree un directorio views en el directorio lesson_gauge_chart.

  2. Cree un archivo widget.view.php en el directorio views.

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

<?php

/**
 * Vista del widget de gráfico de gauge.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem(
        new CTag('h1', true, '¡Hola, mundo!')
    )
    ->show();
  1. Actualice el dashboard. El widget Gauge chart ahora muestra "¡Hola, mundo!".

Parte II - Gráfico de indicador

Añadir ajustes a una vista de configuración y usarlos en una vista de widget

En esta sección, aprenderá cómo añadir un campo de configuración de widget y mostrar el valor introducido en la vista del widget como texto.

La configuración del widget consta de un formulario (Zabbix\Widgets\CWidgetForm) y una vista de formulario de widget (widget.edit.php). Para añadir campos (Zabbix\Widgets\CWidgetField), debe crear una clase WidgetForm, que extenderá Zabbix\Widgets\CWidgetForm.

El formulario contiene el conjunto de campos (Zabbix\Widgets\CWidgetField) de varios tipos, que se utilizan para validar los valores introducidos por el usuario. El campo de formulario (Zabbix\Widgets\CWidgetField) para cada tipo de elemento de entrada convierte el valor en un formato único para almacenarlo en la base de datos.

El archivo form del widget debe estar ubicado en el directorio includes (para este tutorial, ui/modules/lesson_gauge_chart/includes/). Si el archivo tiene el nombre por defecto WidgetForm.php, no es necesario registrarlo en el archivo manifest.json. Si el archivo tiene un nombre diferente, especifíquelo en la sección widget/form_class del archivo manifest.json.

  1. Cree un nuevo directorio includes en el directorio lesson_gauge_chart.

  2. Cree un archivo WidgetForm.php en el directorio includes.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

class WidgetForm extends CWidgetForm {
}
  1. Añada un campo Description al formulario de configuración del widget. Este es un campo de texto normal, donde el usuario puede introducir cualquier conjunto de caracteres. Puede utilizar la clase CWidgetFieldTextBox para ello.

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. En el directorio views, cree un archivo de vista de configuración de widget widget.edit.php y añada una vista para el nuevo campo Description. Para la clase de campo CWidgetFieldTextBox, la vista es 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. Vaya al dashboard y haga clic en el icono de engranaje en el widget para abrir el formulario de configuración del widget.

  2. El formulario de configuración del widget ahora contiene un nuevo campo de texto Description. Introduzca cualquier valor, por ejemplo, Gauge chart description.

  1. Haga clic en Apply en el formulario de configuración del widget. Luego haga clic en Save changes en la esquina superior derecha para guardar el dashboard. Tenga en cuenta que la nueva descripción no es visible en ningún sitio, y el widget sigue mostrando "Hello, world!".

Para que la nueva descripción aparezca en el widget, es necesario recuperar el valor del campo Description de la base de datos y pasarlo a la vista del widget. Para ello, debe crear una clase de acción.

  1. Cree un nuevo directorio actions en el directorio lesson_gauge_chart.

  2. Cree un archivo WidgetView.php en el directorio actions. La clase de acción WidgetView extenderá la clase CControllerDashboardWidgetView.

Los valores de los campos de configuración del widget se almacenan en la propiedad $fields_values de la clase de acción.

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 manifest.json y registre WidgetView como una clase de acción en la sección 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. Ahora puede utilizar el valor del campo de descripción, contenido en $data['description'], en la vista del widget. Abra views/widget.view.php y reemplace el texto estático "Hello, world!" por $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. Actualice la página del dashboard. Ahora debería ver el texto de la descripción del widget en lugar de "Hello, world!".

Recuperar el valor de un item mediante la API

El widget debe mostrar el último valor de un item elegido por el usuario. Para ello, es necesario añadir la posibilidad de seleccionar items en la configuración del widget.

En esta sección, aprenderá cómo añadir un campo de selección de item al formulario del widget y cómo añadir la parte visual de este campo a la vista de configuración. A continuación, el controlador del widget podrá recuperar los datos del item y su valor mediante una petición a la API. Una vez recibido, el valor puede mostrarse en la vista del widget.

  1. Abra includes/WidgetForm.php y añada el campo CWidgetFieldMultiSelectItem. Esto permitirá seleccionar un item en el formulario de configuración.

ui/modules/lesson_gauge_chart/includes/WidgetForm.php

<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\{
    CWidgetField,
    CWidgetForm
};

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

/**
 * Gauge chart widget form.
 */
class WidgetForm extends CWidgetForm {

    public function addFields(): self {
        return $this
            ->addField(
                (new CWidgetFieldMultiSelectItem('itemid', _('Item')))
                    ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK)
                    ->setMultiple(false)
            )
            ->addField(
                new CWidgetFieldTextBox('description', _('Description'))
            );
    }
}
  1. Abra views/widget.edit.php y añada el componente visual del campo a la vista de configuración.

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. Vuelva al dashboard y haga clic en el icono de engranaje del widget para abrir el formulario de configuración del widget.

  2. El formulario de configuración del widget contiene ahora un nuevo campo de entrada Item. Seleccione el host "Zabbix server" y el item "Load average (1m avg)".

  1. Haga clic en Aplicar en el formulario de configuración del widget. A continuación, haga clic en Guardar cambios en la esquina superior derecha para guardar el dashboard.

  2. Abra y modifique actions/WidgetView.php.

A partir de ahora, el ID del item estará disponible en el controlador del widget en $this->fields_values['itemid']. El método doAction() del controlador recopila los datos del item (nombre, tipo de valor, unidades) utilizando el método de la API item.get y el último valor del item utilizando el método de la 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. Abra views/widget.view.php y añada el valor del item a la vista del widget.

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

<?php

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

(new CWidgetView($data))
    ->addItem([
        new CTag('h1', true, $data['description']),
        new CDiv($data['value'] !== null ? $data['value']['value'] : _('No data'))
    ])
    ->show();
  1. Actualice la página del dashboard. El widget mostrará el último valor del item.

Añadir ajustes de configuración avanzados a una vista de configuración

En esta sección, aprenderá cómo añadir una sección Configuración avanzada expandible/colapsable con parámetros opcionales, como color, valores mínimo y máximo, unidades y el campo Descripción creado anteriormente.

  1. Cree un archivo Widget.php en el directorio principal del widget lesson_gauge_chart para crear una nueva clase Widget.

La clase Widget extenderá la clase base CWidget para añadir/sobrescribir los ajustes por defecto del widget (en este caso, las traducciones). El JavaScript, proporcionado a continuación, muestra la cadena "No hay datos" en caso de que falten datos. La cadena "No hay datos" está presente en los archivos de traducción de la interfaz de Zabbix.

Si hay alguna constante del widget, se recomienda especificarla también en la clase 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 includes/WidgetForm.php y añada los nuevos campos Color (selector de color), Min (campo numérico), Max (campo numérico) y Units (select), y defina la paleta de colores por defecto para el selector de color, para que pueda utilizarse en los siguientes pasos.

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

/**
 * Formulario del widget de gráfico de tipo gauge.
 */
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. Abra views/widget.edit.php y añada los componentes visuales de los campos a la vista de configuración.

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

<?php

/**
 * Vista del formulario del widget de gráfico de tipo gauge.
 *
 * @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();

El método addField() de la clase CWidgetFormView acepta una cadena de clase CSS como segundo parámetro.

  1. Vuelva al dashboard, cambie al modo de edición y haga clic en el icono de engranaje del widget para abrir el formulario de configuración del widget. El formulario de configuración del widget ahora contiene una nueva sección expandible/colapsable Configuración avanzada.

  1. Expanda la sección Configuración avanzada para ver los campos de configuración adicionales del widget. Tenga en cuenta que el campo Color aún no tiene selector de color. Esto se debe a que el selector de color debe inicializarse con JavaScript, que se añadirá en la siguiente sección - Añadir JavaScript al widget.

Añadir JavaScript al widget

En esta sección, aprenderá cómo añadir un gráfico de tipo gauge - hecho con JavaScript - que muestra si el último valor es normal o demasiado alto/bajo.

  1. Cree un archivo widget.edit.js.php en el directorio views.

JavaScript será responsable de inicializar el selector de color en la vista de configuración.

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. Abra views/widget.edit.php y añada el archivo widget.edit.js.php con el JavaScript a la vista de configuración. Para ello, utilice el método includeJsFile(). Para añadir JavaScript en línea, utilice el 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 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. Vuelva al dashboard, haga clic en el icono de engranaje en el widget para abrir el formulario de configuración del widget. Ahora, expanda la sección Advanced configuration para ver el selector de color inicializado. Rellene los campos con valores y seleccione un color para el gráfico gauge.

  1. Haga clic en Apply en el formulario de configuración del widget. Luego haga clic en Save changes en la esquina superior derecha para guardar el dashboard.

  2. Abra actions/WidgetView.php y actualice el controlador.

La propiedad $this->fields_values ahora contiene los valores de todos los campos de Advanced configuration. Finalice el controlador para permitir pasar la configuración y el valor del item seleccionado a la 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. Abra y modifique views/widget.view.php.

Necesita crear un contenedor para el gráfico gauge, que dibujará en los siguientes pasos, y un contenedor para la descripción.

Para pasar valores a JavaScript como un objeto JSON, utilice el 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. Cree un nuevo directorio assets en el directorio lesson_gauge_chart. Este directorio se utilizará para almacenar JavaScript, CSS y potencialmente cualquier otro recurso, como fuentes o imágenes.

  2. Para el JavaScript de la vista del widget, cree un directorio js en el directorio assets.

  3. Cree un archivo class.widget.js en el directorio assets/js.

Esta clase JavaScript del widget extenderá la clase base JavaScript de todos los widgets del dashboard - CWidget.

El dashboard depende de una implementación correcta de un widget y comunica cualquier información relevante al widget llamando a los respectivos métodos JavaScript. El dashboard también espera que el widget genere eventos cuando ocurre alguna interacción. Por lo tanto, la clase CWidget contiene un conjunto de métodos con la implementación por defecto del comportamiento del widget, que puede ser personalizado extendiendo la clase.

En este caso, es necesaria cierta personalización, por lo tanto se implementará lógica personalizada para el siguiente comportamiento del widget:

  • inicialización del widget que es responsable de definir el estado inicial del widget (ver el método onInitialize());
  • mostrar el contenido del widget (es decir, dibujar el gráfico gauge) si el proceso de actualización del widget ha sido exitoso y sin errores (ver el método processUpdateResponse(response) y los métodos relacionados _resizeChart() y _updatedChart()).
  • redimensionar el widget (ver el método onResize() y el método relacionado _resizeChart())

Para otros aspectos del widget gauge, se utilizará la implementación por defecto del comportamiento del widget. Para obtener más información sobre los métodos JavaScript de la clase CWidget, consulte: JavaScript.

Dado que este JavaScript es necesario para la vista del widget, debe cargarse con la página del dashboard. Para habilitar la carga de JavaScript, deberá actualizar los parámetros assets/js y js_class en el archivo manifest.json como se muestra en el paso 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. Abra manifest.json y añada:
  • el nombre del archivo (class.widget.js) al array en la sección assets/js;
  • el nombre de la clase (WidgetLessonGaugeChart) al parámetro js_class en la sección widget.

La clase WidgetLessonGaugeChart ahora se cargará automáticamente con el 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"]
    }
}

Añadir estilos CSS al widget

En esta sección aprenderá cómo añadir estilos CSS personalizados para que el widget tenga un aspecto más atractivo.

  1. Para los estilos del widget, cree un nuevo directorio css en el directorio assets.

  2. Cree un archivo widget.css en el directorio assets/css. Para dar estilo a los elementos del widget, utilice el selector div.dashboard-widget-{widget id}. Para configurar el CSS para todo el widget, utilice el selector 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. Abra manifest.json y añada el nombre del archivo CSS (widget.css) al array en la sección assets/css. Esto permitirá que los estilos CSS definidos en widget.css se carguen con la página del 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. Actualice la página del dashboard para ver la versión finalizada del widget.