Presentación

Esta página describe los componentes que se pueden utilizar para crear una vista de presentación de widgets. La vista de presentación del widget es la parte del widget que recibe los datos según su configuración y los muestra en el tablero en un contenedor.

La vista de presentación consta de tres partes:

Acción del widget

La clase de acción de widget (WidgetView) contiene métodos para operaciones con widgets en el modo de vista de presentación. La mayoría de las acciones de los widgets utilizan y/o amplían la clase de controlador predeterminada CControllerDashboardWidgetView.

La clase de acción del widget debe ubicarse en el directorio actions y especificarse en el parámetro actions (actions/widget.{id}.view/class) en el archivo manifest.json.

ejemplo de actions/WidgetView.php (implementado en el widget nativo de Zabbix Información del sistema)

class WidgetView extends CControllerDashboardWidgetView {
       
       protected function doAction(): void {
       $this->setResponse(new CControllerResponseData([
       'name' => $this->getInput('name', $this->widget->getDefaultName()),
       'system_info' => CSystemInfoHelper::getData(),
       'info_type' => $this->fields_values['info_type'],
       'user_type' => CWebUser::getType(),
       'user' => [
       'debug_mode' => $this->getDebugMode()
       ]
       ]));
       }
       }

Vista de widgets

La clase de vista de widget (CWidgetView) es responsable de crear la vista de presentación del widget.

La clase de vista del widget debe estar ubicada en el directorio views. Si el archivo que contiene la clase de vista del widget tiene un nombre diferente al predeterminado (widget.view.php), entonces debe especificarse en el archivo manifest.json parámetro actions (actions/widget.{id}.view/view).

ejemplo de views/widget.view.php

<?php
       
       /**
        * My custom widget view.
        *
        * @var CView $this
        * @var array $data
        */
       
       (new CWidgetView($data))
       ->addItem(
       new CTag('h1', true, $data['name'])
       )
       ->show();

JavaScript

La clase JavaScript es responsable de determinar el comportamiento del widget, como actualizar los datos del widget, cambiar el tamaño del widget, mostrar elementos del widget, etc.

Todas las operaciones de JavaScript utilizan y/o amplían la clase JavaScript base de todos los widgets del panel: CWidget. La clase CWidget contiene un conjunto de métodos con la implementación predeterminada para el comportamiento del widget. Dependiendo de la complejidad del widget, estos métodos se pueden utilizar tal cual o ampliados.

La clase CWidget contiene los siguientes métodos:

  • Métodos que definen el ciclo de vida del widget: _init(), _registerEvents(), _doActivate(), _doDeactivate(), _doDestroy(), setEditMode().
  • Métodos que manejan la actualización y visualización de datos de widgets: _promiseUpdate(), _getUpdateRequestData(), _processUpdateResponse(response), _processUpdateErrorResponse(error), _setContents().
  • Métodos que modifican la apariencia del widget: resize(), _hasPadding().

La clase JavaScript debe ubicarse en el directorio assets/js y especificarse en el parámetro assets (assets/js) en el archivo manifest.json.

Métodos de ciclo de vida

Los métodos del ciclo de vida del widget son invocados por el tablero y en diferentes etapas del ciclo de vida del widget durante su existencia dentro del tablero.

El método _init() define el estado inicial y/o los valores del widget, sin realizar ninguna manipulación de datos o HTML. Este método se invoca cuando se crea un widget (se crea una instancia de un objeto de widget), generalmente agregando el widget a una página del tablero o cargando la página del tablero.

Ejemplo:

_init() {
       super._init();
       
       this._time_offset = 0;
       this._interval_id = null;
       this._clock_type = CWidgetClock.TYPE_ANALOG;
       this._time_zone = null;
       this._show_seconds = true;
       this._time_format = 0;
       this._tzone_format = 0;
       this._show = [];
       this._has_contents = false;
       this._is_enabled = true;
       }

El método _registerEvents() define la estructura HTML del widget, sin realizar ninguna manipulación de datos. Este método se invoca antes de la primera activación de la página del tablero, es decir, antes de que el tablero y sus widgets se muestren completamente al usuario.

Ejemplo:

_registerEvents() {
       super._registerEvents();
       
       this._events.resize = () => {
       const padding = 25;
       const header_height = this._view_mode == ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER
       ? 0
       : this._content_header.offsetHeight;
       
       this._target.style.setProperty(
       '--content-height',
       `${this._cell_height * this._pos.height - padding * 2 - header_height}px`
       );
       }
       }

El método _doActivate() hace que el widget esté activado e interactúe al habilitar detectores de eventos personalizados (para responder a las acciones del usuario) e iniciar el ciclo de actualización del widget (para mantener su contenido actualizado). Este método se invoca cuando se activa la página del tablero, es decir, cuando se muestra completamente en la interfaz de usuario.

