mirror of
https://github.com/Icinga/icingadb-web.git
synced 2026-06-08 16:22:05 -04:00
Replace LoadMoreObjectList with HistoryObjectList
Rename and specialize the list for history views. Insert a day-separator between entries of different days, to support this when load-more is used the a URL parameter with the date of the most recently added element is added to the `loadmoreUrl`. The css for these new classes is added and `action-list.js` is adjusted so it skips over the day-separator.
This commit is contained in:
parent
c927e7ef74
commit
bf83c2637c
4 changed files with 120 additions and 46 deletions
96
library/Icingadb/Widget/ItemList/HistoryObjectList.php
Normal file
96
library/Icingadb/Widget/ItemList/HistoryObjectList.php
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
// SPDX-FileCopyrightText: 2025 Icinga GmbH <https://icinga.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
namespace Icinga\Module\Icingadb\Widget\ItemList;
|
||||
|
||||
use Icinga\Exception\NotImplementedError;
|
||||
use Icinga\Module\Icingadb\Common\LoadMore;
|
||||
use Icinga\Module\Icingadb\Model\History;
|
||||
use Icinga\Module\Icingadb\Model\NotificationHistory;
|
||||
use Icinga\Module\Icingadb\View\EventRenderer;
|
||||
use Icinga\Module\Icingadb\View\NotificationRenderer;
|
||||
use IntlDateFormatter;
|
||||
use ipl\Html\Attributes;
|
||||
use ipl\Html\HtmlDocument;
|
||||
use ipl\Html\HtmlElement;
|
||||
use ipl\Html\Text;
|
||||
use ipl\Orm\Model;
|
||||
use ipl\Orm\ResultSet;
|
||||
use ipl\Web\Widget\ItemList;
|
||||
use Locale;
|
||||
|
||||
/**
|
||||
* HistoryObjectList
|
||||
*
|
||||
* @template Item of NotificationHistory|History
|
||||
*
|
||||
* @extends ObjectList<Item>
|
||||
*/
|
||||
class HistoryObjectList extends ObjectList
|
||||
{
|
||||
use LoadMore;
|
||||
|
||||
/** @var ?int The timestamp of the recently added list item, used to detect day changes */
|
||||
protected ?int $previousTimeStamp = null;
|
||||
|
||||
/**
|
||||
* Create a list of History or NotificationHistory objects with a Load more link and add a separator between days.
|
||||
*
|
||||
* @param ResultSet $data
|
||||
* @param ?int $previousTimeStamp The timestamp of the recently added list item, used to detect day changes
|
||||
* @param bool $useRelativeTimestamps
|
||||
*/
|
||||
public function __construct(ResultSet $data, ?int $previousTimeStamp = null, bool $useRelativeTimestamps = false)
|
||||
{
|
||||
ItemList::__construct($data, function (Model $item) use ($useRelativeTimestamps) {
|
||||
if ($item instanceof NotificationHistory) {
|
||||
return new NotificationRenderer($useRelativeTimestamps);
|
||||
} elseif ($item instanceof History) {
|
||||
return new EventRenderer($useRelativeTimestamps);
|
||||
}
|
||||
|
||||
throw new NotImplementedError('Not implemented');
|
||||
});
|
||||
|
||||
$this->data = $this->getIterator($data);
|
||||
$this->previousTimeStamp = $previousTimeStamp;
|
||||
}
|
||||
|
||||
protected function init(): void
|
||||
{
|
||||
parent::init();
|
||||
$formatter = new IntlDateFormatter(
|
||||
Locale::getDefault(),
|
||||
IntlDateFormatter::MEDIUM,
|
||||
IntlDateFormatter::NONE
|
||||
);
|
||||
|
||||
$this->on(ItemList::BEFORE_ITEM_ADD, function ($item, $data) use ($formatter) {
|
||||
if ($data instanceof NotificationHistory) {
|
||||
$timestamp = $data->send_time->getTimestamp();
|
||||
} else {
|
||||
$timestamp = $data->event_time->getTimestamp();
|
||||
}
|
||||
|
||||
if (
|
||||
$this->previousTimeStamp === null
|
||||
|| $formatter->format($this->previousTimeStamp) !== $formatter->format($timestamp)
|
||||
) {
|
||||
$this->addHtml(new HtmlElement(
|
||||
'li',
|
||||
new Attributes(['class' => ['day-separator']]),
|
||||
new Text($formatter->format($timestamp))
|
||||
));
|
||||
}
|
||||
|
||||
$this->previousTimeStamp = $timestamp;
|
||||
});
|
||||
|
||||
$this->on(
|
||||
HtmlDocument::ON_ASSEMBLED,
|
||||
fn() => $this->loadMoreUrl->setParam('last-entry', $this->previousTimeStamp)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
// SPDX-FileCopyrightText: 2025 Icinga GmbH <https://icinga.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
namespace Icinga\Module\Icingadb\Widget\ItemList;
|
||||
|
||||
use Icinga\Exception\NotImplementedError;
|
||||
use Icinga\Module\Icingadb\Common\LoadMore;
|
||||
use Icinga\Module\Icingadb\Model\History;
|
||||
use Icinga\Module\Icingadb\Model\NotificationHistory;
|
||||
use Icinga\Module\Icingadb\View\EventRenderer;
|
||||
use Icinga\Module\Icingadb\View\NotificationRenderer;
|
||||
use ipl\Orm\Model;
|
||||
use ipl\Orm\ResultSet;
|
||||
use ipl\Web\Widget\ItemList;
|
||||
|
||||
/**
|
||||
* LoadMoreObjectList
|
||||
*
|
||||
* Create a list of icingadb objects with Load more link
|
||||
*
|
||||
* @template Item of NotificationHistory|History
|
||||
*
|
||||
* @extends ObjectList<Item>
|
||||
*/
|
||||
class LoadMoreObjectList extends ObjectList
|
||||
{
|
||||
use LoadMore;
|
||||
|
||||
public function __construct(ResultSet $data)
|
||||
{
|
||||
ItemList::__construct($data, function (Model $item) {
|
||||
if ($item instanceof NotificationHistory) {
|
||||
return new NotificationRenderer();
|
||||
} elseif ($item instanceof History) {
|
||||
return new EventRenderer();
|
||||
}
|
||||
|
||||
throw new NotImplementedError('Not implemented');
|
||||
});
|
||||
|
||||
$this->data = $this->getIterator($data);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,21 @@
|
|||
> .page-separator + .list-item .main {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.interactive-time {
|
||||
&:hover {
|
||||
.rounded-corners(1em);
|
||||
background: @gray-light;
|
||||
}
|
||||
|
||||
.user-select(none);
|
||||
padding-left: 0.5em;
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
.day-separator {
|
||||
background-color: @gray-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
// Layout
|
||||
|
|
@ -80,4 +95,10 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.day-separator {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -317,7 +317,9 @@
|
|||
}
|
||||
|
||||
_this.clearSelection(activeItems);
|
||||
if (toActiveItem.classList.contains('page-separator')) {
|
||||
if (toActiveItem.classList.contains('page-separator')
|
||||
|| toActiveItem.classList.contains('day-separator')
|
||||
) {
|
||||
toActiveItem = _this.getDirectionalNext(toActiveItem, event.key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue