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
path: root/ui/app
diff options
context:
space:
mode:
authorAndrejs Verza <andrejs.verza@zabbix.com>2020-10-11 11:10:21 +0300
committerAndrejs Verza <andrejs.verza@zabbix.com>2020-10-11 11:10:21 +0300
commit9e7ea552f0dc6af69881656c1c4995d9320ed41b (patch)
tree00e1ce11a4985847b070d138139802e10d35e9f0 /ui/app
parent617c51a6641d9d792b4f2f340ed428a3f4877c42 (diff)
parent5d4bbbeb417f13ac4e8d6e5bc64efaab0c14f6b3 (diff)
.......... [ZBXNEXT-6001] updated to the latest master branch (conflicts solved)
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/controllers/CControllerHost.php170
-rw-r--r--ui/app/controllers/CControllerHostView.php176
-rw-r--r--ui/app/controllers/CControllerHostViewRefresh.php121
-rw-r--r--ui/app/controllers/CControllerNotificationsGet.php8
-rw-r--r--ui/app/controllers/CControllerPopupTabFilterDelete.php68
-rw-r--r--ui/app/controllers/CControllerPopupTabFilterEdit.php126
-rw-r--r--ui/app/controllers/CControllerPopupTabFilterUpdate.php123
-rw-r--r--ui/app/controllers/CControllerPopupTriggerExpr.php50
-rw-r--r--ui/app/controllers/CControllerPopupTriggerWizard.php8
-rw-r--r--ui/app/controllers/CControllerProblem.php173
-rw-r--r--ui/app/controllers/CControllerProblemView.php333
-rw-r--r--ui/app/controllers/CControllerProblemViewRefresh.php52
-rw-r--r--ui/app/controllers/CControllerTabFilterProfileUpdate.php171
-rw-r--r--ui/app/controllers/CControllerTimeSelectorUpdate.php18
-rw-r--r--ui/app/partials/monitoring.host.filter.php315
-rw-r--r--ui/app/partials/monitoring.host.view.html.php10
-rw-r--r--ui/app/partials/monitoring.problem.filter.php641
-rw-r--r--ui/app/partials/timeselector.filter.php111
-rw-r--r--ui/app/views/js/monitoring.host.view.js.php98
-rw-r--r--ui/app/views/js/monitoring.problem.view.js.php199
-rw-r--r--ui/app/views/js/popup.tabfilter.edit.js.php84
-rw-r--r--ui/app/views/js/popup.triggerwizard.js.php6
-rw-r--r--ui/app/views/monitoring.host.view.php144
-rw-r--r--ui/app/views/monitoring.problem.view.php314
-rw-r--r--ui/app/views/monitoring.widget.problemhosts.view.php25
-rw-r--r--ui/app/views/monitoring.widget.problemsbysv.view.php11
-rw-r--r--ui/app/views/popup.tabfilter.edit.php93
-rw-r--r--ui/app/views/popup.triggerexpr.php7
-rw-r--r--ui/app/views/popup.triggerwizard.php6
-rw-r--r--ui/app/views/search.php8
30 files changed, 2588 insertions, 1081 deletions
diff --git a/ui/app/controllers/CControllerHost.php b/ui/app/controllers/CControllerHost.php
index 171d8985d69..c9ad329f56e 100644
--- a/ui/app/controllers/CControllerHost.php
+++ b/ui/app/controllers/CControllerHost.php
@@ -25,8 +25,29 @@
*/
abstract class CControllerHost extends CController {
+ // Filter idx prefix.
+ const FILTER_IDX = 'web.monitoring.hosts';
+
+ // Filter fields default values.
+ const FILTER_FIELDS_DEFAULT = [
+ 'name' => '',
+ 'groupids' => [],
+ 'ip' => '',
+ 'dns' => '',
+ 'port' => '',
+ 'status' => -1,
+ 'evaltype' => TAG_EVAL_TYPE_AND_OR,
+ 'tags' => [],
+ 'severities' => [],
+ 'show_suppressed' => ZBX_PROBLEM_SUPPRESSED_FALSE,
+ 'maintenance_status' => HOST_MAINTENANCE_STATUS_ON,
+ 'page' => null,
+ 'sort' => 'name',
+ 'sortorder' => ZBX_SORT_UP
+ ];
+
/**
- * Prepares the host list based on the given filter and sorting options.
+ * Get host list results count for passed filter.
*
* @param array $filter Filter options.
* @param string $filter['name'] Filter hosts by name.
@@ -40,51 +61,61 @@ abstract class CControllerHost extends CController {
* @param string $filter['severities'] Filter problems on hosts by severities.
* @param string $filter['show_suppressed'] Filter suppressed problems.
* @param int $filter['maintenance_status'] Filter hosts by maintenance.
- * @param int $filter['page'] Page number.
- * @param string $sort Sorting field.
- * @param string $sortorder Sorting order.
*
- * @return array
+ * @return int
*/
- protected function prepareData(array $filter, string $sort, string $sortorder): array {
- $child_groups = [];
-
- // Multiselect host groups.
- $multiselect_hostgroup_data = [];
-
- if ($filter['groupids']) {
- $groups = API::HostGroup()->get([
- 'output' => ['groupid', 'name'],
- 'groupids' => $filter['groupids'],
- 'preservekeys' => true
- ]);
+ protected function getCount(array $filter): int {
+ $groupids = $filter['groupids'] ? getSubGroups($filter['groupids']) : null;
- if ($groups) {
- $subgroup_names = [];
-
- foreach ($groups as $group) {
- $subgroup_names[] = $group['name'].'/';
-
- $multiselect_hostgroup_data[] = [
- 'id' => $group['groupid'],
- 'name' => $group['name']
- ];
- }
-
- $groups += API::HostGroup()->get([
- 'output' => ['groupid'],
- 'search' => ['name' => $subgroup_names],
- 'startSearch' => true,
- 'searchByAny' => true,
- 'preservekeys' => true
- ]);
- }
+ return (int) API::Host()->get([
+ 'countOutput' => true,
+ 'evaltype' => $filter['evaltype'],
+ 'tags' => $filter['tags'],
+ 'inheritedTags' => true,
+ 'groupids' => $groupids ? $groupids : null,
+ 'severities' => $filter['severities'] ? $filter['severities'] : null,
+ 'withProblemsSuppressed' => $filter['severities']
+ ? (($filter['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE) ? null : false)
+ : null,
+ 'search' => [
+ 'name' => ($filter['name'] === '') ? null : $filter['name'],
+ 'ip' => ($filter['ip'] === '') ? null : $filter['ip'],
+ 'dns' => ($filter['dns'] === '') ? null : $filter['dns']
+ ],
+ 'filter' => [
+ 'status' => ($filter['status'] == -1) ? null : $filter['status'],
+ 'port' => ($filter['port'] === '') ? null : $filter['port'],
+ 'maintenance_status' => ($filter['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON)
+ ? null
+ : HOST_MAINTENANCE_STATUS_OFF
+ ],
+ 'limit' => CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1
+ ]);
+ }
- $groupids = array_keys($groups);
- }
- else {
- $groupids = null;
- }
+ /**
+ * Prepares the host list based on the given filter and sorting options.
+ *
+ * @param array $filter Filter options.
+ * @param string $filter['name'] Filter hosts by name.
+ * @param array $filter['groupids'] Filter hosts by host groups.
+ * @param string $filter['ip'] Filter hosts by IP.
+ * @param string $filter['dns'] Filter hosts by DNS.
+ * @param string $filter['port'] Filter hosts by port.
+ * @param string $filter['status'] Filter hosts by status.
+ * @param string $filter['evaltype'] Filter hosts by tags.
+ * @param string $filter['tags'] Filter hosts by tag names and values.
+ * @param string $filter['severities'] Filter problems on hosts by severities.
+ * @param string $filter['show_suppressed'] Filter supressed problems.
+ * @param int $filter['maintenance_status'] Filter hosts by maintenance.
+ * @param int $filter['page'] Page number.
+ * @param string $filter['sort'] Sorting field.
+ * @param string $filter['sortorder'] Sorting order.
+ *
+ * @return array
+ */
+ protected function getData(array $filter): array {
+ $groupids = $filter['groupids'] ? getSubGroups($filter['groupids'], $filter_groups) : null;
$limit = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + 1;
$hosts = API::Host()->get([
@@ -92,7 +123,7 @@ abstract class CControllerHost extends CController {
'evaltype' => $filter['evaltype'],
'tags' => $filter['tags'],
'inheritedTags' => true,
- 'groupids' => $groupids,
+ 'groupids' => $groupids ? $groupids : null,
'severities' => $filter['severities'] ? $filter['severities'] : null,
'withProblemsSuppressed' => $filter['severities']
? (($filter['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE) ? null : false)
@@ -115,14 +146,14 @@ abstract class CControllerHost extends CController {
]);
// Sort for paging so we know which IDs go to which page.
- CArrayHelper::sort($hosts, [['field' => $sort, 'order' => $sortorder]]);
+ CArrayHelper::sort($hosts, [['field' => $filter['sort'], 'order' => $filter['sortorder']]]);
- $view_curl = (new CUrl('zabbix.php'))->setArgument('action', 'host.view');
+ $view_curl = (new CUrl())->setArgument('action', 'host.view');
// Split result array and create paging.
- $paging = CPagerHelper::paginate($filter['page'], $hosts, $sortorder, $view_curl);
+ $paging = CPagerHelper::paginate($filter['page'], $hosts, $filter['sortorder'], $view_curl);
- // Get additional data to limited host amount.
+ // Get additonal data to limited host amount.
$hosts = API::Host()->get([
'output' => ['hostid', 'name', 'status', 'maintenance_status', 'maintenanceid', 'maintenance_type',
'available', 'snmp_available', 'jmx_available', 'ipmi_available', 'error', 'ipmi_error', 'snmp_error',
@@ -137,7 +168,7 @@ abstract class CControllerHost extends CController {
'preservekeys' => true
]);
// Re-sort the results again.
- CArrayHelper::sort($hosts, [['field' => $sort, 'order' => $sortorder]]);
+ CArrayHelper::sort($hosts, [['field' => $filter['sort'], 'order' => $filter['sortorder']]]);
$maintenanceids = [];
@@ -234,11 +265,46 @@ abstract class CControllerHost extends CController {
return [
'paging' => $paging,
- 'view_curl' => $view_curl,
'hosts' => $hosts,
- 'maintenances' => $maintenances,
- 'multiselect_hostgroup_data' => $multiselect_hostgroup_data,
- 'filter' => $filter
+ 'maintenances' => $maintenances
];
}
+
+ /**
+ * 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']);
+ }
+
+ 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('tags', $input) && $input['tags']) {
+ $input['tags'] = array_filter($input['tags'], function($tag) {
+ return !($tag['tag'] === '' && $tag['value'] === '');
+ });
+ }
+
+ return $input;
+ }
}
diff --git a/ui/app/controllers/CControllerHostView.php b/ui/app/controllers/CControllerHostView.php
index 83a8ae673c3..8d7eb96df5c 100644
--- a/ui/app/controllers/CControllerHostView.php
+++ b/ui/app/controllers/CControllerHostView.php
@@ -28,29 +28,32 @@ class CControllerHostView extends CControllerHost {
protected function checkInput(): bool {
$fields = [
- 'sort' => 'in name,status',
- 'sortorder' => 'in '.ZBX_SORT_UP.','.ZBX_SORT_DOWN,
- 'page' => 'ge 1',
- 'filter_set' => 'in 1',
- 'filter_rst' => 'in 1',
- 'filter_name' => 'string',
- 'filter_groupids' => 'array_id',
- 'filter_ip' => 'string',
- 'filter_dns' => 'string',
- 'filter_port' => 'string',
- 'filter_status' => 'in -1,'.HOST_STATUS_MONITORED.','.HOST_STATUS_NOT_MONITORED,
- 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR,
- 'filter_tags' => 'array',
- 'filter_severities' => 'array',
- 'filter_show_suppressed' => 'in '.ZBX_PROBLEM_SUPPRESSED_FALSE.','.ZBX_PROBLEM_SUPPRESSED_TRUE,
- 'filter_maintenance_status' => 'in '.HOST_MAINTENANCE_STATUS_OFF.','.HOST_MAINTENANCE_STATUS_ON
+ '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',
+ 'counter_index' => 'ge 0'
];
$ret = $this->validateInput($fields);
// Validate tags filter.
- if ($ret && $this->hasInput('filter_tags')) {
- foreach ($this->getInput('filter_tags') as $filter_tag) {
+ 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'])
@@ -62,13 +65,10 @@ class CControllerHostView extends CControllerHost {
}
// Validate severity checkbox filter.
- if ($ret && $this->hasInput('filter_severities')) {
- foreach ($this->getInput('filter_severities') as $severity) {
- if (!in_array($severity, range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1))) {
- $ret = false;
- break;
- }
- }
+ if ($ret && $this->hasInput('severities')) {
+ $ret = !array_diff($this->getInput('severities'),
+ range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1)
+ );
}
if (!$ret) {
@@ -83,118 +83,34 @@ class CControllerHostView extends CControllerHost {
}
protected function doAction(): void {
- $sort = $this->getInput('sort', CProfile::get('web.hostsmon.sort', 'name'));
- $sortorder = $this->getInput('sortorder', CProfile::get('web.hostsmon.sortorder', ZBX_SORT_UP));
- $active_tab = CProfile::get('web.hostsmon.filter.active', 1);
- CProfile::update('web.hostsmon.filter.active', $active_tab, PROFILE_TYPE_INT);
- CProfile::update('web.hostsmon.sort', $sort, PROFILE_TYPE_STR);
- CProfile::update('web.hostsmon.sortorder', $sortorder, PROFILE_TYPE_STR);
-
- // filter
- if ($this->hasInput('filter_set')) {
- CProfile::update('web.hostsmon.filter.name', $this->getInput('filter_name', ''), PROFILE_TYPE_STR);
- CProfile::updateArray('web.hostsmon.filter.groupids', $this->getInput('filter_groupids', []),
- PROFILE_TYPE_ID
- );
- CProfile::update('web.hostsmon.filter.ip', $this->getInput('filter_ip', ''), PROFILE_TYPE_STR);
- CProfile::update('web.hostsmon.filter.dns', $this->getInput('filter_dns', ''), PROFILE_TYPE_STR);
- CProfile::update('web.hostsmon.filter.port', $this->getInput('filter_port', ''), PROFILE_TYPE_STR);
- $severities = $this->getInput('filter_severities', []);
- CProfile::updateArray('web.hostsmon.filter.severities', $severities, PROFILE_TYPE_INT);
- CProfile::update('web.hostsmon.filter.status', getRequest('filter_status', -1), PROFILE_TYPE_INT);
-
- $filter_tags = ['tags' => [], 'values' => [], 'operators' => []];
- foreach ($this->getInput('filter_tags', []) as $filter_tag) {
- if ($filter_tag['tag'] === '' && $filter_tag['value'] === '') {
- continue;
- }
-
- $filter_tags['tags'][] = $filter_tag['tag'];
- $filter_tags['values'][] = $filter_tag['value'];
- $filter_tags['operators'][] = $filter_tag['operator'];
- }
-
- CProfile::update('web.hostsmon.filter.evaltype', $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR),
- PROFILE_TYPE_INT
- );
- CProfile::updateArray('web.hostsmon.filter.tags.tag', $filter_tags['tags'], PROFILE_TYPE_STR);
- CProfile::updateArray('web.hostsmon.filter.tags.value', $filter_tags['values'], PROFILE_TYPE_STR);
- CProfile::updateArray('web.hostsmon.filter.tags.operator', $filter_tags['operators'], PROFILE_TYPE_INT);
- CProfile::update('web.hostsmon.filter.show_suppressed',
- $this->getInput('filter_show_suppressed', ZBX_PROBLEM_SUPPRESSED_FALSE), PROFILE_TYPE_INT
- );
- CProfile::update('web.hostsmon.filter.maintenance_status',
- $this->getInput('filter_maintenance_status', HOST_MAINTENANCE_STATUS_ON), PROFILE_TYPE_INT
- );
- }
- elseif ($this->hasInput('filter_rst')) {
- CProfile::delete('web.hostsmon.filter.name');
- CProfile::deleteIdx('web.hostsmon.filter.groupids');
- CProfile::delete('web.hostsmon.filter.ip');
- CProfile::delete('web.hostsmon.filter.dns');
- CProfile::delete('web.hostsmon.filter.port');
- CProfile::deleteIdx('web.hostsmon.filter.severities');
- CProfile::delete('web.hostsmon.filter.status');
- CProfile::delete('web.hostsmon.filter.show_suppressed');
- CProfile::delete('web.hostsmon.filter.maintenance_status');
- CProfile::delete('web.hostsmon.filter.evaltype');
- CProfile::deleteIdx('web.hostsmon.filter.tags.tag');
- CProfile::deleteIdx('web.hostsmon.filter.tags.value');
- CProfile::deleteIdx('web.hostsmon.filter.tags.operator');
- }
+ $filter_tabs = [];
+ $profile = (new CTabFilterProfile(static::FILTER_IDX, static::FILTER_FIELDS_DEFAULT))
+ ->read()
+ ->setInput($this->cleanInput($this->getInputAll()));
- $filter_tags = [];
- foreach (CProfile::getArray('web.hostsmon.filter.tags.tag', []) as $i => $tag) {
- $filter_tags[] = [
- 'tag' => $tag,
- 'value' => CProfile::get('web.hostsmon.filter.tags.value', null, $i),
- 'operator' => CProfile::get('web.hostsmon.filter.tags.operator', null, $i)
- ];
+ foreach ($profile->getTabsWithDefaults() as $filter_tab) {
+ $filter_tabs[] = $filter_tab + ['filter_view_data' => $this->getAdditionalData($filter_tab)];
}
- CArrayHelper::sort($filter_tags, ['tag', 'value', 'operator']);
-
- $filter = [
- 'name' => CProfile::get('web.hostsmon.filter.name', ''),
- 'groupids' => CProfile::getArray('web.hostsmon.filter.groupids', []),
- 'ip' => CProfile::get('web.hostsmon.filter.ip', ''),
- 'dns' => CProfile::get('web.hostsmon.filter.dns', ''),
- 'port' => CProfile::get('web.hostsmon.filter.port', ''),
- 'status' => CProfile::get('web.hostsmon.filter.status', -1),
- 'evaltype' => CProfile::get('web.hostsmon.filter.evaltype', TAG_EVAL_TYPE_AND_OR),
- 'tags' => $filter_tags,
- 'severities' => CProfile::getArray('web.hostsmon.filter.severities', []),
- 'show_suppressed' => CProfile::get('web.hostsmon.filter.show_suppressed', ZBX_PROBLEM_SUPPRESSED_FALSE),
- 'maintenance_status' => CProfile::get('web.hostsmon.filter.maintenance_status', HOST_MAINTENANCE_STATUS_ON),
- 'page' => $this->hasInput('page') ? $this->getInput('page') : null
- ];
- $refresh_curl = (new CUrl('zabbix.php'))
- ->setArgument('action', 'host.view.refresh')
- ->setArgument('filter_name', $filter['name'])
- ->setArgument('filter_groupids', $filter['groupids'])
- ->setArgument('filter_ip', $filter['ip'])
- ->setArgument('filter_dns', $filter['dns'])
- ->setArgument('filter_port', $filter['port'])
- ->setArgument('filter_status', $filter['status'])
- ->setArgument('filter_evaltype', $filter['evaltype'])
- ->setArgument('filter_tags', $filter['tags'])
- ->setArgument('filter_severities', $filter['severities'])
- ->setArgument('filter_show_suppressed', $filter['show_suppressed'])
- ->setArgument('filter_maintenance_status', $filter['maintenance_status'])
- ->setArgument('sort', $sort)
- ->setArgument('sortorder', $sortorder)
- ->setArgument('page', $filter['page']);
-
- $prepared_data = $this->prepareData($filter, $sort, $sortorder);
+ $filter = $profile->getTabFilter($profile->selected);
+ $refresh_curl = new CUrl('zabbix.php');
+ $filter['action'] = 'host.view.refresh';
+ array_map([$refresh_curl, 'setArgument'], array_keys($filter), $filter);
$data = [
- 'filter' => $filter,
- 'sort' => $sort,
- 'sortorder' => $sortorder,
'refresh_url' => $refresh_curl->getUrl(),
'refresh_interval' => CWebUser::getRefresh() * 1000,
- 'active_tab' => $active_tab
- ] + $prepared_data;
+ 'filter_view' => 'monitoring.host.filter',
+ 'filter_defaults' => $profile->filter_defaults,
+ 'filter_tabs' => $filter_tabs,
+ 'tabfilter_options' => [
+ 'idx' => static::FILTER_IDX,
+ 'selected' => $profile->selected,
+ 'support_custom_time' => 0,
+ 'expanded' => $profile->expanded,
+ 'page' => $filter['page']
+ ],
+ ] + $this->getData($filter);
$response = new CControllerResponseData($data);
$response->setTitle(_('Hosts'));
diff --git a/ui/app/controllers/CControllerHostViewRefresh.php b/ui/app/controllers/CControllerHostViewRefresh.php
index ae7cfdae677..6ea392e1ea7 100644
--- a/ui/app/controllers/CControllerHostViewRefresh.php
+++ b/ui/app/controllers/CControllerHostViewRefresh.php
@@ -23,99 +23,46 @@
/**
* Controller for the "Host->Monitoring" asynchronous refresh page.
*/
-class CControllerHostViewRefresh extends CControllerHost {
+class CControllerHostViewRefresh extends CControllerHostView {
- protected function init(): void {
- $this->disableSIDValidation();
- }
-
- protected function checkInput(): bool {
- $fields = [
- 'sort' => 'in name,status',
- 'sortorder' => 'in '.ZBX_SORT_UP.','.ZBX_SORT_DOWN,
- 'page' => 'ge 1',
- 'filter_set' => 'in 1',
- 'filter_rst' => 'in 1',
- 'filter_name' => 'string',
- 'filter_groupids' => 'array_id',
- 'filter_ip' => 'string',
- 'filter_dns' => 'string',
- 'filter_port' => 'string',
- 'filter_status' => 'in -1,'.HOST_STATUS_MONITORED.','.HOST_STATUS_NOT_MONITORED,
- 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR,
- 'filter_tags' => 'array',
- 'filter_severities' => 'array',
- 'filter_show_suppressed' => 'in '.ZBX_PROBLEM_SUPPRESSED_FALSE.','.ZBX_PROBLEM_SUPPRESSED_TRUE,
- 'filter_maintenance_status' => 'in '.HOST_MAINTENANCE_STATUS_OFF.','.HOST_MAINTENANCE_STATUS_ON
- ];
+ protected function doAction(): void {
+ $filter = static::FILTER_FIELDS_DEFAULT;
- $ret = $this->validateInput($fields);
+ 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();
+ $filter_counters = [];
- // Validate tags filter.
- if ($ret && $this->hasInput('filter_tags')) {
- foreach ($this->getInput('filter_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;
- }
+ foreach ($filters as $index => $tabfilter) {
+ $filter_counters[$index] = $tabfilter['filter_show_counter'] ? $this->getCount($tabfilter) : 0;
}
- }
- // Validate severity checkbox filter.
- if ($ret && $this->hasInput('filter_severities')) {
- foreach ($this->getInput('filter_severities') as $severity) {
- if (!in_array($severity, range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1))) {
- $ret = false;
- break;
- }
- }
+ $this->setResponse(
+ (new CControllerResponseData([
+ 'main_block' => json_encode(['filter_counters' => $filter_counters])
+ ]))->disableView()
+ );
}
-
- if (!$ret) {
- $this->setResponse(new CControllerResponseFatal());
+ else {
+ $this->getInputs($filter, array_keys($filter));
+ $filter = $this->cleanInput($filter);
+ $prepared_data = $this->getData($filter);
+
+ $view_url = (new CUrl())
+ ->setArgument('action', 'host.view')
+ ->removeArgument('page');
+
+ $data = [
+ 'filter' => $filter,
+ 'view_curl' => $view_url,
+ 'sort' => $filter['sort'],
+ 'sortorder' => $filter['sortorder']
+ ] + $prepared_data;
+
+ $response = new CControllerResponseData($data);
+ $this->setResponse($response);
}
-
- return $ret;
- }
-
- protected function checkPermissions(): bool {
- return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
- }
-
- protected function doAction(): void {
- $filter = [
- 'name' => $this->getInput('filter_name', ''),
- 'groupids' => $this->hasInput('filter_groupids') ? $this->getInput('filter_groupids') : null,
- 'ip' => $this->getInput('filter_ip', ''),
- 'dns' => $this->getInput('filter_dns', ''),
- 'port' => $this->getInput('filter_port', ''),
- 'status' => $this->getInput('filter_status', -1),
- 'evaltype' => $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR),
- 'tags' => $this->getInput('filter_tags', []),
- 'severities' => $this->getInput('filter_severities', []),
- 'show_suppressed' => $this->getInput('filter_show_suppressed', ZBX_PROBLEM_SUPPRESSED_FALSE),
- 'maintenance_status' => $this->getInput('filter_maintenance_status', HOST_MAINTENANCE_STATUS_ON),
- 'page' => $this->hasInput('page') ? $this->getInput('page') : null
- ];
-
- $sort = $this->getInput('sort', 'name');
- $sortorder = $this->getInput('sortorder', ZBX_SORT_UP);
-
- $view_curl = (new CUrl('zabbix.php'))->setArgument('action', 'host.view');
-
- $prepared_data = $this->prepareData($filter, $sort, $sortorder);
-
- $data = [
- 'filter' => $filter,
- 'sort' => $sort,
- 'sortorder' => $sortorder,
- 'view_curl' => $view_curl
- ] + $prepared_data;
-
- $response = new CControllerResponseData($data);
- $this->setResponse($response);
}
}
diff --git a/ui/app/controllers/CControllerNotificationsGet.php b/ui/app/controllers/CControllerNotificationsGet.php
index 1e772334edc..d3700e64a65 100644
--- a/ui/app/controllers/CControllerNotificationsGet.php
+++ b/ui/app/controllers/CControllerNotificationsGet.php
@@ -166,14 +166,14 @@ class CControllerNotificationsGet extends CController {
$url_problems = (new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_hostids[]', $trigger['hosts'][0]['hostid'])
- ->setArgument('filter_set', '1')
+ ->setArgument('filter_name', '')
+ ->setArgument('hostids[]', $trigger['hosts'][0]['hostid'])
->getUrl();
$url_events = (new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_triggerids[]', $triggerid)
- ->setArgument('filter_set', '1')
+ ->setArgument('filter_name', '')
+ ->setArgument('triggerids[]', $triggerid)
->getUrl();
$url_trigger_events_pt = (new CUrl('tr_events.php'))->setArgument('triggerid', $triggerid);
diff --git a/ui/app/controllers/CControllerPopupTabFilterDelete.php b/ui/app/controllers/CControllerPopupTabFilterDelete.php
new file mode 100644
index 00000000000..7b7d2ae9ed4
--- /dev/null
+++ b/ui/app/controllers/CControllerPopupTabFilterDelete.php
@@ -0,0 +1,68 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+
+/**
+ * Controller to delete tab filter by idx and idx2.
+ */
+class CControllerPopupTabFilterDelete extends CController {
+
+ protected function init() {
+ $this->disableSIDValidation();
+ }
+
+ protected function checkInput() {
+ $rules = [
+ 'idx' => 'string|required',
+ 'idx2' => 'int32|required'
+ ];
+
+ $ret = $this->validateInput($rules);
+
+ if (!$ret) {
+ $output = [];
+
+ if (($messages = getMessages()) !== null) {
+ $output['errors'] = $messages->toString();
+ }
+
+ $this->setResponse(new CControllerResponseData(['main_block' => json_encode($output)]));
+ }
+
+ return $ret;
+ }
+
+ protected function checkPermissions() {
+ return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
+ }
+
+ protected function doAction() {
+ $idx = $this->getInput('idx');
+ $idx2 = $this->getInput('idx2');
+
+ (new CTabFilterProfile($idx, []))
+ ->read()
+ ->deleteTab((int) $idx2)
+ ->update();
+
+ $this->setResponse(new CControllerResponseData(['main_block' => json_encode([])]));
+
+ }
+}
diff --git a/ui/app/controllers/CControllerPopupTabFilterEdit.php b/ui/app/controllers/CControllerPopupTabFilterEdit.php
new file mode 100644
index 00000000000..f78c488f77e
--- /dev/null
+++ b/ui/app/controllers/CControllerPopupTabFilterEdit.php
@@ -0,0 +1,126 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+
+/**
+ * Controller to load tab filter properties dialog.
+ */
+class CControllerPopupTabFilterEdit extends CController {
+
+ protected function init() {
+ $this->disableSIDValidation();
+ }
+
+ protected function checkInput() {
+ $rules = [
+ 'idx' => 'string|required',
+ 'idx2' => 'int32|required',
+ 'filter_name' => 'string',
+ 'filter_show_counter' => 'in 0,1',
+ 'filter_custom_time' => 'in 0,1',
+ 'tabfilter_from' => 'string',
+ 'tabfilter_to' => 'string',
+ 'support_custom_time' => 'in 0,1',
+ 'create' => 'in 0,1'
+ ];
+
+ $ret = $this->validateInput($rules) && $this->customValidation();
+
+ if (!$ret) {
+ $output = [];
+
+ if (($messages = getMessages()) !== null) {
+ $output['errors'] = $messages->toString();
+ }
+
+ $this->setResponse(
+ (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView()
+ );
+ }
+
+ return $ret;
+ }
+
+ protected function customValidation(): bool {
+ if (!$this->getInput('support_custom_time', 0) || $this->getInput('filter_custom_time', 0)) {
+ return true;
+ }
+
+ $rules = [
+ 'tabfilter_from' => 'range_time|required',
+ 'tabfilter_to' => 'range_time|required',
+ ];
+
+ $validator = new CNewValidator($this->getInputAll(), $rules);
+ $ret = !$validator->isError() && !$validator->isErrorFatal();
+
+ foreach ($validator->getAllErrors() as $error) {
+ info($error);
+ }
+
+ if ($ret) {
+ $this->input += [
+ 'from' => $this->input['tabfilter_from'],
+ 'to' => $this->input['tabfilter_to']
+ ];
+ $ret = $this->validateTimeSelectorPeriod();
+ }
+
+ return $ret;
+ }
+
+ protected function checkPermissions() {
+ return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
+ }
+
+ protected function doAction() {
+ $data = [
+ 'form_action' => '',
+ 'idx' => '',
+ 'idx2' => '',
+ 'filter_name' => _('Untitled'),
+ 'filter_show_counter' => 0,
+ 'filter_custom_time' => 0,
+ 'tabfilter_from' => '',
+ 'tabfilter_to' => '',
+ 'support_custom_time' => 0,
+ 'create' => 0
+ ];
+ $this->getInputs($data, array_keys($data));
+
+ if (!$data['support_custom_time'] || !$data['filter_custom_time']) {
+ $data = [
+ 'filter_custom_time' => 0,
+ 'tabfilter_from' => 'now-1h',
+ 'tabfilter_to' => 'now'
+ ] + $data;
+ }
+
+ $data += [
+ 'title' => _('Filter properties'),
+ 'errors' => hasErrorMesssages() ? getMessages() : null,
+ 'user' => [
+ 'debug_mode' => $this->getDebugMode()
+ ]
+ ];
+
+ $this->setResponse(new CControllerResponseData($data));
+ }
+}
diff --git a/ui/app/controllers/CControllerPopupTabFilterUpdate.php b/ui/app/controllers/CControllerPopupTabFilterUpdate.php
new file mode 100644
index 00000000000..d6d863c7c72
--- /dev/null
+++ b/ui/app/controllers/CControllerPopupTabFilterUpdate.php
@@ -0,0 +1,123 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+
+/**
+ * Controller to update tab filter.
+ */
+class CControllerPopupTabFilterUpdate extends CController {
+
+ protected function init() {
+ $this->disableSIDValidation();
+ }
+
+ protected function checkInput() {
+ $rules = [
+ 'idx' => 'string|required',
+ 'idx2' => 'int32|required',
+ 'filter_name' => 'string|not_empty',
+ 'filter_show_counter' => 'in 0,1',
+ 'filter_custom_time' => 'in 0,1',
+ 'tabfilter_from' => 'string',
+ 'tabfilter_to' => 'string',
+ 'support_custom_time' => 'in 0,1',
+ 'create' => 'in 0,1'
+ ];
+
+ $ret = $this->validateInput($rules) && $this->customValidation();
+
+ if (!$ret) {
+ $output = [];
+
+ if (($messages = getMessages()) !== null) {
+ $output['errors'] = $messages->toString();
+ }
+
+ $this->setResponse(new CControllerResponseData(['main_block' => json_encode($output)]));
+ }
+
+ return $ret;
+ }
+
+ protected function customValidation(): bool {
+ if (!$this->getInput('support_custom_time', 0) || !$this->getInput('filter_custom_time', 0)) {
+ return true;
+ }
+
+ $rules = [
+ 'tabfilter_from' => 'range_time|required',
+ 'tabfilter_to' => 'range_time|required',
+ ];
+
+ $validator = new CNewValidator($this->getInputAll(), $rules);
+ $ret = !$validator->isError() && !$validator->isErrorFatal();
+
+ foreach ($validator->getAllErrors() as $error) {
+ info($error);
+ }
+
+ if ($ret) {
+ $this->input += [
+ 'from' => $this->input['tabfilter_from'],
+ 'to' => $this->input['tabfilter_to']
+ ];
+ $ret = $this->validateTimeSelectorPeriod();
+ }
+
+ return $ret;
+ }
+
+ protected function checkPermissions() {
+ return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
+ }
+
+ protected function doAction() {
+ $idx = $this->getInput('idx', '');
+ $idx2 = $this->getInput('idx2', '');
+ $create = (int) $this->getInput('create', 0);
+
+ $properties = [
+ 'filter_name' => $this->getInput('filter_name'),
+ 'filter_show_counter' => (int) $this->getInput('filter_show_counter', 0),
+ 'filter_custom_time' => (int) $this->getInput('filter_custom_time', 0)
+ ];
+
+ if ($this->getInput('support_custom_time', 0) && $properties['filter_custom_time']) {
+ $properties['from'] = $this->getInput('tabfilter_from', '');
+ $properties['to'] = $this->getInput('tabfilter_to', '');
+ }
+
+ $filter = (new CTabFilterProfile($idx, []))->read();
+
+ if (array_key_exists($idx2, $filter->tabfilters)) {
+ $properties = $properties + $filter->tabfilters[$idx2];
+ }
+ else {
+ $idx2 = count($filter->tabfilters);
+ }
+
+ $filter->tabfilters[$idx2] = $properties;
+ $filter->update();
+
+ $this->setResponse(new CControllerResponseData([
+ 'main_block' => json_encode($properties + ['idx2' => $idx2, 'create' => $create])
+ ]));
+ }
+}
diff --git a/ui/app/controllers/CControllerPopupTriggerExpr.php b/ui/app/controllers/CControllerPopupTriggerExpr.php
index 65de11fcc28..d0a89985e53 100644
--- a/ui/app/controllers/CControllerPopupTriggerExpr.php
+++ b/ui/app/controllers/CControllerPopupTriggerExpr.php
@@ -22,6 +22,7 @@
class CControllerPopupTriggerExpr extends CController {
private $metrics = [];
private $param1SecCount = [];
+ private $param1Period = [];
private $param1Sec = [];
private $param1Str = [];
private $param2SecCount = [];
@@ -67,6 +68,19 @@ class CControllerPopupTriggerExpr extends CController {
]
];
+ $this->param1Period = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'A' => true
+ ],
+ 'period_shift' => [
+ 'C' => _('Period shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => true
+ ]
+ ];
+
$this->param1Sec = [
'last' => [
'C' => _('Last of').' (T)',
@@ -416,6 +430,42 @@ class CControllerPopupTriggerExpr extends CController {
'params' => $this->paramTimeleft,
'allowed_types' => $this->allowedTypesNumeric,
'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trendavg' => [
+ 'description' => _('trendavg() - Average value of a period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trendcount' => [
+ 'description' => _('trendcount() - Number of successfully retrieved values V (which fulfill operator O) for period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trenddelta' => [
+ 'description' => _('trenddelta() - Difference between MAX and MIN value of a period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trendmax' => [
+ 'description' => _('trendmax() - Maximum value for period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trendmin' => [
+ 'description' => _('trendmin() - Minimum value for period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'trendsum' => [
+ 'description' => _('trendsum() - Sum of values of a period T with exact period shift'),
+ 'params' => $this->param1Period,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
]
];
diff --git a/ui/app/controllers/CControllerPopupTriggerWizard.php b/ui/app/controllers/CControllerPopupTriggerWizard.php
index b9634a1a110..820aa3d59fb 100644
--- a/ui/app/controllers/CControllerPopupTriggerWizard.php
+++ b/ui/app/controllers/CControllerPopupTriggerWizard.php
@@ -29,6 +29,7 @@ class CControllerPopupTriggerWizard extends CController {
protected function checkInput() {
$fields = [
'description' => 'string',
+ 'event_name' => 'db triggers.event_name',
'itemid' => 'required|db items.itemid',
'triggerid' => 'db triggers.triggerid',
'type' => 'in 0,1',
@@ -89,6 +90,7 @@ class CControllerPopupTriggerWizard extends CController {
protected function doAction() {
$page_options = [
'description' => $this->getInput('description', ''),
+ 'event_name' => $this->getInput('event_name', ''),
'opdata' => $this->getInput('opdata', ''),
'itemid' => $this->getInput('itemid', 0),
'type' => $this->getInput('type', 0),
@@ -164,6 +166,7 @@ class CControllerPopupTriggerWizard extends CController {
'triggerid' => $triggerid,
'expression' => $expression,
'description' => $description,
+ 'event_name' => $page_options['event_name'],
'opdata' => $opdata,
'type' => TRIGGER_MULT_EVENT_ENABLED,
'priority' => $page_options['priority'],
@@ -176,6 +179,7 @@ class CControllerPopupTriggerWizard extends CController {
$trigger = [
'expression' => $expression,
'description' => $page_options['description'],
+ 'event_name' => $page_options['event_name'],
'opdata' => $page_options['opdata'],
'type' => TRIGGER_MULT_EVENT_ENABLED,
'priority' => $page_options['priority'],
@@ -245,7 +249,8 @@ class CControllerPopupTriggerWizard extends CController {
// Select requested trigger.
if (array_key_exists('triggerid', $page_options)) {
$result = DBselect(
- 'SELECT t.expression,t.description,t.priority,t.comments,t.url,t.status,t.type,t.opdata'.
+ 'SELECT t.expression,t.description,t.priority,t.comments,t.url,t.status,t.type,t.opdata,'.
+ 't.event_name'.
' FROM triggers t'.
' WHERE t.triggerid='.zbx_dbstr($page_options['triggerid']).
' AND EXISTS ('.
@@ -262,6 +267,7 @@ class CControllerPopupTriggerWizard extends CController {
if ($row = DBfetch($result)) {
$expression = CMacrosResolverHelper::resolveTriggerExpression($row['expression']);
$page_options['description'] = $row['description'];
+ $page_options['event_name'] = $row['event_name'];
$page_options['opdata'] = $row['opdata'];
$page_options['type'] = $row['type'];
$page_options['priority'] = $row['priority'];
diff --git a/ui/app/controllers/CControllerProblem.php b/ui/app/controllers/CControllerProblem.php
new file mode 100644
index 00000000000..8b2e0923034
--- /dev/null
+++ b/ui/app/controllers/CControllerProblem.php
@@ -0,0 +1,173 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+
+/**
+ * Base controller for the "Monitoring->Problems" page.
+ */
+abstract class CControllerProblem extends CController {
+
+ // Filter idx prefix.
+ const FILTER_IDX = 'web.monitoring.problem';
+
+ // Filter fields default values.
+ const FILTER_FIELDS_DEFAULT = [
+ 'show' => TRIGGERS_OPTION_RECENT_PROBLEM,
+ 'groupids' => [],
+ 'hostids' => [],
+ 'application' => '',
+ 'triggerids' => [],
+ 'name' => '',
+ 'severities' => [],
+ 'age_state' => 0,
+ 'age' => 14,
+ 'inventory' => [],
+ 'evaltype' => TAG_EVAL_TYPE_AND_OR,
+ 'tags' => [],
+ 'show_tags' => PROBLEMS_SHOW_TAGS_3,
+ 'show_suppressed' => 0,
+ 'unacknowledged' => 0,
+ 'compact_view' => 0,
+ 'show_timeline' => 1,
+ 'details' => 0,
+ 'highlight_row' => 0,
+ 'show_opdata' => OPERATIONAL_DATA_SHOW_NONE,
+ 'tag_name_format' => PROBLEMS_TAG_NAME_FULL,
+ 'tag_priority' => '',
+ 'page' => null,
+ 'sort' => 'clock',
+ 'sortorder' => ZBX_SORT_DOWN,
+ 'from' => '',
+ 'to' => ''
+ ];
+
+ /**
+ * Get count of resulting rows for specified filter.
+ *
+ * @param array $filter Filter fields values.
+ *
+ * @return int
+ */
+ protected function getCount(array $filter): int {
+ $range_time_parser = new CRangeTimeParser();
+ $range_time_parser->parse($filter['from']);
+ $filter['from'] = $range_time_parser->getDateTime(true)->getTimestamp();
+ $range_time_parser->parse($filter['to']);
+ $filter['to'] = $range_time_parser->getDateTime(false)->getTimestamp();
+
+ $data = CScreenProblem::getData($filter, [
+ 'search_limit' => CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT)
+ ]);
+
+ return count($data['problems']);
+ }
+
+ /**
+ * Get resulting rows for specified filter.
+ *
+ * @param array $filter Filter fields values.
+ *
+ * @return array
+ */
+ protected function getData(array $filter): array {
+ // getData is handled by jsrpc.php 'screen.get' action.
+ return [];
+ }
+
+ /**
+ * Get additional data required for render filter as HTML.
+ *
+ * @param array $filter Filter fileds values.
+ *
+ * @return array
+ */
+ protected function getAdditionalData(array $filter): array {
+ $data = [
+ 'groups' => [],
+ 'hosts' => [],
+ 'triggers' => []
+ ];
+
+ // Host groups multiselect.
+ if ($filter['groupids']) {
+ $host_groups = API::HostGroup()->get([
+ 'output' => ['groupid', 'name'],
+ 'groupids' => $filter['groupids'],
+ 'preservekeys' => true
+ ]);
+ $data['groups'] = CArrayHelper::renameObjectsKeys($host_groups, ['groupid' => 'id']);
+ }
+
+ // Triggers multiselect.
+ if ($filter['triggerids']) {
+ $triggers = CArrayHelper::renameObjectsKeys(API::Trigger()->get([
+ 'output' => ['triggerid', 'description'],
+ 'selectHosts' => ['name'],
+ 'expandDescription' => true,
+ 'triggerids' => $filter['triggerids'],
+ 'monitored' => true
+ ]), ['triggerid' => 'id', 'description' => 'name']);
+
+ CArrayHelper::sort($triggers, [
+ ['field' => 'name', 'order' => ZBX_SORT_UP]
+ ]);
+
+ foreach ($triggers as &$trigger) {
+ $trigger['prefix'] = $trigger['hosts'][0]['name'].NAME_DELIMITER;
+ unset($trigger['hosts']);
+ }
+
+ $data['triggers'] = $triggers;
+ }
+
+ // Hosts multiselect.
+ if ($filter['hostids']) {
+ $data['hosts'] = CArrayHelper::renameObjectsKeys(API::Host()->get([
+ 'output' => ['hostid', 'name'],
+ 'hostids' => $filter['hostids']
+ ]), ['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('tags', $input) && $input['tags']) {
+ $input['tags'] = array_filter($input['tags'], function($tag) {
+ return !($tag['tag'] === '' && $tag['value'] === '');
+ });
+ }
+
+ if (array_key_exists('inventory', $input) && $input['inventory']) {
+ $input['inventory'] = array_filter($input['inventory'], function($inventory) {
+ return $inventory['value'] !== '';
+ });
+ }
+
+ return $input;
+ }
+}
diff --git a/ui/app/controllers/CControllerProblemView.php b/ui/app/controllers/CControllerProblemView.php
index 3036ea8dbd5..c5826783e03 100644
--- a/ui/app/controllers/CControllerProblemView.php
+++ b/ui/app/controllers/CControllerProblemView.php
@@ -19,7 +19,7 @@
**/
-class CControllerProblemView extends CController {
+class CControllerProblemView extends CControllerProblem {
protected function init() {
$this->disableSIDValidation();
@@ -27,43 +27,46 @@ class CControllerProblemView extends CController {
protected function checkInput() {
$fields = [
- 'action' => 'string',
+ 'show' => 'in '.TRIGGERS_OPTION_RECENT_PROBLEM.','.TRIGGERS_OPTION_IN_PROBLEM.','.TRIGGERS_OPTION_ALL,
+ 'groupids' => 'array_id',
+ 'hostids' => 'array_id',
+ 'application' => 'string',
+ 'triggerids' => 'array_id',
+ 'name' => 'string',
+ 'severities' => 'array',
+ 'age_state' => 'in 0,1',
+ 'age' => 'int32',
+ 'inventory' => 'array',
+ 'evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR,
+ 'tags' => 'array',
+ 'show_tags' => 'in '.PROBLEMS_SHOW_TAGS_NONE.','.PROBLEMS_SHOW_TAGS_1.','.PROBLEMS_SHOW_TAGS_2.','.PROBLEMS_SHOW_TAGS_3,
+ 'show_suppressed' => 'in 0,1',
+ 'unacknowledged' => 'in 0,1',
+ 'compact_view' => 'in 0,1',
+ 'show_timeline' => 'in 0,1',
+ 'details' => 'in 0,1',
+ 'highlight_row' => 'in 0,1',
+ 'show_opdata' => 'in '.OPERATIONAL_DATA_SHOW_NONE.','.OPERATIONAL_DATA_SHOW_SEPARATELY.','.OPERATIONAL_DATA_SHOW_WITH_PROBLEM,
+ 'tag_name_format' => 'in '.PROBLEMS_TAG_NAME_FULL.','.PROBLEMS_TAG_NAME_SHORTENED.','.PROBLEMS_TAG_NAME_NONE,
+ 'tag_priority' => 'string',
+ 'from' => 'range_time',
+ 'to' => 'range_time',
'sort' => 'in clock,host,severity,name',
'sortorder' => 'in '.ZBX_SORT_DOWN.','.ZBX_SORT_UP,
- 'uncheck' => 'in 1',
'page' => 'ge 1',
- 'filter_set' => 'in 1',
- 'filter_rst' => 'in 1',
- 'filter_show' => 'in '.TRIGGERS_OPTION_RECENT_PROBLEM.','.TRIGGERS_OPTION_IN_PROBLEM.','.TRIGGERS_OPTION_ALL,
- 'filter_groupids' => 'array_id',
- 'filter_hostids' => 'array_id',
- 'filter_application' => 'string',
- 'filter_triggerids' => 'array_id',
+ 'uncheck' => 'in 1',
'filter_name' => 'string',
- 'filter_severities' => 'array',
- 'filter_age_state' => 'in 1',
- 'filter_age' => 'int32',
- 'filter_inventory' => 'array',
- 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR,
- 'filter_tags' => 'array',
- 'filter_show_tags' => 'in '.PROBLEMS_SHOW_TAGS_NONE.','.PROBLEMS_SHOW_TAGS_1.','.PROBLEMS_SHOW_TAGS_2.','.PROBLEMS_SHOW_TAGS_3,
- 'filter_show_suppressed' => 'in 1',
- 'filter_unacknowledged' => 'in 1',
- 'filter_compact_view' => 'in 1',
- 'filter_show_timeline' => 'in 1',
- 'filter_details' => 'in 1',
- 'filter_highlight_row' => 'in 1',
- 'filter_show_opdata' => 'in '.OPERATIONAL_DATA_SHOW_NONE.','.OPERATIONAL_DATA_SHOW_SEPARATELY.','.OPERATIONAL_DATA_SHOW_WITH_PROBLEM,
- 'filter_tag_name_format' => 'in '.PROBLEMS_TAG_NAME_FULL.','.PROBLEMS_TAG_NAME_SHORTENED.','.PROBLEMS_TAG_NAME_NONE,
- 'filter_tag_priority' => 'string',
- 'from' => 'range_time',
- 'to' => 'range_time'
+ '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) && $this->validateTimeSelectorPeriod();
- if ($ret && $this->hasInput('filter_inventory')) {
- foreach ($this->getInput('filter_inventory') as $filter_inventory) {
+ if ($ret && $this->hasInput('inventory')) {
+ foreach ($this->getInput('inventory') as $filter_inventory) {
if (count($filter_inventory) != 2
|| !array_key_exists('field', $filter_inventory) || !is_string($filter_inventory['field'])
|| !array_key_exists('value', $filter_inventory) || !is_string($filter_inventory['value'])) {
@@ -73,8 +76,8 @@ class CControllerProblemView extends CController {
}
}
- if ($ret && $this->hasInput('filter_tags')) {
- foreach ($this->getInput('filter_tags') as $filter_tag) {
+ 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'])
@@ -97,245 +100,55 @@ class CControllerProblemView extends CController {
}
protected function doAction() {
- $sortField = $this->getInput('sort', CProfile::get('web.problem.sort', 'clock'));
- $sortOrder = $this->getInput('sortorder', CProfile::get('web.problem.sortorder', ZBX_SORT_DOWN));
- $active_tab = CProfile::get('web.problem.filter.active', 1);
-
- CProfile::update('web.problem.sort', $sortField, PROFILE_TYPE_STR);
- CProfile::update('web.problem.sortorder', $sortOrder, PROFILE_TYPE_STR);
-
- // filter
- if ($this->hasInput('filter_set')) {
- $show_db_type = CProfile::get('web.problem.filter.show', TRIGGERS_OPTION_RECENT_PROBLEM);
- $show_type = $this->getInput('filter_show', TRIGGERS_OPTION_RECENT_PROBLEM);
-
- if ($show_db_type != $show_type) {
- CProfile::update('web.problem.filter.show', $show_type, PROFILE_TYPE_INT);
-
- if ($show_type == TRIGGERS_OPTION_ALL && $active_tab == 1) {
- $active_tab = 2;
- CProfile::update('web.problem.filter.active', $active_tab, PROFILE_TYPE_INT);
- }
- }
-
- CProfile::updateArray('web.problem.filter.groupids', $this->getInput('filter_groupids', []),
- PROFILE_TYPE_ID
- );
- CProfile::updateArray('web.problem.filter.hostids', $this->getInput('filter_hostids', []), PROFILE_TYPE_ID);
- CProfile::update('web.problem.filter.application', $this->getInput('filter_application', ''),
- PROFILE_TYPE_STR
- );
- CProfile::updateArray('web.problem.filter.triggerids', $this->getInput('filter_triggerids', []),
- PROFILE_TYPE_ID
- );
- CProfile::update('web.problem.filter.name', $this->getInput('filter_name', ''), PROFILE_TYPE_STR);
- CProfile::updateArray('web.problem.filter.severities', $this->getInput('filter_severities', []),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.age_state', $this->getInput('filter_age_state', 0), PROFILE_TYPE_INT);
- CProfile::update('web.problem.filter.age', $this->getInput('filter_age', 14), PROFILE_TYPE_INT);
-
- $filter_inventory = ['fields' => [], 'values' => []];
- foreach ($this->getInput('filter_inventory', []) as $field) {
- if ($field['value'] === '') {
- continue;
- }
-
- $filter_inventory['fields'][] = $field['field'];
- $filter_inventory['values'][] = $field['value'];
- }
- CProfile::updateArray('web.problem.filter.inventory.field', $filter_inventory['fields'], PROFILE_TYPE_STR);
- CProfile::updateArray('web.problem.filter.inventory.value', $filter_inventory['values'], PROFILE_TYPE_STR);
-
- CProfile::update('web.problem.filter.evaltype', $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR),
- PROFILE_TYPE_INT
- );
-
- $filter_tags = ['tags' => [], 'values' => [], 'operators' => []];
- foreach ($this->getInput('filter_tags', []) as $filter_tag) {
- if ($filter_tag['tag'] === '' && $filter_tag['value'] === '') {
- continue;
- }
-
- $filter_tags['tags'][] = $filter_tag['tag'];
- $filter_tags['values'][] = $filter_tag['value'];
- $filter_tags['operators'][] = $filter_tag['operator'];
+ $filter_tabs = [];
+ $profile = (new CTabFilterProfile(static::FILTER_IDX, static::FILTER_FIELDS_DEFAULT))
+ ->read()
+ ->setInput($this->cleanInput($this->getInputAll()));
+
+ foreach ($profile->getTabsWithDefaults() as $filter_tab) {
+ if ($filter_tab['show'] != TRIGGERS_OPTION_ALL) {
+ $filter_tab['filter_custom_time'] = 0;
}
- CProfile::updateArray('web.problem.filter.tags.tag', $filter_tags['tags'], PROFILE_TYPE_STR);
- CProfile::updateArray('web.problem.filter.tags.value', $filter_tags['values'], PROFILE_TYPE_STR);
- CProfile::updateArray('web.problem.filter.tags.operator', $filter_tags['operators'], PROFILE_TYPE_INT);
-
- CProfile::update('web.problem.filter.show_tags', $this->getInput('filter_show_tags', PROBLEMS_SHOW_TAGS_3),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.tag_name_format', $this->getInput('filter_tag_name_format',
- PROBLEMS_TAG_NAME_FULL), PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.tag_priority', $this->getInput('filter_tag_priority', ''),
- PROFILE_TYPE_STR
- );
- CProfile::update('web.problem.filter.show_suppressed',
- $this->getInput('filter_show_suppressed', ZBX_PROBLEM_SUPPRESSED_FALSE), PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.unacknowledged', $this->getInput('filter_unacknowledged', 0),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.compact_view', $this->getInput('filter_compact_view', 0),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.show_timeline', $this->getInput('filter_show_timeline', 0),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.details', $this->getInput('filter_details', 0), PROFILE_TYPE_INT);
- CProfile::update('web.problem.filter.highlight_row', $this->getInput('filter_highlight_row', 0),
- PROFILE_TYPE_INT
- );
- CProfile::update('web.problem.filter.show_opdata', $this->getInput('filter_show_opdata', 0),
- PROFILE_TYPE_INT
- );
- }
- elseif ($this->hasInput('filter_rst')) {
- CProfile::delete('web.problem.filter.show');
- CProfile::deleteIdx('web.problem.filter.groupids');
- CProfile::deleteIdx('web.problem.filter.hostids');
- CProfile::delete('web.problem.filter.application');
- CProfile::deleteIdx('web.problem.filter.triggerids');
- CProfile::delete('web.problem.filter.name');
- CProfile::deleteIdx('web.problem.filter.severities');
- CProfile::delete('web.problem.filter.age_state');
- CProfile::delete('web.problem.filter.age');
- CProfile::deleteIdx('web.problem.filter.inventory.field');
- CProfile::deleteIdx('web.problem.filter.inventory.value');
- CProfile::delete('web.problem.filter.evaltype');
- CProfile::deleteIdx('web.problem.filter.tags.tag');
- CProfile::deleteIdx('web.problem.filter.tags.value');
- CProfile::deleteIdx('web.problem.filter.tags.operator');
- CProfile::delete('web.problem.filter.show_tags');
- CProfile::delete('web.problem.filter.tag_name_format');
- CProfile::delete('web.problem.filter.tag_priority');
- CProfile::delete('web.problem.filter.show_suppressed');
- CProfile::delete('web.problem.filter.unacknowledged');
- CProfile::delete('web.problem.filter.compact_view');
- CProfile::delete('web.problem.filter.show_timeline');
- CProfile::delete('web.problem.filter.details');
- CProfile::delete('web.problem.filter.highlight_row');
- CProfile::delete('web.problem.filter.show_opdata');
- }
-
- $filter_groupids = CProfile::getArray('web.problem.filter.groupids', []);
- $filter_hostids = CProfile::getArray('web.problem.filter.hostids', []);
- $filter_triggerids = CProfile::getArray('web.problem.filter.triggerids', []);
-
- $groups = [];
-
- if ($filter_groupids) {
- $filter_groupids = getSubGroups($filter_groupids, $groups);
- }
-
- $filter_triggers = $filter_triggerids
- ? CArrayHelper::renameObjectsKeys(API::Trigger()->get([
- 'output' => ['triggerid', 'description'],
- 'selectHosts' => ['name'],
- 'expandDescription' => true,
- 'triggerids' => $filter_triggerids,
- 'monitored' => true
- ]), ['triggerid' => 'id', 'description' => 'name'])
- : [];
-
- CArrayHelper::sort($filter_triggers, [
- ['field' => 'name', 'order' => ZBX_SORT_UP]
- ]);
-
- foreach ($filter_triggers as &$filter_trigger) {
- $filter_trigger['prefix'] = $filter_trigger['hosts'][0]['name'].NAME_DELIMITER;
- unset($filter_trigger['hosts']);
- }
- unset($filter_trigger);
- $inventories = [];
- foreach (getHostInventories() as $inventory) {
- $inventories[$inventory['db_field']] = $inventory['title'];
+ $filter_tabs[] = $filter_tab + ['filter_view_data' => $this->getAdditionalData($filter_tab)];
}
- $filter_inventory = [];
- foreach (CProfile::getArray('web.problem.filter.inventory.field', []) as $i => $field) {
- $filter_inventory[] = [
- 'field' => $field,
- 'value' => CProfile::get('web.problem.filter.inventory.value', null, $i)
- ];
- }
-
- $filter_tags = [];
- foreach (CProfile::getArray('web.problem.filter.tags.tag', []) as $i => $tag) {
- $filter_tags[] = [
- 'tag' => $tag,
- 'value' => CProfile::get('web.problem.filter.tags.value', null, $i),
- 'operator' => CProfile::get('web.problem.filter.tags.operator', null, $i)
- ];
- }
+ $filter = $profile->getTabFilter($profile->selected);
+ $refresh_curl = (new CUrl('zabbix.php'));
+ $filter['action'] = 'problem.view.refresh';
+ array_map([$refresh_curl, 'setArgument'], array_keys($filter), $filter);
- /*
- * Display
- */
$data = [
- 'action' => $this->getInput('action'),
- 'sort' => $sortField,
- 'sortorder' => $sortOrder,
- 'uncheck' => $this->hasInput('uncheck'),
- 'page' => $this->getInput('page', 1),
- 'filter' => [
- 'show' => CProfile::get('web.problem.filter.show', TRIGGERS_OPTION_RECENT_PROBLEM),
- 'groupids' => $filter_groupids,
- 'groups' => $groups,
- 'hostids' => $filter_hostids,
- 'hosts' => $filter_hostids
- ? CArrayHelper::renameObjectsKeys(API::Host()->get([
- 'output' => ['hostid', 'name'],
- 'hostids' => $filter_hostids
- ]), ['hostid' => 'id'])
- : [],
- 'application' => CProfile::get('web.problem.filter.application', ''),
- 'triggerids' => $filter_triggerids,
- 'triggers' => $filter_triggers,
- 'name' => CProfile::get('web.problem.filter.name', ''),
- 'severities' => CProfile::getArray('web.problem.filter.severities', []),
- 'age_state' => CProfile::get('web.problem.filter.age_state', 0),
- 'age' => CProfile::get('web.problem.filter.age', 14),
- 'inventories' => $inventories,
- 'inventory' => $filter_inventory,
- 'evaltype' => CProfile::get('web.problem.filter.evaltype', TAG_EVAL_TYPE_AND_OR),
- 'tags' => $filter_tags,
- 'show_tags' => CProfile::get('web.problem.filter.show_tags', PROBLEMS_SHOW_TAGS_3),
- 'tag_name_format' => CProfile::get('web.problem.filter.tag_name_format', PROBLEMS_TAG_NAME_FULL),
- 'tag_priority' => CProfile::get('web.problem.filter.tag_priority', ''),
- 'show_suppressed' => CProfile::get('web.problem.filter.show_suppressed', 0),
- 'unacknowledged' => CProfile::get('web.problem.filter.unacknowledged', 0),
- 'compact_view' => CProfile::get('web.problem.filter.compact_view', 0),
- 'show_timeline' => CProfile::get('web.problem.filter.show_timeline', 1),
- 'details' => CProfile::get('web.problem.filter.details', 0),
- 'highlight_row' => CProfile::get('web.problem.filter.highlight_row', 0),
- 'show_opdata' => CProfile::get('web.problem.filter.show_opdata', 0)
+ 'action' => $this->getAction(),
+ 'tabfilter_idx' => static::FILTER_IDX,
+ 'filter' => $filter,
+ 'filter_view' => 'monitoring.problem.filter',
+ 'filter_defaults' => $profile->filter_defaults,
+ 'tabfilter_options' => [
+ 'idx' => static::FILTER_IDX,
+ 'selected' => $profile->selected,
+ 'support_custom_time' => 1,
+ 'expanded' => $profile->expanded,
+ 'page' => $filter['page'],
+ 'timeselector' => [
+ 'from' => $profile->from,
+ 'to' => $profile->to,
+ 'disabled' => ($filter['show'] != TRIGGERS_OPTION_ALL || $filter['filter_custom_time'])
+ ] + getTimeselectorActions($profile->from, $profile->to)
],
- 'active_tab' => $active_tab
+ 'filter_tabs' => $filter_tabs,
+ 'refresh_url' => $refresh_curl->getUrl(),
+ 'refresh_interval' => CWebUser::getRefresh() * 1000,
+ 'inventories' => array_column(getHostInventories(), 'title', 'db_field'),
+ 'sort' => $filter['sort'],
+ 'sortorder' => $filter['sortorder'],
+ 'uncheck' => $this->hasInput('filter_reset'),
+ 'page' => $this->getInput('page', 1),
];
- if ($data['filter']['show'] == TRIGGERS_OPTION_ALL) {
- $timeselector_options = [
- 'profileIdx' => 'web.problem.filter',
- 'profileIdx2' => 0,
- 'from' => $this->hasInput('from') ? $this->getInput('from') : null,
- 'to' => $this->hasInput('to') ? $this->getInput('to') : null
- ];
- updateTimeSelectorPeriod($timeselector_options);
-
- $data += $timeselector_options;
- }
- else {
- $data['profileIdx'] = 'web.problem.filter';
- }
-
$response = new CControllerResponseData($data);
$response->setTitle(_('Problems'));
+
if ($data['action'] === 'problem.view.csv') {
$response->setFileName('zbx_problems_export.csv');
}
diff --git a/ui/app/controllers/CControllerProblemViewRefresh.php b/ui/app/controllers/CControllerProblemViewRefresh.php
new file mode 100644
index 00000000000..e160cfcf036
--- /dev/null
+++ b/ui/app/controllers/CControllerProblemViewRefresh.php
@@ -0,0 +1,52 @@
+<?php
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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 CControllerProblemViewRefresh extends CControllerProblemView {
+
+ protected function doAction() {
+ $data = [];
+
+ 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();
+ $data['filter_counters'] = [];
+
+ foreach ($filters as $index => $tabfilter) {
+ if (!$tabfilter['filter_custom_time']) {
+ $tabfilter = [
+ 'from' => $profile->from,
+ 'to' => $profile->to
+ ] + $tabfilter;
+ }
+
+ $data['filter_counters'][$index] = $tabfilter['filter_show_counter'] ? $this->getCount($tabfilter) : 0;
+ }
+ }
+
+ if (($messages = getMessages()) !== null) {
+ $data['messages'] = $messages->toString();
+ }
+
+ $this->setResponse(new CControllerResponseData(['main_block' => json_encode($data)]));
+ }
+}
diff --git a/ui/app/controllers/CControllerTabFilterProfileUpdate.php b/ui/app/controllers/CControllerTabFilterProfileUpdate.php
new file mode 100644
index 00000000000..1c6a5e9a9a5
--- /dev/null
+++ b/ui/app/controllers/CControllerTabFilterProfileUpdate.php
@@ -0,0 +1,171 @@
+<?php declare(strict_types=1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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.
+**/
+
+
+/**
+ * Controller to update tab filter. Handles following events:
+ * - select tab;
+ * - expand/collapse active tab;
+ * - update filter properties;
+ * - save tab order.
+ */
+class CControllerTabFilterProfileUpdate extends CController {
+
+ public static $namespaces = [
+ CControllerHost::FILTER_IDX => CControllerHost::FILTER_FIELDS_DEFAULT,
+ CControllerProblem::FILTER_IDX => CControllerProblem::FILTER_FIELDS_DEFAULT
+ ];
+
+ public function init() {
+ $this->disableSIDvalidation();
+ }
+
+ protected function checkPermissions() {
+ return ($this->getUserType() >= USER_TYPE_ZABBIX_USER);
+ }
+
+ protected function checkInput() {
+ $fields = [
+ 'idx' => 'required|string',
+ 'value_int' => 'int32',
+ 'value_str' => 'string',
+ 'idx2' => 'id'
+ ];
+
+ $ret = $this->validateInput($fields);
+
+ if ($ret) {
+ $idx_cunks = explode('.', $this->getInput('idx'));
+ $property = array_pop($idx_cunks);
+ $idx = implode('.', $idx_cunks);
+ $supported = ['selected', 'expanded', 'properties', 'taborder'];
+
+ $ret = (in_array($property, $supported) && array_key_exists($idx, static::$namespaces));
+
+ if ($property === 'selected' || $property === 'expanded') {
+ $ret = ($ret && $this->hasInput('value_int'));
+ }
+ else if ($property === 'properties' || $property === 'taborder') {
+ $ret = ($ret && $this->hasInput('value_str'));
+ }
+ }
+
+ if (!$ret) {
+ $this->setResponse(new CControllerResponseData(['main_block' => '']));
+ }
+
+ return $ret;
+ }
+
+ protected function doAction() {
+ $data = $this->getInputAll() + [
+ 'value_int' => 0,
+ 'value_str' => '',
+ 'idx2' => 0
+ ];
+ $idx_cunks = explode('.', $this->getInput('idx'));
+ $property = array_pop($idx_cunks);
+ $idx = implode('.', $idx_cunks);
+ $defaults = static::$namespaces[$idx];
+
+ if (array_key_exists('from', $defaults) || array_key_exists('to', $defaults)) {
+ $defaults += [
+ 'from' => 'now-'.CSettingsHelper::get(CSettingsHelper::PERIOD_DEFAULT),
+ 'to' => 'now'
+ ];
+ }
+
+ $filter = (new CTabFilterProfile($idx, $defaults))->read();
+
+ switch ($property) {
+ case 'selected':
+ $dynamictabs = count($filter->tabfilters);
+
+ if ($data['value_int'] >= 0 && $data['value_int'] < $dynamictabs) {
+ $filter->selected = (int) $data['value_int'];
+ }
+
+ break;
+
+ case 'properties':
+ $properties = [];
+ parse_str($this->getInput('value_str'), $properties);
+ $filter->setTabFilter($this->getInput('idx2'), $this->cleanProperties($properties));
+
+ break;
+
+ case 'taborder':
+ $filter->sort($this->getInput('value_str'));
+
+ break;
+
+ case 'expanded':
+ $filter->expanded = ($data['value_int'] > 0);
+
+ break;
+ }
+
+ $filter->update();
+
+ $data += [
+ 'property' => $property,
+ 'idx' => $idx
+ ];
+ $response = new CControllerResponseData($data);
+ $this->setResponse($response);
+ }
+
+ /**
+ * Clean fields data removing empty initial elements.
+ *
+ * @param array $properties Array of submitted fields data.
+ *
+ * @return array
+ */
+ protected function cleanProperties(array $properties): array {
+ if (array_key_exists('tags', $properties)) {
+ $tags = array_filter($properties['tags'], function ($tag) {
+ return !($tag['tag'] === '' && $tag['value'] === '');
+ });
+
+ if ($tags) {
+ $properties['tags'] = array_values($tags);
+ }
+ else {
+ unset($properties['tags']);
+ }
+ }
+
+ if (array_key_exists('inventory', $properties)) {
+ $inventory = array_filter($properties['inventory'], function ($field) {
+ return ($field['value'] !== '');
+ });
+
+ if ($inventory) {
+ $properties['inventory'] = array_values($inventory);
+ }
+ else {
+ unset($properties['inventory']);
+ }
+ }
+
+ return $properties;
+ }
+}
diff --git a/ui/app/controllers/CControllerTimeSelectorUpdate.php b/ui/app/controllers/CControllerTimeSelectorUpdate.php
index 3b7de8f2658..ef0ed19c835 100644
--- a/ui/app/controllers/CControllerTimeSelectorUpdate.php
+++ b/ui/app/controllers/CControllerTimeSelectorUpdate.php
@@ -24,6 +24,12 @@
*/
class CControllerTimeSelectorUpdate extends CController {
+ public static $profiles = ['web.dashbrd.filter', 'web.screens.filter', 'web.charts.filter', 'web.httpdetails.filter',
+ 'web.problem.filter', 'web.auditlog.filter', 'web.slides.filter', 'web.auditacts.filter',
+ 'web.item.graph.filter', 'web.toptriggers.filter', 'web.avail_report.filter', CControllerHost::FILTER_IDX,
+ CControllerProblem::FILTER_IDX
+ ];
+
/**
* @var CRangeTimeParser
*/
@@ -38,14 +44,9 @@ class CControllerTimeSelectorUpdate extends CController {
}
protected function checkInput() {
- $profiles = ['web.auditacts.filter', 'web.auditlog.filter', 'web.avail_report.filter', 'web.charts.filter',
- 'web.dashbrd.filter', 'web.item.graph.filter', 'web.httpdetails.filter', 'web.problem.filter',
- 'web.screens.filter', 'web.slides.filter', 'web.toptriggers.filter'
- ];
-
$fields = [
'method' => 'required|in increment,zoomout,decrement,rangechange,rangeoffset',
- 'idx' => 'required|in '.implode(',', $profiles),
+ 'idx' => 'required|in '.implode(',', static::$profiles),
'idx2' => 'required|id',
'from' => 'required|string',
'to' => 'required|string',
@@ -201,10 +202,7 @@ class CControllerTimeSelectorUpdate extends CController {
'to' => $value['to'],
'to_ts' => $ts['to'],
'to_date' => $date->setTimestamp($ts['to'])->format(ZBX_FULL_DATE_TIME),
- 'can_zoomout' => ($ts['to'] - $ts['from'] + 1 < $max_period),
- 'can_decrement' => ($ts['from'] > 0),
- 'can_increment' => ($ts['to'] < $ts['now'] - ZBX_MIN_PERIOD)
- ])]));
+ ] + getTimeselectorActions($value['from'], $value['to']))]));
}
/**
diff --git a/ui/app/partials/monitoring.host.filter.php b/ui/app/partials/monitoring.host.filter.php
new file mode 100644
index 00000000000..61c8bcc2cc5
--- /dev/null
+++ b/ui/app/partials/monitoring.host.filter.php
@@ -0,0 +1,315 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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
+ */
+
+$filter_tags_table = (new CTable())
+ ->setId('tags_#{uniqid}')
+ ->addRow(
+ (new CCol(
+ (new CRadioButtonList('evaltype', (int) $data['evaltype']))
+ ->setId('evaltype_#{uniqid}')
+ ->addValue(_('And/Or'), TAG_EVAL_TYPE_AND_OR, 'evaltype_0#{uniqid}')
+ ->addValue(_('Or'), TAG_EVAL_TYPE_OR, 'evaltype_2#{uniqid}')
+ ->setModern(true)
+ ))->setColSpan(4)
+);
+
+foreach (array_values($data['tags']) as $i => $tag) {
+ $filter_tags_table->addRow([
+ (new CTextBox('tags['.$i.'][tag]', $tag['tag']))
+ ->setAttribute('placeholder', _('tag'))
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH)
+ ->removeId(),
+ (new CRadioButtonList('tags['.$i.'][operator]', (int) $tag['operator']))
+ ->addValue(_('Contains'), TAG_OPERATOR_LIKE, 'tags_0'.$i.'_#{uniqid}')
+ ->addValue(_('Equals'), TAG_OPERATOR_EQUAL, 'tags_1'.$i.'_#{uniqid}')
+ ->setId('tags_'.$i.'_#{uniqid}')
+ ->setModern(true),
+ (new CTextBox('tags['.$i.'][value]', $tag['value']))
+ ->setAttribute('placeholder', _('value'))
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH)
+ ->removeId(),
+ (new CCol(
+ (new CButton('tags['.$i.'][remove]', _('Remove')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-remove')
+ ->removeId()
+ ))->addClass(ZBX_STYLE_NOWRAP)
+ ], 'form_row');
+}
+$filter_tags_table->addRow(
+ (new CCol(
+ (new CButton('tags_add', _('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-add')
+ ->removeId()
+ ))->setColSpan(3)
+);
+
+$left_column = (new CFormList())
+ ->addRow(_('Name'),
+ (new CTextBox('name', $data['name']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('name_#{uniqid}')
+ )
+ ->addRow((new CLabel(_('Host groups'), 'groupids_#{uniqid}_ms')),
+ (new CMultiSelect([
+ 'name' => 'groupids[]',
+ 'object_name' => 'hostGroup',
+ 'data' => array_key_exists('groups_multiselect', $data) ? $data['groups_multiselect'] : [],
+ 'popup' => [
+ 'parameters' => [
+ 'srctbl' => 'host_groups',
+ 'srcfld1' => 'groupid',
+ 'dstfrm' => 'zbx_filter',
+ 'dstfld1' => 'groupids_',
+ 'real_hosts' => true,
+ 'enrich_parent_groups' => true
+ ]
+ ],
+ 'add_post_js' => false
+ ]))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('groupids_#{uniqid}')
+ )
+ ->addRow(_('IP'),
+ (new CTextBox('ip', $data['ip']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('ip_#{uniqid}')
+ )
+ ->addRow(_('DNS'),
+ (new CTextBox('dns', $data['dns']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('dns_#{uniqid}')
+ )
+ ->addRow(_('Port'),
+ (new CTextBox('port', $data['port']))
+ ->setWidth(ZBX_TEXTAREA_INTERFACE_PORT_WIDTH)
+ ->setId('port_#{uniqid}')
+ )
+ ->addRow(_('Severity'),
+ (new CSeverityCheckBoxList('severities'))
+ ->setChecked($data['severities'])
+ ->setUniqid('#{uniqid}')
+ );
+
+$right_column = (new CFormList())
+ ->addRow(_('Status'),
+ (new CRadioButtonList('status', (int) $data['status']))
+ ->addValue(_('Any'), -1, 'status_1#{uniqid}')
+ ->addValue(_('Enabled'), HOST_STATUS_MONITORED, 'status_2#{uniqid}')
+ ->addValue(_('Disabled'), HOST_STATUS_NOT_MONITORED, 'status_3#{uniqid}')
+ ->setId('status_#{uniqid}')
+ ->setModern(true)
+ )
+ ->addRow(_('Tags'), $filter_tags_table)
+ ->addRow(_('Show hosts in maintenance'), [
+ (new CCheckBox('maintenance_status'))
+ ->setChecked($data['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON)
+ ->setId('maintenance_status_#{uniqid}')
+ ->setUncheckedValue(HOST_MAINTENANCE_STATUS_OFF),
+ (new CDiv([
+ (new CLabel(_('Show suppressed problems'), 'show_suppressed_#{uniqid}'))
+ ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
+ (new CCheckBox('show_suppressed'))
+ ->setId('show_suppressed_#{uniqid}')
+ ->setChecked($data['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
+ ->setUncheckedValue(ZBX_PROBLEM_SUPPRESSED_FALSE)
+ ->setEnabled($data['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON),
+ ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
+ ]);
+
+$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([
+ $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-hosts'))
+ ->setAttribute('data-template', 'monitoring.host.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 CRadioButtonList('tags[#{rowNum}][operator]', TAG_OPERATOR_LIKE))
+ ->addValue(_('Contains'), TAG_OPERATOR_LIKE, 'tags_0#{rowNum}#{uniqid}')
+ ->addValue(_('Equals'), TAG_OPERATOR_EQUAL, 'tags_1#{rowNum}#{uniqid}')
+ ->setModern(true)
+ ->setId('tags_#{rowNum}#{uniqid}'),
+ (new CTextBox('tags[#{rowNum}][value]', '#{value}'))
+ ->setAttribute('placeholder', _('value'))
+ ->removeId()
+ ->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.host.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
+ }
+ }
+ });
+
+ // Show hosts in maintenance events.
+ let maintenance_checkbox = $('[name="maintenance_status"]', container).click(function () {
+ $('[name="show_suppressed"]', container).prop('disabled', !this.checked);
+ });
+
+ if (maintenance_checkbox.attr('unchecked-value') === data['maintenance_status']) {
+ maintenance_checkbox.removeAttr('checked');
+ $('[name="show_suppressed"]', container).prop('disabled', true);
+ }
+
+ // 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;
+ }
+ });
+
+ // Input, radio and single checkboxes.
+ ['name', 'ip', 'dns', 'port', 'status', 'evaltype', 'show_suppressed'].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]);
+ }
+ });
+
+ // Severities checkboxes.
+ for (const value in data.severities) {
+ $('[name="severities[' + value + ']"]', container).attr('checked', true);
+ }
+
+ // 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.host.view.html.php b/ui/app/partials/monitoring.host.view.html.php
index c6ee51bedc9..4ecef5d6d39 100644
--- a/ui/app/partials/monitoring.host.view.html.php
+++ b/ui/app/partials/monitoring.host.view.html.php
@@ -21,10 +21,6 @@
$form = (new CForm())->setName('host_view');
-$url = (new CUrl('zabbix.php'))
- ->setArgument('action', 'host.view')
- ->getUrl();
-
$table = (new CTableInfo());
$view_url = $data['view_curl']->getUrl();
@@ -122,9 +118,9 @@ foreach ($data['hosts'] as $hostid => $host) {
new CLink(_('Problems'),
(new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_set', '1')
- ->setArgument('filter_severities', $data['filter']['severities'])
- ->setArgument('filter_hostids', [$host['hostid']])
+ ->setArgument('filter_name', '')
+ ->setArgument('severities', $data['filter']['severities'])
+ ->setArgument('hostids', [$host['hostid']])
),
CViewHelper::showNum($total_problem_count)
],
diff --git a/ui/app/partials/monitoring.problem.filter.php b/ui/app/partials/monitoring.problem.filter.php
new file mode 100644
index 00000000000..fa5985f6464
--- /dev/null
+++ b/ui/app/partials/monitoring.problem.filter.php
@@ -0,0 +1,641 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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
+ */
+
+$left_column = (new CFormList())
+ ->addRow(_('Show'),
+ (new CRadioButtonList('show', (int) $data['show']))
+ ->addValue(_('Recent problems'), TRIGGERS_OPTION_RECENT_PROBLEM, 'show_1#{uniqid}')
+ ->addValue(_('Problems'), TRIGGERS_OPTION_IN_PROBLEM, 'show_3#{uniqid}')
+ ->addValue(_('History'), TRIGGERS_OPTION_ALL, 'show_2#{uniqid}')
+ ->setId('show_#{uniqid}')
+ ->setModern(true)
+ )
+ ->addRow((new CLabel(_('Host groups'), 'groupids_#{uniqid}_ms')),
+ (new CMultiSelect([
+ 'name' => 'groupids[]',
+ 'object_name' => 'hostGroup',
+ 'data' => array_key_exists('groups', $data) ? $data['groups'] : [],
+ '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}')
+ )
+ ->addRow((new CLabel(_('Hosts'), 'hostids_#{uniqid}_ms')),
+ (new CMultiSelect([
+ 'name' => 'hostids[]',
+ 'object_name' => 'hosts',
+ 'data' => array_key_exists('hosts', $data) ? $data['hosts'] : [],
+ '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}')
+ )
+ ->addRow(_('Application'), [
+ (new CTextBox('application', $data['application']))
+ ->setId('application_#{uniqid}')
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH),
+ (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
+ (new CButton('application_select', _('Select')))
+ ->setId('application_select_#{uniqid}')
+ ->addClass(ZBX_STYLE_BTN_GREY)
+ ])
+ ->addRow((new CLabel(_('Triggers'), 'triggerids_#{uniqid}_ms')),
+ (new CMultiSelect([
+ 'name' => 'triggerids[]',
+ 'object_name' => 'triggers',
+ 'data' => array_key_exists('triggers', $data) ? $data['triggers'] : [],
+ 'popup' => [
+ 'filter_preselect_fields' => [
+ 'hosts' => 'hostids_'
+ ],
+ 'parameters' => [
+ 'srctbl' => 'triggers',
+ 'srcfld1' => 'triggerid',
+ 'dstfrm' => 'zbx_filter',
+ 'dstfld1' => 'triggerids_',
+ 'monitored_hosts' => true,
+ 'with_monitored_triggers' => true,
+ 'noempty' => true
+ ]
+ ]
+ ]))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('triggerids_#{uniqid}')
+ )
+ ->addRow(_('Problem'),
+ (new CTextBox('name', $data['name']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setId('name_#{uniqid}')
+ )
+ ->addRow(_('Severity'),
+ (new CSeverityCheckBoxList('severities'))
+ ->setChecked($data['severities'])
+ ->setUniqid('#{uniqid}')
+ );
+
+$filter_age = (new CNumericBox('age', $data['age'], 3, false, false, false))
+ ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH)
+ ->removeId();
+if ($data['age_state'] == 0) {
+ $filter_age->setAttribute('disabled', 'disabled');
+}
+
+$left_column
+ ->addRow(_('Age less than'), [
+ (new CCheckBox('age_state'))
+ ->setChecked($data['age_state'] == 1)
+ ->setUncheckedValue(0)
+ ->setId('age_state_#{uniqid}'),
+ (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
+ $filter_age,
+ (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
+ _('days')
+ ]);
+
+$filter_inventory_table = new CTable();
+$filter_inventory_table->setId('filter-inventory_#{uniqid}');
+$inventories = array_column(getHostInventories(), 'title', 'db_field');
+$i = 0;
+foreach ($data['inventory'] as $field) {
+ $filter_inventory_table->addRow([
+ new CComboBox('inventory['.$i.'][field]', $field['field'], null, $inventories),
+ (new CTextBox('inventory['.$i.'][value]', $field['value']))->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (new CCol(
+ (new CButton('inventory['.$i.'][remove]', _('Remove')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-remove')
+ ))->addClass(ZBX_STYLE_NOWRAP)
+ ], 'form_row');
+
+ $i++;
+}
+$filter_inventory_table->addRow(
+ (new CCol(
+ (new CButton('inventory_add', _('Add')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-add')
+ ->removeId()
+ ))->setColSpan(3)
+);
+
+$filter_tags_table = new CTable();
+$filter_tags_table->setId('filter-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 CRadioButtonList('tags['.$i.'][operator]', (int) $tag['operator']))
+ ->addValue(_('Contains'), TAG_OPERATOR_LIKE)
+ ->addValue(_('Equals'), TAG_OPERATOR_EQUAL)
+ ->setModern(true),
+ (new CTextBox('tags['.$i.'][value]', $tag['value']))
+ ->setAttribute('placeholder', _('value'))
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (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)
+);
+
+$tag_format_line = (new CHorList())
+ ->addItem((new CRadioButtonList('show_tags', (int) $data['show_tags']))
+ ->addValue(_('None'), PROBLEMS_SHOW_TAGS_NONE, 'show_tags_0#{uniqid}')
+ ->addValue(PROBLEMS_SHOW_TAGS_1, PROBLEMS_SHOW_TAGS_1, 'show_tags_1#{uniqid}')
+ ->addValue(PROBLEMS_SHOW_TAGS_2, PROBLEMS_SHOW_TAGS_2, 'show_tags_2#{uniqid}')
+ ->addValue(PROBLEMS_SHOW_TAGS_3, PROBLEMS_SHOW_TAGS_3, 'show_tags_3#{uniqid}')
+ ->setModern(true)
+ ->setId('show_tags_#{uniqid}')
+ )
+ ->addItem((new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN))
+ ->addItem(new CLabel(_('Tag name')))
+ ->addItem((new CRadioButtonList('tag_name_format', (int) $data['tag_name_format']))
+ ->addValue(_('Full'), PROBLEMS_TAG_NAME_FULL, 'tag_name_format_0#{uniqid}')
+ ->addValue(_('Shortened'), PROBLEMS_TAG_NAME_SHORTENED, 'tag_name_format_1#{uniqid}')
+ ->addValue(_('None'), PROBLEMS_TAG_NAME_NONE, 'tag_name_format_2#{uniqid}')
+ ->setModern(true)
+ ->setEnabled((int) $data['show_tags'] !== PROBLEMS_SHOW_TAGS_NONE)
+ ->setId('tag_name_format_#{uniqid}')
+ );
+
+$right_column = (new CFormList())
+ ->addRow(_('Host inventory'), $filter_inventory_table)
+ ->addRow(_('Tags'), $filter_tags_table)
+ ->addRow(_('Show tags'), $tag_format_line)
+ ->addRow(_('Tag display priority'),
+ (new CTextBox('tag_priority', $data['tag_priority']))
+ ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
+ ->setAttribute('placeholder', _('comma-separated list'))
+ ->setEnabled((int) $data['show_tags'] !== PROBLEMS_SHOW_TAGS_NONE)
+ ->setId('tag_priority_#{uniqid}')
+ )
+ ->addRow(_('Show operational data'), [
+ (new CRadioButtonList('show_opdata', (int) $data['show_opdata']))
+ ->addValue(_('None'), OPERATIONAL_DATA_SHOW_NONE, 'show_opdata_0_#{uniqid}')
+ ->addValue(_('Separately'), OPERATIONAL_DATA_SHOW_SEPARATELY, 'show_opdata_1_#{uniqid}')
+ ->addValue(_('With problem name'), OPERATIONAL_DATA_SHOW_WITH_PROBLEM, 'show_opdata_2_#{uniqid}')
+ ->setModern(true)
+ ->setEnabled($data['compact_view'] == 0)
+ ->removeId()
+ ])
+ ->addRow(_('Show suppressed problems'), [
+ (new CCheckBox('show_suppressed'))
+ ->setChecked($data['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
+ ->setUncheckedValue(0)
+ ->setId('show_suppressed_#{uniqid}'),
+ (new CDiv([
+ (new CLabel(_('Show unacknowledged only'), 'unacknowledged_#{uniqid}'))
+ ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
+ (new CCheckBox('unacknowledged'))
+ ->setChecked($data['unacknowledged'] == 1)
+ ->setUncheckedValue(0)
+ ->setId('unacknowledged_#{uniqid}')
+ ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
+ ])
+ ->addRow(_('Compact view'), [
+ (new CCheckBox('compact_view'))
+ ->setChecked($data['compact_view'] == 1)
+ ->setUncheckedValue(0)
+ ->setId('compact_view_#{uniqid}'),
+ (new CDiv([
+ (new CLabel(_('Show timeline'), 'show_timeline_#{uniqid}'))->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
+ (new CCheckBox('show_timeline'))
+ ->setChecked($data['show_timeline'] == 1)
+ ->setEnabled($data['compact_view'] == 0)
+ ->setUncheckedValue(0)
+ ->setId('show_timeline_#{uniqid}'),
+ ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
+ ])
+ ->addRow(_('Show details'), [
+ (new CCheckBox('details'))
+ ->setChecked($data['details'] == 1)
+ ->setEnabled($data['compact_view'] == 0)
+ ->setUncheckedValue(0)
+ ->setId('details_#{uniqid}'),
+ (new CDiv([
+ (new CLabel(_('Highlight whole row'), 'highlight_row'))->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
+ (new CCheckBox('highlight_row'))
+ ->setChecked($data['highlight_row'] == 1)
+ ->setEnabled($data['compact_view'] == 1)
+ ->setUncheckedValue(0)
+ ->setId('highlight_row_#{uniqid}')
+ ]))
+ ->addClass(ZBX_STYLE_FILTER_HIGHLIGHT_ROW_CB)
+ ->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
+ ]);
+
+$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([
+ $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-problem'))
+ ->setAttribute('data-template', 'monitoring.problem.filter')
+ ->addItem($template)
+ ->show();
+
+(new CScriptTemplate('filter-inventory-row'))
+ ->addItem(
+ (new CRow([
+ (new CComboBox('inventory[#{rowNum}][field]', null, null, $inventories))->removeId(),
+ (new CTextBox('inventory[#{rowNum}][value]', '#{value}'))
+ ->removeId()
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (new CCol(
+ (new CButton('inventory[#{rowNum}][remove]', _('Remove')))
+ ->addClass(ZBX_STYLE_BTN_LINK)
+ ->addClass('element-table-remove')
+ ->removeId()
+ ))->addClass(ZBX_STYLE_NOWRAP)
+ ]))->addClass('form_row')
+ )
+ ->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 CRadioButtonList('tags[#{rowNum}][operator]', TAG_OPERATOR_LIKE))
+ ->addValue(_('Contains'), TAG_OPERATOR_LIKE, 'tags_0#{rowNum}#{uniqid}')
+ ->addValue(_('Equals'), TAG_OPERATOR_EQUAL, 'tags_1#{rowNum}#{uniqid}')
+ ->setModern(true)
+ ->setId('tags_#{rowNum}#{uniqid}'),
+ (new CTextBox('tags[#{rowNum}][value]', '#{value}'))
+ ->setAttribute('placeholder', _('value'))
+ ->removeId()
+ ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
+ (new CCol(
+ (new CButton('tags[#{rowNum}][remove]', _('Remove')))
+ ->removeId()
+ ->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.problem.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();
+
+ let fields = ['show', 'application', 'name', 'tag_priority', 'show_opdata', 'show_suppressed', 'show_tags',
+ 'unacknowledged', 'compact_view', 'show_timeline', 'details', 'highlight_row', 'age_state', 'age',
+ 'tag_name_format', 'evaltype'
+ ],
+ eventHandler = {
+ show: () => {
+ // Dynamically disable hidden input elements to allow correct detection of unsaved changes.
+ var filter_show = ($('input[name="show"]:checked', container).val() != <?= TRIGGERS_OPTION_ALL ?>),
+ disabled = (!filter_show || !$('[name="age_state"]:checked', container).length);
+
+ $('[name="age"]', container).attr('disabled', disabled).closest('li').toggle(filter_show);
+ $('[name="age_state"]', container).attr('disabled', !filter_show);
+
+ if (filter_show) {
+ this._data.filter_custom_time = 0;
+ }
+
+ if (this._parent) {
+ this._parent.updateTimeselector(this, filter_show);
+ }
+ },
+ age_state: (ev) => {
+ $('[name="age"]', container).prop('disabled', !$('[name="age_state"]', container).is(':checked'));
+ },
+ compact_view: () => {
+ let checked = $('[name="compact_view"]', container).is(':checked');
+
+ $('[name="show_timeline"]', container).prop('disabled', checked);
+ $('[name="details"]', container).prop('disabled', checked);
+ $('[name="show_opdata"]', container).prop('disabled', checked);
+ $('[name="highlight_row"]', container).prop('disabled', !checked);
+ },
+ show_tags: () => {
+ let disabled = ($('[name="show_tags"]:checked', container).val() == <?= PROBLEMS_SHOW_TAGS_NONE ?>);
+
+ $('[name="tag_priority"]', container).prop('disabled', disabled);
+ $('[name="tag_name_format"]', container).prop('disabled', disabled);
+ }
+ };
+
+ // Input, radio and single checkboxes.
+ fields.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 timeline default value is checked and it will be rendered in template therefore initalize if unchecked.
+ $('[name="show_timeline"][unchecked-value="' + data['show_timeline'] + '"]', container).removeAttr('checked');
+
+ // Severities checkboxes.
+ for (const value in data.severities) {
+ $('[name="severities[' + value + ']"]', container).attr('checked', true);
+ }
+
+ // Inventory table.
+ if (data.inventory.length == 0) {
+ data.inventory.push({'field': '', 'value': ''});
+ }
+ $('#filter-inventory_' + data.uniqid, container).dynamicRows({
+ template: '#filter-inventory-row',
+ rows: data.inventory,
+ counter: 0
+ });
+
+ // Tags table.
+ if (data.tags.length == 0) {
+ data.tags.push({'tag': '', 'value': '', 'operator': <?= TAG_OPERATOR_LIKE ?>});
+ }
+
+ $('#filter-tags_' + data.uniqid, container).dynamicRows({
+ template: '#filter-tag-row-tmpl',
+ rows: data.tags,
+ counter: 0,
+ dataCallback: (tag) => {
+ tag.uniqid = data.uniqid
+ return tag;
+ }
+ });
+
+ // Host groups multiselect.
+ $('#groupids_' + data.uniqid, container).multiSelectHelper({
+ id: 'groupids_' + data.uniqid,
+ object_name: 'hostGroup',
+ name: 'groupids[]',
+ data: data.filter_view_data.groups || [],
+ objectOptions: {
+ real_hosts: 1,
+ enrich_parent_groups: 1
+ },
+ popup: {
+ parameters: {
+ srctbl: 'host_groups',
+ srcfld1: 'groupid',
+ dstfrm: 'zbx_filter',
+ dstfld1: 'groupids_' + data.uniqid,
+ multiselect: 1,
+ noempty: 1,
+ 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 || [],
+ popup: {
+ filter_preselect_fields: {
+ hostgroups: 'groupids_' + data.uniqid
+ },
+ parameters: {
+ multiselect: 1,
+ srctbl: 'hosts',
+ srcfld1: 'hostid',
+ dstfrm: 'zbx_filter',
+ dstfld1: 'hostids_' + data.uniqid,
+ }
+ }
+ });
+
+ // Application
+ $('#application_select_' + data.uniqid).on('click', function() {
+ let options = {
+ srctbl: 'applications',
+ srcfld1: 'name',
+ dstfrm: 'zbx_filter',
+ dstfld1: 'application_' + data.uniqid,
+ with_applications: '1',
+ real_hosts: '1'
+ };
+
+ PopUp('popup.generic', $.extend(options, getFirstMultiselectValue('hostids_' + data.uniqid)), null, this);
+ });
+
+ // Triggers multiselect.
+ $('#triggerids_' + data.uniqid, container).multiSelectHelper({
+ id: 'triggerids_' + data.uniqid,
+ object_name: 'triggers',
+ name: 'triggerids[]',
+ data: data.filter_view_data.triggers || [],
+ popup: {
+ filter_preselect_fields: {
+ hosts: 'hostids_' + data.uniqid
+ },
+ parameters: {
+ srctbl: 'triggers',
+ srcfld1: 'triggerid',
+ dstfrm: 'zbx_filter',
+ dstfld1: 'triggerids_' + data.uniqid,
+ multiselect: 1,
+ noempty: 1,
+ monitored_hosts: 1,
+ with_monitored_triggers: 1
+ }
+ }
+ });
+
+ $('#show_' + data.uniqid, container).change(eventHandler.show).trigger('change');
+ $('[name="age_state"]').change(eventHandler.age_state).trigger('change');
+ $('[name="compact_view"]', container).change(eventHandler.compact_view).trigger('change');
+ $('[name="show_tags"]', container).change(eventHandler.show_tags).trigger('change');
+
+ // Initialize src_url.
+ this.resetUnsavedState();
+ this.on(TABFILTERITEM_EVENT_ACTION, update.bind(this));
+
+ if (this._parent) {
+ this._parent.on(TABFILTER_EVENT_UPDATE, (ev) => {
+ let form = this.getForm(),
+ tabfilter = ev.detail.target;
+
+ if (tabfilter._active_item !== this) {
+ return;
+ }
+
+ if ($(form).find('[name="filter_custom_time"]').val() == 1) {
+ $('[name="show"][value="<?= TRIGGERS_OPTION_ALL ?>"]', form).prop('checked', true);
+ $('#show_' + this._data.uniqid, form).trigger('change');
+ this.updateUnsavedState();
+ this.setBrowserLocationToApplyUrl();
+ }
+ });
+
+ this._parent.on(TABFILTER_EVENT_NEWITEM, () => {
+ let form = this.getForm();
+
+ if ($(form).find('[name="filter_custom_time"]').val() == 1) {
+ $('[name="show"][value="<?= TRIGGERS_OPTION_ALL ?>"]', form).prop('checked', true);
+ }
+ });
+ }
+ }
+
+ 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();
+
+ // Trigger change to update timeselector ui disabled state.
+ $('#show_' + data.uniqid, container).trigger('change');
+ }
+
+ function select(data, container) {
+ if (this._template_rendered) {
+ // Template rendered, use element events, trigger change to update timeselector ui disabled state.
+ $('#show_' + data.uniqid, container).trigger('change');
+ }
+ else if (this._parent) {
+ // Template is not rendered, use input data.
+ this._parent.updateTimeselector(this, (data.show != <?= TRIGGERS_OPTION_ALL ?>));
+ }
+ }
+
+ /**
+ * 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="highlight_row"],[name="details"],[name="show_timeline"]', container)
+ .filter(':disabled')
+ .prop('checked', false);
+
+ $('[name="show_opdata"]:disabled', container)
+ .prop('checked', false)
+ .filter('[value="' + <?= CControllerProblem::FILTER_FIELDS_DEFAULT['show_opdata'] ?> +'"]')
+ .prop('checked', true);
+
+ if ($('[name="age_state"]', container).not(':checked').length) {
+ $('[name="age"]').val(<?= CControllerProblem::FILTER_FIELDS_DEFAULT['age'] ?>);
+ }
+ }
+
+ // 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);
+ });
+ template.addEventListener(TABFILTERITEM_EVENT_SELECT, function(ev) {
+ select.call(ev.detail, ev.detail._data, ev.detail._content_container);
+ });
+</script>
diff --git a/ui/app/partials/timeselector.filter.php b/ui/app/partials/timeselector.filter.php
new file mode 100644
index 00000000000..3d7d1f78088
--- /dev/null
+++ b/ui/app/partials/timeselector.filter.php
@@ -0,0 +1,111 @@
+<?php declare(strict_types = 1);
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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
+ */
+
+$time_ranges = [
+ [
+ ['now-2d', 'now'],
+ ['now-7d', 'now'],
+ ['now-30d', 'now'],
+ ['now-3M', 'now'],
+ ['now-6M', 'now'],
+ ['now-1y', 'now'],
+ ['now-2y', 'now']
+ ],
+ [
+ ['now-1d/d', 'now-1d/d'],
+ ['now-2d/d', 'now-2d/d'],
+ ['now-1w/d', 'now-1w/d'],
+ ['now-1w/w', 'now-1w/w'],
+ ['now-1M/M', 'now-1M/M'],
+ ['now-1y/y', 'now-1y/y']
+ ],
+ [
+ ['now/d', 'now/d'],
+ ['now/d', 'now'],
+ ['now/w', 'now/w'],
+ ['now/w', 'now'],
+ ['now/M', 'now/M'],
+ ['now/M', 'now'],
+ ['now/y', 'now/y'],
+ ['now/y', 'now']
+ ],
+ [
+ ['now-5m', 'now'],
+ ['now-15m', 'now'],
+ ['now-30m', 'now'],
+ ['now-1h', 'now'],
+ ['now-3h', 'now'],
+ ['now-6h', 'now'],
+ ['now-12h', 'now'],
+ ['now-24h', 'now']
+ ]
+];
+$predefined_ranges = [];
+
+foreach ($time_ranges as $column_ranges) {
+ $column = (new CList())->addClass(ZBX_STYLE_TIME_QUICK);
+
+ foreach ($column_ranges as $range) {
+ $label = relativeDateToText($range[0], $range[1]);
+ $is_selected = ($data['label'] === $label);
+
+ $column->addItem((new CLink($label))
+ ->setAttribute('data-from', $range[0])
+ ->setAttribute('data-to', $range[1])
+ ->setAttribute('data-label', $label)
+ ->addClass($is_selected ? ZBX_STYLE_SELECTED : null)
+ );
+ }
+
+ $predefined_ranges[] = (new CDiv($column))->addClass(ZBX_STYLE_CELL);
+}
+
+(new CDiv([
+ (new CDiv([
+ new CList([
+ new CLabel(_('From'), 'from'),
+ (new CDateSelector('from', $data['from']))->setDateFormat($data['format'])
+ ]),
+ (new CList([(new CListItem(''))->addClass(ZBX_STYLE_RED)]))
+ ->setAttribute('data-error-for', 'from')
+ ->addClass(ZBX_STYLE_TIME_INPUT_ERROR)
+ ->addStyle('display: none'),
+ new CList([
+ new CLabel(_('To'), 'to'),
+ (new CDateSelector('to', $data['to']))->setDateFormat($data['format'])
+ ]),
+ (new CList([(new CListItem(''))->addClass(ZBX_STYLE_RED)]))
+ ->setAttribute('data-error-for', 'to')
+ ->addClass(ZBX_STYLE_TIME_INPUT_ERROR)
+ ->addStyle('display: none'),
+ new CList([
+ new CButton('apply', _('Apply'))
+ ])
+ ]))->addClass(ZBX_STYLE_TIME_INPUT),
+ (new CDiv($predefined_ranges))->addClass(ZBX_STYLE_TIME_QUICK_RANGE)
+]))
+ ->addClass(ZBX_STYLE_FILTER_CONTAINER)
+ ->addClass(ZBX_STYLE_TIME_SELECTION_CONTAINER)
+ ->show();
diff --git a/ui/app/views/js/monitoring.host.view.js.php b/ui/app/views/js/monitoring.host.view.js.php
index 76c8189ff60..23f5ba2195e 100644
--- a/ui/app/views/js/monitoring.host.view.js.php
+++ b/ui/app/views/js/monitoring.host.view.js.php
@@ -22,45 +22,71 @@
/**
* @var CView $this
*/
+
?>
-<script type="text/x-jquery-tmpl" id="filter-tag-row-tmpl">
- <?= (new CRow([
- (new CTextBox('filter_tags[#{rowNum}][tag]'))
- ->setAttribute('placeholder', _('tag'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CRadioButtonList('filter_tags[#{rowNum}][operator]', TAG_OPERATOR_LIKE))
- ->addValue(_('Contains'), TAG_OPERATOR_LIKE)
- ->addValue(_('Equals'), TAG_OPERATOR_EQUAL)
- ->setModern(true),
- (new CTextBox('filter_tags[#{rowNum}][value]'))
- ->setAttribute('placeholder', _('value'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_tags[#{rowNum}][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ]))
- ->addClass('form_row')
- ->toString()
- ?>
-</script>
<script type="text/javascript">
jQuery(function($) {
- $('#filter-tags').dynamicRows({template: '#filter-tag-row-tmpl'});
-
- $('#filter_maintenance_status').on('change', function() {
- $('#filter_show_suppressed').prop('disabled', !this.checked);
- });
-
function hostPage() {
+ let filter_options = <?= json_encode($data['filter_options']) ?>;
+
this.refresh_url = '<?= $data['refresh_url'] ?>';
this.refresh_interval = <?= $data['refresh_interval'] ?>;
this.running = false;
this.timeout = null;
+ this.deferred = null;
+
+ if (filter_options) {
+ this.refresh_counters = this.createCountersRefresh(1);
+ this.filter = new CTabFilter($('#monitoring_hosts_filter')[0], filter_options);
+ this.filter.on(TABFILTER_EVENT_URLSET, (ev) => {
+ let url = new Curl('', false);
+
+ url.setArgument('action', 'host.view.refresh');
+ this.refresh_url = url.getUrl();
+ this.unscheduleRefresh();
+ this.refresh();
+ });
+ this.filter.on(TABFILTER_EVENT_UPDATE, (ev) => {
+ if (!this.filter._active_item.hasCounter() || ev.detail.filter_property !== 'properties') {
+ return;
+ }
+
+ var filter_item = this.filter._active_item;
+
+ $.post('zabbix.php', {
+ action: 'host.view.refresh',
+ filter_counters: 1,
+ counter_index: filter_item._index
+ }).done((json) => {
+ if (json.filter_counters) {
+ filter_item.updateCounter(json.filter_counters.pop());
+ }
+ });
+ });
+ }
}
hostPage.prototype = {
+ createCountersRefresh: function(timeout) {
+ if (this.refresh_counters) {
+ clearTimeout(this.refresh_counters);
+ this.refresh_counters = null;
+ }
+
+ return setTimeout(() => this.getFiltersCounters(), timeout);
+ },
+ getFiltersCounters: function() {
+ return $.post('zabbix.php', {
+ action: 'host.view.refresh',
+ filter_counters: 1
+ }).done((json) => {
+ if (json.filter_counters) {
+ this.filter.updateCounters(json.filter_counters);
+ }
+ }).always(() => {
+ this.refresh_counters = this.createCountersRefresh(this.refresh_interval);
+ });
+ },
getCurrentForm: function() {
return $('form[name=host_view]');
},
@@ -73,9 +99,9 @@
refresh: function() {
this.setLoading();
- var deferred = $.getJSON(this.refresh_url);
+ this.deferred = $.getJSON(this.refresh_url);
- return this.bindDataEvents(deferred);
+ return this.bindDataEvents(this.deferred);
},
setLoading: function() {
this.getCurrentForm().addClass('is-loading is-loading-fadein delayed-15s');
@@ -128,6 +154,7 @@
},
onDataAlways: function() {
if (this.running) {
+ this.deferred = null;
this.scheduleRefresh();
}
},
@@ -143,19 +170,20 @@
clearTimeout(this.timeout);
this.timeout = null;
}
+
+ if (this.deferred) {
+ this.deferred.abort();
+ }
},
start: function() {
if (this.refresh_interval != 0) {
this.running = true;
- this.scheduleRefresh();
+ this.refresh();
}
- },
- stop: function() {
- this.running = false;
- this.unscheduleRefresh();
}
};
window.host_page = new hostPage();
+ window.host_page.start();
});
</script>
diff --git a/ui/app/views/js/monitoring.problem.view.js.php b/ui/app/views/js/monitoring.problem.view.js.php
index a47fc1b22ae..778a0e17a8f 100644
--- a/ui/app/views/js/monitoring.problem.view.js.php
+++ b/ui/app/views/js/monitoring.problem.view.js.php
@@ -22,81 +22,154 @@
/**
* @var CView $this
*/
-?>
-
-<script type="text/x-jquery-tmpl" id="filter-inventory-row">
- <?= (new CRow([
- new CComboBox('filter_inventory[#{rowNum}][field]', null, null, $data['filter']['inventories']),
- (new CTextBox('filter_inventory[#{rowNum}][value]'))->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_inventory[#{rowNum}][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ]))
- ->addClass('form_row')
- ->toString()
- ?>
-</script>
-<script type="text/x-jquery-tmpl" id="filter-tag-row-tmpl">
- <?= (new CRow([
- (new CTextBox('filter_tags[#{rowNum}][tag]'))
- ->setAttribute('placeholder', _('tag'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CRadioButtonList('filter_tags[#{rowNum}][operator]', TAG_OPERATOR_LIKE))
- ->addValue(_('Contains'), TAG_OPERATOR_LIKE)
- ->addValue(_('Equals'), TAG_OPERATOR_EQUAL)
- ->setModern(true),
- (new CTextBox('filter_tags[#{rowNum}][value]'))
- ->setAttribute('placeholder', _('value'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_tags[#{rowNum}][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ]))
- ->addClass('form_row')
- ->toString()
- ?>
-</script>
-
-<script type="text/javascript">
- jQuery(function($) {
- $(function() {
- $('#filter-inventory').dynamicRows({template: '#filter-inventory-row'});
- $('#filter-tags').dynamicRows({template: '#filter-tag-row-tmpl'});
+if (array_key_exists('filter_options', $data)) { ?>
+ <script type="text/javascript">
+ $(function() {
+ var options = <?= json_encode($data['filter_options']) ?>,
+ filter = new CTabFilter($('#monitoring_problem_filter')[0], options),
+ refresh_interval = <?= $data['refresh_interval'] ?>,
+ refresh_url = '<?= $data['refresh_url'] ?>',
+ refresh_timer,
+ filter_item,
+ filter_counter_fetch,
+ active_filter = filter._active_item,
+ global_timerange = {
+ from: options.timeselector.from,
+ to: options.timeselector.to
+ };
+
+ /**
+ * Update on filter changes.
+ */
+ filter.on(TABFILTER_EVENT_URLSET, () => {
+ let url = new Curl();
+
+ url.setArgument('action', 'problem.view.csv');
+ $('#export_csv').attr('data-url', url.getUrl());
+ refreshResults();
+
+ if (active_filter !== filter._active_item) {
+ active_filter = filter._active_item;
+ chkbxRange.checkObjectAll(chkbxRange.pageGoName, false);
+ chkbxRange.clearSelectedOnFilterChange();
+ }
});
- $('#filter_show').change(function() {
- var filter_show = jQuery('input[name=filter_show]:checked').val();
+ /**
+ * Update filter item counter when filter settings updated.
+ */
+ filter.on(TABFILTER_EVENT_UPDATE, (ev) => {
+ if (!filter._active_item.hasCounter() || ev.detail.filter_property !== 'properties') {
+ return;
+ }
- $('#filter_age').closest('li').toggle(filter_show == <?= TRIGGERS_OPTION_RECENT_PROBLEM ?>
- || filter_show == <?= TRIGGERS_OPTION_IN_PROBLEM ?>);
+ if (filter_counter_fetch) {
+ filter_counter_fetch.abort();
+ }
+
+ filter_counter_fetch = new AbortController();
+ filter_item = filter._active_item;
+
+ fetch(refresh_url, {
+ method: 'POST',
+ signal: filter_counter_fetch.signal,
+ body: new URLSearchParams({filter_counters: 1, counter_index: filter_item._index})
+ })
+ .then(response => response.json())
+ .then(response => {
+ filter_item.updateCounter(response.filter_counters.pop());
+ });
});
- $('#filter_show').trigger('change');
+ /**
+ * Refresh results table via window.flickerfreeScreen.refresh call.
+ */
+ function refreshResults() {
+ let url = new Curl(),
+ screen = window.flickerfreeScreen.screens['problem'],
+ data = $.extend(<?= json_encode($data['filter_defaults']) ?>,
+ global_timerange, url.getArgumentsObject()
+ );
+
+ data.inventory = data.inventory
+ ? data.inventory.filter(inventory => 'value' in inventory && inventory.value !== '')
+ : data.inventory;
+ data.tags = data.tags
+ ? data.tags.filter(tag => !(tag.tag === '' && tag.value === ''))
+ : data.tags;
+ data.severities = data.severities
+ ? data.severities.filter((value, key) => value == key)
+ : data.severities;
+
+ // Modify filter data of flickerfreeScreen object with id 'problem'.
+ if (data.page === null) {
+ delete data.page;
+ }
- $('#filter_compact_view').change(function() {
- if ($(this).is(':checked')) {
- $('#filter_show_timeline, #filter_details').prop('disabled', true);
- $('input[name=filter_show_opdata]').prop('disabled', true);
- $('#filter_highlight_row').prop('disabled', false);
+ if (data.filter_custom_time) {
+ screen.timeline.from = data.from;
+ screen.timeline.to = data.to;
}
else {
- $('#filter_show_timeline, #filter_details').prop('disabled', false);
- $('input[name=filter_show_opdata]').prop('disabled', false);
- $('#filter_highlight_row').prop('disabled', true);
+ screen.timeline.from = global_timerange.from;
+ screen.timeline.to = global_timerange.to;
}
- });
- $('#filter_show_tags').change(function() {
- var disabled = $(this).find('[value = "<?= PROBLEMS_SHOW_TAGS_NONE ?>"]').is(':checked');
- $('#filter_tag_priority').prop('disabled', disabled);
- $('#filter_tag_name_format input').prop('disabled', disabled);
- });
+ screen.data.filter = data;
+ screen.data.sort = data.sort;
+ screen.data.sortorder = data.sortorder;
+ // Close all opened hint boxes otherwise flicker free screen will not refresh it content.
+ for (var i = overlays_stack.length - 1; i >= 0; i--) {
+ let hintbox = overlays_stack.getById(overlays_stack.stack[i]);
+
+ if (hintbox.type === 'hintbox') {
+ hintBox.hideHint(hintbox.element, true);
+ removeFromOverlaysStack(overlays_stack.stack[i]);
+ }
+ }
+
+ window.flickerfreeScreen.refresh(screen.id);
+ }
+
+ function refreshCounters() {
+ clearTimeout(refresh_timer);
+
+ fetch(refresh_url, {
+ method: 'POST',
+ body: new URLSearchParams({filter_counters: 1})
+ })
+ .then(response => response.json())
+ .then(response => {
+ if (response.filter_counters) {
+ filter.updateCounters(response.filter_counters);
+ }
+
+ refresh_timer = setTimeout(refreshCounters, refresh_interval);
+ })
+ .catch(() => {
+ // On error restart refresh timer.
+ refresh_timer = setTimeout(refreshCounters, refresh_interval);
+ });
+ }
+
+ refreshCounters();
+
+ // Keep timeselector changes in global_timerange.
+ $.subscribe('timeselector.rangeupdate', (e, data) => {
+ if (data.idx === '<?= CControllerProblem::FILTER_IDX ?>') {
+ global_timerange.from = data.from;
+ global_timerange.to = data.to;
+ }
+ });
+ });
+ </script>
+<?php
+}
+?>
+<script type="text/javascript">
+ jQuery(function($) {
$(document).on({
mouseenter: function() {
if ($(this)[0].scrollWidth > $(this)[0].offsetWidth) {
diff --git a/ui/app/views/js/popup.tabfilter.edit.js.php b/ui/app/views/js/popup.tabfilter.edit.js.php
new file mode 100644
index 00000000000..948e3b68cfe
--- /dev/null
+++ b/ui/app/views/js/popup.tabfilter.edit.js.php
@@ -0,0 +1,84 @@
+<?php
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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 CView $this
+ */
+?>
+
+$('.overlay-dialogue-body #filter_custom_time').on('change', function() {
+ let $calendars = $(this).closest('form').find('.calendar-control');
+
+ $('input,button', $calendars).prop('disabled', !$(this).is(':checked'));
+});
+
+function tabFilterDelete(overlay) {
+ var $form = overlay.$dialogue.find('form'),
+ url = new Curl($form.attr('action')),
+ form_data = $form.serializeJSON();
+
+ url.setArgument('action', 'popup.tabfilter.delete');
+ url.setArgument('idx', form_data['idx']);
+ url.setArgument('idx2', form_data['idx2']);
+
+ overlay.setLoading();
+ overlay.xhr = $.post(url.getUrl(), null, 'json')
+ .done((response) => {
+ overlay.$dialogue.find('.<?= ZBX_STYLE_MSG_BAD ?>').remove();
+
+ if ('errors' in response) {
+ $(response.errors).insertBefore($form);
+ }
+ else {
+ overlayDialogueDestroy(overlay.dialogueid);
+ overlay.element.dispatchEvent(new CustomEvent(TABFILTERITEM_EVENT_DELETE, {bubbles: true}));
+ }
+ })
+ .always(() => {
+ overlay.unsetLoading();
+ });
+}
+
+function tabFilterUpdate(overlay) {
+ var $form = overlay.$dialogue.find('form'),
+ url = new Curl($form.attr('action')),
+ form_data = $form.serializeJSON();
+
+ form_data.filter_name = form_data.filter_name.trim();
+
+ overlay.setLoading();
+ overlay.xhr = $.post(url.getUrl(), form_data, 'json')
+ .done((response) => {
+ overlay.$dialogue.find('.<?= ZBX_STYLE_MSG_BAD ?>').remove();
+
+ if ('errors' in response) {
+ $(response.errors).insertBefore($form);
+ }
+ else {
+ overlayDialogueDestroy(overlay.dialogueid);
+ const properties = {detail: response, bubbles: true};
+ overlay.element.dispatchEvent(new CustomEvent(TABFILTERITEM_EVENT_UPDATE, properties));
+ }
+ })
+ .always(() => {
+ overlay.unsetLoading();
+ });
+}
diff --git a/ui/app/views/js/popup.triggerwizard.js.php b/ui/app/views/js/popup.triggerwizard.js.php
index 72f51f627e3..f01b29205d5 100644
--- a/ui/app/views/js/popup.triggerwizard.js.php
+++ b/ui/app/views/js/popup.triggerwizard.js.php
@@ -142,6 +142,12 @@
$expr_input.val('');
}
+
+ $('#event_name')
+ .textareaFlexible()
+ .on('input keydown paste', function() {
+ overlays_stack.end().centerDialog();
+ });
})(jQuery);
/**
diff --git a/ui/app/views/monitoring.host.view.php b/ui/app/views/monitoring.host.view.php
index ed9a5376baf..ba502131a93 100644
--- a/ui/app/views/monitoring.host.view.php
+++ b/ui/app/views/monitoring.host.view.php
@@ -25,8 +25,11 @@
$this->addJsFile('multiselect.js');
$this->addJsFile('layout.mode.js');
-
-$this->includeJsFile('monitoring.host.view.js.php');
+$this->addJsFile('menupopup.js');
+$this->addJsFile('gtlc.js');
+$this->addJsFile('class.calendar.js');
+$this->addJsFile('class.tabfilter.js');
+$this->addJsFile('class.tabfilteritem.js');
$this->enableLayoutModes();
$web_layout_mode = $this->getLayoutMode();
@@ -39,133 +42,28 @@ $widget = (new CWidget())
->setAttribute('aria-label', _('Content controls'))
);
-$filter_tags = $data['filter']['tags'];
-if (!$filter_tags) {
- $filter_tags = [['tag' => '', 'value' => '', 'operator' => TAG_OPERATOR_LIKE]];
-}
-
-$filter_tags_table = (new CTable())
- ->setId('filter-tags')
- ->addRow(
- (new CCol(
- (new CRadioButtonList('filter_evaltype', (int) $data['filter']['evaltype']))
- ->addValue(_('And/Or'), TAG_EVAL_TYPE_AND_OR)
- ->addValue(_('Or'), TAG_EVAL_TYPE_OR)
- ->setModern(true)
- ))->setColSpan(4)
-);
-
-$i = 0;
-foreach ($filter_tags as $tag) {
- $filter_tags_table->addRow([
- (new CTextBox('filter_tags['.$i.'][tag]', $tag['tag']))
- ->setAttribute('placeholder', _('tag'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CRadioButtonList('filter_tags['.$i.'][operator]', (int) $tag['operator']))
- ->addValue(_('Contains'), TAG_OPERATOR_LIKE)
- ->addValue(_('Equals'), TAG_OPERATOR_EQUAL)
- ->setModern(true),
- (new CTextBox('filter_tags['.$i.'][value]', $tag['value']))
- ->setAttribute('placeholder', _('value'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_tags['.$i.'][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ], 'form_row');
+if ($web_layout_mode == ZBX_LAYOUT_NORMAL) {
+ $filter = (new CTabFilter())
+ ->setId('monitoring_hosts_filter')
+ ->setOptions($data['tabfilter_options'])
+ ->addTemplate(new CPartial($data['filter_view'], $data['filter_defaults']));
- $i++;
-}
-$filter_tags_table->addRow(
- (new CCol(
- (new CButton('filter_tags_add', _('Add')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-add')
- ))->setColSpan(3)
-);
+ foreach ($data['filter_tabs'] as $tab) {
+ $tab['tab_view'] = $data['filter_view'];
+ $filter->addTemplatedTab($tab['filter_name'], $tab);
+ }
-$severities = [];
-foreach (range(TRIGGER_SEVERITY_NOT_CLASSIFIED, TRIGGER_SEVERITY_COUNT - 1) as $severity) {
- $severities[] = [
- 'name' => getSeverityName($severity),
- 'value' => $severity
- ];
+ // Set javascript options for tab filter initialization in monitoring.host.view.js.php file.
+ $data['filter_options'] = $filter->options;
+ $widget->addItem($filter);
}
-
-if ($web_layout_mode == ZBX_LAYOUT_NORMAL) {
- $widget->addItem((new CFilter((new CUrl('zabbix.php'))->setArgument('action', 'host.view')))
- ->setProfile('web.hostsmon.filter')
- ->setActiveTab($data['active_tab'])
- ->addFormItem((new CVar('action', 'host.view'))->removeId())
- ->addFilterTab(_('Filter'), [
- (new CFormList())
- ->addRow(_('Name'),
- (new CTextBox('filter_name', $data['filter']['name']))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- )
- ->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(_('IP'),
- (new CTextBox('filter_ip', $data['filter']['ip']))
- ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- )
- ->addRow(_('DNS'),
- (new CTextBox('filter_dns', $data['filter']['dns']))
- ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- )
- ->addRow(_('Port'),
- (new CTextBox('filter_port', $data['filter']['port']))
- ->setWidth(ZBX_TEXTAREA_INTERFACE_PORT_WIDTH)
- )
- ->addRow(_('Severity'),
- (new CSeverityCheckBoxList('filter_severities'))->setChecked($data['filter']['severities'])
- ),
- (new CFormList())
- ->addRow(_('Status'),
- (new CRadioButtonList('filter_status', (int) $data['filter']['status']))
- ->addValue(_('Any'), -1)
- ->addValue(_('Enabled'), HOST_STATUS_MONITORED)
- ->addValue(_('Disabled'), HOST_STATUS_NOT_MONITORED)
- ->setModern(true)
- )
- ->addRow(_('Tags'), $filter_tags_table)
- ->addRow(_('Show hosts in maintenance'), [
- (new CCheckBox('filter_maintenance_status'))
- ->setChecked($data['filter']['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON)
- ->setUncheckedValue(HOST_MAINTENANCE_STATUS_OFF),
- (new CDiv([
- (new CLabel(_('Show suppressed problems'), 'filter_show_suppressed'))
- ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
- (new CCheckBox('filter_show_suppressed'))
- ->setChecked($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
- ->setUncheckedValue(ZBX_PROBLEM_SUPPRESSED_FALSE)
- ->setEnabled($data['filter']['maintenance_status'] == HOST_MAINTENANCE_STATUS_ON),
- ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
- ])
- ])
- );
+else {
+ $data['filter_options'] = null;
}
-$widget->addItem(new CPartial('monitoring.host.view.html', array_intersect_key($data, array_flip([
- 'filter', 'sort', 'sortorder', 'view_curl', 'hosts', 'maintenances', 'paging'
-]))));
-
+$widget->addItem((new CForm())->setName('host_view')->addClass('is-loading'));
$widget->show();
+$this->includeJsFile('monitoring.host.view.js.php', $data);
(new CScriptTag('host_page.start();'))
->setOnDocumentReady()
diff --git a/ui/app/views/monitoring.problem.view.php b/ui/app/views/monitoring.problem.view.php
index 13c235c6b12..1f17d605e5c 100644
--- a/ui/app/views/monitoring.problem.view.php
+++ b/ui/app/views/monitoring.problem.view.php
@@ -65,25 +65,23 @@ switch ($data['filter']['show']) {
break;
case TRIGGERS_OPTION_ALL:
- $options['profileIdx'] = $data['profileIdx'];
- $options['profileIdx2'] = $data['profileIdx2'];
- $options['from'] = $data['from'];
- $options['to'] = $data['to'];
+ $options['profileIdx'] = $data['tabfilter_idx'];
+ $options['profileIdx2'] = 0;
+ $options['from'] = $data['filter']['from'];
+ $options['to'] = $data['filter']['to'];
break;
}
$screen = CScreenBuilder::getScreen($options);
if ($data['action'] === 'problem.view') {
- if ($data['filter']['show'] == TRIGGERS_OPTION_ALL) {
- $this->addJsFile('class.calendar.js');
- }
+ $this->addJsFile('class.calendar.js');
$this->addJsFile('gtlc.js');
$this->addJsFile('flickerfreescreen.js');
$this->addJsFile('multiselect.js');
$this->addJsFile('layout.mode.js');
-
- $this->includeJsFile('monitoring.problem.view.js.php');
+ $this->addJsFile('class.tabfilter.js');
+ $this->addJsFile('class.tabfilteritem.js');
$this->enableLayoutModes();
$web_layout_mode = $this->getLayoutMode();
@@ -92,267 +90,6 @@ if ($data['action'] === 'problem.view') {
uncheckTableRows('problem');
}
- $filter_column1 = (new CFormList())
- ->addRow(_('Show'),
- (new CRadioButtonList('filter_show', (int) $data['filter']['show']))
- ->addValue(_('Recent problems'), TRIGGERS_OPTION_RECENT_PROBLEM)
- ->addValue(_('Problems'), TRIGGERS_OPTION_IN_PROBLEM)
- ->addValue(_('History'), TRIGGERS_OPTION_ALL)
- ->setModern(true)
- )
- ->addRow((new CLabel(_('Host groups'), 'filter_groupids__ms')),
- (new CMultiSelect([
- 'name' => 'filter_groupids[]',
- 'object_name' => 'hostGroup',
- 'data' => $data['filter']['groups'],
- '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['filter']['hosts'],
- '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(_('Application'), [
- (new CTextBox('filter_application', $data['filter']['application']))
- ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH),
- (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
- (new CButton('filter_application_select', _('Select')))
- ->onClick('return PopUp("popup.generic", jQuery.extend('.
- json_encode([
- 'srctbl' => 'applications',
- 'srcfld1' => 'name',
- 'dstfrm' => 'zbx_filter',
- 'dstfld1' => 'filter_application',
- 'with_applications' => '1',
- 'real_hosts' => '1'
- ]).', getFirstMultiselectValue("filter_hostids_")), null, this);'
- )
- ->addClass(ZBX_STYLE_BTN_GREY)
- ])
- ->addRow((new CLabel(_('Triggers'), 'filter_triggerids__ms')),
- (new CMultiSelect([
- 'name' => 'filter_triggerids[]',
- 'object_name' => 'triggers',
- 'data' => $data['filter']['triggers'],
- 'popup' => [
- 'filter_preselect_fields' => [
- 'hosts' => 'filter_hostids_'
- ],
- 'parameters' => [
- 'srctbl' => 'triggers',
- 'srcfld1' => 'triggerid',
- 'dstfrm' => 'zbx_filter',
- 'dstfld1' => 'filter_triggerids_',
- 'monitored_hosts' => true,
- 'with_monitored_triggers' => true,
- 'noempty' => true
- ]
- ]
- ]))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- )
- ->addRow(_('Problem'),
- (new CTextBox('filter_name', $data['filter']['name']))->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- )
- ->addRow(_('Severity'),
- (new CSeverityCheckBoxList('filter_severities'))->setChecked($data['filter']['severities'])
- );
-
- $filter_age = (new CNumericBox('filter_age', $data['filter']['age'], 3, false, false, false))
- ->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH);
- if ($data['filter']['age_state'] == 0) {
- $filter_age->setAttribute('disabled', 'disabled');
- }
-
- $filter_column1
- ->addRow(_('Age less than'), [
- (new CCheckBox('filter_age_state'))
- ->setChecked($data['filter']['age_state'] == 1)
- ->onClick('javascript: jQuery("#filter_age").prop("disabled", !this.checked)'),
- (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
- $filter_age,
- (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
- _('days')
- ]);
-
- $filter_inventory = $data['filter']['inventory'];
- if (!$filter_inventory) {
- $filter_inventory = [['field' => '', 'value' => '']];
- }
-
- $filter_inventory_table = new CTable();
- $filter_inventory_table->setId('filter-inventory');
- $i = 0;
- foreach ($filter_inventory as $field) {
- $filter_inventory_table->addRow([
- new CComboBox('filter_inventory['.$i.'][field]', $field['field'], null, $data['filter']['inventories']),
- (new CTextBox('filter_inventory['.$i.'][value]', $field['value']))->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_inventory['.$i.'][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ], 'form_row');
-
- $i++;
- }
- $filter_inventory_table->addRow(
- (new CCol(
- (new CButton('filter_inventory_add', _('Add')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-add')
- ))->setColSpan(3)
- );
-
- $filter_tags = $data['filter']['tags'];
- if (!$filter_tags) {
- $filter_tags = [['tag' => '', 'value' => '', 'operator' => TAG_OPERATOR_LIKE]];
- }
-
- $filter_tags_table = new CTable();
- $filter_tags_table->setId('filter-tags');
-
- $filter_tags_table->addRow(
- (new CCol(
- (new CRadioButtonList('filter_evaltype', (int) $data['filter']['evaltype']))
- ->addValue(_('And/Or'), TAG_EVAL_TYPE_AND_OR)
- ->addValue(_('Or'), TAG_EVAL_TYPE_OR)
- ->setModern(true)
- ))->setColSpan(4)
- );
-
- $i = 0;
- foreach ($filter_tags as $tag) {
- $filter_tags_table->addRow([
- (new CTextBox('filter_tags['.$i.'][tag]', $tag['tag']))
- ->setAttribute('placeholder', _('tag'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CRadioButtonList('filter_tags['.$i.'][operator]', (int) $tag['operator']))
- ->addValue(_('Contains'), TAG_OPERATOR_LIKE)
- ->addValue(_('Equals'), TAG_OPERATOR_EQUAL)
- ->setModern(true),
- (new CTextBox('filter_tags['.$i.'][value]', $tag['value']))
- ->setAttribute('placeholder', _('value'))
- ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH),
- (new CCol(
- (new CButton('filter_tags['.$i.'][remove]', _('Remove')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-remove')
- ))->addClass(ZBX_STYLE_NOWRAP)
- ], 'form_row');
-
- $i++;
- }
- $filter_tags_table->addRow(
- (new CCol(
- (new CButton('filter_tags_add', _('Add')))
- ->addClass(ZBX_STYLE_BTN_LINK)
- ->addClass('element-table-add')
- ))->setColSpan(3)
- );
-
- $tag_format_line = (new CHorList())
- ->addItem((new CRadioButtonList('filter_show_tags', (int) $data['filter']['show_tags']))
- ->addValue(_('None'), PROBLEMS_SHOW_TAGS_NONE)
- ->addValue(PROBLEMS_SHOW_TAGS_1, PROBLEMS_SHOW_TAGS_1)
- ->addValue(PROBLEMS_SHOW_TAGS_2, PROBLEMS_SHOW_TAGS_2)
- ->addValue(PROBLEMS_SHOW_TAGS_3, PROBLEMS_SHOW_TAGS_3)
- ->setModern(true)
- )
- ->addItem((new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN))
- ->addItem(new CLabel(_('Tag name')))
- ->addItem((new CRadioButtonList('filter_tag_name_format', (int) $data['filter']['tag_name_format']))
- ->addValue(_('Full'), PROBLEMS_TAG_NAME_FULL)
- ->addValue(_('Shortened'), PROBLEMS_TAG_NAME_SHORTENED)
- ->addValue(_('None'), PROBLEMS_TAG_NAME_NONE)
- ->setModern(true)
- ->setEnabled((int) $data['filter']['show_tags'] !== PROBLEMS_SHOW_TAGS_NONE)
- );
-
- $filter_column2 = (new CFormList())
- ->addRow(_('Host inventory'), $filter_inventory_table)
- ->addRow(_('Tags'), $filter_tags_table)
- ->addRow(_('Show tags'), $tag_format_line)
- ->addRow(_('Tag display priority'),
- (new CTextBox('filter_tag_priority', $data['filter']['tag_priority']))
- ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)
- ->setAttribute('placeholder', _('comma-separated list'))
- ->setEnabled((int) $data['filter']['show_tags'] !== PROBLEMS_SHOW_TAGS_NONE)
- )
- ->addRow(_('Show operational data'), [
- (new CRadioButtonList('filter_show_opdata', (int) $data['filter']['show_opdata']))
- ->addValue(_('None'), OPERATIONAL_DATA_SHOW_NONE)
- ->addValue(_('Separately'), OPERATIONAL_DATA_SHOW_SEPARATELY)
- ->addValue(_('With problem name'), OPERATIONAL_DATA_SHOW_WITH_PROBLEM)
- ->setModern(true)
- ->setEnabled($data['filter']['compact_view'] == 0)
- ])
- ->addRow(_('Show suppressed problems'), [
- (new CCheckBox('filter_show_suppressed'))
- ->setChecked($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE),
- (new CDiv([
- (new CLabel(_('Show unacknowledged only'), 'filter_unacknowledged'))
- ->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
- (new CCheckBox('filter_unacknowledged'))
- ->setChecked($data['filter']['unacknowledged'] == 1)
- ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
- ])
- ->addRow(_('Compact view'), [
- (new CCheckBox('filter_compact_view'))->setChecked($data['filter']['compact_view'] == 1),
- (new CDiv([
- (new CLabel(_('Show timeline'), 'filter_show_timeline'))->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
- (new CCheckBox('filter_show_timeline'))
- ->setChecked($data['filter']['show_timeline'] == 1)
- ->setEnabled($data['filter']['compact_view'] == 0),
- ]))->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
- ])
- ->addRow(_('Show details'), [
- (new CCheckBox('filter_details'))
- ->setChecked($data['filter']['details'] == 1)
- ->setEnabled($data['filter']['compact_view'] == 0),
- (new CDiv([
- (new CLabel(_('Highlight whole row'), 'filter_highlight_row'))->addClass(ZBX_STYLE_SECOND_COLUMN_LABEL),
- (new CCheckBox('filter_highlight_row'))
- ->setChecked($data['filter']['highlight_row'] == 1)
- ->setEnabled($data['filter']['compact_view'] == 1)
- ]))
- ->addClass(ZBX_STYLE_FILTER_HIGHLIGHT_ROW_CB)
- ->addClass(ZBX_STYLE_TABLE_FORMS_SECOND_COLUMN)
- ]);
-
- $filter = (new CFilter((new CUrl('zabbix.php'))->setArgument('action', 'problem.view')))
- ->setProfile($data['profileIdx'])
- ->setActiveTab($data['active_tab'])
- ->addFormItem((new CVar('action', 'problem.view'))->removeId());
-
- if ($data['filter']['show'] == TRIGGERS_OPTION_ALL) {
- $filter->addTimeSelector($screen->timeline['from'], $screen->timeline['to']);
- }
-
- $filter->addFilterTab(_('Filter'), [$filter_column1, $filter_column2]);
-
$widget = (new CWidget())
->setTitle(_('Problems'))
->setWebLayoutMode($web_layout_mode)
@@ -360,14 +97,35 @@ if ($data['action'] === 'problem.view') {
(new CTag('nav', true,
(new CList())
->addItem(new CRedirectButton(_('Export to CSV'),
- (new CUrl('zabbix.php'))->setArgument('action', 'problem.view.csv')
+ (new CUrl())->setArgument('action', 'problem.view.csv')
))
->addItem(get_icon('kioskmode', ['mode' => $web_layout_mode]))
))->setAttribute('aria-label', _('Content controls'))
);
if ($web_layout_mode == ZBX_LAYOUT_NORMAL) {
+ $defaults = [
+ 'tags' => [['tag' => '', 'value' => '', 'operator' => TAG_OPERATOR_LIKE]],
+ 'inventory' => [['field' => 'type', 'value' => '']]
+ ];
+ $filter = (new CTabFilter())
+ ->setId('monitoring_problem_filter')
+ ->setIdx($data['tabfilter_idx'])
+ ->setSelected((int) $data['tab_selected'])
+ ->setExpanded((bool) $data['tab_expanded'])
+ ->addTemplate(new CPartial($data['filter_view'], $data['filter_defaults'] + $defaults));
+
+ foreach ($data['filter_tabs'] as $tab) {
+ $tab['tab_view'] = $data['filter_view'];
+ $filter->addTemplatedTab($tab['filter_name'], $tab);
+ }
+
+ $filter->addTimeselector($data['timerange']);
+ // Set javascript options for tab filter initialization in monitoring.problem.view.js.php file.
+ $data['filter_options'] = $filter->options;
$widget->addItem($filter);
+
+ $this->includeJsFile('monitoring.problem.view.js.php', $data);
}
$widget
@@ -376,20 +134,6 @@ if ($data['action'] === 'problem.view') {
// Activate blinking.
(new CScriptTag('jqBlink.blink();'))->show();
-
- if ($data['filter']['show'] == TRIGGERS_OPTION_ALL) {
- $objData = [
- 'id' => 'timeline_1',
- 'loadSBox' => 0,
- 'loadImage' => 0,
- 'dynamic' => 0
- ];
-
- (new CScriptTag(
- 'timeControl.addObject("scroll_events_id", '.zbx_jsvalue($screen->timeline).', '.zbx_jsvalue($objData).');'.
- 'timeControl.processObjects();'
- ))->show();
- }
}
else {
echo $screen->get();
diff --git a/ui/app/views/monitoring.widget.problemhosts.view.php b/ui/app/views/monitoring.widget.problemhosts.view.php
index cac7cc7994d..8cb2600727f 100644
--- a/ui/app/views/monitoring.widget.problemhosts.view.php
+++ b/ui/app/views/monitoring.widget.problemhosts.view.php
@@ -37,23 +37,20 @@ $table = (new CTableInfo())
$url_group = (new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_set', 1)
- ->setArgument('filter_show', TRIGGERS_OPTION_RECENT_PROBLEM)
- ->setArgument('filter_groupids', null)
- ->setArgument('filter_hostids', $data['filter']['hostids'])
- ->setArgument('filter_name', $data['filter']['problem'])
- ->setArgument('filter_show_suppressed', ($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
+ ->setArgument('filter_name', '')
+ ->setArgument('show', TRIGGERS_OPTION_RECENT_PROBLEM)
+ ->setArgument('hostids', $data['filter']['hostids'])
+ ->setArgument('name', $data['filter']['problem'])
+ ->setArgument('show_suppressed', ($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
? ZBX_PROBLEM_SUPPRESSED_TRUE
: null
);
$url_host = (new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_set', 1)
- ->setArgument('filter_show', TRIGGERS_OPTION_RECENT_PROBLEM)
- ->setArgument('filter_groupids', null)
- ->setArgument('filter_hostids', null)
- ->setArgument('filter_name', $data['filter']['problem'])
- ->setArgument('filter_show_suppressed', ($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
+ ->setArgument('filter_name', '')
+ ->setArgument('show', TRIGGERS_OPTION_RECENT_PROBLEM)
+ ->setArgument('name', $data['filter']['problem'])
+ ->setArgument('show_suppressed', ($data['filter']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
? ZBX_PROBLEM_SUPPRESSED_TRUE
: null
);
@@ -67,8 +64,8 @@ foreach ($data['groups'] as $group) {
continue;
}
- $url_group->setArgument('filter_groupids', [$group['groupid']]);
- $url_host->setArgument('filter_groupids', [$group['groupid']]);
+ $url_group->setArgument('groupids', [$group['groupid']]);
+ $url_host->setArgument('groupids', [$group['groupid']]);
$group_row = [new CLink($group['name'], $url_group->getUrl())];
diff --git a/ui/app/views/monitoring.widget.problemsbysv.view.php b/ui/app/views/monitoring.widget.problemsbysv.view.php
index 9611ade1653..74ace70b452 100644
--- a/ui/app/views/monitoring.widget.problemsbysv.view.php
+++ b/ui/app/views/monitoring.widget.problemsbysv.view.php
@@ -51,14 +51,13 @@ else {
$groupurl = (new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_set', 1)
- ->setArgument('filter_show', TRIGGERS_OPTION_RECENT_PROBLEM)
- ->setArgument('filter_groupids', null)
- ->setArgument('filter_hostids',
+ ->setArgument('filter_name', '')
+ ->setArgument('show', TRIGGERS_OPTION_RECENT_PROBLEM)
+ ->setArgument('hostids',
array_key_exists('hostids', $data['filter']) ? $data['filter']['hostids'] : null
)
- ->setArgument('filter_name', array_key_exists('problem', $data['filter']) ? $data['filter']['problem'] : null)
- ->setArgument('filter_show_suppressed',
+ ->setArgument('name', array_key_exists('problem', $data['filter']) ? $data['filter']['problem'] : null)
+ ->setArgument('show_suppressed',
(array_key_exists('show_suppressed', $data['filter']) && $data['filter']['show_suppressed'] == 1) ? 1 : null
);
diff --git a/ui/app/views/popup.tabfilter.edit.php b/ui/app/views/popup.tabfilter.edit.php
new file mode 100644
index 00000000000..ea94348545c
--- /dev/null
+++ b/ui/app/views/popup.tabfilter.edit.php
@@ -0,0 +1,93 @@
+<?php
+/*
+** Zabbix
+** Copyright (C) 2001-2020 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 CView $this
+ */
+
+$form_list = (new CFormList())
+ ->addVar('idx', $data['idx'])
+ ->addVar('idx2', $data['idx2'])
+ ->addVar('create', $data['create'])
+ ->addVar('support_custom_time', $data['support_custom_time'])
+ ->addRow((new CLabel(_('Name'), 'filter_name'))->setAsteriskMark(),
+ (new CTextBox('filter_name', $data['filter_name']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
+ )
+ ->addRow(_('Show number of records'),
+ (new CCheckBox('filter_show_counter', 1))->setChecked($data['filter_show_counter'])
+ );
+
+if ($data['support_custom_time']) {
+ $form_list
+ ->addRow(_('Set custom time period'),
+ (new CCheckBox('filter_custom_time', 1))
+ ->setChecked($data['filter_custom_time'])
+ )
+ ->addRow(new CLabel(_('From'), 'tabfilter_from'),
+ (new CDateSelector('tabfilter_from', $data['tabfilter_from']))
+ ->setDateFormat(ZBX_DATE_TIME)
+ ->setEnabled((bool) $data['filter_custom_time'])
+ )
+ ->addRow(new CLabel(_('To'), 'tabfilter_to'),
+ (new CDateSelector('tabfilter_to', $data['tabfilter_to']))
+ ->setDateFormat(ZBX_DATE_TIME)
+ ->setEnabled((bool) $data['filter_custom_time'])
+ );
+}
+
+$form = (new CForm())
+ ->cleanItems()
+ ->setName('tabfilter_form')
+ ->addVar('action', 'popup.tabfilter.update')
+ ->addItem([
+ $form_list,
+ (new CInput('submit', 'submit'))->addStyle('display: none;')
+ ]);
+
+$output = [
+ 'header' => $data['title'],
+ 'script_inline' => $this->readJsFile('popup.tabfilter.edit.js.php'),
+ 'body' => (new CDiv([$data['errors'], $form]))->toString(),
+ 'buttons' => [
+ [
+ 'title' => _('Delete'),
+ 'isSubmit' => true,
+ 'keepOpen' => true,
+ 'enabled' => !$data['create'],
+ 'class' => 'float-left',
+ 'confirmation' => _('Are you sure you want to delete this filter?'),
+ 'action' => 'return tabFilterDelete(overlay)'
+ ],
+ [
+ 'title' => _('Save'),
+ 'keepOpen' => true,
+ 'isSubmit' => true,
+ 'action' => 'return tabFilterUpdate(overlay)'
+ ]
+ ]
+];
+
+if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) {
+ CProfiler::getInstance()->stop();
+ $output['debug'] = CProfiler::getInstance()->make()->toString();
+}
+
+echo json_encode($output);
diff --git a/ui/app/views/popup.triggerexpr.php b/ui/app/views/popup.triggerexpr.php
index 674e952eaae..91f445070ef 100644
--- a/ui/app/views/popup.triggerexpr.php
+++ b/ui/app/views/popup.triggerexpr.php
@@ -139,9 +139,16 @@ if (array_key_exists('params', $data['functions'][$data['selectedFunction']])) {
elseif (in_array($param_name, ['shift'])) {
$param_type_element = _('Time');
}
+ elseif (in_array($param_name, ['period_shift'])) {
+ $param_type_element = _('Period');
+ }
$param_field = (new CTextBox('params['.$param_name.']', $param_value))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH);
+ if ($param_name === 'period_shift') {
+ $param_field->setAttribute('placeholder', 'now/h');
+ }
+
$expression_form_list->addRow($label, [
$param_field,
(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
diff --git a/ui/app/views/popup.triggerwizard.php b/ui/app/views/popup.triggerwizard.php
index abcd67251db..de5a0bfe3ac 100644
--- a/ui/app/views/popup.triggerwizard.php
+++ b/ui/app/views/popup.triggerwizard.php
@@ -83,6 +83,12 @@ $form->addItem(
->setAriaRequired()
->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
)
+ ->addRow(
+ new CLabel(_('Event name'), 'event_name'),
+ (new CTextAreaFlexible('event_name', $options['event_name']))
+ ->setMaxlength(DB::getFieldLength('triggers', 'event_name'))
+ ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
+ )
->addRow((new CLabel(_('Item'), 'itemid'))->setAsteriskMark(), $ms_itemid)
->addRow(_('Severity'), new CSeverity([
'name' => 'priority',
diff --git a/ui/app/views/search.php b/ui/app/views/search.php
index 394b04539f9..a0decb08f49 100644
--- a/ui/app/views/search.php
+++ b/ui/app/views/search.php
@@ -123,8 +123,8 @@ foreach ($data['hosts'] as $hostid => $host) {
new CLink(_('Problems'),
(new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_hostids[]', $hostid)
- ->setArgument('filter_set', '1')
+ ->setArgument('filter_name', '')
+ ->setArgument('hostids', [$hostid])
),
new CLink(_('Graphs'),
(new CUrl('zabbix.php'))
@@ -208,8 +208,8 @@ foreach ($data['groups'] as $groupid => $group) {
new CLink(_('Problems'),
(new CUrl('zabbix.php'))
->setArgument('action', 'problem.view')
- ->setArgument('filter_groupids[]', $groupid)
- ->setArgument('filter_set', '1')
+ ->setArgument('filter_name', '')
+ ->setArgument('groupids', [$groupid])
),
new CLink(_('Web'),
(new CUrl('zabbix.php'))