Merge branch 'master' into feature/monitoring-restrictions-9009

This commit is contained in:
Johannes Meyer 2015-06-18 14:54:01 +02:00
commit 2bffe56bd5
25 changed files with 188 additions and 89 deletions

View File

@ -1 +1 @@
v2.0.0-beta3 v2.0.0-rc1

View File

@ -86,12 +86,8 @@ class ConfigController extends Controller
if ($this->firstAllowedAction === null) { if ($this->firstAllowedAction === null) {
throw new SecurityException($this->translate('No permission for application configuration')); throw new SecurityException($this->translate('No permission for application configuration'));
} }
$action = $this->getTabs()->get($this->firstAllowedAction);
if (substr($action->getUrl()->getPath(), 0, 7) === 'config/') { $this->redirectNow($this->getTabs()->get($this->firstAllowedAction)->getUrl());
$this->forward($this->firstAllowedAction);
} else {
$this->redirectNow($action->getUrl());
}
} }
/** /**

View File

@ -1,7 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Exception;
use Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
use Icinga\Forms\ConfirmRemovalForm; use Icinga\Forms\ConfirmRemovalForm;
use Icinga\Forms\Dashboard\DashletForm; use Icinga\Forms\Dashboard\DashletForm;

View File

@ -1,7 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Exception;
use Icinga\Application\Logger; use Icinga\Application\Logger;
use Icinga\Data\DataArray\ArrayDatasource; use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Data\Reducible; use Icinga\Data\Reducible;

View File

@ -1,7 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Exception;
use Icinga\Application\Logger; use Icinga\Application\Logger;
use Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use Icinga\Exception\NotFoundError; use Icinga\Exception\NotFoundError;

View File

@ -1,7 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Exception;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Exception\NotFoundError; use Icinga\Exception\NotFoundError;
use Icinga\Forms\ConfirmRemovalForm; use Icinga\Forms\ConfirmRemovalForm;

View File

@ -5,10 +5,7 @@ use Icinga\Web\Notification;
use Icinga\Authentication\Manager as Auth; use Icinga\Authentication\Manager as Auth;
if (Auth::getInstance()->isAuthenticated()): ?> if (Auth::getInstance()->isAuthenticated()):
<div id="header">
<ul id="notifications"><?php
$moduleName = $this->layout()->moduleName; $moduleName = $this->layout()->moduleName;
if ($moduleName) { if ($moduleName) {
$moduleClass = ' icinga-module module-' . $moduleName; $moduleClass = ' icinga-module module-' . $moduleName;
@ -20,14 +17,8 @@ $refresh = '';
if ($this->layout()->autorefreshInterval) { if ($this->layout()->autorefreshInterval) {
$refresh = ' data-icinga-refresh="' . $this->layout()->autorefreshInterval . '"'; $refresh = ' data-icinga-refresh="' . $this->layout()->autorefreshInterval . '"';
} }
?>
$notifications = Notification::getInstance(); <div id="header">
if ($notifications->hasMessages()) {
foreach ($notifications->getMessages() as $m) {
echo '<li class="' . $m->type . '">' . $this->escape($m->message) . '</li>';
}
}
?></ul>
<div id="logo" data-base-target="_main"> <div id="logo" data-base-target="_main">
<?= $this->qlink( <?= $this->qlink(
'', '',
@ -56,6 +47,16 @@ if ($notifications->hasMessages()) {
<div id="col3" class="container"> <div id="col3" class="container">
</div> </div>
</div><!-- END of main --> </div><!-- END of main -->
<div id="footer">
<ul id="notifications"><?php
$notifications = Notification::getInstance();
if ($notifications->hasMessages()) {
foreach ($notifications->getMessages() as $m) {
echo '<li class="' . $m->type . '">' . $this->escape($m->message) . '</li>';
}
}
?></ul>
</div>
<?php else: ?> <?php else: ?>
<?= $this->render('inline.phtml') ?> <?= $this->render('inline.phtml') ?>
<?php endif ?> <?php endif ?>

View File

@ -14,6 +14,7 @@ if (array_key_exists('_dev', $_GET)) {
$ie8jsfile = 'js/icinga.ie8.js'; $ie8jsfile = 'js/icinga.ie8.js';
$lang = Translator::splitLocaleCode()->language; $lang = Translator::splitLocaleCode()->language;
$isIframe = $this->layout()->isIframe; $isIframe = $this->layout()->isIframe;
$showFullscreen = $this->layout()->showFullscreen;
$iframeClass = $isIframe ? ' iframe' : ''; $iframeClass = $isIframe ? ' iframe' : '';
?><!DOCTYPE html> ?><!DOCTYPE html>
@ -49,7 +50,7 @@ $iframeClass = $isIframe ? ' iframe' : '';
</head> </head>
<body id="body"> <body id="body">
<pre id="responsive-debug"></pre> <pre id="responsive-debug"></pre>
<div id="layout" class="default-layout"> <div id="layout" class="default-layout<?php if ($showFullscreen): ?> fullscreen-layout<?php endif ?>">
<?= $this->render('body.phtml') ?> <?= $this->render('body.phtml') ?>
</div> </div>
<!--[if IE 8]> <!--[if IE 8]>

View File

@ -1,8 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Zend_View_Helper_FormElement;
/** /**
* Render number input controls * Render number input controls
*/ */

