Apresentação

Esta página descreve os componentes que podem ser usados para criar uma visualização de apresentação do widget. A visualização de apresentação do widget é a parte do widget que recebe os dados de acordo com sua configuração e os exibe no painel em um contêiner.

A exibição de apresentação consiste em três partes:

Ação do widget

A classe de ação do widget (WidgetView) contém métodos para operações com widgets no modo de exibição de apresentação. A maioria das ações de widget usa e/ou estende a classe de controlador padrão CControllerDashboardWidgetView.

A classe de ação do widget deve estar localizada no diretório actions e especificada no parâmetro actions (actions/widget.{id}.view/class) no arquivo manifest.json.

exemplo do arquivo actions/WidgetView.php (implementado no widget System information nativo do Zabbix)**

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

Visualização do widget

A classe de visualização do widget (CWidgetView) é responsável por criar a visualização de apresentação do widget.

A classe de visualização do widget deve estar localizada no diretório views. Se o arquivo que contém a classe de visualização do widget tiver um nome diferente do padrão (widget.view.php), ele deverá ser especificado no parâmetro do arquivo manifest.json actions (actions/widget.{id}.view/view).

exemplo de views/widget.view.php**

<?php

/**
 * Minha visualização de widget personalizada.
 *
 * @var CView $this
 * @var array $data
 */

(novo CWidgetView($data))
    ->addItem(
        novo CTag('h1', true, $data['name'])
    )
    ->show();

JavaScript

A classe JavaScript é responsável por determinar o comportamento do widget, como a atualização dos dados do widget, o redimensionamento do widget, a exibição de elementos do widget etc.

Todas as operações JavaScript usam e/ou estendem a classe JavaScript básica de todos os widgets do painel: CWidget. A classe CWidget contém um conjunto de métodos com a implementação padrão para o comportamento do widget. Dependendo da complexidade do widget, esses métodos podem ser utilizados como estão ou estendidos.

A classe CWidget contém os seguintes métodos:

  • Métodos que definem o ciclo de vida do widget: _init(), _registerEvents(), _doActivate(), _doDeactivate(), _doDestroy(), setEditMode().
  • Métodos que tratam da atualização e exibição de dados do widget: _promiseUpdate(), _getUpdateRequestData(), _processUpdateResponse(response), _processUpdateErrorResponse(error), _setContents().
  • Métodos que modificam a aparência do widget: resize(), _hasPadding().

A classe JavaScript deve estar localizada no diretório assets/js e especificada no parâmetro assets (assets/js) no arquivo manifest.json.

Métodos de ciclo de vida

Os métodos do ciclo de vida do widget são invocados pelo painel e em diferentes estágios do ciclo de vida do widget durante sua existência no painel.

O método onInitialize() define o estado inicial e/ou os valores do widget, sem realizar nenhuma manipulação de HTML ou dados. Este método é invocado quando um widget é criado (um objeto widget é instanciado), normalmente adicionando o widget a uma página do painel ou carregando a página do painel.

Exemplo:

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

O método onStart() define a estrutura HTML do widget, sem realizar nenhuma manipulação de dados. Este método é invocado antes da primeira ativação da página do painel, ou seja, antes que o painel e seus widgets sejam totalmente exibidos ao usuário.

Exemplo:

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

O método onActivate() torna o widget ativo e interativo, habilitando ouvintes de eventos personalizados (para responder às ações do usuário) e iniciando o ciclo de atualização do widget (para manter seu conteúdo atualizado). Este método é invocado quando a página do painel é ativada, ou seja, quando ela é totalmente exibida na interface do usuário.

Observe que, antes da invocação do método onActivate(), o widget está no estado inativo (WIDGET_STATE_INACTIVE). Após a invocação bem-sucedida, o widget transita para o estado ativo (WIDGET_STATE_ACTIVE). No estado ativo, o widget é responsivo, ouve eventos, atualiza seu conteúdo periodicamente e pode interagir com outros widgets.

Exemplo:

onActivate() {
this._startClock();

this._resize_observer = new ResizeObserver(this._events.resize);
este._resize_observer.observe(este._target);
}

O método onDeactivate() interrompe qualquer atividade e interatividade do widget desativando ouvintes de eventos personalizados e interrompendo o ciclo de atualização do widget. Este método é invocado quando a página do painel é desativada, ou seja, desativada ou excluída, ou quando o widget é excluído da página do painel.

Observe que, antes da invocação do método onDeactivate(), o widget está no estado ativo (WIDGET_STATE_ACTIVE). Após a invocação bem-sucedida, o widget transita para o estado inativo (WIDGET_STATE_INACTIVE).

Exemplo:

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

O método onDestroy() executa tarefas de limpeza antes que o widget seja excluído do painel, o que pode incluir o fechamento de uma conexão com o banco de dados estabelecida durante a inicialização do widget, a limpeza de dados temporários para liberar memória do sistema e evitar vazamentos de recursos, o cancelamento do registro de ouvintes de eventos relacionados a eventos de redimensionamento ou cliques em botões para evitar manipulação desnecessária de eventos e vazamentos de memória, etc. Este método é invocado quando o widget ou a página do painel que o contém é excluído.

