Adjust dashbaord conent layouts & don't redirect when sorting only dashlets

This commit is contained in:
Yonas Habteab 2022-04-07 17:58:29 +02:00
parent 96fbd28c56
commit 1f9d0547cd
17 changed files with 106 additions and 67 deletions

View File

@ -20,6 +20,7 @@ use Icinga\Web\Dashboard\Settings;
use Icinga\Web\Dashboard\Setup\SetupNewDashboard; use Icinga\Web\Dashboard\Setup\SetupNewDashboard;
use Icinga\Web\Notification; use Icinga\Web\Notification;
use Icinga\Web\Widget\Tabextension\DashboardSettings; use Icinga\Web\Widget\Tabextension\DashboardSettings;
use ipl\Html\HtmlElement;
use ipl\Web\Compat\CompatController; use ipl\Web\Compat\CompatController;
use ipl\Web\Url; use ipl\Web\Url;
use ipl\Web\Widget\ActionLink; use ipl\Web\Widget\ActionLink;
@ -58,11 +59,16 @@ class DashboardsController extends CompatController
})->handleRequest(ServerRequest::fromGlobals()); })->handleRequest(ServerRequest::fromGlobals());
$this->dashboard->setWelcomeForm($welcomeForm); $this->dashboard->setWelcomeForm($welcomeForm);
} elseif (($pane = $this->getParam('pane'))) { } else {
$pane = $this->getParam('pane');
if (! $pane) {
$pane = $this->dashboard->getActivePane()->getName();
}
$this->getTabs()->activate($pane); $this->getTabs()->activate($pane);
} }
$this->content = $this->dashboard; $this->addContent($this->dashboard);
} }
/** /**
@ -84,16 +90,21 @@ class DashboardsController extends CompatController
'title' => $activeHome->getTitle(), 'title' => $activeHome->getTitle(),
'url' => Url::fromRequest() 'url' => Url::fromRequest()
]); ]);
}
// Not to render the cog icon before the above tab // Not to render the cog icon before the above tab
$this->createTabs(); $this->createTabs();
} elseif (($pane = $this->getParam('pane'))) {
$this->createTabs(); if ($activeHome->hasEntries()) {
$pane = $this->getParam('pane');
if (! $pane) {
$pane = $this->dashboard->getActivePane()->getName();
}
$this->dashboard->activate($pane); $this->dashboard->activate($pane);
} }
$this->content = $this->dashboard; $this->addContent($this->dashboard);
} }
public function editHomeAction() public function editHomeAction()
@ -276,6 +287,7 @@ class DashboardsController extends CompatController
$dashboards = Json::decode($dashboards['dashboardData'], true); $dashboards = Json::decode($dashboards['dashboardData'], true);
$originals = $dashboards['originals']; $originals = $dashboards['originals'];
$widgetType = $dashboards['Type'];
unset($dashboards['Type']); unset($dashboards['Type']);
unset($dashboards['originals']); unset($dashboards['originals']);
@ -371,7 +383,13 @@ class DashboardsController extends CompatController
} }
} }
$this->redirectNow($reroutePath); if ($widgetType !== 'Dashlets' || ($orgHome && $orgPane)) {
$this->redirectNow($reroutePath);
}
// Just create a dummy content and ignore it, as we don't have any view scripts and aren't redirecting
$this->getResponse()->setHeader('X-Icinga-Container', 'ignore');
$this->addContent(new HtmlElement('p'));
} }
/** /**
@ -423,7 +441,7 @@ class DashboardsController extends CompatController
] ]
)); ));
$this->content = new Settings($this->dashboard); $this->addContent(new Settings($this->dashboard));
} }
/** /**

View File

@ -17,7 +17,7 @@ class SearchController extends CompatController
$searchDashboard->setUser($this->Auth()->getUser()); $searchDashboard->setUser($this->Auth()->getUser());
$this->controls->setTabs($searchDashboard->getTabs()); $this->controls->setTabs($searchDashboard->getTabs());
$this->content = $searchDashboard->search($this->getParam('q')); $this->addContent($searchDashboard->search($this->getParam('q')));
} }
public function hintAction() public function hintAction()

View File

@ -4,15 +4,15 @@
namespace Icinga\Model; namespace Icinga\Model;
use Icinga\Web\Dashboard;
use ipl\Orm\Model; use ipl\Orm\Model;
use ipl\Orm\Relations; use ipl\Orm\Relations;
use ipl\Sql\Expression;
class Dashlet extends Model class Dashlet extends Model
{ {
public function getTableName() public function getTableName()
{ {
return 'dashlet'; return Dashboard\Dashlet::TABLE;
} }
public function getKeyName() public function getKeyName()
@ -54,11 +54,13 @@ class Dashlet extends Model
public function createRelations(Relations $relations) public function createRelations(Relations $relations)
{ {
$relations->belongsTo('dashboard', Pane::class); $relations->belongsTo(Dashboard\Pane::TABLE, Pane::class)
//$relations->belongsTo('home', Home::class); ->setCandidateKey('dashboard_id');
//$relations->belongsTo(Dashboard\DashboardHome::TABLE, Home::class);
$relations->belongsToMany('module_dashlet', ModuleDashlet::class) $relations->belongsToMany('icingaweb_module_dashlet', ModuleDashlet::class)
->through(SystemDashlet::class) ->through(SystemDashlet::class)
->setForeignKey('dashlet_id')
->setJoinType('LEFT'); ->setJoinType('LEFT');
} }
} }

View File

@ -4,6 +4,8 @@
namespace Icinga\Model; namespace Icinga\Model;
use Icinga\Web\Dashboard\DashboardHome;
use Icinga\Web\Dashboard;
use ipl\Orm\Model; use ipl\Orm\Model;
use ipl\Orm\Relations; use ipl\Orm\Relations;
@ -11,7 +13,7 @@ class Home extends Model
{ {
public function getTableName() public function getTableName()
{ {
return 'dashboard_home'; return DashboardHome::TABLE;
} }
public function getKeyName() public function getKeyName()
@ -51,8 +53,8 @@ class Home extends Model
public function createRelations(Relations $relations) public function createRelations(Relations $relations)
{ {
$relations->hasMany('dashboard', Pane::class); $relations->hasMany(Dashboard\Pane::TABLE, Pane::class);
//$relations->hasMany('dashlet', Dashlet::class); //$relations->hasMany(Dashboard\Dashlet::TABLE, Dashlet::class);
} }
} }

View File

@ -4,6 +4,7 @@
namespace Icinga\Model; namespace Icinga\Model;
use Icinga\Web\Dashboard;
use ipl\Orm\Model; use ipl\Orm\Model;
use ipl\Orm\Relations; use ipl\Orm\Relations;
@ -11,7 +12,7 @@ class ModuleDashlet extends Model
{ {
public function getTableName() public function getTableName()
{ {
return 'module_dashlet'; return 'icingaweb_module_dashlet';
} }
public function getKeyName() public function getKeyName()
@ -52,13 +53,14 @@ class ModuleDashlet extends Model
public function getDefaultSort() public function getDefaultSort()
{ {
return ['module_dashlet.name', 'module_dashlet.priority']; return ['name', 'priority'];
} }
public function createRelations(Relations $relations) public function createRelations(Relations $relations)
{ {
$relations->belongsToMany('dashlet', Dashlet::class) $relations->belongsToMany(Dashboard\Dashlet::TABLE, Dashlet::class)
->through(SystemDashlet::class) ->through(SystemDashlet::class)
->setForeignKey('module_dashlet_id')
->setJoinType('LEFT'); ->setJoinType('LEFT');
} }
} }

View File

@ -4,15 +4,15 @@
namespace Icinga\Model; namespace Icinga\Model;
use Icinga\Web\Dashboard;
use ipl\Orm\Model; use ipl\Orm\Model;
use ipl\Orm\Relations; use ipl\Orm\Relations;
use ipl\Sql\Expression;
class Pane extends Model class Pane extends Model
{ {
public function getTableName() public function getTableName()
{ {
return 'dashboard'; return Dashboard\Pane::TABLE;
} }
public function getKeyName() public function getKeyName()
@ -48,15 +48,16 @@ class Pane extends Model
public function getDefaultSort() public function getDefaultSort()
{ {
return 'dashboard.name'; return 'icingaweb_dashboard.name';
} }
public function createRelations(Relations $relations) public function createRelations(Relations $relations)
{ {
$relations->belongsTo('home', Home::class) $relations->belongsTo(Dashboard\DashboardHome::TABLE, Home::class)
->setCandidateKey('home_id'); ->setCandidateKey('home_id');
$relations->hasMany('dashlet', Dashlet::class) $relations->hasMany(Dashboard\Dashlet::TABLE, Dashlet::class)
->setForeignKey('dashboard_id')
->setJoinType('LEFT'); ->setJoinType('LEFT');
} }
} }

View File

@ -4,6 +4,7 @@
namespace Icinga\Model; namespace Icinga\Model;
use Icinga\Web\Dashboard;
use ipl\Orm\Model; use ipl\Orm\Model;
use ipl\Orm\Relations; use ipl\Orm\Relations;
@ -11,7 +12,7 @@ class SystemDashlet extends Model
{ {
public function getTableName() public function getTableName()
{ {
return 'dashlet_system'; return 'icingaweb_system_dashlet';
} }
public function getKeyName() public function getKeyName()
@ -30,7 +31,8 @@ class SystemDashlet extends Model
public function createRelations(Relations $relations) public function createRelations(Relations $relations)
{ {
$relations->belongsTo('dashlet', Dashlet::class); $relations->belongsTo(Dashboard\Dashlet::TABLE, Dashlet::class);
$relations->belongsTo('module_dashlet', ModuleDashlet::class); $relations->belongsTo('icingaweb_module_dashlet', ModuleDashlet::class)
->setCandidateKey('module_dashlet_id');
} }
} }

View File

@ -247,7 +247,7 @@ trait DashboardManager
/** /**
* Browse all enabled modules configuration file and import all dashboards * Browse all enabled modules configuration file and import all dashboards
* provided by them into the DB table `module_dashlet` * provided by them into the DB table `icingaweb_module_dashlet`
* *
* @return void * @return void
*/ */
@ -261,6 +261,7 @@ trait DashboardManager
$pane->setTitle($dashboardPane->getLabel()); $pane->setTitle($dashboardPane->getLabel());
$pane->fromArray($dashboardPane->getAttributes()); $pane->fromArray($dashboardPane->getAttributes());
$priority = 0;
foreach ($dashboardPane->getIterator()->getItems() as $dashletItem) { foreach ($dashboardPane->getIterator()->getItems() as $dashletItem) {
$uuid = self::getSHA1($module->getName() . $pane->getName() . $dashletItem->getName()); $uuid = self::getSHA1($module->getName() . $pane->getName() . $dashletItem->getName());
$dashlet = new Dashlet($dashletItem->getName(), $dashletItem->getUrl(), $pane); $dashlet = new Dashlet($dashletItem->getName(), $dashletItem->getUrl(), $pane);
@ -269,7 +270,7 @@ trait DashboardManager
->setUuid($uuid) ->setUuid($uuid)
->setModule($module->getName()) ->setModule($module->getName())
->setModuleDashlet(true) ->setModuleDashlet(true)
->setPriority($dashletItem->getPriority()); ->setPriority($priority++);
self::updateOrInsertModuleDashlet($dashlet); self::updateOrInsertModuleDashlet($dashlet);
$pane->addEntry($dashlet); $pane->addEntry($dashlet);
@ -288,12 +289,9 @@ trait DashboardManager
$newDashlet $newDashlet
->setUuid($identifier) ->setUuid($identifier)
->setModule($module->getName()) ->setModule($module->getName())
->setPriority($priority++)
->setModuleDashlet(true); ->setModuleDashlet(true);
if (! $newDashlet->getPriority()) {
$newDashlet->setPriority($priority);
}
self::updateOrInsertModuleDashlet($newDashlet); self::updateOrInsertModuleDashlet($newDashlet);
$priority++; $priority++;
} }
@ -330,7 +328,7 @@ trait DashboardManager
} }
if (! self::moduleDashletExist($dashlet)) { if (! self::moduleDashletExist($dashlet)) {
self::getConn()->insert('module_dashlet', [ self::getConn()->insert('icingaweb_module_dashlet', [
'id' => $dashlet->getUuid(), 'id' => $dashlet->getUuid(),
'name' => $dashlet->getName(), 'name' => $dashlet->getName(),
'label' => $dashlet->getTitle(), 'label' => $dashlet->getTitle(),
@ -341,7 +339,7 @@ trait DashboardManager
'priority' => $dashlet->getPriority() 'priority' => $dashlet->getPriority()
]); ]);
} else { } else {
self::getConn()->update('module_dashlet', [ self::getConn()->update('icingaweb_module_dashlet', [
'label' => $dashlet->getTitle(), 'label' => $dashlet->getTitle(),
'url' => $dashlet->getUrl()->getRelativeUrl(), 'url' => $dashlet->getUrl()->getRelativeUrl(),
'description' => $dashlet->getDescription(), 'description' => $dashlet->getDescription(),

View File

@ -68,7 +68,7 @@ class Dashboard extends BaseHtmlElement implements DashboardEntry
protected $tag = 'div'; protected $tag = 'div';
protected $defaultAttributes = ['class' => 'dashboard content']; protected $defaultAttributes = ['class' => 'dashboard'];
/** /**
* The @see Tabs object for displaying displayable panes * The @see Tabs object for displaying displayable panes
@ -235,11 +235,10 @@ class Dashboard extends BaseHtmlElement implements DashboardEntry
{ {
$activeHome = $this->getActiveHome(); $activeHome = $this->getActiveHome();
if (! $activeHome || (! $activeHome->hasEntries() && $activeHome->getName() === DashboardHome::DEFAULT_HOME)) { if (! $activeHome || (! $activeHome->hasEntries() && $activeHome->getName() === DashboardHome::DEFAULT_HOME)) {
$this->setAttribute('class', 'content welcome-view'); $this->setAttribute('class', 'dashboard-introduction welcome-view');
$wrapper = HtmlElement::create('div', ['class' => 'dashboard-introduction']);
$wrapper->addHtml(HtmlElement::create('h1', null, t('Welcome to Icinga Web 2!'))); $this->addHtml(HtmlElement::create('h1', null, t('Welcome to Icinga Web 2!')));
$wrapper->addHtml(HtmlElement::create( $this->addHtml(HtmlElement::create(
'p', 'p',
null, null,
t('You will see this screen every time you log in and haven\'t created any dashboards yet.') t('You will see this screen every time you log in and haven\'t created any dashboards yet.')
@ -249,25 +248,23 @@ class Dashboard extends BaseHtmlElement implements DashboardEntry
'At the moment this view is empty, but you can populate it with small portions of' 'At the moment this view is empty, but you can populate it with small portions of'
. ' information called Dashlets.' . ' information called Dashlets.'
); );
$wrapper->addHtml(HtmlElement::create('p', null, $message)); $this->addHtml(HtmlElement::create('p', null, $message));
$message = t( $message = t(
'Now you can either customize which dashlets to display, or use the system default dashlets.' 'Now you can either customize which dashlets to display, or use the system default dashlets.'
. ' You will be always able to edit them afterwards.' . ' You will be always able to edit them afterwards.'
); );
$wrapper->addHtml(HtmlElement::create('p', null, $message)); $this->addHtml(HtmlElement::create('p', null, $message));
$wrapper->addHtml($this->welcomeForm); $this->addHtml($this->welcomeForm);
$this->addHtml($wrapper); //$this->addHtml($wrapper);
} elseif (! $activeHome->hasEntries()) { } elseif (! $activeHome->hasEntries()) {
$this->setAttribute('class', 'content');
$this->addHtml(HtmlElement::create('h1', null, t('No dashboard added to this dashboard home'))); $this->addHtml(HtmlElement::create('h1', null, t('No dashboard added to this dashboard home')));
} else { } else {
$activePane = $this->getActivePane(); $activePane = $this->getActivePane();
$this->setAttribute('data-icinga-pane', $activeHome->getName() . '|' . $this->getActivePane()->getName()); $this->setAttribute('data-icinga-pane', $activeHome->getName() . '|' . $this->getActivePane()->getName());
if (! $activePane->hasEntries()) { if (! $activePane->hasEntries()) {
$this->setAttribute('class', 'content');
$this->addHtml(HtmlElement::create('h1', null, t('No dashlet added to this pane.'))); $this->addHtml(HtmlElement::create('h1', null, t('No dashlet added to this pane.')));
} else { } else {
foreach ($activePane->getEntries() as $dashlet) { foreach ($activePane->getEntries() as $dashlet) {

View File

@ -29,7 +29,7 @@ class DashboardHome extends BaseDashboard implements Sortable
* *
* @var string * @var string
*/ */
const TABLE = 'dashboard_home'; const TABLE = 'icingaweb_dashboard_home';
/** /**
* A type of this dashboard home * A type of this dashboard home
@ -139,7 +139,7 @@ class DashboardHome extends BaseDashboard implements Sortable
} }
$this->setEntries([]); $this->setEntries([]);
$panes = \Icinga\Model\Pane::on(Dashboard::getConn())->utilize('home'); $panes = \Icinga\Model\Pane::on(Dashboard::getConn())->utilize(self::TABLE);
$panes $panes
->filter(Filter::equal('home_id', $this->getUuid())) ->filter(Filter::equal('home_id', $this->getUuid()))
->filter(Filter::equal('username', Dashboard::getUser()->getUsername())); ->filter(Filter::equal('username', Dashboard::getUser()->getUsername()));

View File

@ -22,7 +22,7 @@ class Dashlet extends BaseDashboard
use ModuleDashlet; use ModuleDashlet;
/** @var string Database table name */ /** @var string Database table name */
const TABLE = 'dashlet'; const TABLE = 'icingaweb_dashlet';
/** /**
* The url of this Dashlet * The url of this Dashlet

View File

@ -22,7 +22,7 @@ class Pane extends BaseDashboard implements Sortable
{ {
use DashboardControls; use DashboardControls;
const TABLE = 'dashboard'; const TABLE = 'icingaweb_dashboard';
/** /**
* A dashboard home this pane is a part of * A dashboard home this pane is a part of
@ -129,8 +129,8 @@ class Pane extends BaseDashboard implements Sortable
public function loadDashboardEntries($name = '') public function loadDashboardEntries($name = '')
{ {
$dashlets = Model\Dashlet::on(Dashboard::getConn()) $dashlets = Model\Dashlet::on(Dashboard::getConn())
->utilize('dashboard') ->utilize(self::TABLE)
->with('module_dashlet'); ->with('icingaweb_module_dashlet');
$dashlets->filter(Filter::equal('dashboard_id', $this->getUuid())); $dashlets->filter(Filter::equal('dashboard_id', $this->getUuid()));
$this->setEntries([]); $this->setEntries([]);
@ -141,7 +141,7 @@ class Pane extends BaseDashboard implements Sortable
'title' => $dashlet->label, 'title' => $dashlet->label,
'priority' => $dashlet->priority, 'priority' => $dashlet->priority,
'pane' => $this, 'pane' => $this,
'description' => $dashlet->module_dashlet->description 'description' => $dashlet->icingaweb_module_dashlet->description
]); ]);
$this->addDashlet($newDashlet); $this->addDashlet($newDashlet);
@ -202,7 +202,7 @@ class Pane extends BaseDashboard implements Sortable
} }
if ($systemUuid) { if ($systemUuid) {
$conn->insert('dashlet_system', [ $conn->insert('icingaweb_system_dashlet', [
'dashlet_id' => $uuid, 'dashlet_id' => $uuid,
'module_dashlet_id' => $systemUuid 'module_dashlet_id' => $systemUuid
]); ]);

View File

@ -12,7 +12,7 @@ use ipl\Web\Widget\ActionLink;
class Settings extends BaseHtmlElement class Settings extends BaseHtmlElement
{ {
protected $defaultAttributes = ['class' => 'content dashboard-settings']; protected $defaultAttributes = ['class' => 'dashboard-settings'];
protected $tag = 'div'; protected $tag = 'div';

View File

@ -137,6 +137,10 @@
} }
// Dashboard manager // Dashboard manager
:not(.dashboard) > .container > .content {
padding-top: 0;
}
.dashboard-settings { .dashboard-settings {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -306,8 +310,15 @@ form.icinga-form .control-group.form-controls .remove-button {
} }
.control-group.form-controls .modal-cancel { .control-group.form-controls .modal-cancel {
background-color: @low-sat-blue; .button();
border: none; border: none;
color: @icinga-blue;
background-color: @low-sat-blue;
&:hover {
color: @text-color-on-icinga-blue;
background-color: @icinga-blue;
}
} }
// Drag and drop // Drag and drop

View File

@ -183,7 +183,7 @@
// Dashboard grid // Dashboard grid
.dashboard { .dashboard {
letter-spacing: -0.417em; //letter-spacing: -0.417em;
> .container { > .container {
display: inline-block; display: inline-block;

View File

@ -119,7 +119,7 @@
} }
} }
.dashboard.content > .container { .dashboard > .container {
overflow-x: auto; overflow-x: auto;
} }

View File

@ -28,9 +28,10 @@
this.widgetTypes = { Dashlet : 'Dashlets', Dashboard : 'Dashboards', DashboardHome : 'Homes' }; this.widgetTypes = { Dashlet : 'Dashlets', Dashboard : 'Dashboards', DashboardHome : 'Homes' };
this.on('rendered', '#main > .container', this.onRendered, this); this.on('rendered', '#main > .container', this.onRendered, this);
this.on('end', '.dashboard-settings, .dashboard-list-control, .dashlet-list-item', this.elementDropped, this); // Registers all drop events for all the widget types
this.on('end', '.dashboard-settings', this.elementDropped, this);
// This is for the normal dashboard/dashlets view // This is for the normal dashboard/dashlets view
this.on('end', '.dashboard.content', this.elementDropped, this); this.on('end', '.content > .dashboard', this.elementDropped, this);
} }
/** /**
@ -49,7 +50,7 @@
return this.widgetTypes.DashboardHome; return this.widgetTypes.DashboardHome;
} else if (target.matches('.dashboard-item-list')) { } else if (target.matches('.dashboard-item-list')) {
return this.widgetTypes.Dashboard; return this.widgetTypes.Dashboard;
} else if (target.matches('.dashlet-item-list') || target.matches('.dashboard.content')) { } else if (target.matches('.dashlet-item-list') || target.matches('.content > .dashboard')) {
return this.widgetTypes.Dashlet; return this.widgetTypes.Dashlet;
} }
@ -98,7 +99,7 @@
pane, pane,
home; home;
if (orgEvt.to.matches('.dashboard.content')) { if (orgEvt.to.matches('.content > .dashboard')) {
let parentData = orgEvt.to.dataset.icingaPane.split('|', 2); let parentData = orgEvt.to.dataset.icingaPane.split('|', 2);
home = parentData.shift(); home = parentData.shift();
pane = parentData.shift(); pane = parentData.shift();
@ -137,13 +138,18 @@
data = { dashboardData : JSON.stringify(data) }; data = { dashboardData : JSON.stringify(data) };
let url = _this.icinga.config.baseUrl + '/dashboards/reorder-widgets'; let url = _this.icinga.config.baseUrl + '/dashboards/reorder-widgets';
_this.icinga.loader.loadUrl(url, $('#col1'), data, 'post'); let req = _this.icinga.loader.loadUrl(url, $('#col1'), data, 'post');
if (data.Type === _this.widgetTypes.Dashlet && data.originals === null) {
req.addToHistory = false;
req.scripted = true;
}
} }
} }
onRendered(e) { onRendered(e) {
let _this = e.data.self; let _this = e.data.self;
e.target.querySelectorAll('.dashboard-settings, .dashboard.content,' e.target.querySelectorAll('.dashboard-settings, .content > .dashboard,'
+ ' .dashboard-item-list, .dashlet-item-list') + ' .dashboard-item-list, .dashlet-item-list')
.forEach(sortable => { .forEach(sortable => {
let groupName = _this.getTypeFor(sortable), let groupName = _this.getTypeFor(sortable),
@ -163,7 +169,7 @@
break; break;
case _this.widgetTypes.Dashlet: case _this.widgetTypes.Dashlet:
groupName = _this.widgetTypes.Dashlet; groupName = _this.widgetTypes.Dashlet;
if (sortable.matches('.dashboard.content')) { if (sortable.matches('.content > .dashboard')) {
draggable = '> .container'; draggable = '> .container';
} else { } else {
draggable = '.dashlet-list-item'; draggable = '.dashlet-list-item';