mirror of
https://github.com/Icinga/icingadb-web.git
synced 2026-05-28 04:36:06 -04:00
Enhancement/improve column opening behaviour (#1293)
Some checks failed
L10n Update / update (push) Has been cancelled
PHP Tests / Static analysis for php 8.2 on ubuntu-latest (push) Has been cancelled
PHP Tests / Static analysis for php 8.3 on ubuntu-latest (push) Has been cancelled
PHP Tests / Static analysis for php 8.4 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.2 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.3 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.4 on ubuntu-latest (push) Has been cancelled
Some checks failed
L10n Update / update (push) Has been cancelled
PHP Tests / Static analysis for php 8.2 on ubuntu-latest (push) Has been cancelled
PHP Tests / Static analysis for php 8.3 on ubuntu-latest (push) Has been cancelled
PHP Tests / Static analysis for php 8.4 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.2 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.3 on ubuntu-latest (push) Has been cancelled
PHP Tests / Unit tests with php 8.4 on ubuntu-latest (push) Has been cancelled
This PR improves the UX in the IcingaDB Web interface by: - Enhancing the page opening behavior in column views for smoother navigation. - Adding a search bar to the tabs Host Services, Host History and Service History ## Resolves - #981 - #1288
This commit is contained in:
parent
6f6c5700a9
commit
c7cc328bf2
8 changed files with 253 additions and 8 deletions
|
|
@ -150,6 +150,35 @@ class HostController extends Controller
|
|||
);
|
||||
$viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl, true);
|
||||
|
||||
$preserveParams = [
|
||||
$limitControl->getLimitParam(),
|
||||
$sortControl->getSortParam(),
|
||||
$viewModeSwitcher->getViewModeParam(),
|
||||
'name'
|
||||
];
|
||||
|
||||
$requestParams = Url::fromRequest()->onlyWith($preserveParams)->getParams();
|
||||
$searchBar = $this->createSearchBar($history, $preserveParams)
|
||||
->setEditorUrl(
|
||||
Url::fromPath('icingadb/host/history-search-editor')
|
||||
->setParams($requestParams)
|
||||
)->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/host/history-complete')
|
||||
->setParams(clone $requestParams)
|
||||
);
|
||||
|
||||
if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) {
|
||||
if ($searchBar->hasBeenSubmitted()) {
|
||||
$filter = $this->getFilter();
|
||||
} else {
|
||||
$this->addControl($searchBar);
|
||||
$this->sendMultipartUpdate();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$filter = $searchBar->getFilter();
|
||||
}
|
||||
|
||||
$history->peekAhead();
|
||||
|
||||
$page = $paginationControl->getCurrentPageNumber();
|
||||
|
|
@ -160,17 +189,19 @@ class HostController extends Controller
|
|||
}
|
||||
|
||||
$history->filter(Filter::lessThanOrEqual('event_time', $before));
|
||||
$this->filter($history, $filter);
|
||||
|
||||
yield $this->export($history);
|
||||
|
||||
$this->addControl($sortControl);
|
||||
$this->addControl($limitControl);
|
||||
$this->addControl($viewModeSwitcher);
|
||||
$this->addControl($searchBar);
|
||||
|
||||
$historyList = (new LoadMoreObjectList($history->execute()))
|
||||
->setViewMode($viewModeSwitcher->getViewMode())
|
||||
->setPageSize($limitControl->getLimit())
|
||||
->setLoadMoreUrl($url->setParam('before', $before));
|
||||
->setLoadMoreUrl($url->setParam('before', $before)->setFilter($filter));
|
||||
|
||||
if ($compact) {
|
||||
$historyList->setPageNumber($page);
|
||||
|
|
@ -181,6 +212,10 @@ class HostController extends Controller
|
|||
} else {
|
||||
$this->addContent($historyList);
|
||||
}
|
||||
|
||||
if (! $searchBar->hasBeenSubmitted() && $searchBar->hasBeenSent()) {
|
||||
$this->sendMultipartUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public function servicesAction(): Generator
|
||||
|
|
@ -218,6 +253,37 @@ class HostController extends Controller
|
|||
['service.state.severity DESC', 'service.state.last_state_change DESC']
|
||||
);
|
||||
|
||||
$preserveParams = [
|
||||
$limitControl->getLimitParam(),
|
||||
$sortControl->getSortParam(),
|
||||
$viewModeSwitcher->getViewModeParam(),
|
||||
'name'
|
||||
];
|
||||
|
||||
$requestParams = Url::fromRequest()->onlyWith($preserveParams)->getParams();
|
||||
$searchBar = $this->createSearchBar($services, $preserveParams)
|
||||
->setEditorUrl(
|
||||
Url::fromPath('icingadb/host/services-search-editor')
|
||||
->setParams($requestParams)
|
||||
)->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/host/services-complete')
|
||||
->setParams(clone $requestParams)
|
||||
);
|
||||
|
||||
if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) {
|
||||
if ($searchBar->hasBeenSubmitted()) {
|
||||
$filter = $this->getFilter();
|
||||
} else {
|
||||
$this->addControl($searchBar);
|
||||
$this->sendMultipartUpdate();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$filter = $searchBar->getFilter();
|
||||
}
|
||||
|
||||
$services->filter($filter);
|
||||
|
||||
yield $this->export($services);
|
||||
|
||||
$serviceList = (new ObjectList($services))
|
||||
|
|
@ -228,9 +294,18 @@ class HostController extends Controller
|
|||
$this->addControl($sortControl);
|
||||
$this->addControl($limitControl);
|
||||
$this->addControl($viewModeSwitcher);
|
||||
$this->addControl($searchBar);
|
||||
$continueWith = $this->createContinueWith(
|
||||
Links::servicesDetails()->setFilter(Filter::equal('host.name', $this->host->name)),
|
||||
$searchBar
|
||||
);
|
||||
|
||||
$this->addContent($serviceList);
|
||||
|
||||
if (! $searchBar->hasBeenSubmitted() && $searchBar->hasBeenSent()) {
|
||||
$this->sendMultipartUpdate($continueWith);
|
||||
}
|
||||
|
||||
$this->setAutorefreshInterval(10);
|
||||
}
|
||||
|
||||
|
|
@ -391,6 +466,26 @@ class HostController extends Controller
|
|||
$this->getDocument()->add($suggestions);
|
||||
}
|
||||
|
||||
public function historyCompleteAction(): void
|
||||
{
|
||||
$suggestions = (new ObjectSuggestions())
|
||||
->setModel(History::class)
|
||||
->setBaseFilter(Filter::equal('host.id', $this->host->id))
|
||||
->forRequest($this->getServerRequest());
|
||||
|
||||
$this->getDocument()->addHtml($suggestions);
|
||||
}
|
||||
|
||||
public function servicesCompleteAction(): void
|
||||
{
|
||||
$suggestions = (new ObjectSuggestions())
|
||||
->setModel(Service::class)
|
||||
->setBaseFilter(Filter::equal('host.id', $this->host->id))
|
||||
->forRequest($this->getServerRequest());
|
||||
|
||||
$this->getDocument()->addHtml($suggestions);
|
||||
}
|
||||
|
||||
public function searchEditorAction(): void
|
||||
{
|
||||
$editor = $this->createSearchEditor(
|
||||
|
|
@ -432,6 +527,50 @@ class HostController extends Controller
|
|||
$this->setTitle($this->translate('Adjust Filter'));
|
||||
}
|
||||
|
||||
public function historySearchEditorAction(): void
|
||||
{
|
||||
$preserveParams = [
|
||||
LimitControl::DEFAULT_LIMIT_PARAM,
|
||||
SortControl::DEFAULT_SORT_PARAM,
|
||||
ViewModeSwitcher::DEFAULT_VIEW_MODE_PARAM,
|
||||
'name'
|
||||
];
|
||||
$editor = $this->createSearchEditor(
|
||||
History::on($this->getDb()),
|
||||
Url::fromPath('icingadb/host/history', ['name' => $this->host->name]),
|
||||
$preserveParams
|
||||
);
|
||||
$editor->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/host/history-complete')
|
||||
->setParams(Url::fromRequest()->onlyWith($preserveParams)->getParams())
|
||||
);
|
||||
|
||||
$this->getDocument()->addHtml($editor);
|
||||
$this->setTitle($this->translate('Adjust Filter'));
|
||||
}
|
||||
|
||||
public function servicesSearchEditorAction(): void
|
||||
{
|
||||
$preserveParams = [
|
||||
LimitControl::DEFAULT_LIMIT_PARAM,
|
||||
SortControl::DEFAULT_SORT_PARAM,
|
||||
ViewModeSwitcher::DEFAULT_VIEW_MODE_PARAM,
|
||||
'name'
|
||||
];
|
||||
$editor = $this->createSearchEditor(
|
||||
Service::on($this->getDb()),
|
||||
Url::fromPath('icingadb/host/services', ['name' => $this->host->name]),
|
||||
$preserveParams
|
||||
);
|
||||
$editor->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/host/services-complete')
|
||||
->setParams(Url::fromRequest()->onlyWith($preserveParams)->getParams())
|
||||
);
|
||||
|
||||
$this->getDocument()->addHtml($editor);
|
||||
$this->setTitle($this->translate('Adjust Filter'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the dependency nodes of the current host
|
||||
*
|
||||
|
|
|
|||
|
|
@ -300,6 +300,36 @@ class ServiceController extends Controller
|
|||
);
|
||||
$viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl, true);
|
||||
|
||||
$preserveParams = [
|
||||
$limitControl->getLimitParam(),
|
||||
$sortControl->getSortParam(),
|
||||
$viewModeSwitcher->getViewModeParam(),
|
||||
'name',
|
||||
'host.name'
|
||||
];
|
||||
|
||||
$requestParams = Url::fromRequest()->onlyWith($preserveParams)->getParams();
|
||||
$searchBar = $this->createSearchBar($history, $preserveParams)
|
||||
->setEditorUrl(
|
||||
Url::fromPath('icingadb/service/history-search-editor')
|
||||
->setParams($requestParams)
|
||||
)->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/service/history-complete')
|
||||
->setParams(clone $requestParams)
|
||||
);
|
||||
|
||||
if ($searchBar->hasBeenSent() && ! $searchBar->isValid()) {
|
||||
if ($searchBar->hasBeenSubmitted()) {
|
||||
$filter = $this->getFilter();
|
||||
} else {
|
||||
$this->addControl($searchBar);
|
||||
$this->sendMultipartUpdate();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$filter = $searchBar->getFilter();
|
||||
}
|
||||
|
||||
$history->peekAhead();
|
||||
|
||||
$page = $paginationControl->getCurrentPageNumber();
|
||||
|
|
@ -310,17 +340,19 @@ class ServiceController extends Controller
|
|||
}
|
||||
|
||||
$history->filter(Filter::lessThanOrEqual('event_time', $before));
|
||||
$this->filter($history, $filter);
|
||||
|
||||
yield $this->export($history);
|
||||
|
||||
$this->addControl($sortControl);
|
||||
$this->addControl($limitControl);
|
||||
$this->addControl($viewModeSwitcher);
|
||||
$this->addControl($searchBar);
|
||||
|
||||
$historyList = (new LoadMoreObjectList($history->execute()))
|
||||
->setViewMode($viewModeSwitcher->getViewMode())
|
||||
->setPageSize($limitControl->getLimit())
|
||||
->setLoadMoreUrl($url->setParam('before', $before));
|
||||
->setLoadMoreUrl($url->setParam('before', $before)->setFilter($filter));
|
||||
|
||||
if ($compact) {
|
||||
$historyList->setPageNumber($page);
|
||||
|
|
@ -331,6 +363,10 @@ class ServiceController extends Controller
|
|||
} else {
|
||||
$this->addContent($historyList);
|
||||
}
|
||||
|
||||
if (! $searchBar->hasBeenSubmitted() && $searchBar->hasBeenSent()) {
|
||||
$this->sendMultipartUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
public function completeAction(): void
|
||||
|
|
@ -355,6 +391,16 @@ class ServiceController extends Controller
|
|||
$this->getDocument()->add($suggestions);
|
||||
}
|
||||
|
||||
public function historyCompleteAction(): void
|
||||
{
|
||||
$suggestions = (new ObjectSuggestions())
|
||||
->setModel(History::class)
|
||||
->setBaseFilter(Filter::equal('service.id', $this->service->id))
|
||||
->forRequest($this->getServerRequest());
|
||||
|
||||
$this->getDocument()->addHtml($suggestions);
|
||||
}
|
||||
|
||||
public function searchEditorAction(): void
|
||||
{
|
||||
$editor = $this->createSearchEditor(
|
||||
|
|
@ -404,6 +450,29 @@ class ServiceController extends Controller
|
|||
$this->setTitle($this->translate('Adjust Filter'));
|
||||
}
|
||||
|
||||
public function historySearchEditorAction(): void
|
||||
{
|
||||
$preserveParams = [
|
||||
LimitControl::DEFAULT_LIMIT_PARAM,
|
||||
SortControl::DEFAULT_SORT_PARAM,
|
||||
ViewModeSwitcher::DEFAULT_VIEW_MODE_PARAM,
|
||||
'name',
|
||||
'host.name'
|
||||
];
|
||||
$editor = $this->createSearchEditor(
|
||||
History::on($this->getDb()),
|
||||
Url::fromPath('icingadb/service/history', ['name' => $this->service->name]),
|
||||
$preserveParams
|
||||
);
|
||||
$editor->setSuggestionUrl(
|
||||
Url::fromPath('icingadb/service/history-complete')
|
||||
->setParams(Url::fromRequest()->onlyWith($preserveParams)->getParams())
|
||||
);
|
||||
|
||||
$this->getDocument()->addHtml($editor);
|
||||
$this->setTitle($this->translate('Adjust Filter'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the dependency nodes of the current service
|
||||
*
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ abstract class ObjectActionsHook
|
|||
continue;
|
||||
}
|
||||
|
||||
if ($link->getBaseTarget() === null && ! $link->hasAttribute('target')) {
|
||||
$link->setBaseTarget('_next');
|
||||
}
|
||||
|
||||
// It may be ValidHtml, but modules shouldn't be able to break our views.
|
||||
// That's why it needs to be rendered instantly, as any error will then
|
||||
// be caught here.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace Icinga\Module\Icingadb\Widget\Detail;
|
||||
|
||||
use Icinga\Module\Icingadb\Common\HostLinks;
|
||||
use Icinga\Module\Icingadb\Hook\ExtensionHook\ObjectDetailExtensionHook;
|
||||
use Icinga\Module\Icingadb\Model\Host;
|
||||
use Icinga\Module\Icingadb\Model\ServicestateSummary;
|
||||
|
|
@ -25,8 +26,8 @@ class HostDetail extends ObjectDetail
|
|||
protected function createServiceStatistics(): array
|
||||
{
|
||||
if ($this->serviceSummary->services_total > 0) {
|
||||
$services = new ServiceStatistics($this->serviceSummary);
|
||||
$services->setBaseFilter(Filter::equal('host.name', $this->object->name));
|
||||
$services = (new ServiceStatistics($this->serviceSummary))
|
||||
->setUrl(HostLinks::services($this->object));
|
||||
} else {
|
||||
$services = new EmptyState(t('This host has no services'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ use Icinga\Module\Icingadb\Widget\ItemList\DowntimeList;
|
|||
use Icinga\Module\Icingadb\Widget\ShowMore;
|
||||
use ipl\Sql\Expression;
|
||||
use ipl\Sql\Filter\Exists;
|
||||
use ipl\Web\Url;
|
||||
use ipl\Web\Widget\CopyToClipboard;
|
||||
use ipl\Web\Widget\EmptyState;
|
||||
use ipl\Web\Widget\EmptyStateBar;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ use ipl\Web\Layout\ItemLayout;
|
|||
*/
|
||||
class ObjectHeader extends BaseHtmlElement
|
||||
{
|
||||
protected $defaultAttributes = ['data-base-target' => '_next'];
|
||||
|
||||
/** @var Item */
|
||||
protected $object;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
namespace Icinga\Module\Icingadb\Widget\Detail;
|
||||
|
||||
use Icinga\Chart\Donut;
|
||||
use Icinga\Module\Icingadb\Common\HostLinks;
|
||||
use Icinga\Module\Icingadb\Common\Links;
|
||||
use Icinga\Module\Icingadb\Widget\ServiceStateBadges;
|
||||
use ipl\Html\ValidHtml;
|
||||
use ipl\Web\Url;
|
||||
use ipl\Web\Widget\VerticalKeyValue;
|
||||
use ipl\Html\HtmlString;
|
||||
use ipl\Web\Widget\Link;
|
||||
|
|
@ -16,11 +18,40 @@ class ServiceStatistics extends ObjectStatistics
|
|||
{
|
||||
protected $summary;
|
||||
|
||||
/** @var ?Url */
|
||||
protected ?Url $url;
|
||||
|
||||
public function __construct($summary)
|
||||
{
|
||||
$this->summary = $summary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL pointing to all matching services.
|
||||
*
|
||||
* If not set, the URL of the services overview is returned as fallback.
|
||||
*
|
||||
* @return Url
|
||||
*/
|
||||
public function getUrl(): Url
|
||||
{
|
||||
return $this->url ?? Links::services();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL pointing to all matching services.
|
||||
*
|
||||
* @param Url $url The URL to set.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setUrl(Url $url): self
|
||||
{
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function createDonut(): ValidHtml
|
||||
{
|
||||
$donut = (new Donut())
|
||||
|
|
@ -38,7 +69,7 @@ class ServiceStatistics extends ObjectStatistics
|
|||
|
||||
protected function createTotal(): ValidHtml
|
||||
{
|
||||
$url = Links::services();
|
||||
$url = $this->getUrl();
|
||||
if ($this->hasBaseFilter()) {
|
||||
$url->setFilter($this->getBaseFilter());
|
||||
}
|
||||
|
|
@ -59,6 +90,6 @@ class ServiceStatistics extends ObjectStatistics
|
|||
$badges->setBaseFilter($this->getBaseFilter());
|
||||
}
|
||||
|
||||
return $badges;
|
||||
return $badges->setUrl($this->getUrl());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class TagList extends BaseHtmlElement
|
|||
{
|
||||
protected $content = [];
|
||||
|
||||
protected $defaultAttributes = ['class' => 'tag-list'];
|
||||
protected $defaultAttributes = ['class' => 'tag-list', 'data-base-target' => '_next'];
|
||||
|
||||
protected $tag = 'div';
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue