Il s'agit d'un didacticiel étape par étape qui montre comment créer un simple widget de tableau de bord.
La version minimale requise de Zabbix pour ce tutoriel est 6.4.4.
Vous pouvez télécharger tous les fichiers de ce widget sous forme d'archive ZIP : lesson_gauge_chart.zip.
Au cours de ce didacticiel, vous allez d'abord créer un basic "Hello, world!" widget, puis convertissez-le en un widget plus avancé qui affiche la valeur d'un élément sous forme de graphique à jauge. Voici à quoi ressemblera le widget fini :
Dans cette section, vous apprendrez comment créer les éléments de widget minimum requis et ajouter un nouveau widget à l'interface Zabbix.
Tous les widgets personnalisés sont traités comme des modules externes et doivent être ajoutés au répertoire modules de votre installation Zabbix (par exemple, zabbix/ui/modules). Le répertoire zabbix/ui/widgets est réservé aux widgets intégrés de Zabbix et est mis à jour avec l'interface utilisateur de Zabbix.
ui/modules/lesson_gauge_chart/manifest.json
{
"manifest_version": 2.0,
"id": "lesson_gauge_chart",
"type": "widget",
"name": "Tableau de jauge",
"namespace": "LessonGaugeChart",
"version": "1.0",
"author": "Zabbix SIA"
}
Le fichier view du widget doit se trouver dans le répertoire views (pour ce tutoriel, ui/modules/lesson_gauge_chart/views/). Si le fichier porte le nom par défaut widget.view.php, vous n'avez pas besoin de l'enregistrer dans le fichier manifest.json. Si le fichier a un nom différent, spécifiez-le dans la section actions/widget.lesson_gauge_chart.view du fichier manifest.json.
Créez un répertoire views dans le répertoire lesson_gauge_chart.
Créez un fichier widget.view.php dans le répertoire views.
ui/modules/lesson_gauge_chart/views/widget.view.php
<?php
/**
* Vue du widget de graphique de jauge.
*
* @var CView $this
* @var array $data
*/
(new CWidgetView($data))
->addItem(
new CTag('h1', true, 'Hello, world!')
)
->show();
Dans cette section, vous apprendrez comment ajouter un champ de configuration de widget et afficher la valeur saisie dans la vue du widget sous forme de texte.
La configuration du widget se compose d'un formulaire (Zabbix\Widgets\CWidgetForm) et d'une vue de formulaire de widget (widget.edit.php). Pour ajouter des champs (Zabbix\Widgets\CWidgetField), vous devez créer une classe WidgetForm, qui étendra Zabbix\Widgets\CWidgetForm.
Le formulaire contient l'ensemble des champs (Zabbix\Widgets\CWidgetField) de différents types, qui sont utilisés pour valider les valeurs saisies par l'utilisateur. Le champ de formulaire (Zabbix\Widgets\CWidgetField) pour chaque type d'élément d'entrée convertit la valeur dans un format unique pour la stocker dans la base de données.
Le fichier form du widget doit être situé dans le répertoire includes (pour ce didacticiel, ui/modules/lesson_gauge_chart/includes/). Si le fichier porte le nom par défaut WidgetForm.php, vous n'avez pas besoin de l'enregistrer dans le fichier manifest.json. Si le fichier a un nom différent, spécifiez-le dans la section widget/form_class du fichier manifest.json.
Créez un nouveau répertoire includes dans le répertoire lesson_gauge_chart.
Créez un fichier WidgetForm.php dans le répertoire includes.
ui/modules/lesson_gauge_chart/includes/WidgetForm.php
<?php
namespace Modules\LessonGaugeChart\Includes;
use Zabbix\Widgets\CWidgetForm;
class WidgetForm extends CWidgetForm {
}
ui/modules/lesson_gauge_chart/includes/WidgetForm.php
<?php
namespace Modules\LessonGaugeChart\Include
use Zabbix\Widgets\CWidgetForm;
use Zabbix\Widgets\Fields\CWidgetFieldTextBox;
class WidgetForm extends CWidgetForm {
public function addFields(): self {
return $this
->addField(
new CWidgetFieldTextBox('description', _('Description'))
);
}
}
ui/modules/lesson_gauge_chart/views/widget.edit.php
<?php
/**
* Vue du formulaire du widget de graphique de jauge.
*
* @var CView $this
* @var array $data
*/
(new CWidgetFormView($data))
->addField(
new CWidgetFieldTextBoxView($data['fields']['description'])
)
->show();
Accédez au tableau de bord et cliquez sur l'icône d'engrenage dans le widget pour ouvrir le formulaire de configuration du widget.
Le formulaire de configuration du widget contient désormais un nouveau champ de texte Description. Saisissez n'importe quelle valeur, par exemple Description du graphique de jauge.
Pour que la nouvelle description apparaisse dans le widget, la valeur du champ Description doit être récupérée de la base de données et transmise à la vue du widget. Pour cela, vous devez créer une classe d'action.
Créez un nouveau répertoire actions dans le répertoire lesson_gauge_chart.
Créez un fichier WidgetView.php dans le répertoire actions. La classe d'action WidgetView étendra la classe CControllerDashboardWidgetView.
Les valeurs des champs de configuration du widget sont stockées dans la propriété $fields_values de la classe d'action.
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()
]
]));
}
}
ui/modules/lesson_gauge_chart/manifest.json
{
"manifest_version": 2.0,
"id": "lesson_gauge_chart",
"type": "widget",
"name": "Tableau de jauge",
"namespace": "LessonGaugeChart",
"version": "1.0",
"auteur": "Zabbix SIA",
"Actions": {
"widget.lesson_gauge_chart.view": {
"class": "WidgetView"
}
}
}
ui/modules/lesson_gauge_chart/views/widget.view.php
<?php
/**
* Vue du widget de graphique de jauge.
*
* @var CView $this
* @var array $data
*/
(new CWidgetView($data))
->addItem(
new CTag('h1', true, $data['description'])
)
->show();
This widget should show the last value of an item of user's choice. For that, you need to add the ability to select items in the widget configuration.
In this section, you will learn how to add item selection field to the widget form and add the visual part of this field to the configuration view. Then, the widget controller will be able to retrieve item data and its value via an API request. Once received, the value can be displayed in the widget view.
ui/modules/lesson_gauge_chart/includes/WidgetForm.php
<?php
namespace Modules\LessonGaugeChart\Includes;
use Zabbix\Widgets\CWidgetField;
use Zabbix\Widgets\CWidgetForm;
use Zabbix\Widgets\Fields\CWidgetFieldMultiSelectItem;
use Zabbix\Widgets\Fields\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'))
);
}
}
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'], $data['captions']['ms']['items']['itemid'])
)
->addField(
new CWidgetFieldTextBoxView($data['fields']['description'])
)
->show();
Return to the Dashboard and press on the gear icon to open widget configuration.
The widget configuration now contains a new input field Item. Select the host Zabbix server and the item Load average (1m avg).
Press Apply in the widget configuration. Then press Save changes to save the dashboard.
Open and modify /actions/WidgetView.php.
From now on, the item ID will be available in the widget controller in $this->fields_values['itemid']. The doAction() controller method collects the item data (name, value type, units) using the API method item.get and item last value using the API method history.get.
ui/modules/lesson_gauge_chart/actions/WidgetView.php
<?php
namespace Modules\LessonGaugeChart\Actions;
use API;
use CControllerDashboardWidgetView;
use 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()
]
]));
}
}
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();
In this section, you will learn how to add Javascript elements to the widget.
You will add:
JavaScript will be responsible for hiding optional fields behind the Advanced configuration checkbox and initializing the colorpicker in the configuration view. You can add it to the same directory as the configuration view.
Since the JavaScript for configuration view should be loaded with the form, you will need to include it into widget.edit.php as shown in the next steps.
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 ?>;
}
};
The Widget class will extend the CWidget base class to add/override the default widget settings. In this case, these are translations. JavaScript, provided above, displays the string "No data" in case of missing data. The "No data" string is present in the Zabbix UI translation files.
If there are any widget constants, it is recommended to also specify them in the Widget class.
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')
]
];
}
}
ui/modules/lesson_gauge_chart/includes/WidgetForm.php
<?php
namespace Modules\LessonGaugeChart\Includes;
use Modules\LessonGaugeChart\Widget;
use Zabbix\Widgets\CWidgetField;
use Zabbix\Widgets\CWidgetForm;
use Zabbix\Widgets\Fields\CWidgetFieldCheckBox;
use Zabbix\Widgets\Fields\CWidgetFieldColor;
use Zabbix\Widgets\Fields\CWidgetFieldMultiSelectItem;
use Zabbix\Widgets\Fields\CWidgetFieldNumericBox;
use Zabbix\Widgets\Fields\CWidgetFieldSelect;
use Zabbix\Widgets\Fields\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('666666')
)
->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'))
);
}
}
The addField() method of the CWidgetFormView class takes a CSS class string as the second parameter. Add the js-advanced-configuration string to those fields and their labels, which should be hidden if Advanced configuration is not selected.
To add JavaScript file to the configuration view, use the includeJsFile() method. To add inline JavaScript, use the addJavaScript() method.
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']['ms']['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();
Press Apply in the widget configuration. Then press Save changes to save the dashboard.
Open actions/WidgetView.php and update the controller.
The $this->fields_values property now contain the values of all the Advanced configuration fields. Finalize the controller to enable passing the configuration and selected item value to the widget view.
ui/modules/lesson_gauge_chart/actions/WidgetView.php
<?php
namespace Modules\LessonGaugeChart\Actions;
use API;
use CControllerDashboardWidgetView;
use 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()
]
]));
}
}
You need to create a container for the gauge chart, which you will draw in the next steps, and a container for the description.
To pass values to JavaScript as a JSON object, use the setVar() method.
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();
Create a directory assets in the lesson_gauge_chart. This directory will be used for storing Javascript, CSS and potentially any other assets, such as fonts or images.
For widget view JavaScript, create a directory js inside the assets directory.
Create widget.js file in the assets/js directory.
This JavaScript widget class will handle updating the data, resizing the widget, and drawing the gauge chart. Learn more about the JavaScript methods of the CWidget class {link to documentation}
Since this JavaScript is required for the widget view, it should be loaded with the dashboard page. To enable JavaScript loading, you will need to update assets/js and js_class parameters of manifest.json as shown in the next step.
ui/modules/lesson_gauge_chart/assets/js/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);
}
}
WidgetLessonGaugeChart class will now be automatically loaded with the 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 SIA",
"actions": {
"widget.lesson_gauge_chart.view": {
"class": "WidgetView"
}
},
"widget": {
"js_class": "WidgetLessonGaugeChart"
},
"assets": {
"js": ["widget.js"]
}
}
In this section you will learn how to add custom CSS styles to make the widget look more appealing.
For widget styles, create a new directory css inside the assets directory.
Add widget.css file to the assets/css. To style widget elements, use the selector div.dashboard-widget-{widget id}. To configure CSS for the whole widget, use the 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;
}
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": {
"css": ["widget.css"],
"js": ["widget.js"]
}
}