summaryrefslogtreecommitdiffstats
path: root/library/Director/Dashboard
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/Director/Dashboard/AlertsDashboard.php19
-rw-r--r--library/Director/Dashboard/AutomationDashboard.php17
-rw-r--r--library/Director/Dashboard/BranchesDashboard.php36
-rw-r--r--library/Director/Dashboard/CommandsDashboard.php35
-rw-r--r--library/Director/Dashboard/Dashboard.php305
-rw-r--r--library/Director/Dashboard/Dashlet/ActivityLogDashlet.php35
-rw-r--r--library/Director/Dashboard/Dashlet/ApiUserObjectDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/BasketDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/CheckCommandsDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/ChoicesDashlet.php41
-rw-r--r--library/Director/Dashboard/Dashlet/CommandObjectDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/CommandTemplatesDashlet.php26
-rw-r--r--library/Director/Dashboard/Dashlet/CustomvarDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/Dashlet.php239
-rw-r--r--library/Director/Dashboard/Dashlet/DatafieldCategoryDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/DatafieldDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/DatalistDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/DependencyObjectDashlet.php26
-rw-r--r--library/Director/Dashboard/Dashlet/DeploymentDashlet.php114
-rw-r--r--library/Director/Dashboard/Dashlet/EndpointObjectDashlet.php63
-rw-r--r--library/Director/Dashboard/Dashlet/ExternalCheckCommandsDashlet.php26
-rw-r--r--library/Director/Dashboard/Dashlet/ExternalNotificationCommandsDashlet.php21
-rw-r--r--library/Director/Dashboard/Dashlet/HostChoicesDashlet.php7
-rw-r--r--library/Director/Dashboard/Dashlet/HostGroupsDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/HostObjectDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/HostTemplatesDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/HostsDashlet.php32
-rw-r--r--library/Director/Dashboard/Dashlet/ImportSourceDashlet.php65
-rw-r--r--library/Director/Dashboard/Dashlet/InfrastructureDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/JobDashlet.php65
-rw-r--r--library/Director/Dashboard/Dashlet/KickstartDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/NotificationApplyDashlet.php37
-rw-r--r--library/Director/Dashboard/Dashlet/NotificationCommandsDashlet.php21
-rw-r--r--library/Director/Dashboard/Dashlet/NotificationTemplateDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/NotificationsDashlet.php33
-rw-r--r--library/Director/Dashboard/Dashlet/ScheduledDowntimeApplyDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/SelfServiceDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceApplyRulesDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceChoicesDashlet.php7
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceGroupsDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceObjectDashlet.php34
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceSetsDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/ServiceTemplatesDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/SettingsDashlet.php30
-rw-r--r--library/Director/Dashboard/Dashlet/SingleServicesDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/SyncDashlet.php65
-rw-r--r--library/Director/Dashboard/Dashlet/TimeperiodObjectDashlet.php28
-rw-r--r--library/Director/Dashboard/Dashlet/TimeperiodTemplateDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/TimeperiodsDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/UserGroupsDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/UserObjectDashlet.php23
-rw-r--r--library/Director/Dashboard/Dashlet/UserTemplateDashlet.php31
-rw-r--r--library/Director/Dashboard/Dashlet/UsersDashlet.php25
-rw-r--r--library/Director/Dashboard/Dashlet/ZoneObjectDashlet.php25
-rw-r--r--library/Director/Dashboard/DataDashboard.php18
-rw-r--r--library/Director/Dashboard/DeploymentDashboard.php17
-rw-r--r--library/Director/Dashboard/DirectorDashboard.php17
-rw-r--r--library/Director/Dashboard/HostsDashboard.php35
-rw-r--r--library/Director/Dashboard/InfrastructureDashboard.php60
-rw-r--r--library/Director/Dashboard/NotificationsDashboard.php44
-rw-r--r--library/Director/Dashboard/ObjectsDashboard.php17
-rw-r--r--library/Director/Dashboard/ServicesDashboard.php39
-rw-r--r--library/Director/Dashboard/TimeperiodsDashboard.php33
-rw-r--r--library/Director/Dashboard/UsersDashboard.php36
64 files changed, 2555 insertions, 0 deletions
diff --git a/library/Director/Dashboard/AlertsDashboard.php b/library/Director/Dashboard/AlertsDashboard.php
new file mode 100644
index 0000000..447f74f
--- /dev/null
+++ b/library/Director/Dashboard/AlertsDashboard.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class AlertsDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'Notifications',
+ 'Users',
+ 'Timeperiods',
+ 'DependencyObject',
+ 'ScheduledDowntimeApply',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Get alerts when something goes wrong');
+ }
+}
diff --git a/library/Director/Dashboard/AutomationDashboard.php b/library/Director/Dashboard/AutomationDashboard.php
new file mode 100644
index 0000000..dd07d71
--- /dev/null
+++ b/library/Director/Dashboard/AutomationDashboard.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class AutomationDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'ImportSource',
+ 'Sync',
+ 'Job'
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Automate all tasks');
+ }
+}
diff --git a/library/Director/Dashboard/BranchesDashboard.php b/library/Director/Dashboard/BranchesDashboard.php
new file mode 100644
index 0000000..fe8b385
--- /dev/null
+++ b/library/Director/Dashboard/BranchesDashboard.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+use gipfl\Web\Widget\Hint;
+use Icinga\Application\Hook;
+use Icinga\Module\Director\Db\Branch\Branch;
+use Icinga\Module\Director\Db\Branch\BranchStore;
+use Icinga\Module\Director\Hook\BranchSupportHook;
+use ipl\Html\Html;
+
+class BranchesDashboard extends Dashboard
+{
+ public function getTitle()
+ {
+ $branch = Branch::detect(new BranchStore($this->getDb()));
+ if ($branch->isBranch()) {
+ $this->prepend(Hint::info(Html::sprintf(
+ $this->translate('You\'re currently working in a Configuration Branch: %s'),
+ Branch::requireHook()->linkToBranch($branch, $this->getAuth(), $branch->getName())
+ )));
+ }
+
+ return $this->translate('Prepare your configuration in a safe Environment');
+ }
+
+ public function loadDashlets()
+ {
+ /** @var BranchSupportHook $hook */
+ if ($hook = Hook::first('director/BranchSupport')) {
+ $this->dashlets = $hook->loadDashlets($this->getDb());
+ } else {
+ $this->dashlets = [];
+ }
+ }
+}
diff --git a/library/Director/Dashboard/CommandsDashboard.php b/library/Director/Dashboard/CommandsDashboard.php
new file mode 100644
index 0000000..13f4e42
--- /dev/null
+++ b/library/Director/Dashboard/CommandsDashboard.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class CommandsDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'CheckCommands',
+ 'ExternalCheckCommands',
+ // 'NotificationCommands',
+ // 'ExternalNotificationCommands',
+ 'CommandTemplates',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Manage your Icinga Commands');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'Define Check-, Notification- or Event-Commands. Command definitions'
+ . ' are the glue between your Host- and Service-Checks and the Check'
+ . ' plugins on your Monitoring (or monitored) systems'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['hosts', 'services', 'commands']
+ );
+ }
+}
diff --git a/library/Director/Dashboard/Dashboard.php b/library/Director/Dashboard/Dashboard.php
new file mode 100644
index 0000000..de8970c
--- /dev/null
+++ b/library/Director/Dashboard/Dashboard.php
@@ -0,0 +1,305 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+use Exception;
+use gipfl\Translation\TranslationHelper;
+use gipfl\IcingaWeb2\Widget\Tabs;
+use ipl\Html\Html;
+use ipl\Html\HtmlDocument;
+use ipl\Html\HtmlString;
+use Icinga\Authentication\Auth;
+use Icinga\Module\Director\Objects\IcingaObject;
+use Icinga\Module\Director\Restriction\HostgroupRestriction;
+use Icinga\Module\Director\Dashboard\Dashlet\Dashlet;
+use Icinga\Module\Director\Db;
+use Icinga\Web\Widget\Tab;
+use ipl\Html\ValidHtml;
+use Zend_Db_Select as ZfSelect;
+
+abstract class Dashboard extends HtmlDocument
+{
+ use TranslationHelper;
+
+ protected $name;
+
+ /** @var Dashlet[] */
+ protected $dashlets;
+
+ protected $dashletNames;
+
+ /** @var Db */
+ protected $db;
+
+ final private function __construct()
+ {
+ }
+
+ /**
+ * @param $name
+ * @param Db $db
+ *
+ * @return self
+ */
+ public static function loadByName($name, Db $db)
+ {
+ $class = __NAMESPACE__ . '\\' . ucfirst($name) . 'Dashboard';
+ $dashboard = new $class();
+ $dashboard->db = $db;
+ $dashboard->name = $name;
+ return $dashboard;
+ }
+
+ public static function exists($name)
+ {
+ return class_exists(__NAMESPACE__ . '\\' . ucfirst($name) . 'Dashboard');
+ }
+
+ /**
+ * @param $description
+ * @return $this
+ */
+ protected function addDescription($description)
+ {
+ if ($description instanceof ValidHtml) {
+ $this->add(Html::tag('p', $description));
+ } elseif ($description !== null) {
+ $this->add(Html::tag(
+ 'p',
+ null,
+ HtmlString::create(nl2br(Html::escape($description)))
+ ));
+ }
+
+ return $this;
+ }
+
+ public function render()
+ {
+ $this
+ ->setSeparator("\n")
+ ->add(Html::tag('h1', null, $this->getTitle()))
+ ->addDescription($this->getDescription())
+ ->add($this->renderDashlets());
+
+ return parent::render();
+ }
+
+ public function renderDashlets()
+ {
+ $ul = Html::tag('ul', [
+ 'class' => 'main-actions',
+ 'data-base-target' => '_next'
+ ]);
+
+ foreach ($this->dashlets() as $dashlet) {
+ if ($dashlet->shouldBeShown()) {
+ $ul->add($dashlet);
+ }
+ }
+
+ return $ul;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ abstract public function getTitle();
+
+ public function getDescription()
+ {
+ return null;
+ }
+
+ public function getTabs()
+ {
+ $lName = $this->getName();
+ $tabs = new Tabs();
+ $tabs->add($lName, new Tab([
+ 'label' => $this->translate(ucfirst($this->getName())),
+ 'url' => 'director/dashboard',
+ 'urlParams' => ['name' => $lName]
+ ]));
+
+ return $tabs;
+ }
+
+ protected function createTabsForDashboards($names)
+ {
+ $tabs = new Tabs();
+ foreach ($names as $name) {
+ $dashboard = Dashboard::loadByName($name, $this->getDb());
+ if ($dashboard->isAvailable()) {
+ $tabs->add($name, $this->createTabForDashboard($dashboard));
+ }
+ }
+
+ return $tabs;
+ }
+
+ protected function createTabForDashboard(Dashboard $dashboard)
+ {
+ $name = $dashboard->getName();
+ return new Tab([
+ 'label' => $this->translate(ucfirst($name)),
+ 'url' => 'director/dashboard',
+ 'urlParams' => ['name' => $name]
+ ]);
+ }
+
+ public function count()
+ {
+ return count($this->dashlets());
+ }
+
+ public function isAvailable()
+ {
+ return $this->count() > 0;
+ }
+
+ public function getDb()
+ {
+ return $this->db;
+ }
+
+ public function dashlets()
+ {
+ if ($this->dashlets === null) {
+ $this->loadDashlets();
+ $this->fetchDashletSummaries();
+ }
+
+ return $this->dashlets;
+ }
+
+ public function loadDashlets()
+ {
+ $names = $this->getDashletNames();
+
+ if (empty($names)) {
+ $this->dashlets = array();
+ } else {
+ $this->dashlets = Dashlet::loadByNames(
+ $this->dashletNames,
+ $this->getDb()
+ );
+ }
+ }
+
+ public function getDashletNames()
+ {
+ return $this->dashletNames;
+ }
+
+ protected function fetchDashletSummaries()
+ {
+ $types = array();
+ foreach ($this->dashlets as $dashlet) {
+ foreach ($dashlet->listRequiredStats() as $objectType) {
+ $types[$objectType] = $objectType;
+ }
+ }
+
+ if (empty($types)) {
+ return;
+ }
+
+ try {
+ $stats = $this->getObjectSummary($types);
+ } catch (Exception $e) {
+ $stats = array();
+ }
+
+ $failing = array();
+ foreach ($this->dashlets as $key => $dashlet) {
+ foreach ($dashlet->listRequiredStats() as $objectType) {
+ if (array_key_exists($objectType, $stats)) {
+ $dashlet->addStats($objectType, $stats[$objectType]);
+ } else {
+ $failing[] = $key;
+ }
+ }
+ }
+
+ foreach ($failing as $key) {
+ unset($this->dashlets[$key]);
+ }
+ }
+
+ public function getObjectSummary($types)
+ {
+ $queries = array();
+
+ foreach ($types as $type) {
+ $queries[] = $this->makeSummaryQuery($type);
+ }
+ $query = $this->db->select()->union($queries, ZfSelect::SQL_UNION_ALL);
+
+ $result = array();
+ foreach ($this->db->fetchAll($query) as $row) {
+ $result[$row->icinga_type] = $row;
+ }
+
+ return $result;
+ }
+
+ protected function makeSummaryQuery($type)
+ {
+ $columns = array(
+ 'icinga_type' => "('" . $type . "')",
+ 'cnt_object' => $this->getCntSql('object'),
+ 'cnt_template' => $this->getCntSql('template'),
+ 'cnt_external' => $this->getCntSql('external_object'),
+ 'cnt_apply' => $this->getCntSql('apply'),
+ 'cnt_total' => 'COUNT(*)',
+ );
+
+ if ($this->db->isPgsql()) {
+ $dummy = IcingaObject::createByType($type);
+ if (! $dummy->supportsApplyRules()) {
+ $columns['cnt_apply'] = '(0)';
+ }
+ }
+
+ $query = $this->db->getDbAdapter()->select()->from(
+ array('o' => 'icinga_' . $type),
+ $columns
+ );
+
+ return $this->applyRestrictions($type, $query);
+ }
+
+ protected function applyRestrictions($type, $query)
+ {
+ switch ($type) {
+ case 'host':
+ case 'hostgroup':
+ $r = new HostgroupRestriction($this->getDb(), $this->getAuth());
+ $r->applyToQuery($query);
+ break;
+ }
+
+ return $query;
+ }
+
+ protected function applyHostgroupRestrictions($query)
+ {
+ $restrictions = new HostgroupRestriction($this->getDb(), $this->getAuth());
+ $restrictions->applyToHostGroupsQuery($query);
+ }
+
+ protected function getAuth()
+ {
+ return Auth::getInstance();
+ }
+
+ protected function getCntSql($objectType)
+ {
+ return sprintf(
+ "COALESCE(SUM(CASE WHEN o.object_type = '%s' THEN 1 ELSE 0 END), 0)",
+ $objectType
+ );
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ActivityLogDashlet.php b/library/Director/Dashboard/Dashlet/ActivityLogDashlet.php
new file mode 100644
index 0000000..9794986
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ActivityLogDashlet.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ActivityLogDashlet extends Dashlet
+{
+ protected $icon = 'book';
+
+ public function getTitle()
+ {
+ return $this->translate('Activity Log');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Wondering about what changed why? Track your changes!'
+ );
+ }
+
+ public function listCssClasses()
+ {
+ return 'state-ok';
+ }
+
+ public function getUrl()
+ {
+ return 'director/config/activities';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/audit');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ApiUserObjectDashlet.php b/library/Director/Dashboard/Dashlet/ApiUserObjectDashlet.php
new file mode 100644
index 0000000..419859d
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ApiUserObjectDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ApiUserObjectDashlet extends Dashlet
+{
+ protected $icon = 'lock-open-alt';
+
+ protected $requiredStats = array('apiuser');
+
+ public function getTitle()
+ {
+ return $this->translate('Icinga Api users');
+ }
+
+ public function getUrl()
+ {
+ return 'director/apiusers';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/BasketDashlet.php b/library/Director/Dashboard/Dashlet/BasketDashlet.php
new file mode 100644
index 0000000..10f2b81
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/BasketDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class BasketDashlet extends Dashlet
+{
+ protected $icon = 'tag';
+
+ public function getTitle()
+ {
+ return $this->translate('Configuration Baskets');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Preserve specific configuration objects in a specific state'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/baskets';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/CheckCommandsDashlet.php b/library/Director/Dashboard/Dashlet/CheckCommandsDashlet.php
new file mode 100644
index 0000000..65d8c8c
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/CheckCommandsDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class CheckCommandsDashlet extends Dashlet
+{
+ protected $icon = 'wrench';
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Manage definitions for your Commands that should be executed as'
+ . ' Check Plugins, Notifications or based on Events'
+ );
+ }
+
+ public function getTitle()
+ {
+ return $this->translate('Commands');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+
+ public function getUrl()
+ {
+ return 'director/commands';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ChoicesDashlet.php b/library/Director/Dashboard/Dashlet/ChoicesDashlet.php
new file mode 100644
index 0000000..efdbba5
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ChoicesDashlet.php
@@ -0,0 +1,41 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+abstract class ChoicesDashlet extends Dashlet
+{
+ protected $icon = 'flapping';
+
+ public function getTitle()
+ {
+ return $this->translate('Choices');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Combine multiple templates into meaningful Choices, making life'
+ . ' easier for your users'
+ );
+ }
+
+ protected function getType()
+ {
+ return strtolower(substr(
+ substr(get_called_class(), strlen(__NAMESPACE__) + 1),
+ 0,
+ - strlen('ChoicesDashlet')
+ ));
+ }
+
+ public function getUrl()
+ {
+
+ return 'director/templatechoices/' . $this->getType();
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/CommandObjectDashlet.php b/library/Director/Dashboard/Dashlet/CommandObjectDashlet.php
new file mode 100644
index 0000000..083172e
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/CommandObjectDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class CommandObjectDashlet extends Dashlet
+{
+ protected $icon = 'wrench';
+
+ protected $requiredStats = array('command');
+
+ public function getTitle()
+ {
+ return $this->translate('Commands');
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=commands';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/CommandTemplatesDashlet.php b/library/Director/Dashboard/Dashlet/CommandTemplatesDashlet.php
new file mode 100644
index 0000000..512298a
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/CommandTemplatesDashlet.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class CommandTemplatesDashlet extends CheckCommandsDashlet
+{
+ protected $icon = 'cubes';
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'External Notification Commands have been defined in your local Icinga 2'
+ . ' Configuration.'
+ );
+ }
+
+ public function getTitle()
+ {
+ return $this->translate('Command Templates');
+ }
+
+ public function getUrl()
+ {
+ return 'director/commands/templates';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/CustomvarDashlet.php b/library/Director/Dashboard/Dashlet/CustomvarDashlet.php
new file mode 100644
index 0000000..919c06b
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/CustomvarDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class CustomvarDashlet extends Dashlet
+{
+ protected $icon = 'keyboard';
+
+ public function getTitle()
+ {
+ return $this->translate('CustomVar Overview');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Get an overview of used CustomVars and their variants'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/data/vars';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/Dashlet.php b/library/Director/Dashboard/Dashlet/Dashlet.php
new file mode 100644
index 0000000..f8bc708
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/Dashlet.php
@@ -0,0 +1,239 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Icinga\Module\Director\Acl;
+use Icinga\Module\Director\Db;
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\Html;
+use gipfl\IcingaWeb2\Icon;
+use gipfl\IcingaWeb2\Link;
+use gipfl\Translation\TranslationHelper;
+
+abstract class Dashlet extends BaseHtmlElement
+{
+ use TranslationHelper;
+
+ /** @var Db */
+ protected $db;
+
+ protected $tag = 'li';
+
+ protected $icon = 'help';
+
+ protected $stats;
+
+ protected $requiredStats = [];
+
+ public function __construct(Db $db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function listRequiredStats()
+ {
+ return $this->requiredStats;
+ }
+
+ public function addStats($type, $stats)
+ {
+ $this->stats[$type] = $stats;
+ }
+
+ /**
+ * @param $name
+ * @param Db $db
+ * @return Dashlet
+ */
+ public static function loadByName($name, Db $db)
+ {
+ /** @var Dashlet */
+ $class = __NAMESPACE__ . '\\' . $name . 'Dashlet';
+ return new $class($db);
+ }
+
+ public static function loadByNames(array $names, Db $db)
+ {
+ $dashlets = [];
+ foreach ($names as $name) {
+ $dashlet = static::loadByName($name, $db);
+
+ if ($dashlet->isAllowed()) {
+ $dashlets[] = $dashlet;
+ }
+ }
+
+ return $dashlets;
+ }
+
+ public function listCssClasses()
+ {
+ return [];
+ }
+
+ public function getIconName()
+ {
+ return $this->icon;
+ }
+
+ abstract public function getTitle();
+
+ abstract public function getUrl();
+
+ protected function assemble()
+ {
+ $this->add(Link::create([
+ $this->getTitle(),
+ Icon::create($this->getIconName()),
+ Html::tag('p', null, $this->getSummary())
+ ], $this->getUrl(), null, [
+ 'class' => $this->listCssClasses()
+ ]));
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array($this->getUrl());
+ }
+
+ public function isAllowed()
+ {
+ $acl = Acl::instance();
+ foreach ($this->listRequiredPermissions() as $perm) {
+ if (! $acl->hasPermission($perm)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public function shouldBeShown()
+ {
+ return true;
+ }
+
+ public function getSummary()
+ {
+ $result = '';
+ if (! empty($this->requiredStats)) {
+ reset($this->requiredStats);
+ $result .= $this->statSummary(current($this->requiredStats));
+ }
+
+ return $result;
+ }
+
+ public function getStats($type, $name = null)
+ {
+ if ($name === null) {
+ return $this->stats[$type];
+ } else {
+ return $this->stats[$type]->{'cnt_' . $name};
+ }
+ }
+
+ protected function getTemplateSummaryText($type)
+ {
+ $cnt = (int) $this->stats[$type]->cnt_template;
+
+ if ($cnt === 0) {
+ return $this->translate('No template has been defined yet');
+ }
+
+ if ($cnt === 1) {
+ return $this->translate('One template has been defined');
+ }
+
+ return sprintf(
+ $this->translate('%d templates have been defined'),
+ $cnt
+ );
+ }
+
+ protected function getApplySummaryText($type)
+ {
+ $cnt = (int) $this->stats[$type]->cnt_apply;
+
+ if ($cnt === 0) {
+ return $this->translate('No apply rule has been defined yet');
+ }
+
+ if ($cnt === 1) {
+ return $this->translate('One apply rule has been defined');
+ }
+
+ return sprintf(
+ $this->translate('%d apply rules have been defined'),
+ $cnt
+ );
+ }
+
+ protected function statSummary($type)
+ {
+ $stat = $this->stats[$type];
+
+ if ((int) $stat->cnt_total === 0) {
+ return $this->translate('No object has been defined yet');
+ }
+
+ if ((int) $stat->cnt_total === 1) {
+ if ($stat->cnt_template > 0) {
+ $msg = $this->translate('One template has been defined');
+ } elseif ($stat->cnt_external > 0) {
+ $msg = $this->translate(
+ 'One external object has been defined, it will not be deployed'
+ );
+ } else {
+ $msg = $this->translate('One object has been defined');
+ }
+ } else {
+ $msg = sprintf(
+ $this->translate('%d objects have been defined'),
+ $stat->cnt_total
+ );
+ }
+
+ $extra = array();
+ if ($stat->cnt_total !== $stat->cnt_object) {
+ if ($stat->cnt_template > 0) {
+ $extra[] = sprintf(
+ $this->translate('%d of them are templates'),
+ $stat->cnt_template
+ );
+ }
+
+ if ($stat->cnt_external > 0) {
+ $extra[] = sprintf(
+ $this->translate(
+ '%d have been externally defined and will not be deployed'
+ ),
+ $stat->cnt_external
+ );
+ }
+ }
+
+ if (array_key_exists($type . 'group', $this->stats)) {
+ $groupstat = $this->stats[$type . 'group'];
+ if ((int) $groupstat->cnt_total === 0) {
+ $extra[] = $this->translate('no related group exists');
+ } elseif ((int) $groupstat->cnt_total === 1) {
+ $extra[] = $this->translate('one related group exists');
+ } else {
+ $extra[] = sprintf(
+ $this->translate('%s related group objects have been created'),
+ $groupstat->cnt_total
+ );
+ }
+ }
+
+ if (empty($extra)) {
+ return $msg;
+ }
+
+ return $msg . ', ' . implode(', ', $extra);
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/DatafieldCategoryDashlet.php b/library/Director/Dashboard/Dashlet/DatafieldCategoryDashlet.php
new file mode 100644
index 0000000..6efb4ca
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/DatafieldCategoryDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class DatafieldCategoryDashlet extends Dashlet
+{
+ protected $icon = 'th-list';
+
+ public function getTitle()
+ {
+ return $this->translate('Data Field Categories');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Categories bring structure to your Data Fields'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/data/fieldcategories';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/DatafieldDashlet.php b/library/Director/Dashboard/Dashlet/DatafieldDashlet.php
new file mode 100644
index 0000000..03f2d8d
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/DatafieldDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class DatafieldDashlet extends Dashlet
+{
+ protected $icon = 'edit';
+
+ public function getTitle()
+ {
+ return $this->translate('Define Data Fields');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Data fields make sure that configuration fits your rules'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/data/fields';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/DatalistDashlet.php b/library/Director/Dashboard/Dashlet/DatalistDashlet.php
new file mode 100644
index 0000000..bdf179f
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/DatalistDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class DatalistDashlet extends Dashlet
+{
+ protected $icon = 'sort-name-up';
+
+ public function getTitle()
+ {
+ return $this->translate('Provide Data Lists');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Provide data lists to make life easier for your users'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/data/lists';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/DependencyObjectDashlet.php b/library/Director/Dashboard/Dashlet/DependencyObjectDashlet.php
new file mode 100644
index 0000000..47a18aa
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/DependencyObjectDashlet.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class DependencyObjectDashlet extends Dashlet
+{
+ protected $icon = 'sitemap';
+
+ protected $requiredStats = array('dependency');
+
+ public function getTitle()
+ {
+ return $this->translate('Dependencies');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate('Object dependency relationships.')
+ . ' ' . parent::getSummary();
+ }
+
+ public function getUrl()
+ {
+ return 'director/dependencies/applyrules';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/DeploymentDashlet.php b/library/Director/Dashboard/Dashlet/DeploymentDashlet.php
new file mode 100644
index 0000000..7a52793
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/DeploymentDashlet.php
@@ -0,0 +1,114 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Exception;
+use Icinga\Module\Director\Objects\DirectorDeploymentLog;
+
+class DeploymentDashlet extends Dashlet
+{
+ protected $icon = 'wrench';
+
+ protected $undeployedActivities;
+
+ protected $lastDeployment;
+
+ public function getTitle()
+ {
+ return $this->translate('Config Deployment');
+ }
+
+ public function hasUndeployedActivities()
+ {
+ return $this->undeployedActivities() > 0;
+ }
+
+ public function undeployedActivities()
+ {
+ if ($this->undeployedActivities === null) {
+ try {
+ $this->undeployedActivities = $this->db
+ ->countActivitiesSinceLastDeployedConfig();
+ } catch (Exception $e) {
+ $this->undeployedActivities = 0;
+ }
+ }
+
+ return $this->undeployedActivities;
+ }
+
+ public function lastDeploymentFailed()
+ {
+ return ! $this->lastDeployment()->succeeded();
+ }
+
+ public function lastDeploymentPending()
+ {
+ return $this->lastDeployment()->isPending();
+ }
+
+ public function listCssClasses()
+ {
+ try {
+ if ($this->lastDeploymentFailed()) {
+ return array('state-critical');
+ } elseif ($this->lastDeploymentPending()) {
+ return array('state-pending');
+ } elseif ($this->hasUndeployedActivities()) {
+ return array('state-warning');
+ } else {
+ return array('state-ok');
+ }
+ } catch (Exception $e) {
+ return null;
+ }
+ }
+
+ protected function lastDeployment()
+ {
+ if ($this->lastDeployment === null) {
+ $this->lastDeployment = DirectorDeploymentLog::loadLatest($this->db);
+ }
+
+ return $this->lastDeployment;
+ }
+
+ public function getSummary()
+ {
+ $msgs = array();
+ $cnt = $this->undeployedActivities();
+
+ try {
+ if ($this->lastDeploymentFailed()) {
+ $msgs[] = $this->translate('The last deployment did not succeed');
+ } elseif ($this->lastDeploymentPending()) {
+ $msgs[] = $this->translate('The last deployment is currently pending');
+ }
+ } catch (Exception $e) {
+ }
+
+ if ($cnt === 0) {
+ $msgs[] = $this->translate('There are no pending changes');
+ } else {
+ $msgs[] = sprintf(
+ $this->translate(
+ 'A total of %d config changes happened since your last'
+ . ' deployed config has been rendered'
+ ),
+ $cnt
+ );
+ }
+
+ return implode('. ', $msgs) . '.';
+ }
+
+ public function getUrl()
+ {
+ return 'director/config/deployments';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/deploy');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/EndpointObjectDashlet.php b/library/Director/Dashboard/Dashlet/EndpointObjectDashlet.php
new file mode 100644
index 0000000..9dd9467
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/EndpointObjectDashlet.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Exception;
+
+class EndpointObjectDashlet extends Dashlet
+{
+ protected $icon = 'cloud';
+
+ protected $requiredStats = array('endpoint');
+
+ protected $hasDeploymentEndpoint;
+
+ public function getTitle()
+ {
+ return $this->translate('Endpoints');
+ }
+
+ public function getUrl()
+ {
+ return 'director/endpoints';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+
+ protected function hasDeploymentEndpoint()
+ {
+ if ($this->hasDeploymentEndpoint === null) {
+ try {
+ $this->hasDeploymentEndpoint = $this->db->hasDeploymentEndpoint();
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
+ return $this->hasDeploymentEndpoint;
+ }
+
+ public function listCssClasses()
+ {
+ if (! $this->hasDeploymentEndpoint()) {
+ return 'state-critical';
+ }
+
+ return null;
+ }
+
+ public function getSummary()
+ {
+ $msg = parent::getSummary();
+ if (! $this->hasDeploymentEndpoint()) {
+ $msg .= '. ' . $this->translate(
+ 'None could be used for deployments right now'
+ );
+ }
+
+ return $msg;
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ExternalCheckCommandsDashlet.php b/library/Director/Dashboard/Dashlet/ExternalCheckCommandsDashlet.php
new file mode 100644
index 0000000..2711fb9
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ExternalCheckCommandsDashlet.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ExternalCheckCommandsDashlet extends CheckCommandsDashlet
+{
+ protected $icon = 'download';
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'External Commands have been defined in your local Icinga 2'
+ . ' Configuration.'
+ );
+ }
+
+ public function getTitle()
+ {
+ return $this->translate('External Commands');
+ }
+
+ public function getUrl()
+ {
+ return 'director/commands?type=external_object';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ExternalNotificationCommandsDashlet.php b/library/Director/Dashboard/Dashlet/ExternalNotificationCommandsDashlet.php
new file mode 100644
index 0000000..435d0cb
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ExternalNotificationCommandsDashlet.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ExternalNotificationCommandsDashlet extends CheckCommandsDashlet
+{
+ protected $icon = 'wrench';
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'External Notification Commands have been defined in your local Icinga 2'
+ . ' Configuration.'
+ );
+ }
+
+ public function getTitle()
+ {
+ return $this->translate('External Notification Commands');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/HostChoicesDashlet.php b/library/Director/Dashboard/Dashlet/HostChoicesDashlet.php
new file mode 100644
index 0000000..98bfe32
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/HostChoicesDashlet.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class HostChoicesDashlet extends ChoicesDashlet
+{
+}
diff --git a/library/Director/Dashboard/Dashlet/HostGroupsDashlet.php b/library/Director/Dashboard/Dashlet/HostGroupsDashlet.php
new file mode 100644
index 0000000..5d3b25f
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/HostGroupsDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class HostGroupsDashlet extends Dashlet
+{
+ protected $icon = 'tags';
+
+ public function getTitle()
+ {
+ return $this->translate('Host Groups');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Define Host Groups to give your configuration more structure. They'
+ . ' are useful for Dashboards, Notifications or Restrictions'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/hostgroups';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/hostgroups');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/HostObjectDashlet.php b/library/Director/Dashboard/Dashlet/HostObjectDashlet.php
new file mode 100644
index 0000000..10cff94
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/HostObjectDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class HostObjectDashlet extends Dashlet
+{
+ protected $icon = 'host';
+
+ protected $requiredStats = array('host', 'hostgroup');
+
+ public function getTitle()
+ {
+ return $this->translate('Host objects');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return ['director/hosts'];
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=hosts';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/HostTemplatesDashlet.php b/library/Director/Dashboard/Dashlet/HostTemplatesDashlet.php
new file mode 100644
index 0000000..09bed17
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/HostTemplatesDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class HostTemplatesDashlet extends Dashlet
+{
+ protected $icon = 'cubes';
+
+ public function getTitle()
+ {
+ return $this->translate('Host Templates');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Manage your Host Templates. Use Fields to make it easy for'
+ . ' your users to get them customized.'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/hosts/templates';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/HostsDashlet.php b/library/Director/Dashboard/Dashlet/HostsDashlet.php
new file mode 100644
index 0000000..39c1421
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/HostsDashlet.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class HostsDashlet extends Dashlet
+{
+ protected $icon = 'host';
+
+ public function getTitle()
+ {
+ return $this->translate('Hosts');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'This is where you add all your servers, containers, network or'
+ . ' sensor devices - and much more. Every subject worth to be'
+ . ' monitored'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/hosts';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return ['director/hosts'];
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ImportSourceDashlet.php b/library/Director/Dashboard/Dashlet/ImportSourceDashlet.php
new file mode 100644
index 0000000..302c1ed
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ImportSourceDashlet.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Exception;
+use Icinga\Module\Director\Objects\ImportSource;
+
+class ImportSourceDashlet extends Dashlet
+{
+ protected $icon = 'database';
+
+ public function getTitle()
+ {
+ return $this->translate('Import data sources');
+ }
+
+ public function listCssClasses()
+ {
+ try {
+ return $this->fetchStateClass();
+ } catch (Exception $e) {
+ return 'state-critical';
+ }
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Define and manage imports from various data sources'
+ );
+ }
+
+ protected function fetchStateClass()
+ {
+ $srcs = ImportSource::loadAll($this->db);
+ if (count($srcs) > 0) {
+ $state = 'state-ok';
+ } else {
+ $state = null;
+ }
+
+ foreach ($srcs as $src) {
+ if ($src->import_state !== 'in-sync') {
+ if ($src->import_state === 'failing') {
+ $state = 'state-critical';
+ break;
+ } else {
+ $state = 'state-warning';
+ }
+ }
+ }
+
+ return $state;
+ }
+
+ public function getUrl()
+ {
+ return 'director/importsources';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/InfrastructureDashlet.php b/library/Director/Dashboard/Dashlet/InfrastructureDashlet.php
new file mode 100644
index 0000000..328df72
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/InfrastructureDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class InfrastructureDashlet extends Dashlet
+{
+ protected $icon = 'cloud';
+
+ public function getTitle()
+ {
+ return $this->translate('Icinga Infrastructure');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Manage your Icinga 2 infrastructure: Masters, Zones, Satellites and more'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=infrastructure';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/JobDashlet.php b/library/Director/Dashboard/Dashlet/JobDashlet.php
new file mode 100644
index 0000000..d7452e0
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/JobDashlet.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Exception;
+use Icinga\Module\Director\Objects\DirectorJob;
+
+class JobDashlet extends Dashlet
+{
+ protected $icon = 'clock';
+
+ public function getTitle()
+ {
+ return $this->translate('Jobs');
+ }
+
+ public function listCssClasses()
+ {
+ try {
+ return $this->fetchStateClass();
+ } catch (Exception $e) {
+ return 'state-critical';
+ }
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Schedule and automate Import, Syncronization, Config Deployment,'
+ . ' Housekeeping and more'
+ );
+ }
+
+ protected function fetchStateClass()
+ {
+ /** @var DirectorJob[] $jobs */
+ $jobs = DirectorJob::loadAll($this->db);
+ if (count($jobs) > 0) {
+ $state = 'state-ok';
+ } else {
+ $state = null;
+ }
+
+ foreach ($jobs as $job) {
+ if ($job->isPending()) {
+ $state = 'state-pending';
+ } elseif (! $job->lastAttemptSucceeded()) {
+ $state = 'state-critical';
+ break;
+ }
+ }
+
+ return $state;
+ }
+
+ public function getUrl()
+ {
+ return 'director/jobs';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/KickstartDashlet.php b/library/Director/Dashboard/Dashlet/KickstartDashlet.php
new file mode 100644
index 0000000..09801f5
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/KickstartDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class KickstartDashlet extends Dashlet
+{
+ protected $icon = 'gauge';
+
+ public function getTitle()
+ {
+ return $this->translate('Kickstart Wizard');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'This synchronizes Icinga Director to your Icinga 2 infrastructure.'
+ . ' A new run should be triggered on infrastructure changes'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/kickstart';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/NotificationApplyDashlet.php b/library/Director/Dashboard/Dashlet/NotificationApplyDashlet.php
new file mode 100644
index 0000000..e0b0443
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/NotificationApplyDashlet.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class NotificationApplyDashlet extends Dashlet
+{
+ protected $icon = 'bell';
+
+ protected $requiredStats = array('notification');
+
+ public function getTitle()
+ {
+ return $this->translate('Notifications');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Apply notifications with specific properties according to given rules.'
+ ) . ' ' . $this->getApplySummaryText('notification');
+ }
+
+ public function shouldBeShown()
+ {
+ return $this->getStats('notification', 'template') > 0;
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/notifications');
+ }
+
+ public function getUrl()
+ {
+ return 'director/notifications/applyrules';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/NotificationCommandsDashlet.php b/library/Director/Dashboard/Dashlet/NotificationCommandsDashlet.php
new file mode 100644
index 0000000..0a640ae
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/NotificationCommandsDashlet.php
@@ -0,0 +1,21 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class NotificationCommandsDashlet extends CheckCommandsDashlet
+{
+ protected $icon = 'wrench';
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Notification Commands allow you to trigger any action you want when'
+ . ' a notification takes place'
+ );
+ }
+
+ public function getTitle()
+ {
+ return $this->translate('Notification Commands');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/NotificationTemplateDashlet.php b/library/Director/Dashboard/Dashlet/NotificationTemplateDashlet.php
new file mode 100644
index 0000000..a58b5d0
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/NotificationTemplateDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class NotificationTemplateDashlet extends Dashlet
+{
+ protected $icon = 'cubes';
+
+ protected $requiredStats = array('notification');
+
+ public function getTitle()
+ {
+ return $this->translate('Notification templates');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate('Provide templates for your notifications.')
+ . ' ' . $this->getTemplateSummaryText('notification');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+
+ public function getUrl()
+ {
+ return 'director/notifications/templates';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/NotificationsDashlet.php b/library/Director/Dashboard/Dashlet/NotificationsDashlet.php
new file mode 100644
index 0000000..85610f0
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/NotificationsDashlet.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class NotificationsDashlet extends Dashlet
+{
+ protected $icon = 'bell';
+
+ protected $requiredStats = array('notification');
+
+ public function getTitle()
+ {
+ return $this->translate('Notifications');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Schedule your notifications. Define who should be notified, when,'
+ . ' and for which kind of problem'
+ );
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/notifications');
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=notifications';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ScheduledDowntimeApplyDashlet.php b/library/Director/Dashboard/Dashlet/ScheduledDowntimeApplyDashlet.php
new file mode 100644
index 0000000..45bcfa2
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ScheduledDowntimeApplyDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ScheduledDowntimeApplyDashlet extends Dashlet
+{
+ protected $icon = 'plug';
+
+ protected $requiredStats = ['scheduled_downtime'];
+
+ public function getTitle()
+ {
+ return $this->translate('Scheduled Downtimes');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/scheduled-downtimes');
+ }
+
+ public function getUrl()
+ {
+ return 'director/scheduled-downtimes/applyrules';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/SelfServiceDashlet.php b/library/Director/Dashboard/Dashlet/SelfServiceDashlet.php
new file mode 100644
index 0000000..32b1cfa
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/SelfServiceDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class SelfServiceDashlet extends Dashlet
+{
+ protected $icon = 'chat';
+
+ public function getTitle()
+ {
+ return $this->translate('Self Service API');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Icinga Director offers a Self Service API, allowing new Icinga'
+ . ' nodes to register themselves'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/settings/self-service';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceApplyRulesDashlet.php b/library/Director/Dashboard/Dashlet/ServiceApplyRulesDashlet.php
new file mode 100644
index 0000000..b4bee04
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceApplyRulesDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ServiceApplyRulesDashlet extends Dashlet
+{
+ protected $icon = 'resize-full-alt';
+
+ public function getTitle()
+ {
+ return $this->translate('Service Apply Rules');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Using Apply Rules a Service can be applied to multiple hosts at once,'
+ . ' based on filters dealing with any combination of their properties'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/services/applyrules';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceChoicesDashlet.php b/library/Director/Dashboard/Dashlet/ServiceChoicesDashlet.php
new file mode 100644
index 0000000..ff23321
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceChoicesDashlet.php
@@ -0,0 +1,7 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ServiceChoicesDashlet extends ChoicesDashlet
+{
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceGroupsDashlet.php b/library/Director/Dashboard/Dashlet/ServiceGroupsDashlet.php
new file mode 100644
index 0000000..ad47768
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceGroupsDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ServiceGroupsDashlet extends Dashlet
+{
+ protected $icon = 'tags';
+
+ public function getTitle()
+ {
+ return $this->translate('Service Groups');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Defining Service Groups get more structure. Great for Dashboards.'
+ . ' Notifications and Permissions might be based on groups.'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/servicegroups';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceObjectDashlet.php b/library/Director/Dashboard/Dashlet/ServiceObjectDashlet.php
new file mode 100644
index 0000000..01fb800
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceObjectDashlet.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Icinga\Module\Director\Acl;
+
+class ServiceObjectDashlet extends Dashlet
+{
+ protected $icon = 'services';
+
+ protected $requiredStats = array('service', 'servicegroup');
+
+ public function getTitle()
+ {
+ return $this->translate('Monitored Services');
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=services';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return ['director/services'];
+ }
+
+ public function isAllowed()
+ {
+ $acl = Acl::instance();
+ return $acl->hasPermission('director/services')
+ || $acl->hasPermission('director/service_sets');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceSetsDashlet.php b/library/Director/Dashboard/Dashlet/ServiceSetsDashlet.php
new file mode 100644
index 0000000..f971d42
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceSetsDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ServiceSetsDashlet extends Dashlet
+{
+ protected $icon = 'services';
+
+ public function getTitle()
+ {
+ return $this->translate('Service Sets');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Grouping your Services into Sets allow you to quickly assign services'
+ . ' often used together in a single operation all at once'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/services/sets';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/servicesets');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ServiceTemplatesDashlet.php b/library/Director/Dashboard/Dashlet/ServiceTemplatesDashlet.php
new file mode 100644
index 0000000..62d1b41
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ServiceTemplatesDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ServiceTemplatesDashlet extends Dashlet
+{
+ protected $icon = 'cubes';
+
+ public function getTitle()
+ {
+ return $this->translate('Service Templates');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Manage your Service Templates. Use Fields to make it easy for'
+ . ' your users to get them customized.'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/services/templates';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/SettingsDashlet.php b/library/Director/Dashboard/Dashlet/SettingsDashlet.php
new file mode 100644
index 0000000..716e565
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/SettingsDashlet.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class SettingsDashlet extends Dashlet
+{
+ protected $icon = 'edit';
+
+ public function getTitle()
+ {
+ return $this->translate('Director Settings');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Tweak some global Director settings'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/config/settings';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/SingleServicesDashlet.php b/library/Director/Dashboard/Dashlet/SingleServicesDashlet.php
new file mode 100644
index 0000000..297b3f8
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/SingleServicesDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class SingleServicesDashlet extends Dashlet
+{
+ protected $icon = 'service';
+
+ public function getTitle()
+ {
+ return $this->translate('Single Services');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Here you can find all single services directly attached to single'
+ . ' hosts'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/services';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/services');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/SyncDashlet.php b/library/Director/Dashboard/Dashlet/SyncDashlet.php
new file mode 100644
index 0000000..4ac689a
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/SyncDashlet.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use Exception;
+use Icinga\Module\Director\Objects\SyncRule;
+
+class SyncDashlet extends Dashlet
+{
+ protected $icon = 'flapping';
+
+ public function getTitle()
+ {
+ return $this->translate('Synchronize');
+ }
+
+ public function listCssClasses()
+ {
+ try {
+ return $this->fetchStateClass();
+ } catch (Exception $e) {
+ return 'state-critical';
+ }
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Define how imported data should be synchronized with Icinga'
+ );
+ }
+
+ protected function fetchStateClass()
+ {
+ $syncs = SyncRule::loadAll($this->db);
+ if (count($syncs) > 0) {
+ $state = 'state-ok';
+ } else {
+ $state = null;
+ }
+
+ foreach ($syncs as $sync) {
+ if ($sync->sync_state !== 'in-sync') {
+ if ($sync->sync_state === 'failing') {
+ $state = 'state-critical';
+ break;
+ } else {
+ $state = 'state-warning';
+ }
+ }
+ }
+
+ return $state;
+ }
+
+ public function getUrl()
+ {
+ return 'director/syncrules';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/TimeperiodObjectDashlet.php b/library/Director/Dashboard/Dashlet/TimeperiodObjectDashlet.php
new file mode 100644
index 0000000..ba4c1db
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/TimeperiodObjectDashlet.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use DirectoryIterator;
+use Icinga\Exception\ProgrammingError;
+
+class TimeperiodObjectDashlet extends Dashlet
+{
+ protected $icon = 'calendar';
+
+ protected $requiredStats = array('timeperiod');
+
+ public function getTitle()
+ {
+ return $this->translate('Timeperiods');
+ }
+
+ public function getUrl()
+ {
+ return 'director/timeperiods';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/TimeperiodTemplateDashlet.php b/library/Director/Dashboard/Dashlet/TimeperiodTemplateDashlet.php
new file mode 100644
index 0000000..26339e4
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/TimeperiodTemplateDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class TimeperiodTemplateDashlet extends Dashlet
+{
+ protected $icon = 'cubes';
+
+ protected $requiredStats = array('timeperiod');
+
+ public function getTitle()
+ {
+ return $this->translate('Timeperiod Templates');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate('Provide templates for your TimePeriod objects.')
+ . ' ' . $this->getTemplateSummaryText('timeperiod');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+
+ public function getUrl()
+ {
+ return 'director/timeperiods/templates';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/TimeperiodsDashlet.php b/library/Director/Dashboard/Dashlet/TimeperiodsDashlet.php
new file mode 100644
index 0000000..5a54bec
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/TimeperiodsDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class TimeperiodsDashlet extends Dashlet
+{
+ protected $icon = 'calendar';
+
+ protected $requiredStats = array('timeperiod');
+
+ public function getTitle()
+ {
+ return $this->translate('Timeperiods');
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=timeperiods';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/UserGroupsDashlet.php b/library/Director/Dashboard/Dashlet/UserGroupsDashlet.php
new file mode 100644
index 0000000..3fba4ba
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/UserGroupsDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class UserGroupsDashlet extends Dashlet
+{
+ protected $icon = 'tags';
+
+ public function getTitle()
+ {
+ return $this->translate('User Groups');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate(
+ 'Defining Notifications for User Groups instead of single Users'
+ . ' gives more flexibility'
+ );
+ }
+
+ public function getUrl()
+ {
+ return 'director/usergroups';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/UserObjectDashlet.php b/library/Director/Dashboard/Dashlet/UserObjectDashlet.php
new file mode 100644
index 0000000..463b84c
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/UserObjectDashlet.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+use DirectoryIterator;
+use Icinga\Exception\ProgrammingError;
+
+class UserObjectDashlet extends Dashlet
+{
+ protected $icon = 'users';
+
+ protected $requiredStats = array('user', 'usergroup');
+
+ public function getTitle()
+ {
+ return $this->translate('Users / Contacts');
+ }
+
+ public function getUrl()
+ {
+ return 'director/users';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/UserTemplateDashlet.php b/library/Director/Dashboard/Dashlet/UserTemplateDashlet.php
new file mode 100644
index 0000000..291ab05
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/UserTemplateDashlet.php
@@ -0,0 +1,31 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class UserTemplateDashlet extends Dashlet
+{
+ protected $icon = 'cubes';
+
+ protected $requiredStats = array('user');
+
+ public function getTitle()
+ {
+ return $this->translate('User Templates');
+ }
+
+ public function getSummary()
+ {
+ return $this->translate('Provide templates for your User objects.')
+ . ' ' . $this->getTemplateSummaryText('user');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+
+ public function getUrl()
+ {
+ return 'director/users/templates';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/UsersDashlet.php b/library/Director/Dashboard/Dashlet/UsersDashlet.php
new file mode 100644
index 0000000..43ddc26
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/UsersDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class UsersDashlet extends Dashlet
+{
+ protected $icon = 'users';
+
+ protected $requiredStats = array('user', 'usergroup');
+
+ public function getTitle()
+ {
+ return $this->translate('Users / Contacts');
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/users');
+ }
+
+ public function getUrl()
+ {
+ return 'director/dashboard?name=users';
+ }
+}
diff --git a/library/Director/Dashboard/Dashlet/ZoneObjectDashlet.php b/library/Director/Dashboard/Dashlet/ZoneObjectDashlet.php
new file mode 100644
index 0000000..ee789f2
--- /dev/null
+++ b/library/Director/Dashboard/Dashlet/ZoneObjectDashlet.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard\Dashlet;
+
+class ZoneObjectDashlet extends Dashlet
+{
+ protected $icon = 'globe';
+
+ protected $requiredStats = array('zone');
+
+ public function getTitle()
+ {
+ return $this->translate('Zones');
+ }
+
+ public function getUrl()
+ {
+ return 'director/zones';
+ }
+
+ public function listRequiredPermissions()
+ {
+ return array('director/admin');
+ }
+}
diff --git a/library/Director/Dashboard/DataDashboard.php b/library/Director/Dashboard/DataDashboard.php
new file mode 100644
index 0000000..36a807b
--- /dev/null
+++ b/library/Director/Dashboard/DataDashboard.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class DataDashboard extends Dashboard
+{
+ protected $dashletNames = [
+ 'Datafield',
+ 'DatafieldCategory',
+ 'Datalist',
+ 'Customvar'
+ ];
+
+ public function getTitle()
+ {
+ return $this->translate('Do more with custom data');
+ }
+}
diff --git a/library/Director/Dashboard/DeploymentDashboard.php b/library/Director/Dashboard/DeploymentDashboard.php
new file mode 100644
index 0000000..6cd2005
--- /dev/null
+++ b/library/Director/Dashboard/DeploymentDashboard.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class DeploymentDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'ActivityLog',
+ 'Deployment',
+ 'Infrastructure',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Deploy configuration to your Icinga nodes');
+ }
+}
diff --git a/library/Director/Dashboard/DirectorDashboard.php b/library/Director/Dashboard/DirectorDashboard.php
new file mode 100644
index 0000000..47a17af
--- /dev/null
+++ b/library/Director/Dashboard/DirectorDashboard.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class DirectorDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'Settings',
+ 'Basket',
+ 'SelfService',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Icinga Director Configuration');
+ }
+}
diff --git a/library/Director/Dashboard/HostsDashboard.php b/library/Director/Dashboard/HostsDashboard.php
new file mode 100644
index 0000000..281accb
--- /dev/null
+++ b/library/Director/Dashboard/HostsDashboard.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class HostsDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'Hosts',
+ 'HostTemplates',
+ 'HostGroups',
+ 'HostChoices',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Manage your Icinga Hosts');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'This is where you manage your Icinga 2 Host Checks. Host templates'
+ . ' are your main building blocks. You can bundle them to "choices",'
+ . ' allowing (or forcing) your users to choose among a given set of'
+ . ' preconfigured templates.'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['hosts', 'services', 'commands']
+ );
+ }
+}
diff --git a/library/Director/Dashboard/InfrastructureDashboard.php b/library/Director/Dashboard/InfrastructureDashboard.php
new file mode 100644
index 0000000..2b369fc
--- /dev/null
+++ b/library/Director/Dashboard/InfrastructureDashboard.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+use gipfl\Web\Widget\Hint;
+use Icinga\Application\Icinga;
+use Icinga\Authentication\Auth;
+use Icinga\Module\Director\Web\Tabs\InfraTabs;
+use Icinga\Module\Director\Web\Widget\Documentation;
+use ipl\Html\Html;
+use ipl\Html\HtmlDocument;
+
+class InfrastructureDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'Kickstart',
+ 'ApiUserObject',
+ 'EndpointObject',
+ 'ZoneObject',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Manage your Icinga Infrastructure');
+ }
+
+ public function getDescription()
+ {
+ $documentation = new Documentation(Icinga::app(), Auth::getInstance());
+
+ $link = $documentation->getModuleLink(
+ $this->translate('documentation'),
+ 'director',
+ '24-Working-with-agents',
+ $this->translate('Working with Agents and Config Zones')
+ );
+ return (new HtmlDocument())->add([
+ $this->translate(
+ 'This is where you manage your Icinga 2 infrastructure. When adding'
+ . ' a new Icinga Master or Satellite please re-run the Kickstart'
+ . ' Helper once.'
+ ),
+ Hint::warning($this->translate(
+ 'When you feel the desire to manually create Zone or Endpoint'
+ . ' objects please rethink this twice. Doing so is mostly the wrong'
+ . ' way, might lead to a dead end, requiring quite some effort to'
+ . ' clean up the whole mess afterwards.'
+ )),
+ Html::sprintf(
+ $this->translate('Want to connect to your Icinga Agents? Have a look at our %s!'),
+ $link
+ )
+ ]);
+ }
+
+ public function getTabs()
+ {
+ return new InfraTabs($this->getAuth());
+ }
+}
diff --git a/library/Director/Dashboard/NotificationsDashboard.php b/library/Director/Dashboard/NotificationsDashboard.php
new file mode 100644
index 0000000..b7d72f5
--- /dev/null
+++ b/library/Director/Dashboard/NotificationsDashboard.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class NotificationsDashboard extends Dashboard
+{
+ protected $dashletNames = [
+ 'NotificationApply',
+ 'NotificationTemplate',
+ ];
+
+ public function getTitle()
+ {
+ return $this->translate('Schedule your notifications');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'Notifications are sent when a host or service reaches a non-ok hard'
+ . ' state or recovers from such. One might also want to send them for'
+ . ' special events like when a Downtime starts, a problem gets'
+ . ' acknowledged and much more. You can send specific notifications'
+ . ' only within specific time periods, you can delay them and of course'
+ . ' re-notify at specific intervals.'
+ . "\n\n"
+ . ' Combine those possibilities in case you need to define escalation'
+ . ' levels, like notifying operators first and your management later on'
+ . ' in case the problem remains unhandled for a certain time.'
+ . "\n\n"
+ . ' You might send E-Mail or SMS, make phone calls or page on various'
+ . ' channels. You could also delegate notifications to external service'
+ . ' providers. The possibilities are endless, as you are allowed to'
+ . ' define as many custom notification commands as you want'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['notifications', 'users', 'timeperiods']
+ );
+ }
+}
diff --git a/library/Director/Dashboard/ObjectsDashboard.php b/library/Director/Dashboard/ObjectsDashboard.php
new file mode 100644
index 0000000..02c2a4b
--- /dev/null
+++ b/library/Director/Dashboard/ObjectsDashboard.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class ObjectsDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'HostObject',
+ 'ServiceObject',
+ 'CommandObject',
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Define whatever you want to be monitored');
+ }
+}
diff --git a/library/Director/Dashboard/ServicesDashboard.php b/library/Director/Dashboard/ServicesDashboard.php
new file mode 100644
index 0000000..65c8f0a
--- /dev/null
+++ b/library/Director/Dashboard/ServicesDashboard.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class ServicesDashboard extends Dashboard
+{
+ protected $dashletNames = array(
+ 'SingleServices',
+ 'ServiceApplyRules',
+ 'ServiceTemplates',
+ 'ServiceGroups',
+ 'ServiceChoices',
+ 'ServiceSets'
+ );
+
+ public function getTitle()
+ {
+ return $this->translate('Manage your Icinga Service Checks');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'This is where you manage your Icinga 2 Service Checks. Service'
+ . ' Templates are your base building blocks, Service Sets allow'
+ . ' you to assign multiple Services at once. Apply Rules make it'
+ . ' possible to assign Services based on Host properties. And'
+ . ' the list of all single Service Objects gives you the possibility'
+ . ' to still modify (or delete) many of them at once.'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['hosts', 'services', 'commands']
+ );
+ }
+}
diff --git a/library/Director/Dashboard/TimeperiodsDashboard.php b/library/Director/Dashboard/TimeperiodsDashboard.php
new file mode 100644
index 0000000..9821b94
--- /dev/null
+++ b/library/Director/Dashboard/TimeperiodsDashboard.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class TimeperiodsDashboard extends Dashboard
+{
+ protected $dashletNames = [
+ 'TimeperiodObject',
+ 'TimeperiodTemplate',
+ ];
+
+ public function getTitle()
+ {
+ return $this->translate('Define custom Time Periods');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'Want to define to execute specific checks only withing specific'
+ . ' time periods? Get mobile notifications only out of office hours,'
+ . ' but mail notifications all around the clock? Time Periods allow'
+ . ' you to tackle those and similar requirements.'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['notifications', 'users', 'timeperiods']
+ );
+ }
+}
diff --git a/library/Director/Dashboard/UsersDashboard.php b/library/Director/Dashboard/UsersDashboard.php
new file mode 100644
index 0000000..036d149
--- /dev/null
+++ b/library/Director/Dashboard/UsersDashboard.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Icinga\Module\Director\Dashboard;
+
+class UsersDashboard extends Dashboard
+{
+ protected $dashletNames = [
+ 'UserObject',
+ 'UserTemplate',
+ 'UserGroups',
+ ];
+
+ public function getTitle()
+ {
+ return $this->translate('Schedule your notifications');
+ }
+
+ public function getDescription()
+ {
+ return $this->translate(
+ 'This is where you manage your Icinga 2 User (Contact) objects. Try'
+ . ' to keep your User objects simply by movin complexity to your'
+ . ' templates. Bundle your users in groups and build Notifications'
+ . ' based on them. Running MS Active Directory or another central'
+ . ' User inventory? Stay away from fiddling with manual config, try'
+ . ' to automate all the things with Imports and related Sync Rules!'
+ );
+ }
+
+ public function getTabs()
+ {
+ return $this->createTabsForDashboards(
+ ['notifications', 'users', 'timeperiods']
+ );
+ }
+}