Tenga en cuenta que antes de invocar el método _doActivate(), el widget está en estado inactivo (WIDGET_STATE_INACTIVE). Después de una invocación exitosa, el widget pasa al estado activo (WIDGET_STATE_ACTIVE). En el estado activo, el widget responde, escucha eventos, actualiza su contenido periódicamente y puede interactuar con otros widgets.

Ejemplo:

_doActivate() {
       super._doActivate();
       
       if (this._has_contents) {
       this._activateContentsEvents();
       }
       }

El método _doDeactivate() detiene cualquier actividad e interactividad del widget desactivando los detectores de eventos personalizados y deteniendo el ciclo de actualización del widget. Este método se invoca cuando la página del tablero está desactivada, es decir, se apaga o se elimina, o cuando el widget se elimina de la página del tablero.

Tenga en cuenta que antes de invocar el método _doDeactivate(), el widget está en estado activo (WIDGET_STATE_ACTIVE). Después de una invocación exitosa, el widget pasa al estado inactivo (WIDGET_STATE_INACTIVE).

Ejemplo:

_doDeactivate() {
       super._doDeactivate();
       
       this._deactivateContentsEvents();
       }

El método _doDestroy() realiza tareas de limpieza antes de que el widget se elimine del tablero. que puede incluir cerrar una conexión de base de datos que se estableció durante la inicialización del widget, limpiar datos temporales para liberar memoria del sistema y evitar fugas de recursos, cancelar el registro de detectores de eventos relacionados con eventos de cambio de tamaño o clics de botones para evitar el manejo innecesario de eventos y pérdidas de memoria, etc. Este método se invoca cuando se elimina el widget o la página del tablero que lo contiene.

Tenga en cuenta que antes de invocar el método _doDestroy(), un widget en estado activo (WIDGET_STATE_ACTIVE) siempre se desactiva con la invocación del método _doDeactivate().

Ejemplo:

_doDestroy() {
       super._doDestroy();
       
       if (this._filter_widget) {
       this._filter_widget.off(CWidgetMap.WIDGET_NAVTREE_EVENT_MARK, this._events.mark);
       this._filter_widget.off(CWidgetMap.WIDGET_NAVTREE_EVENT_SELECT, this._events.select);
       }
       }

El método setEditMode() define la apariencia y el comportamiento del widget cuando el tablero pasa al modo de edición. Este método se invoca cuando el tablero pasa al modo de edición, normalmente cuando un usuario interactúa con el botón Editar del widget o el botón Editar tablero del tablero.

Ejemplo:

setEditMode() {
       if (this._has_contents) {
       this._deactivateContentsEvents();
       this._removeTree();
       }
       
       super.setEditMode();
       
       if (this._has_contents && this._state === WIDGET_STATE_ACTIVE) {
       this._makeTree();
       this._activateTree();
       this._activateContentsEvents();
       }
       }
Métodos de proceso de actualización

Los métodos del proceso de actualización del widget son responsables de recuperar datos actualizados del servidor Zabbix o cualquier otra fuente de datos y mostrarlos en el widget.

El método _promiseUpdate() inicia el proceso de actualización de datos recuperando datos, normalmente mediante solicitudes web o llamadas API. Este método se invoca cuando se muestra una página del tablero y periódicamente después, hasta que la página del tablero cambia a otra página del tablero.

El siguiente es un ejemplo de la implementación predeterminada del método _promiseUpdate() utilizado por la mayoría de los widgets nativos de Zabbix. En la implementación predeterminada, el método _promiseUpdate() sigue un patrón general para recuperar datos del servidor. Crea un nuevo objeto Curl con la URL apropiada y los parámetros de solicitud. envía una solicitud POST usando el método fetch() con el objeto de datos construido por el método _getUpdateRequestData(), y procesa la respuesta (o una respuesta de error) con _processUpdateResponse(response) o _processUpdateErrorResponse(error) en consecuencia. Esta implementación es adecuada para la mayoría de los widgets, ya que normalmente recuperan datos en formato JSON y los manejan de manera consistente.

_promiseUpdate() {
       const curl = new Curl('zabbix.php');
       
       curl.setArgument('action', `widget.${this._type}.view`);
       
       return fetch(curl.getUrl(), {
       method: 'POST',
       headers: {'Content-Type': 'application/json'},
       body: JSON.stringify(this._getUpdateRequestData()),
       signal: this._update_abort_controller.signal
       })
       .then((response) => response.json())
       .then((response) => {
       if ('error' in response) {
       this._processUpdateErrorResponse(response.error);
       
       return;
       }
       
       this._processUpdateResponse(response);
       });
       }

