[comment]: # aside:2

[comment]: # ({04e47dfc-fa26c138})
# Направите виџет (водич)

[comment]: # ({/04e47dfc-fa26c138})

[comment]: # ({14b8f451-386f5763})
Ово је водич корак по корак који показује како да направите једноставан Zabbix кориснички интерфејс модул.Све датотеке овог модула можете преузети као ZIP  архиву: [MyAddress.zip](../../../../assets/en/devel/modules/examples/MyAddress.zip).

[comment]: # ({/14b8f451-386f5763})

[comment]: # ({6bed8352-dead8e1e})
## Шта ћеш изградити

Током овог туторијала, прво ћете направити [basic](#part-i---hello-world) "Здраво, свете!" виџет, а затим га конвертујте у [more advanced](#part-ii---gauge-chart) виџет који приказује вредност ставке као графикон мерача.
Ево како ће готови виџет изгледати:

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_finished.png){width="600"}

[comment]: # ({/6bed8352-dead8e1e})

[comment]: # ({156649db-03fc601d})
## Part I - "Hello, world!" 

У овом одељку ћете научити како да креирате минимално потребне елементе виџета и додате нови виџет на Zabbix кориснички интерфејс.

[comment]: # ({/156649db-03fc601d})

[comment]: # ({33e23fc9-ac51379a})
### Додајте празан виџет у Zabbix кориснички интерфејс

1. Креирајте директоријум *lesson_gauge_chart* у директоријуму *modules* ваше Zabbix инсталације корисничког интерфејса (на пример, *zabbix/ui/modules*).

::: noteclassic
Сви прилагођени виџети се третирају као спољни модули и морају се додати у директоријум *modules* ваше Zabbix инсталације корисничког интерфејса (на пример, *zabbix/ui/modules*).
Директоријум *zabbix/ui/widgets* је резервисан за Zabbix уграђене виџете и ажурира се заједно са Zabbix корисничким интерфејсом.
:::

2. Креирајте датотеку *manifest.json* са основним метаподацима виџета (погледајте опис подржаних [параметара](../file_structure/manifest)).

**ui/modules/lesson_gauge_chart/manifest.json**

```json

{
    "manifest_version": 2.0,
    "id": "lesson_gauge_chart",
    "type": "widget",
    "name": "Gauge chart",
    "namespace": "LessonGaugeChart",
    "version": "1.1",
    "author": "Zabbix"
}
```

3. У Zabbix корисничком интерфејсу идите на *Администрација → Опште → Модули* одељак и кликните на дугме *Скенирај директоријум*.

![](../../../../assets/en/devel/modules/tutorials/widget/scan_dir.png)

4. Пронађите нови модул *Gauge chart* на листи и кликните на хипервезу "Онемогућено" да бисте променили статус модула из "Онемогућено" у "Омогућено" (ако модул није наведен, погледајте одељак [решавање проблема](/manual/extensions/frontendmodules#installation)).

![](../../../../assets/en/devel/modules/tutorials/widget/widget_register.png){width="600"}

5. Отворите контролну таблу, пребаците је у режим за уређивање и додајте нови виџет. У пољу *Тип* изаберите "Gauge chart".

![](../../../../assets/en/devel/modules/tutorials/widget/widget_add.png){width="600"}

6. У овом тренутку, конфигурација виџета *Gauge chart* садржи само уобичајена поља виџета *Назив* и *Интервал освежавања*.
Кликните на *Додај* да додате виџет на контролну таблу.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_b.png){width="600"}

7. Празан виџет би требало да се појави на контролној табли. Кликните на *Сачувај промене* у горњем десном углу да бисте сачували контролну таблу.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_blank_b.png){width="600"}

[comment]: # ({/33e23fc9-ac51379a})

[comment]: # ({6ca1b1e7-a953cd01})
### Додајте приказ виџета

