summaryrefslogtreecommitdiffstats
path: root/application
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:30:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:30:50 +0000
commitd5f222b7ebf4d2c2d47d20a25adcc9aadf67fbd5 (patch)
treeda9b32212bf99154450a7668f61a75f65617a9fa /application
parentInitial commit. (diff)
downloadicingaweb2-module-toplevelview-d5f222b7ebf4d2c2d47d20a25adcc9aadf67fbd5.tar.xz
icingaweb2-module-toplevelview-d5f222b7ebf4d2c2d47d20a25adcc9aadf67fbd5.zip
Adding upstream version 0.3.3.upstream/0.3.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'application')
-rw-r--r--application/clicommands/ConvertCommand.php104
-rw-r--r--application/clicommands/LegacyCommand.php92
-rw-r--r--application/controllers/EditController.php92
-rw-r--r--application/controllers/IndexController.php24
-rw-r--r--application/controllers/ShowController.php93
-rw-r--r--application/forms/EditForm.php176
-rw-r--r--application/locale/de_DE/LC_MESSAGES/toplevelview.mobin0 -> 2751 bytes
-rw-r--r--application/locale/de_DE/LC_MESSAGES/toplevelview.po163
-rw-r--r--application/views/helpers/Badges.php49
-rw-r--r--application/views/helpers/Breadcrumb.php32
-rw-r--r--application/views/helpers/Tiles.php55
-rw-r--r--application/views/helpers/Tree.php110
-rw-r--r--application/views/scripts/edit/index.phtml36
-rw-r--r--application/views/scripts/index/index.phtml51
-rw-r--r--application/views/scripts/show/actions.phtml43
-rw-r--r--application/views/scripts/show/index.phtml23
-rw-r--r--application/views/scripts/show/tree.phtml22
-rw-r--r--application/views/scripts/text/index.phtml11
18 files changed, 1176 insertions, 0 deletions
diff --git a/application/clicommands/ConvertCommand.php b/application/clicommands/ConvertCommand.php
new file mode 100644
index 0000000..a05538b
--- /dev/null
+++ b/application/clicommands/ConvertCommand.php
@@ -0,0 +1,104 @@
+<?php
+/* TopLevelView module for Icingaweb2 - Copyright (c) 2017 Icinga Development Team <info@icinga.com> */
+
+namespace Icinga\Module\Toplevelview\Clicommands;
+
+use Icinga\Exception\ConfigurationError;
+use Icinga\Module\Toplevelview\Command;
+use Icinga\Module\Toplevelview\Config\ConfigEmitter;
+use Icinga\Module\Toplevelview\Legacy\LegacyDbHelper;
+use Icinga\Module\Toplevelview\ViewConfig;
+use Zend_Db_Adapter_Pdo_Sqlite;
+
+/**
+ * Converts a TopLevelView database into the new YAML configuration format
+ */
+class ConvertCommand extends Command
+{
+ protected $dbConnections = array();
+
+ public function init()
+ {
+ parent::init();
+
+ if (! extension_loaded('pdo_sqlite')) {
+ throw new ConfigurationError('You need the PHP extension "pdo_sqlite" in order to convert TopLevelView');
+ }
+ }
+
+ /**
+ * List all hierarchies in the database
+ *
+ * Arguments:
+ * --db <file> SQLite3 data from from old TopLevelView module
+ */
+ public function listAction()
+ {
+ $dbFile = $this->params->getRequired('db');
+ $db = $this->sqlite($dbFile);
+
+ $helper = new LegacyDbHelper($db);
+ foreach ($helper->fetchHierarchies() as $root) {
+ printf("[%d] %s\n", $root['id'], $root['name']);
+ }
+ }
+
+ /**
+ * Generate a YAML config file for Icinga Web 2 module
+ *
+ * Arguments:
+ * --db <file> SQLite3 data from from old TopLevelView module
+ * --id <id> Database id to export (see list)
+ * --output <file> Write to file (default '-' for stdout)
+ * --name <name> If name is specified instead of file,
+ * config is saved under that name
+ */
+ public function convertAction()
+ {
+ $dbFile = $this->params->getRequired('db');
+ $db = $this->sqlite($dbFile);
+
+ $id = $this->params->getRequired('id');
+
+ $output = $this->params->get('output', null);
+ $name = $this->params->get('name', null);
+ $format = $this->params->get('format', 'yaml');
+
+ $helper = new LegacyDbHelper($db, $this->monitoringBackend());
+ $tree = $helper->fetchTree($id);
+
+ $emitter = ConfigEmitter::fromLegacyTree($tree);
+
+ if ($name !== null and $output === null) {
+ $viewConfig = new ViewConfig();
+ $viewConfig->setConfigDir();
+ $viewConfig->setFormat(ViewConfig::FORMAT_YAML);
+ $viewConfig->setName($name);
+ $viewConfig->setText($emitter->emitYAML($format));
+ $viewConfig->store();
+ printf("Saved as config %s\n", $name);
+ exit(0);
+ }
+
+ $text = $emitter->emit($format);
+ if ($output === null || $output === '-') {
+ echo $text;
+ } else {
+ file_put_contents($output, $text);
+ }
+ }
+
+ /**
+ * Sets up the Zend PDO resource for SQLite
+ *
+ * @param string $file
+ *
+ * @return Zend_Db_Adapter_Pdo_Sqlite
+ */
+ protected function sqlite($file)
+ {
+ return new Zend_Db_Adapter_Pdo_Sqlite(array(
+ 'dbname' => $file,
+ ));
+ }
+}
diff --git a/application/clicommands/LegacyCommand.php b/application/clicommands/LegacyCommand.php
new file mode 100644
index 0000000..f9784be
--- /dev/null
+++ b/application/clicommands/LegacyCommand.php
@@ -0,0 +1,92 @@
+<?php
+/* TopLevelView module for Icingaweb2 - Copyright (c) 2021 Icinga Development Team <info@icinga.com> */
+
+namespace Icinga\Module\Toplevelview\Clicommands;
+
+use Icinga\Exception\ConfigurationError;
+use Icinga\Module\Monitoring\Backend\MonitoringBackend;
+use Icinga\Module\Toplevelview\Command;
+use Icinga\Module\Toplevelview\Legacy\LegacyDbHelper;
+use Zend_Db_Adapter_Pdo_Sqlite;
+
+/**
+ * Tools for the legacy DB
+ */
+class LegacyCommand extends Command
+{
+ public function init()
+ {
+ parent::init();
+
+ if (! extension_loaded('pdo_sqlite')) {
+ throw new ConfigurationError('You need the PHP extension "pdo_sqlite" in order to convert TopLevelView');
+ }
+ }
+
+ /**
+ * Delete unreferenced objects from the database
+ *
+ * Arguments:
+ * --db <file> SQLite3 data from from old TopLevelView module
+ * --noop Only show counts, don't delete
+ */
+ public function cleanupAction()
+ {
+ $dbFile = $this->params->getRequired('db');
+ $noop = $this->params->shift('noop');
+ $db = $this->sqlite($dbFile);
+
+ $helper = new LegacyDbHelper($db);
+
+ $result = $helper->cleanupUnreferencedObjects($noop);
+ foreach ($result as $type => $c) {
+ printf("%s: %d\n", $type, $c);
+ }
+ }
+
+ /**
+ * Migrate database ids from an IDO to another IDO
+ *
+ * Arguments:
+ * --db <file> SQLite3 data from from old TopLevelView module
+ * --target <file> Target database path (will be overwritten)
+ * --old <backend> OLD IDO backend (configured in monitoring module)
+ * --new <backend> New IDO backend (configured in monitoring module) (optional)
+ * --purge Remove unresolvable data during update (see log)
+ */
+ public function idomigrateAction()
+ {
+ $dbFile = $this->params->getRequired('db');
+ $old = $this->params->getRequired('old');
+ $target = $this->params->getRequired('target');
+ $new = $this->params->get('new');
+ $purge = $this->params->shift('purge');
+
+ $db = $this->sqlite($dbFile);
+
+ $helper = new LegacyDbHelper($db, MonitoringBackend::instance($new));
+ $helper->setOldBackend(MonitoringBackend::instance($old));
+
+ // Use the copy as db
+ $helper->setDb($helper->copySqliteDb($db, $target));
+
+ $result = $helper->migrateObjectIds(false, $purge);
+ foreach ($result as $type => $c) {
+ printf("%s: %d\n", $type, $c);
+ }
+ }
+
+ /**
+ * Sets up the Zend PDO resource for SQLite
+ *
+ * @param string $file
+ *
+ * @return Zend_Db_Adapter_Pdo_Sqlite
+ */
+ protected function sqlite($file)
+ {
+ return new Zend_Db_Adapter_Pdo_Sqlite(array(
+ 'dbname' => $file,
+ ));
+ }
+}
diff --git a/application/controllers/EditController.php b/application/controllers/EditController.php
new file mode 100644
index 0000000..b91255c
--- /dev/null
+++ b/application/controllers/EditController.php
@@ -0,0 +1,92 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Toplevelview\Controllers;
+
+use Icinga\Module\Toplevelview\Forms\EditForm;
+use Icinga\Module\Toplevelview\ViewConfig;
+use Icinga\Module\Toplevelview\Web\Controller;
+use Icinga\Web\Url;
+
+class EditController extends Controller
+{
+ public function init()
+ {
+ $this->assertPermission('toplevelview/edit');
+
+ $tabs = $this->getTabs();
+
+ if ($name = $this->getParam('name')) {
+ $tabs->add(
+ 'tiles',
+ array(
+ 'title' => $this->translate('Tiles'),
+ 'url' => Url::fromPath('toplevelview/show', array(
+ 'name' => $name
+ ))
+ )
+ );
+
+ $tabs->add(
+ 'index',
+ array(
+ 'title' => $this->translate('Edit'),
+ 'url' => Url::fromPath('toplevelview/edit', array(
+ 'name' => $name
+ ))
+ )
+ );
+ }
+
+
+ $action = $this->getRequest()->getActionName();
+ if ($tab = $tabs->get($action)) {
+ $tab->setActive();
+ }
+ }
+
+ public function indexAction()
+ {
+ $action = $this->getRequest()->getActionName();
+ if ($action === 'add') {
+ $this->view->title = sprintf(
+ '%s Top Level View',
+ $this->translate('Add')
+ );
+ $view = new ViewConfig();
+ $view->setConfigDir();
+ } elseif ($action === 'clone') {
+ $name = $this->params->getRequired('name');
+ $this->view->title = sprintf(
+ '%s Top Level View',
+ $this->translate('Clone')
+ );
+ $view = clone ViewConfig::loadByName($name);
+ } else {
+ $this->view->name = $name = $this->params->getRequired('name');
+ $this->view->title = sprintf(
+ '%s Top Level View: %s',
+ $this->translate('Edit'),
+ $this->params->getRequired('name')
+ );
+ $view = ViewConfig::loadByName($name);
+ }
+
+ $this->view->form = $form = new EditForm();
+ $view->setFormat(ViewConfig::FORMAT_YAML);
+ $form->setViewConfig($view);
+ $form->handleRequest();
+
+ $this->setViewScript('edit/index');
+ }
+
+ public function addAction()
+ {
+ $this->indexAction();
+ }
+
+ public function cloneAction()
+ {
+ $this->indexAction();
+ }
+}
diff --git a/application/controllers/IndexController.php b/application/controllers/IndexController.php
new file mode 100644
index 0000000..e1353f3
--- /dev/null
+++ b/application/controllers/IndexController.php
@@ -0,0 +1,24 @@
+<?php
+/* Copyright (C) 2017 Icinga Development Team <info@icinga.com> */
+
+namespace Icinga\Module\Toplevelview\Controllers;
+
+use Icinga\Module\Toplevelview\ViewConfig;
+use Icinga\Module\Toplevelview\Web\Controller;
+
+class IndexController extends Controller
+{
+ public function indexAction()
+ {
+ $this->getTabs()->add(
+ 'index',
+ array(
+ 'title' => 'Top Level View',
+ 'url' => 'toplevelview',
+ )
+ )->activate('index');
+ $this->view->views = ViewConfig::loadAll();
+
+ $this->setAutorefreshInterval(30);
+ }
+}
diff --git a/application/controllers/ShowController.php b/application/controllers/ShowController.php
new file mode 100644
index 0000000..d0560f2
--- /dev/null
+++ b/application/controllers/ShowController.php
@@ -0,0 +1,93 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Toplevelview\Controllers;
+
+use Icinga\Module\Toplevelview\ViewConfig;
+use Icinga\Module\Toplevelview\Web\Controller;
+use Icinga\Web\Url;
+use Icinga\Web\Widget\Tab;
+
+class ShowController extends Controller
+{
+ public function init()
+ {
+ $tabs = $this->getTabs();
+
+ $tiles = Url::fromPath('toplevelview/show', array(
+ 'name' => $this->params->getRequired('name')
+ ));
+
+ $tabs->add(
+ 'index',
+ array(
+ 'title' => $this->translate('Tiles'),
+ 'url' => $tiles
+ )
+ );
+
+ if (($id = $this->getParam('id')) !== null) {
+ $tabs->add(
+ 'tree',
+ array(
+ 'title' => $this->translate('Tree'),
+ 'url' => Url::fromPath('toplevelview/show/tree', array(
+ 'name' => $this->params->getRequired('name'),
+ 'id' => $id
+ ))
+ )
+ );
+ }
+
+ $fullscreen = new Tab(array(
+ 'title' => $this->translate('Go Fullscreen'),
+ 'icon' => 'dashboard',
+ 'url' => ((string) $tiles) . '&view=compact&showFullscreen'
+ ));
+ $fullscreen->setTargetBlank();
+ $tabs->addAsDropdown('fullscreen', $fullscreen);
+
+ $action = $this->getRequest()->getActionName();
+ if ($tab = $tabs->get($action)) {
+ $tab->setActive();
+ }
+ }
+
+ public function indexAction()
+ {
+ $this->view->name = $name = $this->params->getRequired('name');
+ $this->view->view = $view = ViewConfig::loadByName($name);
+ $tree = $view->getTree();
+ $tree->setBackend($this->monitoringBackend());
+
+ if (($lifetime = $this->getParam('cache')) !== null) {
+ $tree->setCacheLifetime($lifetime);
+ }
+
+ $this->setAutorefreshInterval(30);
+ }
+
+ public function treeAction()
+ {
+ $this->view->name = $name = $this->params->getRequired('name');
+ $this->view->view = $view = ViewConfig::loadByName($name);
+ $tree = $view->getTree();
+ $this->view->node = $tree->getById($this->params->getRequired('id'));
+ $tree->setBackend($this->monitoringBackend());
+
+ if (($lifetime = $this->getParam('cache')) !== null) {
+ $tree->setCacheLifetime($lifetime);
+ }
+
+ $this->setAutorefreshInterval(30);
+ }
+
+ public function sourceAction()
+ {
+ $this->view->name = $name = $this->params->getRequired('name');
+ $this->view->view = $view = ViewConfig::loadByName($name);
+
+ $this->view->text = $view->getText();
+ $this->setViewScript('index', 'text');
+ }
+}
diff --git a/application/forms/EditForm.php b/application/forms/EditForm.php
new file mode 100644
index 0000000..86e7880
--- /dev/null
+++ b/application/forms/EditForm.php
@@ -0,0 +1,176 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Toplevelview\Forms;
+
+use Exception;
+use Icinga\Module\Toplevelview\ViewConfig;
+use Icinga\Web\Form;
+use Icinga\Web\Notification;
+use Icinga\Web\Url;
+
+class EditForm extends Form
+{
+ /**
+ * @var ViewConfig
+ */
+ protected $viewConfig;
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ $this->setName('form_toplevelview_edit');
+ }
+
+ public function setViewConfig(ViewConfig $viewConfig)
+ {
+ $this->viewConfig = $viewConfig;
+ return $this;
+ }
+
+ /**
+ * @see Form::onSuccess()
+ */
+ public function onSuccess()
+ {
+ try {
+ $this->viewConfig->setName($this->getValue('name'));
+ $this->viewConfig->setText($this->getValue('config'));
+
+ // ensure config can be parsed...
+ $this->viewConfig->getMetaData();
+ $this->viewConfig->getTree();
+
+ $this->viewConfig->storeToSession();
+
+ $cancel = $this->getElement('btn_submit_cancel');
+ $delete = $this->getElement('btn_submit_delete');
+
+ if ($this->getElement('btn_submit_save_file')->getValue() !== null) {
+ $this->viewConfig->store();
+ Notification::success($this->translate('Top Level View successfully saved'));
+ } elseif ($cancel !== null && $cancel->getValue() !== null) {
+ $this->viewConfig->clearSession();
+ Notification::success($this->translate('Top Level View restored from disk'));
+ } elseif ($delete != null && $delete->getValue() !== null) {
+ $this->viewConfig->delete();
+ $this->setRedirectUrl('toplevelview');
+ Notification::success($this->translate('Top Level View successfully deleted'));
+ } else {
+ Notification::success($this->translate('Top Level View successfully saved for the current session'));
+ }
+ return true;
+ } catch (Exception $e) {
+ $this->addError(sprintf('Could not save config: %s', $e->getMessage()));
+ return false;
+ }
+ }
+
+ public function getRedirectUrl()
+ {
+ if ($this->redirectUrl === null && ($name = $this->viewConfig->getName()) !== null) {
+ $this->redirectUrl = Url::fromPath('toplevelview/show', array('name' => $name));
+ }
+ return parent::getRedirectUrl();
+ }
+
+ /**
+ * Populate form
+ *
+ * @see Form::onRequest()
+ */
+ public function onRequest()
+ {
+ $values = array();
+ $values['name'] = $this->viewConfig->getName();
+ $values['config'] = $this->viewConfig->getText();
+
+ $this->populate($values);
+ }
+
+ /**
+ * @see Form::createElements()
+ */
+ public function createElements(array $formData)
+ {
+ if ($this->viewConfig->hasBeenLoadedFromSession()) {
+ $this->warning(
+ $this->translate(
+ 'This config is only stored in your session!'
+ . ' Make sure to save it to disk once your work is complete!'
+ ),
+ false
+ );
+ }
+
+ $this->addElement(
+ 'text',
+ 'name',
+ array(
+ 'label' => $this->translate('File name'),
+ 'required' => true
+ )
+ );
+ $this->addElement(
+ 'textarea',
+ 'config',
+ array(
+ //'required' => true,
+ 'label' => $this->translate('YAML Config'),
+ 'class' => 'code-editor codemirror',
+ 'decorators' => array(
+ array('Label', array('tag'=>'div', 'separator' => '')),
+ array('HtmlTag', array('tag' => 'div')),
+ 'ViewHelper'
+ ),
+ 'data-codemirror-mode' => 'yaml'
+ )
+ );
+
+ $this->addElement(
+ 'submit',
+ 'btn_submit_save_session',
+ array(
+ 'ignore' => true,
+ 'label' => $this->translate('Save for the current Session'),
+ 'decorators' => array('ViewHelper')
+ )
+ );
+
+ $this->addElement(
+ 'submit',
+ 'btn_submit_save_file',
+ array(
+ 'ignore' => true,
+ 'label' => $this->translate('Save to config file'),
+ 'decorators' => array('ViewHelper')
+ )
+ );
+
+ if ($this->viewConfig->hasBeenLoadedFromSession()) {
+ $this->addElement(
+ 'submit',
+ 'btn_submit_cancel',
+ array(
+ 'ignore' => true,
+ 'label' => $this->translate('Cancel editing'),
+ 'decorators' => array('ViewHelper')
+ )
+ );
+ }
+
+ if ($this->viewConfig->hasBeenLoaded()) {
+ $this->addElement(
+ 'submit',
+ 'btn_submit_delete',
+ array(
+ 'ignore' => true,
+ 'label' => $this->translate('Delete config'),
+ 'decorators' => array('ViewHelper')
+ )
+ );
+ }
+ }
+}
diff --git a/application/locale/de_DE/LC_MESSAGES/toplevelview.mo b/application/locale/de_DE/LC_MESSAGES/toplevelview.mo
new file mode 100644
index 0000000..9964d3f
--- /dev/null
+++ b/application/locale/de_DE/LC_MESSAGES/toplevelview.mo
Binary files differ
diff --git a/application/locale/de_DE/LC_MESSAGES/toplevelview.po b/application/locale/de_DE/LC_MESSAGES/toplevelview.po
new file mode 100644
index 0000000..d562ff3
--- /dev/null
+++ b/application/locale/de_DE/LC_MESSAGES/toplevelview.po
@@ -0,0 +1,163 @@
+# Icinga Web 2 - Head for multiple monitoring backends.
+# Copyright (C) 2017 Icinga Development Team
+# This file is distributed under the same license as Toplevelview Module.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Toplevelview Module (0.0.0)\n"
+"Report-Msgid-Bugs-To: dev@icinga.com\n"
+"POT-Creation-Date: 2017-10-13 11:53+0000\n"
+"PO-Revision-Date: 2017-10-13 14:00+0200\n"
+"Language: de_DE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Basepath: .\n"
+"Last-Translator: Markus Frosch <markus.frosch@icinga.com>\n"
+"Language-Team: \n"
+"X-Generator: Poedit 1.8.11\n"
+"X-Poedit-SearchPath-0: .\n"
+
+#: ../../../../modules/toplevelview/application/views/helpers/Tree.php:58
+#, php-format
+msgid "%s host"
+msgid_plural "%s hosts"
+msgstr[0] "%s Host"
+msgstr[1] "%s Hosts"
+
+#: ../../../../modules/toplevelview/application/views/helpers/Tree.php:54
+#, php-format
+msgid "%s unhandled host"
+msgid_plural "%s unhandled hosts"
+msgstr[0] "%s unbehandelte Problem"
+msgstr[1] "%s unbehandelte Probleme"
+
+#: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:13
+#: ../../../../modules/toplevelview/application/controllers/EditController.php:53
+msgid "Add"
+msgstr "Hinzufügen"
+
+#: ../../../../modules/toplevelview/configuration.php:9
+msgid "Allow the user to edit Top Level Views"
+msgstr "Erlauben dass Benutzer Top Level Views ändern"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:157
+msgid "Cancel editing"
+msgstr "Bearbeitung abbrechen"
+
+#: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:19
+#: ../../../../modules/toplevelview/application/controllers/EditController.php:60
+msgid "Clone"
+msgstr "Klonen"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:169
+msgid "Delete config"
+msgstr "Konfiguration löschen"
+
+#: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:38
+#: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:9
+#: ../../../../modules/toplevelview/application/controllers/EditController.php:33
+#: ../../../../modules/toplevelview/application/controllers/EditController.php:66
+msgid "Edit"
+msgstr "Bearbeiten"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:9
+msgid "Editor Help"
+msgstr "Editor Hilfe"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:111
+msgid "File name"
+msgstr "Dateiname"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:17
+msgid "Find next"
+msgstr "Nächster Treffer"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:21
+msgid "Find previous"
+msgstr "Vorheriger Treffer"
+
+#: ../../../../modules/toplevelview/application/controllers/ShowController.php:43
+msgid "Go Fullscreen"
+msgstr "Zur Vollbildansicht"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:33
+msgid "Jump to line"
+msgstr "Zu Zeile springen"
+
+#: ../../../../modules/toplevelview/application/views/scripts/show/tree.phtml:16
+#: ../../../../modules/toplevelview/application/views/scripts/show/index.phtml:14
+msgid "Last update"
+msgstr "Letzte Aktualisierung"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:13
+msgid ""
+"Persistent search (dialog doesn't autoclose, enter to find next, Shift-Enter "
+"to find previous)"
+msgstr ""
+"Dauerhafte Suche (Dialog schließt nicht automatisch, Enter für nächsten "
+"Treffer, Shift-Enter für Vorherigen)"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:25
+msgid "Replace"
+msgstr "Ersetzen"
+
+#: ../../../../modules/toplevelview/application/views/scripts/edit/index.phtml:29
+msgid "Replace all"
+msgstr "Alle Ersetzen"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:136
+msgid "Save for the current Session"
+msgstr "Für die aktuelle Sitzung speichern"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:146
+msgid "Save to config file"
+msgstr "Speichern in Konfigurationsdatei"
+
+#: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:30
+msgid "Source"
+msgstr "Quelle"
+
+#: ../../../../modules/toplevelview/application/views/scripts/show/actions.phtml:39
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:101
+msgid ""
+"This config is only stored in your session! Make sure to save it to disk "
+"once your work is complete!"
+msgstr ""
+"Diese Konfiguration ist nur in Ihrer Sitzung gespeichert! Stellen Sie sicher "
+"sie in eine Datei zu speichern wenn Ihre Änderung fertig ist!"
+
+#: ../../../../modules/toplevelview/application/controllers/ShowController.php:24
+#: ../../../../modules/toplevelview/application/controllers/EditController.php:23
+msgid "Tiles"
+msgstr "Kacheln"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:56
+msgid "Top Level View restored from disk"
+msgstr "Top Level View von Speicher wiederhergestellt"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:60
+msgid "Top Level View successfully deleted"
+msgstr "Top Level View erfolgreich gelöscht"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:53
+msgid "Top Level View successfully saved"
+msgstr "Top Level View erfolgreich gespeichert"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:62
+msgid "Top Level View successfully saved for the current session"
+msgstr "Top Level View erfolgreich für Ihre Sitzung gespeichert"
+
+#: ../../../../modules/toplevelview/application/controllers/ShowController.php:33
+msgid "Tree"
+msgstr "Baum"
+
+#: ../../../../modules/toplevelview/application/views/scripts/index/index.phtml:32
+msgid "Unsaved changes!"
+msgstr "Nicht-Gespeicherte Änderungen!"
+
+#: ../../../../modules/toplevelview/application/forms/EditForm.php:120
+msgid "YAML Config"
+msgstr "YAML Konfiguration"
diff --git a/application/views/helpers/Badges.php b/application/views/helpers/Badges.php
new file mode 100644
index 0000000..6066a72
--- /dev/null
+++ b/application/views/helpers/Badges.php
@@ -0,0 +1,49 @@
+<?php
+/* Icinga Web 2 Top Level View | (c) 2017 Icinga Development Team | GPLv2+ */
+
+use Icinga\Module\Toplevelview\Tree\TLVStatus;
+use Icinga\Web\Url;
+
+class Zend_View_Helper_Badges extends Zend_View_Helper_Abstract
+{
+ /** @var \Icinga\Web\View */
+ public $view;
+
+ protected function prettyTitle($identifier)
+ {
+ $s = '';
+ foreach (preg_split('/[\.\-_\s]+/', $identifier) as $p) {
+ $s .= ' ' . ucfirst($p);
+ }
+ return trim($s);
+ }
+
+ public function badges(TLVStatus $status, $problemsOnly = true, $showTotal = false)
+ {
+ $htm = '';
+
+ $values = false;
+ $htm .= '<div class="badges">';
+ foreach ($status->getProperties() as $key => $value) {
+ if ($problemsOnly === true && ($key === 'ok' || $key === 'downtime_active')
+ || ($key === 'total' && $showTotal !== true)
+ ) {
+ continue;
+ }
+ if ($value !== null && $value > 0) {
+ $values = true;
+ $title = $value . ' ' . $this->prettyTitle($key);
+ $class = 'tlv-status-tile ' . str_replace('_', ' ', $key);
+ $htm .= sprintf(
+ '<div class="badge status-badge %s" title="%s">%s</div>',
+ $class,
+ $title,
+ $value
+ );
+ }
+ }
+ $htm .= '</div>';
+
+ return $values ? $htm : '';
+ }
+}
diff --git a/application/views/helpers/Breadcrumb.php b/application/views/helpers/Breadcrumb.php
new file mode 100644
index 0000000..3263712
--- /dev/null
+++ b/application/views/helpers/Breadcrumb.php
@@ -0,0 +1,32 @@
+<?php
+/* Icinga Web 2 | (c) 2016 Icinga Development Team | GPLv2+ */
+
+use Icinga\Module\Toplevelview\Tree\TLVTreeNode;
+
+class Zend_View_Helper_Breadcrumb extends Zend_View_Helper_Abstract
+{
+ /** @var \Icinga\Web\View */
+ public $view;
+
+ /**
+ * @param TLVTreeNode[] $breadcrumb
+ *
+ * @return string
+ */
+ public function breadcrumb($breadcrumb, $config_name)
+ {
+ $htm = '<ul class="breadcrumb">';
+ foreach ($breadcrumb as $crumb) {
+ $htm .= '<li>' . $this->view->qlink(
+ $crumb->getTitle(),
+ 'toplevelview/show/tree',
+ array(
+ 'name' => $config_name,
+ 'id' => $crumb->getFullId()
+ )
+ ) . '</li>';
+ }
+ $htm .= '</ul>';
+ return $htm;
+ }
+}
diff --git a/application/views/helpers/Tiles.php b/application/views/helpers/Tiles.php
new file mode 100644
index 0000000..dcefbfe
--- /dev/null
+++ b/application/views/helpers/Tiles.php
@@ -0,0 +1,55 @@
+<?php
+/* Icinga Web 2 Top Level View | (c) 2017 Icinga Development Team | GPLv2+ */
+
+use Icinga\Module\Toplevelview\Tree\TLVTreeNode;
+
+class Zend_View_Helper_Tiles extends Zend_View_Helper_Abstract
+{
+ /** @var \Icinga\Web\View */
+ public $view;
+
+ public function tiles(TLVTreeNode $node, $levels = 2, $classes = array())
+ {
+ $htm = '';
+ $title = $this->view->escape($node->getTitle());
+
+ $status = $node->getStatus();
+ if ($levels > 1) {
+ $statusClass = 'tlv-status-section';
+ } else {
+ $statusClass = 'tlv-status-tile';
+ }
+ $statusClasses = array($statusClass, $status->getOverall());
+
+ $htm .= sprintf(
+ '<div class="tlv-tile %s" title="%s" data-base-target="_next">' . "\n",
+ join(' ', $classes + $statusClasses),
+ $title
+ );
+ $badges = $this->view->badges($status);
+
+ $htm .= $this->view->qlink(
+ $title . $badges,
+ 'toplevelview/show/tree',
+ array(
+ 'name' => $node->getRoot()->getConfig()->getName(),
+ 'id' => $node->getFullId()
+ ),
+ array(
+ 'class' => 'tlv-tile-title'
+ ),
+ false
+ );
+
+ if ($levels > 1 && $node->hasChildren()) {
+ $htm .= '<div class="tlv-tiles">';
+ foreach ($node->getChildren() as $child) {
+ $htm .= $this->tiles($child, $levels - 1, $classes);
+ }
+ $htm .= '</div>';
+ }
+
+ $htm .= "</div>\n";
+ return $htm;
+ }
+}
diff --git a/application/views/helpers/Tree.php b/application/views/helpers/Tree.php
new file mode 100644
index 0000000..a016b68
--- /dev/null
+++ b/application/views/helpers/Tree.php
@@ -0,0 +1,110 @@
+<?php
+/* Icinga Web 2 Top Level View | (c) 2017 Icinga Development Team | GPLv2+ */
+
+use Icinga\Module\Toplevelview\Tree\TLVTreeNode;
+use Icinga\Web\Url;
+
+class Zend_View_Helper_Tree extends Zend_View_Helper_Abstract
+{
+ /** @var \Icinga\Web\View */
+ public $view;
+
+ public function tree(TLVTreeNode $node, $classes = array(), $level = 0)
+ {
+ $htm = '';
+ $htmExtra = '';
+ $title = $node->getTitle();
+ $type = $node->getType();
+
+ $cssClasses = join(' ', $classes);
+
+ $status = $node->getStatus();
+ $statusClass = $status->getOverall();
+
+ if ($type === 'host') {
+ $icon = 'host';
+ $url = Url::fromPath(
+ 'monitoring/host/show',
+ array(
+ 'host' => $node->get('host')
+ )
+ );
+ } elseif ($type === 'service') {
+ $icon = 'service';
+ $url = Url::fromPath(
+ 'monitoring/service/show',
+ array(
+ 'host' => $node->get('host'),
+ 'service' => $node->get('service')
+ )
+ );
+ } elseif ($type === 'hostgroup') {
+ $icon = 'cubes';
+ $url = Url::fromPath(
+ 'monitoring/list/services',
+ array(
+ 'hostgroup' => $node->get('hostgroup'),
+ 'sort' => 'service_severity',
+ 'dir' => 'desc',
+ )
+ );
+
+ if (($h = $status->getMeta('hosts_unhandled')) > 0) {
+ $hostTitle = '(<strong>'
+ . sprintf($this->view->translatePlural('%s unhandled host', '%s unhandled hosts', $h), $h)
+ . '</strong>)';
+ } else {
+ $h = $status->getMeta('hosts_total');
+ $hostTitle = '(' . sprintf($this->view->translatePlural('%s host', '%s hosts', $h), $h) . ')';
+ }
+
+ $htmExtra .= ' ' . $this->view->qlink(
+ $hostTitle,
+ 'monitoring/list/hosts',
+ array(
+ 'hostgroup' => $node->get('hostgroup'),
+ 'sort' => 'host_severity',
+ 'dir' => 'desc',
+ ),
+ null,
+ false
+ );
+ } else {
+ $icon = null;
+ $url = Url::fromPath(
+ 'toplevelview/show/tree',
+ array(
+ 'name' => $node->getRoot()->getConfig()->getName(),
+ 'id' => $node->getFullId()
+ )
+ );
+ }
+
+ if ($type !== 'node') {
+ $htm .= "<div class=\"tlv-node-icinga tlv-node-\$type tlv-status-tile action $statusClass $cssClasses\""
+ . " data-base-target=\"_next\" href=\"$url\">";
+ $htm .= $this->view->icon($icon) . ' ';
+ $htm .= $this->view->qlink($title, $url);
+ $htm .= $htmExtra;
+ $htm .= ' ' . $this->view->badges($status, false);
+ $htm .= '</div>';
+ } else {
+ $htm .= "<div class=\"tlv-tree-node tlv-status-section tlv-collapsible $statusClass $cssClasses\"";
+ $htm .= " title=\"$title\">";
+ $htm .= '<div class="tlv-tree-title">';
+ $htm .= $this->view->badges($status, false, $level === 0 ? true : false);
+ $htm .= '<i class="icon icon-bycss tlv-collapse-handle"></i> ';
+ $htm .= $this->view->qlink($title, $url);
+ $htm .= $htmExtra;
+ $htm .= '</div>';
+ if ($node->hasChildren()) {
+ foreach ($node->getChildren() as $child) {
+ $htm .= $this->tree($child, $classes, $level + 1);
+ }
+ }
+ $htm .= '</div>';
+ }
+
+ return $htm;
+ }
+}
diff --git a/application/views/scripts/edit/index.phtml b/application/views/scripts/edit/index.phtml
new file mode 100644
index 0000000..614e962
--- /dev/null
+++ b/application/views/scripts/edit/index.phtml
@@ -0,0 +1,36 @@
+<?php if (! $this->compact): ?>
+<div class="controls">
+ <?= $this->tabs ?>
+</div>
+<?php endif ?>
+<div class="content full-form">
+ <h1><?= $title ?></h1>
+ <?= $form ?>
+ <h2><?= $this->translate('Editor Help') ?></h2>
+ <table class="name-value-table">
+ <tr>
+ <th>Ctrl-F / Cmd-F</th>
+ <td><?= $this->translate('Persistent search (dialog doesn\'t autoclose, enter to find next, Shift-Enter to find previous)') ?></td>
+ </tr>
+ <tr>
+ <th>Ctrl-G / Cmd-G</th>
+ <td><?= $this->translate('Find next') ?></td>
+ </tr>
+ <tr>
+ <th>Shift-Ctrl-G / Shift-Cmd-G</th>
+ <td><?= $this->translate('Find previous') ?></td>
+ </tr>
+ <tr>
+ <th>Shift-Ctrl-F / Cmd-Option-F</th>
+ <td><?= $this->translate('Replace') ?></td>
+ </tr>
+ <tr>
+ <th>Shift-Ctrl-R / Shift-Cmd-Option-F</th>
+ <td><?= $this->translate('Replace all') ?></td>
+ </tr>
+ <tr>
+ <th>Alt-G</th>
+ <td><?= $this->translate('Jump to line') ?></td>
+ </tr>
+ </table>
+</div>
diff --git a/application/views/scripts/index/index.phtml b/application/views/scripts/index/index.phtml
new file mode 100644
index 0000000..3797583
--- /dev/null
+++ b/application/views/scripts/index/index.phtml
@@ -0,0 +1,51 @@
+<?php
+/** @var array $views */
+
+if (! $this->compact): ?>
+ <div class="controls">
+ <?= $this->tabs ?>
+ </div>
+<?php endif ?>
+<div class="content">
+ <div class="tlv-overview-tiles">
+ <div class="action-links">
+ <?= $this->qlink(
+ $this->translate('Add'),
+ 'toplevelview/edit/add',
+ array(),
+ array(
+ 'class' => 'action-link',
+ 'icon' => 'plus',
+ )
+ ) ?>
+ </div>
+
+ <?php
+ foreach ($views as $name => $view):
+ /** @var \Icinga\Module\Toplevelview\ViewConfig $view */
+ $url = $this->url('toplevelview/show', array('name' => $name));
+ ?>
+ <div class="tlv-overview-tile">
+ <div class="tlv-title"><?= $this->qlink($view->getMeta('name'), $url) ?></div>
+ <div class="tlv-name"><?= $name ?></div>
+ <?php if ($view->hasBeenLoadedFromSession()): ?>
+ <div class="unsaved"><?= $this->translate('Unsaved changes!') ?></div>
+ <?php endif; ?>
+
+ <?php if (! $this->compact && $this->hasPermission('toplevelview/edit')): ?>
+ <div class="action-links">
+ <?= $this->qlink(
+ $this->translate('Edit'),
+ 'toplevelview/edit',
+ array('name' => $view->getName()),
+ array(
+ 'class' => 'action-link',
+ 'icon' => 'edit',
+ )
+ ) ?>
+ </div>
+ <?php endif; ?>
+ </div>
+ <?php endforeach; ?>
+ </div>
+</div>
diff --git a/application/views/scripts/show/actions.phtml b/application/views/scripts/show/actions.phtml
new file mode 100644
index 0000000..c72d5a6
--- /dev/null
+++ b/application/views/scripts/show/actions.phtml
@@ -0,0 +1,43 @@
+<?php
+/** @var \Icinga\Module\Toplevelview\ViewConfig $view */
+?>
+<div class="action-links">
+ <?php
+ if (! $this->compact) {
+ if ($this->hasPermission('toplevelview/edit')) {
+ echo $this->qlink(
+ $this->translate('Edit'),
+ 'toplevelview/edit',
+ array('name' => $view->getName()),
+ array(
+ 'class' => 'action-link',
+ 'icon' => 'edit',
+ 'data-base-target' => '_next'
+ )
+ );
+ echo $this->qlink(
+ $this->translate('Clone'),
+ 'toplevelview/edit/clone',
+ array('name' => $view->getName()),
+ array(
+ 'class' => 'action-link',
+ 'icon' => 'rewind',
+ 'data-base-target' => '_next'
+ )
+ );
+ } else {
+ echo $this->qlink(
+ $this->translate('Source'),
+ 'toplevelview/show/source',
+ array('name' => $view->getName())
+ );
+ }
+ }
+ ?>
+ <?php if ($view->hasBeenLoadedFromSession()): ?>
+ <div class="warning-note">
+ <?= $this->translate('This config is only stored in your session!'
+ . ' Make sure to save it to disk once your work is complete!') ?>
+ </div>
+ <?php endif; ?>
+</div>
diff --git a/application/views/scripts/show/index.phtml b/application/views/scripts/show/index.phtml
new file mode 100644
index 0000000..8278ae4
--- /dev/null
+++ b/application/views/scripts/show/index.phtml
@@ -0,0 +1,23 @@
+<?php
+/** @var \Icinga\Web\View $this */
+/** @var \Icinga\Module\Toplevelview\ViewConfig $view */
+$tree = $view->getTree();
+if (! $this->compact):
+?>
+<div class="controls">
+ <?= $this->tabs ?>
+</div>
+<?php endif ?>
+<div class="content tlv-content">
+ <div class="tlv-header">
+ <?= $this->badges($tree->getStatus(), false, true) ?>
+ <h1><?= $view->getMeta('name') ?></h1>
+ <?= $this->partial('show/actions.phtml', $this) ?>
+ <div class="last-refresh"><?= $this->timeAgo($tree->getFetchTime()) ?></div>
+ </div>
+ <div class="tlv-view-tiles">
+ <?php foreach ($tree->getChildren() as $topTile): ?>
+ <?= $this->tiles($topTile) ?>
+ <?php endforeach; ?>
+ </div>
+</div>
diff --git a/application/views/scripts/show/tree.phtml b/application/views/scripts/show/tree.phtml
new file mode 100644
index 0000000..52e4f80
--- /dev/null
+++ b/application/views/scripts/show/tree.phtml
@@ -0,0 +1,22 @@
+<?php
+/** @var \Icinga\Module\Toplevelview\ViewConfig $view */
+/** @var \Icinga\Module\Toplevelview\Tree\TLVTreeNode $node */
+
+$tree = $view->getTree();
+
+if (! $this->compact):
+?>
+<div class="controls">
+ <?= $this->tabs ?>
+</div>
+<?php endif ?>
+<div class="content tlv-view-tree">
+ <div class="tlv-header">
+ <?= $this->badges($tree->getStatus(), false, true) ?>
+ <h1><?= $view->getMeta('name') ?></h1>
+ <?= $this->partial('show/actions.phtml', $this) ?>
+ <div class="last-refresh"><?= $this->timeAgo($tree->getFetchTime()) ?></div>
+ </div>
+ <?= $this->breadcrumb($node->getBreadCrumb(), $view->getName()) ?>
+ <?= $this->tree($node) ?>
+</div>
diff --git a/application/views/scripts/text/index.phtml b/application/views/scripts/text/index.phtml
new file mode 100644
index 0000000..82b8ee8
--- /dev/null
+++ b/application/views/scripts/text/index.phtml
@@ -0,0 +1,11 @@
+<?php
+/** @var \Icinga\Module\Toplevelview\ViewConfig $view */
+if (! $this->compact):
+?>
+<div class="controls">
+ <?= $this->tabs ?>
+</div>
+<?php endif ?>
+<div class="content">
+ <pre><?= $this->text ?></pre>
+</div>