Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'ui/js/class.widget.iterator.js')
-rw-r--r--ui/js/class.widget.iterator.js594
1 files changed, 594 insertions, 0 deletions
diff --git a/ui/js/class.widget.iterator.js b/ui/js/class.widget.iterator.js
new file mode 100644
index 00000000000..d1c8db7131b
--- /dev/null
+++ b/ui/js/class.widget.iterator.js
@@ -0,0 +1,594 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2022 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+class CWidgetIterator extends CWidget {
+
+ _init() {
+ super._init();
+
+ this._css_classes = {
+ ...this._css_classes,
+ actions: 'dashboard-grid-iterator-actions',
+ container: 'dashboard-grid-iterator-container',
+ content: 'dashboard-grid-iterator-content',
+ focus: 'dashboard-grid-iterator-focus',
+ head: 'dashboard-grid-iterator-head',
+ hidden_header: 'dashboard-grid-iterator-hidden-header',
+ mask: 'dashboard-grid-iterator-mask',
+ root: 'dashboard-grid-iterator'
+ };
+
+ this._widgets = new Map();
+ this._placeholders = [];
+
+ this._grid_pos = [];
+
+ this._has_contents = false;
+ this._has_alt_content = false;
+
+ this._page = 1;
+ this._page_count = 1;
+ }
+
+ _doDeactivate() {
+ if (this._has_contents) {
+ for (const widget of this._widgets.values()) {
+ if (widget._state === WIDGET_STATE_ACTIVE) {
+ widget.deactivate();
+ this._removeWidgetEventListeners(widget);
+ }
+ }
+ }
+
+ super._doDeactivate();
+ }
+
+ getNumHeaderLines() {
+ if (this._view_mode == ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER
+ && this._target.classList.contains('iterator-double-header')) {
+ return 2;
+ }
+
+ return 1;
+ }
+
+ resize() {
+ super.resize();
+
+ if (this._has_contents && !this._isTooSmall()) {
+ this._updatePager();
+ }
+
+ if (this._has_alt_content || this._isTooSmall() || this._isResizing()) {
+ return;
+ }
+
+ for (const widget of this._widgets.values()) {
+ widget.resize();
+ }
+ }
+
+ _setViewMode(view_mode) {
+ super._setViewMode(view_mode);
+
+ for (const widget of this._widgets.values()) {
+ widget._setViewMode(view_mode);
+ }
+ }
+
+ _setFields(fields) {
+ const num_columns = this._getColumnsField();
+ const num_rows = this._getRowsField();
+
+ super._setFields(fields);
+
+ if (num_columns != this._getColumnsField() || num_rows != this._getRowsField()) {
+ this._clearContents();
+ this._clearAltContent();
+
+ this._updateTooSmallState();
+
+ if (this._isTooSmall()) {
+ if (this._state === WIDGET_STATE_ACTIVE) {
+ this._stopUpdating();
+ }
+ }
+
+ this._updateGridPositions();
+ }
+ }
+
+ _startUpdating(delay_sec = 0, {do_update_once = null} = {}) {
+ if (this._isTooSmall()) {
+ return;
+ }
+
+ if (this._isResizing()) {
+ if (this._has_contents || this._has_alt_content) {
+ return;
+ }
+ }
+
+ super._startUpdating(delay_sec, {do_update_once});
+ }
+
+ setPos(pos, {is_managed = false} = {}) {
+ const original_pos = {...this._pos};
+
+ super.setPos(pos, {is_managed});
+
+ if (this._grid_pos.length > 0
+ && this._pos.width == original_pos.width && this._pos.height == original_pos.height) {
+ return;
+ }
+
+ const was_too_small = this._isTooSmall();
+
+ this._updateTooSmallState();
+
+ if (this._isTooSmall()) {
+ if (this._state === WIDGET_STATE_ACTIVE && !was_too_small) {
+ this._stopUpdating();
+ }
+
+ return;
+ }
+
+ if (this._has_alt_content) {
+ return;
+ }
+
+ this._updateGridPositions();
+
+ if (!this._has_contents) {
+ if (this._state === WIDGET_STATE_ACTIVE && was_too_small) {
+ this._startUpdating();
+ }
+
+ return;
+ }
+
+ const widgets = [...this._widgets.values()];
+
+ for (let index = 0; index < this._grid_pos.length; index++) {
+ if (index < this._widgets.size) {
+ const widget = widgets[index];
+ const widget_pos = widget.getPos();
+
+ this._alignToGrid(widget.getView(), index);
+
+ if (widget_pos.width != this._grid_pos[index].width
+ || widget_pos.height != this._grid_pos[index].height) {
+ widget.setPos(this._grid_pos[index], {is_managed: true});
+ widget.resize();
+ }
+ }
+ else {
+ this._alignToGrid(this._placeholders[index - this._widgets.size], index);
+ }
+ }
+
+ if (this._state === WIDGET_STATE_ACTIVE) {
+ this._startUpdating();
+ }
+ }
+
+ _setContents(response) {
+ this._updatePager(response.page, response.page_count);
+
+ let response_widgetids = [];
+
+ for (const data of response.children) {
+ response_widgetids.push(data.widgetid);
+ }
+
+ for (const widgetid of this._widgets.keys()) {
+ if (!response_widgetids.includes(widgetid)) {
+ this._deleteWidget(widgetid);
+ }
+ }
+
+ for (const [index, data] of Object.entries(response.children)) {
+ const widget = this._widgets.has(data.widgetid) ? this._widgets.get(data.widgetid) : this._addWidget(data);
+
+ this._alignToGrid(widget.getView(), index);
+ widget.setPos(this._grid_pos[index], {is_managed: true});
+
+ if (widget.getState() !== WIDGET_STATE_ACTIVE) {
+ widget.activate();
+ this._addWidgetEventListeners(widget);
+ }
+ else {
+ this._updateWidget(widget);
+ }
+ }
+
+ this._appendPlaceholders();
+
+ this._has_contents = true;
+ }
+
+ _clearContents() {
+ this._deleteWidgets();
+ this._deletePlaceholders();
+ this._updatePager(1, 1);
+
+ this._has_contents = false;
+ }
+
+ _setAltContent({body = null, messages = null} = {}) {
+ this._clearAltContent();
+
+ const alt_content = document.createElement('div');
+
+ if (messages !== null) {
+ const message_box = makeMessageBox('bad', messages)[0];
+
+ alt_content.appendChild(message_box);
+ }
+
+ if (body !== null) {
+ alt_content.insertAdjacentHTML('beforeend', body);
+ }
+
+ this._content_body.appendChild(alt_content);
+ this._target.classList.add('iterator-alt-content');
+
+ this._has_alt_content = true;
+ }
+
+ _clearAltContent() {
+ if (this._has_alt_content) {
+ this._has_alt_content = false;
+
+ this._target.classList.remove('iterator-alt-content');
+ this._content_body.innerHTML = '';
+ }
+ }
+
+ _setErrorContents({error}) {
+ this._clearContents();
+
+ this._setAltContent({
+ messages: error.messages
+ });
+ }
+
+ _getUpdateRequestData() {
+ const request_data = super._getUpdateRequestData();
+
+ request_data.page = this._page;
+
+ return request_data;
+ }
+
+ _processUpdateResponse(response) {
+ if ('name' in response) {
+ this._setHeaderName(response.name);
+ }
+
+ if ('body' in response || 'messages' in response) {
+ this._clearContents();
+
+ this._setAltContent({
+ body: response.body ?? null,
+ messages: response.messages ?? null
+ });
+ }
+ else {
+ this._clearAltContent();
+ this._setContents(response);
+ }
+ }
+
+ _addWidget(data) {
+ const widget = this._createWidget(data);
+
+ widget.start();
+
+ this._content_body.append(widget.getView());
+
+ this._truncateWidget(widget);
+
+ this._widgets.set(data.widgetid, widget);
+
+ return widget;
+ }
+
+ _createWidget(data) {
+ return new (eval(data.defaults.js_class))({
+ type: data.type,
+ name: data.name,
+ view_mode: this._view_mode,
+ fields: data.fields,
+ defaults: data.defaults,
+ widgetid: data.widgetid,
+ is_new: false,
+ rf_rate: 0,
+ dashboard: this._dashboard,
+ dashboard_page: this._dashboard_page,
+ cell_width: this._cell_width,
+ cell_height: this._cell_height,
+ is_editable: false,
+ is_edit_mode: false,
+ can_edit_dashboards: this._can_edit_dashboards,
+ time_period: this._time_period,
+ dynamic_hostid: this._dynamic_hostid,
+ unique_id: this._createUniqueId()
+ });
+ }
+
+ _truncateWidget(widget) {
+ widget._actions.style.display = 'none';
+ }
+
+ _deleteWidget(widgetid) {
+ const widget = this._widgets.get(widgetid);
+
+ this._content_body.removeChild(widget.getView());
+
+ this._removeWidgetEventListeners(widget);
+ widget.destroy();
+
+ this._widgets.delete(widgetid);
+ }
+
+ _updateWidget(widget) {
+ widget._startUpdating();
+ }
+
+ _deleteWidgets() {
+ for (const widgetid of this._widgets.keys()) {
+ this._deleteWidget(widgetid);
+ }
+ }
+
+ _addWidgetEventListeners(widget) {
+ widget
+ .on(WIDGET_EVENT_ENTER, this._events.widgetEnter)
+ .on(WIDGET_EVENT_LEAVE, this._events.widgetLeave);
+ }
+
+ _removeWidgetEventListeners(widget) {
+ widget
+ .off(WIDGET_EVENT_ENTER, this._events.widgetEnter)
+ .off(WIDGET_EVENT_LEAVE, this._events.widgetLeave);
+ }
+
+ _deletePlaceholders() {
+ for (const placeholder of this._placeholders) {
+ placeholder.remove();
+ }
+
+ this._placeholders = [];
+ }
+
+ _appendPlaceholders() {
+ this._deletePlaceholders();
+
+ const placeholder = document.createElement('div');
+
+ placeholder.appendChild(document.createElement('div'));
+ placeholder.classList.add('dashboard-grid-iterator-placeholder');
+
+ for (let index = this._widgets.size; index < this._grid_pos.length; index++) {
+ const placeholder_clone = placeholder.cloneNode(true);
+
+ this._content_body.appendChild(placeholder_clone);
+ this._alignToGrid(placeholder_clone, index);
+
+ this._placeholders.push(placeholder_clone);
+ }
+ }
+
+ _isTooSmall() {
+ return this._target.classList.contains('iterator-too-small');
+ }
+
+ _updateTooSmallState() {
+ const is_too_small = this._pos.width < this._getColumnsField()
+ || this._pos.height < this._getRowsField() * this._min_rows;
+
+ this._target.classList.toggle('iterator-too-small', is_too_small);
+ }
+
+ _updateGridPositions() {
+ this._grid_pos = [];
+
+ const num_columns = this._getColumnsField();
+ const num_rows = this._getRowsField();
+
+ for (let index = 0, count = num_columns * num_rows; index < count; index++) {
+ const cell_column = index % num_columns;
+ const cell_row = Math.floor(index / num_columns);
+ const cell_width_min = Math.floor(this._pos.width / num_columns);
+ const cell_height_min = Math.floor(this._pos.height / num_rows);
+
+ const num_enlarged_columns = this._pos.width - cell_width_min * num_columns;
+ const num_enlarged_rows = this._pos.height - cell_height_min * num_rows;
+
+ this._grid_pos.push({
+ x: cell_column * cell_width_min + Math.min(cell_column, num_enlarged_columns),
+ y: cell_row * cell_height_min + Math.min(cell_row, num_enlarged_rows),
+ width: cell_width_min + (cell_column < num_enlarged_columns ? 1 : 0),
+ height: cell_height_min + (cell_row < num_enlarged_rows ? 1 : 0)
+ });
+ }
+ }
+
+ _alignToGrid(element, grid_index) {
+ const pos = this._grid_pos[grid_index];
+
+ element.style.left = `${pos.x / this._pos.width * 100}%`;
+ element.style.top = `${pos.y * this._cell_height}px`;
+ element.style.width = `${pos.width / this._pos.width * 100}%`;
+ element.style.height =`${pos.height * this._cell_height}px`;
+ }
+
+ _updatePager(page = this._page, page_count = this._page_count) {
+ this._page = page;
+ this._page_count = page_count;
+
+ if (this._page_count == 1) {
+ this._content_header.classList.remove('pager-visible');
+
+ return;
+ }
+
+ this._pager_stats.textContent = `${this._page} / ${this._page_count}`;
+
+ this._content_header.classList.add('pager-visible');
+
+ const width_available = this._content_header.clientWidth
+ - this._pager.offsetWidth - this._actions.offsetWidth
+ - parseFloat(getComputedStyle(this._content_header).paddingLeft)
+ - parseFloat(getComputedStyle(this._content_header).paddingRight)
+ - parseFloat(getComputedStyle(this._pager).marginLeft)
+ - parseFloat(getComputedStyle(this._pager).marginRight);
+
+ this._content_header.classList.toggle('pager-visible', width_available >= 0);
+ }
+
+ _getColumnsField() {
+ return this._fields.columns !== undefined ? this._fields.columns : 2;
+ }
+
+ _getRowsField() {
+ return this._fields.rows !== undefined ? this._fields.rows : 1;
+ }
+
+ _createUniqueId() {
+ let unique_ids = [];
+
+ for (const widget of this._widgets.values()) {
+ unique_ids.push(widget.getUniqueId());
+ }
+
+ let index = 0;
+
+ while (unique_ids.includes(`${this._unique_id}-${index}`)) {
+ index++;
+ }
+
+ return `${this._unique_id}-${index}`;
+ }
+
+ _makeView() {
+ super._makeView();
+
+ this._target.style.minWidth = null;
+ this._target.style.minHeight = null;
+
+ this._pager = document.createElement('div');
+ this._pager.classList.add('dashboard-grid-iterator-pager');
+
+ this._button_previous_page = document.createElement('button');
+ this._button_previous_page.type = 'button';
+ this._button_previous_page.title = t('Previous page');
+ this._button_previous_page.classList.add('btn-iterator-page-previous');
+ this._pager.appendChild(this._button_previous_page);
+
+ this._pager_stats = document.createElement('span');
+ this._pager_stats.classList.add('dashboard-grid-iterator-pager-info');
+ this._pager.appendChild(this._pager_stats);
+
+ this._button_next_page = document.createElement('button');
+ this._button_next_page.type = 'button';
+ this._button_next_page.title = t('Next page');
+ this._button_next_page.classList.add('btn-iterator-page-next');
+ this._pager.appendChild(this._button_next_page);
+
+ this._content_header.insertBefore(this._pager, this._actions);
+
+ this._too_small = document.createElement('div');
+ this._too_small.classList.add('dashboard-grid-iterator-too-small');
+
+ const too_small_content = document.createElement('div');
+
+ too_small_content.textContent = t('Widget is too small for the specified number of columns and rows.');
+ this._too_small.appendChild(too_small_content);
+
+ this._container.appendChild(this._too_small);
+ }
+
+ _registerEvents() {
+ super._registerEvents();
+
+ this._events = {
+ ...this._events,
+
+ widgetEnter: (e) => {
+ const widget = e.detail.target;
+
+ if (!widget.isEntered()) {
+ widget.enter();
+
+ if (this._view_mode == ZBX_WIDGET_VIEW_MODE_HIDDEN_HEADER) {
+ this._target.classList.toggle('iterator-double-header', widget.getPos().y == 0);
+ }
+ }
+ },
+
+ widgetLeave: (e) => {
+ const widget = e.detail.target;
+
+ if (widget.isEntered()) {
+ widget.leave();
+ }
+ },
+
+ iteratorEnter: (e) => {
+ if (e.target.closest('.dashboard-grid-iterator-placeholder') !== null) {
+ this._target.classList.remove('iterator-double-header');
+ }
+ },
+
+ previousPageClick: () => {
+ if (this._page > 1) {
+ this._page--;
+ this._startUpdating();
+ }
+ },
+
+ nextPageClick: () => {
+ if (this._page < this._page_count) {
+ this._page++;
+ this._startUpdating();
+ }
+ }
+ };
+ }
+
+ _activateEvents() {
+ super._activateEvents();
+
+ this._target.addEventListener('mousemove', this._events.iteratorEnter);
+ this._button_previous_page.addEventListener('click', this._events.previousPageClick);
+ this._button_next_page.addEventListener('click', this._events.nextPageClick);
+ }
+
+ _deactivateEvents() {
+ super._deactivateEvents();
+
+ this._target.removeEventListener('mousemove', this._events.iteratorEnter);
+ this._button_previous_page.removeEventListener('click', this._events.previousPageClick);
+ this._button_next_page.removeEventListener('click', this._events.nextPageClick);
+ }
+}