:::noteclassic
Датотека **view** виџета треба да се налази у директоријуму *views* (за овај водич, *ui/modules/lesson_gauge_chart/views/*).
Ако датотека има подразумевано име *widget.view.php*, не морате да је региструјете у датотеци *manifest.json*.
Ако датотека има другачије име, наведите га у одељку *actions/widget.lesson_gauge_chart.view* датотеке [manifest.json](devel/modules/file_structure/manifest).
:::

1. Креирајте директоријум *views* у директоријуму *lesson_gauge_chart*.

2. Креирајте датотеку *widget.view.php* у директоријуму *views*.

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

```php
<?php

/**
 * Приказ виџета мерача.
 *
 * @var CView $this
 * @var array $data
 */

(new CWidgetView($data))
    ->addItem(new CTag('h1', true, 'Hello, world!')
    )
    ->show();
```

3. Освежите контролну таблу. Виџет *Gauge chart* сада приказује "Здраво, свете!".

![](../../../../assets/en/devel/modules/tutorials/widget/widget_hello_world.png){width="600"}

[comment]: # ({/6ca1b1e7-a953cd01})

[comment]: # ({f5b50cf9-b89998cf})
## Part II - Табела мерача

[comment]: # ({/f5b50cf9-b89998cf})

[comment]: # ({d1da3c35-b23d5e39})
### Додајте подешавања у приказ конфигурације и користите их у приказу виџета

У овом одељку ћете научити како да додате поље за конфигурацију виџета и прикажете унету вредност у приказу виџета као текст.

Конфигурација виџета се састоји од обрасца (*Zabbix\\Widgets\\CWidgetForm*) и приказа обрасца виџета (*widget.edit.php*).
Да бисте додали поља (*Zabbix\\Widgets\\CWidgetField*), потребно је да креирате класу *WidgetForm*, која ће проширити *Zabbix\\Widgets\\CWidgetForm*.

Образац садржи скуп поља (*Zabbix\\Widgets\\CWidgetField*) различитих типова, који се користе за проверу вредности које је унео корисник. Поље обрасца (*Zabbix\\Widgets\\CWidgetField*) за сваки тип улазног елемента конвертује вредност у један формат да би је ускладиштио у бази података.

:::noteclassic
Датотека **form*** виџета треба да се налази у директоријуму * ncludes* (за овај водич, *ui/modules/lesson_gauge_chart/includes/*).
Ако датотека има подразумевано име *WidgetForm.php*, не морате да је региструјете у датотеци *manifest.json*.
Ако датотека има другачије име, наведите га у одељку *widget/form_class* датотеке [manifest.json](devel/modules/file_structure/manifest).
:::

1. Креирајте нови директоријум *includes* у директоријуму *lesson_gauge_chart*.

2. Креирајте датотеку *WidgetForm.php* у директоријуму * includes*.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Zabbix\Widgets\CWidgetForm;

class WidgetForm extends CWidgetForm {
}
```

3. Додајте поље *Опис* у образац за конфигурацију виџета.
Ово је обично текстуално поље у које корисник може да унесе било који скуп карактера.
За то можете користити класу *CWidgetFieldTextBox*.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

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

4. У директоријуму *views* креирајте датотеку приказа конфигурације виџета *widget.edit.php* и додајте приказ за ново поље *Description*. За класу поља *CWidgetFieldTextBox*, приказ је *CWidgetFieldTextBoxView.*

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

```php
<?php

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

(new CWidgetFormView($data))
    ->addField(
        new CWidgetFieldTextBoxView($data['fields']['description'])
    )
    ->show();
```

5. Идите на контролну таблу и кликните на икону зупчаника у виџету да бисте отворили образац за конфигурацију виџета.

6. Образац за конфигурацију виџета сада садржи ново текстуално поље *Description*.
Унесите било коју вредност, на пример, *Gauge chart description*.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_descr.png){width="600"}

7. Кликните на *Примени* у обрасцу за конфигурацију виџета. Затим кликните на *Сачувај промене* у горњем десном углу да бисте сачували контролну таблу. Имајте на уму да се нови опис нигде не види, а виџет и даље приказује "Здраво, свете!".

