diff options
Diffstat (limited to '')
26 files changed, 2162 insertions, 0 deletions
diff --git a/application/controllers/CommentsController.php b/application/controllers/CommentsController.php new file mode 100644 index 0000000..a371c7b --- /dev/null +++ b/application/controllers/CommentsController.php @@ -0,0 +1,17 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Controllers; + +use Icinga\Module\Eventdb\EventdbController; + +class CommentsController extends EventdbController +{ + /** + * @deprecated Moved to eventdb/events/details + */ + public function newAction() + { + $this->redirectNow($this->getRequest()->getUrl()->setPath('eventdb/events/details')); + } +} diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php new file mode 100644 index 0000000..d812918 --- /dev/null +++ b/application/controllers/ConfigController.php @@ -0,0 +1,45 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Controllers; + +use Icinga\Module\Eventdb\Forms\Config\BackendConfigForm; +use Icinga\Module\Eventdb\Forms\Config\GlobalConfigForm; +use Icinga\Module\Eventdb\Forms\Config\MonitoringConfigForm; +use Icinga\Web\Controller; + +class ConfigController extends Controller +{ + public function init() + { + $this->assertPermission('config/modules'); + parent::init(); + } + + public function indexAction() + { + $backendConfig = new BackendConfigForm(); + $backendConfig + ->setIniConfig($this->Config()) + ->handleRequest(); + $this->view->backendConfig = $backendConfig; + + $globalConfig = new GlobalConfigForm(); + $globalConfig + ->setIniConfig($this->Config()) + ->handleRequest(); + $this->view->globalConfig = $globalConfig; + + $this->view->tabs = $this->Module()->getConfigTabs()->activate('config'); + } + + public function monitoringAction() + { + $monitoringConfig = new MonitoringConfigForm(); + $monitoringConfig + ->setIniConfig($this->Config()) + ->handleRequest(); + $this->view->form = $monitoringConfig; + $this->view->tabs = $this->Module()->getConfigTabs()->activate('monitoring'); + } +} diff --git a/application/controllers/EventController.php b/application/controllers/EventController.php new file mode 100644 index 0000000..f6a323c --- /dev/null +++ b/application/controllers/EventController.php @@ -0,0 +1,216 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Controllers; + +use Icinga\Data\Filter\Filter; +use Icinga\Exception\NotFoundError; +use Icinga\Module\Eventdb\Event; +use Icinga\Module\Eventdb\EventdbController; +use Icinga\Module\Eventdb\Forms\Event\EventCommentForm; +use Icinga\Module\Eventdb\Hook\DetailviewExtensionHook; +use Icinga\Module\Eventdb\Web\EventdbOutputFormat; +use Icinga\Web\Hook; +use Icinga\Web\Url; + +class EventController extends EventdbController +{ + public function indexAction() + { + $eventId = $this->params->getRequired('id'); + + $url = Url::fromRequest(); + + $this->getTabs()->add('event', array( + 'active' => ! $this->isFormatRequest(), + 'title' => $this->translate('Event'), + 'url' => $url->without(array('format')) + ))->extend(new EventdbOutputFormat(array(), array(EventdbOutputFormat::TYPE_TEXT))); + + $columnConfig = $this->Config('columns'); + if (! $columnConfig->isEmpty()) { + $additionalColumns = $columnConfig->keys(); + } else { + $additionalColumns = array(); + } + + $event = $this->getDb() + ->select() + ->from('event'); + + $columns = array_merge($event->getColumns(), $additionalColumns); + + $event->from('event', $columns); + $event->where('id', $eventId); + + $event->applyFilter(Filter::matchAny(array_map( + '\Icinga\Data\Filter\Filter::fromQueryString', + $this->getRestrictions('eventdb/events/filter', 'eventdb/events') + ))); + + $eventData = $event->fetchRow(); + if (! $eventData) { + throw new NotFoundError('Could not find event with id %d', $eventId); + } + + $eventObj = Event::fromData($eventData); + + $groupedEvents = null; + if ($this->getDb()->hasCorrelatorExtensions()) { + $group_leader = (int) $eventObj->group_leader; + if ($group_leader > 0) { + // redirect to group leader + $this->redirectNow(Url::fromPath('eventdb/event', array('id' => $group_leader))); + } + + if ($group_leader === -1) { + // load grouped events, if any + $groupedEvents = $this->getDb() + ->select() + ->from('event') + ->where('group_leader', $eventObj->id) + ->order('ack', 'ASC') + ->order('created', 'DESC'); + } + } + + $comments = null; + $commentForm = null; + if ($this->hasPermission('eventdb/comments')) { + $comments = $this->getDb() + ->select() + ->from('comment', array( + 'id', + 'type', + 'message', + 'created', + 'modified', + 'user' + )) + ->where('event_id', $eventId) + ->order('created', 'DESC'); + + if ($this->hasPermission('eventdb/interact')) { + $commentForm = new EventCommentForm(); + $commentForm + ->setDb($this->getDb()) + ->setFilter(Filter::expression('id', '=', $eventId)); + } + } + + $format = $this->params->get('format'); + if ($format === 'sql') { + $this->sendSqlSummary(array($event, $comments, $groupedEvents)); + } elseif ($this->isApiRequest()) { + $data = new \stdClass; + $data->event = $eventData; + if ($comments !== null) { + $data->comments = $comments; + } + if ($groupedEvents !== null) { + $data->groupedEvents = $groupedEvents; + } + $this->sendJson($data); + } elseif ($this->isTextRequest()) { + $this->view->event = $eventObj; + $this->view->columnConfig = $columnConfig; + $this->view->additionalColumns = $additionalColumns; + $this->view->groupedEvents = $groupedEvents; + $this->view->comments = $comments; + + $this->sendText(null, 'event/index-plain'); + } else { + if ($commentForm !== null) { + $commentForm->handleRequest(); + } + + $this->view->event = $eventObj; + $this->view->columnConfig = $columnConfig; + $this->view->additionalColumns = $additionalColumns; + $this->view->groupedEvents = $groupedEvents; + $this->view->comments = $comments; + $this->view->commentForm = $commentForm; + + $this->view->extensionsHtml = array(); + foreach (Hook::all('Eventdb\DetailviewExtension') as $hook) { + /** @var DetailviewExtensionHook $hook */ + $module = $this->view->escape($hook->getModule()->getName()); + $this->view->extensionsHtml[] = + '<div class="icinga-module module-' . $module . '" data-icinga-module="' . $module . '">' + . $hook->setView($this->view)->getHtmlForEvent($eventObj) + . '</div>'; + } + } + } + + /** + * @deprecated redirects to index view now + */ + public function commentsAction() + { + $this->redirectNow( + Url::fromPath( + 'eventdb/event', + array('id' => $this->params->getRequired('id')) + ) + ); + } + + /** + * Action allowing you to be forwarded to host in Icinga monitoring + * + * **But** case insensitive! + */ + public function hostAction() + { + $host = $this->params->getRequired('host'); + + $backend = $this->monitoringBackend(); + + $query = $backend->select() + ->from('hoststatus', array('host_name')) + ->where('host', $host); + + $realHostname = $query->fetchOne(); + + if ($realHostname !== null && $realHostname !== false) { + $this->redirectNow(Url::fromPath('monitoring/host/services', array('host' => $realHostname))); + } else { + throw new NotFoundError('Could not find a hostname matching: %s', $host); + } + } + + /** + * Action allowing you to be forwarded to host in Icinga monitoring + * + * **But** case insensitive! + */ + public function serviceAction() + { + $host = $this->params->getRequired('host'); + $service = $this->params->getRequired('service'); + + $backend = $this->monitoringBackend(); + + $query = $backend->select() + ->from('servicestatus', array('host_name', 'service')) + ->where('host', $host) + ->where('service', $service); + + $realService = $query->fetchRow(); + + if ($realService !== null && $realService !== false) { + $this->redirectNow( + Url::fromPath( + 'monitoring/service/show', + array( + 'host' => $realService->host_name, + 'service' => $realService->service + ) + ) + ); + } else { + throw new NotFoundError('Could not find a service "%s" for host "%s"', $service, $host); + } + } +} diff --git a/application/controllers/EventsController.php b/application/controllers/EventsController.php new file mode 100644 index 0000000..09e5a8d --- /dev/null +++ b/application/controllers/EventsController.php @@ -0,0 +1,186 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Controllers; + +use Icinga\Data\Filter\Filter; +use Icinga\Module\Eventdb\EventdbController; +use Icinga\Module\Eventdb\Forms\Event\EventCommentForm; +use Icinga\Module\Eventdb\Forms\Events\AckFilterForm; +use Icinga\Module\Eventdb\Forms\Events\SeverityFilterForm; +use Icinga\Module\Eventdb\Hook\DetailviewExtensionHook; +use Icinga\Module\Eventdb\Web\EventdbOutputFormat; +use Icinga\Util\StringHelper; +use Icinga\Web\Hook; +use Icinga\Web\Url; + +class EventsController extends EventdbController +{ + public function init() + { + parent::init(); + $this->view->title = 'EventDB: ' . $this->translate('Events'); + } + + public function indexAction() + { + $this->assertPermission('eventdb/events'); + + $this->getTabs()->add('events', array( + 'active' => ! $this->isFormatRequest(), + 'title' => $this->translate('Events'), + 'url' => Url::fromRequest()->without(array('format')) + ))->extend(new EventdbOutputFormat(array(), array(EventdbOutputFormat::TYPE_TEXT))); + + $columnConfig = $this->Config('columns'); + if ($this->params->has('columns')) { + $additionalColumns = StringHelper::trimSplit($this->params->get('columns')); + } elseif (! $columnConfig->isEmpty()) { + $additionalColumns = $columnConfig->keys(); + } else { + $additionalColumns = array(); + } + + $events = $this->getDb()->select() + ->from('event'); + + $columns = array_merge($events->getColumns(), $additionalColumns); + $events->columns($columns); + + $events->applyFilter(Filter::matchAny(array_map( + '\Icinga\Data\Filter\Filter::fromQueryString', + $this->getRestrictions('eventdb/events/filter', 'eventdb/events') + ))); + + $this->getDb()->filterGroups($events); + + $this->setupPaginationControl($events); + + $this->setupFilterControl( + $events, + array( + 'host_name' => $this->translate('Host'), + 'host_address' => $this->translate('Host Address'), + 'type' => $this->translate('Type'), + 'program' => $this->translate('Program'), + 'facility' => $this->translate('Facility'), + 'priority' => $this->translate('Priority'), + 'message' => $this->translate('Message'), + 'ack' => $this->translate('Acknowledged'), + 'created' => $this->translate('Created') + ), + array('host_name'), + array('columns', 'format') + ); + + $this->setupLimitControl(); + + $this->setupSortControl( + array( + 'host_name' => $this->translate('Host'), + 'host_address' => $this->translate('Host Address'), + 'type' => $this->translate('Type'), + 'program' => $this->translate('Program'), + 'facility' => $this->translate('Facility'), + 'priority' => $this->translate('Priority'), + 'message' => $this->translate('Message'), + 'ack' => $this->translate('Acknowledged'), + 'created' => $this->translate('Created') + ), + $events, + array('created' => 'desc') + ); + + if ($this->view->compact) { + $events->peekAhead(); + } + + if ($this->params->get('format') === 'sql') { + $this->sendSqlSummary($events); + } elseif ($this->isApiRequest()) { + $data = new \stdClass; + $data->events = $events->fetchAll(); + $this->sendJson($data); + exit; + } elseif ($this->isTextRequest()) { + $this->view->columnConfig = $this->Config('columns'); + $this->view->additionalColumns = $additionalColumns; + $this->view->events = $events; + + $this->sendText(null, 'events/index-plain'); + } else { + $this->setAutorefreshInterval(15); + + $severityFilterForm = new SeverityFilterForm(); + $severityFilterForm->handleRequest(); + + $ackFilterForm = new AckFilterForm(); + $ackFilterForm->handleRequest(); + + $this->view->ackFilterForm = $ackFilterForm; + $this->view->columnConfig = $this->Config('columns'); + $this->view->additionalColumns = $additionalColumns; + $this->view->events = $events; + $this->view->severityFilterForm = $severityFilterForm; + } + } + + public function detailsAction() + { + $this->assertPermission('eventdb/events'); + + $url = Url::fromRequest()->without(array('format')); + + $this->getTabs()->add('events', array( + 'active' => ! $this->isFormatRequest(), + 'title' => $this->translate('Events'), + 'url' => $url + ))->extend(new EventdbOutputFormat(array(), array(EventdbOutputFormat::TYPE_TEXT))); + + $events = $this->getDb() + ->select() + ->from('event'); + + $this->getDb()->filterGroups($events); + + $filter = Filter::fromQueryString($url->getQueryString()); + $events->applyFilter($filter); + + $events->applyFilter(Filter::matchAny(array_map( + '\Icinga\Data\Filter\Filter::fromQueryString', + $this->getRestrictions('eventdb/events/filter', 'eventdb/events') + ))); + + if ($this->isApiRequest()) { + $this->sendJson($events->fetchAll()); + } elseif ($this->isTextRequest()) { + $this->view->events = $events->fetchAll(); + $this->view->columnConfig = $this->Config('columns'); + + $this->sendText(null, 'events/details-plain'); + } else { + $commentForm = null; + if ($this->hasPermission('eventdb/interact')) { + $commentForm = new EventCommentForm(); + $commentForm + ->setDb($this->getDb()) + ->setFilter($filter) + ->handleRequest(); + $this->view->commentForm = $commentForm; + } + + $this->view->events = $events->fetchAll(); + $this->view->columnConfig = $this->Config('columns'); + + $this->view->extensionsHtml = array(); + foreach (Hook::all('Eventdb\DetailviewExtension') as $hook) { + /** @var DetailviewExtensionHook $hook */ + $module = $this->view->escape($hook->getModule()->getName()); + $this->view->extensionsHtml[] = + '<div class="icinga-module module-' . $module . '" data-icinga-module="' . $module . '">' + . $hook->setView($this->view)->getHtmlForEvents($this->view->events) + . '</div>'; + } + } + } +} diff --git a/application/controllers/IndexController.php b/application/controllers/IndexController.php new file mode 100644 index 0000000..5322936 --- /dev/null +++ b/application/controllers/IndexController.php @@ -0,0 +1,14 @@ +<?php +/* Icinga Web 2 | (c) 2018 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Controllers; + +use Icinga\Web\Controller; + +class IndexController extends Controller +{ + public function indexAction() + { + $this->redirectNow('eventdb/events'); + } +} diff --git a/application/forms/Config/BackendConfigForm.php b/application/forms/Config/BackendConfigForm.php new file mode 100644 index 0000000..a9c85c1 --- /dev/null +++ b/application/forms/Config/BackendConfigForm.php @@ -0,0 +1,112 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Config; + +use Exception; +use Icinga\Data\ResourceFactory; +use Icinga\Forms\ConfigForm; + +/** + * Form for managing the connection to the EventDB backend + */ +class BackendConfigForm extends ConfigForm +{ + /** + * {@inheritdoc} + */ + public function init() + { + $this->setSubmitLabel($this->translate('Save')); + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $resources = array(); + foreach (ResourceFactory::getResourceConfigs() as $name => $config) { + if ($config->type === 'db') { + $resources[] = $name; + } + } + + $this->addElement( + 'select', + 'backend_resource', + array( + 'description' => $this->translate('The resource to use'), + 'label' => $this->translate('Resource'), + 'multiOptions' => array_combine($resources, $resources), + 'required' => true + ) + ); + + if (isset($formData['skip_validation']) && $formData['skip_validation']) { + $this->addSkipValidationCheckbox(); + } + } + + /** + * Return whether the given values are valid + * + * @param array $formData The data to validate + * + * @return bool + */ + public function isValid($formData) + { + if (! parent::isValid($formData)) { + return false; + } + + if (($el = $this->getElement('skip_validation')) === null || ! $el->isChecked()) { + $resourceConfig = ResourceFactory::getResourceConfig($this->getValue('backend_resource')); + + if (! $this->isValidEventDbSchema($resourceConfig)) { + if ($el === null) { + $this->addSkipValidationCheckbox(); + } + + return false; + } + } + + return true; + } + + public function isValidEventDbSchema($resourceConfig) + { + try { + $db = ResourceFactory::createResource($resourceConfig); + $db->select()->from('event', array('id'))->fetchOne(); + } catch (Exception $_) { + $this->error($this->translate( + 'Cannot find the EventDB schema. Please verify that the given database ' + . 'contains the schema and that the configured user has access to it.' + )); + return false; + } + return true; + } + + /** + * Add a checkbox to the form by which the user can skip the schema validation + */ + protected function addSkipValidationCheckbox() + { + $this->addElement( + 'checkbox', + 'skip_validation', + array( + 'description' => $this->translate( + 'Check this to not to validate the EventDB schema of the chosen resource' + ), + 'ignore' => true, + 'label' => $this->translate('Skip Validation'), + 'order' => 0 + ) + ); + } +} diff --git a/application/forms/Config/GlobalConfigForm.php b/application/forms/Config/GlobalConfigForm.php new file mode 100644 index 0000000..5b4bf2a --- /dev/null +++ b/application/forms/Config/GlobalConfigForm.php @@ -0,0 +1,32 @@ +<?php +/* Icinga Web 2 - EventDB | (c) 2018 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Config; + +use Icinga\Forms\ConfigForm; + +class GlobalConfigForm extends ConfigForm +{ + /** + * {@inheritdoc} + */ + public function init() + { + $this->setSubmitLabel($this->translate('Save')); + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'global_default_filter', + array( + 'description' => $this->translate('Filter to be used by the menu link for EventDB by default'), + 'label' => $this->translate('Default Filter') + ) + ); + } +} diff --git a/application/forms/Config/MonitoringConfigForm.php b/application/forms/Config/MonitoringConfigForm.php new file mode 100644 index 0000000..e1c7638 --- /dev/null +++ b/application/forms/Config/MonitoringConfigForm.php @@ -0,0 +1,72 @@ +<?php +/* Icinga Web 2 - EventDB | (c) 2017 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Config; + +use Icinga\Forms\ConfigForm; + +/** + * Form for managing settings for the integration into monitoring module + */ +class MonitoringConfigForm extends ConfigForm +{ + /** + * {@inheritdoc} + */ + public function init() + { + $this->setSubmitLabel($this->translate('Save')); + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $this->addElement( + 'text', + 'monitoring_custom_var', + array( + 'description' => $this->translate('Name of the custom variable to enable EventDB integration for (usually "edb")'), + 'label' => $this->translate('Custom Variable') + ) + ); + + $this->addElement( + 'checkbox', + 'monitoring_always_on_host', + array( + 'description' => $this->translate('Always enable the integration on hosts, even when the custom variable is not set'), + 'label' => $this->translate('Always enable for hosts') + ) + ); + + $this->addElement( + 'checkbox', + 'monitoring_always_on_service', + array( + 'description' => $this->translate('Always enable the integration on services, even when the custom variable is not set'), + 'label' => $this->translate('Always enable for services') + ) + ); + + $this->addElement( + 'checkbox', + 'monitoring_detailview_disable', + array( + 'description' => $this->translate('Disable the detail view inside the monitoring module'), + 'label' => $this->translate('Disable the detail view') + ) + ); + + $this->addElement( + 'text', + 'monitoring_detailview_filter', + array( + 'description' => $this->translate('Filter events in the detail view area inside the monitoring module'), + 'label' => $this->translate('Filter the detail view'), + 'value' => 'ack=0', // Also see DetailviewExtension + ) + ); + } +} diff --git a/application/forms/Event/EventCommentForm.php b/application/forms/Event/EventCommentForm.php new file mode 100644 index 0000000..130910c --- /dev/null +++ b/application/forms/Event/EventCommentForm.php @@ -0,0 +1,144 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Event; + +use Exception; +use Icinga\Data\Filter\Filter; +use Icinga\Module\Eventdb\Eventdb; +use Icinga\Web\Form; + +/** + * Form for managing the connection to the EventDB backend + */ +class EventCommentForm extends Form +{ + /** + * @var Eventdb + */ + protected $db; + + protected $filter; + + protected static $types = array( + 'comment', + 'ack', + 'revoke' + ); + + /** + * {@inheritdoc} + */ + public static $defaultElementDecorators = array( + array('ViewHelper', array('separator' => '')), + array('Errors', array('separator' => '')), + ); + + /** + * {@inheritdoc} + */ + public function init() + { + $this->setSubmitLabel($this->translate('Submit')); + } + + public function setDb(Eventdb $db) + { + $this->db = $db; + return $this; + } + + public function setFilter(Filter $filter) + { + $this->filter = $filter; + return $this; + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $this->addElement( + 'select', + 'type', + array( + 'label' => $this->translate('Type'), + 'multiOptions' => array( + 0 => $this->translate('Comment'), + 1 => $this->translate('Acknowledge'), + 2 => $this->translate('Revoke') + ), + 'required' => true, + 'value' => 1, + ) + ); + $this->addElement( + 'text', + 'comment', + array( + 'label' => $this->translate('Comment'), + 'required' => true + ) + ); + } + + public function onSuccess() + { + $type = $this->getValue('type'); + $comment = $this->getValue('comment'); + $username = $this->Auth()->getUser()->getUsername(); + + $events = $this->db->select()->from('event', array('id'))->applyFilter($this->filter); + + $dbAdapter = $this->db->getDataSource()->getDbAdapter(); + + $dbAdapter->beginTransaction(); + try { + foreach ($events as $event) { + $this->db->insert('comment', array( + 'event_id' => $event->id, + 'type' => $type, + 'message' => $comment, + 'created' => date(Eventdb::DATETIME_FORMAT), + 'modified' => date(Eventdb::DATETIME_FORMAT), + 'user' => $username + )); + + if ($type !== '0') { + $ackFilter = Filter::expression('id', '=', $event->id); + if ($this->db->hasCorrelatorExtensions()) { + $ackFilter = Filter::matchAny($ackFilter, Filter::where('group_leader', $event->id)); + } + $this->db->update('event', array( + 'ack' => $type === '1' ? 1 : 0 + ), $ackFilter); + } + } + $dbAdapter->commit(); + return true; + } catch (Exception $e) { + $dbAdapter->rollback(); + $this->error($e->getMessage()); + return false; + } + } + + /** + * {@inheritdoc} + */ + public function loadDefaultDecorators() + { + parent::loadDefaultDecorators(); + + $this->removeDecorator('FormHints'); + } + + public function addSubmitButton() + { + parent::addSubmitButton(); + + $btn = $this->getElement('btn_submit'); + $btn->removeDecorator('HtmlTag'); + } +} diff --git a/application/forms/Events/AckFilterForm.php b/application/forms/Events/AckFilterForm.php new file mode 100644 index 0000000..829c6ce --- /dev/null +++ b/application/forms/Events/AckFilterForm.php @@ -0,0 +1,80 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Events; + +use Icinga\Data\Filter\Filter; +use Icinga\Web\Form; + +class AckFilterForm extends Form +{ + /** + * {@inheritdoc} + */ + public function init() + { + $this->setAttrib('class', 'inline ack-filter-form'); + } + + /** + * {@inheritdoc} + */ + public function addSubmitButton() + { + if ((bool) $this->getRequest()->getUrl()->getParams()->get('ack', true)) { + $icon = 'ok'; + $title = $this->translate('Hide acknowledged events'); + } else { + $icon = 'cancel'; + $title = $this->translate('Show also acknowledged events'); + } + + $this->addElements(array( + array( + 'button', + 'btn_submit', + array( + 'class' => 'link-button spinner', + 'decorators' => array( + 'ViewHelper', + array('HtmlTag', array('tag' => 'div', 'class' => 'control-group form-controls')) + ), + 'escape' => false, + 'ignore' => true, + 'label' => $this->getView()->icon($icon) . $this->translate('Ack'), + 'type' => 'submit', + 'title' => $title, + 'value' => $this->translate('Ack') + ) + ) + )); + + return $this; + } + + public function onSuccess() + { + $redirect = clone $this->getRequest()->getUrl(); + $params = $redirect->getParams(); + $modifyFilter = $params->shift('modifyFilter'); + $columns = $params->shift('columns'); + if (! (bool) $this->getRequest()->getUrl()->getParams()->get('ack', true)) { + $params->remove('ack'); + } else { + $redirect->setQueryString( + Filter::fromQueryString($redirect->getQueryString()) + ->andFilter(Filter::expression('ack', '=', 0)) + ->toQueryString() + ); + } + $params = $redirect->getParams(); + if ($modifyFilter) { + $params->add('modifyFilter'); + } + if ($columns) { + $params->add('columns', $columns); + } + $this->setRedirectUrl($redirect); + return true; + } +} diff --git a/application/forms/Events/SeverityFilterForm.php b/application/forms/Events/SeverityFilterForm.php new file mode 100644 index 0000000..bd1ec5e --- /dev/null +++ b/application/forms/Events/SeverityFilterForm.php @@ -0,0 +1,224 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Eventdb\Forms\Events; + +use Icinga\Data\Filter\Filter; +use Icinga\Data\Filter\FilterAnd; +use Icinga\Data\Filter\FilterChain; +use Icinga\Data\Filter\FilterExpression; +use Icinga\Data\Filter\FilterMatch; +use Icinga\Module\Eventdb\Event; +use Icinga\Web\Form; + +class SeverityFilterForm extends Form +{ + protected $includedPriorities; + protected $excludedPriorities; + + /** + * @var FilterChain + */ + protected $filter; + + /** + * @var array + */ + protected $filterEditorParams = array('modifyFilter', 'addFilter'); + + /** + * {@inheritdoc} + */ + public function init() + { + $this->setAttrib('class', 'inline severity-filter-form'); + } + + protected function findPriorities(Filter $filter, $sign, &$target) + { + if ($filter->isEmpty()) { + return; + } + + if ($filter->isChain()) { + /** @var FilterChain $filter */ + foreach ($filter->filters() as $part) { + /** @var Filter $part */ + if (! $part->isEmpty() && $part->isExpression()) { + /** @var FilterMatch $part */ + if (strtolower($part->getColumn()) === 'priority' && $part->getSign() === $sign) { + $expression = $part->getExpression(); + if (is_array($expression)) { + foreach ($expression as $priority) { + $target[(int) $priority] = $part; + } + } else { + $target[(int) $expression] = $part; + } + } + } else { + /** @var FilterChain $part */ + foreach ($part->filters() as $or) { + /** @var FilterExpression $or */ + if (strtolower($or->getColumn()) === 'priority' && $or->getSign() === $sign) { + $expression = $or->getExpression(); + if (is_array($expression)) { + foreach ($expression as $priority) { + $target[(int) $priority] = $or; + } + } else { + $target[(int) $expression] = $or; + } + } + } + } + } + } else { + /** @var FilterMatch $filter */ + if (strtolower($filter->getColumn()) === 'priority' && $filter->getSign() === $sign) { + $expression = $filter->getExpression(); + if (is_array($expression)) { + foreach ($expression as $priority) { + $target[(int) $priority] = $filter; + } + } else { + $target[(int) $expression] = $filter; + } + } + } + } + + /** + * {@inheritdoc} + */ + public function createElements(array $formData) + { + $includedPriorities = array(); + $excludedPriorities = array(); + $params = $this->getRequest()->getUrl()->getParams() + ->without($this->filterEditorParams) + ->without('columns') + ->without('page'); + + $filter = Filter::fromQueryString((string) $params); + + $this->findPriorities($filter, '=', $includedPriorities); + $this->findPriorities($filter, '!=', $excludedPriorities); + + foreach (Event::$priorities as $id => $priority) { + $class = $priority; + if ( + (empty($includedPriorities) or isset($includedPriorities[$id])) + && ! isset($excludedPriorities[$id]) + ) { + $class .= ' active'; + $title = $this->translate('Filter out %s'); + } else { + $title = $this->translate('Filter in %s'); + } + + $label = ucfirst(substr($priority, 0, 1)); + if ($id === 3) { + $label .= substr($priority, 1, 1); + } + $this->addElement( + 'submit', + $priority, + array( + 'class' => $class, + 'label' => $label, + 'title' => sprintf($title, ucfirst($priority)), + ) + ); + } + + $this->includedPriorities = $includedPriorities; + $this->excludedPriorities = $excludedPriorities; + + $this->filter = $filter; + } + + public function onSuccess() + { + $postData = $this->getRequest()->getPost(); + unset($postData['formUID']); + unset($postData['CSRFToken']); + reset($postData); + $priority = Event::getPriorityId(key($postData)); + $redirect = clone $this->getRequest()->getUrl(); + + // convert inclusion to exclusion + if (! empty($this->includedPriorities)) { + if (empty($this->excludedPriorities)) { + $this->excludedPriorities = array(); + } + // set exclusion with for all not included values + foreach (array_keys(Event::$priorities) as $id) { + if (! isset($this->includedPriorities[$id]) + && ! isset($this->excludedPriorities[$id]) + ) { + $this->excludedPriorities[$id] = true; + } + } + // purge from inclusions from filter + if ($this->filter instanceof FilterChain) { + foreach ($this->includedPriorities as $filter) { + if ($filter instanceof Filter) { + /** @var Filter $filter */ + $this->filter = $this->filter->removeId($filter->getId()); + } + } + } + } + + if ($this->filter instanceof FilterChain) { + // purge existing exclusions from a complex filter + foreach ($this->excludedPriorities as $filter) { + if ($filter instanceof Filter) { + /** @var Filter $filter */ + $this->filter = $this->filter->removeId($filter->getId()); + } + } + } elseif (! empty($this->excludedPriorities)) { + // empty the filter - because it only was a simple exclusion + $this->filter = new FilterAnd; + } + + // toggle exclusion + if (isset($this->excludedPriorities[$priority])) { + // in exclusion: just remove + unset($this->excludedPriorities[$priority]); + } else { + // not set: add to exclusion + $this->excludedPriorities[$priority] = true; + } + + $priorityFilter = Filter::matchAll(); + foreach (array_keys($this->excludedPriorities) as $id) { + $priorityFilter->andFilter(Filter::expression('priority', '!=', $id)); + } + + if ($this->filter->isEmpty()) { + // set the Filter + $this->filter = $priorityFilter; + } else { + // append our filter to the rest of the existing Filter + $this->filter = $this->filter->andFilter($priorityFilter); + } + + $redirect->setQueryString($this->filter->toQueryString()); + + $requestParams = $this->getRequest()->getUrl()->getParams(); + $redirectParams = $redirect->getParams(); + foreach ($this->filterEditorParams as $filterEditorParam) { + if ($requestParams->has($filterEditorParam)) { + $redirectParams->add($filterEditorParam); + } + } + if ($requestParams->has('columns')) { + $redirectParams->add('columns', $this->getRequest()->getUrl()->getParam('columns')); + } + $this->setRedirectUrl($redirect); + return true; + } +} diff --git a/application/locale/de_DE/LC_MESSAGES/eventdb.mo b/application/locale/de_DE/LC_MESSAGES/eventdb.mo Binary files differnew file mode 100644 index 0000000..0bcec3c --- /dev/null +++ b/application/locale/de_DE/LC_MESSAGES/eventdb.mo diff --git a/application/locale/de_DE/LC_MESSAGES/eventdb.po b/application/locale/de_DE/LC_MESSAGES/eventdb.po new file mode 100644 index 0000000..29b432a --- /dev/null +++ b/application/locale/de_DE/LC_MESSAGES/eventdb.po @@ -0,0 +1,413 @@ +# Icinga Web 2 - Head for multiple monitoring backends. +# Copyright (C) 2018 Icinga Development Team +# This file is distributed under the same license as Eventdb Module. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Eventdb Module (1.1.0)\n" +"Report-Msgid-Bugs-To: dev@icinga.com\n" +"POT-Creation-Date: 2018-01-25 14:31+0000\n" +"PO-Revision-Date: 2018-01-25 15:32+0100\n" +"Last-Translator: Markus Frosch <markus.frosch@icinga.com>\n" +"Language: de_DE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Basepath: .\n" +"Language-Team: \n" +"X-Generator: Poedit 2.0.5\n" +"X-Poedit-SearchPath-0: .\n" + +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:15 +#, php-format +msgctxt "Multi-selection count" +msgid "%s row(s) selected" +msgstr "%s Zeilen ausgewählt" + +#: ../../../../modules/eventdb/application/forms/Events/AckFilterForm.php:44 +#: ../../../../modules/eventdb/application/forms/Events/AckFilterForm.php:47 +msgid "Ack" +msgstr "Bestätigt" + +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:69 +msgid "Acknowledge" +msgstr "Bestätigen" + +#: ../../../../modules/eventdb/application/views/helpers/Column.php:23 +#: ../../../../modules/eventdb/application/views/scripts/events/index-plain.phtml:10 +#: ../../../../modules/eventdb/application/views/scripts/events/details-plain.phtml:9 +#: ../../../../modules/eventdb/application/views/scripts/events/details.phtml:24 +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:72 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:18 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:51 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:27 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:161 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:69 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:87 +msgid "Acknowledged" +msgstr "Bestätigt" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:9 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:9 +msgid "Acknowledgement" +msgstr "Bestätigung" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:60 +msgid "Actions" +msgstr "Aktionen" + +#: ../../../../modules/eventdb/application/views/scripts/events/details.phtml:41 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:118 +msgid "Add comment / acknowledge" +msgstr "Kommentar / Bestätigung hinzufügen" + +#: ../../../../modules/eventdb/library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php:151 +msgid "All events for host" +msgstr "Alle Ereignisse für Host" + +#: ../../../../modules/eventdb/configuration.php:40 +msgid "Allow to acknowledge and comment events" +msgstr "Erlauben Ereignisse zu Bestätigen und zu Kommentieren" + +#: ../../../../modules/eventdb/configuration.php:35 +msgid "Allow to view comments" +msgstr "Erlauben Kommentare zu sehen" + +#: ../../../../modules/eventdb/configuration.php:30 +msgid "Allow to view events" +msgstr "Erlauben Ereignisse zu sehen" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:40 +msgid "Always enable for hosts" +msgstr "Immer für Hosts aktivieren" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:49 +msgid "Always enable for services" +msgstr "Immer für Services aktivieren" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:39 +msgid "" +"Always enable the integration on hosts, even when the custom variable is not " +"set" +msgstr "" +"Immer bei Interaktionen mit Hosts anzeigen, auch wenn die angepasste " +"Variable nicht gesetzt ist" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:48 +msgid "" +"Always enable the integration on services, even when the custom variable is " +"not set" +msgstr "" +"Immer bei Interaktionen mit Services anzeigen, auch wenn die angepasste " +"Variable nicht gesetzt ist" + +#: ../../../../modules/eventdb/application/views/scripts/events/details.phtml:44 +msgid "At least one event is set to auto-clear." +msgstr "Mindestens ein Ereignis ist für automatische Bestätigung gesetzt." + +#: ../../../../modules/eventdb/application/views/scripts/events/details.phtml:25 +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:73 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:28 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:162 +msgid "Auto-Clear" +msgstr "Automatische Bestätigung" + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:86 +msgid "" +"Cannot find the EventDB schema. Please verify that the given database " +"contains the schema and that the configured user has access to it." +msgstr "" +"Kann das EventDB-Schema nicht finden. Bitte stellen Sie sicher, dass die " +"angegebene Datenbankverbindung das Schema enthält und dass der konfigurierte " +"Benutzer Zugriff darauf hat." + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:104 +msgid "Check this to not to validate the EventDB schema of the chosen resource" +msgstr "" +"Häkchen setzen um das EventDB Schema der gewählten Ressource nicht zu " +"überprüfen." + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:8 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:8 +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:68 +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:80 +msgid "Comment" +msgstr "Kommentar" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:28 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:128 +msgid "Comments" +msgstr "Kommentare" + +#: ../../../../modules/eventdb/configuration.php:19 +msgid "Config" +msgstr "Konfiguration" + +#: ../../../../modules/eventdb/configuration.php:18 +#, fuzzy +msgid "Configure EventDB" +msgstr "EventDB Datenbankverbindung einrichten" + +#: ../../../../modules/eventdb/configuration.php:23 +#: ../../../../modules/eventdb/application/views/scripts/config/monitoring.phtml:5 +msgid "Configure integration into the monitoring module" +msgstr "Interaktionen im Monitoring Modul" + +#: ../../../../modules/eventdb/application/views/scripts/config/index.phtml:19 +msgid "Configure module" +msgstr "Modul konfigurieren" + +#: ../../../../modules/eventdb/application/views/scripts/config/index.phtml:7 +msgid "Create a New Resource" +msgstr "Neue Ressource erstellen" + +#: ../../../../modules/eventdb/application/views/scripts/config/index.phtml:14 +msgid "Create a new resource" +msgstr "Neue Ressource erstellen" + +#: ../../../../modules/eventdb/application/controllers/EventsController.php:70 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:88 +msgid "Created" +msgstr "Erstellt" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:31 +msgid "Custom Variable" +msgstr "Angepasste Variable" + +#: ../../../../modules/eventdb/application/views/scripts/config/index.phtml:5 +#, fuzzy +msgid "Database backend" +msgstr "EventDB Datenbankverbindung einrichten" + +#: ../../../../modules/eventdb/application/forms/Config/GlobalConfigForm.php:28 +msgid "Default Filter" +msgstr "Standard Filter" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:36 +msgid "Details" +msgstr "Details" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:58 +msgid "Disable the detail view" +msgstr "Detailansicht deaktivieren" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:57 +msgid "Disable the detail view inside the monitoring module" +msgstr "Die Detailansicht innerhalb des Monitoring Moduls deaktivieren" + +#: ../../../../modules/eventdb/application/controllers/EventController.php:26 +msgid "Event" +msgstr "Ereignis" + +#: ../../../../modules/eventdb/application/controllers/EventsController.php:22 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:31 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:136 +msgid "Events" +msgstr "Ereignisse" + +# Spezifische Syslog Bezeichnung +#: ../../../../modules/eventdb/application/controllers/EventsController.php:66 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:84 +msgid "Facility" +msgstr "Facility" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:66 +msgid "Filter events in the detail view area inside the monitoring module" +msgstr "Ereignisse der Detailansicht im Monitoring Modul filtern" + +#: ../../../../modules/eventdb/application/forms/Events/SeverityFilterForm.php:117 +#, php-format +msgid "Filter in %s" +msgstr "Filtern nach %s" + +#: ../../../../modules/eventdb/application/forms/Events/SeverityFilterForm.php:115 +#, php-format +msgid "Filter out %s" +msgstr "Filtern ohne %s" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:67 +msgid "Filter the detail view" +msgstr "Detailansicht filtern" + +#: ../../../../modules/eventdb/application/forms/Config/GlobalConfigForm.php:27 +msgid "Filter to be used by the menu link for EventDB by default" +msgstr "Filter für die URL des Menü Eintrages der EventDB" + +#: ../../../../modules/eventdb/library/Eventdb/ProvidedHook/Monitoring/EventdbActionHook.php:134 +msgid "Filtered events" +msgstr "Gefilterte Ereignisse" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:42 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:147 +msgid "Grouped Events" +msgstr "Gruppierte Ereignisse" + +#: ../../../../modules/eventdb/application/forms/Events/AckFilterForm.php:26 +msgid "Hide acknowledged events" +msgstr "Bestätigte Ereignisse verstecken" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:65 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:62 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:80 +msgid "Host" +msgstr "Host" + +#: ../../../../modules/eventdb/application/controllers/EventsController.php:63 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:81 +msgid "Host Address" +msgstr "Host Adresse" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:105 +msgid "Host service status" +msgstr "Host Service Status" + +#: ../../../../modules/eventdb/library/Eventdb/ProvidedHook/Monitoring/DetailviewExtension.php:66 +msgid "Loading" +msgstr "Lade" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:35 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:50 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:68 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:86 +msgid "Message" +msgstr "Meldung" + +#: ../../../../modules/eventdb/configuration.php:24 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:102 +msgid "Monitoring" +msgstr "Monitoring" + +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:30 +msgid "" +"Name of the custom variable to enable EventDB integration for (usually \"edb" +"\")" +msgstr "" +"Name der angepassten Variable um die EventDB Integration zu aktivieren " +"(normalerweise \"edb\")" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:130 +msgid "No comments recorded for this event yet." +msgstr "Keine Kommentare für dieses Ereignis." + +#: ../../../../modules/eventdb/application/views/scripts/events/index-plain.phtml:3 +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:33 +msgid "No events recorded yet." +msgstr "Keine Ereignisse gespeichert." + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:63 +msgid "Other events for" +msgstr "Andere Ereignisse für" + +#: ../../../../modules/eventdb/application/views/scripts/events/details.phtml:45 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:122 +msgid "Please only acknowledge manually, if you know what that means." +msgstr "Bitte nur manuell Bestätigen wenn Sie wissen was das bedeutet." + +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:6 +msgctxt "Multi-selection help" +msgid "" +"Press and hold the Ctrl key while clicking on rows to select multiple rows " +"or press and hold the Shift key to select a range of rows" +msgstr "" +"Drücken und halten Sie STRG während Sie auf Spalten klicken, um mehrere " +"auszuwählen. Mit der Umschalttaste können Sie Bereiche von Spalten auswählen" + +#: ../../../../modules/eventdb/application/views/scripts/events/index-plain.phtml:9 +#: ../../../../modules/eventdb/application/views/scripts/events/details-plain.phtml:8 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:17 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:50 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:67 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:85 +msgid "Priority" +msgstr "Priorität" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:75 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:65 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:83 +msgid "Program" +msgstr "Programm" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:86 +msgid "Program and Host" +msgstr "Programm und Host" + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:40 +msgid "Resource" +msgstr "Ressource" + +#: ../../../../modules/eventdb/configuration.php:45 +msgid "Restrict views to the events that match the filter" +msgstr "Ereignisse mit einem Filter einschränken" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:10 +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:10 +msgid "Revocation" +msgstr "Widerruf" + +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:70 +msgid "Revoke" +msgstr "Wiederrufen" + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:20 +#: ../../../../modules/eventdb/application/forms/Config/MonitoringConfigForm.php:18 +#: ../../../../modules/eventdb/application/forms/Config/GlobalConfigForm.php:15 +msgid "Save" +msgstr "Speichern" + +#: ../../../../modules/eventdb/application/views/scripts/events/index.phtml:84 +msgid "Show More" +msgstr "Mehr zeigen" + +#: ../../../../modules/eventdb/application/forms/Events/AckFilterForm.php:29 +msgid "Show also acknowledged events" +msgstr "Auch bestätigte Ereignisse anzeigen" + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:107 +msgid "Skip Validation" +msgstr "Überprüfung überspringen" + +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:42 +msgid "Submit" +msgstr "Absenden" + +#: ../../../../modules/eventdb/library/Eventdb/Web/EventdbOutputFormat.php:49 +msgid "Text" +msgstr "Text" + +#: ../../../../modules/eventdb/application/forms/Config/BackendConfigForm.php:39 +msgid "The resource to use" +msgstr "Die zu benutzenden Ressource" + +#: ../../../../modules/eventdb/application/views/scripts/event/index.phtml:121 +msgid "This event is set to auto-clear." +msgstr "Das Ereignis ist auf automatische Bestätigung gesetzt." + +#: ../../../../modules/eventdb/application/views/scripts/events/index-plain.phtml:7 +#: ../../../../modules/eventdb/application/views/scripts/events/details-plain.phtml:6 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:15 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:48 +msgid "Timestamp" +msgstr "Zeitstempel" + +#: ../../../../modules/eventdb/application/views/scripts/events/index-plain.phtml:12 +#: ../../../../modules/eventdb/application/views/scripts/events/details-plain.phtml:11 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:20 +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:53 +#: ../../../../modules/eventdb/application/forms/Event/EventCommentForm.php:66 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:64 +#: ../../../../modules/eventdb/application/controllers/EventsController.php:82 +msgid "Type" +msgstr "Typ" + +#: ../../../../modules/eventdb/application/views/scripts/event/index-plain.phtml:33 +msgid "User" +msgstr "Benutzername" + +#: ../../../../modules/eventdb/library/Eventdb/Eventdb.php:141 +msgid "You need to configure a resource to access the EventDB database first" +msgstr "Sie müssen zuerst die Datenbank der EventDB konfigurieren" + +#~ msgid "Backend" +#~ msgstr "Datenbank" diff --git a/application/views/helpers/Column.php b/application/views/helpers/Column.php new file mode 100644 index 0000000..b343de4 --- /dev/null +++ b/application/views/helpers/Column.php @@ -0,0 +1,51 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +use Icinga\Module\Eventdb\Event; + +class Zend_View_Helper_Column extends Zend_View_Helper_Abstract +{ + public function column($column, Event $event, $classes = array()) + { + switch ($column) { + case 'host_name': + $default = 'host_url'; + break; + case 'message': + $default = 'message'; + break; + default: + $default = null; + break; + } + + if ($column === 'ack') { + $html = $event->$column ? $this->view->icon('ok', $this->view->translate('Acknowledged')) : '-'; + } else { + $renderer = $this->view->columnConfig->get($column, 'renderer', $default); + + switch ($renderer) { + case 'host_url': + $html = $this->view->qlink($event->$column, 'eventdb/event/host', + array('host' => $event->$column)); + break; + case 'service_url': + $html = $this->view->qlink($event->$column, 'eventdb/event/service', + array('service' => $event->$column, 'host' => $event->host_name)); + break; + case 'url': + $html = $this->view->qlink($event->$column, $event->$column); + break; + case 'message': + $html = $this->view->eventMessage($event->$column); + break; + default: + $html = $this->view->escape($event->$column); + break; + } + } + + return '<td class="' . 'event-' . $this->view->escape($column) . ' ' + . implode(' ', $classes) . '" data-base-target="_next">' . $html . '</td>'; + } +} diff --git a/application/views/helpers/ColumnHeader.php b/application/views/helpers/ColumnHeader.php new file mode 100644 index 0000000..3c7f7cd --- /dev/null +++ b/application/views/helpers/ColumnHeader.php @@ -0,0 +1,17 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +class Zend_View_Helper_ColumnHeader extends Zend_View_Helper_Abstract +{ + public function columnHeader($columnHeader, $classes = array(), $plain = false) + { + $header = $this->view->columnConfig->get($columnHeader, 'label', ucwords(str_replace('_', ' ', $columnHeader))); + if ($plain) { + return $header; + } + $htm = '<th classes="' . implode(' ', $classes) . '">'; + $htm .= $this->view->escape($header); + $htm .= '</th>'; + return $htm; + } +} diff --git a/application/views/helpers/Event.php b/application/views/helpers/Event.php new file mode 100644 index 0000000..f61a793 --- /dev/null +++ b/application/views/helpers/Event.php @@ -0,0 +1,12 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +use Icinga\Module\Eventdb\Event; + +class Zend_View_Helper_Event extends Zend_View_Helper_Abstract +{ + public function event($data) + { + return Event::fromData($data); + } +} diff --git a/application/views/helpers/EventMessage.php b/application/views/helpers/EventMessage.php new file mode 100644 index 0000000..de52518 --- /dev/null +++ b/application/views/helpers/EventMessage.php @@ -0,0 +1,70 @@ +<?php +/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */ + +use Icinga\Application\Config; + +class Zend_View_Helper_EventMessage extends Zend_View_Helper_Abstract +{ + /** + * The RegExp for locating URLs. + * + * Modifications: + * - Don't allow ; in + * + * @source https://mathiasbynens.be/demo/url-regex + */ + const URL_REGEX = '@(https?)://(-\.)?([^\s/?\.#-]+\.?)+(/[^\s;]*)?@i'; + + /** + * Purifier instance + * + * @var HTMLPurifier + */ + protected static $purifier; + + public function eventMessage($message) + { + $htm = $this->getPurifier()->purify($message); + + // search for URLs and make them a link + $htm = preg_replace_callback( + static::URL_REGEX, + function ($match) { + return sprintf( + '<a href="%s" target="_blank">%s</a>', + htmlspecialchars($match[0]), + htmlspecialchars($match[0]) + ); + }, + $htm + ); + + return $htm; + } + + /** + * Get the purifier instance + * + * @return HTMLPurifier + */ + protected function getPurifier() + { + if (self::$purifier === null) { + require_once 'HTMLPurifier/Bootstrap.php'; + require_once 'HTMLPurifier.php'; + require_once 'HTMLPurifier.autoload.php'; + + $config = HTMLPurifier_Config::createDefault(); + $config->set('Core.EscapeNonASCIICharacters', true); + $config->set('HTML.Allowed', Config::module('eventdb')->get( + 'frontend', + 'allowed_html', + 'p,br,b,a[href|target],i,table,tr,td[colspan],div,*[class]' + )); + $config->set('Attr.AllowedFrameTargets', array('_blank')); + $config->set('Cache.DefinitionImpl', null); + self::$purifier = new HTMLPurifier($config); + } + return self::$purifier; + } +} diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml new file mode 100644 index 0000000..2c47663 --- /dev/null +++ b/application/views/scripts/config/index.phtml @@ -0,0 +1,21 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <h2><?= $this->translate('Database backend') ?></h2> + <?= $this->qlink( + $this->translate('Create a New Resource'), + 'config/createresource', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new resource'), + ) + ) ?> + <?= $backendConfig ?> + + <h2><?= $this->translate('Configure module') ?></h2> + <?= $globalConfig ?> +</div> diff --git a/application/views/scripts/config/monitoring.phtml b/application/views/scripts/config/monitoring.phtml new file mode 100644 index 0000000..1f6bbde --- /dev/null +++ b/application/views/scripts/config/monitoring.phtml @@ -0,0 +1,7 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <h2><?= $this->translate('Configure integration into the monitoring module') ?></h2> + <?= $form ?> +</div> diff --git a/application/views/scripts/event/index-plain.phtml b/application/views/scripts/event/index-plain.phtml new file mode 100644 index 0000000..5b6ea8d --- /dev/null +++ b/application/views/scripts/event/index-plain.phtml @@ -0,0 +1,62 @@ +<?php +/** @var \Icinga\Module\Eventdb\Event $event */ +/** @var array $additionalColumns */ +/** @var \Icinga\Repository\RepositoryQuery $comments */ +/** @var \Icinga\Repository\RepositoryQuery $groupedEvents */ + +$commentTypes = array( + $this->translate('Comment'), + $this->translate('Acknowledgement'), + $this->translate('Revocation'), +); + +$displayColumns = array_merge(array('program', 'message', 'facility'), $additionalColumns); +?> +<?= $this->translate('Timestamp') ?>: <?= $event->created ?> + +<?= $this->translate('Priority') ?>: <?= strtoupper($event->getPriority()) ?> +<?= $event->ack ? sprintf(' (%s)', $this->translate('Acknowledged')) : '' ?> + +<?= $this->translate('Type') ?>: <?= $event->getType() ?> + +<?php foreach ($displayColumns as $col): ?> +<?= $this->columnHeader($col, null, true) ?>: <?= htmlspecialchars($event->offsetGet($col)) ?> + +<?php endforeach ?> + +<?php if ($comments->hasResult()): ?> +[ <?= $this->translate('Comments') ?> ] + +<?php foreach ($comments as $comment): ?> +<?= $commentTypes[$comment->type] ?>: <?= $comment->created ?> + +<?= $this->translate('User') ?>: <?= $comment->user ?> + +<?= $this->translate('Message') ?>: <?= $comment->message ?> + + +<?php endforeach ?> + +<?php endif; ?> +<?php if ($groupedEvents !== null && $groupedEvents->hasResult()): ?> +[ <?= $this->translate('Grouped Events') ?> ] + +<?php foreach ($groupedEvents as $groupedEventData): + /** @var \Icinga\Module\Eventdb\Event $groupedEvent */ + $groupedEvent = $this->event($groupedEventData); +?> +<?= $this->translate('Timestamp') ?>: <?= $event->created ?> + +<?= $this->translate('Priority') ?>: <?= strtoupper($event->getPriority()) ?> +<?= $event->ack ? sprintf(' (%s)', $this->translate('Acknowledged')) : '' ?> + +<?= $this->translate('Type') ?>: <?= $event->getType() ?> + +<?php foreach (array('host_name', 'program', 'message') as $col): ?> +<?= $this->columnHeader($col, null, true) ?>: <?= htmlspecialchars($event->offsetGet($col)) ?> + +<?php endforeach ?> + +<?php endforeach ?> +<?php endif; ?> + diff --git a/application/views/scripts/event/index.phtml b/application/views/scripts/event/index.phtml new file mode 100644 index 0000000..83dcf01 --- /dev/null +++ b/application/views/scripts/event/index.phtml @@ -0,0 +1,174 @@ +<?php +/** @var \Icinga\Module\Eventdb\Event $event */ +/** @var array $additionalColumns */ +/** @var \Icinga\Repository\RepositoryQuery $comments */ +/** @var \Icinga\Repository\RepositoryQuery $groupedEvents */ + +$commentIcons = array( + $this->icon('comment', $this->translate('Comment')), + $this->icon('ok', $this->translate('Acknowledgement')), + $this->icon('cancel', $this->translate('Revocation')) +); + +if (! $this->compact): ?> +<div class="controls"> + <?= $this->tabs ?> +</div> +<?php endif ?> +<div class="content"> + <table class="event-summary-table"> + <tr> + <td rowspan="2" class="priority-col <?= $event->getPriority() ?> <?= $event->ack ? 'ack' : '' ?>"> + <div class="priority-label"><?= strtoupper($event->getPriority()) ?></div> + <div class="event-meta"><span class="timeago" title="<?= $event->created ?>"><?= $this->timeAgo(strtotime($event->created)) ?></span></div> + </td> + <td rowspan="2" class="icon-col"> + <?= $this->icon($event->getTypeIcon(), $event->getType()) ?> + <?php if ($event->ack) { echo $this->icon('ok', $this->translate('Acknowledged')); } ?> + <?php if ($event->group_autoclear) { echo $this->icon('reschedule', $this->translate('Auto-Clear')); } ?> + </td> + <?= $this->column('host_name', $event, array('selectable')) ?> + </tr> + <tr> + <?= $this->column('host_address', $event, array('selectable')) ?> + </tr> + </table> + <h2><?= $this->translate('Details') ?></h2> + <table class="name-value-table"> + <?php + $displayColumns = array_merge(array('program', 'message', 'facility'), $additionalColumns); + foreach ($displayColumns as $column): + if ($column === 'message') continue; + ?> + <tr> + <?= $this->columnHeader($column) ?> + <?= $this->column($column, $event) ?> + </tr> + <?php endforeach ?> + </table> + <?php if ($event->message): ?> + <h2><?= $this->translate('Message') ?></h2> + <div class="event-message detail preformatted"><?= $this->eventMessage($event->message) ?></div> + <?php endif; ?> + + <?php + foreach ($extensionsHtml as $extensionHtml) { + echo $extensionHtml; + } + ?> + + <h2><?= $this->translate('Actions') ?></h2> + <table class="name-value-table" data-base-target="_next"> + <tr> + <th><?= $this->translate('Other events for') ?></th> + <td><?= $this->qlink( + $this->translate('Host'), + 'eventdb/events', + array('host_name' => $event->host_name), + array( + 'icon' => 'search', + 'class' => 'action-link' + ) + ) ?> + <?php if ($event->program): ?> + <?= $this->qlink( + $this->translate('Program'), + 'eventdb/events', + array( + 'program' => $event->program, + ), + array( + 'icon' => 'search', + 'class' => 'action-link' + ) + ) ?> + <?= $this->qlink( + $this->translate('Program and Host'), + 'eventdb/events', + array( + 'host_name' => $event->host_name, + 'program' => $event->program, + ), + array( + 'icon' => 'search', + 'class' => 'action-link' + ) + ) ?> + <?php endif; ?> + </td> + </tr> + <tr> + <tr> + <th><?= $this->translate('Monitoring') ?></th> + <td> + <?= $this->qlink( + $this->translate('Host service status'), + 'eventdb/event/host', + array('host' => $event->host_name), + array( + 'icon' => 'search', + 'class' => 'action-link' + ) + ) ?> + </td> + </tr> + </table> + + <?php if (isset($commentForm)): ?> + <h2><?= $this->translate('Add comment / acknowledge') ?></h2> + <?php if ($event->group_autoclear): ?> + <div class="warning"> + <?= $this->translate('This event is set to auto-clear.') ?> + <?= $this->translate('Please only acknowledge manually, if you know what that means.') ?> + </div> + <?php endif; ?> + <div class="comment-form"><?= $commentForm ?></div> + <?php endif ?> + + <h2><?= $this->translate('Comments') ?></h2> + <?php if (! $comments->hasResult()): ?> + <p><?= $this->translate('No comments recorded for this event yet.') ?></p> + <?php else: ?> + <table class="common-table comments-table"> + <tbody> + <?php foreach ($comments as $comment): ?> + <tr> + <td class="comment-created timeago" title="<?= $comment->created ?>"><?= $this->timeAgo(strtotime($comment->created)) ?></td> + <td class="comment-type"><?= $commentIcons[$comment->type] ?></td> + <td class="comment-user"><?= $this->escape($comment->user) ?></td> + <td class="comment-message"><?= $this->escape($comment->message) ?></td> + </tr> + <?php endforeach ?> + </tbody> + </table> + <?php endif; ?> + + <?php if ($groupedEvents !== null && $groupedEvents->hasResult()): ?> + <h2><?= $this->translate('Grouped Events') ?></h2> + <table class="common-table events-table" data-base-target="_next"> + <tbody> + <?php foreach ($groupedEvents as $groupedEventData): + /** @var \Icinga\Module\Eventdb\Event $groupedEvent */ + $groupedEvent = $this->event($groupedEventData); + ?> + <tr> + <td class="priority-col <?= $groupedEvent->getPriority() ?> <?= $groupedEvent->ack ? 'ack' : '' ?>"> + <div class="priority-label"><?= strtoupper($groupedEvent->getPriority()) ?></div> + <div class="event-meta"><span class="timeago" title="<?= $groupedEvent->created ?>"><?= $this->timeAgo(strtotime($groupedEvent->created)) ?></span></div> + </td> + <td class="icon-col"> + <?= $this->icon($groupedEvent->getTypeIcon(), $groupedEvent->getType()) ?> + <?php if ($groupedEvent->ack) { echo $this->icon('ok', $this->translate('Acknowledged')); } ?> + <?php if ($groupedEvent->group_autoclear) { $autoClear = true; echo $this->icon('reschedule', $this->translate('Auto-Clear')); } ?> + </td> + <?= $this->column('host_name', $groupedEvent) ?> + <?= $this->column('program', $groupedEvent) ?> + <?= $this->column('message', $groupedEvent) ?> + </tr> + <?php endforeach ?> + </tbody> + </table> + <?php endif; ?> + +</div> + diff --git a/application/views/scripts/events/details-plain.phtml b/application/views/scripts/events/details-plain.phtml new file mode 100644 index 0000000..d5eb724 --- /dev/null +++ b/application/views/scripts/events/details-plain.phtml @@ -0,0 +1,18 @@ +<?php foreach($events as $eventData): + /** @var \Icinga\Module\Eventdb\Event $event */ + $event = $this->event($eventData); + $url = $this->url('eventdb/event', array('id' => $event->id)); +?> +<?= $this->translate('Timestamp') ?>: <?= $event->created ?> + +<?= $this->translate('Priority') ?>: <?= strtoupper($event->getPriority()) ?> +<?= $event->ack ? sprintf(' (%s)', $this->translate('Acknowledged')) : '' ?> + +<?= $this->translate('Type') ?>: <?= $event->getType() ?> + +<?php foreach (array('host_name', 'program', 'message') as $col): ?> +<?= $this->columnHeader($col, null, true) ?>: <?= htmlspecialchars($event->offsetGet($col)) ?> + +<?php endforeach ?> + +<?php endforeach ?> diff --git a/application/views/scripts/events/details.phtml b/application/views/scripts/events/details.phtml new file mode 100644 index 0000000..ee9f3cd --- /dev/null +++ b/application/views/scripts/events/details.phtml @@ -0,0 +1,50 @@ +<?php +/** @var array $events */ + +if (! $this->compact): +?> +<div class="controls"> + <?= $this->tabs ?> +</div> +<?php endif ?> +<div class="content"> + <table class="common-table event-summary-table table-row-selectable" data-base-target="_next"> + <?php $autoClear = false; foreach($events as $eventData): + /** @var \Icinga\Module\Eventdb\Event $event */ + $event = $this->event($eventData); + $url = $this->url('eventdb/event', array('id' => $event->id)); + ?> + <tr href="<?= $url ?>"> + <td class="priority-col <?= $event->getPriority() ?> <?= $event->ack ? 'ack' : '' ?>"> + <div class="priority-label"><?= strtoupper($event->getPriority()) ?></div> + <div class="event-meta"><span class="timeago" title="<?= $event->created ?>"><?= $this->timeAgo(strtotime($event->created)) ?></span></div> + </td> + <td class="icon-col"> + <?= $this->icon($event->getTypeIcon(), $event->getType()) ?> + <?php if ($event->ack) { echo $this->icon('ok', $this->translate('Acknowledged')); } ?> + <?php if ($event->group_autoclear) { $autoClear = true; echo $this->icon('reschedule', $this->translate('Auto-Clear')); } ?> + </td> + <?= $this->column('host_name', $event) ?> + <?= $this->column('program', $event) ?> + <?= $this->column('message', $event) ?> + </tr> + <?php endforeach; ?> + </table> + + <?php + foreach ($extensionsHtml as $extensionHtml) { + echo $extensionHtml; + } + ?> + + <?php if (isset($commentForm)): ?> + <h3><?= $this->translate('Add comment / acknowledge') ?></h3> + <?php if ($autoClear): ?> + <div class="warning"> + <?= $this->translate('At least one event is set to auto-clear.') ?> + <?= $this->translate('Please only acknowledge manually, if you know what that means.') ?> + </div> + <?php endif; ?> + <div class="comment-form"><?= $commentForm ?></div> + <?php endif ?> +</div> diff --git a/application/views/scripts/events/index-plain.phtml b/application/views/scripts/events/index-plain.phtml new file mode 100644 index 0000000..55f4c2e --- /dev/null +++ b/application/views/scripts/events/index-plain.phtml @@ -0,0 +1,19 @@ +<?php /** @var \Icinga\Repository\RepositoryQuery $events */ +if (! $events->hasResult()): ?> +<?= $this->translate('No events recorded yet.') ?> +<?php else: +$displayColumns = array_merge(array('host_name', 'program', 'message', 'facility'), $additionalColumns); +foreach ($events as $eventData): /** @var \Icinga\Module\Eventdb\Event $event */ $event = $this->event($eventData); ?> +<?= $this->translate('Timestamp') ?>: <?= $event->created ?> + +<?= $this->translate('Priority') ?>: <?= strtoupper($event->getPriority()) ?> +<?= $event->ack ? sprintf(' (%s)', $this->translate('Acknowledged')) : '' ?> + +<?= $this->translate('Type') ?>: <?= $event->getType() ?> + +<?php foreach ($displayColumns as $col): ?> +<?= $this->columnHeader($col, null, true) ?>: <?= htmlspecialchars($event->offsetGet($col)) ?> + +<?php endforeach ?> + +<?php endforeach; endif; ?> diff --git a/application/views/scripts/events/index.phtml b/application/views/scripts/events/index.phtml new file mode 100644 index 0000000..f1e4da7 --- /dev/null +++ b/application/views/scripts/events/index.phtml @@ -0,0 +1,93 @@ +<?php if (! $this->compact): ?> +<div class="controls"> + <?= $this->tabs ?> + <?php + $helpMessage = $this->translate( + 'Press and hold the Ctrl key while clicking on rows to select multiple rows or press and hold the Shift key to' + . ' select a range of rows', + 'Multi-selection help' + ); + ?> + <div class="selection-info" title="<?= $this->escape($helpMessage) ?>"> + <?= sprintf( + /// TRANSLATORS: Please leave %s as it is because the selection counter is wrapped in a span tag for updating + /// the counter via JavaScript + $this->translate('%s row(s) selected', 'Multi-selection count'), + '<span class="selection-info-count">0</span>' + ) ?> + </div> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + <?= $this->sortBox ?> + </div> + <?= $this->filterEditor ?> + <div class="quick-filter-controls"> + <?= $this->severityFilterForm ?> + <?= $this->ackFilterForm ?> + </div> +</div> +<?php endif ?> +<div class="content"> +<?php /** @var \Icinga\Repository\RepositoryQuery $events */if (! $events->hasResult()): ?> + <p><?= $this->translate('No events recorded yet.') ?></p> +</div> +<?php return; endif; $displayColumns = array_merge(array('host_name', 'program', 'message', 'facility'), $additionalColumns); ?> + <table class="common-table table-row-selectable multiselect table-responsive events-table" + data-base-target="_next" + data-icinga-multiselect-url="<?= $this->href('eventdb/events/details') ?>" + data-icinga-multiselect-controllers="<?= $this->href('eventdb/events') ?>" + data-icinga-multiselect-data="id"> + <?php if (! $this->compact): ?> + <thead> + <tr> + <th></th> + <th></th> + <?php foreach ($displayColumns as $displayColumn): ?> + <?= $this->columnHeader($displayColumn) ?> + <?php endforeach ?> + </tr> + </thead> + <?php endif; ?> + <tbody> + <?php + foreach ($events as $eventData): + /** @var \Icinga\Module\Eventdb\Event $event */ + $event = $this->event($eventData); + $created = $event->created; + $createdTs = strtotime($created); + $url = $this->url('eventdb/event', array('id' => $event->id)); + $classes = array('priority-col', $event->getPriority()); + if ($event->ack) { + $classes[] = 'ack'; + } + ?> + <tr href="<?= $url ?>"> + <td class="<?= implode(' ', $classes) ?>"> + <div class="priority-label"><?= strtoupper($event->getPriority()) ?></div> + <div class="event-meta"><a href="<?= $url ?>" class="timeago" title="<?= $created ?>"><?= $this->timeAgo($createdTs) ?></a></div> + </td> + <td class="icon-col"> + <?= $this->icon($event->getTypeIcon(), $event->getType()) ?> + <?php if ($event->ack) { echo $this->icon('ok', $this->translate('Acknowledged')); } ?> + <?php if ($event->group_autoclear) { echo $this->icon('reschedule', $this->translate('Auto-Clear')); } ?> + </td> + <?php foreach ($displayColumns as $displayColumn): ?> + <?= $this->column($displayColumn, $event) ?> + <?php endforeach ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php if ($this->compact && $events->hasMore()): ?> + <?= $this->qlink( + $this->translate('Show More'), + $this->url()->without(array('view', 'limit')), + null, + array( + 'data-base-target' => '_next', + 'class' => 'action-link' + ) + ) ?> +<?php endif; ?> +</div> diff --git a/application/views/scripts/format/text.phtml b/application/views/scripts/format/text.phtml new file mode 100644 index 0000000..647914b --- /dev/null +++ b/application/views/scripts/format/text.phtml @@ -0,0 +1,13 @@ +<?php +/** @var string $text */ +/** @var string|null $partial */ +if (! $this->compact): ?> +<div class="controls"><?= $this->tabs ?></div> +<?php endif ?> +<div class="content"> +<?php if ($partial !== null): ?> + <pre class="copyable"><?= $this->partial($partial . '.phtml', null, $this) ?></pre> +<?php else: ?> + <pre class="copyable"><?= htmlspecialchars($text) ?></pre> +<?php endif ?> +</div> |