diff options
author | Gregory Chalenko <gregory.chalenko@zabbix.com> | 2020-08-21 12:16:58 +0300 |
---|---|---|
committer | Gregory Chalenko <gregory.chalenko@zabbix.com> | 2020-08-21 12:16:58 +0300 |
commit | 56d9e4451ef8b5f838c4ebebd6e44c88ba963fd4 (patch) | |
tree | a5d35a634c24993831c3967072fb8238df6f313a | |
parent | 6169a6457821219e059a6752c7af7103f1d2475a (diff) |
..F....... [ZBXNEXT-710] draft changes
-rw-r--r-- | ui/app/controllers/CControllerHost.php | 2 | ||||
-rw-r--r-- | ui/app/controllers/CControllerHostView.php | 65 | ||||
-rw-r--r-- | ui/app/controllers/CControllerHostViewRefresh.php | 64 | ||||
-rw-r--r-- | ui/app/controllers/CControllerPopupTabFilterEdit.php | 38 | ||||
-rw-r--r-- | ui/app/views/js/monitoring.host.view.js.php | 2 | ||||
-rw-r--r-- | ui/app/views/js/popup.tabfilter.edit.js.php | 2 | ||||
-rw-r--r-- | ui/app/views/monitoring.host.view.php | 2 | ||||
-rw-r--r-- | ui/include/classes/html/CCheckBoxList.php | 11 | ||||
-rw-r--r-- | ui/include/classes/html/CSeverityCheckBoxList.php | 11 | ||||
-rw-r--r-- | ui/js/class.tabfilter.js | 81 | ||||
-rw-r--r-- | ui/js/class.tabfilteritem.js | 65 |
11 files changed, 180 insertions, 163 deletions
diff --git a/ui/app/controllers/CControllerHost.php b/ui/app/controllers/CControllerHost.php index f135594b070..e6bf596ac97 100644 --- a/ui/app/controllers/CControllerHost.php +++ b/ui/app/controllers/CControllerHost.php @@ -26,7 +26,7 @@ abstract class CControllerHost extends CController { // Filter idx prefix. - const FILTER_IDX = 'web.monitoringhosts'; + const FILTER_IDX = 'web.monitoring.hosts'; // Filter fields default values. const FILTER_FIELDS_DEFAULT = [ diff --git a/ui/app/controllers/CControllerHostView.php b/ui/app/controllers/CControllerHostView.php index 451c2943235..92a6463a3be 100644 --- a/ui/app/controllers/CControllerHostView.php +++ b/ui/app/controllers/CControllerHostView.php @@ -20,10 +20,71 @@ **/ -class CControllerHostView extends CControllerHostViewRefresh { +class CControllerHostView extends CControllerHost { + + protected function init(): void { + $this->disableSIDValidation(); + } + + protected function checkInput(): bool { + $fields = [ + 'name' => 'string', + 'groupids' => 'array_id', + 'ip' => 'string', + 'dns' => 'string', + 'port' => 'string', + 'status' => 'in -1,'.HOST_STATUS_MONITORED.','.HOST_STATUS_NOT_MONITORED, + 'evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, + 'tags' => 'array', + 'severities' => 'array', + 'show_suppressed' => 'in '.ZBX_PROBLEM_SUPPRESSED_FALSE.','.ZBX_PROBLEM_SUPPRESSED_TRUE, + 'maintenance_status' => 'in '.HOST_MAINTENANCE_STATUS_OFF.','.HOST_MAINTENANCE_STATUS_ON, + 'sort' => 'in name,status', + 'sortorder' => 'in '.ZBX_SORT_UP.','.ZBX_SORT_DOWN, + 'page' => 'ge 1', + 'filter_name' => 'string', + 'filter_custom_time' => 'in 1,0', + 'filter_show_counter' => 'in 1,0', + 'filter_counters' => 'in 1' + ]; + + $ret = $this->validateInput($fields); + + // Validate tags filter. + if ($ret && $this->hasInput('tags')) { + foreach ($this->getInput('tags') as $filter_tag) { + if (count($filter_tag) != 3 + || !array_key_exists('tag', $filter_tag) || !is_string($filter_tag['tag']) + || !array_key_exists('value', $filter_tag) || !is_string($filter_tag['value']) + || !array_key_exists('operator', $filter_tag) || !is_string($filter_tag['operator'])) { + $ret = false; + break; + } + } + } + + // Validate severity checkbox filter. + if ($ret && $this->hasInput('severities')) { + foreach ($this->getInput('severities') as $severity) { + if (!in_array($severity, range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1))) { + $ret = false; + break; + } + } + } + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + protected function checkPermissions(): bool { + return ($this->getUserType() >= USER_TYPE_ZABBIX_USER); + } protected function doAction(): void { - $data['filter_defaults'] = static::FILTER_FIELDS_DEFAULT; $profile = (new CTabFilterProfile(static::FILTER_IDX, static::FILTER_FIELDS_DEFAULT)) ->read() ->setInput($this->getInputAll()); diff --git a/ui/app/controllers/CControllerHostViewRefresh.php b/ui/app/controllers/CControllerHostViewRefresh.php index eaa95aa9204..5a3352fb692 100644 --- a/ui/app/controllers/CControllerHostViewRefresh.php +++ b/ui/app/controllers/CControllerHostViewRefresh.php @@ -23,69 +23,7 @@ /** * Controller for the "Host->Monitoring" asynchronous refresh page. */ -class CControllerHostViewRefresh extends CControllerHost { - - protected function init(): void { - $this->disableSIDValidation(); - } - - protected function checkInput(): bool { - $fields = [ - 'name' => 'string', - 'groupids' => 'array_id', - 'ip' => 'string', - 'dns' => 'string', - 'port' => 'string', - 'status' => 'in -1,'.HOST_STATUS_MONITORED.','.HOST_STATUS_NOT_MONITORED, - 'evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, - 'tags' => 'array', - 'severities' => 'array', - 'show_suppressed' => 'in '.ZBX_PROBLEM_SUPPRESSED_FALSE.','.ZBX_PROBLEM_SUPPRESSED_TRUE, - 'maintenance_status' => 'in '.HOST_MAINTENANCE_STATUS_OFF.','.HOST_MAINTENANCE_STATUS_ON, - 'sort' => 'in name,status', - 'sortorder' => 'in '.ZBX_SORT_UP.','.ZBX_SORT_DOWN, - 'page' => 'ge 1', - 'filter_name' => 'string', - 'filter_custom_time' => 'in 1,0', - 'filter_show_counter' => 'in 1,0', - 'filter_counters' => 'in 1' - ]; - - $ret = $this->validateInput($fields); - - // Validate tags filter. - if ($ret && $this->hasInput('tags')) { - foreach ($this->getInput('tags') as $filter_tag) { - if (count($filter_tag) != 3 - || !array_key_exists('tag', $filter_tag) || !is_string($filter_tag['tag']) - || !array_key_exists('value', $filter_tag) || !is_string($filter_tag['value']) - || !array_key_exists('operator', $filter_tag) || !is_string($filter_tag['operator'])) { - $ret = false; - break; - } - } - } - - // Validate severity checkbox filter. - if ($ret && $this->hasInput('severities')) { - foreach ($this->getInput('severities') as $severity) { - if (!in_array($severity, range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1))) { - $ret = false; - break; - } - } - } - - if (!$ret) { - $this->setResponse(new CControllerResponseFatal()); - } - - return $ret; - } - - protected function checkPermissions(): bool { - return ($this->getUserType() >= USER_TYPE_ZABBIX_USER); - } +class CControllerHostViewRefresh extends CControllerHostView { protected function doAction(): void { $filter = static::FILTER_FIELDS_DEFAULT; diff --git a/ui/app/controllers/CControllerPopupTabFilterEdit.php b/ui/app/controllers/CControllerPopupTabFilterEdit.php index 58d83cec133..8a05f81f6a8 100644 --- a/ui/app/controllers/CControllerPopupTabFilterEdit.php +++ b/ui/app/controllers/CControllerPopupTabFilterEdit.php @@ -35,7 +35,8 @@ class CControllerPopupTabFilterEdit extends CController { 'filter_custom_time' => 'in 0,1', 'tabfilter_from' => 'string', 'tabfilter_to' => 'string', - 'support_custom_time' => 'in 0,1' + 'support_custom_time' => 'in 0,1', + 'create' => 'in 0,1' ]; $ret = $this->validateInput($rules) && $this->customValidation(); @@ -91,7 +92,8 @@ class CControllerPopupTabFilterEdit extends CController { 'filter_custom_time' => 0, 'tabfilter_from' => '', 'tabfilter_to' => '', - 'support_custom_time' => 0 + 'support_custom_time' => 0, + 'create' => 0 ]; $this->getInputs($data, array_keys($data)); @@ -131,23 +133,27 @@ class CControllerPopupTabFilterEdit extends CController { */ public function updateTab(array $data) { $filter = (new CTabFilterProfile($data['idx'], []))->read(); + $properties = [ + 'filter_name' => $data['filter_name'], + 'filter_show_counter' => (int) $data['filter_show_counter'], + 'filter_custom_time' => (int) $data['filter_custom_time'], + 'from' => $data['tabfilter_from'], + 'to' => $data['tabfilter_to'] + ]; - if (array_key_exists($data['idx2'], $filter->tabfilters)) { - $properties = [ - 'filter_name' => $data['filter_name'], - 'filter_show_counter' => (int) $data['filter_show_counter'], - 'filter_custom_time' => (int) $data['filter_custom_time'], - 'from' => $data['tabfilter_from'], - 'to' => $data['tabfilter_to'] - ]; - - if (!$properties['filter_custom_time']) { - unset($properties['from'], $properties['to']); - } + if (!$properties['filter_custom_time']) { + unset($properties['from'], $properties['to']); + } - $filter->tabfilters[$data['idx2']] = $properties + $filter->tabfilters[$data['idx2']]; - $filter->update(); + if (array_key_exists($data['idx2'], $filter->tabfilters)) { + $properties = $properties + $filter->tabfilters[$data['idx2']]; } + else { + $data['idx2'] = count($filter->tabfilters); + } + + $filter->tabfilters[$data['idx2']] = $properties; + $filter->update(); $this->setResponse((new CControllerResponseData(['main_block' => json_encode($data)]))->disableView()); } diff --git a/ui/app/views/js/monitoring.host.view.js.php b/ui/app/views/js/monitoring.host.view.js.php index 3891962928d..51073fcb172 100644 --- a/ui/app/views/js/monitoring.host.view.js.php +++ b/ui/app/views/js/monitoring.host.view.js.php @@ -53,7 +53,7 @@ this.running = false; this.timeout = null; this.refresh_counters = this.createCountersRefresh(1); - this.filter = new CTabFilter($('#monitoringhostsfilter')[0], <?= json_encode($data['filter_options']) ?>); + this.filter = new CTabFilter($('#monitoring_hosts_filter')[0], <?= json_encode($data['filter_options']) ?>); this.filter.on(TABFILTER_EVENT_URLSET, (ev) => { let url = new Curl('', false); diff --git a/ui/app/views/js/popup.tabfilter.edit.js.php b/ui/app/views/js/popup.tabfilter.edit.js.php index bb84544e9fa..50bfc8f4e92 100644 --- a/ui/app/views/js/popup.tabfilter.edit.js.php +++ b/ui/app/views/js/popup.tabfilter.edit.js.php @@ -45,7 +45,7 @@ function tabFilterFormAction(form_action, overlay) { } else { overlayDialogueDestroy(overlay.dialogueid); - overlay.element.dispatchEvent(new CustomEvent('popup.tabfilter', {detail: response})); + overlay.element.dispatchEvent(new CustomEvent('popup.tabfilter', {detail: response, bubbles: true})); } }) .always(() => { diff --git a/ui/app/views/monitoring.host.view.php b/ui/app/views/monitoring.host.view.php index 6f39427e666..b317a77b40e 100644 --- a/ui/app/views/monitoring.host.view.php +++ b/ui/app/views/monitoring.host.view.php @@ -44,7 +44,7 @@ $widget = (new CWidget()) if ($web_layout_mode == ZBX_LAYOUT_NORMAL) { $filter = (new CTabFilter()) - ->setId('monitoringhostsfilter') + ->setId('monitoring_hosts_filter') ->setIdx($data['tabfilter_idx']) ->setSelected((int) $data['tab_selected']) ->setExpanded((bool) $data['tab_expanded']) diff --git a/ui/include/classes/html/CCheckBoxList.php b/ui/include/classes/html/CCheckBoxList.php index 2a4058c690e..f419554290f 100644 --- a/ui/include/classes/html/CCheckBoxList.php +++ b/ui/include/classes/html/CCheckBoxList.php @@ -53,6 +53,17 @@ class CCheckBoxList extends CList { } /** + * Set uinqueid, it is used as suffix for generated check box ids. + * + * @param string $uniqid Unique id string. + */ + public function setUniqid(string $uniqid) { + $this->uniqid = $uniqid; + + return $this; + } + + /** * @param array $values * * @return CCheckBoxList diff --git a/ui/include/classes/html/CSeverityCheckBoxList.php b/ui/include/classes/html/CSeverityCheckBoxList.php index 9dc4c84c1fa..265541d0d96 100644 --- a/ui/include/classes/html/CSeverityCheckBoxList.php +++ b/ui/include/classes/html/CSeverityCheckBoxList.php @@ -41,17 +41,6 @@ class CSeverityCheckBoxList extends CCheckBoxList { } /** - * Set uinqueid, it is used as suffix for generated check box ids. - * - * @param string $uniqid Unique id string. - */ - public function setUniqid(string $uniqid) { - $this->uniqid = $uniqid; - - return $this; - } - - /** * Generate array with data for severities options ordered for showing by rows. * * @return array diff --git a/ui/js/class.tabfilter.js b/ui/js/class.tabfilter.js index 711eba64e2d..44921d57eeb 100644 --- a/ui/js/class.tabfilter.js +++ b/ui/js/class.tabfilter.js @@ -163,6 +163,29 @@ class CTabFilter extends CBaseComponent { }, /** + * Event handler for 'Save as' button + */ + popupUpdateAction: (ev) => { + var item = this.create(this._active_item._target.cloneNode(), {}); + + if (ev.detail.form_action === 'update') { + item.update(Object.assign(ev.detail, { + from: ev.detail.tabfilter_from, + to: ev.detail.tabfilter_to + })); + var params = item.getFilterParams(); + + this.profileUpdate('properties', { + 'idx2': ev.detail.idx2, + 'value_str': params.toString() + }).then(() => { + item.setBrowserLocation(params); + window.location.reload(true); + }); + } + }, + + /** * Action on 'chevron left' button press. Select previous active tab filter. */ selectPrevTab: (ev) => { @@ -219,11 +242,11 @@ class CTabFilter extends CBaseComponent { /** * Action on 'Update' button press. */ - update: () => { + buttonUpdateAction: () => { var params = this._active_item.getFilterParams(); this.profileUpdate('properties', { - 'idx2[]': this._active_item._index, + 'idx2': this._active_item._index, 'value_str': params.toString() }).then(() => { this._active_item.setBrowserLocation(params); @@ -231,52 +254,29 @@ class CTabFilter extends CBaseComponent { }, /** - * Action on 'Save as' button press, refresh whole page for simplisity. + * Action on 'Save as' button press, open properties popup. */ - create: () => { - let params = this._active_item.getFilterParams(), - url = new Curl('', false), - title = t('Untitled'), - regex = new RegExp(title + ' \\((\\d+)\\)'), - match, - index = 0; - - for (const item of this._items) { - match = (item._data.filter_name||'').match(regex); - - index = Math.max( - item._data.filter_name === title ? 1 : 0, - match ? (+match[1]) + 1 : 0, - index - ); - } + buttonSaveasAction: (ev) => { + let params = this._active_item.getFilterParams(); - if (index) { - title += ' (' + index + ')'; - } - - params.set('filter_name', title); - - this.profileUpdate('properties', { - 'idx2[]': this._items.length, - 'value_str': params.toString() - }).then(() => { - params.set('action', url.getArgument('action')); - window.location.search = params.toString(); + this._active_item.openPropertiesForm(ev.target, { + 'idx': this._active_item._idx_namespace, + 'idx2': this._items.length }); }, /** * Action on 'Apply' button press. */ - apply: () => { + buttonApplyAction: () => { + this._active_item.setUnsavedState(); this._active_item.setBrowserLocation(this._active_item.getFilterParams()); }, /** * Action on 'Reset' button press. */ - reset: () => { + buttonResetAction: () => { this._active_item.setBrowserLocation(new URLSearchParams()); window.location.reload(true); }, @@ -315,12 +315,13 @@ class CTabFilter extends CBaseComponent { action.addEventListener('click', this._events[action.getAttribute('data-action')]); } - this._shared_domnode.querySelector('[name="filter_update"]').addEventListener('click', this._events.update); - this._shared_domnode.querySelector('[name="filter_new"]').addEventListener('click', this._events.create); - this._shared_domnode.querySelector('[name="filter_apply"]').addEventListener('click', this._events.apply); - this._shared_domnode.querySelector('[name="filter_reset"]').addEventListener('click', this._events.reset); + this._shared_domnode.querySelector('[name="filter_update"]').addEventListener('click', this._events.buttonUpdateAction); + this._shared_domnode.querySelector('[name="filter_new"]').addEventListener('click', this._events.buttonSaveasAction); + this._shared_domnode.querySelector('[name="filter_apply"]').addEventListener('click', this._events.buttonApplyAction); + this._shared_domnode.querySelector('[name="filter_reset"]').addEventListener('click', this._events.buttonResetAction); this.on('keydown', this._events.keydown); + this.on('popup.tabfilter', this._events.popupUpdateAction); } /** @@ -412,14 +413,14 @@ class CTabFilter extends CBaseComponent { body.idx = this._idx_namespace + '.' + property; this._fetch = new AbortController(); - return fetch('zabbix.php?action=profile.update', { + return fetch('zabbix.php?action=tabfilter.profile.update', { method: 'POST', signal: this._fetch.signal, body: new URLSearchParams(body) }).then(() => { this._fetch = null; }).catch(() => { - // Catch DOMExeception: The user aborted a request. + // User aborted a request. }); } diff --git a/ui/js/class.tabfilteritem.js b/ui/js/class.tabfilteritem.js index 2d153213c0a..5b2b23e19f8 100644 --- a/ui/js/class.tabfilteritem.js +++ b/ui/js/class.tabfilteritem.js @@ -25,7 +25,7 @@ const TABFILTERITEM_EVENT_EXPAND_BEFORE = 'expandbefore.tabfilter'; const TABFILTERITEM_EVENT_RENDER = 'render.tabfilter'; const TABFILTERITEM_EVENT_DELETE = 'delete.tabfilter'; const TABFILTERITEM_EVENT_URLSET = 'urlset.tabfilter'; -const TABFILTERITEM_EVENT_UPDATE = 'update.tabfilter' +const TABFILTERITEM_EVENT_UPDATE = 'update.tabfilter'; class CTabFilterItem extends CBaseComponent { @@ -42,6 +42,7 @@ class CTabFilterItem extends CBaseComponent { this._expanded = options.expanded; this._support_custom_time = options.support_custom_time; this._template_rendered = false; + this._unsaved = false; this.init(); this.registerEvents(); @@ -151,18 +152,10 @@ class CTabFilterItem extends CBaseComponent { * Open tab filter configuration poup. * * @param {HTMLElement} edit_elm HTML element to broadcast popup update or delete event. + * @param {object} params Object of params to be passed to ajax call when opening popup. */ - openPropertiesForm(edit_elm) { - PopUp('popup.tabfilter.edit', { - idx: this._idx_namespace, - idx2: this._index, - filter_name: this._data.filter_name, - filter_show_counter: this._data.filter_show_counter, - filter_custom_time: this._data.filter_custom_time, - tabfilter_from: this._data.from||'', - tabfilter_to: this._data.to||'', - support_custom_time: +this._support_custom_time - }, 'tabfilter_dialogue', edit_elm); + openPropertiesForm(edit_elm, params) { + return PopUp('popup.tabfilter.edit', params, 'tabfilter_dialogue', edit_elm); } /** @@ -172,21 +165,16 @@ class CTabFilterItem extends CBaseComponent { let edit = document.createElement('a'); edit.classList.add('icon-edit'); - edit.addEventListener('click', (ev) => this.openPropertiesForm(ev.target)); - edit.addEventListener('popup.tabfilter', (ev) => { - let data = ev.detail; - - if (data.form_action === 'update') { - this.update(Object.assign(data, { - from: data.tabfilter_from, - to: data.tabfilter_to - })); - this.fire(TABFILTERITEM_EVENT_UPDATE); - } - else { - this.delete(); - } - }); + edit.addEventListener('click', (ev) => this.openPropertiesForm(ev.target, { + idx: this._idx_namespace, + idx2: this._index, + filter_name: this._data.filter_name, + filter_show_counter: this._data.filter_show_counter, + filter_custom_time: this._data.filter_custom_time, + tabfilter_from: this._data.from||'', + tabfilter_to: this._data.to||'', + support_custom_time: +this._support_custom_time + })); this._target.parentNode.appendChild(edit); } @@ -302,4 +290,27 @@ class CTabFilterItem extends CBaseComponent { history.replaceState(history.state, '', url.getUrl()); this.fire(TABFILTERITEM_EVENT_URLSET); } + + /** + * Checks difference between original form values and to be posted values. + * Updates this._unsaved according to check results + * + * @param {URLSearchParams} search_params Filter field values to compare against. + */ + setUnsavedState() { + let search_params = this.getFilterParams(), + src_query = new URLSearchParams(this._src_url), + unmodified = true; + + src_query.sort(); + search_params.sort(); + // TODO: check and remove method + + src_query.forEach((value, key) => { + unmodified = unmodified && (search_params.get(key) == value); + }); + + this._unsaved = !unmodified; + this.toggleClass('unsaved', this._unsaved); + } } |