Да би се нови опис појавио у виџету, вредност поља *Опис* треба да се преузме из базе података и проследи у приказ виџета.
За то морате да креирате класу акције.

8. Креирајте нови директоријум *actions* у директоријуму *lesson_gauge_chart*.

9. Креирајте датотеку *WidgetView.php* у директоријуму *actions*.
Класа акције *WidgetView* ће проширити класу *CControllerDashboardWidgetView*.

Вредности конфигурационих поља виџета се чувају у својству **$fields_values** класе акције.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

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

10. Отворите *manifest.json* и региструјте *WidgetView* као класу акције у одељку *actions/widget.lesson_gauge_chart.view*.

**ui/modules/lesson_gauge_chart/manifest.json**

```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"
        }
    }
}
```

11. Сада можете да користите вредност поља за опис, садржану у *$data['description']*, у приказу виџета.
Отворите *views/widget.view.php* и замените статички текст "Здраво, свете!" са *$data['description']*.

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

```php
<?php

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

(new CWidgetView($data))
    ->addItem(
        new CTag('h1', true, $data['description'])
    )
    ->show();
```

12. Освежите страницу контролне табле. Сада би требало да видите текст описа виџета уместо "Здраво, светe!".

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_descr.png){width="600"}

[comment]: # ({/d1da3c35-b23d5e39})

[comment]: # ({c52f5522-3f0e28b2})
### Преузимање вредности ставке преко API-ја

Виџет треба да приказује последњу вредност ставке по избору корисника.
За то је потребно да додате могућност избора ставки у конфигурацији виџета.

У овом одељку ћете научити како да додате поље за избор ставке у виџет образац и како да додате визуелни део овог поља у приказ конфигурације.
Затим ће контролер виџета моћи да преузме податке о ставци и њену вредност путем API захтева.
Једном када се прими, вредност се може приказати у приказу виџета.

1. Отворите *includes/WidgetForm.php* и додајте поље *CWidgetFieldMultiSelectItem*.
Ово ће омогућити одабир ставке у обрасцу за конфигурацију.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

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

```
2. Отворите views/widget.edit.php*  и додајте визуелну компоненту поља у приказ конфигурације.

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

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

3. Вратите се на контролну таблу и кликните на икону зупчаника у виџету да бисте отворили образац за конфигурацију виџета.

4. Образац за конфигурацију виџета сада садржи ново поље за унос *Ставка*.
Изаберите домаћина "Zabbix server" и ставку "Просек учитавања (1м прос.)".

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_item.png){width=600}

5. Кликните на *Примени* у обрасцу за конфигурацију виџета. Затим кликните на *Сачувај промене* у горњем десном углу да бисте сачували контролну таблу.

6. Отворите и измените *actions/WidgetView.php*.

Од сада, ID ставке ће бити доступне у контролеру виџета у *$this->fields\_values\['itemid'\]*.
Метод контролера *doAction()* прикупља податке о ставци (име, тип вредности, јединице) користећи API метод *[item.get](/manual/api/reference/item/get)* и последњу вредност ставке користећи API метод *[history.get](/manual/api/reference/history/get)*.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

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

7. Отворите *views/widget.view.php* и додајте вредност ставке у приказ виџета.

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

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

8. Освежите страницу контролне табле. Виџет ће приказати најновију вредност ставке.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_item.png){width="600"}

[comment]: # ({/c52f5522-3f0e28b2})

[comment]: # ({aa1b47ba-8f001ece})
### Додајте напредна подешавања конфигурације у приказ конфигурације

У овом одељку ћете научити како да додате прошириви/склопиви одељак *Напредна конфигурација* са опционим параметрима, као што су боја, минималне и максималне вредности, јединице и поље *Опис* креиране раније.

1. Направите датотеку *Widget.php* у главном директоријуму виџета *lesson_gauge_chart* да бисте креирали нову класу *Widget*.

Класа *Widget* ће проширити основну класу *CWidget* да би додала/заменила подразумевана подешавања виџета (у овом случају - преводе).
JavaScript, наведен испод, приказује стринг "Нема података" у случају да подаци недостају.
Низ "Нема података" је присутан у датотекама за превођење Zabbix корисничког интерфејса.

Ако постоје константе виџета, препоручује се да их наведете и у класи *Widget*.

**ui/modules/lesson_gauge_chart/Widget.php**

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

2. Отворите *includes/WidgetForm.php* и додајте нова поља *Color* (бирач боје), *Min* (нумеричко поље), *Max* (нумеричко поље) и *Units* (селект поље) и дефинишите подразумевану палету боја за бирач боја, тако да се може користити у наредним корацима.

**ui/modules/lesson_gauge_chart/includes/WidgetForm.php**

```php
<?php

