From 39e364e9b43eba84409d1f8a73236faee1377122 Mon Sep 17 00:00:00 2001 From: raviks789 Date: Wed, 20 Mar 2024 12:25:57 +0100 Subject: [PATCH] WIP --- library/Notifications/Common/BaseItemList.php | 7 +- .../Hook/EventsObjectsInfoHook.php | 88 +++++++++++++++++++ library/Notifications/Model/Event.php | 10 +++ library/Notifications/Model/Objects.php | 4 + library/Notifications/Model/Source.php | 5 ++ .../Widget/Detail/EventDetail.php | 40 ++++----- .../Widget/ItemList/EventList.php | 37 ++++++++ .../Widget/ItemList/EventListItem.php | 6 +- public/css/detail/event-detail.less | 14 +++ 9 files changed, 183 insertions(+), 28 deletions(-) create mode 100644 library/Notifications/Hook/EventsObjectsInfoHook.php create mode 100644 public/css/detail/event-detail.less diff --git a/library/Notifications/Common/BaseItemList.php b/library/Notifications/Common/BaseItemList.php index f261730f5..4113f8624 100644 --- a/library/Notifications/Common/BaseItemList.php +++ b/library/Notifications/Common/BaseItemList.php @@ -13,6 +13,10 @@ abstract class BaseItemList extends BaseHtmlElement { use BaseFilter; + public const ON_ITEM_ADD = 'item-added'; + + public const BEFORE_ITEM_ADD = 'before-item-added'; + protected $baseAttributes = [ 'class' => 'item-list', 'data-base-target' => '_next', @@ -64,8 +68,9 @@ protected function assemble() foreach ($this->data as $data) { /** @var BaseListItem $item */ $item = new $itemClass($data, $this); - + $this->emit(self::BEFORE_ITEM_ADD, [$item, $data]); $this->add($item); + $this->emit(self::ON_ITEM_ADD, [$item, $data]); } if ($this->isEmpty()) { diff --git a/library/Notifications/Hook/EventsObjectsInfoHook.php b/library/Notifications/Hook/EventsObjectsInfoHook.php new file mode 100644 index 000000000..11457182a --- /dev/null +++ b/library/Notifications/Hook/EventsObjectsInfoHook.php @@ -0,0 +1,88 @@ +> $objectIdTags + * + * @return array + */ + abstract public function renderObjectDisplayNames(array $objectIdTags): array; + + /** + * Get the source of the objects + * + * @return string + */ + abstract public function getSource(): string; + + /** + * Get the object list item widget for the given object ID tag + * + * @param array $objectIdTag + * + * @return ValidHtml + */ + abstract public function getHtmlForObject(array $objectIdTag): ValidHtml; + + /** + * Get object display names for the objects using the object ID tags + * + * @param array>> $objectIdTags + * + * @return array + */ + final public static function getObjectsDisplayNames(array $objectIdTags): array + { + $objectDisplayNames = []; + foreach (Hook::all('Notifications\\EventsObjectsInfo') as $hook) { + /** @var self $hook */ + try { + $objectDisplayNames = array_merge( + $objectDisplayNames, + $hook->renderObjectDisplayNames($objectIdTags[$hook->getSource()]) + ); + } catch (Exception $e) { + Logger::error('Failed to load hook %s:', get_class($hook), $e); + } + } + + return $objectDisplayNames; + } + + /** + * Get the object list item widget for the object using the object ID tag + * + * @param string $source + * @param array $objectIdTag + * + * @return ?ValidHtml + */ + final public static function getObjectListItemWidget(string $source, array $objectIdTag): ?ValidHtml + { + $objectListItemWidget = null; + foreach (Hook::all('Notifications\\EventsObjectsInfo') as $hook) { + /** @var self $hook */ + try { + if ($source === $hook->getSource()) { + $objectListItemWidget = $hook->getHtmlForObject($objectIdTag); + } + } catch (Exception $e) { + Logger::error('Failed to load hook %s:', get_class($hook), $e); + } + } + + return $objectListItemWidget; + } +} diff --git a/library/Notifications/Model/Event.php b/library/Notifications/Model/Event.php index 827845276..ee688c72a 100644 --- a/library/Notifications/Model/Event.php +++ b/library/Notifications/Model/Event.php @@ -5,6 +5,7 @@ namespace Icinga\Module\Notifications\Model; use Icinga\Module\Notifications\Common\Database; +use DateTime; use ipl\Orm\Behavior\Binary; use ipl\Orm\Behavior\MillisecondTimestamp; use ipl\Orm\Behaviors; @@ -14,6 +15,15 @@ use ipl\Sql\Connection; use ipl\Sql\Select; +/** + * @property int $id + * @property DateTime $time + * @property string $object_id + * @property string $type + * @property string $severity + * @property string $message + * @property string $username + */ class Event extends Model { public function getTableName() diff --git a/library/Notifications/Model/Objects.php b/library/Notifications/Model/Objects.php index 61ff187ed..23c47b595 100644 --- a/library/Notifications/Model/Objects.php +++ b/library/Notifications/Model/Objects.php @@ -13,6 +13,10 @@ use ipl\Orm\Relations; /** + * @property string $id + * @property int $source_id + * @property string $name + * @property string $url * @property array $id_tags */ class Objects extends Model diff --git a/library/Notifications/Model/Source.php b/library/Notifications/Model/Source.php index 8ddb08579..117c8eae7 100644 --- a/library/Notifications/Model/Source.php +++ b/library/Notifications/Model/Source.php @@ -9,6 +9,11 @@ use ipl\Web\Widget\IcingaIcon; use ipl\Web\Widget\Icon; +/** + * @property int $id + * @property string $type + * @property string $name + */ class Source extends Model { public function getTableName() diff --git a/library/Notifications/Widget/Detail/EventDetail.php b/library/Notifications/Widget/Detail/EventDetail.php index b96275e0a..35f6be765 100644 --- a/library/Notifications/Widget/Detail/EventDetail.php +++ b/library/Notifications/Widget/Detail/EventDetail.php @@ -5,13 +5,16 @@ namespace Icinga\Module\Notifications\Widget\Detail; use Icinga\Date\DateFormatter; +use Icinga\Module\Notifications\Hook\EventsObjectsInfoHook; use Icinga\Module\Notifications\Model\Event; use Icinga\Module\Notifications\Model\Objects; +use Icinga\Module\Notifications\Model\Source; use Icinga\Module\Notifications\Widget\EventSourceBadge; use Icinga\Module\Notifications\Widget\ItemList\IncidentList; use ipl\Html\BaseHtmlElement; use ipl\Html\Html; use ipl\Html\ValidHtml; +use ipl\Web\Url; use ipl\Web\Widget\HorizontalKeyValue; use ipl\Web\Widget\Link; use ipl\Web\Widget\StateBall; @@ -70,37 +73,24 @@ protected function createMessage(): array /** @return ValidHtml[] */ protected function createRelatedObject(): array { - //TODO(sd): This is just placeholder. Add hook implementation instead - $relatedObj = Html::tag('ul', ['class' => ['item-list', 'action-list'], 'data-base-target' => '_next']); - /** @var Objects $obj */ $obj = $this->event->object; - /** @var string $objUrl */ - $objUrl = $obj->url; - $relatedObj->add( - Html::tag( - 'li', - ['class' => 'list-item', 'data-action-item' => true], - [ //TODO(sd): fix stateball - Html::tag('div', ['class' => 'visual'], new StateBall('down', StateBall::SIZE_LARGE)), - Html::tag( - 'div', - ['class' => 'main'], - Html::tag('header') - ->add(Html::tag( - 'div', - ['class' => 'title'], - new Link($obj->getName(), $objUrl, ['class' => 'subject']) - )) - ) - ] - ) - ); + /** @var Source $source */ + $source = $obj->source; + + $objWidget = EventsObjectsInfoHook::getObjectListItemWidget($source->name, $obj->id_tags); + $objUrl = Url::fromPath($obj->url); return [ Html::tag('h2', t('Related Object')), - $relatedObj + $objWidget ?? (new Link( + $obj->getName(), + $objUrl->isExternal() ? $objUrl->getAbsoluteUrl() : $objUrl->getRelativeUrl(), + [ + 'class' => 'subject' + ] + ))->setBaseTarget('_next') ]; } diff --git a/library/Notifications/Widget/ItemList/EventList.php b/library/Notifications/Widget/ItemList/EventList.php index 550c35a23..c9bdae7e0 100644 --- a/library/Notifications/Widget/ItemList/EventList.php +++ b/library/Notifications/Widget/ItemList/EventList.php @@ -7,6 +7,11 @@ use Icinga\Module\Notifications\Common\LoadMore; use Icinga\Module\Notifications\Common\BaseItemList; use Icinga\Module\Notifications\Common\NoSubjectLink; +use Icinga\Module\Notifications\Hook\EventsObjectsInfoHook; +use Icinga\Module\Notifications\Model\Event; +use Icinga\Module\Notifications\Model\Objects; +use Icinga\Module\Notifications\Model\Source; +use ipl\Html\ValidHtml; use ipl\Orm\ResultSet; class EventList extends BaseItemList @@ -19,6 +24,12 @@ class EventList extends BaseItemList /** @var ResultSet */ protected $data; + /** @var array>> Object ID tags for each source */ + public $objectIdTagsCache = []; + + /** @var array Object display names obtained from the corresponding web modules of the sources */ + public $renderedObjectDisplayNames = []; + public function __construct(ResultSet $data) { parent::__construct($data); @@ -27,10 +38,36 @@ public function __construct(ResultSet $data) protected function init(): void { $this->data = $this->getIterator($this->data); + + $this->on(self::ON_ITEM_ADD, function (EventListItem $item, Event $data) { + /** @var Objects $obj */ + $obj = $data->object; + /** @var Source $src */ + $src = $obj->source; + $this->objectIdTagsCache[$src->type][$obj->id] = $obj->id_tags; + }); + + $this->on(self::ON_ASSEMBLED, function () { + $this->renderedObjectDisplayNames = EventsObjectsInfoHook::getObjectsDisplayNames( + $this->objectIdTagsCache + ); + }); } protected function getItemClass(): string { return EventListItem::class; } + + /** + * Get the rendered object display name for the given object ID + * + * @param string $objectID + * + * @return ?ValidHtml + */ + public function getRenderedObjectDisplayName(string $objectID): ?ValidHtml + { + return $this->renderedObjectDisplayNames[$objectID] ?? null; + } } diff --git a/library/Notifications/Widget/ItemList/EventListItem.php b/library/Notifications/Widget/ItemList/EventListItem.php index 51bd09b93..b110d9acf 100644 --- a/library/Notifications/Widget/ItemList/EventListItem.php +++ b/library/Notifications/Widget/ItemList/EventListItem.php @@ -10,6 +10,7 @@ use Icinga\Module\Notifications\Model\Objects; use Icinga\Module\Notifications\Widget\SourceIcon; use ipl\Html\BaseHtmlElement; +use ipl\Html\DeferredText; use ipl\Html\Html; use ipl\Web\Widget\Icon; use ipl\Web\Widget\Link; @@ -82,14 +83,15 @@ protected function assembleTitle(BaseHtmlElement $title): void /** @var Objects $obj */ $obj = $this->item->object; - $name = $obj->getName(); + $name = (new DeferredText(function () use ($obj) { + return $this->list->getRenderedObjectDisplayName($obj->id) ?? $obj->getName(); + }))->setEscaped(); if (! $this->list->getNoSubjectLink()) { $content = new Link($name, Links::event($this->item->id), ['class' => 'subject']); } else { $content = Html::tag('span', ['class' => 'subject'], $name); } - $msg = null; if ($this->item->severity === null) { $msg = t('acknowledged'); } elseif ($this->item->severity === 'ok') { diff --git a/public/css/detail/event-detail.less b/public/css/detail/event-detail.less new file mode 100644 index 000000000..bafe464ac --- /dev/null +++ b/public/css/detail/event-detail.less @@ -0,0 +1,14 @@ +.event-detail { + .subject { + color: @default-text-color; + } + + a { + font-weight: bold; + + &:hover { + color: @list-item-title-hover-color; + text-decoration: none; + } + } +} \ No newline at end of file