diff --git a/application/controllers/IncidentsController.php b/application/controllers/IncidentsController.php index 13ebb8431..f6ccdbf7a 100644 --- a/application/controllers/IncidentsController.php +++ b/application/controllers/IncidentsController.php @@ -6,11 +6,15 @@ use Icinga\Module\Notifications\Common\Auth; use Icinga\Module\Notifications\Common\Database; +use Icinga\Module\Notifications\Common\Links; use Icinga\Module\Notifications\Hook\ObjectsRendererHook; +use Icinga\Module\Notifications\Model\Contact; use Icinga\Module\Notifications\View\IncidentRenderer; use Icinga\Module\Notifications\Web\Control\SearchBar\ObjectSuggestions; use Icinga\Module\Notifications\Model\Incident; use Icinga\Module\Notifications\Widget\ItemList\ObjectList; +use ipl\Orm\Query; +use ipl\Sql\Expression; use ipl\Stdlib\Filter; use ipl\Web\Compat\CompatController; use ipl\Web\Compat\SearchControls; @@ -20,6 +24,7 @@ use ipl\Web\Layout\MinimalItemLayout; use ipl\Web\Widget\ItemList; use ipl\Web\Widget\ListItem; +use ipl\Web\Widget\Tabs; class IncidentsController extends CompatController { @@ -31,7 +36,7 @@ class IncidentsController extends CompatController public function indexAction(): void { - $this->addTitleTab(t('Incidents')); + $this->getTabs()->activate('incidents'); $incidents = Incident::on(Database::get()) ->with(['object', 'object.source']) @@ -128,4 +133,29 @@ public function getFilter(): Filter\Rule return $this->filter; } + + public function getTabs(): Tabs + { + $tabs = parent::getTabs(); + + $tabs->add('incidents', [ + 'label' => t('Incidents'), + 'url' => $this->getRequest()->getUrl(), + 'baseTarget' => '_main' + ]); + + $contact = Contact::on(Database::get()) + ->columns([new Expression('1')]) + ->filter(Filter::equal('username', $this->Auth()->getUser()->getUsername())) + ->first(); + if ($contact !== null) { + $tabs->add('my-incidents', [ + 'label' => t('My Incidents'), + 'url' => Links::myIncidents(), + 'baseTarget' => '_main' + ]); + } + + return $tabs; + } } diff --git a/application/controllers/MyIncidentsController.php b/application/controllers/MyIncidentsController.php new file mode 100644 index 000000000..259c4a9e5 --- /dev/null +++ b/application/controllers/MyIncidentsController.php @@ -0,0 +1,147 @@ +getTabs()->activate('my-incidents'); + + $incidents = Incident::on(Database::get()) + ->with(['object', 'object.source']) + ->withColumns('object.id_tags') + ->filter(Filter::equal('contact.username', $this->Auth()->getUser()->getUsername())); + + $limitControl = $this->createLimitControl(); + $sortControl = $this->createSortControl( + $incidents, + [ + 'incident.severity desc, incident.started_at' => t('Severity'), + 'incident.started_at desc' => t('Opened On'), + 'incident.recovered_at' => t('Recovered At'), + ] + ); + + $paginationControl = $this->createPaginationControl($incidents); + $searchBar = $this->createSearchBar($incidents, [ + $limitControl->getLimitParam(), + $sortControl->getSortParam(), + ]); + + if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) { + if ($searchBar->hasBeenSubmitted()) { + $filter = QueryString::parse((string) $this->params); + } else { + $this->addControl($searchBar); + $this->sendMultipartUpdate(); + return; + } + } else { + $filter = $searchBar->getFilter(); + } + + $this->applyRestrictions($incidents); + $incidents->filter($filter); + + $this->addControl($paginationControl); + $this->addControl($sortControl); + $this->addControl($limitControl); + $this->addControl($searchBar); + + $incidentList = (new ObjectList($incidents, new IncidentRenderer())) + ->setItemLayoutClass(MinimalItemLayout::class) + ->on(ItemList::ON_ITEM_ADD, function (ListItem $item, Incident $data) { + ObjectsRendererHook::register($data->object); + }) + ->on(ItemList::ON_ASSEMBLED, function () { + ObjectsRendererHook::load(); + }); + + $this->addContent($incidentList); + + if (! $searchBar->hasBeenSubmitted() && $searchBar->hasBeenSent()) { + $this->sendMultipartUpdate(); + } + + $this->setAutorefreshInterval(10); + } + + public function completeAction(): void + { + $suggestions = new ObjectSuggestions(); + $suggestions->setModel(Incident::class); + $suggestions->forRequest($this->getServerRequest()); + $this->getDocument()->add($suggestions); + } + + public function searchEditorAction(): void + { + $editor = $this->createSearchEditor(Incident::on(Database::get()), [ + LimitControl::DEFAULT_LIMIT_PARAM, + SortControl::DEFAULT_SORT_PARAM, + ]); + + $this->getDocument()->add($editor); + $this->setTitle(t('Adjust Filter')); + } + + protected function getPageSize($default) + { + return parent::getPageSize($default ?? 50); + } + + public function getTabs(): Tabs + { + $tabs = parent::getTabs(); + + $tabs->add('incidents', [ + 'label' => t('Incidents'), + 'url' => Links::incidents(), + 'baseTarget' => '_main' + ]); + + $contact = Contact::on(Database::get()) + ->columns([new Expression('1')]) + ->filter(Filter::equal('username', $this->Auth()->getUser()->getUsername())) + ->first(); + if ($contact !== null) { + $tabs->add('my-incidents', [ + 'label' => t('My Incidents'), + 'url' => $this->getRequest()->getUrl(), + 'baseTarget' => '_main' + ]); + } + + return $tabs; + } +} diff --git a/configuration.php b/configuration.php index c81f70444..db0b73d83 100644 --- a/configuration.php +++ b/configuration.php @@ -4,6 +4,8 @@ use Icinga\Application\Modules\Module; use Icinga\Authentication\Auth; +use Icinga\Module\Notifications\Common\Links; +use ipl\Stdlib\Filter; /** @var Module $this */ @@ -21,11 +23,11 @@ $configLandingPage = null; if ($authenticated) { if ($auth->hasPermission('notifications/config/schedules')) { - $configLandingPage = 'notifications/schedules'; + $configLandingPage = Links::schedules()->getAbsoluteUrl(); } elseif ($auth->hasPermission('notifications/config/event-rules')) { - $configLandingPage = 'notifications/event-rules'; + $configLandingPage = Links::eventRules()->getAbsoluteUrl(); } elseif ($auth->hasPermission('notifications/config/contacts')) { - $configLandingPage = 'notifications/contacts'; + $configLandingPage = Links::contacts()->getAbsoluteUrl(); } } @@ -34,7 +36,9 @@ [ 'icon' => 'th-list', 'description' => $this->translate('Open Incidents'), - 'url' => 'notifications/incidents?incident.severity!=ok', + 'url' => Links::incidents() + ->setFilter(Filter::unequal('incident.severity', 'ok')) + ->getAbsoluteUrl(), 'priority' => 10 ] ); @@ -44,7 +48,7 @@ [ 'icon' => 'history', 'description' => $this->translate('Events'), - 'url' => 'notifications/events', + 'url' => Links::events()->getAbsoluteUrl(), 'priority' => 20 ] ); diff --git a/library/Notifications/Common/Links.php b/library/Notifications/Common/Links.php index d816d8966..31ba2bec7 100644 --- a/library/Notifications/Common/Links.php +++ b/library/Notifications/Common/Links.php @@ -26,9 +26,9 @@ public static function events(): Url return Url::fromPath('notifications/events'); } - public static function incidents(): Url + public static function myIncidents(): Url { - return Url::fromPath('notifications/incidents'); + return Url::fromPath('notifications/my-incidents'); } public static function incident(int $id): Url @@ -36,6 +36,11 @@ public static function incident(int $id): Url return Url::fromPath('notifications/incident', ['id' => $id]); } + public static function incidents(): Url + { + return Url::fromPath('notifications/incidents'); + } + public static function contacts(): Url { return Url::fromPath('notifications/contacts');