namespace Modules\LessonGaugeChart\Includes;

use Modules\LessonGaugeChart\Widget;

use Zabbix\Widgets\{
    CWidgetField,
    CWidgetForm
};

use Zabbix\Widgets\Fields\{
    CWidgetFieldColor,
    CWidgetFieldMultiSelectItem,
    CWidgetFieldNumericBox,
    CWidgetFieldSelect,
    CWidgetFieldTextBox
};

/**
 * Gauge chart widget form.
 */
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'))
            );
    }
}
```

3. Отворите *views/widget.edit.php* и додајте визуелне компоненте поља у приказ конфигурације.

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

```php
<?php

/**
 * Gauge chart widget form view.
 *
 * @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();
```

::: noteclassic
Метода *addField()* класе *CWidgetFormView* узима стринг CSS класе као други параметар.
:::

4. Вратите се на контролну таблу, пребаците се на режим уређивања и кликните на икону зупчаника у виџету да бисте отворили образац за конфигурацију виџета.
Образац за конфигурацију виџета сада садржи нови прошириви/склопиви одељак *Напредна конфигурација*.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced.png){width="600"}

5. Проширите одељак *Напредна конфигурација* да бисте видели додатна поља за конфигурацију виџета.
Имајте на уму да поље *Боја* још нема бирач боја.
То је зато што бирач боја мора бити иницијализован JavaScript-ом, који ће бити додат у следећем одељку - [*Add JavaScript to the widget*](#add-javascript-to-the-widget).

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced_a.png){width="600"}

[comment]: # ({/aa1b47ba-8f001ece})

[comment]: # ({175c9f96-c573cc71})
### Додавање JavaScript-а у виџет

У овом одељку ћете научити како да додате индикатор графикона - направљен помоћу JavaScript-а - који показује да ли је последња вредност нормална или превисока/прениска.

1. Креирајте датотеку *widget.edit.js.php* у директоријуму *views*.

JavaScript ће бити одговоран за иницијализацију бирача боја у приказу конфигурације.

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

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

2. Отворите *views/widget.edit.php* и додајте датотеку *widget.edit.js.php*  са JavaScript-ом у приказ конфигурације. Да бисте то урадили, користите методу *includeJsFile()*. Да бисте додали уграђени  JavaScript, користите методу *addJavaScript()*.

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

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

3. Вратите се на контролну таблу, кликните на икону зупчаника у виџету да бисте отворили образац за конфигурацију виџета. Сада проширите одељак *Напредна конфигурација* да бисте видели иницијализовани бирач боја. Попуните поља са вредностима и изаберите боју за индикатор графикона.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_conf_advanced_b.png){width="600"}

4. Клините на *Примени* у обрасцу за конфигурацију виџета. Затим кликните на *Сачувај промене* у горњем десном углу да бисте сачували контролну таблу.

5. Отворите *actions/WidgetView.php* и ажурирајте контролера.

Својство **$this->fields_values** сада садржи врености свих поља *Advanced configuration*.
Финализујте контролер како бисте омогућили прослеђивање конфигурације и вредности изабране ставке приказу виџета.

**ui/modules/lesson_gauge_chart/actions/WidgetView.php**

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

6. Отворите и измените *views/widget.view.php*.

Морате да креирате контејнер за индикатор грификона, који ћете нацртати у следећим корацима, и контејнер за опис.

Да бисте проследили вредности у JavaScriptu-у као JSON објекат, користите метод *setVar()*.

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

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

7. Креирајте нови директоријум *assets* у директоријуму *lesson_gauge_chart*. Овај директоријум ће се користити за чување JavaScript-а, CSS-а и потенцијално свих других средстава, као што су фонтови или слике.

8. За JavaScript преглед виџета, направите директоријум *js* у *assets* директоријуму.

9. Креирајте датотеку *class.widget.js* у директоријуму *assets/js* .

Ова JavaScript класа виџета ће прошитири основну JavaScript класу свих виџета контролне табле - *CWidget*.

Контролна табла се ослања на исправну имплементацију виџета и саопштава све релевантне информације виџету позивањем одговарајућих Javascript метода.
Контролна табла такође очекује да виџет генерише догађаје када дође до неке интеракције.
Дакле, класа *CWidget*  садржи скуп методе са подразумеваном имплементацијом понашања виџета, које се може прилагодити проширењем класе. 

У овом случају, потребно је нешто прилагођавања, па ће прилагођена логика бити имплементирана за следеће понашање виџета:

-  иницијализација виџета који је одговоран за дефинисање почетног стања виџета (погледајте методу *onInitialize()*);
-  приказивање садржаја виџета (односно, цртање индикатора графикона) ако је процес ажурирања виџета био успешан и без грешака (погледајте методу *processUpdateResponse(response)* и сродне методе *\_resizeChart()* и *\_updatedChart()*)
-  промена величине виџета (погледајте методу *onResize()* и сродну методу *\_resizeChart()*)

За друге аспекте виџета са индикатором графикона, користиће се подразумевана имплементација за понашање виџета.
Да бисте сазнали више о JavaScript методама класе *CWidget*, погледајте: [JavaScript](/devel/modules/widgets/presentation/javascript).

Пошто је овај JavaScript потребан за приказ виџета, требало би да се учита са страницом контролне табле. 
Да бисте омогућили учитавање JavaScript-а, мораћете да ажурирате параметре *assets/js* и *js_class* у ***manifest.json** * датотеци као што је приказано у кораку 10.

**ui/modules/lesson_gauge_chart/assets/js/class.widget.js**

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

10. Отворите *manifest.json* и додајте:

-  име датотеке (*class.widget.js*) у низ у одељку *assets/js*;
-  име класе (*WidgetLessonGaugeChart*) у параметар *js_class* у одељак *widget*.

Класа *WidgetLessonGaugeChart* ће сада бити аутоматски учитана са контролном таблом.

**ui/modules/lesson_gauge_chart/manifest.json**

```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"]
    }
}
```

[comment]: # ({/175c9f96-c573cc71})

[comment]: # ({6ea664c3-71184963})
### Додајте CSS стилове у виџет

У овом одељку ћете научити како да додате прилагођене CSS стилове да би виџет изгледао привлачније.

1. За стилове виџета, направите нови директоријум *css* у директоријуму *assets*.

2. Креирајте датотеку *widget.css* у директоријуму *assets/css*.
Да бисте стилизовали елементе виџета, користите селектор *div.dashboard-widget-{widget id}*.
Да бисте конфигурисали CSS за цео виџет, користите селектор *form.dashboard-widget-{widget id}*

**ui/modules/lesson_gauge_chart/assets/css/widget.css**

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

3. Отворите *manifest.json* и додајте име CSS датотеке (*widget.css**) у низ у одељку *assets/css*.
Ово ће омогућити да се CSS стилови дефинисани у *widget.css** учитају са страницом контролне табле.

**ui/modules/lesson_gauge_chart/manifest.json**

```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"]
    }
}
```

4. Освежите страницу контролне табле да бисте видели готову верзију виџета.

![](../../../../assets/en/devel/modules/tutorials/widget/widget_view_finished.png){width="600"}

[comment]: # ({/6ea664c3-71184963})