El método _getUpdateRequestData() prepara los datos de solicitud del servidor para actualizar el widget recopilando varias propiedades y sus valores correspondientes (identificadores de widget, configuraciones de filtro, rangos de tiempo, etc.) del estado y la configuración del widget. y construir un objeto de datos que representa la información necesaria para ser enviada al servidor en la solicitud de actualización. Este método se invoca sólo como parte del método predeterminado [_promiseUpdate()], es decir, durante el proceso de actualización del widget.

Implementación predeterminada:

_getUpdateRequestData() {
       return {
       templateid: this._dashboard.templateid ?? undefined,
       dashboardid: this._dashboard.dashboardid ?? undefined,
       widgetid: this._widgetid ?? undefined,
       name: this._name !== '' ? this._name : undefined,
       fields: Object.keys(this._fields).length > 0 ? this._fields : undefined,
       view_mode: this._view_mode,
       edit_mode: this._is_edit_mode ? 1 : 0,
       dynamic_hostid: this._dashboard.templateid !== null || this.supportsDynamicHosts()
       ? (this._dynamic_hostid ?? undefined)
       : undefined,
       ...this._content_size
       };
       }

El método _processUpdateResponse(response) maneja la respuesta recibida del servidor después de la solicitud de actualización, y, si el proceso de actualización ha sido exitoso y sin errores, borra los datos del widget y muestra nuevos contenidos con el método _setContents(). Este método se invoca sólo como parte del método predeterminado _promiseUpdate(), es decir, durante el proceso de actualización del widget.

Implementación predeterminada:

_processUpdateResponse(response) {
       this._setContents({
       name: response.name,
       body: response.body,
       messages: response.messages,
       info: response.info,
       debug: response.debug
       });
       }

El método _processUpdateErrorResponse(error) maneja la respuesta recibida del servidor después de la solicitud de actualización si la respuesta es un error y muestra los mensajes de error. Este método se invoca solo como parte del método predeterminado _promiseUpdate(), es decir, durante el proceso de actualización del widget.

Implementación predeterminada:

_processUpdateErrorResponse(error) {
           this._setErrorContents({error});
       }
       
       _setErrorContents({error}) {
           const message_box = makeMessageBox('bad', error.messages, error.title)[0];
       
           this._content_body.innerHTML = '';
           this._content_body.appendChild(message_box);
       
           this._removeInfoButtons();
       }

El método _setContents() muestra el contenido del widget si el proceso de actualización del widget ha sido exitoso y sin errores, que puede incluir la manipulación de elementos DOM, la actualización de componentes de la interfaz de usuario, la aplicación de estilos o formato, etc. Este método se invoca sólo como parte del método predeterminado _processUpdateResponse(response), es decir, durante el proceso de manejo de la respuesta recibida del servidor después de la solicitud de actualización.

Implementación predeterminada:

_setContents({name, body, messages, info, debug}) {
       this._setHeaderName(name);
       
       this._content_body.innerHTML = '';
       
       if (messages !== undefined) {
       const message_box = makeMessageBox('bad', messages)[0];
       
       this._content_body.appendChild(message_box);
       }
       
       if (body !== undefined) {
       this._content_body.insertAdjacentHTML('beforeend', body);
       }
       
       if (debug !== undefined) {
       this._content_body.insertAdjacentHTML('beforeend', debug);
       }
       
       this._removeInfoButtons();
       
       if (info !== undefined) {
       this._addInfoButtons(info);
       }
       }
Métodos de modificación de presentación

Los métodos de modificación de la presentación del widget son responsables de modificar la apariencia del widget.

El método resize() es responsable de ajustar los elementos visuales del widget para acomodar el nuevo tamaño del widget. que puede incluir reorganizar elementos, ajustar las dimensiones de los elementos, truncar texto, implementar carga diferida para mejorar la capacidad de respuesta durante el cambio de tamaño, etc. Este método se invoca cuando se cambia el tamaño del widget, por ejemplo, cuando el usuario cambia manualmente el tamaño del widget o cuando se cambia el tamaño de la ventana del navegador.

Ejemplo:

resize() {
       if (this._state === WIDGET_STATE_ACTIVE) {
       this._startUpdating();
       }
       }

El método _hasPadding() es responsable de aplicar un relleno vertical de 8px en la parte inferior del widget cuando está configurado para mostrar su encabezado. Este método se invoca cuando se activa la página del tablero, es decir, cuando se convierte en la página que se muestra en la interfaz de usuario.

Implementación predeterminada:

_hasPadding() {
       return this._view_mode !== ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER;
       }

Para algunos widgets es necesario utilizar todo el espacio disponible para configurar, por ejemplo, un color de fondo personalizado. El siguiente es un ejemplo de la implementación del método _hasPadding() utilizado en el widget nativo de Zabbix Valor de la métrica.

_hasPadding() {
       return false;
       }