diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 12:39:39 +0000 |
commit | 8ca6cc32b2c789a3149861159ad258f2cb9491e3 (patch) | |
tree | 2492de6f1528dd44eaa169a5c1555026d9cb75ec /application/views | |
parent | Initial commit. (diff) | |
download | icingaweb2-8ca6cc32b2c789a3149861159ad258f2cb9491e3.tar.xz icingaweb2-8ca6cc32b2c789a3149861159ad258f2cb9491e3.zip |
Adding upstream version 2.11.4.upstream/2.11.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'application/views')
56 files changed, 2567 insertions, 0 deletions
diff --git a/application/views/helpers/CreateTicketLinks.php b/application/views/helpers/CreateTicketLinks.php new file mode 100644 index 0000000..4f8a272 --- /dev/null +++ b/application/views/helpers/CreateTicketLinks.php @@ -0,0 +1,23 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +/** + * Helper for creating ticket links from ticket hooks + */ +class Zend_View_Helper_CreateTicketLinks extends Zend_View_Helper_Abstract +{ + /** + * Create ticket links form ticket hooks + * + * @param string $text + * + * @return string + * @see \Icinga\Application\Hook\TicketHook::createLinks() + */ + public function createTicketLinks($text) + { + $tickets = $this->view->tickets; + /** @var \Icinga\Application\Hook\TicketHook $tickets */ + return isset($tickets) ? $tickets->createLinks($text) : $text; + } +} diff --git a/application/views/helpers/FormDate.php b/application/views/helpers/FormDate.php new file mode 100644 index 0000000..39e6d94 --- /dev/null +++ b/application/views/helpers/FormDate.php @@ -0,0 +1,46 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +/** + * Render date input controls + */ +class Zend_View_Helper_FormDate extends Zend_View_Helper_FormElement +{ + /** + * Render the date input control + * + * @param string $name + * @param int $value + * @param array $attribs + * + * @return string The rendered date input control + */ + public function formDate($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + + extract($info); // name, id, value, attribs, options, listsep, disable + /** @var string $id */ + /** @var bool $disable */ + + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + /** @var \Icinga\Web\View $view */ + $view = $this->view; + + $html5 = sprintf( + '<input type="date" name="%s" id="%s" value="%s"%s%s%s', + $view->escape($name), + $view->escape($id), + $view->escape($value), + $disabled, + $this->_htmlAttribs($attribs), + $this->getClosingBracket() + ); + + return $html5; + } +} diff --git a/application/views/helpers/FormDateTime.php b/application/views/helpers/FormDateTime.php new file mode 100644 index 0000000..de5eb4b --- /dev/null +++ b/application/views/helpers/FormDateTime.php @@ -0,0 +1,63 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +/** + * Render date-and-time input controls + */ +class Zend_View_Helper_FormDateTime extends Zend_View_Helper_FormElement +{ + /** + * Format date and time + * + * @param DateTime $dateTime + * @param bool $local + * + * @return string + */ + public function formatDate(DateTime $dateTime, $local) + { + $format = (bool) $local === true ? 'Y-m-d\TH:i:s' : DateTime::RFC3339; + return $dateTime->format($format); + } + + /** + * Render the date-and-time input control + * + * @param string $name The element name + * @param DateTime $value The default timestamp + * @param array $attribs Attributes for the element tag + * + * @return string The element XHTML + */ + public function formDateTime($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, id, value, attribs, options, listsep, disable + /** @var string $id */ + /** @var bool $disable */ + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + if ($value instanceof DateTime) { + // If value was valid, it's a DateTime object + $value = $this->formatDate($value, $attribs['local']); + } + if (isset($attribs['placeholder']) && $attribs['placeholder'] instanceof DateTime) { + $attribs['placeholder'] = $this->formatDate($attribs['placeholder'], $attribs['local']); + } + $type = $attribs['local'] === true ? 'datetime-local' : 'datetime'; + unset($attribs['local']); // Unset local to not render it again in $this->_htmlAttribs($attribs) + $html5 = sprintf( + '<input type="%s" data-use-datetime-picker name="%s" id="%s" step="1" value="%s"%s%s%s', + $type, + $this->view->escape($name), + $this->view->escape($id), + $this->view->escape($value), + $disabled, + $this->_htmlAttribs($attribs), + $this->getClosingBracket() + ); + return $html5; + } +} diff --git a/application/views/helpers/FormNumber.php b/application/views/helpers/FormNumber.php new file mode 100644 index 0000000..f447180 --- /dev/null +++ b/application/views/helpers/FormNumber.php @@ -0,0 +1,77 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +/** + * Render number input controls + */ +class Zend_View_Helper_FormNumber extends Zend_View_Helper_FormElement +{ + /** + * Format a number + * + * @param $number + * + * @return string + */ + public function formatNumber($number) + { + if (empty($number)) { + return $number; + } + return $this->view->escape( + sprintf( + ctype_digit((string) $number) ? '%d' : '%F', + $number + ) + ); + } + + /** + * Render the number input control + * + * @param string $name + * @param int $value + * @param array $attribs + * + * @return string The rendered number input control + */ + public function formNumber($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + extract($info); // name, id, value, attribs, options, listsep, disable + /** @var string $id */ + /** @var bool $disable */ + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + $min = ''; + if (isset($attribs['min'])) { + $min = sprintf(' min="%s"', $this->formatNumber($attribs['min'])); + } + unset($attribs['min']); // Unset min to not render it again in $this->_htmlAttribs($attribs) + $max = ''; + if (isset($attribs['max'])) { + $max = sprintf(' max="%s"', $this->formatNumber($attribs['max'])); + } + unset($attribs['max']); // Unset max to not render it again in $this->_htmlAttribs($attribs) + $step = ''; + if (isset($attribs['step'])) { + $step = sprintf(' step="%s"', $attribs['step'] === 'any' ? 'any' : $this->formatNumber($attribs['step'])); + } + unset($attribs['step']); // Unset step to not render it again in $this->_htmlAttribs($attribs) + $html5 = sprintf( + '<input type="number" name="%s" id="%s" value="%s"%s%s%s%s%s%s', + $this->view->escape($name), + $this->view->escape($id), + $this->view->escape($this->formatNumber($value)), + $min, + $max, + $step, + $disabled, + $this->_htmlAttribs($attribs), + $this->getClosingBracket() + ); + return $html5; + } +} diff --git a/application/views/helpers/FormTime.php b/application/views/helpers/FormTime.php new file mode 100644 index 0000000..39d1b83 --- /dev/null +++ b/application/views/helpers/FormTime.php @@ -0,0 +1,46 @@ +<?php +/* Icinga Web 2 | (c) 2017 Icinga Development Team | GPLv2+ */ + +/** + * Render time input controls + */ +class Zend_View_Helper_FormTime extends Zend_View_Helper_FormElement +{ + /** + * Render the time input control + * + * @param string $name + * @param int $value + * @param array $attribs + * + * @return string The rendered time input control + */ + public function formTime($name, $value = null, $attribs = null) + { + $info = $this->_getInfo($name, $value, $attribs); + + extract($info); // name, id, value, attribs, options, listsep, disable + /** @var string $id */ + /** @var bool $disable */ + + $disabled = ''; + if ($disable) { + $disabled = ' disabled="disabled"'; + } + + /** @var \Icinga\Web\View $view */ + $view = $this->view; + + $html5 = sprintf( + '<input type="time" name="%s" id="%s" value="%s"%s%s%s', + $view->escape($name), + $view->escape($id), + $view->escape($value), + $disabled, + $this->_htmlAttribs($attribs), + $this->getClosingBracket() + ); + + return $html5; + } +} diff --git a/application/views/helpers/ProtectId.php b/application/views/helpers/ProtectId.php new file mode 100644 index 0000000..f6dc226 --- /dev/null +++ b/application/views/helpers/ProtectId.php @@ -0,0 +1,13 @@ +<?php +/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */ + +/** + * Class Zend_View_Helper_Util + */ +class Zend_View_Helper_ProtectId extends Zend_View_Helper_Abstract +{ + public function protectId($id) + { + return Zend_Controller_Front::getInstance()->getRequest()->protectId($id); + } +} diff --git a/application/views/helpers/Util.php b/application/views/helpers/Util.php new file mode 100644 index 0000000..7a3e410 --- /dev/null +++ b/application/views/helpers/Util.php @@ -0,0 +1,68 @@ +<?php +/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ + +/** + * Class Zend_View_Helper_Util + */ +class Zend_View_Helper_Util extends Zend_View_Helper_Abstract +{ + public function util() + { + return $this; + } + + public static function showTimeSince($timestamp) + { + if (! $timestamp) { + return 'unknown'; + } + $duration = time() - $timestamp; + if ($duration > 3600 * 24 * 3) { + if (date('Y') === date('Y', $timestamp)) { + return date('d.m.', $timestamp); + } + return date('m.Y', $timestamp); + } + return self::showHourMin($duration); + } + + public static function showHourMin($sec) + { + $min = floor($sec / 60); + if ($min < 60) { + return $min . 'm ' . ($sec % 60) . 's'; + } + $hour = floor($min / 60); + if ($hour < 24) { + return date('H:i', time() - $sec); + } + return floor($hour / 24) . 'd ' . ($hour % 24) . 'h'; + } + + public static function showSeconds($sec) + { + // Todo: localization + if ($sec < 1) { + return round($sec * 1000) . 'ms'; + } + if ($sec < 60) { + return $sec . 's'; + } + return floor($sec / 60) . 'm ' . ($sec % 60) . 's'; + } + + public static function showTime($timestamp) + { + // Todo: localization + if ($timestamp < 86400) { + return 'undef'; + } + if (date('Ymd') === date('Ymd', $timestamp)) { + return date('H:i:s', $timestamp); + } + if (date('Y') === date('Y', $timestamp)) { + return date('H:i d.m.', $timestamp); + } + return date('H:i d.m.Y', $timestamp); + } +} diff --git a/application/views/scripts/about/index.phtml b/application/views/scripts/about/index.phtml new file mode 100644 index 0000000..e80cd89 --- /dev/null +++ b/application/views/scripts/about/index.phtml @@ -0,0 +1,171 @@ +<?php + +use ipl\Html\HtmlElement; +use ipl\Web\Widget\Icon; + +?> +<div class="controls"> + <?= $tabs ?> +</div> +<div id="about" class="content"> + + <?= $this->img('img/icinga-logo-big.svg', null, array('class' => 'icinga-logo', 'width' => 194)) ?> + + <section> + <table class="name-value-table"> + <?php if (isset($version['appVersion'])): ?> + <tr> + <th><?= $this->translate('Icinga Web 2 Version') ?></th> + <td><?= $this->escape($version['appVersion']) ?></td> + </tr> + <?php endif ?> + <?php if (isset($version['gitCommitID'])): ?> + <tr> + <th><?= $this->translate('Git commit') ?></th> + <td><?= $this->escape($version['gitCommitID']) ?></td> + </tr> + <?php endif ?> + <tr> + <th><?= $this->translate('PHP Version') ?></th> + <td><?= $this->escape(PHP_VERSION) ?></td> + </tr> + <?php if (isset($version['gitCommitDate'])): ?> + <tr> + <th><?= $this->translate('Git commit date') ?></th> + <td><?= $this->escape($version['gitCommitDate']) ?></td> + </tr> + <?php endif ?> + </table> + + <div class="external-links"> + <div class="col"> + <?= + HtmlElement::create('a', [ + 'href' => 'https://icinga.com/support/', + 'target' => '_blank', + 'title' => $this->translate('Get Icinga Support') + ], [ + new Icon('life-ring'), + $this->translate('Get Icinga Support'), + ] + ); + ?> + </div> + <div class="col"> + <?= + HtmlElement::create('a', [ + 'href' => 'https://icinga.com/community/', + 'target' => '_blank', + 'title' => $this->translate('Icinga Community') + ], [ + new Icon('globe-europe'), + $this->translate('Icinga Community'), + ] + ); + ?> + </div> + <div class="col"> + <?= + HtmlElement::create('a', [ + 'href' => 'https://github.com/icinga/icingaweb2/issues', + 'target' => '_blank', + 'title' => $this->translate('Icinga Community') + ], [ + new Icon('bullhorn'), + $this->translate('Report a bug'), + ] + ); + ?> + </div> + <div class="col"> + <?= + HtmlElement::create('a', [ + 'href' => 'https://icinga.com/docs/icinga-web-2/' + . (isset($version['docVersion']) ? $version['docVersion'] : 'latest'), + 'target' => '_blank', + 'title' => $this->translate('Icinga Documentation') + ], [ + new Icon('book'), + $this->translate('Icinga Documentation'), + ] + ); + ?> + </div> + </div> + + <h2><?= $this->translate('Loaded Libraries') ?></h2> + <table class="name-value-table" data-base-target="_next"> + <?php foreach ($libraries as $library): ?> + <tr> + <th> + <?= $this->escape($library->getName()) ?> + </th> + <td> + <?= $this->escape($library->getVersion()) ?: '-' ?> + </td> + </tr> + <?php endforeach ?> + </table> + + <h2><?= $this->translate('Loaded Modules') ?></h2> + <table class="name-value-table" data-base-target="_next"> + <?php foreach ($modules as $module): ?> + <tr> + <th> + <?= $this->escape($module->getName()) ?> + </th> + <td> + <td> + <?= $this->escape($module->getVersion()) ?> + </td> + <td> + <?php if ($this->hasPermission('config/modules')): ?> + <?= $this->qlink( + $this->translate('Configure'), + 'config/module/', + array('name' => $module->getName()), + array('title' => sprintf($this->translate('Show the overview of the %s module'), $module->getName())) + ) ?> + <?php endif ?> + </td> + </tr> + <?php endforeach ?> + </table> + </section> + + <footer> + <div class="about-copyright"> + <?= $this->translate('Copyright') ?> + <span>© 2013-<?= date('Y') ?></span> + <?= $this->qlink( + 'Icinga GmbH', + 'https://icinga.com', + null, + array( + 'target' => '_blank' + ) + ) ?> + </div> + <div class="about-social"> + <?= $this->qlink( + null, + 'https://www.twitter.com/icinga', + null, + array( + 'target' => '_blank', + 'icon' => 'twitter', + 'title' => $this->translate('Icinga on Twitter') + ) + ) ?> <?= $this->qlink( + null, + 'https://www.facebook.com/icinga', + null, + array( + 'target' => '_blank', + 'icon' => 'facebook-squared', + 'title' => $this->translate('Icinga on Facebook') + ) + ) ?> + </div> + </footer> +</div> diff --git a/application/views/scripts/account/index.phtml b/application/views/scripts/account/index.phtml new file mode 100644 index 0000000..efc2bcb --- /dev/null +++ b/application/views/scripts/account/index.phtml @@ -0,0 +1,11 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> +<?php if (isset($changePasswordForm)): ?> + <h1><?= $this->translate('Account') ?></h1> + <?= $changePasswordForm ?> +<?php endif ?> + <h1><?= $this->translate('Preferences') ?></h1> + <?= $form ?> +</div> diff --git a/application/views/scripts/announcements/index.phtml b/application/views/scripts/announcements/index.phtml new file mode 100644 index 0000000..ff87c66 --- /dev/null +++ b/application/views/scripts/announcements/index.phtml @@ -0,0 +1,71 @@ +<?php if (! $this->compact): ?> +<div class="controls"> + <?= $this->tabs ?> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + <?= $this->sortBox ?> + </div> + <?= $this->filterEditor ?> +</div> +<?php endif ?> +<div class="content"> +<?php if ($this->hasPermission('application/announcements')) { + echo $this->qlink( + $this->translate('Create a New Announcement') , + 'announcements/new', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new announcement') + ) + ); +} ?> +<?php if (empty($this->announcements)): ?> + <p><?= $this->translate('No announcements found.') ?></p> +</div> +<?php return; endif ?> + <table data-base-target="_next" class="table-row-selectable common-table"> + <thead> + <tr> + <th><?= $this->translate('Author') ?></th> + <th><?= $this->translate('Message') ?></th> + <th><?= $this->translate('Start') ?></th> + <th><?= $this->translate('End') ?></th> + <th></th> + </tr> + </thead> + <tbody> + <?php foreach ($this->announcements as $announcement): /** @var object $announcement */ ?> + <tr> + <td><?= $this->escape($announcement->author) ?></td> + <?php if ($this->hasPermission('application/announcements')): ?> + <td> + <a href="<?= $this->href('announcements/update', array('id' => $announcement->id)) ?>"> + <?= $this->ellipsis($this->escape($announcement->message), 100) ?> + </a> + </td> + <?php else: ?> + <td><?= $this->ellipsis($this->escape($announcement->message), 100) ?></td> + <?php endif ?> + <td><?= $this->formatDateTime($announcement->start) ?></td> + <td><?= $this->formatDateTime($announcement->end) ?></td> + <?php if ($this->hasPermission('application/announcements')): ?> + <td class="icon-col"><?= $this->qlink( + null, + 'announcements/remove', + array('id' => $announcement->id), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => $this->translate('Remove this announcement') + ) + ) ?></td> + <?php endif ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/authentication/login.phtml b/application/views/scripts/authentication/login.phtml new file mode 100644 index 0000000..167a468 --- /dev/null +++ b/application/views/scripts/authentication/login.phtml @@ -0,0 +1,74 @@ +<div id="login"> + <div class="login-form" data-base-target="layout"> + <div role="status" class="sr-only"> + <?= $this->translate( + 'Welcome to Icinga Web 2. For users of the screen reader Jaws full and expectant compliant' + . ' accessibility is possible only with use of the Firefox browser. VoiceOver on Mac OS X is tested on' + . ' Chrome, Safari and Firefox.' + ) ?> + </div> + <div class="logo-wrapper"><div id="icinga-logo" aria-hidden="true"></div></div> + <?php if ($requiresSetup): ?> + <p class="config-note"><?= sprintf( + $this->translate( + 'It appears that you did not configure Icinga Web 2 yet so it\'s not possible to log in without any defined ' + . 'authentication method. Please define a authentication method by following the instructions in the' + . ' %1$sdocumentation%3$s or by using our %2$sweb-based setup-wizard%3$s.' + ), + '<a href="https://icinga.com/docs/icinga-web-2/latest/doc/05-Authentication/#authentication" title="' + . $this->translate('Icinga Web 2 Documentation') . '">', + '<a href="' . $this->href('setup') . '" title="' . $this->translate('Icinga Web 2 Setup-Wizard') . '">', + '</a>' + ) ?></p> + <?php endif ?> + <?= $this->form ?> + <div id="login-footer"> + <p>Icinga Web 2 © 2013-<?= date('Y') ?></p> + <?= $this->qlink($this->translate('icinga.com'), 'https://icinga.com') ?> + </div> + </div> + <ul id="social"> + <li> + <?= $this->qlink( + null, + 'https://twitter.com/icinga', + null, + array( + 'target' => '_blank', + 'icon' => 'twitter', + 'title' => $this->translate('Icinga on Twitter') + ) + ) ?> + </li> + <li> + <?= $this->qlink( + null, + 'https://www.facebook.com/icinga', + null, + array( + 'target' => '_blank', + 'icon' => 'facebook-squared', + 'title' => $this->translate('Icinga on Facebook') + ) + ) ?> + </li> + <li><?= $this->qlink( + null, + 'https://github.com/Icinga', + null, + array( + 'target' => '_blank', + 'icon' => 'github-circled', + 'title' => $this->translate('Icinga on GitHub') + ) + ) ?> + </li> + </ul> +</div> +<div id="orb-analytics" class="orb" ><?= $this->img('img/orb-analytics.png'); ?></div> +<div id="orb-automation" class="orb"><?= $this->img('img/orb-automation.png'); ?></div> +<div id="orb-cloud" class="orb"><?= $this->img('img/orb-cloud.png'); ?></div> +<div id="orb-icinga" class="orb"><?= $this->img('img/orb-icinga.png'); ?></div> +<div id="orb-infrastructure" class="orb"><?= $this->img('img/orb-infrastructure.png'); ?></div> +<div id="orb-metrics" class="orb" ><?= $this->img('img/orb-metrics.png'); ?></div> +<div id="orb-notifactions" class="orb"><?= $this->img('img/orb-notifications.png'); ?></div> diff --git a/application/views/scripts/authentication/logout.phtml b/application/views/scripts/authentication/logout.phtml new file mode 100644 index 0000000..d4bd78e --- /dev/null +++ b/application/views/scripts/authentication/logout.phtml @@ -0,0 +1,79 @@ +<!-- + This view provides a workaround to logout from an external authentication provider, in case external + authentication was configured (the default is to handle authentications internally in Icingaweb2). + + The <a href="http://tools.ietf.org/html/rfc2617">Http Basic and Digest Authentication</a> is not + designed to handle logout. When the user has provided valid credentials, the client is adviced to include these + in every further request until the browser was closed. To allow logout and to allow the user to change the + logged-in user this JavaScript provides a workaround to force a new authentication prompt in most browsers. +--> +<div class="content"> + <div id="icinga-logo" aria-hidden="true"></div> + <div class="alert alert-warning" id="logout-status"> + <b><?= $this->translate('Logging out...'); ?></b> + <br> + <?= $this->translate( + 'If this message does not disappear, it might be necessary to quit the' + . ' current session manually by clearing the cache, or by closing the current' + . ' browser session.' + ); ?> + </div> + + <div class="container"> + <a href="<?= $this->href('dashboard'); ?>"><?= $this->translate('Login'); ?></a> + </div> +</div> +<script type="text/javascript"> + /* + * When JavaScript is available, trigger an XmlHTTPRequest with the non-existing user 'logout' and abort it + * before it is able to finish. This will cause the browser to show a new authentication prompt in the next + * request. + */ + document.addEventListener('DOMContentLoaded', function () { + var msg = document.getElementById('logout-status'); + try { + if (navigator.userAgent.toLowerCase().indexOf('msie') !== -1) { + document.execCommand('ClearAuthenticationCache'); + } else { + var xhttp = new XMLHttpRequest(); + xhttp.open('GET', 'arbitrary url', true, 'logout', 'logout'); + xhttp.send(''); + xhttp.abort(); + } + } catch (e) { + } + msg.innerHTML = '<?= $this->translate('Logout successful!'); ?>'; + msg.className = 'alert alert-success'; + }); +</script> +<style type="text/css"> + body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + background-color: #0095bf; + color: white; + } + .content { + text-align: center; + } + + #icinga-logo { + background-image: url('../img/icinga-logo-big.svg'); + background-position: center bottom; + background-repeat: no-repeat; + background-size: contain; + height: 177px; + margin-top: 10em; + width: 100%; + } + + #logout-status { + margin: 2em 0 1em; + font-size: 2em; + font-weight: bold; + } + + .container a { + color: white; + font-size: 1.5em; + } +</style> diff --git a/application/views/scripts/config/devtools.phtml b/application/views/scripts/config/devtools.phtml new file mode 100644 index 0000000..245a71a --- /dev/null +++ b/application/views/scripts/config/devtools.phtml @@ -0,0 +1,6 @@ +<div class="controls"> +<?= $this->tabs ?> +</div> +<table class="avp"> +<tr><th><?= $this->translate('UI Debug') ?></th><td><a href="javascript:void(0);" onclick="icinga.ui.toggleDebug();"><?= $this->translate('toggle') ?></td></tr> +</table> diff --git a/application/views/scripts/config/general.phtml b/application/views/scripts/config/general.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/config/general.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/config/module-configuration-error.phtml b/application/views/scripts/config/module-configuration-error.phtml new file mode 100644 index 0000000..85fb128 --- /dev/null +++ b/application/views/scripts/config/module-configuration-error.phtml @@ -0,0 +1,28 @@ +<?php + $action = (isset($this->action)) ? $this->action : 'do something with'; + $moduleName = $this->moduleName; + $exceptionMessage = $this->exceptionMessage; +?> +<?= $this->tabs->render($this); ?> +<br/> +<div> + <h1>Could not <?= $action; ?> module "<?= $moduleName; ?>"</h1> + <p> + While operation the following error occurred: + <br /> + <?= $exceptionMessage; ?> + </p> +</div> + +<p> + This could have one or more of the following reasons: +<ul> + <li>No file permissions to write into module directory</li> + <li>Errors on filesystems: Mount points, operational errors </li> + <li>General application error</li> +</ul> +</p> + +<p> + Details can be seen in your application log (if you don't have access to this file, call your administrator in this case). +</p>
\ No newline at end of file diff --git a/application/views/scripts/config/module.phtml b/application/views/scripts/config/module.phtml new file mode 100644 index 0000000..6d41ab2 --- /dev/null +++ b/application/views/scripts/config/module.phtml @@ -0,0 +1,136 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?php if (! $module): ?> + <?= $this->translate('There is no such module installed.') ?> + <?php return; endif ?> + <?php + $requiredMods = $module->getRequiredModules(); + $requiredLibs = $module->getRequiredLibraries(); + $restrictions = $module->getProvidedRestrictions(); + $permissions = $module->getProvidedPermissions(); + $unmetDependencies = $moduleManager->hasUnmetDependencies($module->getName()); + $isIcingadbSupported = isset($requiredMods['icingadb']); + $state = $moduleData->enabled ? ($moduleData->loaded ? 'enabled' : 'failed') : 'disabled'; + ?> + <table class="name-value-table"> + <tr> + <th><?= $this->escape($this->translate('Name')) ?></th> + <td><?= $this->escape($module->getName()) ?></td> + </tr> + <tr> + <th><?= $this->translate('State') ?></th> + <td> + <?= $state ?> + <?php if (isset($this->toggleForm)): ?> + <?php if ($moduleData->enabled || ! $unmetDependencies): ?> + <?= $this->toggleForm ?> + <?php else: ?> + <?= $this->icon('attention-alt', $this->translate('Module can\'t be enabled due to unmet dependencies')) ?> + <?php endif ?> + <?php endif ?> + </td> + <tr> + <th><?= $this->escape($this->translate('Version')) ?></th> + <td><?= $this->escape($module->getVersion()) ?></td> + </tr> + <?php if (isset($moduleGitCommitId) && $moduleGitCommitId !== false): ?> + <tr> + <th><?= $this->escape($this->translate('Git commit')) ?></th> + <td><?= $this->escape($moduleGitCommitId) ?></td> + </tr> + <?php endif ?> + <tr> + <th><?= $this->escape($this->translate('Description')) ?></th> + <td> + <strong><?= $this->escape($module->getTitle()) ?></strong><br> + <?= nl2br($this->escape($module->getDescription())) ?> + </td> + </tr> + <tr> + <th><?= $this->escape($this->translate('Dependencies')) ?></th> + <td class="module-dependencies"> + <?php if (empty($requiredLibs) && empty($requiredMods)): ?> + <?= $this->translate('This module has no dependencies') ?> + <?php else: ?> + <?php if ($unmetDependencies): ?> + <strong class="unmet-dependencies"> + <?= $this->translate('Unmet dependencies found! Module can\'t be enabled unless all dependencies are met.') ?> + </strong> + <?php endif ?> + <?php if (! empty($requiredLibs)): ?> + <table class="name-value-table"> + <caption><?= $this->translate('Libraries') ?></caption> + <?php foreach ($requiredLibs as $libraryName => $versionString): ?> + <tr> + <th><?= $this->escape($libraryName) ?></th> + <td> + <?php if ($libraries->has($libraryName, $versionString === true ? null : $versionString)): ?> + <?= $versionString === true ? '*' : $this->escape($versionString) ?> + <?php else: ?> + <span class="missing"><?= $versionString === true ? '*' : $this->escape($versionString) ?></span> + <?php if (($library = $libraries->get($libraryName)) !== null): ?> + (<?= $library->getVersion() ?>) + <?php endif ?> + <?php endif ?> + </td> + </tr> + <?php endforeach ?> + </table> + <?php endif ?> + <?php if (! empty($requiredMods)): ?> + <table class="name-value-table"> + <caption><?= $this->translate('Modules') ?></caption> + <?php foreach ($requiredMods as $moduleName => $versionString): ?> + <?php if ($moduleName === 'monitoring' && $isIcingadbSupported && $moduleManager->has('icingadb', $requiredMods['icingadb'])) : ?> + <?php continue; ?> + <?php endif ?> + <tr> + <th><?= $this->escape($moduleName) ?></th> + <td> + <?php if ($moduleManager->has($moduleName, $versionString === true ? null : $versionString)): ?> + <?= $versionString === true ? '*' : $this->escape($versionString) ?> + <?php else: ?> + <span <?= ($moduleName === 'icingadb' && isset($requiredMods['monitoring']) && $moduleManager->has('monitoring', $requiredMods['monitoring'])) ? 'class="optional"' : 'class="missing"' ?>> + <?= $versionString === true ? '*' : $this->escape($versionString) ?> + </span> + <?php if (! $moduleManager->hasInstalled($moduleName)): ?> + (<?= $this->translate('not installed') ?>) + <?php else: ?> + (<?= $moduleManager->getModule($moduleName, false)->getVersion() ?><?= $moduleManager->hasEnabled($moduleName) ? '' : ', ' . $this->translate('disabled') ?>) + <?php endif ?> + <?php endif ?> + </td> + <?php if ($moduleName === 'monitoring' && $isIcingadbSupported) : ?> + <td class="or-separator"><?= $this->translate('or') ?></td> + <?php endif ?> + </tr> + <?php endforeach ?> + </table> + <?php endif ?> + <?php endif ?> + </td> + </tr> + <?php if (! empty($permissions)): ?> + <tr> + <th><?= $this->escape($this->translate('Permissions')) ?></th> + <td> + <?php foreach ($permissions as $permission): ?> + <strong><?= $this->escape($permission->name) ?></strong>: <?= $this->escape($permission->description) ?><br /> + <?php endforeach ?> + </td> + </tr> + <?php endif ?> + <?php if (! empty($restrictions)): ?> + <tr> + <th><?= $this->escape($this->translate('Restrictions')) ?></th> + <td> + <?php foreach ($restrictions as $restriction): ?> + <strong><?= $this->escape($restriction->name) ?></strong>: <?= $this->escape($restriction->description) ?><br /> + <?php endforeach ?> + </td> + </tr> + <?php endif ?> + </table> +</div> diff --git a/application/views/scripts/config/modules.phtml b/application/views/scripts/config/modules.phtml new file mode 100644 index 0000000..b13b378 --- /dev/null +++ b/application/views/scripts/config/modules.phtml @@ -0,0 +1,42 @@ +<?php if (! $this->compact): ?> +<div class="controls"> + <?= $this->tabs ?> + <?= $this->paginator ?> +</div> +<?php endif ?> +<div class="content"> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Module') ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($modules as $module): ?> + <tr> + <td> + <?php if (! $module->installed) { + $this->icon('flash', sprintf($this->translate('Module %s is dangling'), $module->name)); + } elseif ($module->enabled && $module->loaded) { + echo $this->icon('thumbs-up', sprintf($this->translate('Module %s is enabled'), $module->name)); + } elseif (! $module->enabled) { + echo $this->icon('block', sprintf($this->translate('Module %s is disabled'), $module->name)); + } else { // ! $module->loaded + echo $this->icon('block', sprintf($this->translate('Module %s has failed to load'), $module->name)); + } + + echo $this->qlink( + $module->name, + 'config/module', + array('name' => $module->name), + array( + 'class' => 'rowaction', + 'title' => sprintf($this->translate('Show the overview of the %s module'), $module->name) + ) + ); ?> + </td> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/config/resource.phtml b/application/views/scripts/config/resource.phtml new file mode 100644 index 0000000..317c115 --- /dev/null +++ b/application/views/scripts/config/resource.phtml @@ -0,0 +1,73 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $this->qlink( + $this->translate('Create a New Resource') , + 'config/createresource', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new resource') + ) + ) ?> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Resource') ?></th> + <th></th> + </tr> + </thead> + <tbody> +<?php foreach ($this->resources as $name => $value): ?> + <tr> + <td> + <?php + switch ($value->type) { + case 'db': + $icon = 'database'; + break; + case 'ldap': + $icon = 'sitemap'; + break; + case 'ssh': + $icon = 'user'; + break; + case 'file': + case 'ini': + $icon = 'doc-text'; + break; + default: + $icon = 'edit'; + break; + } + ?> + <?= $this->qlink( + $name, + 'config/editresource', + array('resource' => $name), + array( + 'icon' => $icon, + 'title' => sprintf($this->translate('Edit resource %s'), $name) + ) + ) ?> + </td> + <td class="icon-col text-right"> + <?= $this->qlink( + '', + 'config/removeresource', + array('resource' => $name), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove resource %s'), $name) + ) + ) ?> + </td> + </tr> +<?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/config/resource/create.phtml b/application/views/scripts/config/resource/create.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/config/resource/create.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/config/resource/modify.phtml b/application/views/scripts/config/resource/modify.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/config/resource/modify.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/config/resource/remove.phtml b/application/views/scripts/config/resource/remove.phtml new file mode 100644 index 0000000..13a8ed9 --- /dev/null +++ b/application/views/scripts/config/resource/remove.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form ?> +</div> diff --git a/application/views/scripts/config/userbackend/reorder.phtml b/application/views/scripts/config/userbackend/reorder.phtml new file mode 100644 index 0000000..c77fd2e --- /dev/null +++ b/application/views/scripts/config/userbackend/reorder.phtml @@ -0,0 +1,75 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?php if ($this->auth()->hasPermission('config/access-control/users')): ?> + <h1><?= $this->translate('User Backends') ?></h1> + <?= $this->qlink( + $this->translate('Create a New User Backend') , + 'config/createuserbackend', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new user backend') + ) + ) ?> + <?= $form ?> + <?php endif ?> + + <?php if ($this->auth()->hasPermission('config/access-control/groups')): ?> + <h1><?= $this->translate('User Group Backends') ?></h1> + <?= $this->qlink( + $this->translate('Create a New User Group Backend') , + 'usergroupbackend/create', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new user group backend') + ) + ) ?> +<?php if (! count($backendNames)) { return; } ?> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Backend') ?></th> + <th></th> + </tr> + </thead> + <tbody> +<?php foreach ($backendNames as $backendName => $config): + $type = $config->get('backend'); +?> + <tr> + <td> + <?= $this->qlink( + $backendName, + 'usergroupbackend/edit', + array('backend' => $backendName), + array( + 'icon' => $type === 'external' ? 'magic' : ($type === 'ldap' || $type === 'msldap' ? 'sitemap' : 'database'), + 'title' => sprintf($this->translate('Edit user group backend %s'), $backendName) + ) + ); ?> + </td> + <td class="icon-col text-right"> + <?= $this->qlink( + null, + 'usergroupbackend/remove', + array('backend' => $backendName), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove user group backend %s'), $backendName) + ) + ) ?> + </td> + </tr> + <?php endforeach ?> + </tbody> + </table> + <?php endif ?> +</div> diff --git a/application/views/scripts/dashboard/error.phtml b/application/views/scripts/dashboard/error.phtml new file mode 100644 index 0000000..9396b49 --- /dev/null +++ b/application/views/scripts/dashboard/error.phtml @@ -0,0 +1,13 @@ +<div class="content"> + <h1><?= $this->translate('Could not save dashboard'); ?></h1> + <p> + <?= $this->translate('Please copy the following dashboard snippet to '); ?> + <strong><?= $this->config->getConfigFile(); ?>;</strong>. + <br> + <?= $this->translate('Make sure that the webserver can write to this file.'); ?> + </p> + <pre><?= $this->config; ?></pre> + <hr> + <h2><?= $this->translate('Error details'); ?></h2> + <p><?= $this->error->getMessage(); ?></p> +</div>
\ No newline at end of file diff --git a/application/views/scripts/dashboard/index.phtml b/application/views/scripts/dashboard/index.phtml new file mode 100644 index 0000000..1d56114 --- /dev/null +++ b/application/views/scripts/dashboard/index.phtml @@ -0,0 +1,26 @@ +<div class="controls"> +<?php if (! $this->compact): ?> +<?= $this->tabs ?> +<?php endif ?> +</div> +<?php if ($this->dashboard): ?> + <div class="dashboard content"> + <?= $this->dashboard ?> + </div> +<?php else: ?> + <div class="content"> + <h1><?= $this->escape($this->translate('Welcome to Icinga Web!')) ?></h1> + <p> + <?php if (! $this->hasPermission('config/modules')) { + echo $this->escape($this->translate( + 'Currently there is no dashlet available. Please contact the administrator.' + )); + } else { + printf( + $this->escape($this->translate('Currently there is no dashlet available. This might change once you enabled some of the available %s.')), + $this->qlink($this->translate('modules'), 'config/modules') + ); + } ?> + </p> + </div> +<?php endif ?> diff --git a/application/views/scripts/dashboard/new-dashlet.phtml b/application/views/scripts/dashboard/new-dashlet.phtml new file mode 100644 index 0000000..b265a25 --- /dev/null +++ b/application/views/scripts/dashboard/new-dashlet.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?= $this->form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/dashboard/remove-dashlet.phtml b/application/views/scripts/dashboard/remove-dashlet.phtml new file mode 100644 index 0000000..b265a25 --- /dev/null +++ b/application/views/scripts/dashboard/remove-dashlet.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?= $this->form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/dashboard/remove-pane.phtml b/application/views/scripts/dashboard/remove-pane.phtml new file mode 100644 index 0000000..b265a25 --- /dev/null +++ b/application/views/scripts/dashboard/remove-pane.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?= $this->form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/dashboard/rename-pane.phtml b/application/views/scripts/dashboard/rename-pane.phtml new file mode 100644 index 0000000..b265a25 --- /dev/null +++ b/application/views/scripts/dashboard/rename-pane.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?= $this->form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/dashboard/settings.phtml b/application/views/scripts/dashboard/settings.phtml new file mode 100644 index 0000000..a6cfe83 --- /dev/null +++ b/application/views/scripts/dashboard/settings.phtml @@ -0,0 +1,91 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <h1><?= t('Dashboard Settings'); ?></h1> + + <table class="avp action" data-base-target="_next"> + <thead> + <tr> + <th style="width: 18em;"> + <strong><?= t('Dashlet Name') ?></strong> + </th> + <th> + <strong><?= t('Url') ?></strong> + </th> + <th style="width: 1.4em;"> </th> + </tr> + </thead> + <tbody> + <?php foreach ($this->dashboard->getPanes() as $pane): ?> + <?php if ($pane->getDisabled()) continue; ?> + <tr> + <th colspan="2" style="text-align: left; padding: 0.5em;"> + <?php if ($pane->isUserWidget()): ?> + <?= $this->qlink( + $pane->getName(), + 'dashboard/rename-pane', + array('pane' => $pane->getName()), + array('title' => sprintf($this->translate('Edit pane %s'), $pane->getName())) + ) ?> + <?php else: ?> + <?= $this->escape($pane->getName()) ?> + <?php endif ?> + </th> + <th> + <?= $this->qlink( + '', + 'dashboard/remove-pane', + array('pane' => $pane->getName()), + array( + 'icon' => 'trash', + 'title' => sprintf($this->translate('Remove pane %s'), $pane->getName()) + ) + ); ?> + </th> + </tr> + <?php $dashlets = $pane->getDashlets(); ?> + <?php if(empty($dashlets)): ?> + <tr> + <td colspan="3"> + <?= $this->translate('No dashlets added to dashboard') ?>. + </td> + </tr> + <?php else: ?> + <?php foreach ($dashlets as $dashlet): ?> + <?php if ($dashlet->getDisabled()) continue; ?> + <tr> + <td> + <?= $this->qlink( + $dashlet->getTitle(), + 'dashboard/update-dashlet', + array('pane' => $pane->getName(), 'dashlet' => $dashlet->getName()), + array('title' => sprintf($this->translate('Edit dashlet %s'), $dashlet->getTitle())) + ); ?> + </td> + <td style="table-layout: fixed; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> + <?= $this->qlink( + $dashlet->getUrl()->getRelativeUrl(), + $dashlet->getUrl()->getRelativeUrl(), + null, + array('title' => sprintf($this->translate('Show dashlet %s'), $dashlet->getTitle())) + ); ?> + </td> + <td> + <?= $this->qlink( + '', + 'dashboard/remove-dashlet', + array('pane' => $pane->getName(), 'dashlet' => $dashlet->getName()), + array( + 'icon' => 'trash', + 'title' => sprintf($this->translate('Remove dashlet %s from pane %s'), $dashlet->getTitle(), $pane->getTitle()) + ) + ); ?> + </td> + </tr> + <?php endforeach; ?> + <?php endif; ?> + <?php endforeach; ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/dashboard/update-dashlet.phtml b/application/views/scripts/dashboard/update-dashlet.phtml new file mode 100644 index 0000000..b265a25 --- /dev/null +++ b/application/views/scripts/dashboard/update-dashlet.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $this->tabs ?> +</div> +<div class="content"> + <?= $this->form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/error/error.phtml b/application/views/scripts/error/error.phtml new file mode 100644 index 0000000..3c7462f --- /dev/null +++ b/application/views/scripts/error/error.phtml @@ -0,0 +1,106 @@ +<?php if (! $this->compact && ! $hideControls): ?> +<div class="controls"> + <?= $tabs ?> +</div> +<?php endif ?> +<div class="content"> +<?php +if (isset($stackTraces)) { + foreach ($messages as $i => $message) { + echo '<p tabindex="-1" class="autofocus error-message">' . nl2br($this->escape($message)) . '</p>' + . '<hr>' + . '<pre>' . $this->escape($stackTraces[$i]) . '</pre>'; + } +} else { + foreach ($messages as $message) { + echo '<p tabindex="-1" class="autofocus error-message">' . nl2br($this->escape($message)) . '</p>'; + } +} + +$libraries = \Icinga\Application\Icinga::app()->getLibraries(); +$coreReason = []; +$modReason = []; + +if (isset($requiredVendor, $requiredProject) && $requiredVendor && $requiredProject) { + // TODO: I don't like this, can we define requirements somewhere else? + $coreDeps = ['icinga-php-library' => '>= 0.9', 'icinga-php-thirdparty' => '>= 0.11']; + + foreach ($coreDeps as $libraryName => $requiredVersion) { + if (! $libraries->has($libraryName)) { + $coreReason[] = sprintf($this->translate( + 'Library "%s" is required and missing. Please install a version of it matching the required one: %s' + ), $libraryName, $requiredVersion); + } elseif (! $libraries->has($libraryName, $requiredVersion) && $libraries->get($libraryName)->isRequired($requiredVendor, $requiredProject)) { + $coreReason[] = sprintf($this->translate( + 'Library "%s" is required and installed, but its version (%s) does not satisfy the required one: %s' + ), $libraryName, $libraries->get($libraryName)->getVersion() ?: '-', $requiredVersion); + } + } + + if (! empty($coreReason)) { + array_unshift($coreReason, $this->translate('You have unmet dependencies. Please check Icinga Web 2\'s installation instructions.')); + } +} + +if (isset($module)) { + $manager = \Icinga\Application\Icinga::app()->getModuleManager(); + if ($manager->hasUnmetDependencies($module->getName())) { + if (isset($requiredModule) && $requiredModule && isset($module->getRequiredModules()[$requiredModule])) { + if (! $manager->hasInstalled($requiredModule)) { + $modReason[] = sprintf($this->translate( + 'Module "%s" is required and missing. Please install a version of it matching the required one: %s' + ), $requiredModule, $module->getRequiredModules()[$requiredModule]); + } elseif (! $manager->hasEnabled($requiredModule)) { + $modReason[] = sprintf($this->translate( + 'Module "%s" is required and installed, but not enabled. Please enable module "%1$s".' + ), $requiredModule); + } elseif (! $manager->has($requiredModule, $module->getRequiredModules()[$requiredModule])) { + $modReason[] = sprintf($this->translate( + 'Module "%s" is required and installed, but its version (%s) does not satisfy the required one: %s' + ), $requiredModule, $manager->getModule($requiredModule, false)->getVersion(), $module->getRequiredModules()[$requiredModule]); + } + } elseif (isset($requiredVendor, $requiredProject) && $requiredVendor && $requiredProject) { + foreach ($module->getRequiredLibraries() as $libraryName => $requiredVersion) { + if (! $libraries->has($libraryName)) { + $modReason[] = sprintf($this->translate( + 'Library "%s" is required and missing. Please install a version of it matching the required one: %s' + ), $libraryName, $requiredVersion); + } elseif (! $libraries->has($libraryName, $requiredVersion) && $libraries->get($libraryName)->isRequired($requiredVendor, $requiredProject)) { + $modReason[] = sprintf($this->translate( + 'Library "%s" is required and installed, but its version (%s) does not satisfy the required one: %s' + ), $libraryName, $libraries->get($libraryName)->getVersion() ?: '-', $requiredVersion); + } + } + } + + if (! empty($modReason)) { + array_unshift($modReason, sprintf($this->translate( + 'This error might have occurred because module "%s" has unmet dependencies.' + . ' Please check it\'s installation instructions and install missing dependencies.' + ), $module->getName())); + } + } +} + +// The following doesn't use ipl\Html because that's what the error possibly is about +?> +<?php if (! empty($coreReason)): ?> +<div class="error-reason"> +<?php endif ?> +<?php foreach ($coreReason as $msg): ?> + <p><?= $msg ?></p> +<?php endforeach ?> +<?php if (! empty($coreReason)): ?> +</div> +<?php endif ?> + +<?php if (! empty($modReason)): ?> +<div class="error-reason"> +<?php endif ?> +<?php foreach ($modReason as $msg): ?> + <p><?= $msg ?></p> +<?php endforeach ?> +<?php if (! empty($modReason)): ?> +</div> +<?php endif ?> +</div> diff --git a/application/views/scripts/filter/index.phtml b/application/views/scripts/filter/index.phtml new file mode 100644 index 0000000..5e6a63d --- /dev/null +++ b/application/views/scripts/filter/index.phtml @@ -0,0 +1,11 @@ +<?php + +echo $this->form; + +if ($this->tree) { + echo $this->tree->render($this); + echo '<br/><pre><code>'; + echo $this->sqlString; + echo '</pre></code>'; + print_r($this->params); +}
\ No newline at end of file diff --git a/application/views/scripts/form/reorder-authbackend.phtml b/application/views/scripts/form/reorder-authbackend.phtml new file mode 100644 index 0000000..34b10b3 --- /dev/null +++ b/application/views/scripts/form/reorder-authbackend.phtml @@ -0,0 +1,83 @@ +<form id="<?= +$this->escape($form->getId()) +?>" name="<?= +$this->escape($form->getName()) +?>" enctype="<?= +$this->escape($form->getEncType()) +?>" method="<?= +$this->escape($form->getMethod()) +?>" action="<?= +$this->escape($form->getAction()) +?>"> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <th><?= $this->translate('Backend') ?></th> + <th></th> + <th></th> + </thead> + <tbody> +<?php + $backendNames = $form->getBackendOrder(); + $backendConfigs = $form->getConfig(); + for ($i = 0; $i < count($backendNames); $i++): + $type = $backendConfigs->getSection($backendNames[$i])->get('backend'); +?> + <tr> + <td class="action"> + <?= $this->qlink( + $backendNames[$i], + 'config/edituserbackend', + array('backend' => $backendNames[$i]), + array( + 'icon' => $type === 'external' ? + 'magic' : ($type === 'ldap' || $type === 'msldap' ? 'sitemap' : 'database'), + 'class' => 'rowaction', + 'title' => sprintf($this->translate('Edit user backend %s'), $backendNames[$i]) + ) + ) ?> + </td> + <td class="icon-col text-right"> + <?= $this->qlink( + '', + 'config/removeuserbackend', + array('backend' => $backendNames[$i]), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove user backend %s'), $backendNames[$i]) + ) + ) ?> + </td> + <td class="icon-col text-right" data-base-target="_self"> +<?php if ($i > 0): ?> + <button type="submit" name="backend_newpos" class="link-button icon-only animated move-up" value="<?= $this->escape( + $backendNames[$i] . '|' . ($i - 1) + ) ?>" title="<?= $this->translate( + 'Move up in authentication order' + ) ?>" aria-label="<?= $this->escape(sprintf( + $this->translate('Move user backend %s upwards'), + $backendNames[$i] + )) ?>"> + <?= $this->icon('up-small') ?> + </button> +<?php endif ?> +<?php if ($i + 1 < count($backendNames)): ?> + <button type="submit" name="backend_newpos" class="link-button icon-only animated move-down" value="<?= $this->escape( + $backendNames[$i] . '|' . ($i + 1) + ) ?>" title="<?= $this->translate( + 'Move down in authentication order' + ) ?>" aria-label="<?= $this->escape(sprintf( + $this->translate('Move user backend %s downwards'), + $backendNames[$i] + )) ?>"> + <?= $this->icon('down-small') ?> + </button> +<?php endif ?> + </td> + </tr> +<?php endfor ?> + </tbody> + </table> + <?= $form->getElement($form->getTokenElementName()) ?> + <?= $form->getElement($form->getUidElementName()) ?> +</form> diff --git a/application/views/scripts/group/form.phtml b/application/views/scripts/group/form.phtml new file mode 100644 index 0000000..cbf0659 --- /dev/null +++ b/application/views/scripts/group/form.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs->showOnlyCloseButton(); ?> +</div> +<div class="content"> + <?= $form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/group/list.phtml b/application/views/scripts/group/list.phtml new file mode 100644 index 0000000..d362db4 --- /dev/null +++ b/application/views/scripts/group/list.phtml @@ -0,0 +1,96 @@ +<?php + +use Icinga\Data\Extensible; +use Icinga\Data\Reducible; + +if (! $this->compact): ?> +<div class="controls separated"> + <?= $this->tabs ?> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + <?= $this->sortBox ?> + </div> + <?= $this->backendSelection ?> + <?= $this->filterEditor ?> +</div> +<?php endif ?> +<div class="content"> +<?php + +if (! isset($backend)) { + echo $this->translate('No backend found which is able to list user groups') . '</div>'; + return; +} else { + $extensible = $this->hasPermission('config/access-control/groups') && $backend instanceof Extensible; + $reducible = $this->hasPermission('config/access-control/groups') && $backend instanceof Reducible; +} +?> + +<?php if ($extensible): ?> + <?= $this->qlink( + $this->translate('Add a New User Group'), + 'group/add', + array('backend' => $backend->getName()), + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus' + ) + ) ?> +<?php endif ?> + +<?php if (! $groups->hasResult()): ?> + <p><?= $this->translate('No user groups found matching the filter'); ?></p> +</div> +<?php return; endif ?> + <table data-base-target="_next" class="table-row-selectable common-table"> + <thead> + <tr> + <th><?= $this->translate('User Group'); ?></th> + <?php if ($reducible): ?> + <th><?= $this->translate('Remove'); ?></th> + <?php endif ?> + </tr> + </thead> + <tbody> + <?php foreach ($groups as $group): ?> + <tr> + <td> + <?= $this->qlink( + $group->group_name, + 'group/show', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'title' => sprintf( + $this->translate('Show detailed information for user group %s'), + $group->group_name + ) + ) + ); ?> + </td> + <?php if ($reducible): ?> + <td class="icon-col"> + <?= $this->qlink( + null, + 'group/remove', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'class' => 'action-link', + 'title' => sprintf($this->translate('Remove user group %s'), $group->group_name), + 'icon' => 'cancel' + ) + ); ?> + </td> + <?php endif ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/group/show.phtml b/application/views/scripts/group/show.phtml new file mode 100644 index 0000000..75f0b75 --- /dev/null +++ b/application/views/scripts/group/show.phtml @@ -0,0 +1,108 @@ +<?php + +use Icinga\Data\Extensible; +use Icinga\Data\Updatable; + +$extensible = $this->hasPermission('config/access-control/groups') && $backend instanceof Extensible; + +$editLink = null; +if ($this->hasPermission('config/access-control/groups') && $backend instanceof Updatable) { + $editLink = $this->qlink( + null, + 'group/edit', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'title' => sprintf($this->translate('Edit group %s'), $group->group_name), + 'class' => 'group-edit', + 'icon' => 'edit' + ) + ); +} + +?> +<div class="controls separated"> +<?php if (! $this->compact): ?> + <?= $tabs; ?> +<?php endif ?> + <h2 class="clearfix"><?= $this->escape($group->group_name) ?><span class="pull-right"><?= $editLink ?></span></h2> + <table class="name-value-table"> + <tr> + <th><?= $this->translate('Created at'); ?></th> + <td><?= $group->created_at === null ? '-' : $this->formatDateTime($group->created_at); ?></td> + </tr> + <tr> + <th><?= $this->translate('Last modified'); ?></th> + <td><?= $group->last_modified === null ? '-' : $this->formatDateTime($group->last_modified); ?></td> + </tr> + </table> +<?php if (! $this->compact): ?> + <h2><?= $this->translate('Members'); ?></h2> + <div class="sort-controls-container"> + <?= $this->limiter; ?> + <?= $this->paginator; ?> + <?= $this->sortBox; ?> + </div> + <?= $this->filterEditor; ?> +<?php endif ?> +</div> +<div class="content"> +<?php if ($extensible): ?> + <?= $this->qlink( + $this->translate('Add New Member'), + 'group/addmember', + array( + 'backend' => $backend->getName(), + 'group' => $group->group_name + ), + array( + 'icon' => 'plus', + 'class' => 'button-link' + ) + ) ?> +<?php endif ?> + +<?php if (! $members->hasResult()): ?> + <p><?= $this->translate('No group member found matching the filter'); ?></p> +</div> +<?php return; endif ?> + + <table data-base-target="_next" class="table-row-selectable common-table"> + <thead> + <tr> + <th><?= $this->translate('Username'); ?></th> + <?php if (isset($removeForm)): ?> + <th><?= $this->translate('Remove'); ?></th> + <?php endif ?> + </tr> + </thead> + <tbody> + <?php foreach ($members as $member): ?> + <tr> + <td> + <?php if ( + $this->hasPermission('config/access-control/users') + && ($userBackend = $backend->getUserBackendName($member->user_name)) !== null + ): ?> + <?= $this->qlink($member->user_name, 'user/show', array( + 'backend' => $userBackend, + 'user' => $member->user_name + ), array( + 'title' => sprintf($this->translate('Show detailed information about %s'), $member->user_name) + )); ?> + <?php else: ?> + <?= $this->escape($member->user_name); ?> + <?php endif ?> + </td> + <?php if (isset($removeForm)): ?> + <td class="icon-col" data-base-target="_self"> + <?php $removeForm->getElement('user_name')->setValue($member->user_name); echo $removeForm; ?> + </td> + <?php endif ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/iframe/index.phtml b/application/views/scripts/iframe/index.phtml new file mode 100644 index 0000000..96e9de7 --- /dev/null +++ b/application/views/scripts/iframe/index.phtml @@ -0,0 +1,8 @@ +<?php if (! $compact): ?> +<div class="controls"> + <?= $tabs ?> +</div> +<?php endif ?> +<div class="iframe-container"> + <iframe src="<?= $this->escape($url) ?>" frameborder="no"></iframe> +</div> diff --git a/application/views/scripts/index/welcome.phtml b/application/views/scripts/index/welcome.phtml new file mode 100644 index 0000000..496dec9 --- /dev/null +++ b/application/views/scripts/index/welcome.phtml @@ -0,0 +1,2 @@ +<h1>Welcome to Icinga!</h1> +You should install/configure some <a href="<?= $this->href('config/modules');?>">modules</a> now! diff --git a/application/views/scripts/inline.phtml b/application/views/scripts/inline.phtml new file mode 100644 index 0000000..2534d44 --- /dev/null +++ b/application/views/scripts/inline.phtml @@ -0,0 +1,2 @@ +<?= $this->layout()->content ?> + diff --git a/application/views/scripts/joystickPagination.phtml b/application/views/scripts/joystickPagination.phtml new file mode 100644 index 0000000..a8c24c9 --- /dev/null +++ b/application/views/scripts/joystickPagination.phtml @@ -0,0 +1,162 @@ +<?php + +use Icinga\Web\Url; + +$showText = $this->translate('%s: Show %s %u to %u out of %u', 'pagination.joystick'); +$xAxisPages = $xAxisPaginator->getPages('all'); +$yAxisPages = $yAxisPaginator->getPages('all'); + +$flipUrl = Url::fromRequest(); +if ($flipUrl->getParam('flipped')) { + $flipUrl->remove('flipped'); +} else { + $flipUrl->setParam('flipped'); +} +if ($flipUrl->hasParam('page')) { + $flipUrl->setParam('page', implode(',', array_reverse(explode(',', $flipUrl->getParam('page'))))); +} +if ($flipUrl->hasParam('limit')) { + $flipUrl->setParam('limit', implode(',', array_reverse(explode(',', $flipUrl->getParam('limit'))))); +} + +$totalYAxisPages = $yAxisPaginator->count(); +$currentYAxisPage = $yAxisPaginator->getCurrentPageNumber(); +$prevYAxisPage = $currentYAxisPage > 1 ? $currentYAxisPage - 1 : null; +$nextYAxisPage = $currentYAxisPage < $totalYAxisPages ? $currentYAxisPage + 1 : null; + +$totalXAxisPages = $xAxisPaginator->count(); +$currentXAxisPage = $xAxisPaginator->getCurrentPageNumber(); +$prevXAxisPage = $currentXAxisPage > 1 ? $currentXAxisPage - 1 : null; +$nextXAxisPage = $currentXAxisPage < $totalXAxisPages ? $currentXAxisPage + 1 : null; + +?> + +<table class="joystick-pagination"> + <tbody> + <tr> + <td> </td> + <td> + <?php if ($prevYAxisPage): ?> + <?= $this->qlink( + '', + Url::fromRequest(), + array( + 'page' => $currentXAxisPage . ',' . $prevYAxisPage + ), + array( + 'icon' => 'up-open', + 'data-base-target' => '_self', + 'title' => sprintf( + $showText, + $this->translate('Y-Axis', 'pagination.joystick'), + $this->translate('hosts', 'pagination.joystick'), + ($prevYAxisPage - 1) * $yAxisPages->itemCountPerPage + 1, + $prevYAxisPage * $yAxisPages->itemCountPerPage, + $yAxisPages->totalItemCount + ) + ) + ); ?> + <?php else: ?> + <?= $this->icon('up-open'); ?> + <?php endif ?> + </td> + <td> </td> + </tr> + <tr> + <td> + <?php if ($prevXAxisPage): ?> + <?= $this->qlink( + '', + Url::fromRequest(), + array( + 'page' => $prevXAxisPage . ',' . $currentYAxisPage + ), + array( + 'icon' => 'left-open', + 'data-base-target' => '_self', + 'title' => sprintf( + $showText, + $this->translate('X-Axis', 'pagination.joystick'), + $this->translate('services', 'pagination.joystick'), + ($prevXAxisPage - 1) * $xAxisPages->itemCountPerPage + 1, + $prevXAxisPage * $xAxisPages->itemCountPerPage, + $xAxisPages->totalItemCount + ) + ) + ); ?> + <?php else: ?> + <?= $this->icon('left-open'); ?> + <?php endif ?> + </td> + <?php if ($this->flippable): ?> + <td><?= $this->qlink( + '', + $flipUrl, + null, + array( + 'icon' => 'arrows-cw', + 'data-base-target' => '_self', + 'title' => $this->translate('Flip grid axes') + ) + ) ?></td> + <?php else: ?> + <td> </td> + <?php endif ?> + <td> + <?php if ($nextXAxisPage): ?> + <?= $this->qlink( + '', + Url::fromRequest(), + array( + 'page' => $nextXAxisPage . ',' . $currentYAxisPage + ), + array( + 'icon' => 'right-open', + 'data-base-target' => '_self', + 'title' => sprintf( + $showText, + $this->translate('X-Axis', 'pagination.joystick'), + $this->translate('services', 'pagination.joystick'), + $currentXAxisPage * $xAxisPages->itemCountPerPage + 1, + $nextXAxisPage === $xAxisPages->last ? $xAxisPages->totalItemCount : $nextXAxisPage * $xAxisPages->itemCountPerPage, + $xAxisPages->totalItemCount + ) + ), + false + ); ?> + <?php else: ?> + <?= $this->icon('right-open'); ?> + <?php endif ?> + </td> + </tr> + <tr> + <td> </td> + <td> + <?php if ($nextYAxisPage): ?> + <?= $this->qlink( + '', + Url::fromRequest(), + array( + 'page' => $currentXAxisPage . ',' . $nextYAxisPage + ), + array( + 'icon' => 'down-open', + 'data-base-target' => '_self', + 'title' => sprintf( + $showText, + $this->translate('Y-Axis', 'pagination.joystick'), + $this->translate('hosts', 'pagination.joystick'), + $currentYAxisPage * $yAxisPages->itemCountPerPage + 1, + $nextYAxisPage === $yAxisPages->last ? $yAxisPages->totalItemCount : $nextYAxisPage * $yAxisPages->itemCountPerPage, + $yAxisPages->totalItemCount + ) + ) + ); ?> + <?php else: ?> + <?= $this->icon('down-open'); ?> + <?php endif ?> + </td> + <td> </td> + </tr> + </tbody> +</table> diff --git a/application/views/scripts/layout/announcements.phtml b/application/views/scripts/layout/announcements.phtml new file mode 100644 index 0000000..3be6b83 --- /dev/null +++ b/application/views/scripts/layout/announcements.phtml @@ -0,0 +1 @@ +<?= $this->widget('announcements') ?> diff --git a/application/views/scripts/layout/menu.phtml b/application/views/scripts/layout/menu.phtml new file mode 100644 index 0000000..dfb544d --- /dev/null +++ b/application/views/scripts/layout/menu.phtml @@ -0,0 +1,20 @@ +<?php + +use Icinga\Web\Navigation\ConfigMenu; +use Icinga\Web\Widget\SearchDashboard; + +$searchDashboard = new SearchDashboard(); +$searchDashboard->setUser($this->Auth()->getUser()); + +if ($searchDashboard->search('dummy')->getPane('search')->hasDashlets()): ?> + <form action="<?= $this->href('search') ?>" method="get" role="search" class="search-control"> + <input type="text" name="q" id="search" class="search search-input" required + placeholder="<?= $this->translate('Search') ?> …" + autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"> + <button class="search-reset icon-cancel" type="reset"></button> + </form> +<?php endif; ?> +<?= $menuRenderer->setCssClass('primary-nav')->setElementTag('nav')->setHeading(t('Navigation')); ?> +<nav class="config-menu"> + <?= new ConfigMenu() ?> +</nav> diff --git a/application/views/scripts/list/applicationlog.phtml b/application/views/scripts/list/applicationlog.phtml new file mode 100644 index 0000000..aa1a90a --- /dev/null +++ b/application/views/scripts/list/applicationlog.phtml @@ -0,0 +1,29 @@ +<?php if (! $this->compact): ?> +<div class="controls separated"> + <?= $this->tabs ?> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + </div> +</div> +<?php endif ?> +<div class="content"> +<?php if ($this->logData !== null): ?> + <table class="action"> + <tbody> + <?php foreach ($this->logData as $value): ?> + <?php $datetime = new Datetime($value->datetime) ?> + <tr class="state"> + <td style="width: 6em; text-align: center"> + <?= $this->escape($datetime->format('d.m. H:i')) ?><br /> + <?= $this->escape($value->loglevel) ?> + </td> + <td> + <?= nl2br($this->escape($value->message), false) ?> + </td> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php endif ?> +</div> diff --git a/application/views/scripts/mixedPagination.phtml b/application/views/scripts/mixedPagination.phtml new file mode 100644 index 0000000..e92a9c9 --- /dev/null +++ b/application/views/scripts/mixedPagination.phtml @@ -0,0 +1,79 @@ +<?php if ($this->pageCount <= 1) return; ?> +<div class="pagination-control" role="navigation"> + <h2 id="<?= $this->protectId('pagination') ?>" class="sr-only" tabindex="-1"><?= $this->translate('Pagination') ?></h2> + <ul class="nav tab-nav"> + <?php if (isset($this->previous)): ?> + <?php $label = sprintf( + $this->translate('Show rows %u to %u of %u'), + ($this->current - 2) * $this->itemCountPerPage + 1, + ($this->current - 1) * $this->itemCountPerPage, + $this->totalItemCount + ) ?> + <li class="nav-item"> + <a href="<?= $this->escape($this->url()->overwriteParams(array('page' => $this->previous))->getAbsoluteUrl()) ?>" + title="<?= $label ?>" + aria-label="<?= $label ?>" + class="previous-page"> + <?= $this->icon('angle-double-left') ?> + </a> + </li> + <?php else: ?> + <li class="nav-item disabled" aria-hidden="true"> + <span class="previous-page"> + <span class="sr-only"><?= $this->translate('Previous page') ?></span> + <?= $this->icon('angle-double-left') ?> + </span> + </li> + <?php endif ?> + <?php foreach ($this->pagesInRange as $page): ?> + <?php if ($page === '...'): ?> + <li class="nav-item disabled"> + <span>...</span> + </li> + <?php else: ?> + <?php + $end = $page * $this->itemCountPerPage; + if ($end > $this->totalItemCount) { + $end = $this->totalItemCount; + } + $label = sprintf( + $this->translate('Show rows %u to %u of %u'), + ($page - 1) * $this->itemCountPerPage + 1, + $end, + $this->totalItemCount + ); + ?> + <li<?= $page === $this->current ? ' class="active nav-item"' : ' class="nav-item"' ?>> + <a href="<?= $this->escape($this->url()->overwriteParams(array('page' => $page))->getAbsoluteUrl()) ?>" + title="<?= $label ?>" + aria-label="<?= $label ?>"> + <?= $page ?> + </a> + </li> + <?php endif ?> + <?php endforeach ?> + <?php if (isset($this->next)): ?> + <?php $label = sprintf( + $this->translate('Show rows %u to %u of %u'), + $this->current * $this->itemCountPerPage + 1, + ($this->current + 1) * $this->itemCountPerPage, + $this->totalItemCount + ) ?> + <li class="nav-item"> + <a href="<?= $this->escape($this->url()->overwriteParams(array('page' => $this->next))->getAbsoluteUrl()) ?>" + title="<?= $label ?>" + aria-label="<?= $label ?>" + class="next-page"> + <?= $this->icon('angle-double-right') ?> + </a> + </li> + <?php else: ?> + <li class="disabled nav-item" aria-hidden="true"> + <span class="next-page"> + <span class="sr-only"><?= $this->translate('Next page') ?></span> + <?= $this->icon('angle-double-right') ?> + </span> + </li> + <?php endif ?> + </ul> +</div> diff --git a/application/views/scripts/navigation/dashboard.phtml b/application/views/scripts/navigation/dashboard.phtml new file mode 100644 index 0000000..f069882 --- /dev/null +++ b/application/views/scripts/navigation/dashboard.phtml @@ -0,0 +1,27 @@ +<?php + +use ipl\Web\Widget\Icon; + +?> +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?php foreach ($navigation as $item): /** @var \Icinga\Web\Navigation\NavigationItem $item */?> + <a class="dashboard-link" href="<?= $this->url($item->getUrl(), $item->getUrlParameters()) ?>"<?= $this->propertiesToString($item->getAttributes()) ?>> + <div class="link-icon"> + <?php + if (substr($item->getUrl()->getPath(), 0, 9) === 'icingadb/') { + echo new Icon($item->getIcon(), [ 'aria-hidden' => 1]); + } else { + echo $this->icon($item->getIcon() ?: 'forward', null, array('aria-hidden' => true)); + } + ?> + </div> + <div class="link-meta"> + <div class="link-label"><?= $this->escape($item->getLabel()) ?></div> + <div class="link-description"><?= $this->escape($item->getDescription() ?: sprintf('Open %s', strtolower($item->getLabel()))) ?></div> + </div> + </a> + <?php endforeach ?> +</div> diff --git a/application/views/scripts/navigation/index.phtml b/application/views/scripts/navigation/index.phtml new file mode 100644 index 0000000..bf08562 --- /dev/null +++ b/application/views/scripts/navigation/index.phtml @@ -0,0 +1,78 @@ +<?php if (! $this->compact): ?> +<div class="controls separated"> + <?= $this->tabs ?> + <div class="grid"> + <?= $this->sortBox ?> + </div> + <?= $this->filterEditor ?> +</div> +<?php endif ?> +<div class="content"> + <?= $this->qlink( + $this->translate('Create a New Navigation Item') , + 'navigation/add', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new navigation item') + ) + ) ?> +<?php if (count($items) === 0): ?> + <p><?= $this->translate('You did not create any navigation item yet.') ?></p> +</div> +<?php return; endif ?> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Navigation') ?></th> + <th><?= $this->translate('Type') ?></th> + <th><?= $this->translate('Shared') ?></th> + <th></th> + </tr> + </thead> + <tbody> +<?php foreach ($items as $item): ?> + <tr> + <td> + <?= $this->qlink( + $item->name, + 'navigation/edit', + array( + 'name' => $item->name, + 'type' => $item->type + ), + array( + 'title' => sprintf($this->translate('Edit navigation item %s'), $item->name) + ) + ) ?> + </td> + <td> + <?= $item->type && isset($types[$item->type]) + ? $this->escape($types[$item->type]) + : $this->escape($this->translate('Unknown')) ?> + </td> + <td class="icon-col"> + <?= $item->owner ? $this->translate('Yes') : $this->translate('No') ?> + </td> + <td class="icon-col text-right"> + <?= $this->qlink( + '', + 'navigation/remove', + array( + 'name' => $item->name, + 'type' => $item->type + ), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove navigation item %s'), $item->name) + ) + ) ?> + </td> + </tr> +<?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/navigation/shared.phtml b/application/views/scripts/navigation/shared.phtml new file mode 100644 index 0000000..b6739fb --- /dev/null +++ b/application/views/scripts/navigation/shared.phtml @@ -0,0 +1,68 @@ +<?php + +use Icinga\Web\Url; + +if (! $this->compact): ?> +<div class="controls"> + <?= $this->tabs; ?> + <div class="grid"> + <?= $this->sortBox ?> + </div> +</div> +<?php endif ?> +<div class="content" data-base-target="_next"> +<?php if (count($items) === 0): ?> + <p><?= $this->translate('There are currently no navigation items being shared'); ?></p> +<?php else: ?> + <table class="table-row-selectable common-table"> + <thead> + <th><?= $this->translate('Shared Navigation'); ?></th> + <th style="width: 10em"><?= $this->translate('Type'); ?></th> + <th style="width: 10em"><?= $this->translate('Owner'); ?></th> + <th style="width: 5em"><?= $this->translate('Unshare'); ?></th> + </thead> + <tbody> + <?php foreach ($items as $item): ?> + <tr> + <td><?= $this->qlink( + $item->name, + 'navigation/edit', + array( + 'name' => $item->name, + 'type' => $item->type, + 'owner' => $item->owner, + 'referrer' => 'shared' + ), + array( + 'title' => sprintf($this->translate('Edit shared navigation item %s'), $item->name) + ) + ); ?></td> + <td><?= $item->type && isset($types[$item->type]) + ? $this->escape($types[$item->type]) + : $this->escape($this->translate('Unknown')); ?></td> + <td><?= $this->escape($item->owner); ?></td> + <?php if ($item->parent): ?> + <td><?= $this->icon( + 'block', + sprintf( + $this->translate( + 'This is a child of the navigation item %1$s. You can' + . ' only unshare this item by unsharing %1$s' + ), + $item->parent + ) + ); ?></td> + <?php else: ?> + <td data-base-target="_self"><?= $removeForm + ->setDefault('name', $item->name) + ->setAction(Url::fromPath( + 'navigation/unshare', + array('type' => $item->type, 'owner' => $item->owner) + )); ?></td> + <?php endif ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +<?php endif ?> +</div> diff --git a/application/views/scripts/pivottablePagination.phtml b/application/views/scripts/pivottablePagination.phtml new file mode 100644 index 0000000..ce18014 --- /dev/null +++ b/application/views/scripts/pivottablePagination.phtml @@ -0,0 +1,48 @@ +<?php + +use Icinga\Web\Url; + +if ($xAxisPaginator->count() <= 1 && $yAxisPaginator->count() <= 1) { + return; // Display this pagination only if there are multiple pages +} + +$fromTo = t('%s: %d to %d of %d (on the %s-axis)'); +$xAxisPages = $xAxisPaginator->getPages('all'); +$yAxisPages = $yAxisPaginator->getPages('all'); + +?> + +<div class="pivot-pagination"> + <span><?= t('Navigation'); ?></span> + <table> + <tbody> +<?php foreach ($yAxisPages->pagesInRange as $yAxisPage): ?> + <tr> +<?php foreach ($xAxisPages->pagesInRange as $xAxisPage): ?> + <td<?= $xAxisPage === $xAxisPages->current && $yAxisPage === $yAxisPages->current ? ' class="active"' : ''; ?>> +<?php if ($xAxisPage !== $xAxisPages->current || $yAxisPage !== $yAxisPages->current): ?> + <a href="<?= Url::fromRequest()->overwriteParams( + array('page' => $xAxisPage . ',' . $yAxisPage) + )->getAbsoluteUrl(); ?>" title="<?= sprintf( + $fromTo, + t('Hosts'), + ($yAxisPage - 1) * $yAxisPages->itemCountPerPage + 1, + $yAxisPage === $yAxisPages->last ? $yAxisPages->totalItemCount : $yAxisPage * $yAxisPages->itemCountPerPage, + $yAxisPages->totalItemCount, + 'y' + ) . '; ' . sprintf( + $fromTo, + t('Services'), + ($xAxisPage - 1) * $xAxisPages->itemCountPerPage + 1, + $xAxisPage === $xAxisPages->last ? $xAxisPages->totalItemCount : $xAxisPage * $xAxisPages->itemCountPerPage, + $xAxisPages->totalItemCount, + 'x' + ); ?>"></a> +<?php endif ?> + </td> +<?php endforeach ?> + </tr> +<?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/role/list.phtml b/application/views/scripts/role/list.phtml new file mode 100644 index 0000000..352e3e2 --- /dev/null +++ b/application/views/scripts/role/list.phtml @@ -0,0 +1,65 @@ +<div class="controls separated"> + <?= $tabs ?> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + <?= $this->sortBox ?> + </div> + <?= $this->filterEditor ?> +</div> +<div class="content"> + <?= $this->qlink( + $this->translate('Create a New Role') , + 'role/add', + null, + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus', + 'title' => $this->translate('Create a new role') + ) + ) ?> +<?php /** @var \Icinga\Application\Config $roles */ if (! $roles->hasResult()): ?> + <p><?= $this->translate('No roles found.') ?></p> +<?php return; endif ?> + <table class="table-row-selectable common-table" data-base-target="_next"> + <thead> + <tr> + <th><?= $this->translate('Name') ?></th> + <th><?= $this->translate('Users') ?></th> + <th><?= $this->translate('Groups') ?></th> + <th><?= $this->translate('Inherits From') ?></th> + <th></th> + </tr> + </thead> + <tbody> +<?php foreach ($roles as $name => $role): /** @var object $role */ ?> + <tr> + <td> + <?= $this->qlink( + $name, + 'role/edit', + array('role' => $name), + array('title' => sprintf($this->translate('Edit role %s'), $name)) + ) ?> + </td> + <td><?= $this->escape($role->users) ?></td> + <td><?= $this->escape($role->groups) ?></td> + <td><?= $this->escape($role->parent) ?></td> + <td class="icon-col text-right"> + <?= $this->qlink( + '', + 'role/remove', + array('role' => $name), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove role %s'), $name) + ) + ) ?> + </td> + </tr> +<?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/search/hint.phtml b/application/views/scripts/search/hint.phtml new file mode 100644 index 0000000..d54c0b2 --- /dev/null +++ b/application/views/scripts/search/hint.phtml @@ -0,0 +1,8 @@ +<div class="content"> +<h1><?= $this->translate("I'm ready to search, waiting for your input") ?></h1> +<p><strong><?= $this->translate('Hint') ?>: </strong><?= $this->translate( + 'Please use the asterisk (*) as a placeholder for wildcard searches.' + . " For convenience I'll always add a wildcard in front and after your" + . ' search string.' +) ?></p> +</div> diff --git a/application/views/scripts/search/index.phtml b/application/views/scripts/search/index.phtml new file mode 100644 index 0000000..321597e --- /dev/null +++ b/application/views/scripts/search/index.phtml @@ -0,0 +1,7 @@ +<div class="controls"> +<?= $this->dashboard->getTabs() ?> +</div> + +<div class="content dashboard"> +<?= $this->dashboard ?> +</div> diff --git a/application/views/scripts/showConfiguration.phtml b/application/views/scripts/showConfiguration.phtml new file mode 100644 index 0000000..682b349 --- /dev/null +++ b/application/views/scripts/showConfiguration.phtml @@ -0,0 +1,27 @@ +<div> + <h4><?= $this->translate('Saving Configuration Failed'); ?></h4> + <p> + <?= sprintf( + $this->translate('The file %s couldn\'t be stored. (Error: "%s")'), + $this->escape($filePath), + $this->escape($errorMessage) + ); ?> + <br> + <?= $this->translate('This could have one or more of the following reasons:'); ?> + </p> + <ul> + <li><?= $this->translate('You don\'t have file-system permissions to write to the file'); ?></li> + <li><?= $this->translate('Something went wrong while writing the file'); ?></li> + <li><?= $this->translate('There\'s an application error preventing you from persisting the configuration'); ?></li> + </ul> +</div> +<p> + <?= $this->translate('Details can be found in the application log. (If you don\'t have access to this log, call your administrator in this case)'); ?> + <br> + <?= $this->translate('In case you can access the file by yourself, you can open it and insert the config manually:'); ?> +</p> +<p> + <pre> + <code><?= $this->escape($configString); ?></code> + </pre> +</p> diff --git a/application/views/scripts/simple-form.phtml b/application/views/scripts/simple-form.phtml new file mode 100644 index 0000000..9bcba74 --- /dev/null +++ b/application/views/scripts/simple-form.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs ?> +</div> +<div class="content"> + <?= $form->create()->setTitle(null) // @TODO(el): create() has to be called because the UserForm is setting the title there ?> +</div> diff --git a/application/views/scripts/user/form.phtml b/application/views/scripts/user/form.phtml new file mode 100644 index 0000000..cbf0659 --- /dev/null +++ b/application/views/scripts/user/form.phtml @@ -0,0 +1,6 @@ +<div class="controls"> + <?= $tabs->showOnlyCloseButton(); ?> +</div> +<div class="content"> + <?= $form; ?> +</div>
\ No newline at end of file diff --git a/application/views/scripts/user/list.phtml b/application/views/scripts/user/list.phtml new file mode 100644 index 0000000..bdb5f1a --- /dev/null +++ b/application/views/scripts/user/list.phtml @@ -0,0 +1,90 @@ +<?php + +use Icinga\Data\Extensible; +use Icinga\Data\Reducible; + +if (! $this->compact): ?> +<div class="controls separated"> + <?= $this->tabs ?> + <?= $this->paginator ?> + <div class="sort-controls-container"> + <?= $this->limiter ?> + <?= $this->sortBox ?> + </div> + <?= $this->backendSelection ?> + <?= $this->filterEditor ?> +</div> +<?php endif ?> +<div class="content"> +<?php + +if (! isset($backend)) { + echo $this->translate('No backend found which is able to list users') . '</div>'; + return; +} else { + $extensible = $this->hasPermission('config/access-control/users') && $backend instanceof Extensible; + $reducible = $this->hasPermission('config/access-control/users') && $backend instanceof Reducible; +} +?> + +<?php if ($extensible): ?> + <?= $this->qlink( + $this->translate('Add a New User') , + 'user/add', + array('backend' => $backend->getName()), + array( + 'class' => 'button-link', + 'data-base-target' => '_next', + 'icon' => 'plus' + ) + ) ?> +<?php endif ?> + +<?php if (! $users->hasResult()): ?> + <p><?= $this->translate('No users found matching the filter') ?></p> +</div> +<?php return; endif ?> + + <table data-base-target="_next" class="table-row-selectable common-table"> + <thead> + <tr> + <th><?= $this->translate('Username') ?></th> + <?php if ($reducible): ?> + <th><?= $this->translate('Remove') ?></th> + <?php endif ?> + </tr> + </thead> + <tbody> + <?php foreach ($users as $user): ?> + <tr> + <td><?= $this->qlink( + $user->user_name, + 'user/show', + array( + 'backend' => $backend->getName(), + 'user' => $user->user_name + ), + array( + 'title' => sprintf($this->translate('Show detailed information about %s'), $user->user_name) + ) + ) ?></td> + <?php if ($reducible): ?> + <td class="icon-col"><?= $this->qlink( + null, + 'user/remove', + array( + 'backend' => $backend->getName(), + 'user' => $user->user_name + ), + array( + 'class' => 'action-link', + 'icon' => 'cancel', + 'title' => sprintf($this->translate('Remove user %s'), $user->user_name) + ) + ) ?></td> + <?php endif ?> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> diff --git a/application/views/scripts/user/show.phtml b/application/views/scripts/user/show.phtml new file mode 100644 index 0000000..b19c15a --- /dev/null +++ b/application/views/scripts/user/show.phtml @@ -0,0 +1,138 @@ +<?php + +use Icinga\Data\Updatable; +use Icinga\Data\Reducible; +use Icinga\Data\Selectable; + +?> +<div class="controls separated"> +<?php if (! $this->compact): ?> + <?= $tabs; ?> +<?php endif ?> + <h2><?= $this->escape($user->user_name) ?></h2> + <?php + if ($this->hasPermission('config/access-control/users') && $backend instanceof Updatable) { + echo $this->qlink( + $this->translate('Edit User'), + 'user/edit', + array( + 'backend' => $backend->getName(), + 'user' => $user->user_name + ), + array( + 'class' => 'button-link', + 'icon' => 'edit', + 'title' => sprintf($this->translate('Edit user %s'), $user->user_name) + ) + ); + } + ?> + <table class="name-value-table"> + <tr> + <th><?= $this->translate('State'); ?></th> + <td><?= $user->is_active === null ? '-' : ($user->is_active ? $this->translate('Active') : $this->translate('Inactive')); ?></td> + </tr> + <tr> + <th><?= $this->translate('Created at'); ?></th> + <td><?= $user->created_at === null ? '-' : $this->formatDateTime($user->created_at); ?></td> + </tr> + <tr> + <th><?= $this->translate('Last modified'); ?></th> + <td><?= $user->last_modified === null ? '-' : $this->formatDateTime($user->last_modified); ?></td> + </tr> + <tr> + <th><?= $this->translate('Role Memberships'); ?></th> + <td> + <?php $roles = $userObj->getRoles(); ?> + <?php if (! empty($roles)): ?> + <ul class="role-memberships"> + <?php foreach($roles as $role): ?> + <li> + <?php if ($this->allowedToEditRoles): ?> + <?= $this->qlink( + $role->getName(), + 'role/edit', + ['role' => $role->getName()], + ['title' => sprintf($this->translate('Edit role %s'), $role->getName())] + ); + $role === end($roles) ? print '' : print ', '; ?> + <?php else: ?> + <?= $role->getName() ?> + <?php endif ?> + </li> + <?php endforeach ?> + </ul> + <?php else: ?> + <p><?= $this->translate('No memberships found'); ?></p> + <?php endif ?> + </td> + </tr> + </table> +<?php if (! $this->compact): ?> + <h2><?= $this->translate('Group Memberships'); ?></h2> + <div class="sort-controls-container"> + <?= $this->limiter; ?> + <?= $this->paginator; ?> + <?= $this->sortBox; ?> + </div> + <?= $this->filterEditor; ?> +<?php endif ?> +</div> +<div class="content"> +<?php if ($showCreateMembershipLink): ?> + <?= $this->qlink( + $this->translate('Create New Membership'), + 'user/createmembership', + array( + 'backend' => $backend->getName(), + 'user' => $user->user_name + ), + array( + 'icon' => 'plus', + 'class' => 'button-link' + ) + ) ?> +<?php endif ?> + +<?php if (! $memberships->hasResult()): ?> + <p><?= $this->translate('No memberships found matching the filter'); ?></p> +</div> +<?php return; endif ?> + + <table data-base-target="_next" class="table-row-selectable common-table"> + <thead> + <tr> + <th><?= $this->translate('Group'); ?></th> + <th><?= $this->translate('Cancel', 'group.membership'); ?></th> + </tr> + </thead> + <tbody> + <?php foreach ($memberships as $membership): ?> + <tr> + <td> + <?php if ($this->hasPermission('config/access-control/groups') && $membership->backend instanceof Selectable): ?> + <?= $this->qlink($membership->group_name, 'group/show', array( + 'backend' => $membership->backend->getName(), + 'group' => $membership->group_name + ), array( + 'title' => sprintf($this->translate('Show detailed information for group %s'), $membership->group_name) + )); ?> + <?php else: ?> + <?= $this->escape($membership->group_name); ?> + <?php endif ?> + </td> + <td class="icon-col" data-base-target="_self"> + <?php if (isset($removeForm) && $membership->backend instanceof Reducible): ?> + <?= $removeForm->setAction($this->url('group/removemember', array( + 'backend' => $membership->backend->getName(), + 'group' => $membership->group_name + ))); ?> + <?php else: ?> + - + <?php endif ?> + </td> + </tr> + <?php endforeach ?> + </tbody> + </table> +</div> |