diff options
-rw-r--r-- | create/src/schema.tmpl | 2 | ||||
-rw-r--r-- | src/libs/zbxdbupgrade/dbupgrade_5050.c | 12 | ||||
-rw-r--r-- | ui/app/controllers/CControllerLatest.php | 146 | ||||
-rw-r--r-- | ui/app/controllers/CControllerLatestView.php | 192 | ||||
-rw-r--r-- | ui/app/controllers/CControllerLatestViewRefresh.php | 137 | ||||
-rw-r--r-- | ui/app/controllers/CControllerTabFilterProfileUpdate.php | 3 | ||||
-rw-r--r-- | ui/app/partials/monitoring.latest.filter.php | 364 | ||||
-rw-r--r-- | ui/app/partials/monitoring.latest.view.html.php | 1 | ||||
-rw-r--r-- | ui/app/views/js/monitoring.latest.view.js.php | 146 | ||||
-rw-r--r-- | ui/app/views/monitoring.latest.view.php | 85 | ||||
-rw-r--r-- | ui/include/defines.inc.php | 2 |
11 files changed, 754 insertions, 336 deletions
diff --git a/create/src/schema.tmpl b/create/src/schema.tmpl index 901adab5f02..cdfd7a214c0 100644 --- a/create/src/schema.tmpl +++ b/create/src/schema.tmpl @@ -1905,4 +1905,4 @@ TABLE|dbversion|dbversionid| FIELD |dbversionid |t_id | |NOT NULL |0 FIELD |mandatory |t_integer |'0' |NOT NULL | FIELD |optional |t_integer |'0' |NOT NULL | -ROW |1 |5050111 |5050111 +ROW |1 |5050112 |5050112 diff --git a/src/libs/zbxdbupgrade/dbupgrade_5050.c b/src/libs/zbxdbupgrade/dbupgrade_5050.c index c3f68c2682e..142636370e8 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5050.c @@ -1185,6 +1185,17 @@ static int DBpatch_5050111(void) return DBcreate_index("alerts", "alerts_8", "acknowledgeid", 0); } + +static int DBpatch_5050112(void) +{ + if (0 == (program_type & ZBX_PROGRAM_TYPE_SERVER)) + return SUCCEED; + + if (ZBX_DB_OK > DBexecute("delete from profiles where idx like 'web.latest.filter.%%'")) + return FAIL; + + return SUCCEED; +} #endif DBPATCH_START(5050) @@ -1290,5 +1301,6 @@ DBPATCH_ADD(5050108, 0, 1) DBPATCH_ADD(5050109, 0, 1) DBPATCH_ADD(5050110, 0, 1) DBPATCH_ADD(5050111, 0, 1) +DBPATCH_ADD(5050112, 0, 1) DBPATCH_END() diff --git a/ui/app/controllers/CControllerLatest.php b/ui/app/controllers/CControllerLatest.php index 41a49b387e9..75fbd2267e5 100644 --- a/ui/app/controllers/CControllerLatest.php +++ b/ui/app/controllers/CControllerLatest.php @@ -24,13 +24,30 @@ */ abstract class CControllerLatest extends CController { + // Filter idx prefix. + const FILTER_IDX = 'web.monitoring.latest'; + + // Filter fields default values. + const FILTER_FIELDS_DEFAULT = [ + 'groupids' => [], + 'hostids' => [], + 'name' => '', + 'evaltype' => TAG_EVAL_TYPE_AND_OR, + 'tags' => [], + 'show_without_data' => true, + 'show_details' => true, + 'page' => null, + 'sort' => 'name', + 'sortorder' => ZBX_SORT_UP + ]; + /** * Prepare the latest data based on the given filter and sorting options. * * @param array $filter Item filter options. * @param array $filter['groupids'] Filter items by host groups. * @param array $filter['hostids'] Filter items by hosts. - * @param string $filter['select'] Filter items by name. + * @param string $filter['name'] Filter items by name. * @param int $filter['evaltype'] Filter evaltype. * @param array $filter['tags'] Filter tags. * @param string $filter['tags'][]['tag'] @@ -44,8 +61,7 @@ abstract class CControllerLatest extends CController { */ protected function prepareData(array $filter, $sort_field, $sort_order) { // Select groups for subsequent selection of hosts and items. - $multiselect_hostgroup_data = []; - $groupids = $filter['groupids'] ? getSubGroups($filter['groupids'], $multiselect_hostgroup_data) : null; + $groupids = $filter['groupids'] ? getSubGroups($filter['groupids']) : null; // Select hosts for subsequent selection of items. $hosts = API::Host()->get([ @@ -76,8 +92,8 @@ abstract class CControllerLatest extends CController { 'filter' => [ 'status' => [ITEM_STATUS_ACTIVE] ], - 'search' => ($filter['select'] === '') ? null : [ - 'name' => $filter['select'] + 'search' => ($filter['name'] === '') ? null : [ + 'name' => $filter['name'] ], 'preservekeys' => true ]); @@ -125,18 +141,9 @@ abstract class CControllerLatest extends CController { $items = []; } - $multiselect_host_data = $filter['hostids'] - ? API::Host()->get([ - 'output' => ['hostid', 'name'], - 'hostids' => $filter['hostids'] - ]) - : []; - return [ 'hosts' => $hosts, - 'items' => $items, - 'multiselect_hostgroup_data' => $multiselect_hostgroup_data, - 'multiselect_host_data' => CArrayHelper::renameObjectsKeys($multiselect_host_data, ['hostid' => 'id']) + 'items' => $items ]; } @@ -158,4 +165,113 @@ abstract class CControllerLatest extends CController { $prepared_data['items'] = $items; $prepared_data['history'] = $history; } + + /** + * Get additional data for filters. Selected groups for multiselect, etc. + * + * @param array $filter Filter fields values array. + * + * @return array + */ + protected function getAdditionalData($filter): array { + $data = []; + + if ($filter['groupids']) { + $groups = API::HostGroup()->get([ + 'output' => ['groupid', 'name'], + 'groupids' => $filter['groupids'] + ]); + $data['groups_multiselect'] = CArrayHelper::renameObjectsKeys(array_values($groups), ['groupid' => 'id']); + } + + if ($filter['hostids']) { + $hosts = API::Host()->get([ + 'output' => ['hostid', 'name'], + 'hostids' => $filter['hostids'] + ]); + $data['hosts_multiselect'] = CArrayHelper::renameObjectsKeys(array_values($hosts), ['hostid' => 'id']); + } + + return $data; + } + + /** + * Clean passed filter fields in input from default values required for HTML presentation. Convert field + * + * @param array $input Filter fields values. + * + * @return array + */ + protected function cleanInput(array $input): array { + if (array_key_exists('filter_reset', $input) && $input['filter_reset']) { + return array_intersect_key(['filter_name' => ''], $input); + } + + if (array_key_exists('tags', $input) && $input['tags']) { + $input['tags'] = array_filter($input['tags'], function($tag) { + return !($tag['tag'] === '' && $tag['value'] === ''); + }); + $input['tags'] = array_values($input['tags']); + } + + return $input; + } + + /** + * Get items count for passed filter. + * + * @param array $filter Filter options. + * @param string $filter['name'] Filter items by name. + * @param array $filter['groupids'] Filter items by host groups. + * @param array $filter['hostids'] Filter items by host groups. + * @param string $filter['evaltype'] Filter items by tags. + * @param string $filter['tags'] Filter items by tag names and values. + * @param int $filter['show_without_data'] Filter items with/without data. + * + * @return int + */ + protected function getCount(array $filter): int { + $groupids = $filter['groupids'] ? getSubGroups($filter['groupids']) : null; + + $hosts = API::Host()->get([ + 'output' => [], + 'groupids' => $groupids, + 'hostids' => $filter['hostids'] ? $filter['hostids'] : null, + 'monitored_hosts' => true, + 'preservekeys' => true + ]); + + $search_limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT); + $history_period = timeUnitToSeconds(CSettingsHelper::get(CSettingsHelper::HISTORY_PERIOD)); + $select_items_cnt = 0; + + foreach (array_keys($hosts) as $hostid) { + if ($select_items_cnt >= $search_limit) { + break; + } + + $host_items = API::Item()->get([ + 'output' => ['itemid', 'value_type'], + 'hostids' => [$hostid], + 'webitems' => true, + 'evaltype' => $filter['evaltype'], + 'tags' => $filter['tags'] ? $filter['tags'] : null, + 'filter' => [ + 'status' => [ITEM_STATUS_ACTIVE] + ], + 'search' => ($filter['name'] === '') ? null : [ + 'name' => $filter['name'] + ], + 'preservekeys' => true + ]); + + $host_items = $filter['show_without_data'] + ? $host_items + : Manager::History()->getItemsHavingValues($host_items, $history_period); + + $select_items_cnt += count($host_items); + } + + return min($select_items_cnt, $search_limit); + } } diff --git a/ui/app/controllers/CControllerLatestView.php b/ui/app/controllers/CControllerLatestView.php index 15a44cd47ef..c82f357f25b 100644 --- a/ui/app/controllers/CControllerLatestView.php +++ b/ui/app/controllers/CControllerLatestView.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types = 1); /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA @@ -24,32 +24,51 @@ */ class CControllerLatestView extends CControllerLatest { - protected function init() { + protected function init(): void { $this->disableSIDValidation(); } protected function checkInput() { $fields = [ - 'page' => 'ge 1', - - // filter inputs - 'filter_groupids' => 'array_id', - 'filter_hostids' => 'array_id', - 'filter_select' => 'string', - 'filter_show_without_data' => 'in 0,1', - 'filter_show_details' => 'in 1', - 'filter_set' => 'in 1', - 'filter_rst' => 'in 1', - 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, - 'filter_tags' => 'array', + // filter fields + 'groupids' => 'array_db hosts_groups.groupid', + 'hostids' => 'array_db hosts.hostid', + 'name' => 'string', + 'show_without_data' => 'in 1', + 'show_details' => 'in 1', + 'evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, + 'tags' => 'array', // table sorting inputs - 'sort' => 'in host,name,lastclock', - 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP + 'sort' => 'in name,status', + 'sortorder' => 'in '.ZBX_SORT_UP.','.ZBX_SORT_DOWN, + 'page' => 'ge 1', + + // named filter properties + 'filter_name' => 'string', + 'filter_custom_time' => 'in 1,0', + 'filter_show_counter' => 'in 1,0', + 'filter_counters' => 'in 1', + 'filter_reset' => 'in 1', + 'counter_index' => 'ge 0' ]; $ret = $this->validateInput($fields); + // Validate tags filter. + if ($ret && $this->hasInput('tags')) { + foreach ($this->getInput('tags') as $filter_tag) { + if (!is_array($filter_tag) + || 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; + } + } + } + if (!$ret) { $this->setResponse(new CControllerResponseFatal()); } @@ -57,116 +76,73 @@ class CControllerLatestView extends CControllerLatest { return $ret; } - protected function checkPermissions() { + protected function checkPermissions(): bool { return $this->checkAccess(CRoleHelper::UI_MONITORING_LATEST_DATA); } - protected function doAction() { - // filter - if ($this->hasInput('filter_set')) { - CProfile::updateArray('web.latest.filter.groupids', $this->getInput('filter_groupids', []), - PROFILE_TYPE_ID - ); - CProfile::updateArray('web.latest.filter.hostids', $this->getInput('filter_hostids', []), PROFILE_TYPE_ID); - CProfile::update('web.latest.filter.select', trim($this->getInput('filter_select', '')), PROFILE_TYPE_STR); - CProfile::update('web.latest.filter.show_without_data', $this->getInput('filter_show_without_data', 1), - PROFILE_TYPE_INT - ); - CProfile::update('web.latest.filter.show_details', $this->getInput('filter_show_details', 0), - PROFILE_TYPE_INT - ); - - // tags - $evaltype = $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR); - CProfile::update('web.latest.filter.evaltype', $evaltype, PROFILE_TYPE_INT); - - $filter_tags = ['tags' => [], 'values' => [], 'operators' => []]; - foreach ($this->getInput('filter_tags', []) as $tag) { - if ($tag['tag'] === '' && $tag['value'] === '') { - continue; - } - $filter_tags['tags'][] = $tag['tag']; - $filter_tags['values'][] = $tag['value']; - $filter_tags['operators'][] = $tag['operator']; + protected function doAction(): void { + + $profile = (new CTabFilterProfile(static::FILTER_IDX, static::FILTER_FIELDS_DEFAULT)) + ->read() + ->setInput($this->cleanInput($this->getInputAll())); + + $filter_tabs = []; + foreach ($profile->getTabsWithDefaults() as $index => $filter_tab) { + if ($index == $profile->selected) { + // Initialize multiselect data for filter_scr to allow tabfilter correctly handle unsaved state. + $filter_tab['filter_src']['filter_view_data'] = $this->getAdditionalData($filter_tab['filter_src']); } - CProfile::updateArray('web.latest.filter.tags.tag', $filter_tags['tags'], PROFILE_TYPE_STR); - CProfile::updateArray('web.latest.filter.tags.value', $filter_tags['values'], PROFILE_TYPE_STR); - CProfile::updateArray('web.latest.filter.tags.operator', $filter_tags['operators'], PROFILE_TYPE_INT); - } - elseif ($this->hasInput('filter_rst')) { - CProfile::deleteIdx('web.latest.filter.groupids'); - CProfile::deleteIdx('web.latest.filter.hostids'); - CProfile::delete('web.latest.filter.select'); - CProfile::delete('web.latest.filter.show_without_data'); - CProfile::delete('web.latest.filter.show_details'); - CProfile::deleteIdx('web.latest.filter.evaltype'); - CProfile::deleteIdx('web.latest.filter.tags.tag'); - CProfile::deleteIdx('web.latest.filter.tags.value'); - CProfile::deleteIdx('web.latest.filter.tags.operator'); + + $filter_tabs[] = $filter_tab + ['filter_view_data' => $this->getAdditionalData($filter_tab)]; } - // Force-check "Show items without data" if there are no hosts selected. - $filter_hostids = CProfile::getArray('web.latest.filter.hostids'); - $filter_show_without_data = $filter_hostids ? CProfile::get('web.latest.filter.show_without_data', 1) : 1; - - $filter = [ - 'groupids' => CProfile::getArray('web.latest.filter.groupids'), - 'hostids' => $filter_hostids, - 'select' => CProfile::get('web.latest.filter.select', ''), - 'show_without_data' => $filter_show_without_data, - 'show_details' => CProfile::get('web.latest.filter.show_details', 0), - 'evaltype' => CProfile::get('web.latest.filter.evaltype', TAG_EVAL_TYPE_AND_OR), - 'tags' => [] - ]; + $filter = ['action' => 'latest.view.refresh'] + $filter_tabs[$profile->selected]; - // Tags filters. - foreach (CProfile::getArray('web.latest.filter.tags.tag', []) as $i => $tag) { - $filter['tags'][] = [ - 'tag' => $tag, - 'value' => CProfile::get('web.latest.filter.tags.value', null, $i), - 'operator' => CProfile::get('web.latest.filter.tags.operator', null, $i) - ]; - } + $refresh_curl = new CUrl('zabbix.php'); + array_map([$refresh_curl, 'setArgument'], array_keys($filter), $filter); - $sort_field = $this->getInput('sort', CProfile::get('web.latest.sort', 'name')); - $sort_order = $this->getInput('sortorder', CProfile::get('web.latest.sortorder', ZBX_SORT_UP)); + // data sort and pager + $sort_field = $this->getInput('sort', 'name'); + $sort_order = $this->getInput('sortorder', ZBX_SORT_UP); + $prepared_data = $this->prepareData($filter, $sort_field, $sort_order); - CProfile::update('web.latest.sort', $sort_field, PROFILE_TYPE_STR); - CProfile::update('web.latest.sortorder', $sort_order, PROFILE_TYPE_STR); + $view_url = (new CUrl('zabbix.php'))->setArgument('action', 'latest.view'); + $paging = CPagerHelper::paginate($this->getInput('page', 1), $prepared_data['items'], ZBX_SORT_UP, $view_url); - $view_curl = (new CUrl('zabbix.php'))->setArgument('action', 'latest.view'); + $this->extendData($prepared_data); - $refresh_curl = (new CUrl('zabbix.php'))->setArgument('action', 'latest.view.refresh'); $refresh_data = array_filter([ - 'filter_groupids' => $filter['groupids'], - 'filter_hostids' => $filter['hostids'], - 'filter_select' => $filter['select'], - 'filter_show_without_data' => $filter['show_without_data'] ? 1 : null, - 'filter_show_details' => $filter['show_details'] ? 1 : null, - 'filter_evaltype' => $filter['evaltype'], - 'filter_tags' => $filter['tags'], + 'groupids' => $filter['groupids'], + 'hostids' => $filter['hostids'], + 'name' => $filter['name'], + 'show_without_data' => $filter['show_without_data'] ? 1 : null, + 'show_details' => $filter['show_details'] ? 1 : null, + 'evaltype' => $filter['evaltype'], + 'tags' => $filter['tags'], 'sort' => $sort_field, 'sortorder' => $sort_order, 'page' => $this->hasInput('page') ? $this->getInput('page') : null ]); - // data sort and pager - $prepared_data = $this->prepareData($filter, $sort_field, $sort_order); - - $paging = CPagerHelper::paginate($this->getInput('page', 1), $prepared_data['items'], ZBX_SORT_UP, $view_curl); - - $this->extendData($prepared_data); - // display $data = [ + 'refresh_url' => $refresh_curl->getUrl(), + 'refresh_interval' => CWebUser::getRefresh() * 1000, + 'refresh_data' => $refresh_data, + 'filter_defaults' => $profile->filter_defaults, + 'filter_view' => 'monitoring.latest.filter', + 'filter_tabs' => $filter_tabs, + 'tabfilter_options' => [ + 'idx' => static::FILTER_IDX, + 'selected' => $profile->selected, + 'support_custom_time' => 0, + 'expanded' => $profile->expanded, + 'page' => $filter['page'] + ], 'filter' => $filter, 'sort_field' => $sort_field, 'sort_order' => $sort_order, - 'view_curl' => $view_curl, - 'refresh_url' => $refresh_curl->getUrl(), - 'refresh_data' => $refresh_data, - 'refresh_interval' => CWebUser::getRefresh() * 1000, - 'active_tab' => CProfile::get('web.latest.filter.active', 1), + 'view_curl' => $view_url, 'paging' => $paging, 'config' => [ 'hk_trends' => CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS), @@ -177,14 +153,6 @@ class CControllerLatestView extends CControllerLatest { 'tags' => makeTags($prepared_data['items'], true, 'itemid', ZBX_TAG_COUNT_DEFAULT, $filter['tags']) ] + $prepared_data; - if (!$data['filter']['tags']) { - $data['filter']['tags'] = [[ - 'tag' => '', - 'operator' => TAG_OPERATOR_LIKE, - 'value' => '' - ]]; - } - $response = new CControllerResponseData($data); $response->setTitle(_('Latest data')); $this->setResponse($response); diff --git a/ui/app/controllers/CControllerLatestViewRefresh.php b/ui/app/controllers/CControllerLatestViewRefresh.php index 06d15d2c530..fd17caf6829 100644 --- a/ui/app/controllers/CControllerLatestViewRefresh.php +++ b/ui/app/controllers/CControllerLatestViewRefresh.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types = 1); /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA @@ -22,100 +22,59 @@ /** * Controller for the "Latest data" asynchronous refresh page. */ -class CControllerLatestViewRefresh extends CControllerLatest { +class CControllerLatestViewRefresh extends CControllerLatestView { - protected function init() { - $this->disableSIDValidation(); - } - - protected function checkInput() { - $fields = [ - 'page' => 'ge 1', - - // filter inputs - 'filter_groupids' => 'array_id', - 'filter_hostids' => 'array_id', - 'filter_select' => 'string', - 'filter_show_without_data' => 'in 1', - 'filter_show_details' => 'in 1', - 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, - 'filter_tags' => 'array', + protected function doAction(): void { - // table sorting inputs - 'sort' => 'in host,name,lastclock', - 'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP - ]; + if ($this->getInput('filter_counters', 0)) { + $profile = (new CTabFilterProfile(static::FILTER_IDX, static::FILTER_FIELDS_DEFAULT))->read(); + $filters = $this->hasInput('counter_index') + ? [$profile->getTabFilter($this->getInput('counter_index'))] + : $profile->getTabsWithDefaults(); - $ret = $this->validateInput($fields); - - if ($ret) { - // Hosts must have been selected as well if filtering items with data only. - if (!$this->getInput('filter_hostids', []) && !$this->getInput('filter_show_without_data', 0)) { - $ret = false; + $filter_counters = []; + foreach ($filters as $index => $tabfilter) { + $filter_counters[$index] = $tabfilter['filter_show_counter'] ? $this->getCount($tabfilter) : 0; } - } - if (!$ret) { - $this->setResponse(new CControllerResponseFatal()); + $this->setResponse( + (new CControllerResponseData([ + 'main_block' => json_encode(['filter_counters' => $filter_counters]) + ]))->disableView() + ); } - - return $ret; - } - - protected function checkPermissions() { - return $this->checkAccess(CRoleHelper::UI_MONITORING_LATEST_DATA); - } - - protected function doAction() { - // filter - $filter = [ - 'groupids' => $this->hasInput('filter_groupids') ? $this->getInput('filter_groupids') : null, - 'hostids' => $this->hasInput('filter_hostids') ? $this->getInput('filter_hostids') : null, - 'select' => $this->getInput('filter_select', ''), - 'show_without_data' => $this->getInput('filter_show_without_data', 0), - 'show_details' => $this->getInput('filter_show_details', 0), - 'evaltype' => CProfile::get('web.latest.filter.evaltype', TAG_EVAL_TYPE_AND_OR), - 'tags' => [] - ]; - - // Tags filters. - foreach (CProfile::getArray('web.latest.filter.tags.tag', []) as $i => $tag) { - $filter['tags'][] = [ - 'tag' => $tag, - 'value' => CProfile::get('web.latest.filter.tags.value', null, $i), - 'operator' => CProfile::get('web.latest.filter.tags.operator', null, $i) - ]; + else { + $filter = static::FILTER_FIELDS_DEFAULT; + $this->getInputs($filter, array_keys($filter)); + $filter = $this->cleanInput($filter); + + // make data + $prepared_data = $this->prepareData($filter, $filter['sort'], $filter['sortorder']); + + $page = $this->getInput('page', 1); + $view_url = (new CUrl('zabbix.php'))->setArgument('action', 'latest.view'); + $paging = CPagerHelper::paginate($page, $prepared_data['items'], ZBX_SORT_UP, $view_url); + + $this->extendData($prepared_data); + + // make response + $data = [ + 'filter' => $filter, + 'view_curl' => $view_url, + 'sort_field' => $filter['sort'], + 'sort_order' => $filter['sortorder'], + 'paging' => $paging, + 'config' => [ + 'hk_trends' => CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS), + 'hk_trends_global' => CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS_GLOBAL), + 'hk_history' => CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY), + 'hk_history_global' => CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY_GLOBAL) + ], + 'tags' => makeTags($prepared_data['items'], true, 'itemid', ZBX_TAG_COUNT_DEFAULT, $filter['tags']) + ] + $prepared_data; + + $response = new CControllerResponseData($data); + $this->setResponse($response); } - - $sort_field = $this->getInput('sort', 'name'); - $sort_order = $this->getInput('sortorder', ZBX_SORT_UP); - - $view_curl = (new CUrl('zabbix.php'))->setArgument('action', 'latest.view'); - - // data sort and pager - $prepared_data = $this->prepareData($filter, $sort_field, $sort_order); - - $paging = CPagerHelper::paginate($this->getInput('page', 1), $prepared_data['items'], ZBX_SORT_UP, $view_curl); - - $this->extendData($prepared_data); - - // display - $data = [ - 'filter' => $filter, - 'sort_field' => $sort_field, - 'sort_order' => $sort_order, - 'view_curl' => $view_curl, - 'paging' => $paging, - 'config' => [ - 'hk_trends' => CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS), - 'hk_trends_global' => CHousekeepingHelper::get(CHousekeepingHelper::HK_TRENDS_GLOBAL), - 'hk_history' => CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY), - 'hk_history_global' => CHousekeepingHelper::get(CHousekeepingHelper::HK_HISTORY_GLOBAL) - ], - 'tags' => makeTags($prepared_data['items'], true, 'itemid', ZBX_TAG_COUNT_DEFAULT, $filter['tags']) - ] + $prepared_data; - - $response = new CControllerResponseData($data); - $this->setResponse($response); } } diff --git a/ui/app/controllers/CControllerTabFilterProfileUpdate.php b/ui/app/controllers/CControllerTabFilterProfileUpdate.php index 2cb078f2cb4..b33f21ba81f 100644 --- a/ui/app/controllers/CControllerTabFilterProfileUpdate.php +++ b/ui/app/controllers/CControllerTabFilterProfileUpdate.php @@ -30,7 +30,8 @@ class CControllerTabFilterProfileUpdate extends CController { public static $namespaces = [ CControllerHost::FILTER_IDX => CControllerHost::FILTER_FIELDS_DEFAULT, - CControllerProblem::FILTER_IDX => CControllerProblem::FILTER_FIELDS_DEFAULT + CControllerProblem::FILTER_IDX => CControllerProblem::FILTER_FIELDS_DEFAULT, + CControllerLatest::FILTER_IDX => CControllerLatest::FILTER_FIELDS_DEFAULT ]; protected function checkPermissions() { diff --git a/ui/app/partials/monitoring.latest.filter.php b/ui/app/partials/monitoring.latest.filter.php new file mode 100644 index 00000000000..a03c766df35 --- /dev/null +++ b/ui/app/partials/monitoring.latest.filter.php @@ -0,0 +1,364 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 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. +**/ + + +/** + * @var CPartial $this + * @var array $data + */ + +$left_column = (new CFormGrid()) + ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE) + ->addItem([ + new CLabel(_('Host groups'), 'groupids__ms'), + new CFormField( + (new CMultiSelect([ + 'name' => 'groupids[]', + 'object_name' => 'hostGroup', + 'data' => [], + 'popup' => [ + 'parameters' => [ + 'srctbl' => 'host_groups', + 'srcfld1' => 'groupid', + 'dstfrm' => 'zbx_filter', + 'dstfld1' => 'groupids_', + 'real_hosts' => true, + 'enrich_parent_groups' => true + ] + ] + ])) + ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) + ->setId('groupids_#{uniqid}') + ) + ]) + ->addItem([ + new CLabel(_('Hosts'), 'hostids__ms'), + new CFormField( + (new CMultiSelect([ + 'name' => 'hostids[]', + 'object_name' => 'hosts', + 'data' => [], + 'popup' => [ + 'filter_preselect_fields' => [ + 'hostgroups' => 'groupids_' + ], + 'parameters' => [ + 'srctbl' => 'hosts', + 'srcfld1' => 'hostid', + 'dstfrm' => 'zbx_filter', + 'dstfld1' => 'hostids_' + ] + ] + ])) + ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) + ->setId('hostids_#{uniqid}') + ) + ]) + ->addItem([ + new CLabel(_('Name'), 'name'), + new CFormField( + (new CTextBox('name', ''))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) + ) + ]); + +$filter_tags_table = new CTable(); +$filter_tags_table->setId('tags_#{uniqid}'); + +$filter_tags_table->addRow( + (new CCol( + (new CRadioButtonList('evaltype', (int) $data['evaltype'])) + ->addValue(_('And/Or'), TAG_EVAL_TYPE_AND_OR, 'evaltype_0#{uniqid}') + ->addValue(_('Or'), TAG_EVAL_TYPE_OR, 'evaltype_2#{uniqid}') + ->setModern(true) + ->setId('evaltype_#{uniqid}') + ))->setColSpan(4) +); + +$i = 0; +foreach ($data['tags'] as $tag) { + $filter_tags_table->addRow([ + (new CTextBox('tags['.$i.'][tag]', $tag['tag'])) + ->setAttribute('placeholder', _('tag')) + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH), + (new CSelect('tags['.$i.'][operator]')) + ->addOptions(CSelect::createOptionsFromArray([ + TAG_OPERATOR_EXISTS => _('Exists'), + TAG_OPERATOR_EQUAL => _('Equals'), + TAG_OPERATOR_LIKE => _('Contains'), + TAG_OPERATOR_NOT_EXISTS => _('Does not exist'), + TAG_OPERATOR_NOT_EQUAL => _('Does not equal'), + TAG_OPERATOR_NOT_LIKE => _('Does not contain') + ])) + ->setValue($tag['operator']) + ->setFocusableElementId('tags-'.$i.'#{uniqid}-operator-select') + ->setId('tags_'.$i.'#{uniqid}_operator'), + (new CTextBox('tags['.$i.'][value]', $tag['value'])) + ->setAttribute('placeholder', _('value')) + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH) + ->setId('tags_'.$i.'#{uniqid}_value'), + (new CCol( + (new CButton('tags['.$i.'][remove]', _('Remove'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('element-table-remove') + ->removeId() + ))->addClass(ZBX_STYLE_NOWRAP) + ], 'form_row'); + + $i++; +} +$filter_tags_table->addRow( + (new CCol( + (new CButton('tags_add', _('Add'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('element-table-add') + ->removeId() + ))->setColSpan(3) +); + +$right_column = (new CFormGrid()) + ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE) + ->addItem([ + new CLabel(_('Tags')), + new CFormField($filter_tags_table) + ]) + ->addItem([ + new CLabel(_('Show details')), + new CFormField([ + (new CCheckBox('show_details'))->setChecked(true), + (new CDiv([ + (new CLabel(_('Show items without data'), 'show_without_data')) + ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL), + (new CCheckBox('show_without_data')) + ->setChecked(true) + ->setAttribute('disabled', 'disabled') + ->setUncheckedValue(0) + ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN) + ]) + ]); + +$filter_template = (new CDiv()) + ->addClass(ZBX_STYLE_TABLE) + ->addClass(ZBX_STYLE_FILTER_FORMS) + ->addItem([ + (new CDiv($left_column))->addClass(ZBX_STYLE_CELL), + (new CDiv($right_column))->addClass(ZBX_STYLE_CELL) + ]); + +$template = (new CForm('get')) + ->cleanItems() + ->setName('zbx_filter') + ->addItem([ + $filter_template, + (new CSubmitButton(null))->addClass(ZBX_STYLE_DISPLAY_NONE), + (new CVar('filter_name', '#{filter_name}'))->removeId(), + (new CVar('filter_show_counter', '#{filter_show_counter}'))->removeId(), + (new CVar('filter_custom_time', '#{filter_custom_time}'))->removeId(), + (new CVar('sort', '#{sort}'))->removeId(), + (new CVar('sortorder', '#{sortorder}'))->removeId() + ]); + +if (array_key_exists('render_html', $data)) { + /** + * Render HTML to prevent filter flickering after initial page load. PHP created content will be replaced by + * javascript with additional event handling (dynamic rows, etc.) when page will be fully loaded and javascript + * executed. + */ + $template->show(); + + return; +} + +(new CScriptTemplate('filter-monitoring-latest')) + ->setAttribute('data-template', 'monitoring.latest.filter') + ->addItem($template) + ->show(); + +(new CScriptTemplate('filter-tag-row-tmpl')) + ->addItem( + (new CRow([ + (new CTextBox('tags[#{rowNum}][tag]', '#{tag}')) + ->setAttribute('placeholder', _('tag')) + ->removeId() + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH), + (new CSelect('tags[#{rowNum}][operator]')) + ->addOptions(CSelect::createOptionsFromArray([ + TAG_OPERATOR_EXISTS => _('Exists'), + TAG_OPERATOR_EQUAL => _('Equals'), + TAG_OPERATOR_LIKE => _('Contains'), + TAG_OPERATOR_NOT_EXISTS => _('Does not exist'), + TAG_OPERATOR_NOT_EQUAL => _('Does not equal'), + TAG_OPERATOR_NOT_LIKE => _('Does not contain') + ])) + ->setValue(TAG_OPERATOR_LIKE) + ->setFocusableElementId('tags-#{rowNum}#{uniqid}-operator-select') + ->setId('tags_#{rowNum}#{uniqid}_operator'), + (new CTextBox('tags[#{rowNum}][value]', '#{value}')) + ->setAttribute('placeholder', _('value')) + ->setId('tags_#{rowNum}#{uniqid}_value') + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH), + (new CCol( + (new CButton('tags[#{rowNum}][remove]', _('Remove'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('element-table-remove') + ->removeId() + ))->addClass(ZBX_STYLE_NOWRAP) + ])) + ->addClass('form_row') + ) + ->show(); +?> + +<script type="text/javascript"> + let template = document.querySelector('[data-template="monitoring.latest.filter"]'); + + function render(data, container) { + // "Save as" can contain only home tab, also home tab cannot contain "Update" button. + $('[name="filter_new"],[name="filter_update"]').hide() + .filter(data.filter_configurable ? '[name="filter_update"]' : '[name="filter_new"]').show(); + + // Host groups multiselect. + $('#groupids_' + data.uniqid, container).multiSelectHelper({ + id: 'groupids_' + data.uniqid, + object_name: 'hostGroup', + name: 'groupids[]', + data: data.filter_view_data.groups_multiselect || [], + objectOptions: { + real_hosts: 1, + enrich_parent_groups: 1 + }, + popup: { + parameters: { + multiselect: '1', + noempty: '1', + srctbl: 'host_groups', + srcfld1: 'groupid', + dstfrm: 'zbx_filter', + dstfld1: 'groupids_' + data.uniqid, + real_hosts: 1, + enrich_parent_groups: 1 + } + } + }); + + // Hosts multiselect. + $('#hostids_' + data.uniqid, container).multiSelectHelper({ + id: 'hostids_' + data.uniqid, + object_name: 'hosts', + name: 'hostids[]', + data: data.filter_view_data.hosts_multiselect || [], + popup: { + filter_preselect_fields: { + hostgroups: 'groupids_' + data.uniqid + }, + parameters: { + multiselect: 1, + srctbl: 'hosts', + srcfld1: 'hostid', + dstfrm: 'zbx_filter', + dstfld1: 'hostids_' + data.uniqid, + } + } + }); + + // Tags table + if (data.tags.length == 0) { + data.tags.push({'tag': '', 'value': '', 'operator': <?= TAG_OPERATOR_LIKE ?>, uniqid: data.uniqid}); + } + + $('#tags_' + data.uniqid, container) + .dynamicRows({ + template: '#filter-tag-row-tmpl', + rows: data.tags, + counter: 0, + dataCallback: (tag) => { + tag.uniqid = data.uniqid; + return tag; + } + }) + .on('afteradd.dynamicRows', function() { + var rows = this.querySelectorAll('.form_row'); + new CTagFilterItem(rows[rows.length - 1]); + }); + + // Init existing fields once loaded. + document.querySelectorAll('#tags_' + data.uniqid + ' .form_row').forEach(row => { + new CTagFilterItem(row); + }); + + // Input, radio and single checkboxes. + ['name', 'evaltype', 'show_without_data', 'show_details'].forEach((key) => { + var elm = $('[name="' + key + '"]', container); + + if (elm.is(':radio,:checkbox')) { + elm.filter('[value="' + data[key] + '"]').attr('checked', true); + } + else { + elm.val(data[key]); + } + }); + + // Show without data can be used only with 1+ hosts. + $('#hostids_' + data.uniqid, container) + .on('change', function () { + const no_hosts_selected = !$(this).multiSelect('getData').length; + if (no_hosts_selected) { + $('#show_without_data').prop('checked', true); + } + $('#show_without_data').prop('disabled', no_hosts_selected); + }) + .trigger('change'); + + // Initialize src_url. + this.resetUnsavedState(); + this.on(TABFILTERITEM_EVENT_ACTION, update.bind(this)); + } + + function expand(data, container) { + // "Save as" can contain only home tab, also home tab cannot contain "Update" button. + $('[name="filter_new"],[name="filter_update"]').hide() + .filter(data.filter_configurable ? '[name="filter_update"]' : '[name="filter_new"]').show(); + } + + /** + * On filter apply or update buttons press update disabled UI fields. + * + * @param {CustomEvent} ev CustomEvent object. + */ + function update(ev) { + let action = ev.detail.action, + container = this._content_container; + + if (action !== 'filter_apply' && action !== 'filter_update') { + return; + } + + $('[name="show_suppressed"]', container) + .filter(':disabled') + .prop('checked', false); + } + + // Tab filter item events handlers. + template.addEventListener(TABFILTERITEM_EVENT_RENDER, function (ev) { + render.call(ev.detail, ev.detail._data, ev.detail._content_container); + }); + template.addEventListener(TABFILTERITEM_EVENT_EXPAND, function (ev) { + expand.call(ev.detail, ev.detail._data, ev.detail._content_container); + }); +</script> diff --git a/ui/app/partials/monitoring.latest.view.html.php b/ui/app/partials/monitoring.latest.view.html.php index 3353b65a63c..84ea1cd5b3d 100644 --- a/ui/app/partials/monitoring.latest.view.html.php +++ b/ui/app/partials/monitoring.latest.view.html.php @@ -21,6 +21,7 @@ /** * @var CPartial $this + * @var array $data */ $form = (new CForm('GET', 'history.php')) diff --git a/ui/app/views/js/monitoring.latest.view.js.php b/ui/app/views/js/monitoring.latest.view.js.php index 4390ff705bf..68215e85c03 100644 --- a/ui/app/views/js/monitoring.latest.view.js.php +++ b/ui/app/views/js/monitoring.latest.view.js.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types = 1); /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA @@ -24,27 +24,90 @@ */ ?> -<script type="text/x-jquery-tmpl" id="filter-tag-row-tmpl"> - <?= CTagFilterFieldHelper::getTemplate(); ?> -</script> - <script> const view = { refresh_url: null, refresh_data: null, + + refresh_simple_url: null, refresh_interval: null, + refresh_counters: null, + running: false, timeout: null, _refresh_message_box: null, _popup_message_box: null, - init({refresh_url, refresh_data, refresh_interval}) { + init({refresh_url, refresh_data, refresh_interval, filter_options}) { this.refresh_url = refresh_url; this.refresh_data = refresh_data; this.refresh_interval = refresh_interval; - this.liveFilter(); - this.start(); + const url = new Curl('zabbix.php', false); + url.setArgument('action', 'latest.view.refresh'); + this.refresh_simple_url = url.getUrl(); + + this.initTabFilter(filter_options); + }, + + initTabFilter(filter_options) { + if (!filter_options) { + return; + } + + this.refresh_counters = this.createCountersRefresh(1); + this.filter = new CTabFilter(document.getElementById('monitoring_latest_filter'), filter_options); + this.filter.on(TABFILTER_EVENT_URLSET, () => { + this.reloadPartialAndTabCounters(); + }); + }, + + createCountersRefresh(timeout) { + if (this.refresh_counters) { + clearTimeout(this.refresh_counters); + this.refresh_counters = null; + } + + return setTimeout(() => this.getFiltersCounters(), timeout); + }, + + getFiltersCounters() { + return $.post(this.refresh_simple_url, { + filter_counters: 1 + }) + .done((json) => { + if (json.filter_counters) { + this.filter.updateCounters(json.filter_counters); + } + }) + .always(() => { + if (this.refresh_interval > 0) { + this.refresh_counters = this.createCountersRefresh(this.refresh_interval); + } + }); + }, + + reloadPartialAndTabCounters() { + this.refresh_url = new Curl('', false); + + this.unscheduleRefresh(); + this.refresh(); + + // Filter is not present in Kiosk mode. + if (this.filter) { + const filter_item = this.filter._active_item; + + if (this.filter._active_item.hasCounter()) { + $.post(this.refresh_simple_url, { + filter_counters: 1, + counter_index: filter_item._index + }).done((json) => { + if (json.filter_counters) { + filter_item.updateCounter(json.filter_counters.pop()); + } + }); + } + } }, getCurrentForm() { @@ -82,9 +145,20 @@ refresh() { this.setLoading(); + const params = this.refresh_url.getArgumentsObject(); + const exclude = ['action', 'filter_src', 'filter_show_counter', 'filter_custom_time', 'filter_name']; + const post_data = Object.keys(params) + .filter(key => !exclude.includes(key)) + .reduce((post_data, key) => { + post_data[key] = (typeof params[key] === 'object') + ? [...params[key]].filter(i => i) + : params[key]; + return post_data; + }, {}); + var deferred = $.ajax({ - url: this.refresh_url, - data: this.refresh_data, + url: this.refresh_simple_url, + data: post_data, type: 'post', dataType: 'json' }); @@ -156,10 +230,13 @@ scheduleRefresh() { this.unscheduleRefresh(); - this.timeout = setTimeout((function() { - this.timeout = null; - this.refresh(); - }).bind(this), this.refresh_interval); + + if (this.refresh_interval > 0) { + this.timeout = setTimeout((function () { + this.timeout = null; + this.refresh(); + }).bind(this), this.refresh_interval); + } }, unscheduleRefresh() { @@ -167,47 +244,12 @@ clearTimeout(this.timeout); this.timeout = null; } - }, - start() { - if (this.refresh_interval != 0) { - this.running = true; - this.scheduleRefresh(); + if (this.deferred) { + this.deferred.abort(); } }, - stop() { - this.running = false; - this.unscheduleRefresh(); - }, - - liveFilter() { - var $filter_hostids = $('#filter_hostids_'), - $filter_show_without_data = $('#filter_show_without_data'); - - $filter_hostids.on('change', function() { - var no_hosts_selected = !$(this).multiSelect('getData').length; - - if (no_hosts_selected) { - $filter_show_without_data.prop('checked', true); - } - - $filter_show_without_data.prop('disabled', no_hosts_selected); - }); - - $('#filter-tags') - .dynamicRows({template: '#filter-tag-row-tmpl'}) - .on('afteradd.dynamicRows', function() { - var rows = this.querySelectorAll('.form_row'); - new CTagFilterItem(rows[rows.length - 1]); - }); - - // Init existing fields once loaded. - document.querySelectorAll('#filter-tags .form_row').forEach(row => { - new CTagFilterItem(row); - }); - }, - editHost(hostid) { const host_data = {hostid}; @@ -267,5 +309,5 @@ view.refresh(); } } - } + }; </script> diff --git a/ui/app/views/monitoring.latest.view.php b/ui/app/views/monitoring.latest.view.php index bd83321590a..32b269a77a9 100644 --- a/ui/app/views/monitoring.latest.view.php +++ b/ui/app/views/monitoring.latest.view.php @@ -1,4 +1,4 @@ -<?php +<?php declare(strict_types = 1); /* ** Zabbix ** Copyright (C) 2001-2021 Zabbix SIA @@ -25,6 +25,8 @@ $this->addJsFile('layout.mode.js'); $this->addJsFile('class.tagfilteritem.js'); +$this->addJsFile('class.tabfilter.js'); +$this->addJsFile('class.tabfilteritem.js'); $this->includeJsFile('monitoring.latest.view.js.php'); @@ -40,70 +42,22 @@ $widget = (new CWidget()) ); if ($web_layout_mode == ZBX_LAYOUT_NORMAL) { - $widget->addItem((new CFilter()) - ->setResetUrl((new CUrl('zabbix.php'))->setArgument('action', 'latest.view')) - ->setProfile('web.latest.filter') - ->setActiveTab($data['active_tab']) - ->addFormItem((new CVar('action', 'latest.view'))->removeId()) - ->addFilterTab(_('Filter'), [ - (new CFormList()) - ->addRow((new CLabel(_('Host groups'), 'filter_groupids__ms')), - (new CMultiSelect([ - 'name' => 'filter_groupids[]', - 'object_name' => 'hostGroup', - 'data' => $data['multiselect_hostgroup_data'], - 'popup' => [ - 'parameters' => [ - 'srctbl' => 'host_groups', - 'srcfld1' => 'groupid', - 'dstfrm' => 'zbx_filter', - 'dstfld1' => 'filter_groupids_', - 'real_hosts' => true, - 'enrich_parent_groups' => true - ] - ] - ]))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) - ) - ->addRow((new CLabel(_('Hosts'), 'filter_hostids__ms')), - (new CMultiSelect([ - 'name' => 'filter_hostids[]', - 'object_name' => 'hosts', - 'data' => $data['multiselect_host_data'], - 'popup' => [ - 'filter_preselect_fields' => [ - 'hostgroups' => 'filter_groupids_' - ], - 'parameters' => [ - 'srctbl' => 'hosts', - 'srcfld1' => 'hostid', - 'dstfrm' => 'zbx_filter', - 'dstfld1' => 'filter_hostids_' - ] - ] - ]))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) - ) - ->addRow(_('Name'), - (new CTextBox('filter_select', $data['filter']['select'])) - ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) - ), - (new CFormList()) - ->addRow(_('Tags'), CTagFilterFieldHelper::getTagFilterField([ - 'evaltype' => $data['filter']['evaltype'], - 'tags' => $data['filter']['tags'] - ])) - ->addRow(_('Show details'), [ - (new CCheckBox('filter_show_details'))->setChecked($data['filter']['show_details'] == 1), - (new CDiv([ - (new CLabel(_('Show items without data'), 'filter_show_without_data')) - ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL), - (new CCheckBox('filter_show_without_data')) - ->setChecked($data['filter']['show_without_data'] == 1) - ->setAttribute('disabled', $data['filter']['hostids'] ? null : 'disabled') - ->setUncheckedValue(0) - ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN) - ]) - ]) - ); + $filter = (new CTabFilter()) + ->setId('monitoring_latest_filter') + ->setOptions($data['tabfilter_options']) + ->addTemplate(new CPartial($data['filter_view'], $data['filter_defaults'])); + + foreach ($data['filter_tabs'] as $tab) { + $tab['tab_view'] = $data['filter_view']; + $filter->addTemplatedTab($tab['filter_name'], $tab); + } + + // Set javascript options for tab filter initialization in monitoring.latest.view.js.php file. + $data['filter_options'] = $filter->options; + $widget->addItem($filter); +} +else { + $data['filter_options'] = null; } $widget->addItem(new CPartial('monitoring.latest.view.html', array_intersect_key($data, @@ -116,6 +70,7 @@ $widget->show(); (new CScriptTag(' view.init('.json_encode([ + 'filter_options' => $data['filter_options'], 'refresh_url' => $data['refresh_url'], 'refresh_data' => $data['refresh_data'], 'refresh_interval' => $data['refresh_interval'] diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index 533fd60dc50..eb7617c0c44 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -22,7 +22,7 @@ define('ZABBIX_VERSION', '6.0.0alpha8'); define('ZABBIX_API_VERSION', '6.0.0'); define('ZABBIX_EXPORT_VERSION', '6.0'); -define('ZABBIX_DB_VERSION', 5050111); +define('ZABBIX_DB_VERSION', 5050112); define('DB_VERSION_SUPPORTED', 0); define('DB_VERSION_LOWER_THAN_MINIMUM', 1); |