diff options
author | Janis Freibergs <janis.freibergs@zabbix.com> | 2021-11-25 15:25:31 +0300 |
---|---|---|
committer | Janis Freibergs <janis.freibergs@zabbix.com> | 2021-11-25 15:25:31 +0300 |
commit | 86dd93671922df992b9745aa9eeb45ecb2dffc1b (patch) | |
tree | e2606885dec5eaba22a94c6c0528b4bd8eac2808 | |
parent | 882f0efe3fbdd4bc81d55702c897b8687285b18d (diff) |
..F....... [ZBXNEXT-6999] added temporary commit
39 files changed, 1218 insertions, 54 deletions
diff --git a/create/src/schema.tmpl b/create/src/schema.tmpl index 56f9fd0a1e4..afb4688a90c 100644 --- a/create/src/schema.tmpl +++ b/create/src/schema.tmpl @@ -1929,6 +1929,6 @@ TABLE|dbversion|dbversionid| FIELD |dbversionid |t_id | |NOT NULL |0 FIELD |mandatory |t_integer |'0' |NOT NULL | FIELD |optional |t_integer |'0' |NOT NULL | -ROW |1 |5050127 |5050127 +ROW |1 |5050128 |5050128 diff --git a/sass/stylesheets/sass/components/_menu-main.scss b/sass/stylesheets/sass/components/_menu-main.scss index 5296387e8ac..ab3451a1005 100644 --- a/sass/stylesheets/sass/components/_menu-main.scss +++ b/sass/stylesheets/sass/components/_menu-main.scss @@ -7,6 +7,7 @@ $menu-main-icons: ( dashboard: -540px -664px, problems: -540px -688px, monitoring: -540px -712px, + services: -42px -832px, inventory: -540px -736px, reports: -540px -760px, configuration: -540px -784px, @@ -30,6 +31,7 @@ $menu-main-icons: ( // .icon-dashboard // .icon-problems // .icon-monitoring +// .icon-services // .icon-inventory // .icon-reports // .icon-configuration diff --git a/src/libs/zbxdbupgrade/dbupgrade_5050.c b/src/libs/zbxdbupgrade/dbupgrade_5050.c index 3cd1bec6246..f2eea80a5cc 100644 --- a/src/libs/zbxdbupgrade/dbupgrade_5050.c +++ b/src/libs/zbxdbupgrade/dbupgrade_5050.c @@ -1329,6 +1329,15 @@ static int DBpatch_5050127(void) return DBadd_field("services", &field); } +static int DBpatch_5050128(void) +{ + if (ZBX_DB_OK > DBexecute("update role_rule set name='ui.services.services' where name='ui.monitoring.services'")) + return FAIL; + + return SUCCEED; +} + + #endif DBPATCH_START(5050) @@ -1450,5 +1459,6 @@ DBPATCH_ADD(5050124, 0, 1) DBPATCH_ADD(5050125, 0, 1) DBPATCH_ADD(5050126, 0, 1) DBPATCH_ADD(5050127, 0, 1) +DBPATCH_ADD(5050128, 0, 1) DBPATCH_END() diff --git a/ui/app/controllers/CControllerPopupMassupdateService.php b/ui/app/controllers/CControllerPopupMassupdateService.php index dc76e61ba07..d1ec953f963 100644 --- a/ui/app/controllers/CControllerPopupMassupdateService.php +++ b/ui/app/controllers/CControllerPopupMassupdateService.php @@ -50,7 +50,7 @@ class CControllerPopupMassupdateService extends CController { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerPopupServiceEdit.php b/ui/app/controllers/CControllerPopupServiceEdit.php index 96d1ec14120..d7c11cfdf47 100644 --- a/ui/app/controllers/CControllerPopupServiceEdit.php +++ b/ui/app/controllers/CControllerPopupServiceEdit.php @@ -48,7 +48,7 @@ class CControllerPopupServiceEdit extends CController { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php b/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php index f457abd02a3..e501f523f92 100644 --- a/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php +++ b/ui/app/controllers/CControllerPopupServiceStatusRuleEdit.php @@ -47,7 +47,7 @@ class CControllerPopupServiceStatusRuleEdit extends CController { } protected function checkPermissions(): bool { - return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES); + return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES); } protected function doAction(): void { diff --git a/ui/app/controllers/CControllerPopupServiceTimeEdit.php b/ui/app/controllers/CControllerPopupServiceTimeEdit.php index 515c6fc76da..b31be8009e6 100644 --- a/ui/app/controllers/CControllerPopupServiceTimeEdit.php +++ b/ui/app/controllers/CControllerPopupServiceTimeEdit.php @@ -54,7 +54,7 @@ class CControllerPopupServiceTimeEdit extends CController { } protected function checkPermissions(): bool { - return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES); + return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES); } protected function doAction(): void { diff --git a/ui/app/controllers/CControllerServiceCreate.php b/ui/app/controllers/CControllerServiceCreate.php index 53f59fcfbf3..bfb0f162c2c 100644 --- a/ui/app/controllers/CControllerServiceCreate.php +++ b/ui/app/controllers/CControllerServiceCreate.php @@ -103,7 +103,7 @@ class CControllerServiceCreate extends CController { } protected function checkPermissions(): bool { - return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES); + return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES); } /** diff --git a/ui/app/controllers/CControllerServiceDelete.php b/ui/app/controllers/CControllerServiceDelete.php index 653845a69ff..b314fd0df01 100644 --- a/ui/app/controllers/CControllerServiceDelete.php +++ b/ui/app/controllers/CControllerServiceDelete.php @@ -40,7 +40,7 @@ class CControllerServiceDelete extends CController { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerServiceList.php b/ui/app/controllers/CControllerServiceList.php index 73ab4e3004d..71abaed622b 100644 --- a/ui/app/controllers/CControllerServiceList.php +++ b/ui/app/controllers/CControllerServiceList.php @@ -50,7 +50,7 @@ class CControllerServiceList extends CControllerServiceListGeneral { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerServiceListEdit.php b/ui/app/controllers/CControllerServiceListEdit.php index eb224588d33..c815c9fc1c1 100755 --- a/ui/app/controllers/CControllerServiceListEdit.php +++ b/ui/app/controllers/CControllerServiceListEdit.php @@ -54,7 +54,7 @@ class CControllerServiceListEdit extends CControllerServiceListGeneral { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES) || !$this->canEdit()) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES) || !$this->canEdit()) { return false; } diff --git a/ui/app/controllers/CControllerServiceListEditRefresh.php b/ui/app/controllers/CControllerServiceListEditRefresh.php index 94805b21059..656ec8013d1 100755 --- a/ui/app/controllers/CControllerServiceListEditRefresh.php +++ b/ui/app/controllers/CControllerServiceListEditRefresh.php @@ -54,7 +54,7 @@ class CControllerServiceListEditRefresh extends CControllerServiceListGeneral { } protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES) || !$this->canEdit()) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES) || !$this->canEdit()) { return false; } diff --git a/ui/app/controllers/CControllerServiceListRefresh.php b/ui/app/controllers/CControllerServiceListRefresh.php index d8d2a291307..1a9b875c5ff 100644 --- a/ui/app/controllers/CControllerServiceListRefresh.php +++ b/ui/app/controllers/CControllerServiceListRefresh.php @@ -51,7 +51,7 @@ class CControllerServiceListRefresh extends CControllerServiceListGeneral { } protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerServiceStatusRuleValidate.php b/ui/app/controllers/CControllerServiceStatusRuleValidate.php index 3b20b8753a7..99b368f501f 100644 --- a/ui/app/controllers/CControllerServiceStatusRuleValidate.php +++ b/ui/app/controllers/CControllerServiceStatusRuleValidate.php @@ -84,7 +84,7 @@ class CControllerServiceStatusRuleValidate extends CController { } protected function checkPermissions(): bool { - return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES); + return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES); } protected function doAction(): void { diff --git a/ui/app/controllers/CControllerServiceTimeValidate.php b/ui/app/controllers/CControllerServiceTimeValidate.php index 02d4c446ec9..3064f9c9a2f 100644 --- a/ui/app/controllers/CControllerServiceTimeValidate.php +++ b/ui/app/controllers/CControllerServiceTimeValidate.php @@ -109,7 +109,7 @@ class CControllerServiceTimeValidate extends CController { } protected function checkPermissions(): bool { - return $this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES); + return $this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES); } protected function doAction(): void { diff --git a/ui/app/controllers/CControllerServiceUpdate.php b/ui/app/controllers/CControllerServiceUpdate.php index 41988240ad7..af2ab5f86e1 100644 --- a/ui/app/controllers/CControllerServiceUpdate.php +++ b/ui/app/controllers/CControllerServiceUpdate.php @@ -107,7 +107,7 @@ class CControllerServiceUpdate extends CController { * @throws APIException */ protected function checkPermissions(): bool { - if (!$this->checkAccess(CRoleHelper::UI_MONITORING_SERVICES)) { + if (!$this->checkAccess(CRoleHelper::UI_SERVICES_SERVICES)) { return false; } diff --git a/ui/app/controllers/CControllerSlaList.php b/ui/app/controllers/CControllerSlaList.php new file mode 100644 index 00000000000..ed3c4e2ed3f --- /dev/null +++ b/ui/app/controllers/CControllerSlaList.php @@ -0,0 +1,185 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +class CControllerSlaList extends CController { + + protected function init(): void { + $this->disableSIDValidation(); + } + + protected function checkInput(): bool { + $fields = [ + 'filter_name' => 'string', + 'filter_status' => 'in '.implode(',', [ + CSlaHelper::SLA_STATUS_ANY, + CSlaHelper::SLA_STATUS_ENABLED, + CSlaHelper::SLA_STATUS_DISABLED + ]), + 'filter_evaltype' => 'in '.TAG_EVAL_TYPE_AND_OR.','.TAG_EVAL_TYPE_OR, + 'filter_tags' => 'array', + 'filter_set' => 'in 1', + 'sort' => 'in '.implode(',', [ + 'name', + 'slo', + 'effective_date', + 'status' + ]), + 'sortorder' => 'in '.implode(',', [ZBX_SORT_UP, ZBX_SORT_DOWN]), + 'page' => 'ge 1' + ]; + + $ret = $this->validateInput($fields); + + if (!$ret) { + $this->setResponse(new CControllerResponseFatal()); + } + + return $ret; + } + + /** + * @throws APIException + */ + protected function checkPermissions(): bool { + return $this->checkAccess(CRoleHelper::UI_SERVICES_SLA); + } + + /** + * @throws Exception + */ + protected function doAction(): void { + $filter = [ + 'name' => $this->getInput('filter_name', ''), + 'status' => $this->getInput('filter_status', CSlaHelper::SLA_STATUS_ANY), + 'evaltype' => $this->getInput('filter_evaltype', TAG_EVAL_TYPE_AND_OR), + 'tags' => [], + 'filter_set' => $this->hasInput('filter_set') + ]; + + foreach ($this->getInput('filter_tags', []) as $tag) { + if (!array_key_exists('tag', $tag) || !array_key_exists('value', $tag) + || ($tag['tag'] === '' && $tag['value'] === '')) { + continue; + } + + $filter['tags'][] = $tag; + } + + $paging_curl = (new CUrl('zabbix.php')) + ->setArgument('action', 'sla.list'); + + $reset_curl = clone $paging_curl; + + if ($filter['filter_set']) { + $paging_curl + ->setArgument('filter_name', $filter['name']) + ->setArgument('filter_status', $filter['status']) + ->setArgument('filter_evaltype', $filter['evaltype']) + ->setArgument('filter_tags', $filter['tags']) + ->setArgument('filter_set', 1); + } + + $page_num = $this->getInput('page', 1); + $per_page = CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT); + $sort_field = $this->getInput('sort', CProfile::get('sla.list.sort', 'name')); + $sort_order = $this->getInput('sortorder', CProfile::get('sla.list.sortorder', ZBX_SORT_UP)); + + $edit_mode_curl = (clone $paging_curl) + ->setArgument('action', 'service.list.edit') + ->setArgument('page', $page_num); + + $data = [ + 'can_edit' => CWebUser::checkAccess(CRoleHelper::ACTIONS_MANAGE_SLA), + 'filter' => $filter, + 'is_filtered' => $filter['filter_set'], + 'active_tab' => CProfile::get('web.sla.filter.active', 1), + 'refresh_interval' => CWebUser::getRefresh() * 1000, + 'reset_curl' => $reset_curl, + 'filter_url' => $paging_curl->getUrl(), + 'max_in_table' => CSettingsHelper::get(CSettingsHelper::MAX_IN_TABLE), + 'sort' => $sort_field, + 'sortorder' => $sort_order, + 'edit_mode_url' => $edit_mode_curl->getUrl(), + 'refresh_url' => (clone $paging_curl) + ->setArgument('action', 'sla.list.refresh') + ->getUrl(), + 'user' => [ + 'debug_mode' => $this->getDebugMode() + ] + ]; + + $options = [ + 'output' => [], + 'search' => ($filter['name'] === '') + ? null + : ['name' => $filter['name']], + 'filter' => [ + 'status' => $filter['status'] + ], + 'tags' => $filter['tags'], + 'evaltype' => $filter['evaltype'], + 'sortfield' => [$sort_field], + 'sortorder' => $sort_order, + 'preservekeys' => true + ]; + + if (in_array($filter['status'], [CSlaHelper::SLA_STATUS_ENABLED, CSlaHelper::SLA_STATUS_DISABLED])) { + $options['filter']['status'] = $filter['status']; + } + + $x = 120; + $records = []; + + while ($x-- > 0) { + $records[$x] = [ + 'name' => 'My SLA-'.$x, + 'period' => mt_rand(0, 4), + 'slo' => 99.9999, + 'effective_date' => strtotime('+'.mt_rand(0, 365).' days'), + 'timezone' => array_rand(['UTC' => 1, 'Europe/Riga' => 1, 'Europe/Dublin']), + 'schedule_mode' => mt_rand(0, 1), + 'status' => mt_rand(0, 1), + 'description' => 'Description of SLA '.$x + ]; + } + + //$db_slaids = array_keys(API::Sla()->get($options)); + $db_slaids = array_keys($records); + + CPagerHelper::savePage('sla.list', $page_num); + $data['paging'] = CPagerHelper::paginate($page_num, $db_slaids, $sort_order, $paging_curl); + + $options = [ + 'output' => [], + 'selectTags' => ['tag', 'value'], + 'slaids' => $db_slaids, + 'limit' => $per_page, + 'offset' => $page_num * $per_page + ]; + + //$data['records'] = API::Sla()->get($options); + $data['records'] = $records; + + $response = new CControllerResponseData($data); + $response->setTitle(_('SLA')); + $this->setResponse($response); + } +} diff --git a/ui/app/controllers/CControllerUserroleCreate.php b/ui/app/controllers/CControllerUserroleCreate.php index db948a52a1e..d9b95f1df61 100644 --- a/ui/app/controllers/CControllerUserroleCreate.php +++ b/ui/app/controllers/CControllerUserroleCreate.php @@ -38,7 +38,10 @@ class CControllerUserroleCreate extends CControllerUserroleEditGeneral { 'ui_monitoring_latest_data' => 'in 0,1', 'ui_monitoring_maps' => 'in 0,1', 'ui_monitoring_discovery' => 'in 0,1', - 'ui_monitoring_services' => 'in 0,1', + 'ui_services_services' => 'in 0,1', + 'ui_services_actions' => 'in 0,1', + 'ui_services_sla' => 'in 0,1', + 'ui_services_sla_report' => 'in 0,1', 'ui_inventory_overview' => 'in 0,1', 'ui_inventory_hosts' => 'in 0,1', 'ui_reports_system_info' => 'in 0,1', @@ -74,6 +77,7 @@ class CControllerUserroleCreate extends CControllerUserroleEditGeneral { 'actions_execute_scripts' => 'in 0,1', 'actions_manage_api_tokens' => 'in 0,1', 'actions_manage_scheduled_reports' => 'in 0,1', + 'actions_manage_sla' => 'in 0,1', 'modules' => 'array', 'api_mode' => 'in '.implode(',', [ZBX_ROLE_RULE_API_MODE_DENY, ZBX_ROLE_RULE_API_MODE_ALLOW]), 'api_methods' => 'array', diff --git a/ui/app/controllers/CControllerUserroleEdit.php b/ui/app/controllers/CControllerUserroleEdit.php index bd76cbc2c7c..d578545c670 100644 --- a/ui/app/controllers/CControllerUserroleEdit.php +++ b/ui/app/controllers/CControllerUserroleEdit.php @@ -41,7 +41,10 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral { 'ui_monitoring_latest_data' => 'in 0,1', 'ui_monitoring_maps' => 'in 0,1', 'ui_monitoring_discovery' => 'in 0,1', - 'ui_monitoring_services' => 'in 0,1', + 'ui_services_services' => 'in 0,1', + 'ui_services_actions' => 'in 0,1', + 'ui_services_sla' => 'in 0,1', + 'ui_services_sla_report' => 'in 0,1', 'ui_inventory_overview' => 'in 0,1', 'ui_inventory_hosts' => 'in 0,1', 'ui_reports_system_info' => 'in 0,1', @@ -77,6 +80,7 @@ class CControllerUserroleEdit extends CControllerUserroleEditGeneral { 'actions_execute_scripts' => 'in 0,1', 'actions_manage_api_tokens' => 'in 0,1', 'actions_manage_scheduled_reports' => 'in 0,1', + 'actions_manage_sla' => 'in 0,1', 'ui_default_access' => 'in 0,1', 'modules_default_access' => 'in 0,1', 'actions_default_access' => 'in 0,1', diff --git a/ui/app/controllers/CControllerUserroleUpdate.php b/ui/app/controllers/CControllerUserroleUpdate.php index e2a97d7b66c..997f35e128e 100644 --- a/ui/app/controllers/CControllerUserroleUpdate.php +++ b/ui/app/controllers/CControllerUserroleUpdate.php @@ -37,7 +37,10 @@ class CControllerUserroleUpdate extends CControllerUserroleEditGeneral { 'ui_monitoring_latest_data' => 'in 0,1', 'ui_monitoring_maps' => 'in 0,1', 'ui_monitoring_discovery' => 'in 0,1', - 'ui_monitoring_services' => 'in 0,1', + 'ui_services_services' => 'in 0,1', + 'ui_services_actions' => 'in 0,1', + 'ui_services_sla' => 'in 0,1', + 'ui_services_sla_report' => 'in 0,1', 'ui_inventory_overview' => 'in 0,1', 'ui_inventory_hosts' => 'in 0,1', 'ui_reports_system_info' => 'in 0,1', @@ -73,6 +76,7 @@ class CControllerUserroleUpdate extends CControllerUserroleEditGeneral { 'actions_execute_scripts' => 'in 0,1', 'actions_manage_api_tokens' => 'in 0,1', 'actions_manage_scheduled_reports' => 'in 0,1', + 'actions_manage_sla' => 'in 0,1', 'ui_default_access' => 'in 0,1', 'modules_default_access' => 'in 0,1', 'actions_default_access' => 'in 0,1', diff --git a/ui/app/partials/monitoring.service.list.edit.php b/ui/app/partials/services.service.list.edit.php index c8a1b4eabbc..c8a1b4eabbc 100644 --- a/ui/app/partials/monitoring.service.list.edit.php +++ b/ui/app/partials/services.service.list.edit.php diff --git a/ui/app/partials/monitoring.service.list.php b/ui/app/partials/services.service.list.php index 6c22fbbc977..6c22fbbc977 100644 --- a/ui/app/partials/monitoring.service.list.php +++ b/ui/app/partials/services.service.list.php diff --git a/ui/app/partials/services.sla.list.php b/ui/app/partials/services.sla.list.php new file mode 100644 index 00000000000..1ebf07ef0dc --- /dev/null +++ b/ui/app/partials/services.sla.list.php @@ -0,0 +1,97 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * @var CPartial $this + */ + +$form = (new CForm()) + ->setId('sla-list') + ->setName('sla_list'); + +$header = [ + make_sorting_header(_('Name'), 'name', $data['sort'], $data['sortorder'], $data['filter_url']) + ->addStyle('width: 14%'), + (new CColHeader(_('SLO'))), + (new CColHeader(_('Effective date')))->addStyle('width: 24%'), + (new CColHeader(_('Reporting period')))->addStyle('width: 14%'), + (new CColHeader(_('Timezone'))), + (new CColHeader(_('Schedule'))), + (new CColHeader(_('SLA report'))), + (new CColHeader(_('Status'))), +]; + +if ($data['can_edit']) { + array_unshift($header, + (new CCheckBox('all_ids'))->onClick("checkAll('sla-list', 'all_ids', 'ids');") + ); +} + +$table = (new CTableInfo()) + ->setHeader($header); + +foreach ($data['records'] as $recordid => $record) { + $row = [ + $record['name'], + sprintf('%.4f', $record['slo']), + zbx_date2str(DATE_FORMAT, $record['effective_date']), + ]; + + if ($data['can_edit']) { + array_unshift($row, + new CCheckBox('ids['.$recordid.']', $recordid), + ); + } + + $table->addRow(new CRow($row)); +} + + +$form->addItem([ + $table, + $data['paging'], + new CActionButtonList('action', 'ids', [ + 'sla.massenable' => [ + 'content' => (new CSimpleButton(_('Enable'))) + ->setAttribute('confirm', _('Enable selected SLAs?')) + ->onClick('view.massEnable(this);') + ->addClass(ZBX_STYLE_BTN_ALT) + ->addClass('no-chkbxrange') + ->removeAttribute('id') + ], + 'sla.massdisable' => [ + 'content' => (new CSimpleButton(_('Disable'))) + ->setAttribute('confirm', _('Disable selected SLAs?')) + ->onClick('view.massDisable(this);') + ->addClass(ZBX_STYLE_BTN_ALT) + ->addClass('no-chkbxrange') + ->removeAttribute('id') + ], + 'sla.massdelete' => [ + 'content' => (new CSimpleButton(_('Delete'))) + ->setAttribute('confirm', _('Delete selected SLAs?')) + ->onClick('view.massDeleteSlas(this);') + ->addClass(ZBX_STYLE_BTN_ALT) + ->addClass('no-chkbxrange') + ->removeAttribute('id') + ] + ], 'slas') +])->show();
\ No newline at end of file diff --git a/ui/app/views/js/administration.userrole.edit.js.php b/ui/app/views/js/administration.userrole.edit.js.php index 0d04c88e2b3..e4189aba613 100644 --- a/ui/app/views/js/administration.userrole.edit.js.php +++ b/ui/app/views/js/administration.userrole.edit.js.php @@ -84,7 +84,10 @@ CRoleHelper::UI_MONITORING_LATEST_DATA => USER_TYPE_ZABBIX_USER, CRoleHelper::UI_MONITORING_MAPS => USER_TYPE_ZABBIX_USER, CRoleHelper::UI_MONITORING_DISCOVERY => USER_TYPE_ZABBIX_ADMIN, - CRoleHelper::UI_MONITORING_SERVICES => USER_TYPE_ZABBIX_USER, + CRoleHelper::UI_SERVICES_SERVICES => USER_TYPE_ZABBIX_USER, + CRoleHelper::UI_SERVICES_ACTIONS => USER_TYPE_ZABBIX_ADMIN, + CRoleHelper::UI_SERVICES_SLA => USER_TYPE_ZABBIX_ADMIN, + CRoleHelper::UI_SERVICES_SLA_REPORT => USER_TYPE_ZABBIX_USER, CRoleHelper::UI_INVENTORY_OVERVIEW => USER_TYPE_ZABBIX_USER, CRoleHelper::UI_INVENTORY_HOSTS => USER_TYPE_ZABBIX_USER, CRoleHelper::UI_REPORTS_SYSTEM_INFO => USER_TYPE_SUPER_ADMIN, @@ -119,7 +122,8 @@ CRoleHelper::ACTIONS_ADD_PROBLEM_COMMENTS => USER_TYPE_ZABBIX_USER, CRoleHelper::ACTIONS_EXECUTE_SCRIPTS => USER_TYPE_ZABBIX_USER, CRoleHelper::ACTIONS_MANAGE_API_TOKENS => USER_TYPE_ZABBIX_USER, - CRoleHelper::ACTIONS_MANAGE_SCHEDULED_REPORTS => USER_TYPE_ZABBIX_ADMIN + CRoleHelper::ACTIONS_MANAGE_SCHEDULED_REPORTS => USER_TYPE_ZABBIX_ADMIN, + CRoleHelper::ACTIONS_MANAGE_SLA => USER_TYPE_ZABBIX_ADMIN ], JSON_FORCE_OBJECT) ?>; for (const [id, value] of Object.entries(access)) { diff --git a/ui/app/views/js/monitoring.service.list.js.php b/ui/app/views/js/services.service.list.js.php index 1f4e1e632ff..1f4e1e632ff 100755..100644 --- a/ui/app/views/js/monitoring.service.list.js.php +++ b/ui/app/views/js/services.service.list.js.php diff --git a/ui/app/views/js/services.sla.list.js.php b/ui/app/views/js/services.sla.list.js.php new file mode 100644 index 00000000000..a86d0ffdf2e --- /dev/null +++ b/ui/app/views/js/services.sla.list.js.php @@ -0,0 +1,165 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * @var CView $this + */ +?> + +<script type="text/x-jquery-tmpl" id="filter-tag-row-tmpl"> + <?= CTagFilterFieldHelper::getTemplate() ?> +</script> + +<script> + const view = { + mode_switch_url: null, + refresh_url: null, + refresh_interval: null, + back_url: null, + is_refresh_paused: false, + is_refresh_pending: false, + + init({mode_switch_url, refresh_url, refresh_interval, back_url = null}) { + this.mode_switch_url = mode_switch_url; + this.refresh_url = refresh_url; + this.refresh_interval = refresh_interval; + this.back_url = back_url; + + this.initViewModeSwitcher(); + this.initTagFilter(); + this.initActionButtons(); + this.initRefresh(); + }, + + initViewModeSwitcher() { + for (const element of document.getElementsByName('list_mode')) { + if (!element.checked) { + element.addEventListener('click', () => { + location.href = this.mode_switch_url; + }); + } + } + }, + + initTagFilter() { + $('#filter-tags') + .dynamicRows({template: '#filter-tag-row-tmpl'}) + .on('afteradd.dynamicRows', function() { + const rows = this.querySelectorAll('.form_row'); + new CTagFilterItem(rows[rows.length - 1]); + }); + + document.querySelectorAll('#filter-tags .form_row').forEach(row => { + new CTagFilterItem(row); + }); + }, + + initActionButtons() { + document.addEventListener('click', (e) => { + if (e.target.matches('.js-create-sla')) { + const options = e.target.dataset.slaid !== undefined + ? {slaid: [e.target.dataset.slaid]} + : {}; + + this.edit(options); + } + else if (e.target.classList.contains('js-edit-sla')) { + this.edit({slaid: e.target.dataset.slaid}); + } + else if (e.target.classList.contains('js-massupdate-sla')) { + openMassupdatePopup(e.target, 'popup.massupdate.sla', {location_url: this.back_url}); + } + }); + }, + + initRefresh() { + if (this.refresh_interval > 0) { + setInterval(() => this.refresh(), this.refresh_interval); + } + }, + + edit(options = {}) { + this.pauseRefresh(); + + const overlay = PopUp('popup.sla.edit', options, 'service_edit', document.activeElement); + + overlay.$dialogue[0].addEventListener('dialogue.submit', (e) => { + postMessageOk(e.detail.title); + + if (e.detail.messages !== null) { + postMessageDetails('success', e.detail.messages); + } + + location.href = location.href; + }); + + overlay.$dialogue[0].addEventListener('overlay.close', () => this.resumeRefresh(), {once: true}); + }, + + pauseRefresh() { + this.is_refresh_paused = true; + }, + + resumeRefresh() { + this.is_refresh_paused = false; + }, + + refresh() { + if (this.is_refresh_paused || this.is_refresh_pending) { + return; + } + + const record_list = document.getElementById('record-list'); + + if (record_list.querySelectorAll('[data-expanded="true"], [aria-expanded="true"]').length > 0) { + return; + } + + this.is_refresh_pending = true; + + record_list.classList.add('is-loading', 'is-loading-fadein', 'delayed-15s'); + + fetch(this.refresh_url) + .then((response) => response.json()) + .then((response) => { + if ('errors' in response) { + clearMessages(); + addMessage(response.errors); + } + else { + if ('messages' in response) { + clearMessages(); + addMessage(response.messages); + } + + record_list.outerHTML = response.body; + + chkbxRange.init(); + } + }) + .finally(() => { + record_list.classList.remove('is-loading', 'is-loading-fadein', 'delayed-15s'); + + this.is_refresh_pending = false; + }); + } + }; +</script> diff --git a/ui/app/views/popup.sla.edit.php b/ui/app/views/popup.sla.edit.php new file mode 100644 index 00000000000..270cc276627 --- /dev/null +++ b/ui/app/views/popup.sla.edit.php @@ -0,0 +1,428 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * @var CView $this + */ + +$form = (new CForm('post')) + ->setId('sla-form') + ->setName('sla_form') + ->addItem(getMessages()); + +// Enable form submitting on Enter. +$form->addItem((new CInput('submit'))->addStyle('display: none;')); + +// Service tab. + +$parent_services = (new CMultiSelect([ + 'name' => 'parent_serviceids[]', + 'object_name' => 'services', + 'data' => CArrayHelper::renameObjectsKeys($data['form']['parents'], ['serviceid' => 'id']), + 'custom_select' => true +]))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH); + +$service_tab = (new CFormGrid()) + ->addItem([ + (new CLabel(_('Name'), 'name'))->setAsteriskMark(), + new CFormField( + (new CTextBox('name', $data['form']['name'], false, DB::getFieldLength('services', 'name'))) + ->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH) + ->setAriaRequired() + ->setAttribute('autofocus', 'autofocus') + ) + ]) + ->addItem([ + new CLabel(_('Parent services'), 'parent_serviceids__ms'), + new CFormField($parent_services) + ]) + ->addItem([ + new CLabel(_('Problem tags')), + new CFormField( + (new CDiv([ + (new CTable()) + ->setId('problem_tags') + ->addStyle('min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;') + ->setHeader( + (new CRowHeader([_('Name'), _('Operation'), _('Value'), _('Action')])) + ->addClass(ZBX_STYLE_GREY) + ) + ->setFooter( + (new CCol( + (new CSimpleButton(_('Add'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('element-table-add') + )) + ), + (new CScriptTemplate('problem-tag-row-tmpl')) + ->addItem( + (new CRow([ + (new CTextBox('problem_tags[#{rowNum}][tag]', '#{tag}', false, + DB::getFieldLength('service_problem_tag', 'tag') + )) + ->addClass('js-problem-tag-input') + ->addClass('js-problem-tag-tag') + ->setAttribute('placeholder', _('tag')) + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH), + (new CSelect('problem_tags[#{rowNum}][operator]')) + ->addClass('js-problem-tag-input') + ->addOptions(CSelect::createOptionsFromArray([ + SERVICE_TAG_OPERATOR_EQUAL => _('Equals'), + SERVICE_TAG_OPERATOR_LIKE => _('Contains') + ])) + ->setValue(SERVICE_TAG_OPERATOR_EQUAL), + (new CTextBox('problem_tags[#{rowNum}][value]', '#{value}', false, + DB::getFieldLength('service_problem_tag', 'value') + )) + ->addClass('js-problem-tag-input') + ->setAttribute('placeholder', _('value')) + ->setWidth(ZBX_TEXTAREA_FILTER_SMALL_WIDTH), + (new CSimpleButton(_('Remove'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('element-table-remove') + ]))->addClass('form_row') + ) + ]))->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) + ) + ]) + ->addItem([ + (new CLabel(_('Sort order (0->999)'), 'sortorder'))->setAsteriskMark(), + new CFormField( + (new CTextBox('sortorder', $data['form']['sortorder'], false, 3)) + ->setWidth(ZBX_TEXTAREA_TINY_WIDTH) + ->setAriaRequired() + ) + ]) + ->addItem([ + new CLabel([ + _('Status calculation rule'), + (new CSpan([ + ' ', + makeWarningIcon( + _('Status calculation rule and additional rules are only applicable if child services exist.') + ) + ])) + ->setId('algorithm-not-applicable-warning') + ->addStyle($data['form']['children'] ? 'display: none' : '') + ], 'algorithm_focusable'), + new CFormField( + (new CSelect('algorithm')) + ->setId('algorithm') + ->setFocusableElementId('algorithm_focusable') + ->setValue($data['form']['algorithm']) + ->addOptions(CSelect::createOptionsFromArray(CServiceHelper::getAlgorithmNames())) + ) + ]) + ->addItem( + (new CFormField( + (new CCheckBox('advanced_configuration')) + ->setLabel(_('Advanced configuration')) + ->setChecked($data['form']['advanced_configuration']) + ))->addClass(CFormField::ZBX_STYLE_FORM_FIELD_OFFSET_1) + ); + +$additional_rules = (new CTable()) + ->setId('status_rules') + ->setHeader( + (new CRowHeader([_('Name'), _('Action')]))->addClass(ZBX_STYLE_GREY) + ); + +$additional_rules->addItem( + (new CTag('tfoot', true)) + ->addItem( + (new CCol( + (new CSimpleButton(_('Add'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('js-add') + ))->setColSpan(2) + ) +); + +$service_tab + ->addItem([ + (new CLabel(_('Additional rules'))) + ->setId('additional_rules_label') + ->addStyle('display: none;'), + (new CFormField( + (new CDiv($additional_rules)) + ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) + ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') + )) + ->setId('additional_rules_field') + ->addStyle('display: none;') + ]) + ->addItem([ + (new CLabel(_('Status propagation rule'))) + ->setId('status_propagation_rules_label') + ->addStyle('display: none;'), + (new CFormField( + (new CSelect('propagation_rule')) + ->setId('propagation_rule') + ->setFocusableElementId('propagation_rule_focusable') + ->setValue($data['form']['propagation_rule']) + ->addOptions(CSelect::createOptionsFromArray(CServiceHelper::getStatusPropagationNames())) + )) + ->setId('status_propagation_rules_field') + ->addStyle('display: none;') + ]); + +$propagation_value_number = (new CRadioButtonList('propagation_value_number', + $data['form']['propagation_value_number'] !== null ? (int) $data['form']['propagation_value_number'] : null +)) + ->setId('propagation_value_number') + ->setModern(true); + +foreach (range(1, TRIGGER_SEVERITY_COUNT - 1) as $value) { + $propagation_value_number->addValue($value, $value, 'propagation_value_number_'.$value); +} + +$propagation_value_status = (new CSeverity('propagation_value_status', + $data['form']['propagation_value_status'] !== null ? (int) $data['form']['propagation_value_status'] : null +))->addValue(_('OK'), ZBX_SEVERITY_OK, ZBX_STYLE_NORMAL_BG); + +$service_tab + ->addItem([ + (new CFormField([ + $propagation_value_number, + $propagation_value_status + ])) + ->setId('status_propagation_value_field') + ->addStyle('display: none;') + ]) + ->addItem([ + (new CLabel(_('Weight'))) + ->setId('weight_label') + ->addStyle('display: none;'), + (new CFormField( + (new CTextBox('weight', $data['form']['weight'], false, 7))->setWidth(ZBX_TEXTAREA_TINY_WIDTH) + )) + ->setId('weight_field') + ->addStyle('display: none;') + ]); + +// SLA tab. + +$times = (new CTable()) + ->setId('times') + ->setHeader( + (new CRowHeader([_('Type'), _('Interval'), _('Note'), _('Action')]))->addClass(ZBX_STYLE_GREY) + ); + +$times->addItem( + (new CTag('tfoot', true)) + ->addItem( + (new CCol( + (new CSimpleButton(_('Add'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('js-add') + ))->setColSpan(4) + ) +); + +$sla_tab = (new CFormGrid()) + ->addItem([ + new CLabel(_('SLA'), 'showsla'), + new CFormField( + new CHorList([ + (new CCheckBox('showsla'))->setChecked($data['form']['showsla'] == SERVICE_SHOW_SLA_ON), + (new CTextBox('goodsla', $data['form']['goodsla'], false, 8))->setWidth(ZBX_TEXTAREA_TINY_WIDTH) + ]) + ) + ]) + ->addItem([ + new CLabel(_('Service times')), + new CFormField([ + (new CDiv($times)) + ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) + ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') + ]) + ]); + +// Tags tab. + +$tags_tab = (new CFormGrid()) + ->addItem([ + new CLabel(_('Tags')), + new CFormField( + (new CDiv()) + ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) + ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') + ->addItem([ + renderTagTable($data['form']['tags']) + ->setId('tags-table') + ->setHeader((new CRowHeader([_('Name'), _('Value'), _('Action')]))->addClass(ZBX_STYLE_GREY)), + (new CScriptTemplate('tag-row-tmpl')) + ->addItem(renderTagTableRow('#{rowNum}', '', '', ['add_post_js' => false])) + + ]) + ) + ]); + +// Child services tab. + +$child_services = (new CTable()) + ->setId('children') + ->setAttribute('data-tab-indicator', count($data['form']['children'])) + ->setHeader( + (new CRowHeader([ + _('Service'), + _('Status calculation rule'), + _('Problem tags'), + _('Action') + ]))->addClass(ZBX_STYLE_GREY) + ) + ->addItem( + (new CTag('tfoot', true)) + ->addItem( + (new CCol( + (new CList()) + ->addClass(ZBX_STYLE_INLINE_FILTER_FOOTER) + ->addItem( + (new CSimpleButton(_('Add'))) + ->addClass(ZBX_STYLE_BTN_LINK) + ->addClass('js-add') + ) + ->addItem( + (new CListItem(null)) + ->addClass(ZBX_STYLE_INLINE_FILTER_STATS) + ) + ))->setColSpan(4) + ) + ); + +$child_services_filter = (new CList()) + ->setId('children-filter') + ->addClass(ZBX_STYLE_INLINE_FILTER) + ->addItem(new CLabel(_('Name'), 'children-filter-name'), ZBX_STYLE_INLINE_FILTER_LABEL) + ->addItem( + (new CTextBox(null)) + ->setId('children-filter-name') + ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH)) + ->addItem( + (new CSimpleButton(_('Filter'))) + ->addClass('js-filter') + ) + ->addItem( + (new CSimpleButton(_('Reset'))) + ->addClass('js-reset') + ->addClass(ZBX_STYLE_BTN_ALT) + ); + +$child_services_tab = [ + (new CFormGrid()) + ->addItem(new CFormField($child_services_filter)) + ->addItem([ + new CLabel(_('Child services')), + new CFormField( + (new CDiv($child_services)) + ->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR) + ->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;') + ) + ]) +]; + +$tabs = (new CTabView()) + ->setSelected(0) + ->addTab('service-tab', _('Service'), $service_tab) + ->addTab('sla-tab', _('SLA'), $sla_tab, TAB_INDICATOR_SLA) + ->addTab('tags-tab', _('Tags'), $tags_tab, TAB_INDICATOR_TAGS) + ->addTab('child-services-tab', _('Child services'), $child_services_tab, TAB_INDICATOR_CHILD_SERVICES); + +// Output. + +$form + ->addItem($tabs) + ->addItem( + (new CScriptTag(' + const params = '.json_encode([ + 'serviceid' => $data['serviceid'], + 'children' => $data['form']['children'], + 'children_problem_tags_html' => $data['form']['children_problem_tags_html'], + 'problem_tags' => $data['form']['problem_tags'], + 'status_rules' => $data['form']['status_rules'], + 'service_times' => $data['form']['times'], + 'create_url' => (new CUrl('zabbix.php')) + ->setArgument('action', 'service.create') + ->getUrl(), + 'update_url' => (new CUrl('zabbix.php')) + ->setArgument('action', 'service.update') + ->getUrl(), + 'search_limit' => CSettingsHelper::get(CSettingsHelper::SEARCH_LIMIT) + ]).' + + params.algorithm_names = '.json_encode(CServiceHelper::getAlgorithmNames(), JSON_FORCE_OBJECT).'; + + service_edit_popup.init(params); + '))->setOnDocumentReady() + ); + +if ($data['serviceid'] !== null) { + $title = _('Service'); + $buttons = [ + [ + 'title' => _('Update'), + 'class' => 'js-update', + 'keepOpen' => true, + 'isSubmit' => true, + 'action' => 'service_edit_popup.submit();' + ], + [ + 'title' => _('Clone'), + 'class' => implode(' ', [ZBX_STYLE_BTN_ALT, 'js-clone']), + 'keepOpen' => true, + 'action' => 'service_edit_popup.clone('.json_encode(_('New service')).');' + ], + [ + 'title' => _('Add'), + 'class' => implode(' ', [ZBX_STYLE_DISPLAY_NONE, 'js-add']), + 'keepOpen' => true, + 'isSubmit' => true, + 'action' => 'service_edit_popup.submit();' + ] + ]; +} +else { + $title = _('New service'); + $buttons = [ + [ + 'title' => _('Add'), + 'class' => 'js-add', + 'keepOpen' => true, + 'isSubmit' => true, + 'action' => 'service_edit_popup.submit();' + ] + ]; +} + +$output = [ + 'header' => $title, + 'body' => $form->toString(), + 'buttons' => $buttons, + 'script_inline' => getPagePostJs(). + $this->readJsFile('popup.service.edit.js.php') +]; + +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/monitoring.service.list.edit.php b/ui/app/views/services.service.list.edit.php index aa0145a89dc..d137ed77a99 100755..100644 --- a/ui/app/views/monitoring.service.list.edit.php +++ b/ui/app/views/services.service.list.edit.php @@ -32,7 +32,7 @@ $this->addJsFile('layout.mode.js'); $this->addJsFile('class.tagfilteritem.js'); $this->addJsFile('class.calendar.js'); -$this->includeJsFile('monitoring.service.list.js.php'); +$this->includeJsFile('services.service.list.js.php'); $breadcrumbs = []; $filter = null; @@ -149,7 +149,7 @@ $filter->addFilterTab(_('Filter'), [ $breadcrumbs ? new CList([new CBreadcrumbs($breadcrumbs)]) : null ) ->addItem($filter) - ->addItem(new CPartial('monitoring.service.list.edit', array_intersect_key($data, array_flip([ + ->addItem(new CPartial('services.service.list.edit', array_intersect_key($data, array_flip([ 'can_monitor_problems', 'path', 'is_filtered', 'max_in_table', 'service', 'services', 'events', 'tags', 'paging', 'back_url' ])))) diff --git a/ui/app/views/monitoring.service.list.edit.refresh.php b/ui/app/views/services.service.list.edit.refresh.php index c567382739f..c27fe4feb70 100755..100644 --- a/ui/app/views/monitoring.service.list.edit.refresh.php +++ b/ui/app/views/services.service.list.edit.refresh.php @@ -24,7 +24,7 @@ */ $output = [ - 'body' => (new CPartial('monitoring.service.list.edit', $data))->getOutput() + 'body' => (new CPartial('services.service.list.edit', $data))->getOutput() ]; if (($messages = getMessages()) !== null) { diff --git a/ui/app/views/monitoring.service.list.php b/ui/app/views/services.service.list.php index b8a4db1458d..60c12815e9b 100644 --- a/ui/app/views/monitoring.service.list.php +++ b/ui/app/views/services.service.list.php @@ -27,7 +27,7 @@ $this->addJsFile('layout.mode.js'); $this->addJsFile('class.tagfilteritem.js'); -$this->includeJsFile('monitoring.service.list.js.php'); +$this->includeJsFile('services.service.list.js.php'); $this->enableLayoutModes(); $web_layout_mode = $this->getLayoutMode(); @@ -123,7 +123,7 @@ if ($web_layout_mode == ZBX_LAYOUT_NORMAL) { $breadcrumbs ? new CList([new CBreadcrumbs($breadcrumbs)]) : null ) ->addItem($filter) - ->addItem(new CPartial('monitoring.service.list', array_intersect_key($data, array_flip(['can_monitor_problems', + ->addItem(new CPartial('services.service.list', array_intersect_key($data, array_flip(['can_monitor_problems', 'path', 'is_filtered', 'max_in_table', 'service', 'services', 'events', 'tags', 'paging' ])))) ->show(); diff --git a/ui/app/views/monitoring.service.list.refresh.php b/ui/app/views/services.service.list.refresh.php index b2d177406a3..b92a2a12e83 100644 --- a/ui/app/views/monitoring.service.list.refresh.php +++ b/ui/app/views/services.service.list.refresh.php @@ -24,7 +24,7 @@ */ $output = [ - 'body' => (new CPartial('monitoring.service.list', $data))->getOutput() + 'body' => (new CPartial('services.service.list', $data))->getOutput() ]; if (($messages = getMessages()) !== null) { diff --git a/ui/app/views/services.sla.list.php b/ui/app/views/services.sla.list.php new file mode 100644 index 00000000000..07a6139efa9 --- /dev/null +++ b/ui/app/views/services.sla.list.php @@ -0,0 +1,101 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * @var CView $this + * @var array $data + */ + +$this->addJsFile('layout.mode.js'); +$this->addJsFile('class.tagfilteritem.js'); + +$this->includeJsFile('services.sla.list.js.php'); + +$this->enableLayoutModes(); +$web_layout_mode = $this->getLayoutMode(); + +$filter = null; + +if ($web_layout_mode == ZBX_LAYOUT_NORMAL) { + $filter = (new CFilter()) + ->addVar('action', 'sla.list') + ->setResetUrl($data['reset_curl']) + ->setProfile('web.sla.filter') + ->setActiveTab($data['active_tab']); + + $filter->addFilterTab(_('Filter'), [ + (new CFormGrid()) + ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE) + ->addItem([ + new CLabel(_('Name'), 'filter_name'), + new CFormField( + (new CTextBox('filter_name', $data['filter']['name'])) + ->setWidth(ZBX_TEXTAREA_FILTER_STANDARD_WIDTH) + ) + ]) + ->addItem([ + new CLabel(_('Status')), + new CFormField( + (new CRadioButtonList('filter_status', (int) $data['filter']['status'])) + ->addValue(_('Any'), CSlaHelper::SLA_STATUS_ANY) + ->addValue(_('Enabled'), CSlaHelper::SLA_STATUS_ENABLED) + ->addValue(_('Disabled'), CSlaHelper::SLA_STATUS_DISABLED) + ->setModern(true) + ) + ]), + (new CFormGrid()) + ->addClass(CFormGrid::ZBX_STYLE_FORM_GRID_LABEL_WIDTH_TRUE) + ->addItem([ + new CLabel(_('Tags')), + new CFormField( + CTagFilterFieldHelper::getTagFilterField([ + 'evaltype' => $data['filter']['evaltype'], + 'tags' => $data['filter']['tags'] ?: [ + ['tag' => '', 'value' => '', 'operator' => TAG_OPERATOR_LIKE] + ] + ]) + ) + ]) + ]); +} + +(new CWidget()) + ->setTitle(_('SLA')) + ->setWebLayoutMode($web_layout_mode) + ->setControls( + (new CTag('nav', true, + (new CList()) + ->addItem(get_icon('kioskmode', ['mode' => $web_layout_mode])) + ))->setAttribute('aria-label', _('Content controls')) + ) + ->addItem($filter) + ->addItem(new CPartial('services.sla.list', $data)) + ->show(); + +(new CScriptTag(' + view.init('.json_encode([ + 'mode_switch_url' => $data['edit_mode_url'], + 'refresh_url' => $data['refresh_url'], + 'refresh_interval' => $data['refresh_interval'] + ]).'); +')) + ->setOnDocumentReady() + ->show(); diff --git a/ui/assets/styles/blue-theme.css b/ui/assets/styles/blue-theme.css index f45ea4b353c..e0786205fb0 100644 --- a/ui/assets/styles/blue-theme.css +++ b/ui/assets/styles/blue-theme.css @@ -1478,7 +1478,7 @@ footer { .inline-filter-footer > li.inline-filter-stats { color: #768d99; } -.icon-dashboard::before, .icon-problems::before, .icon-monitoring::before, .icon-inventory::before, .icon-reports::before, .icon-configuration::before, .icon-administration::before { +.icon-dashboard::before, .icon-problems::before, .icon-monitoring::before, .icon-services::before, .icon-inventory::before, .icon-reports::before, .icon-configuration::before, .icon-administration::before { content: ''; width: 24px; height: 24px; @@ -1497,6 +1497,10 @@ footer { background-position: -540px -712px; transition: opacity 0.3s; } +.icon-services::before { + background-position: -42px -832px; + transition: opacity 0.3s; } + .icon-inventory::before { background-position: -540px -736px; transition: opacity 0.3s; } diff --git a/ui/include/classes/helpers/CMenuHelper.php b/ui/include/classes/helpers/CMenuHelper.php index 65de90d325e..a772184616b 100644 --- a/ui/include/classes/helpers/CMenuHelper.php +++ b/ui/include/classes/helpers/CMenuHelper.php @@ -60,11 +60,6 @@ class CMenuHelper { : null, CWebUser::checkAccess(CRoleHelper::UI_MONITORING_DISCOVERY) ? (new CMenuItem(_('Discovery')))->setAction('discovery.view') - : null, - CWebUser::checkAccess(CRoleHelper::UI_MONITORING_SERVICES) - ? (new CMenuItem(_('Services'))) - ->setAction('service.list') - ->setAliases(['service.list.edit']) : null ]; $submenu_monitoring = array_filter($submenu_monitoring); @@ -78,6 +73,42 @@ class CMenuHelper { ); } + $submenu_services = [ + CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SERVICES) + ? (new CMenuItem(_('Services'))) + ->setAction('service.list') + ->setAliases(['service.list.edit']) + : null, + CWebUser::checkAccess(CRoleHelper::UI_SERVICES_ACTIONS) + ? (new CMenuItem(_('Service actions'))) + ->setUrl( + (new CUrl('actionconf.php'))->setArgument('eventsource', EVENT_SOURCE_SERVICE), + 'actionconf.php?eventsource='.EVENT_SOURCE_SERVICE + ) + : null, + CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SLA) + ? (new CMenuItem(_('SLA'))) + ->setAction('sla.list') + ->setAliases(['sla.list.edit']) + : null, + CWebUser::checkAccess(CRoleHelper::UI_SERVICES_SLA_REPORT) + ? (new CMenuItem(_('SLA report'))) + ->setAction('sla_report.list') + ->setAliases(['sla_report.list.edit']) + : null + ]; + + $submenu_services = array_filter($submenu_services); + + if ($submenu_services) { + $menu->add( + (new CMenuItem(_('Services'))) + ->setId('view') + ->setIcon('icon-services') + ->setSubMenu(new CMenu($submenu_services)) + ); + } + $submenu_inventory = [ CWebUser::checkAccess(CRoleHelper::UI_INVENTORY_OVERVIEW) ? (new CMenuItem(_('Overview'))) diff --git a/ui/include/classes/helpers/CRoleHelper.php b/ui/include/classes/helpers/CRoleHelper.php index 832d9842eb7..d1325068888 100644 --- a/ui/include/classes/helpers/CRoleHelper.php +++ b/ui/include/classes/helpers/CRoleHelper.php @@ -30,7 +30,6 @@ class CRoleHelper { public const UI_MONITORING_LATEST_DATA = 'ui.monitoring.latest_data'; public const UI_MONITORING_MAPS = 'ui.monitoring.maps'; public const UI_MONITORING_DISCOVERY = 'ui.monitoring.discovery'; - public const UI_MONITORING_SERVICES = 'ui.monitoring.services'; public const UI_INVENTORY_OVERVIEW = 'ui.inventory.overview'; public const UI_INVENTORY_HOSTS = 'ui.inventory.hosts'; public const UI_REPORTS_SYSTEM_INFO = 'ui.reports.system_info'; @@ -40,6 +39,10 @@ class CRoleHelper { public const UI_REPORTS_ACTION_LOG = 'ui.reports.action_log'; public const UI_REPORTS_NOTIFICATIONS = 'ui.reports.notifications'; public const UI_REPORTS_SCHEDULED_REPORTS = 'ui.reports.scheduled_reports'; + public const UI_SERVICES_SERVICES = 'ui.services.services'; + public const UI_SERVICES_ACTIONS = 'ui.services.actions'; + public const UI_SERVICES_SLA = 'ui.services.sla'; + public const UI_SERVICES_SLA_REPORT = 'ui.services.sla_report'; public const UI_CONFIGURATION_HOST_GROUPS = 'ui.configuration.host_groups'; public const UI_CONFIGURATION_TEMPLATES = 'ui.configuration.templates'; public const UI_CONFIGURATION_HOSTS = 'ui.configuration.hosts'; @@ -67,8 +70,10 @@ class CRoleHelper { public const ACTIONS_EXECUTE_SCRIPTS = 'actions.execute_scripts'; public const ACTIONS_MANAGE_API_TOKENS = 'actions.manage_api_tokens'; public const ACTIONS_MANAGE_SCHEDULED_REPORTS = 'actions.manage_scheduled_reports'; + public const ACTIONS_MANAGE_SLA = 'actions.manage_sla'; public const UI_SECTION_MONITORING = 'ui.monitoring'; + public const UI_SECTION_SERVICES = 'ui.services'; public const UI_SECTION_INVENTORY = 'ui.inventory'; public const UI_SECTION_REPORTS = 'ui.reports'; public const UI_SECTION_CONFIGURATION = 'ui.configuration'; @@ -211,27 +216,50 @@ class CRoleHelper { */ public static function getUiElementsByUserType(int $user_type): array { $rules = [ - self::UI_MONITORING_DASHBOARD, self::UI_MONITORING_PROBLEMS, self::UI_MONITORING_HOSTS, - self::UI_MONITORING_LATEST_DATA, self::UI_MONITORING_MAPS, self::UI_MONITORING_SERVICES, - self::UI_INVENTORY_OVERVIEW, self::UI_INVENTORY_HOSTS, self::UI_REPORTS_AVAILABILITY_REPORT, - self::UI_REPORTS_TOP_TRIGGERS + self::UI_INVENTORY_HOSTS, + self::UI_INVENTORY_OVERVIEW, + self::UI_MONITORING_DASHBOARD, + self::UI_MONITORING_HOSTS, + self::UI_MONITORING_LATEST_DATA, + self::UI_MONITORING_MAPS, + self::UI_MONITORING_PROBLEMS, + self::UI_REPORTS_AVAILABILITY_REPORT, + self::UI_REPORTS_TOP_TRIGGERS, + self::UI_SERVICES_SERVICES, + self::UI_SERVICES_SLA_REPORT ]; if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) { $rules = array_merge($rules, [ - self::UI_MONITORING_DISCOVERY, self::UI_REPORTS_NOTIFICATIONS, self::UI_REPORTS_SCHEDULED_REPORTS, - self::UI_CONFIGURATION_HOST_GROUPS, self::UI_CONFIGURATION_TEMPLATES, self::UI_CONFIGURATION_HOSTS, - self::UI_CONFIGURATION_MAINTENANCE, self::UI_CONFIGURATION_ACTIONS, self::UI_CONFIGURATION_DISCOVERY + self::UI_CONFIGURATION_ACTIONS, + self::UI_CONFIGURATION_DISCOVERY, + self::UI_CONFIGURATION_HOST_GROUPS, + self::UI_CONFIGURATION_HOSTS, + self::UI_CONFIGURATION_MAINTENANCE, + self::UI_CONFIGURATION_TEMPLATES, + self::UI_MONITORING_DISCOVERY, + self::UI_REPORTS_NOTIFICATIONS, + self::UI_REPORTS_SCHEDULED_REPORTS, + self::UI_SERVICES_ACTIONS, + self::UI_SERVICES_SLA ]); } if ($user_type === USER_TYPE_SUPER_ADMIN) { $rules = array_merge($rules, [ - self::UI_REPORTS_SYSTEM_INFO, self::UI_REPORTS_AUDIT, self::UI_REPORTS_ACTION_LOG, - self::UI_CONFIGURATION_EVENT_CORRELATION, self::UI_ADMINISTRATION_GENERAL, self::UI_ADMINISTRATION_PROXIES, - self::UI_ADMINISTRATION_AUTHENTICATION, self::UI_ADMINISTRATION_USER_GROUPS, - self::UI_ADMINISTRATION_USER_ROLES, self::UI_ADMINISTRATION_USERS, self::UI_ADMINISTRATION_MEDIA_TYPES, - self::UI_ADMINISTRATION_SCRIPTS, self::UI_ADMINISTRATION_QUEUE + self::UI_ADMINISTRATION_AUTHENTICATION, + self::UI_ADMINISTRATION_GENERAL, + self::UI_ADMINISTRATION_MEDIA_TYPES, + self::UI_ADMINISTRATION_PROXIES, + self::UI_ADMINISTRATION_QUEUE, + self::UI_ADMINISTRATION_SCRIPTS, + self::UI_ADMINISTRATION_USER_GROUPS, + self::UI_ADMINISTRATION_USER_ROLES, + self::UI_ADMINISTRATION_USERS, + self::UI_CONFIGURATION_EVENT_CORRELATION, + self::UI_REPORTS_ACTION_LOG, + self::UI_REPORTS_AUDIT, + self::UI_REPORTS_SYSTEM_INFO ]); } @@ -257,6 +285,7 @@ class CRoleHelper { if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) { $rules[] = self::ACTIONS_EDIT_MAINTENANCE; $rules[] = self::ACTIONS_MANAGE_SCHEDULED_REPORTS; + $rules[] = self::ACTIONS_MANAGE_SLA; } return $rules; @@ -274,8 +303,9 @@ class CRoleHelper { public static function getUiSectionsLabels(int $user_type): array { $sections = [ self::UI_SECTION_MONITORING => _('Monitoring'), + self::UI_SECTION_SERVICES => _('Services'), self::UI_SECTION_INVENTORY => _('Inventory'), - self::UI_SECTION_REPORTS => _('Reports') + self::UI_SECTION_REPORTS => _('Reports'), ]; if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) { @@ -314,9 +344,22 @@ class CRoleHelper { $labels += [self::UI_MONITORING_DISCOVERY => _('Discovery')]; } - $labels += [self::UI_MONITORING_SERVICES => _('Services')]; + return $labels; + + case self::UI_SECTION_SERVICES: + $labels = [ + self::UI_SERVICES_SERVICES => _('Services'), + self::UI_SERVICES_ACTIONS => _('Service actions'), + ]; + + if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) { + $labels += [self::UI_SERVICES_SLA => _('SLA')]; + } + + $labels += [self::UI_SERVICES_SLA_REPORT => _('SLA report')]; return $labels; + case self::UI_SECTION_INVENTORY: return [ self::UI_INVENTORY_OVERVIEW => _('Overview'), @@ -424,7 +467,10 @@ class CRoleHelper { ]; if ($user_type === USER_TYPE_ZABBIX_ADMIN || $user_type === USER_TYPE_SUPER_ADMIN) { - $labels += [self::ACTIONS_MANAGE_SCHEDULED_REPORTS => _('Manage scheduled reports')]; + $labels += [ + self::ACTIONS_MANAGE_SCHEDULED_REPORTS => _('Manage scheduled reports'), + self::ACTIONS_MANAGE_SLA => _('Manage SLA') + ]; } return $labels; diff --git a/ui/include/classes/helpers/CSlaHelper.php b/ui/include/classes/helpers/CSlaHelper.php new file mode 100644 index 00000000000..9dddf48b525 --- /dev/null +++ b/ui/include/classes/helpers/CSlaHelper.php @@ -0,0 +1,72 @@ +<?php declare(strict_types = 1); +/* +** Zabbix +** Copyright (C) 2001-2021 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * A class designed to perform actions and contain constants related to SLA. + */ +class CSlaHelper { + + public const SLA_STATUS_ANY = -1; + public const SLA_STATUS_ENABLED = 0; + public const SLA_STATUS_DISABLED = 1; + + public const PERIOD_DAILY = 0; + public const PERIOD_WEEKLY = 1; + public const PERIOD_MONTHLY = 2; + public const PERIOD_QUARTERLY = 3; + public const PERIOD_ANNUALLY = 4; + + public const SCHEDULE_MODE_NONSTOP = 0; + public const SCHEDULE_MODE_CUSTOM = 1; + + public static function periodToStr(int $period): ?string { + static $period_strings; + + if ($period_strings === null) { + $period_strings = [ + self::PERIOD_DAILY => _('Daily'), + self::PERIOD_WEEKLY => _('Weekly'), + self::PERIOD_MONTHLY => _('Monthly'), + self::PERIOD_QUARTERLY => _('Quarterly'), + self::PERIOD_ANNUALLY => _('Annually') + ]; + } + + return array_key_exists($period, $period_strings) + ? $period_strings[$period] + : null; + } + + public static function scheduleToStr(int $schedule_mode): ?string { + static $schedule_modes; + + if ($schedule_modes === null) { + $schedule_modes = [ + self::SCHEDULE_MODE_NONSTOP => _('24x7'), + self::SCHEDULE_MODE_CUSTOM => _('Custom') + ]; + } + + return array_key_exists($schedule_mode, $schedule_modes) + ? $schedule_modes[$schedule_mode] + : null; + } +} diff --git a/ui/include/classes/mvc/CRouter.php b/ui/include/classes/mvc/CRouter.php index b7f7cc7508c..26b27378720 100644 --- a/ui/include/classes/mvc/CRouter.php +++ b/ui/include/classes/mvc/CRouter.php @@ -239,10 +239,14 @@ class CRouter { 'search' => ['CControllerSearch', 'layout.htmlpage', 'search'], 'service.create' => ['CControllerServiceCreate', 'layout.json', null], 'service.delete' => ['CControllerServiceDelete', null, null], - 'service.list' => ['CControllerServiceList', 'layout.htmlpage', 'monitoring.service.list'], - 'service.list.refresh' => ['CControllerServiceListRefresh', 'layout.json', 'monitoring.service.list.refresh'], - 'service.list.edit' => ['CControllerServiceListEdit', 'layout.htmlpage', 'monitoring.service.list.edit'], - 'service.list.edit.refresh' => ['CControllerServiceListEditRefresh', 'layout.json', 'monitoring.service.list.edit.refresh'], + 'service.list' => ['CControllerServiceList', 'layout.htmlpage', 'services.service.list'], + 'service.list.refresh' => ['CControllerServiceListRefresh', 'layout.json', 'services.service.list.refresh'], + 'service.list.edit' => ['CControllerServiceListEdit', 'layout.htmlpage', 'services.service.list.edit'], + 'service.list.edit.refresh' => ['CControllerServiceListEditRefresh', 'layout.json', 'services.service.list.edit.refresh'], + 'sla.create' => ['CControllerSlaCreate', 'layout.json', null], + 'sla.delete' => ['CControllerSlaDelete', null, null], + 'sla.list' => ['CControllerSlaList', 'layout.htmlpage', 'services.sla.list'], + 'sla.list.refresh' => ['CControllerSlaListRefresh', 'layout.json', 'services.sla.list.refresh'], 'service.statusrule.validate' => ['CControllerServiceStatusRuleValidate', 'layout.json', null], 'service.time.validate' => ['CControllerServiceTimeValidate', 'layout.json', null], 'service.update' => ['CControllerServiceUpdate', 'layout.json', null], diff --git a/ui/include/defines.inc.php b/ui/include/defines.inc.php index 8e1f1d49f19..0058a028869 100644 --- a/ui/include/defines.inc.php +++ b/ui/include/defines.inc.php @@ -22,7 +22,7 @@ define('ZABBIX_VERSION', '6.0.0alpha7'); define('ZABBIX_API_VERSION', '6.0.0'); define('ZABBIX_EXPORT_VERSION', '6.0'); -define('ZABBIX_DB_VERSION', 5050127); +define('ZABBIX_DB_VERSION', 5050128); define('DB_VERSION_SUPPORTED', 0); define('DB_VERSION_LOWER_THAN_MINIMUM', 1); @@ -2027,6 +2027,9 @@ define('ZBX_STYLE_ZSELECT_HOST_INTERFACE', 'z-select-host-interface'); define('ZBX_STYLE_DASHBOARD_LIST', 'dashboard-list'); define('ZBX_STYLE_DASHBOARD_LIST_ITEM', 'dashboard-list-item'); +define('ZBX_SLA_MAX_REPORTING_PERIODS', 100); +define('ZBX_SLA_DEFAULT_REPORTING_PERIODS', 20); + // server variables define('HTTPS', isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] && $_SERVER['HTTPS'] !== 'off'); diff --git a/ui/tests/selenium/testSID.php b/ui/tests/selenium/testSID.php index 77b7ce6dae6..52dfe3e66a6 100644 --- a/ui/tests/selenium/testSID.php +++ b/ui/tests/selenium/testSID.php @@ -331,7 +331,7 @@ class testSID extends CWebTest { // User role creation. [['link' => 'zabbix.php?form_refresh=1&name=sadasda&type=1&ui_monitoring_dashboard=1&ui_monitoring_problems='. '1&ui_monitoring_hosts=1&ui_monitoring_overview=1&ui_monitoring_latest_data=1&ui_monitoring_screens=1'. - '&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_monitoring_services=1&ui_inventory_overview=1&'. + '&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_services_services=1&ui_inventory_overview=1&'. 'ui_inventory_hosts=1&ui_reports_system_info=0&ui_reports_availability_report=1&ui_reports_top_triggers'. '=1&ui_reports_audit=0&ui_reports_action_log=0&ui_reports_notifications=0&ui_configuration_host_groups=0'. '&ui_configuration_templates=0&ui_configuration_hosts=0&ui_configuration_maintenance=0&'. @@ -348,7 +348,7 @@ class testSID extends CWebTest { [['link' => 'zabbix.php?form_refresh=1&roleid=5&name=sadasda&type=2&ui_monitoring_dashboard=1&'. 'ui_monitoring_problems=1&ui_monitoring_hosts=1&ui_monitoring_overview=1&ui_monitoring_latest_data=1'. '&ui_monitoring_screens=1&ui_monitoring_maps=1&ui_monitoring_discovery=0&ui_monitoring_discovery=1&'. - 'ui_monitoring_services=1&ui_inventory_overview=1&ui_inventory_hosts=1&ui_reports_system_info=0&'. + 'ui_services_services=1&ui_inventory_overview=1&ui_inventory_hosts=1&ui_reports_system_info=0&'. 'ui_reports_availability_report=1&ui_reports_top_triggers=1&ui_reports_audit=0&ui_reports_action_log=0'. '&ui_reports_notifications=0&ui_reports_notifications=1&ui_configuration_host_groups=0&'. 'ui_configuration_host_groups=1&ui_configuration_templates=0&ui_configuration_templates=1&'. |