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 de tablero: 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: onInitialize(), onStart(), onActivate(), onDeactivate(), onDestroy(), onEdit().
  • Métodos que manejan la actualización y visualización de datos de widgets: promiseUpdate(), getUpdateRequestData(), processUpdateResponse(response), processUpdateErrorResponse(error), setContents(response).
  • Métodos que modifican la apariencia del widget: onResize(), 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 onInitialize() 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:

onInitialize() {
           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 onStart() 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:

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

El método onActivate() hace que el widget sea activo e interactivo 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 onActivate(), 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:

onActivate() {
           this._startClock();
       
           this._resize_observer = new ResizeObserver(this._events.resize);
           this._resize_observer.observe(this._target);
       }

El método onDeactivate() 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 onDeactivate(), 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:

onDeactivate() {
           this._stopClock();
           this._resize_observer.disconnect();
       }

El método onDestroy() realiza tareas de limpieza antes de que el widget se elimine del tablero, lo 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 onDestroy(), un widget en estado activo (WIDGET_STATE_ACTIVE) siempre se desactiva con la invocación del método onDeactivate().

Ejemplo:

onDestroy() {
           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 onEdit() 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:

onEdit() {
           this._deactivateGraph();
       }
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 construye 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._contents_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._setHeaderName(response.name);
       
           this._updateMessages(response.messages);
           this._updateInfo(response.info);
           this._updateDebug(response.debug);
       
           this.setContents(response);
       }

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._updateMessages(error.messages, error.title);
       }

El método setContents(response) muestra el contenido del widget si el proceso de actualización del widget ha sido exitoso y sin errores, lo 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(response) {
           this._body.innerHTML = response.body ?? '';
       }
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 onResize() es responsable de ajustar los elementos visuales del widget para adaptarse al nuevo tamaño del widget, lo 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:

onResize() {
           if (this.getState() === 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.getViewMode() !== 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 Valor de métrica nativo de Zabbix.

hasPadding() {
           return false;
       }