Skip to content

Commit bf0b380

Browse files
committed
Dashboard to show all favorites
1 parent 9f9c55d commit bf0b380

File tree

7 files changed

+189
-2
lines changed

7 files changed

+189
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/* Icinga for Kubernetes Web | (c) 2025 Icinga GmbH | AGPLv3 */
4+
5+
namespace Icinga\Module\Kubernetes\Controllers;
6+
7+
use Icinga\Module\Kubernetes\Web\Controller;
8+
use Icinga\Module\Kubernetes\Web\Factory;
9+
use Icinga\Module\Kubernetes\Web\FavoriteDashboard;
10+
use Icinga\Web\Widget\Dashboard;
11+
use Icinga\Web\Widget\Dashboard\Dashlet;
12+
use Icinga\Web\Widget\Dashboard\Pane;
13+
14+
class FavoritesController extends Controller
15+
{
16+
const array FAVORABLE_KINDS = [
17+
'Cron Jobs',
18+
'Daemon Sets',
19+
'Deployments',
20+
'Ingresses',
21+
'Jobs',
22+
'Namespaces',
23+
'Nodes',
24+
'Persistent Volume Claims',
25+
'Persistent Volumes',
26+
'Pods',
27+
'Replica Sets',
28+
'Services',
29+
'Stateful Sets'
30+
];
31+
32+
public function indexAction(): void
33+
{
34+
$this->addTitleTab('Favorites');
35+
$dashboard = new Dashboard();
36+
$pane = (new Pane('favorites'))->setTitle('Favorites');
37+
$dashboard->addPane($pane);
38+
39+
foreach (self::FAVORABLE_KINDS as $kind) {
40+
$dashlet = new Dashlet($kind, 'kubernetes/' . Factory::canonicalizeKind($kind) . '?view=minimal&show-favorites=y', $pane);
41+
$pane->addDashlet($dashlet);
42+
}
43+
44+
$dashboard->activate('favorites');
45+
$this->addContent(new FavoriteDashboard($dashboard));
46+
}
47+
}

configuration.php

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717

1818
$priority = 0;
1919

20+
$section->add(
21+
N_('All Favorites'),
22+
[
23+
'description' => $this->translate('All Favorites'),
24+
'url' => 'kubernetes/favorites',
25+
'priority' => $priority++
26+
]
27+
);
28+
2029
$section->add(
2130
N_('Cluster Services'),
2231
[

library/Kubernetes/Web/Factory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public static function canonicalizeKind(string $kind): string
4141
return 'persistentvolumeclaim';
4242
}
4343

44-
return strtolower(str_replace(['_', '-'], '', $kind));
44+
return strtolower(str_replace([' ', '_', '-'], '', $kind));
4545
}
4646

4747
public static function createIcon(string $kind): ?ValidHtml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/* Icinga for Kubernetes Web | (c) 2025 Icinga GmbH | AGPLv3 */
4+
5+
namespace Icinga\Module\Kubernetes\Web;
6+
7+
use Icinga\Web\Widget\Dashboard;
8+
use ipl\Html\BaseHtmlElement;
9+
10+
class FavoriteDashboard extends BaseHtmlElement
11+
{
12+
/** @var Dashboard The dashboard to show all favorites of all resources. */
13+
protected Dashboard $dashboard;
14+
15+
protected $tag = 'div';
16+
17+
protected $defaultAttributes = ['class' => 'favorite-dashboard'];
18+
19+
public function __construct(Dashboard $dashboard)
20+
{
21+
$this->dashboard = $dashboard;
22+
}
23+
24+
public function assemble()
25+
{
26+
foreach ($this->dashboard->getActivePane()->getDashlets() as $dashlet) {
27+
$this->add(new FavoriteDashlet($dashlet));
28+
}
29+
}
30+
}
+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/* Icinga for Kubernetes Web | (c) 2025 Icinga GmbH | AGPLv3 */
4+
5+
namespace Icinga\Module\Kubernetes\Web;
6+
7+
use Icinga\Web\Widget\Dashboard\Dashlet;
8+
use ipl\Html\Attributes;
9+
use ipl\Html\BaseHtmlElement;
10+
use ipl\Html\Html;
11+
12+
class FavoriteDashlet extends BaseHtmlElement
13+
{
14+
/** @var Dashlet The dashlet to show all favorites of a resource. */
15+
protected Dashlet $dashlet;
16+
17+
protected $tag = 'div';
18+
19+
protected $defaultAttributes = [
20+
'class' => 'container',
21+
'data-last-update' => -1,
22+
'data-icinga-refresh' => 60
23+
];
24+
25+
public function __construct(Dashlet $dashlet)
26+
{
27+
$this->dashlet = $dashlet;
28+
}
29+
30+
public function assemble()
31+
{
32+
$url = $this->dashlet->getUrl()->setParam('showCompact');
33+
$fullUrl = $url->getUrlWithout(['showCompact', 'limit', 'view']);
34+
$tooltip = sprintf('Show %s', $this->dashlet->getTitle());
35+
$progressLabel = $this->dashlet->getProgressLabe();
36+
37+
$this->addAttributes(['data-icinga-url' => $url]);
38+
39+
$this->addHtml(
40+
Html::tag(
41+
'h1',
42+
null,
43+
Html::tag(
44+
'a',
45+
Attributes::create([
46+
'href' => $fullUrl,
47+
'aria-label' => $tooltip,
48+
'title' => $tooltip,
49+
'data-base-target' => 'col1'
50+
]),
51+
$this->dashlet->getName()
52+
)
53+
),
54+
Html::tag(
55+
'p',
56+
Attributes::create(['class' => 'progress-label']),
57+
[
58+
$progressLabel,
59+
Html::tag('span', null, '.'),
60+
Html::tag('span', null, '.'),
61+
Html::tag('span', null, '.')
62+
]
63+
),
64+
Html::tag('div', Attributes::create(['class' => 'content']))
65+
);
66+
}
67+
}

public/css/common.less

+34
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,37 @@ pre {
164164
}
165165
}
166166
}
167+
168+
.favorite-dashboard {
169+
display: flex;
170+
flex-wrap: wrap;
171+
gap: 1em;
172+
173+
.container {
174+
border: 1px solid @gray-light;
175+
border-radius: 1em;
176+
padding: 1em;
177+
width: 100%;
178+
179+
&:has(.empty-state) {
180+
max-height: 10em;
181+
}
182+
183+
> .content {
184+
padding: 0;
185+
}
186+
187+
> .progress-label {
188+
margin: 0;
189+
190+
span {
191+
font-size: 0.75em;
192+
}
193+
}
194+
}
195+
}
196+
197+
#layout.wide-layout:not(.twocols) .favorite-dashboard > .container:not(:only-child),
198+
#layout.default-layout:not(.twocols) .favorite-dashboard > .container:not(:only-child) {
199+
width: ~"calc(50% - 0.5em)";
200+
}

public/js/action-list.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
return;
9999
}
100100

101-
let dashboard = list.closest('.dashboard');
101+
let dashboard = list.closest('.dashboard') || list.closest('.favorite-dashboard');
102102
if (dashboard) {
103103
_this.clearDashboardSelections(dashboard, list);
104104
}

0 commit comments

Comments
 (0)