Observe que, antes da invocação do método onDestroy(), um widget em estado ativo (WIDGET_STATE_ACTIVE) é sempre desativado com a invocação do método onDeactivate().

Exemplo:

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

O método onEdit() define a aparência e o comportamento do widget quando o dashboard entra no modo de edição. Este método é invocado quando o dashboard entra no modo de edição, normalmente quando um usuário interage com o botão Editar do widget ou com o botão Editar dashboard do dashboard.

Exemplo:

onEdit() {
    this._deactivateGraph();
}
Atualizar métodos de processo

Os métodos do processo de atualização do widget são responsáveis por recuperar dados atualizados do servidor Zabbix ou de qualquer outra fonte de dados e exibi-los no widget.

O método promiseUpdate() inicia o processo de atualização de dados recuperando dados, normalmente usando requisições web ou chamadas de API. Este método é invocado quando uma página de dashboard é exibida e periodicamente depois disso, até que a página do dashboard seja trocada para outra página de dashboard.

A seguir está um exemplo da implementação padrão do método promiseUpdate() usado pela maioria dos widgets nativos do Zabbix. Na implementação padrão, o método promiseUpdate() segue um padrão geral para recuperar dados do server. Ele cria um novo objeto Curl com a URL apropriada e parâmetros de requisição, envia uma requisição POST usando o método fetch() com o objeto de dados construído pelo método getUpdateRequestData(), e processa a resposta (ou uma resposta de erro) com processUpdateResponse(response) ou processUpdateErrorResponse(error), respectivamente. Esta implementação é adequada para a maioria dos widgets, pois normalmente recuperam dados em formato JSON e os tratam de maneira 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);
        });
    }

O método getUpdateRequestData() prepara os dados da solicitação para o server para atualizar o widget, reunindo várias propriedades e seus valores correspondentes (identificadores de widget, configurações de filtro, intervalos de tempo, etc.) do estado e da configuração do widget, e construindo um objeto de dados que representa as informações necessárias a serem enviadas ao server na solicitação de atualização. Este método é invocado apenas como parte do método padrão promiseUpdate(), ou seja, durante o processo de atualização do widget.

Implementação padrão:

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

O método processUpdateResponse(response) lida com a resposta recebida do server após a solicitação de atualização e, se o processo de atualização foi bem-sucedido e sem erros, limpa os dados do widget e exibe novos conteúdos com o método setContents(). Este método é invocado apenas como parte do método padrão promiseUpdate(), ou seja, durante o processo de atualização do widget.

Implementação padrão:

processUpdateResponse(response) {
    this._setHeaderName(response.name);

    this._updateMessages(response.messages);
    this._updateInfo(response.info);
    this._updateDebug(response.debug);

    this.setContents(response);
}

O método processUpdateErrorResponse(error) manipula a resposta recebida do server após a solicitação de atualização se a resposta for um erro e exibe a(s) mensagem(ns) de erro. Este método é invocado apenas como parte do método padrão promiseUpdate(), ou seja, durante o processo de atualização do widget.

Implementação padrão:

processUpdateErrorResponse(error) {
    this._updateMessages(error.messages, error.title);
}

O método setContents(response) exibe o conteúdo do widget se o processo de atualização do widget foi bem-sucedido e sem erros, o que pode incluir manipulação de elementos DOM, atualização de componentes da interface do usuário, aplicação de estilos ou formatação, etc. Este método é invocado apenas como parte do método padrão processUpdateResponse(response), ou seja, durante o processo de tratamento da resposta recebida do server após a solicitação de atualização.

Implementação padrão:

setContents(response) {
    this._body.innerHTML = response.body ?? '';
}
Métodos de modificação de apresentação

Os métodos de modificação da apresentação do widget são responsáveis por modificar a aparência do widget.

O método onResize() é responsável por ajustar os elementos visuais do widget para acomodar o novo tamanho do widget, o que pode incluir o rearranjo de elementos, ajuste das dimensões dos elementos, truncamento de texto, implementação de carregamento preguiçoso para melhorar a capacidade de resposta durante o redimensionamento, etc. Este método é invocado quando o widget é redimensionado, por exemplo, quando o usuário redimensiona manualmente o widget ou quando a janela do navegador é redimensionada.

Exemplo:

onResize() {
    if (this.getState() === WIDGET_STATE_ACTIVE) {
        this._startUpdating();
    }
}

O método hasPadding() é responsável por aplicar um padding vertical de 8px na parte inferior do widget quando ele está configurado para exibir seu cabeçalho. Este método é invocado quando a página do dashboard é ativada, ou seja, quando ela se torna a página exibida na interface do usuário.

Implementação padrão:

hasPadding() {
    return this.getViewMode() !== ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER;
}

Para alguns widgets, é necessário usar todo o espaço disponível do widget para configurar, por exemplo, uma cor de fundo personalizada. A seguir está um exemplo da implementação do método hasPadding() usado no widget nativo do Zabbix Valor do item.

hasPadding() {
    return false;
}