diff options
Diffstat (limited to 'ui/widgets/problems/views/widget.view.php')
-rw-r--r-- | ui/widgets/problems/views/widget.view.php | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/ui/widgets/problems/views/widget.view.php b/ui/widgets/problems/views/widget.view.php new file mode 100644 index 00000000000..e0ee472868c --- /dev/null +++ b/ui/widgets/problems/views/widget.view.php @@ -0,0 +1,334 @@ +<?php declare(strict_types = 0); +/* +** Zabbix +** Copyright (C) 2001-2022 Zabbix SIA +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +**/ + + +/** + * Problems widget view. + * + * @var CView $this + * @var array $data + */ + +// indicator of sort field +$sort_div = (new CSpan())->addClass(($data['sortorder'] === ZBX_SORT_DOWN) ? ZBX_STYLE_ARROW_DOWN : ZBX_STYLE_ARROW_UP); + +$url_details = $data['allowed_ui_problems'] + ? (new CUrl('tr_events.php')) + ->setArgument('triggerid') + ->setArgument('eventid') + : null; + +$show_timeline = ($data['sortfield'] === 'clock' && $data['fields']['show_timeline']); +$show_recovery_data = in_array($data['fields']['show'], [TRIGGERS_OPTION_RECENT_PROBLEM, TRIGGERS_OPTION_ALL]); + +$header_time = new CColHeader(($data['sortfield'] === 'clock') + ? [_x('Time', 'compact table header'), $sort_div] + : _x('Time', 'compact table header')); + +if ($show_timeline) { + $header = [ + $header_time->addClass(ZBX_STYLE_RIGHT), + (new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH), + (new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH) + ]; +} +else { + $header = [$header_time]; +} + +$show_opdata = $data['fields']['show_opdata']; + +$table = (new CTableInfo()) + ->setHeader(array_merge($header, [ + $show_recovery_data + ? _x('Recovery time', 'compact table header') + : null, + $show_recovery_data + ? _x('Status', 'compact table header') + : null, + _x('Info', 'compact table header'), + ($data['sortfield'] === 'host') + ? [_x('Host', 'compact table header'), $sort_div] + : _x('Host', 'compact table header'), + [ + ($data['sortfield'] === 'name') + ? [_x('Problem', 'compact table header'), $sort_div] + : _x('Problem', 'compact table header'), + ' • ', + ($data['sortfield'] === 'severity') + ? [_x('Severity', 'compact table header'), $sort_div] + : _x('Severity', 'compact table header') + ], + ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) + ? _x('Operational data', 'compact table header') + : null, + _x('Duration', 'compact table header'), + _x('Ack', 'compact table header'), + _x('Actions', 'compact table header'), + $data['fields']['show_tags'] ? _x('Tags', 'compact table header') : null + ])); + +$today = strtotime('today'); +$last_clock = 0; + +if ($data['data']['problems']) { + $triggers_hosts = makeTriggersHostsList($data['data']['triggers_hosts']); +} + +$allowed = [ + 'ui_problems' => $data['allowed_ui_problems'], + 'add_comments' => $data['allowed_add_comments'], + 'change_severity' => $data['allowed_change_severity'], + 'acknowledge' => $data['allowed_acknowledge'], + 'suppress' => $data['allowed_suppress'] +]; + +foreach ($data['data']['problems'] as $eventid => $problem) { + $trigger = $data['data']['triggers'][$problem['objectid']]; + + if ($problem['r_eventid'] != 0) { + $value = TRIGGER_VALUE_FALSE; + $value_str = _('RESOLVED'); + $value_clock = $problem['r_clock']; + $can_be_closed = false; + } + else { + $in_closing = hasEventCloseAction($problem['acknowledges']); + $can_be_closed = ($trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED && $data['allowed_close'] + && !$in_closing + ); + $value = $in_closing ? TRIGGER_VALUE_FALSE : TRIGGER_VALUE_TRUE; + $value_str = $in_closing ? _('CLOSING') : _('PROBLEM'); + $value_clock = $in_closing ? time() : $problem['clock']; + } + + $cell_clock = ($problem['clock'] >= $today) + ? zbx_date2str(TIME_FORMAT_SECONDS, $problem['clock']) + : zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['clock']); + + if ($url_details !== null) { + $url_details + ->setArgument('triggerid', $problem['objectid']) + ->setArgument('eventid', $problem['eventid']); + $cell_clock = new CCol(new CLink($cell_clock, $url_details)); + } + else { + $cell_clock = new CCol($cell_clock); + } + + $is_acknowledged = ($problem['acknowledged'] == EVENT_ACKNOWLEDGED); + + $cell_r_clock = ''; + $cell_status = ''; + + if ($show_recovery_data) { + if ($problem['r_eventid'] != 0) { + $cell_r_clock = ($problem['r_clock'] >= $today) + ? zbx_date2str(TIME_FORMAT_SECONDS, $problem['r_clock']) + : zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['r_clock']); + $cell_r_clock = (new CCol($url_details !== null ? new CLink($cell_r_clock, $url_details) : $cell_r_clock)) + ->addClass(ZBX_STYLE_NOWRAP) + ->addClass(ZBX_STYLE_RIGHT); + } + + $cell_status = new CSpan($value_str); + + // Add colors and blinking to span depending on configuration and trigger parameters. + addTriggerValueStyle($cell_status, $value, $value_clock, $is_acknowledged); + } + + // Info. + $info_icons = []; + if ($problem['r_eventid'] != 0) { + if ($problem['correlationid'] != 0) { + $info_icons[] = makeInformationIcon( + array_key_exists($problem['correlationid'], $data['data']['correlations']) + ? _s('Resolved by correlation rule "%1$s".', + $data['data']['correlations'][$problem['correlationid']]['name'] + ) + : _('Resolved by correlation rule.') + ); + } + elseif ($problem['userid'] != 0) { + $info_icons[] = makeInformationIcon( + array_key_exists($problem['userid'], $data['data']['users']) + ? _s('Resolved by user "%1$s".', getUserFullname($data['data']['users'][$problem['userid']])) + : _('Resolved by inaccessible user.') + ); + } + } + + if (array_key_exists('suppression_data', $problem)) { + if (count($problem['suppression_data']) == 1 + && $problem['suppression_data'][0]['maintenanceid'] == 0 + && isEventRecentlyUnsuppressed($problem['acknowledges'], $unsuppression_action)) { + // Show blinking button if the last manual suppression was recently revoked. + $user_unsuppressed = array_key_exists($unsuppression_action['userid'], $data['data']['users']) + ? getUserFullname($data['data']['users'][$unsuppression_action['userid']]) + : _('Inaccessible user'); + + $info_icons[] = (new CSimpleButton()) + ->addClass(ZBX_STYLE_ACTION_ICON_UNSUPPRESS) + ->addClass('blink') + ->setHint(_s('Unsuppressed by: %1$s', $user_unsuppressed)); + } + elseif ($problem['suppression_data']) { + $info_icons[] = makeSuppressedProblemIcon($problem['suppression_data']); + } + elseif (isEventRecentlySuppressed($problem['acknowledges'], $suppression_action)) { + // Show blinking button if suppression was made but is not yet processed by server. + $info_icons[] = makeSuppressedProblemIcon([[ + 'suppress_until' => $suppression_action['suppress_until'], + 'username' => array_key_exists($suppression_action['userid'], $data['data']['users']) + ? getUserFullname($data['data']['users'][$suppression_action['userid']]) + : _('Inaccessible user') + ]], true); + } + } + + $opdata = null; + if ($show_opdata != OPERATIONAL_DATA_SHOW_NONE) { + + // operational data + if ($trigger['opdata'] === '') { + if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) { + $opdata = (new CCol(CScreenProblem::getLatestValues($trigger['items'])))->addClass('latest-values'); + } + } else { + $opdata = CMacrosResolverHelper::resolveTriggerOpdata( + [ + 'triggerid' => $trigger['triggerid'], + 'expression' => $trigger['expression'], + 'opdata' => $trigger['opdata'], + 'clock' => ($problem['r_eventid'] != 0) ? $problem['r_clock'] : $problem['clock'], + 'ns' => ($problem['r_eventid'] != 0) ? $problem['r_ns'] : $problem['ns'] + ], + [ + 'events' => true, + 'html' => true + ] + ); + + if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) { + $opdata = (new CCol($opdata))->addClass('opdata'); + } + } + } + + $problem_link = [ + (new CLinkAction($problem['name'])) + ->setMenuPopup(CMenuPopupHelper::getTrigger($trigger['triggerid'], $problem['eventid'])) + ->setAttribute('aria-label', _xs('%1$s, Severity, %2$s', 'screen reader', + $problem['name'], CSeverityHelper::getName((int) $problem['severity']) + )) + ]; + + if ($show_opdata == OPERATIONAL_DATA_SHOW_WITH_PROBLEM && $opdata) { + $problem_link = array_merge($problem_link, [' (', $opdata, ')']); + } + + $description = (new CCol($problem_link))->addClass(ZBX_STYLE_WORDBREAK); + + $description_style = CSeverityHelper::getStyle((int) $problem['severity']); + + if ($value == TRIGGER_VALUE_TRUE) { + $description->addClass($description_style); + } + + if (!$show_recovery_data + && (($is_acknowledged && $data['config']['problem_ack_style']) + || (!$is_acknowledged && $data['config']['problem_unack_style']))) { + // blinking + $duration = time() - $problem['clock']; + $blink_period = timeUnitToSeconds($data['config']['blink_period']); + + if ($blink_period != 0 && $duration < $blink_period) { + $description + ->addClass('blink') + ->setAttribute('data-time-to-blink', $blink_period - $duration) + ->setAttribute('data-toggle-class', ZBX_STYLE_BLINK_HIDDEN); + } + } + + if ($show_timeline) { + if ($last_clock != 0) { + CScreenProblem::addTimelineBreakpoint($table, $last_clock, $problem['clock'], $data['sortorder']); + } + $last_clock = $problem['clock']; + + $row = [ + $cell_clock->addClass(ZBX_STYLE_TIMELINE_DATE), + (new CCol()) + ->addClass(ZBX_STYLE_TIMELINE_AXIS) + ->addClass(ZBX_STYLE_TIMELINE_DOT), + (new CCol())->addClass(ZBX_STYLE_TIMELINE_TD) + ]; + } + else { + $row = [ + $cell_clock + ->addClass(ZBX_STYLE_NOWRAP) + ->addClass(ZBX_STYLE_RIGHT) + ]; + } + + // Create acknowledge link. + $problem_update_link = ($allowed['add_comments'] || $allowed['change_severity'] || $allowed['acknowledge'] + || $can_be_closed || $allowed['suppress']) + ? (new CLink($is_acknowledged ? _('Yes') : _('No'))) + ->addClass($is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED) + ->addClass(ZBX_STYLE_LINK_ALT) + ->setAttribute('data-eventid', $problem['eventid']) + ->onClick('acknowledgePopUp({eventids: [this.dataset.eventid]}, this);') + : (new CSpan($is_acknowledged ? _('Yes') : _('No')))->addClass( + $is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED + ); + + $table->addRow(array_merge($row, [ + $show_recovery_data ? $cell_r_clock : null, + $show_recovery_data ? $cell_status : null, + makeInformationList($info_icons), + $triggers_hosts[$trigger['triggerid']], + $description, + ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY ) ? $opdata->addClass(ZBX_STYLE_WORDBREAK) : null, + (new CCol( + (new CLinkAction(zbx_date2age($problem['clock'], ($problem['r_eventid'] != 0) ? $problem['r_clock'] : 0))) + ->setAjaxHint(CHintBoxHelper::getEventList($trigger['triggerid'], $eventid, $show_timeline, + $data['fields']['show_tags'], $data['fields']['tags'], $data['fields']['tag_name_format'], + $data['fields']['tag_priority'] + )) + ))->addClass(ZBX_STYLE_NOWRAP), + $problem_update_link, + makeEventActionsIcons($problem['eventid'], $data['data']['actions'], $data['data']['users']), + $data['fields']['show_tags'] ? $data['data']['tags'][$problem['eventid']] : null + ])); +} + +if ($data['info'] !== '') { + $table->setFooter([ + (new CCol($data['info'])) + ->setColSpan($table->getNumCols()) + ->addClass(ZBX_STYLE_LIST_TABLE_FOOTER) + ]); +} + +(new CWidgetView($data)) + ->addItem($table) + ->show(); |