Skip to content

Commit

Permalink
Implement object hook to get event object information from respective…
Browse files Browse the repository at this point in the history
… sources
  • Loading branch information
raviks789 committed May 17, 2024
1 parent e044065 commit 2d1a99b
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 74 deletions.
2 changes: 1 addition & 1 deletion application/controllers/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function indexAction(): void
$id = $this->params->getRequired('id');

$query = Event::on(Database::get())
->with(['object', 'object.source', 'incident', 'incident.object'])
->with(['object', 'object.source', 'incident', 'incident.object', 'incident.object.source'])
->withColumns(['object.id_tags', 'incident.object.id_tags'])
->filter(Filter::equal('event.id', $id));

Expand Down
2 changes: 1 addition & 1 deletion application/controllers/IncidentsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function indexAction(): void
$this->addTitleTab(t('Incidents'));

$incidents = Incident::on(Database::get())
->with('object')
->with(['object', 'object.source'])
->withColumns('object.id_tags');

$limitControl = $this->createLimitControl();
Expand Down
123 changes: 123 additions & 0 deletions library/Notifications/Hook/EventsObjectsInfoHook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

/* Icinga Notifications Web | (c) 2024 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Notifications\Hook;

use Exception;
use Icinga\Application\Hook;
use Icinga\Application\Logger;
use Icinga\Module\Notifications\Model\Objects;
use ipl\Html\HtmlString;
use ipl\Html\ValidHtml;
use ipl\Web\Url;
use ipl\Web\Widget\Link;

abstract class EventsObjectsInfoHook
{
/** @var array<string, ValidHtml> */
protected static $objectNameWidgets = [];

/**
* Get the object name widgets for the objects using the object ID tags
*
* @param array<string, array<string, string>> $objectIdTags
*
* @return array<string, ValidHtml>
*/
abstract public function getObjectNameWidgets(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<string, string> $objectIdTag
*
* @return ValidHtml
*/
abstract public function getHtmlForObject(array $objectIdTag): ValidHtml;

/**
* Register object name widgets for the objects using the object ID tags
*
* @param array<string, array<string, array<string, string>>> $objectIdTags
*
* @return void
*/
final public static function registerObjectNameWidgets(array $objectIdTags): void
{
$objectDisplayNames = [];
foreach (Hook::all('Notifications\\EventsObjectsInfo') as $hook) {
/** @var self $hook */
try {
$objectDisplayNames[] = $hook->getObjectNameWidgets($objectIdTags[$hook->getSource()]);
} catch (Exception $e) {
Logger::error('Failed to load hook %s:', get_class($hook), $e);
}
}

self::$objectNameWidgets = array_merge([], ...$objectDisplayNames);
}

/**
* Get the display name for the given object
*
* @param Objects $obj
*
* @return ValidHtml
*/
final public static function getObjectNameWidget(Objects $obj): ValidHtml
{
if (isset(self::$objectNameWidgets[$obj->source->type][$obj->id])) {
return self::$objectNameWidgets[$obj->source->type][$obj->id];
}

$objectTags = [];

foreach ($obj->id_tags as $tag => $value) {
$objectTags[] = sprintf('%s=%s', $tag, $value);
}

return new HtmlString(implode(', ', $objectTags));
}

/**
* Get the object list item widget for the given object
*
* @param Objects $object
*
* @return ValidHtml
*/
final public static function getObjectListItemWidget(Objects $object): ValidHtml
{
$objectListItemWidget = null;
foreach (Hook::all('Notifications\\EventsObjectsInfo') as $hook) {
/** @var self $hook */
try {
if ($object->source->name === $hook->getSource()) {
$objectListItemWidget = $hook->getHtmlForObject($object->id_tags);
}
} catch (Exception $e) {
Logger::error('Failed to load hook %s:', get_class($hook), $e);
}
}

if ($objectListItemWidget) {
return $objectListItemWidget;
}

$objUrl = Url::fromPath($object->url);

return (new Link(
EventsObjectsInfoHook::getObjectNameWidget($object),
$objUrl->isExternal() ? $objUrl->getAbsoluteUrl() : $objUrl->getRelativeUrl(),
['class' => 'subject']
))->setBaseTarget('_next');
}
}
11 changes: 2 additions & 9 deletions library/Notifications/Model/Objects.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace Icinga\Module\Notifications\Model;

use Icinga\Module\Notifications\Hook\EventsObjectsInfoHook;
use Icinga\Module\Notifications\Model\Behavior\IdTagAggregator;
use ipl\Html\HtmlString;
use ipl\Html\ValidHtml;
use ipl\Orm\Behavior\Binary;
use ipl\Orm\Behaviors;
Expand Down Expand Up @@ -91,13 +91,6 @@ public function createRelations(Relations $relations)