View File

@ -1,5 +1,7 @@
<div class="controls"> <div class="controls">
<?php if (! $this->compact): ?>
<?= $this->tabs ?> <?= $this->tabs ?>
<?php endif ?>
</div> </div>
<?php if ($this->dashboard): ?> <?php if ($this->dashboard): ?>
<div class="dashboard content"> <div class="dashboard content">

View File

@ -1,6 +1,6 @@
# Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ # Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+
%define revision 3.beta3 %define revision 4.rc1
Name: icingaweb2 Name: icingaweb2
Version: 2.0.0 Version: 2.0.0

View File

@ -156,7 +156,7 @@ class Query extends SimpleQuery
{ {
$result = $this->fetchAll(); $result = $this->fetchAll();
$sorted = array(); $sorted = array();
$quotedDn = preg_quote($this->connection->getDN(), '/'); $quotedDn = preg_quote($this->ds->getDN(), '/');
foreach ($result as $key => & $item) { foreach ($result as $key => & $item) {
$new_key = LdapUtils::implodeDN( $new_key = LdapUtils::implodeDN(
array_reverse( array_reverse(
@ -170,7 +170,7 @@ class Query extends SimpleQuery
unset($groups); unset($groups);
ksort($sorted); ksort($sorted);
$tree = Root::forConnection($this->connection); $tree = Root::forConnection($this->ds);
$root_dn = $tree->getDN(); $root_dn = $tree->getDN();
foreach ($sorted as $sort_key => & $key) { foreach ($sorted as $sort_key => & $key) {
if ($key === $root_dn) { if ($key === $root_dn) {

View File

@ -86,9 +86,13 @@ class ActionController extends Zend_Controller_Action
$this->handlerBrowserWindows(); $this->handlerBrowserWindows();
$this->view->translationDomain = 'icinga'; $this->view->translationDomain = 'icinga';
$this->_helper->layout()->isIframe = $request->getUrl()->shift('isIframe'); $this->_helper->layout()->isIframe = $request->getUrl()->shift('isIframe');
$this->_helper->layout()->showFullscreen = $request->getUrl()->shift('showFullscreen');
$this->_helper->layout()->moduleName = false; $this->_helper->layout()->moduleName = false;
$this->view->compact = $request->getParam('view') === 'compact'; $this->view->compact = $request->getParam('view') === 'compact';
if ($request->getUrl()->shift('showCompact')) {
$this->view->compact = true;
}
if ($this->rerenderLayout = $request->getUrl()->shift('renderLayout')) { if ($this->rerenderLayout = $request->getUrl()->shift('renderLayout')) {
$this->xhrLayout = 'body'; $this->xhrLayout = 'body';
} }

View File

@ -18,6 +18,7 @@ class StyleSheet
'css/icinga/layout-structure.less', 'css/icinga/layout-structure.less',
'css/icinga/menu.less', 'css/icinga/menu.less',
'css/icinga/header-elements.less', 'css/icinga/header-elements.less',
'css/icinga/footer-elements.less',
'css/icinga/main-content.less', 'css/icinga/main-content.less',
'css/icinga/tabs.less', 'css/icinga/tabs.less',
'css/icinga/forms.less', 'css/icinga/forms.less',

View File

@ -1,7 +1,6 @@
<?php <?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */ /* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
use \Zend_Controller_Router_Route;
use Icinga\Application\Icinga; use Icinga\Application\Icinga;
if (Icinga::app()->isCli()) { if (Icinga::app()->isCli()) {

View File

@ -20,6 +20,12 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
public function perfdata($perfdataStr, $compact = false, $limit = 0, $color = Perfdata::PERFDATA_OK) public function perfdata($perfdataStr, $compact = false, $limit = 0, $color = Perfdata::PERFDATA_OK)
{ {
$pieChartData = PerfdataSet::fromString($perfdataStr)->asArray(); $pieChartData = PerfdataSet::fromString($perfdataStr)->asArray();
uasort(
$pieChartData,
function($a, $b) {
return $a->worseThan($b) ? -1 : ($b->worseThan($a) ? 1 : 0);
}
);
$results = array(); $results = array();
$keys = array('', 'label', 'value', 'min', 'max', 'warn', 'crit'); $keys = array('', 'label', 'value', 'min', 'max', 'warn', 'crit');
$columns = array(); $columns = array();

View File

@ -12,6 +12,7 @@
'compact' => true, 'compact' => true,
'showHost' => false, 'showHost' => false,
'services' => $services, 'services' => $services,
'addColumns' => array() 'addColumns' => array(),
'baseTarget' => '_self'
) )
); ?> ); ?>

View File

@ -25,7 +25,7 @@ if (count($services) === 0) {
return; return;
} }
?> ?>
<table data-base-target="_next" <table data-base-target="<?= isset($baseTarget) ? $baseTarget : '_next'; ?>"
class="action multiselect <?php if ($this->compact): ?> compact<?php endif ?>" style="table-layout: auto;" class="action multiselect <?php if ($this->compact): ?> compact<?php endif ?>" style="table-layout: auto;"
data-icinga-multiselect-url="<?= $this->href("monitoring/services/show") ?>" data-icinga-multiselect-url="<?= $this->href("monitoring/services/show") ?>"
data-icinga-multiselect-data="service,host"> data-icinga-multiselect-data="service,host">
@ -60,7 +60,7 @@ if (count($services) === 0) {
</td> </td>
<td> <td>
<div class="sparkline-box"><?= $this->perfdata($service->service_perfdata, true, 8) ?> </div> <div class="sparkline-box"><?= $this->perfdata($service->service_perfdata, true, 5) ?> </div>
<?= $this->iconImage()->service($service) ?> <?= $this->iconImage()->service($service) ?>
<?= implode(' ', $this->serviceFlags($service)); ?> <?= implode(' ', $this->serviceFlags($service)); ?>
<?= $this->qlink( <?= $this->qlink(

View File

@ -7,6 +7,7 @@ use Icinga\Util\Format;
use InvalidArgumentException; use InvalidArgumentException;
use Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
use Icinga\Web\Widget\Chart\InlinePie; use Icinga\Web\Widget\Chart\InlinePie;
use Icinga\Module\Monitoring\Object\Service;
use Zend_Controller_Front; use Zend_Controller_Front;
class Perfdata class Perfdata
@ -453,4 +454,60 @@ class Perfdata
); );
return $parts; return $parts;
} }
/**
* Return the state indicated by this perfdata
*
* @see Service
*
* @return int
*/
public function getState()
{
if ($this->value === null) {
return Service::STATE_UNKNOWN;
}
if (! ($this->criticalThreshold === null
|| $this->value < $this->criticalThreshold)) {
return Service::STATE_CRITICAL;
}
if (! ($this->warningThreshold === null
|| $this->value < $this->warningThreshold)) {
return Service::STATE_WARNING;
}
return Service::STATE_OK;
}
/**
* Return whether the state indicated by this perfdata is worse than
* the state indicated by the other perfdata
* CRITICAL > UNKNOWN > WARNING > OK
*
* @param Perfdata $rhs the other perfdata
*
* @return bool
*/
public function worseThan(Perfdata $rhs)
{
if (($state = $this->getState()) === ($rhsState = $rhs->getState())) {
return $this->getPercentage() > $rhs->getPercentage();
}
if ($state === Service::STATE_CRITICAL) {
return true;
}
if ($state === Service::STATE_UNKNOWN) {
return $rhsState !== Service::STATE_CRITICAL;
}
if ($state === Service::STATE_WARNING) {
return $rhsState === Service::STATE_OK;
}
return false;
}
} }

View File

@ -0,0 +1,50 @@
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
div#footer {
position: fixed;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 9999;
}
/** Notifications **/
#notifications {
margin: 0;
padding: 0;
}
#notifications > li {
list-style-type: none;
display: block;
border-top: 1px solid #999;
color: white;
line-height: 2.5em;
padding-left: 3em;
background-repeat: no-repeat;
background-position: 1em center;
}
#notifications > li:hover {
cursor: pointer;
}
#notifications > li.info {
background-color: @colorFormNotificationInfo;
}
#notifications > li.warning {
background-color: @colorWarningHandled;
}
#notifications > li.error {
background-color: @colorCritical;
background-image: url(../img/icons/error_white.png);
}
#notifications > li.success {
background-color: #fe6;
background-image: url(../img/icons/success.png);
color: #333;
}
/** END of Notifications **/

View File

@ -81,13 +81,29 @@ html {
/** Fullscreen layout **/ /** Fullscreen layout **/
#layout.fullscreen-layout { #layout.fullscreen-layout {
#header, #sidebar, .controls > .tabs { #header, #sidebar {
display: none; display: none;
} }
.container .controls {
padding: 0;
}
.controls > ul.tabs {
margin-top: 0;
height: 1.5em;
background-color: @colorPetrol;
font-size: 0.75em;
padding: 0.2em 0 0;
}
.controls > ul.tabs > li > a {
line-height: 1.5em;
}
#main { #main {
left: 0; left: 0;
top: 0; top: 0 !important;
} }
} }