public function getName(): ValidHtml
{
//TODO: Once hooks are available, they should render the tags accordingly
$objectTags = [];

foreach ($this->id_tags as $tag => $value) {
$objectTags[] = sprintf('%s=%s', $tag, $value);
}

return new HtmlString(implode(', ', $objectTags));
return EventsObjectsInfoHook::getObjectNameWidget($this);
}
}
33 changes: 4 additions & 29 deletions library/Notifications/Widget/Detail/EventDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
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\Incident;
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 InvalidArgumentException;
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;
Expand Down Expand Up @@ -80,37 +83,9 @@ 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'])
))
)
]
)
);

return [
Html::tag('h2', t('Related Object')),
$relatedObj
EventsObjectsInfoHook::getObjectListItemWidget($this->event->object)
];
}

Expand Down
36 changes: 4 additions & 32 deletions library/Notifications/Widget/Detail/IncidentDetail.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

namespace Icinga\Module\Notifications\Widget\Detail;

use Icinga\Module\Notifications\Hook\EventsObjectsInfoHook;
use Icinga\Module\Notifications\Model\Incident;
use Icinga\Module\Notifications\Model\Objects;
use Icinga\Module\Notifications\Model\Source;
use Icinga\Module\Notifications\Widget\EventSourceBadge;
use Icinga\Module\Notifications\Widget\ItemList\IncidentContactList;
use Icinga\Module\Notifications\Widget\ItemList\IncidentHistoryList;
Expand All @@ -14,8 +16,8 @@
use ipl\Html\Html;
use ipl\Html\HtmlElement;
use ipl\Html\Table;
use ipl\Web\Url;
use ipl\Web\Widget\Link;
use ipl\Web\Widget\StateBall;

class IncidentDetail extends BaseHtmlElement
{
Expand Down Expand Up @@ -52,39 +54,9 @@ protected function createContacts()

protected function createRelatedObject()
{
//TODO(sd): Add hook implementation
$list = Html::tag('ul', ['class' => ['item-list', 'minimal', 'action-list'], 'data-base-target' => '_next']);

/** @var Objects $obj */
$obj = $this->incident->object;

/** @var string $objUrl */
$objUrl = $obj->url;
$list->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'])
))
)
]
));

return [
Html::tag('h2', t('Object')),
$list
EventsObjectsInfoHook::getObjectListItemWidget($this->incident->object)
];
}

Expand Down
21 changes: 21 additions & 0 deletions library/Notifications/Widget/ItemList/EventList.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

use Icinga\Module\Notifications\Common\LoadMore;
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;
use ipl\Web\Common\BaseItemList;

Expand All @@ -19,6 +24,9 @@ class EventList extends BaseItemList
/** @var ResultSet */
protected $data;

/** @var array<string, array<string, array<string, string>>> Object ID tags for each source */
public $objectIdTagsCache = [];

public function __construct(ResultSet $data)
{
parent::__construct($data);
Expand All @@ -27,6 +35,19 @@ 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;

$this->objectIdTagsCache[$obj->source->type][$obj->id] = $obj->id_tags;
});

$this->on(self::ON_ASSEMBLED, function () {
EventsObjectsInfoHook::registerObjectNameWidgets(
$this->objectIdTagsCache
);
});
}

protected function getItemClass(): string
Expand Down
7 changes: 5 additions & 2 deletions library/Notifications/Widget/ItemList/EventListItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Icinga\Module\Notifications\Widget\ItemList;

use Icinga\Module\Notifications\Common\Links;
use Icinga\Module\Notifications\Hook\EventsObjectsInfoHook;
use Icinga\Module\Notifications\Model\Event;
use Icinga\Module\Notifications\Model\Incident;
use Icinga\Module\Notifications\Model\Objects;
Expand All @@ -13,6 +14,7 @@
use Icinga\Module\Notifications\Widget\SourceIcon;
use InvalidArgumentException;
use ipl\Html\BaseHtmlElement;
use ipl\Html\DeferredText;
use ipl\Html\Html;
use ipl\Stdlib\Str;
use ipl\Web\Common\BaseListItem;
Expand Down Expand Up @@ -105,14 +107,15 @@ protected function assembleTitle(BaseHtmlElement $title): void

/** @var Objects $obj */
$obj = $this->item->object;
$name = $obj->getName();
$name = (new DeferredText(function () use ($obj) {
return EventsObjectsInfoHook::getObjectNameWidget($obj);
}))->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) {
$description = strtolower(trim($this->item->message ?? ''));
if (Str::startsWith($description, 'incident reached age')) {
Expand Down
16 changes: 16 additions & 0 deletions public/css/common.less
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@
}
}

.incident-detail,
.event-detail {
.subject {
color: @default-text-color;
}

a {
font-weight: bold;

&:hover {
color: @list-item-title-hover-color;
text-decoration: none;
}
}
}

.source-icon {
.ball();
.ball-solid(@gray-light);
Expand Down

0 comments on commit 2d1a99b

Please sign in to comment.