View File

@ -23,43 +23,6 @@ img.icon {
border: none; border: none;
} }
/** Notifications **/
#notifications {
margin: 0;
padding: 0;
}
#notifications > li {
list-style-type: none;
display: block;
border-bottom: 1px solid #999;
color: white;
line-height: 2.5em;
padding-left: 3em;
background-repeat: no-repeat;
background-position: 1em center;
}
#notifications > li.info {
background-color: @colorFormNotificationInfo;
}
#notifications > li.warning {
background-color: @colorWarningHandled;
}
#notifications > li.error {
background-color: @colorCritical;
background-image: url(../img/icons/error_white.png);
}
#notifications > li.success {
background-color: #fe6;
background-image: url(../img/icons/success.png);
color: #333;
}
/** END of Notifications **/
/* TODO: Remove once there is no more module container */ /* TODO: Remove once there is no more module container */
.container > div > pre { .container > div > pre {
margin: 1em; margin: 1em;

View File

@ -105,6 +105,9 @@
// We catch scroll events in our containers // We catch scroll events in our containers
$('.container').on('scroll', { self: this }, this.icinga.events.onContainerScroll); $('.container').on('scroll', { self: this }, this.icinga.events.onContainerScroll);
// Remove notifications on click
$(document).on('click', '#notifications li', function () { $(this).remove(); });
// We want to catch each link click // We want to catch each link click
$(document).on('click', 'a', { self: this }, this.linkClicked); $(document).on('click', 'a', { self: this }, this.linkClicked);
$(document).on('click', 'tr[href]', { self: this }, this.linkClicked); $(document).on('click', 'tr[href]', { self: this }, this.linkClicked);

View File

@ -706,7 +706,7 @@
}, },
initializeControls: function (parent) { initializeControls: function (parent) {
if ($(parent).closest('.dashboard').length) { if ($(parent).closest('.dashboard').length || $('#layout').hasClass('fullscreen-layout')) {
return; return;
} }
@ -736,14 +736,19 @@
fixControls: function ($parent) { fixControls: function ($parent) {
var self = this; var self = this;
if ($('#layout').hasClass('fullscreen-layout')) {
return;
}
if ('undefined' === typeof $parent) { if ('undefined' === typeof $parent) {
if (! $('#layout').hasClass('fullscreen-layout')) {
$('#header').css({height: 'auto'}); $('#header').css({height: 'auto'});
$('#main').css({top: $('#header').css('height')}); $('#main').css({top: $('#header').css('height')});
$('#sidebar').css({top: $('#header').height() + 'px'}); $('#sidebar').css({top: $('#header').height() + 'px'});
$('#header').css({height: $('#header').height() + 'px'}); $('#header').css({height: $('#header').height() + 'px'});
$('#inner-layout').css({top: $('#header').css('height')}); $('#inner-layout').css({top: $('#header').css('height')});
}
$('.container').each(function (idx, container) { $('.container').each(function (idx, container) {
self.fixControls($(container)); self.fixControls($(container));
}); });