Merge branch 'feature/fanzzzy-5481' into feature/master-1

Conflicts:
	application/controllers/AuthenticationController.php
	application/controllers/ErrorController.php
	application/views/scripts/authentication/login.phtml
	library/Icinga/Application/ApplicationBootstrap.php
	library/Icinga/Web/Controller/ActionController.php
	library/Icinga/Web/Hook.php
	library/Icinga/Web/Widget/Dashboard.php
This commit is contained in:
Thomas Gelf 2014-03-04 09:42:25 +00:00
commit 57caacb93f
198 changed files with 7610 additions and 13430 deletions

View File

@ -142,8 +142,9 @@ copy-web-files-%:
#
# Create release or snapshot tarball
#
create-tarball:
@./bin/make-tarball --prefix $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)/
create-tarball-nightly:
./bin/make-tarball --prefix $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-`date +%Y%m%d`-`git rev-parse --short HEAD`/
# TODO: Use git-archive
# create-tarball:
# @./bin/make-tarball --prefix $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)/
#
# create-tarball-nightly:
# ./bin/make-tarball --prefix $(PACKAGE_TARNAME)-$(PACKAGE_VERSION)-`date +%Y%m%d`-`git rev-parse --short HEAD`/

View File

@ -56,7 +56,6 @@ class AuthenticationController extends ActionController
*/
public function loginAction()
{
$this->_helper->layout->setLayout('login');
$this->view->form = new LoginForm();
$this->view->form->setRequest($this->_request);
$this->view->title = 'Icinga Web Login';

View File

@ -112,6 +112,7 @@ class ConfigController extends BaseConfigController
public function indexAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('index');
$form = new GeneralForm();
//$form->setConfiguration(IcingaConfig::app());
$form->setRequest($this->_request);
@ -132,6 +133,7 @@ class ConfigController extends BaseConfigController
public function loggingAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('logging');
$form = new LoggingForm();
$form->setConfiguration(IcingaConfig::app());
@ -153,6 +155,7 @@ class ConfigController extends BaseConfigController
public function moduleoverviewAction()
{
$this->view->messageBox = new AlertMessageBox(true);
$this->view->tabs->activate('modules');
$this->view->modules = Icinga::app()->getModuleManager()->select()
->from('modules')
@ -207,6 +210,8 @@ class ConfigController extends BaseConfigController
public function authenticationAction($showOnly = false)
{
$config = IcingaConfig::app('authentication', true);
$this->view->tabs->activate('authentication');
$order = array_keys($config->toArray());
$this->view->backends = array();
$this->view->messageBox = new AlertMessageBox(true);
@ -382,6 +387,8 @@ class ConfigController extends BaseConfigController
public function resourceAction($showOnly = false)
{
$this->view->tabs->activate('resources');
$this->view->messageBox = new AlertMessageBox(true);
$this->view->resources = IcingaConfig::app('resources', true)->toArray();
$this->render('resource');

View File

@ -130,8 +130,7 @@ class DashboardController extends ActionController
$this->view->tabs->add(
'Add',
array(
'title' => 'Add Url',
'iconCls' => 'plus',
'title' => '+',
'url' => Url::fromPath('dashboard/addurl')
)
);

View File

@ -0,0 +1,42 @@
<?php
/**
* Icinga (http://www.icinga.org)
*
* @copyright 2014 Icinga Development Team <info@icinga.org>
* @license http://www.icinga.org/license/gpl2 GPL, version 2
*/
use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga;
use Icinga\Web\Widget;
use Icinga\Web\Url;
/**
* Search controller
*/
class SearchController extends ActionController
{
public function indexAction()
{
$search = $this->_request->getParam('q');
$dashboard = Widget::create('dashboard')->createPane('Search');
$pane = $dashboard->getPane('Search');
$pane->addComponent('Hosts', Url::fromPath('monitoring/list/hosts', array(
'host_name' => $search . '*',
'sort' => 'host_severity',
'limit' => 10,
)));
$pane->addComponent('Services', Url::fromPath('monitoring/list/services', array(
'service_description' => '*' . $search . '*',
'sort' => 'service_severity',
'limit' => 10,
)));
$pane->addComponent('Hostgroups', Url::fromPath('monitoring/list/hostgroups', array(
'hostgroup' => '*' . $search . '*',
'limit' => 10,
)));
$dashboard->activate('Search');
$this->view->dashboard = $dashboard;
$this->view->tabs = $dashboard->getTabs();
}
}

View File

@ -54,6 +54,13 @@ class StaticController extends ActionController
$this->_helper->layout()->disableLayout();
}
public function gravatarAction()
{
$img = file_get_contents('http://www.gravatar.com/avatar/' . md5(strtolower(trim($this->_request->getParam('email')))) . '?s=200&d=mm');
header('image/jpeg');
echo $img;
}
/**
* Return an image from the application's or the module's public folder
*/

View File

@ -52,21 +52,23 @@ class LoginForm extends Form
'text',
'username',
array(
'label' => t('Username'),
'required' => true
'required' => true,
'placeholder' => t('Username'),
'class' => 'autofocus'
)
);
$this->addElement(
'password',
'password',
array(
'label' => t('Password'),
'placeholder' => t('Password'),
'required' => true
)
);
$this->setSubmitLabel('Login');
$this->setSubmitLabel('Login');
}
}

View File

@ -1,28 +1,42 @@
<?= $this->action('topbar', 'layout'); ?>
<div class="row">
<!-- Only required for left/right tabs -->
<div class="col-sm-12 col-xs-12 col-md-2 col-lg-2">
<?= $this->partial('layout/menu.phtml', 'default', array(
'url' => \Icinga\Web\Url::fromRequest()->getRelativeUrl(),
'items' => \Icinga\Web\Menu::fromConfig()->getChildren(),
'sub' => false
)); ?>
</div>
<div class="col-sm-12 col-xs-12 col-md-10 col-lg-10">
<?= $this->mainDetail($this->render('inline.phtml'), $this->layout()->detailContent); ?>
</div>
<?php if (Icinga\Authentication\Manager::getInstance()->isAuthenticated()): ?>
<div id="layout">
<div id="header">
<ul id="notifications"></ul>
<div id="logo"><a href="<?= $this->href('/dashboard') ?>"><img src="<?= $this->href('img/logo_icinga-inv.png') ?>" class="logo" /></a>
</div>
<br/>
<div class="row">
<div class="col-md-12">
<!-- Make some space at the end of the page -->
<div class="panel">
<div class="panel-body text-center">
Icinga Web 2 &copy; 2014 Icinga Team
</div>
</div>
</div>
<!--
<ul class="tabs" >
<li class="dropdown">
<a href="#" class="dropdown-toggle">
<?= $this->img('icons/user.png') ?>
<?= $this->escape($this->auth()->getUser()->getUsername()) ?>
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="<?= $this->href('/preference') ?>"><?= $this->translate('Preferences'); ?></a></li>
<li><a href="<?= $this->href('/authentication/logout'); ?>" title="Logout"><?= $this->translate('Logout'); ?></a></li>
</ul>
</li>
</ul>
-->
<div id="sidebar">
<?= $this->layout()->navigation ?>
<?php echo $this->render('parts/navigation.phtml') ?>
</div>
<div id="main">
<div id="col1" class="container">
<?= $this->render('inline.phtml') ?>
</div>
</div>
<div id="col2" class="container">
<ul class="tabs"></ul>
</div>
<div id="col3" class="container">
</div>
</div><!-- END of main -->
</div><!-- END of layout -->
<?php else: ?>
<?= $this->render('inline.phtml') ?>
<?php endif ?>

View File

@ -1,2 +1,4 @@
<?= $this->layout()->moduleStart ?>
<?= $this->layout()->content ?>
<?= $this->layout()->benchmark ?>
<?= $this->layout()->moduleEnd ?>

View File

@ -1,4 +1,20 @@
<!DOCTYPE html>
<?php
$jsfiles = array(
'js/vendor/jquery-1.8.3.js',
'js/vendor/jquery.sparkline.min.js',
'js/helpers.js',
'js/icinga.js',
'js/icinga/logger.js',
'js/icinga/utils.js',
'js/icinga/ui.js',
'js/icinga/timer.js',
'js/icinga/loader.js',
'js/icinga/events.js',
'js/icinga/module.js',
);
?><!DOCTYPE html>
<!--[if lt IE 7]>
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>
@ -11,35 +27,28 @@
<meta charset="utf-8">
<meta content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><?= $this->title ? $this->title : 'Icinga Web'; ?></title>
<title><?= $this->title ? $this->escape($this->title) : 'Icinga Web'; ?></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- Bootstrap and components -->
<link rel="stylesheet" href="<?= $this->baseUrl('static/stylesheet') ?>" media="screen">
<script type="text/javascript">
var base_url = '<?= $this->baseUrl() ?>';
var request_id = '<?= $this->requestId(); ?>';
ICINGA_DEBUG = true;
</script>
<link rel="stylesheet" href="<?= $this->href('css/icinga.css') ?>" media="screen" type="text/css" />
<? if (isset($_GET['iframe']) && $_GET['iframe'] === 'true'): ?>
<base target="_parent"/>
<? endif ?>
<script src="<?= $this->baseUrl('js/vendor/modernizr-2.6.2.min.js') ?>"></script>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- Respond.js IE8 support of media queries -->
<!--[if lt IE 9]>
<script src="<?= $this->baseUrl('js/vendor/html5shiv.js');?>"></script>
<script src="<?= $this->baseUrl('js/vendor/respond.min.js');?>"></script>
<![endif]-->
</head>
<body>
<?= $this->render('body.phtml') ?>
<script data-main="<?php echo $this->baseUrl('js/main.js')?>"
src="<?php echo $this->baseUrl('js/vendor/require.js') ?>"></script>
<body id="body">
<?= $this->render('body.phtml') ?>
<?php foreach ($jsfiles as $file): ?>
<script type="text/javascript" src="<?= $this->href($file) ?>"></script>
<?php endforeach ?>
<script type="text/javascript">
var icinga = new Icinga({
baseUrl: '<?= $this->href('/') ?>',
});
</script>
</body>
</html>

View File

@ -1,55 +0,0 @@
<!DOCTYPE html>
<!--[if lt IE 7]>
<html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>
<html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>
<html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title><?= $this->title ? $this->title : 'Icinga Web'; ?></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!-- Bootstrap and components -->
<link rel="stylesheet" href="<?= $this->baseUrl('static/stylesheet') ?>" media="screen">
<? if (isset($_GET['iframe']) && $_GET['iframe'] === 'true'): ?>
<base target="_parent"/>
<? endif ?>
<script src="<?= $this->baseUrl('js/vendor/modernizr-2.6.2.min.js') ?>"></script>
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="<?= $this->baseUrl('js/vendor/html5shiv.js');?>"></script>
<script src="<?= $this->baseUrl('js/vendor/respond.min.js');?>"></script>
<![endif]-->
</head>
<body class="login">
<div class="logo-container">
<div class="image-container">
<div class="hidden-xs">
<img src="<?= $this->baseUrl('img/logo_icinga_big.png') ?>" width="400px">
</div>
<div class="hidden-sm hidden-lg hidden-md">
<img src="<?= $this->baseUrl('img/logo_icinga_big.png') ?>" width="200px">
</div>
</div>
</div>
<div class="form-container">
<?= $this->layout()->content; ?>
<div class="footer">
<br/>
Icinga Web 2 &copy; 2013 Icinga Team
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,28 @@
<ul>
<?php
foreach ($this->items as $item) {
printf(
' <li%s><a href="%s">%s%s</a>',
$this->href($this->url) === $this->href($item->getUrl()) ? ' class="active"' : '',
$item->getUrl() ? $this->href($item->getUrl()) : '#',
$item->getIcon() ? $this->img(
$item->getIcon(),
array('height' => '16px', 'width' => '16px')
) . ' ' : '',
$this->escape($item->getTitle())
);
if ($item->hasChildren()) {
echo $this->partial(
'parts/menu.phtml',
array('items' => $item->getChildren(), 'url' => $this->url)
);
}
echo "</li>\n";
}
?>
</ul>

View File

@ -1,13 +1,20 @@
<?php
if ($this->auth()->isAuthenticated()) {
echo $this->partial(
'parts/menu.phtml',
array(
'items' => $menu->getChildren(),
'url' => $url
)
);
// Don't render a menu for unauthenticated users unless menu is auth aware
if (! $this->auth()->isAuthenticated()) {
return;
}
// Current url
$url = Icinga\Web\Url::fromRequest()->getRelativeUrl();
$menu = Icinga\Web\Menu::fromConfig();
?>
<div id="menu">
<form action="<?= $this->href('search') ?>" method="post"><input type="text" name="q" class="search" placeholder="Search..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /></form>
<?= $this->partial('parts/menu.phtml', array(
'items' => $menu->getChildren(),
'url' => $url
))
?>
</div>

View File

@ -29,6 +29,8 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Util\Format;
/**
* Class Zend_View_Helper_TimeSince
*/
@ -36,42 +38,9 @@ class Zend_View_Helper_TimeSince extends Zend_View_Helper_Abstract
{
public function timeSince($timestamp)
{
if (!is_numeric($timestamp)) {
$timestamp = strtotime($timestamp);
}
if (!is_numeric($timestamp)) {
return '?';
}
if (! $timestamp) return '-';
$duration = time() - $timestamp;
$prefix = '';
if ($duration < 0) {
$prefix = '-';
$duration *= -1;
}
if ($duration > 3600 * 24 * 3) {
if (date('Y') === date('Y', $timestamp)) {
return date('d.m.', $timestamp);
}
return date('m.Y', $timestamp);
}
return $prefix . $this->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';
return '<span class="timesince">'
. Format::timeSince($timestamp)
. '</span>';
}
}

View File

@ -1,5 +1,6 @@
#!/usr/bin/php
<?php
// @codingStandardsIgnoreStart
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
@ -28,17 +29,18 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
set_include_path(
realpath(dirname(__FILE__) . '/../library/')
. ':'
. get_include_path()
);
require_once 'Icinga/Application/Cli.php';
use Icinga\Application\Cli;
use Icinga\Util\Format;
$app = Cli::start();
echo Format::bytes(10930423) . "\n";
/**
* Class Zend_View_Helper_TimeSince
*/
class Zend_View_Helper_TimeUnless extends Zend_View_Helper_Abstract
{
public function timeUnless($timestamp)
{
return '<span class="timeunless">'
. Format::timeUntil($timestamp)
. '</span>';
}
}
// @codingStandardsIgnoreStop

View File

@ -1,29 +1,21 @@
<?php if (isset($this->errorInfo)): ?>
<div class="row">
<br/>
<div class="md-offset-2 col-md-8 col-sm-8 col-sm-offset-2">
<div class="alert alert-danger">
<?= $this->errorInfo ?>
</div>
</div>
<div class="layout fullscreen login">
<div class="main">
<div class="logo">
<div class="image">
<img src="<?= $this->baseUrl('img/logo_icinga_big.png') ?>" >
</div>
</div>
<?php endif ?>
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3">
<div class="container">
<?= $this->form; ?>
</div>
<div class="form">
<h1>Icinga Users Login</h1>
<?php
/* TODO: remove this as soon as notifications and forms are ready */
if (isset($this->errorInfo)): ?>
<div class="error">
<?= $this->errorInfo ?>
</div>
<?php endif ?>
<?= $this->form ?>
<div class="footer">Icinga Web 2 &copy; 2013-2014 Icinga Team</div>
</div>
<script type="text/javascript">
/*
* Preserve the html anchor when redirecting to the originally called link. This
* is useful for preserving the detail view and the selection in that case.
*
* refs #4833
*/
var url = document.URL.match(/(^[^#]*)/)[0] + encodeURIComponent(window.location.hash);
document.getElementById('form_login').action = url;
</script>
</div>
</div>

View File

@ -3,9 +3,11 @@ use Icinga\Web\Url;
$createLdapBackend = $this->href('/config/createAuthenticationBackend', array('type' => 'ldap'));
$createDbBackend = $this->href('/config/createAuthenticationBackend', array('type' => 'db'));
?>
<div class="controls">
<?= $this->tabs->render($this); ?>
</div>
<div class="content">
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
@ -40,4 +42,5 @@ $createDbBackend = $this->href('/config/createAuthenticationBackend', array('typ
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>

View File

@ -1,7 +1,11 @@
<div class="controls">
<?= $this->tabs->render($this); ?>
</div>
<div class="content">
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
<?= $this->form ?>
<?= $this->form ?>
</div>

View File

@ -1,5 +1,8 @@
<div class="controls">
<?= $this->tabs->render($this); ?>
</div>
<div class="content">
<?php $errors = $this->form->getErrorMessages(); ?>
<?php if (isset($this->messageBox)): ?>
@ -27,4 +30,6 @@
</div>
<?php endif; ?>
<?= $this->form ?>
<?= $this->form ?>
</div>

View File

@ -5,8 +5,11 @@ $this->modules->limit(10);
$modules = $this->modules->paginate();
?>
<div class="controls">
<?= $this->tabs->render($this); ?>
</div>
<div class="content">
<h3>Installed Modules</h3>
<?php if (isset($this->messageBox)): ?>
@ -17,7 +20,7 @@ $modules = $this->modules->paginate();
'preserve' => $this->preserve
));
?>
<table class="table">
<table class="action">
<tbody>
<? foreach ($modules as $module): ?>
<?php
@ -40,3 +43,4 @@ $modules = $this->modules->paginate();
<? endforeach ?>
</tbody>
</table>
</div>

View File

@ -2,8 +2,11 @@
use Icinga\Web\Url;
$createResource = $this->href('/config/createresource');
?>
<div class="controls">
<?= $this->tabs->render($this); ?>
</div>
<div class="content">
<?php if (isset($this->messageBox)): ?>
<?= $this->messageBox->render() ?>
<?php endif ?>
@ -41,4 +44,6 @@ $createResource = $this->href('/config/createresource');
</div>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>

View File

@ -1,5 +1,6 @@
<?= $this->tabs->render($this); ?>
<div class="dashboard" data-columns>
<?= $this->dashboard->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
</div>
<div class="dashboard content">
<?= $this->dashboard ?>
</div>

View File

@ -1,7 +1,4 @@
<?= $this->tabs->render($this); ?>
<div class="alert alert-danger">
<p><?= $message ?></p>
</div>
<h1 class="alert alert-danger"><?= $message ?></h1>
<?php if (isset($stackTrace)) : ?>
<hr />
<pre><?= $stackTrace ?></pre>

View File

@ -1,8 +1,17 @@
<?php
use Icinga\Web\Url;
// Please note that there is a reason for the strange way of writing ><.
// It was the best compromise that came to my mind to get rid of whitespaces
// between inline-block elements. Found no better hack - and table-cell seems
// to be less supported.
if ($this->pageCount <= 1) return;
?><ul class="pagination"
<?php
$fromto = $this->translate('%d to %d of %d');
$total = $this->totalItemCount;
$limit = $this->itemCountPerPage;
@ -19,25 +28,27 @@ $title_next = sprintf(
($this->current + 1) * $limit,
$total
);
$li = ' ><li%s><a href="%s" title="%s">%s</a></li
';
?>
<ul class="pagination">
<!-- Previous page link -->
<?php if (isset($this->previous)): ?>
<li>
<a href="<?= Url::fromRequest()->overwriteParams(array('page' => $this->previous))->getAbsoluteUrl() ?>"
title="<?= $title_prev ?>">« <?= $this->translate('Prev') ?>
</a>
</li>
<?php else: ?>
<li class="disabled"><span>« <?= $this->translate('Prev') ?></span></li>
<?php endif ?>
<!-- Numbered page links -->
<?php
foreach ($this->pagesInRange as $page):
if (isset($this->previous)) {
printf(
$li,
'',
Url::fromRequest()->overwriteParams(
array('page' => $this->previous)
)->getAbsoluteUrl(),
$title_prev,
'« ' . $this->translate('Prev')
);
} else {
echo ' ><li class="disabled"><span>« ' . $this->translate('Prev') . '</span></li';
}
foreach ($this->pagesInRange as $page) {
$start = ($page - 1) * $limit + 1;
$end = $page * $limit;
if ($end > $total) {
@ -46,26 +57,34 @@ foreach ($this->pagesInRange as $page):
$title = sprintf($fromto, $start, $end, $total);
$class = $page === $this->current ? ' class="active"' : '';
if ($page === '...'): ?>
<li class="disabled"><span>...</span></li>
<?php else: ?>
<li <?= $class ?>>
<a href="<?= Url::fromRequest()->overwriteParams(array('page' => $page))->getAbsoluteUrl() ?>" title="<?= $title ?>">
<?= $page ?>
</a>
</li>
<?php
endif;
endforeach;
if ($page === '...') {
echo ' ><li class="disabled"><span>...</span></li';
} else {
printf(
$li,
$class,
Url::fromRequest()->overwriteParams(
array('page' => $page)
)->getAbsoluteUrl(),
$title,
$page
);
}
}
if (isset($this->next)) {
printf(
$li,
'',
Url::fromRequest()->overwriteParams(
array('page' => $this->next)
)->getAbsoluteUrl(),
$title_next,
$this->translate('Next') . ' »'
);
} else {
echo ' ><li class="disabled"><span>' . $this->translate('Next') . ' »</span></li';
}
?>
<!-- Next page link -->
<? if (isset($this->next)): ?>
<li>
<a href="<?= Url::fromRequest()->overwriteParams(array('page' => $this->next))->getAbsoluteUrl() ?>"
title="<?= $title_next ?>"><?= t('Next') ?> »
</a>
</li>
<? else: ?>
<li class="disabled"><span><?= t('Next') ?> »</span></li>
<? endif ?>
</ul>
></ul>

View File

@ -0,0 +1,7 @@
<div class="controls">
<?= $this->tabs ?>
</div>
<div class="content dashboard">
<?= $this->dashboard ?>
</div>

View File

@ -1,183 +0,0 @@
#!/usr/bin/python
import sys
import os
import fnmatch
from time import gmtime,strftime
#
# Helper script to create test templates from application code
#
pattern="*.php"
TESTDIR_NAME="tests"
def mkdirs_graceful(testtarget):
dirtree = []
curdir = os.path.dirname(testtarget)
while not os.path.exists(curdir):
dirtree.insert(0,curdir)
curdir = os.path.dirname(curdir)
for i in dirtree:
os.mkdir(i)
class TestClassFile(object):
def __init__(self):
self.namespace = ""
self.uses = []
self.in_class = False
self.is_abstract = False
self.classname = ""
self.test_methods = []
self.test_static_methods = []
def write_test_class(self,filed):
lines = []
lines.append("<?php\n")
lines.append("\n")
if self.namespace:
lines.append("namespace %s\n" % self.namespace)
lines.append("/**\n")
lines.append("*\n")
lines.append("* Test class for %s \n" % self.classname.title())
lines.append("* Created %s \n" % strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()))
lines.append("*\n")
lines.append("**/\n")
lines.append("class %s extends \PHPUnit_Framework_TestCase\n" % (self.classname.title()+"Test"))
lines.append("{\n\n")
if not self.is_abstract:
for method in self.test_methods:
self.write_testmethod(lines,method)
for method in self.test_static_methods:
self.write_testmethod(lines,method,True)
lines.append("}\n")
filed.writelines(lines)
def write_testmethod(self,lines,method,static=False):
if method == "__construct":
return
method = method[0].upper()+method[1:]
lines.append(" /**\n")
lines.append(" * Test for %s::%s() \n" % (self.classname,method))
if static:
lines.append(" * Note: This method is static! \n" )
lines.append(" *\n")
lines.append(" **/\n")
lines.append(" public function test%s()\n" % method)
lines.append(" {\n")
lines.append(" $this->markTestIncomplete('test%s is not implemented yet');\n" % method)
lines.append(" }\n\n")
def get_test_definition(filename):
file_hdl = open(filename,"r")
t = TestClassFile()
ignorenext = False
for line in file_hdl:
line = line.strip()
if "@dont_test" in line:
ignorenext = True
continue
if line.startswith("namespace") and not t.in_class:
t.namespace = "Tests\\"+line[len("namespace"):].strip()
continue
if line.startswith("use") and not t.in_class:
t.uses.append(line[len("uses"):].strip())
continue
if line.startswith("abstract class") and not t.in_class:
if ignorenext:
ignorenext = False
continue
t.in_class = True
t.is_abstract = True
t.classname = line[len("abstract class"):].strip().split(" ")[0]
continue
if line.startswith("class") and not t.in_class:
if ignorenext:
ignorenext = False
continue
t.in_class = True
t.is_abstract = False
t.classname = line[len("class"):].strip().split(" ")[0]
continue
if t.in_class and line.startswith("public"):
tokens = line.split(" ")
if not "function" in tokens:
continue
is_static = "static" in tokens
if ignorenext:
ignorenext = False
continue
lasttoken = ""
for token in tokens:
method = None
if token.startswith("("):
method = lasttoken
else:
if "(" in token:
method = token.partition("(")[0]
if method:
if is_static:
t.test_static_methods.append(method)
else:
t.test_methods.append(method)
break
return t
if len(sys.argv) < 2:
print "Usage: %s file_or_dir [pattern]\nPattern is %s by default\n" % (sys.argv[0],pattern)
sys.exit(1)
bpath = os.path.abspath(sys.argv[1])
if not os.path.exists(bpath):
print "Path %s could not be found or read!" % bpath
sys.exit(1)
if len(sys.argv) > 2:
pattern = sys.argv[2]
base="."
while not os.path.exists("%s/%s" % (base,TESTDIR_NAME)):
if os.path.abspath("%s" % (base)) == "/":
print "Can't find %s directory in this folder or any of it's parents" % TESTDIR_NAME
sys.exit(1)
else:
base = "../%s" % base
testdir = os.path.abspath("%s/%s" % (base,TESTDIR_NAME))
print "Found testdir under %s" % os.path.abspath("%s/%s" % (base,TESTDIR_NAME))
prefix = os.path.commonprefix((bpath,testdir))
if prefix == "/":
print "Test and source dir should be in the same prefix!"
exit(1)
filelist = []
for root,dirs,files in os.walk(bpath):
filtered = [i for i in files if fnmatch.fnmatch(i,pattern)]
if not filtered:
continue
filelist += ["%s/%s" % (root,i) for i in filtered]
for filename in filelist:
test = get_test_definition(filename)
if not test.in_class:
print "Omitting %s, no class found" % filename
continue
if not test.test_static_methods and (test.is_abstract or not test.test_methods):
print "Omitting %s, no public methods to test" % filename
continue
filename,ext = os.path.splitext(filename)
testtarget = "%s/%sTest%s" % (testdir,filename[len(prefix):],ext)
if os.path.exists(testtarget):
print "Omitting %s as there already exists a test for it" % testtarget
continue
print "Creating %s" % testtarget
mkdirs_graceful(testtarget)
test.write_test_class(open(testtarget,"w"))

View File

@ -1,64 +0,0 @@
#!/bin/sh
# {{{ICINGA_LICENSE_HEADER}}}
# Icinga Web 2 - Head for multiple monitoring frontends
# Copyright (C) %(YEAR)s Icinga Development Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# @copyright 2013 Icinga Development Team <info@icinga.org>
# @author Icinga Development Team <info@icinga.org>
# {{{ICINGA_LICENSE_HEADER}}}
set -o nounset
DIR=$(readlink -f $(dirname $0)/../)
BIN=$(basename $0)
PHPDOC=$(which phpdoc)
CONFIG=$DIR/doc/phpdoc.xml
OUTPUT=$DIR/doc/api
ARG=${1-}
BUILD=""
cd $DIR
if [ ! -x $PHPDOC ]; then
echo "phpDocumentor not found (phpdoc)"
echo "Please read http://phpdoc.org/docs/latest/for-users/installation.html how to install"
exit 1
fi
if [ -d $OUTPUT ]; then
echo "Output directory exists"
echo "rm -rf $OUTPUT"
rm -rf $OUTPUT
fi
if [ "$ARG" == "--build" ]; then
BUILD="-q"
fi
if [ "$ARG" == "--help" ]; then
echo "Usage $BIN [ --build ]"
echo ""
echo "Options:"
echo " --build Silent output"
echo " --help Print this screen"
echo ""
exit 1
fi
$PHPDOC $BUILD -c $CONFIG
exit $?

View File

@ -1,34 +0,0 @@
#!/bin/sh
# {{{ICINGA_LICENSE_HEADER}}}
# Icinga Web 2 - Head for multiple monitoring frontends
# Copyright (C) %(YEAR)s Icinga Development Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# @copyright 2013 Icinga Development Team <info@icinga.org>
# @author Icinga Development Team <info@icinga.org>
# {{{ICINGA_LICENSE_HEADER}}}
set -o nounset
SCRIPTNAME=$(readlink -f $0)
DIR=$(dirname $SCRIPTNAME)
for filepath in `find $DIR/../doc -type f -name "*.md"`; do
markdown $filepath > `dirname $filepath`/`basename $filepath .md`.html
done
exit 0

View File

@ -1,198 +0,0 @@
#!/bin/sh -
#
# File: make-tarball
#
# Description: A utility script that builds an archive file(s) of all
# git repositories and submodules in the current path.
# Useful for creating a single tarfile of a git super-
# project that contains other submodules.
# Derived from git-archive-all.sh, modified for Icinga
# DEBUGGING
set -e
set -C # noclobber
# TRAP SIGNALS
trap 'cleanup' QUIT EXIT
# For security reasons, explicitly set the internal field separator
# to newline, space, tab
OLD_IFS=$IFS
IFS='
'
cleanup () {
rm -f $TMPFILE
rm -f $TOARCHIVE
IFS="$OLD_IFS"
}
usage () {
echo "Usage is as follows:"
echo
echo "$PROGRAM <--version>"
echo " Prints the program version number on a line by itself and exits."
echo
echo "$PROGRAM <--usage|--help|-?>"
echo " Prints this usage output and exits."
echo
echo "$PROGRAM [--format <fmt>] [--prefix <path>] [--separate|-s] [output_file]"
echo " Creates an archive for the entire git superproject, and its submodules"
echo " using the passed parameters, described below."
echo
echo " If '--format' is specified, the archive is created with the named"
echo " git archiver backend. Obviously, this must be a backend that git-archive"
echo " understands. The format defaults to 'tar' if not specified."
echo
echo " If '--prefix' is specified, the archive's superproject and all submodules"
echo " are created with the <path> prefix named. The default is to not use one."
echo
echo " If '--separate' or '-s' is specified, individual archives will be created"
echo " for each of the superproject itself and its submodules. The default is to"
echo " concatenate individual archives into one larger archive."
echo
echo " If 'output_file' is specified, the resulting archive is created as the"
echo " file named. This parameter is essentially a path that must be writeable."
echo " When combined with '--separate' ('-s') this path must refer to a directory."
echo " Without this parameter or when combined with '--separate' the resulting"
echo " archive(s) are named with a dot-separated path of the archived directory and"
echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')."
}
version () {
echo "$PROGRAM version $VERSION"
}
# Internal variables and initializations.
readonly PROGRAM=`basename "$0"`
readonly VERSION=0.2
OLD_PWD="`pwd`"
TMPDIR=${TMPDIR:-/tmp}
TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress
TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"`
OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default
SEPARATE=0
FORMAT=tar
PREFIX=
TREEISH=HEAD
# RETURN VALUES/EXIT STATUS CODES
readonly E_BAD_OPTION=254
readonly E_UNKNOWN=255
# Process command-line arguments.
while test $# -gt 0; do
case $1 in
--format )
shift
FORMAT="$1"
shift
;;
--prefix )
shift
PREFIX="$1"
shift
;;
--separate | -s )
shift
SEPARATE=1
;;
--version )
version
exit
;;
-? | --usage | --help )
usage
exit
;;
-* )
echo "Unrecognized option: $1" >&2
usage
exit $E_BAD_OPTION
;;
* )
break
;;
esac
done
if [ ! -z "$1" ]; then
OUT_FILE="$1"
shift
fi
# Validate parameters; error early, error often.
if [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then
echo "When creating multiple archives, your destination must be a directory."
echo "If it's not, you risk being surprised when your files are overwritten."
exit
elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then
echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)."
exit
fi
# Create the superproject's git-archive
git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename $(pwd)).$FORMAT
echo $TMPDIR/$(basename $(pwd)).$FORMAT >| $TMPFILE # clobber on purpose
superfile=`head -n 1 $TMPFILE`
# DEACTIVATED: We do not have any exportable sub repositories
# find . -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' | grep -v '^$' >> $TOARCHIVE
while read path; do
TREEISH=$(git submodule | grep "^ .*${path%/}" | cut -d ' ' -f 2) # git-submodule does not list trailing slashes in $path
cd "$path"
git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT
if [ $FORMAT = 'zip' ]; then
# delete the empty directory entry; zipped submodules won't unzip if we don't do this
zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/'
fi
echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE
cd "$OLD_PWD"
done < $TOARCHIVE
# Concatenate archives into a super-archive.
if [ $SEPARATE -eq 0 ]; then
if [ $FORMAT = 'tar' ]; then
sed -e '1d' $TMPFILE | while read file; do
tar --concatenate -f "$superfile" "$file" && rm -f "$file"
done
elif [ $FORMAT = 'zip' ]; then
sed -e '1d' $TMPFILE | while read file; do
# zip incorrectly stores the full path, so cd and then grow
cd `dirname "$file"`
zip -g "$superfile" `basename "$file"` && rm -f "$file"
done
cd "$OLD_PWD"
fi
echo "$superfile" >| $TMPFILE # clobber on purpose
fi
while read file; do
mv "$file" "$OUT_FILE"
done < $TMPFILE
CURRENTDIR=${PWD##*/}
gzip $OUT_FILE/$CURRENTDIR.tar
TAR_NAME=${PREFIX%/}
test -f $TAR_NAME.tar.gz && rm -f $TAR_NAME.tar.gz
mv $OUT_FILE/$CURRENTDIR.tar.gz ../$TAR_NAME.tar.gz
echo "../$TAR_NAME.tar.gz created for uploading..."
cd ..
test -f $TAR_NAME.tar.gz.md5 && rm $TAR_NAME.tar.gz.md5
md5sum $TAR_NAME.tar.gz > $TAR_NAME.tar.gz.md5
echo "../$TAR_NAME.tar.gz.md5 created for uploading..."

3
configure vendored
View File

@ -2950,7 +2950,7 @@ fi
#
# Create config files
#
ac_config_files="$ac_config_files Makefile config/authentication.ini config/config.ini config/resources.ini config/modules/monitoring/backends.ini config/modules/monitoring/instances.ini etc/apache/icingaweb.conf public/.htaccess public/index.php"
ac_config_files="$ac_config_files Makefile config/authentication.ini config/config.ini config/resources.ini config/modules/monitoring/backends.ini config/modules/monitoring/instances.ini etc/apache/icingaweb.conf public/.htaccess public/index.php public/css.php"
#
@ -3671,6 +3671,7 @@ do
"etc/apache/icingaweb.conf") CONFIG_FILES="$CONFIG_FILES etc/apache/icingaweb.conf" ;;
"public/.htaccess") CONFIG_FILES="$CONFIG_FILES public/.htaccess" ;;
"public/index.php") CONFIG_FILES="$CONFIG_FILES public/index.php" ;;
"public/css.php") CONFIG_FILES="$CONFIG_FILES public/css.php" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View File

@ -442,6 +442,7 @@ AC_CONFIG_FILES([
etc/apache/icingaweb.conf
public/.htaccess
public/index.php
public/css.php
])
#

View File

@ -2,13 +2,13 @@
namespace Icinga\File;
use \DOMPDF;
use \DOMDocument;
use \DOMXPath;
use DOMPDF;
use DOMDocument;
use DOMXPath;
require_once 'vendor/dompdf/dompdf_config.inc.php';
spl_autoload_register("DOMPDF_autoload");
spl_autoload_register('DOMPDF_autoload');
class Pdf extends DOMPDF
{
@ -20,18 +20,19 @@ class Pdf extends DOMPDF
public $rowsPerPage = 10;
/**
* If tables should only start at new pages.
* Wether tables should only start at new pages.
*
* @var bool
*/
public $tableInitialPageBreak = false;
/**
* If occurring tables should be split up into smaller tables to avoid errors in the document layout.
* Whether occurring tables should be split up into smaller tables to avoid
* errors in the document layout.
*
* @var bool
*/
public $paginateTable = true;
public $paginateTable = false;
public function __construct()
{

View File

@ -29,6 +29,8 @@
namespace Icinga\Util;
use Icinga\Exception\ProgrammingError;
class Format
{
const STANDARD_IEC = 0;
@ -99,6 +101,9 @@ class Format
if (! $timestamp) {
return '-';
}
if (! preg_match('~^\d+$~', $timestamp)) {
throw new ProgrammingError(sprintf('"%s" is not a number', $timestamp));
}
$duration = time() - $timestamp;
$prefix = '';
if ($duration < 0) {

View File

@ -29,13 +29,14 @@
namespace Icinga\Web\Controller;
use \Exception;
use \Zend_Controller_Action;
use \Zend_Controller_Request_Abstract;
use \Zend_Controller_Response_Abstract;
use \Zend_Controller_Action_HelperBroker;
use Exception;
use Zend_Controller_Action;
use Zend_Controller_Request_Abstract;
use Zend_Controller_Response_Abstract;
use Zend_Controller_Action_HelperBroker;
use Icinga\Authentication\Manager as AuthManager;
use Icinga\Application\Benchmark;
use Icinga\Application\Config;
use Icinga\Util\Translator;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Url;
@ -59,6 +60,32 @@ class ActionController extends Zend_Controller_Action
*/
protected $requiresAuthentication = true;
private $config;
private $configs = array();
// TODO: This would look better if we had a ModuleActionController
public function Config($file = null)
{
if ($this->config === null) {
$module = $this->getRequest()->getModuleName();
if ($module === 'default') {
if ($file === null) {
$this->config = Config::app();
} else {
$this->config = Config::app($file);
}
} else {
if ($file === null) {
$this->config = Config::module($module);
} else {
$this->config = Config::module($module, $file);
}
}
}
return $this->config;
}
/**
* The constructor starts benchmarking, loads the configuration and sets
* other useful controller properties
@ -202,7 +229,11 @@ class ActionController extends Zend_Controller_Action
$base = $this->_request->getModuleName() . '/' .
$this->_request->getControllerName() . '/' .
$this->_request->getActionName();
return $_SERVER['QUERY_STRING'] !== '' ? $base . '?' . $_SERVER['QUERY_STRING'] : $base;
// TODO: We should NOT fiddle with Querystring here in the middle of nowhere
if (isset($_SERVER['QUERY_STRING']) && $_SERVER['QUERY_STRING'] !== '') {
return $base . '?' . $_SERVER['QUERY_STRING'];
}
return $base;
}
/**
@ -229,12 +260,8 @@ class ActionController extends Zend_Controller_Action
{
Benchmark::measure('Action::postDispatch()');
if ($this->_request->isXmlHttpRequest()) {
$target = ($this->getParam('render') === 'detail') ? 'inline' : 'body';
if ($target !== 'inline') {
$target = ($this->getParam('view') === 'compact') ? 'inline' : 'body';
}
$this->_helper->layout()->setLayout($target);
if ($this->_request->isXmlHttpRequest() || $this->getParam('view') === 'compact') {
$this->_helper->layout()->setLayout('inline');
}
if ($user = $this->getRequest()->getUser()) {
// Cast preference app.showBenchmark to bool because preferences loaded from a preferences storage are
@ -247,6 +274,16 @@ class ActionController extends Zend_Controller_Action
if ($this->_request->getParam('format') === 'pdf' && $this->_request->getControllerName() !== 'static') {
$this->sendAsPdfAndDie();
}
// Module container
$module_name = $this->_request->getModuleName();
$this->_helper->layout()->moduleStart =
'<div class="icinga-module module-'
. $module_name
. '" data-icinga-module="' . $module_name . '">'
. "\n"
;
$this->_helper->layout()->moduleEnd = "</div>\n";
}
protected function sendAsPdfAndDie()

View File

@ -366,7 +366,6 @@ class Form extends Zend_Form
array(
'name' => 'btn_submit',
'label' => $this->submitLabel,
'class' => 'button btn btn-cta'
)
);
$this->addElement($submitButton);
@ -619,9 +618,6 @@ class Form extends Zend_Form
$el->removeDecorator('Label');
$el->removeDecorator('DtDdWrapper');
$el->addDecorator(new BootstrapForm());
if ($el->getId() === 'btn_submit' || stripos($el->getAttrib('class'), 'btn') === false) {
$el->setAttrib('class', $el->getAttrib('class') . ' form-control input-sm');
}
}
return $this;

View File

@ -29,9 +29,9 @@
namespace Icinga\Web;
use \stdClass;
use \Icinga\Logger\Logger;
use \Icinga\Exception\ProgrammingError;
use Icinga\Logger\Logger;
use Icinga\Exception\ProgrammingError;
use stdClass;
/**
* Icinga Web Hook registry

View File

@ -29,12 +29,14 @@
namespace Icinga\Web;
use \Exception;
use \RecursiveDirectoryIterator;
use \RecursiveIteratorIterator;
use \RegexIterator;
use \RecursiveRegexIterator;
use \Zend_Controller_Front;
use Exception;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RegexIterator;
use RecursiveRegexIterator;
use Zend_Controller_Front;
use Icinga\Application\Icinga;
use lessc;
/**
* Less compiler prints files or directories to stdout
@ -56,6 +58,8 @@ class LessCompiler
private $lessc;
private $baseUrl;
private $source;
/**
* Create a new instance
@ -63,7 +67,7 @@ class LessCompiler
public function __construct()
{
require_once 'vendor/lessphp/lessc.inc.php';
$this->lessc = new \lessc();
$this->lessc = new lessc();
$this->lessc->setVariables(
array(
@ -72,6 +76,13 @@ class LessCompiler
);
}
public function compress()
{
$this->lessc->setPreserveComments(false);
$this->lessc->setFormatter('compressed');
return $this;
}
/**
* Add usable style item to stack
*
@ -82,6 +93,51 @@ class LessCompiler
$this->items[] = $item;
}
public function addLoadedModules()
{
foreach (Icinga::app()->getModuleManager()->getLoadedModules() as $name => $module) {
$this->addModule($name, $module);
}
return $this;
}
public function addFile($filename)
{
$this->source .= "\n/* CSS: $filename */\n"
. file_get_contents($filename)
. "\n\n";
return $this;
}
public function compile()
{
//TODO:
/* $tmpfile = '/tmp/icinga.less';
$cssfile = '/tmp/icinga.css';
if (! file_exists($tmpfile)) {
file_put_contents($tmpfile, $this->source);
}
if ($this->lessc->checkedCompile($tmpfile, $cssfile)) {
}
return file_get_contents($cssfile);
*/
return $this->lessc->compile($this->source);
}
public function addModule($name, $module)
{
if ($module->hasCss()) {
$this->source .= "\n/* CSS: modules/$name/module.less */\n"
. '.icinga-module.module-'
. $name
. " {\n"
. file_get_contents($module->getCssFilename())
. "}\n\n"
;
}
return $this;
}
/**
* Compile and print a single file
*

View File

@ -0,0 +1,53 @@
<?php
/**
* Web widget class
*/
namespace Icinga\Web;
use Icinga\Exception\ProgrammingError;
/**
* Web widgets make things easier for you!
*
* This class provides nothing but a static factory method for widget creation.
* Usually it will not be used directly as there are widget()-helpers available
* in your action controllers and view scripts.
*
* Usage example:
* <code>
* $tabs = Widget::create('tabs');
* </code>
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Widget
{
/**
* Create a new widget
*
* @param string $name Widget name
* @param array $options Widget constructor options
*
* @return Icinga\Web\Widget\AbstractWidget
*/
public static function create($name, $options = array(), $module_name = null)
{
$class = 'Icinga\\Web\\Widget\\' . ucfirst($name);
if (! class_exists($class)) {
throw new ProgrammingError(
sprintf(
'There is no such widget: %s',
$name
)
);
}
$widget = new $class($options, $module_name);
return $widget;
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
* Web Widget abstract class
*/
namespace Icinga\Web\Widget;
use Icinga\Exception\ProgrammingError;
use Zend_Controller_Action_HelperBroker as ZfActionHelper;
use Zend_View_Abstract;
use Icinga\Web\Widget\Widget;
/**
* Web widgets MUST extend this class
*
* AbstractWidget implements getters and setters for widget options stored in
* the protected options array. If you want to allow options for your own
* widget, you have to set a default value (may be null) for each single option
* in this array.
*
* Please have a look at the available widgets in this folder to get a better
* idea on what they should look like.
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
abstract class AbstractWidget implements Widget
{
/**
* If you are going to access the current view with the view() function,
* it's instance is stored here for performance reasons.
*
* @var Zend_View_Abstract
*/
protected static $view;
/**
* Getter for widget properties
*
* @param string $key The option you're interested in
*
* @throws ProgrammingError for unknown property name
*
* @return mixed
*/
public function __get($key)
{
if (array_key_exists($key, $this->properties)) {
return $this->properties[$key];
}
throw new ProgrammingError(
sprintf(
'Trying to get invalid "%s" property for %s',
$key,
get_class($this)
)
);
}
/**
* Setter for widget properties
*
* @param string $key The option you want to set
* @param string $val The new value going to be assigned to this option
*
* @throws ProgrammingError for unknown property name
*
* @return mixed
*/
public function __set($key, $val)
{
if (array_key_exists($key, $this->properties)) {
$this->properties[$key] = $val;
return;
}
throw new ProgrammingError(
sprintf(
'Trying to set invalid "%s" property in %s. Allowed are: %s',
$key,
get_class($this),
empty($this->properties)
? 'none'
: implode(', ', array_keys($this->properties))
)
);
}
/**
* Access the current view
*
* Will instantiate a new one if none exists
* // TODO: App->getView
*
* @return Zend_View_Abstract
*/
protected function view()
{
if (self::$view === null) {
$renderer = ZfActionHelper::getStaticHelper(
'viewRenderer'
);
if (null === $renderer->view) {
$renderer->initView();
}
self::$view = $renderer->view;
}
return self::$view;
}
/**
* Cast this widget to a string. Will call your render() function
*
* @return string
*/
public function __toString()
{
try {
$html = $this->render($this->view());
} catch (Exception $e) {
return htmlspecialchars($e->getMessage());
}
return $html;
}
}

View File

@ -29,16 +29,15 @@
namespace Icinga\Web\Widget;
use \Icinga\Application\Icinga;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Logger\Logger;
use \Icinga\Exception\ConfigurationError;
use \Icinga\Web\Widget\Widget;
use \Icinga\Web\Widget\Dashboard\Pane;
use \Icinga\Web\Widget\Dashboard\Component as DashboardComponent;
use \Icinga\Web\Url;
use \Zend_View_Abstract;
use Icinga\Application\Icinga;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Logger\Logger;
use Icinga\Exception\ConfigurationError;
use Icinga\Web\Widget\AbstractWidget;
use Icinga\Web\Widget\Dashboard\Pane;
use Icinga\Web\Widget\Dashboard\Component as DashboardComponent;
use Icinga\Web\Url;
use Zend_View_Abstract;
/**
* Dashboards display multiple views on a single page
@ -49,7 +48,7 @@ use \Zend_View_Abstract;
* - Dashboard: Shows all panes
*
*/
class Dashboard implements Widget
class Dashboard extends AbstractWidget
{
/**
* The configuration containing information about this dashboard
@ -326,7 +325,7 @@ class Dashboard implements Widget
public function determineActivePane()
{
$active = $this->getTabs()->getActiveName();
if (!$active) {
if (! $active) {
if ($active = Url::fromRequest()->getParam($this->tabParam)) {
if ($this->isEmptyPane($active)) {
$active = $this->setDefaultPane();

View File

@ -37,6 +37,7 @@ use Zend_View_Abstract;
use Zend_Config;
use Zend_Form_Element_Submit;
use Zend_Form_Element_Button;
use Exception;
/**
* A dashboard pane component
@ -93,16 +94,11 @@ class Component implements Widget
*/
private $template =<<<'EOD'
<div data-icinga-component="app/dashboard" style="overflow:hidden" class="dashboard-component {{IS_FULL}}" data-icinga-url="{URL}">
<h1 class="pull-left"><a data-icinga-target="self" href="{FULL_URL}"> {TITLE}</a></h1>
{REMOVE_BTN}
<div class="container" >
</div>
<div class="container" data-icinga-url="{URL}">
<h1><a href="{FULL_URL}">{TITLE}</a></h1>
<noscript>
<iframe src="{URL}" style="height:100%; width:99%" frameborder="no"></iframe>
</noscript>
</div>
EOD;
@ -119,8 +115,15 @@ EOD;
$this->pane = $pane;
if ($url instanceof Url) {
$this->url = $url;
} else {
} elseif ($url) {
$this->url = Url::fromPath($url);
} else {
throw new Exception(
sprintf(
'Cannot create dashboard component "%s" without valid URL',
$title
)
);
}
}

View File

@ -102,11 +102,9 @@ EOT;
'text',
'query',
array(
'label' => 'Filter Results',
// 'label' => 'Filter Results',
'name' => 'query',
'data-icinga-component' => 'app/semanticsearch',
'data-icinga-filter-domain' => $this->domain,
'data-icinga-filter-module' => $this->module
'placeholder' => 'Add filter'
)
);
$form->removeAttrib('data-icinga-component');

View File

@ -223,7 +223,7 @@ class Tab implements Widget
public function render(Zend_View_Abstract $view)
{
$class = $this->active ? ' class="active" ' : '';
$caption = $this->title;
$caption = $view->escape($this->title);
if ($this->icon !== null) {
$caption = '<img src="' . $this->icon->getAbsoluteUrl()
@ -240,7 +240,7 @@ class Tab implements Widget
}
}
$tab = '<a' . $tagParams .' href="' . $this->url->getAbsoluteUrl()
. '" data-icinga-target="self">' . $caption . '</a>';
. '">' . $caption . '</a>';
} else {
$tab = $caption;
}

View File

@ -43,8 +43,6 @@ class BasketAction implements Tabextension
* Applies the dashboard actions to the provided tabset
*
* @param Tabs $tabs The tabs object to extend with
*
* @see \Icinga\Web\Widget\Tabextension::apply()
*/
public function apply(Tabs $tabs)
{

View File

@ -45,15 +45,13 @@ class DashboardAction implements Tabextension
* Applies the dashboard actions to the provided tabset
*
* @param Tabs $tabs The tabs object to extend with
*
* @see \Icinga\Web\Widget\Tabextension::apply()
*/
public function apply(Tabs $tabs)
{
$tabs->addAsDropdown(
'dashboard',
array(
'iconCls' => 'icinga-icon-dashboard',
'icon' => 'img/icons/dashboard.png',
'title' => 'Add To Dashboard',
'url' => Url::fromPath('dashboard/addurl'),
'urlParams' => array(

View File

@ -65,21 +65,22 @@ class OutputFormat implements Tabextension
private $supportedTypes = array(
self::TYPE_PDF => array(
'name' => 'pdf',
'title' => '<i class="icinga-icon-pdf"></i> PDF',
'urlParams' => array('format' => 'pdf')
'title' => 'PDF',
'icon' => 'img/icons/pdf.png',
'urlParams' => array('format' => 'pdf'),
),
/*
self::TYPE_CSV => array(
'name' => 'csv',
'title' => '<i class="icinga-icon-csv"></i> CSV',
'title' => 'CSV',
'icon' => 'img/icons/csv.png',
'urlParams' => array('format' => 'csv')
),
self::TYPE_JSON => array(
'name' => 'json',
'title' => '<i class="icinga-icon-json"></i> JSON',
'title' => 'JSON',
'icon' => 'img/icons/json.png',
'urlParams' => array('format' => 'json')
)
*/
);
/**
@ -109,7 +110,10 @@ class OutputFormat implements Tabextension
continue;
}
$tabConfig = $this->supportedTypes[$type];
$tabConfig["url"] = Url::fromRequest();
$tabConfig['url'] = Url::fromRequest();
$tabConfig['tagParams'] = array(
'target' => '_blank'
);
$this->tabs[] = new Tab($tabConfig);
}
}

View File

@ -29,10 +29,11 @@
namespace Icinga\Web\Widget;
use \Icinga\Exception\ProgrammingError;
use \Icinga\Web\Widget\Tabextension\Tabextension;
use \Zend_View_Abstract;
use \Countable;
use Icinga\Exception\ProgrammingError;
use Icinga\Web\Widget\Tabextension\Tabextension;
use Icinga\Application\Icinga;
use Zend_View_Abstract;
use Countable;
/**
* Navigation tab widget
@ -45,9 +46,9 @@ class Tabs implements Countable, Widget
* @var string
*/
private $baseTpl = <<< 'EOT'
<ul class="nav nav-tabs">
{TABS}
{DROPDOWN}
<ul class="tabs">
{TABS}
{DROPDOWN}
</ul>
EOT;
@ -57,13 +58,11 @@ EOT;
* @var string
*/
private $dropdownTpl = <<< 'EOT'
<li class="dropdown pull-right ">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" style="margin-top:3px">
<i style="" class="caret"></i> Actions
</a>
<ul class="dropdown-menu">
{TABS}
</ul>
<li class="dropdown">
<a href="#" class="dropdown-toggle"></a>
<ul class="dropdown-menu">
{TABS}
</ul>
</li>
EOT;
@ -285,6 +284,16 @@ EOT;
return $html;
}
public function __toString()
{
try {
$html = $this->render(Icinga::app()->getViewRenderer()->view);
} catch (Exception $e) {
return htmlspecialchars($e->getMessage());
}
return $html;
}
/**
* Return the number of tabs
*

View File

@ -782,6 +782,9 @@ class Parsedown
{
$element['»'] = str_replace('&', '&amp;', $element['»']);
$element['»'] = str_replace('<', '&lt;', $element['»']);
// TODO: this should be documented and patched upstream
$element['»'] = preg_replace('~ =(\d+)x$~', '" width="$1', $element['»']);
$element['»'] = preg_replace('~ =(\d+)x(\d+)$~', '" width="$1" height="$2"', $element['»']);
if ($element['!'])
{

View File

@ -1415,6 +1415,18 @@ class Style {
//see __set and __get, on all assignments clear cache, not needed on direct set through __set
$this->_prop_cache["color"] = null;
// NETWAYS [tgelf] 2014-02-21: quickfix for inherited/transparent colors.
// TODO: Do it right and report it upstream
if (is_string($col)) {
if ($col === 'inherit') {
$col = array('hex' => '#000000');
} elseif ($col === 'transparent') {
$col = array('hex' => '#ffffff');
} else {
die(var_export($col, 1));
}
}
$this->_props["color"] = $col["hex"];
}

View File

@ -52,9 +52,11 @@ use Icinga\Module\Monitoring\DataView\ServiceStatus as ServiceStatusView;
use Icinga\Module\Monitoring\DataView\Comment as CommentView;
use Icinga\Module\Monitoring\DataView\Groupsummary as GroupsummaryView;
use Icinga\Module\Monitoring\DataView\EventHistory as EventHistoryView;
use Icinga\Module\Monitoring\DataView\StateHistorySummary;
use Icinga\Module\Monitoring\Filter\UrlViewFilter;
use Icinga\Module\Monitoring\DataView\ServiceStatus;
use Icinga\Filter\Filterable;
use Icinga\Web\Url;
class Monitoring_ListController extends MonitoringController
{
@ -102,7 +104,13 @@ class Monitoring_ListController extends MonitoringController
*/
public function hostsAction()
{
$this->getTabs()->add('hosts', array(
'title' => 'Hosts Status',
'url' => Url::fromPath('monitoring/list/hosts')
))->activate('hosts');
header('X-Icinga-Refresh: 30');
$this->view->title = 'Host Status';
$this->compactView = 'hosts-compact';
$dataview = HostStatusView::fromRequest(
$this->_request,
@ -113,7 +121,7 @@ class Monitoring_ListController extends MonitoringController
'host_address',
'host_acknowledged',
'host_output',
'host_long_output',
// 'host_long_output',
'host_in_downtime',
'host_is_flapping',
'host_state_type',
@ -121,10 +129,10 @@ class Monitoring_ListController extends MonitoringController
'host_last_check',
'host_last_state_change',
'host_notifications_enabled',
'host_unhandled_service_count',
// 'host_unhandled_service_count',
'host_action_url',
'host_notes_url',
'host_last_comment',
// 'host_last_comment',
'host_active_checks_enabled',
'host_passive_checks_enabled',
'host_current_check_attempt',
@ -146,6 +154,7 @@ class Monitoring_ListController extends MonitoringController
));
$this->handleFormatRequest($query);
$this->view->hosts = $query->paginate();
}
/**
@ -153,12 +162,19 @@ class Monitoring_ListController extends MonitoringController
*/
public function servicesAction()
{
$this->getTabs()->add('services', array(
'title' => 'Services Status',
'url' => Url::fromPath('monitoring/list/services')
))->activate('services');
$this->view->title = 'Service Status';
header('X-Icinga-Refresh: 30');
$this->compactView = 'services-compact';
$query = $this->fetchServices();
$this->applyRestrictions($query);
$this->view->services = $query->paginate();
$this->setupFilterControl(ServiceStatus::fromRequest($this->getRequest()), 'service');
//$this->setupFilterControl(ServiceStatus::fromRequest($this->getRequest()), 'service');
$this->setupFilterControl($query, 'service');
$this->setupSortControl(array(
'service_last_check' => 'Last Service Check',
'service_severity' => 'Severity',
@ -181,7 +197,11 @@ class Monitoring_ListController extends MonitoringController
*/
public function downtimesAction()
{
$query = DowntimeView::fromRequest($this->_request)->getQuery();
$this->getTabs()->add('downtimes', array(
'title' => 'Downtimes',
'url' => Url::fromPath('monitoring/list/downtimes')
))->activate('downtimes');
$query = DowntimeView::fromRequest($this->_request)->getQuery()->order('downtime_is_in_effect', 'DESC')->order('downtime_scheduled_start_time', 'DESC');
$this->view->downtimes = $query->paginate();
$this->setupSortControl(array(
@ -206,6 +226,8 @@ class Monitoring_ListController extends MonitoringController
*/
public function notificationsAction()
{
$this->addTitleTab('notifications');
$query = NotificationView::fromRequest($this->_request)->getQuery();
$this->view->notifications = $query->paginate();
$this->setupSortControl(array(
@ -216,6 +238,7 @@ class Monitoring_ListController extends MonitoringController
public function contactsAction()
{
$this->addTitleTab('contactgroups');
$query = ContactView::fromRequest(
$this->_request,
array(
@ -251,26 +274,42 @@ class Monitoring_ListController extends MonitoringController
$this->handleFormatRequest($query);
}
public function statehistorysummaryAction()
{
$this->addTitleTab('statehistorysummary');
$query = StateHistorySummary::fromRequest(
$this->_request, array('day', 'cnt_events')
)->getQuery();
$this->view->summary = $query->fetchAll();
$this->handleFormatRequest($query);
}
public function contactgroupsAction()
{
$this->addTitleTab('contactgroups');
$query = ContactgroupView::fromRequest(
$this->_request,
array(
'contactgroup_name',
'contactgroup_alias',
'contact_name'
'contact_name',
'contact_alias',
'contact_email',
'contact_pager',
)
)->getQuery();
$this->view->contactgroups = $query->paginate();
$this->setupSortControl(array(
'contactgroup_name' => 'Group Name',
'contactgroup_alias' => 'Group Alias'
));
)->getQuery()->order('contactgroup_alias');
$this->view->contactgroups = $query->fetchAll();
$this->handleFormatRequest($query);
}
public function commentsAction()
{
$this->getTabs()->add('comments', array(
'title' => 'Comments',
'url' => Url::fromPath('monitoring/list/comments')
))->activate('comments');
$query = CommentView::fromRequest(
$this->_request,
array(
@ -332,21 +371,28 @@ class Monitoring_ListController extends MonitoringController
public function hostgroupsAction()
{
$this->addTitleTab('hostgroups');
$query = GroupsummaryView::fromRequest(
$this->_request,
array(
'hostgroup',
'hosts_up',
'hosts_unreachable',
'hosts_unreachable_handled',
'hosts_unreachable_unhandled',
'hosts_down',
'hosts_down_handled',
'hosts_down_unhandled',
'hosts_pending',
'services_ok',
'services_unknown',
'services_unknown_handled',
'services_unknown_unhandled',
'services_critical',
'services_critical_handled',
'services_critical_unhandled',
'services_warning',
'services_warning_handled',
'services_warning_unhandled',
'services_pending'
@ -439,6 +485,14 @@ class Monitoring_ListController extends MonitoringController
}
protected function addTitleTab($action)
{
$this->getTabs()->add($action, array(
'title' => ucfirst($action),
'url' => Url::fromPath('monitoring/list/' . $action)
))->activate($action);
}
/**
* Return all tabs for this controller
*
@ -448,7 +502,7 @@ class Monitoring_ListController extends MonitoringController
{
$tabs = $this->getTabs();
$tabs->extend(new OutputFormat())
->extend(new DashboardAction());
->extend(new DashboardAction());
}
}
// @codingStandardsIgnoreEnd

View File

@ -28,23 +28,23 @@
// {{{ICINGA_LICENSE_HEADER}}}
// @codingStandardsIgnoreStart
use \Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller as MonitoringController;
use \Icinga\Web\Hook;
use \Icinga\Module\Monitoring\Object\Host;
use \Icinga\Module\Monitoring\Object\Service;
use \Icinga\Application\Benchmark;
use \Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Application\Benchmark;
use Icinga\Web\Hook;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Widget\Tabextension\OutputFormat;
use Icinga\Web\Widget\Tabextension\DashboardAction;
use Icinga\Module\Monitoring\Backend;
use Icinga\Module\Monitoring\Controller;
use Icinga\Module\Monitoring\Object\AbstractObject;
use \Icinga\Web\Widget\Tabs;
use Icinga\Module\Monitoring\Object\Host;
use Icinga\Module\Monitoring\Object\Service;
/**
* Class Monitoring_ShowController
*
* Actions for show context
*/
class Monitoring_ShowController extends MonitoringController
class Monitoring_ShowController extends Controller
{
/**
* @var Backend
@ -62,6 +62,7 @@ class Monitoring_ShowController extends MonitoringController
|| $this->getRequest()->getActionName() === 'services' ) {
$this->view->object = new Service($this->getRequest());
} else {
// TODO: Well... this could be done better
$this->view->object = AbstractObject::fromRequest($this->getRequest());
}
@ -73,6 +74,7 @@ class Monitoring_ShowController extends MonitoringController
*/
public function serviceAction()
{
$this->getTabs()->activate('service');
$this->view->object->populate();
}
@ -81,15 +83,16 @@ class Monitoring_ShowController extends MonitoringController
*/
public function hostAction()
{
$this->getTabs()->activate('host');
$this->view->object->populate();
}
public function historyAction()
{
$this->getTabs()->activate('history');
$this->view->object->populate();
$this->view->object->fetchEventHistory();
$this->view->history = $this->view->object->eventhistory->limit(10)->paginate();
}
public function servicesAction()
@ -153,12 +156,9 @@ class Monitoring_ShowController extends MonitoringController
'service',
array(
'title' => 'Service',
'iconCls' => 'icinga-icon-service',
'icon' => 'img/icons/service.png',
'url' => 'monitoring/show/service',
'urlParams' => $params,
'tagParams' => array(
'data-icinga-target' => 'detail'
)
)
);
}
@ -166,40 +166,31 @@ class Monitoring_ShowController extends MonitoringController
'host',
array(
'title' => 'Host',
'iconCls' => 'icinga-icon-host',
'icon' => 'img/icons/host.png',
'url' => 'monitoring/show/host',
'urlParams' => $params,
'tagParams' => array(
'data-icinga-target' => 'detail'
)
)
);
$tabs->add(
'services',
array(
'title' => 'Services',
'iconCls' => 'icinga-icon-service',
'icon' => 'img/icons/service.png',
'url' => 'monitoring/show/services',
'urlParams' => $params,
'tagParams' => array(
'data-icinga-target' => 'detail'
)
)
);
$tabs->add(
'history',
array(
'title' => 'History',
'iconCls' => 'icinga-icon-history',
'icon' => 'img/icons/history.png',
'url' => 'monitoring/show/history',
'urlParams' => $params,
'tagParams' => array(
'data-icinga-target' => 'detail'
)
)
);
$tabs->extend(new OutputFormat())
->extend(new DashboardAction());
->extend(new DashboardAction());
}
}
// @codingStandardsIgnoreEnd

View File

@ -86,7 +86,7 @@ class ConfirmRemovalForm extends Form
'escape' => false,
'value' => '1',
'class' => 'btn btn-cta btn-common',
'label' => '<i class="icinga-icon-remove"></i> Confirm Removal'
'label' => $this->view->img('img/icons/remove.png') . ' Confirm Removal'
)
);
}

View File

@ -98,11 +98,11 @@ class Zend_View_Helper_CommandForm extends Zend_View_Helper_Abstract
*
* @return Form
*/
public function iconSubmitForm($iconCls, $submitTitle, $cls, $commandName, array $arguments = array())
public function iconSubmitForm($icon, $submitTitle, $cls, $commandName, array $arguments = array())
{
$form = $this->labelSubmitForm('', $submitTitle, $cls, $commandName, $arguments);
$submit = $form->getElement('btn_submit');
$submit->setLabel(sprintf('<i class="%s"></i>', $iconCls));
$submit->setLabel($this->view->img($icon));
return $form;
}

View File

@ -44,6 +44,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
continue;
}
if ($unit == 'c') continue; // Counter pie graphs are not useful
if ($compact && $val < 0.0001) continue;
if ($unit == '%') {
if (! $min ) $min = 0;
if (! $max) $max = 100;
@ -76,7 +77,7 @@ class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
. '</td></tr>';
}
}
if ($result == '') {
if ($result == '' && ! $compact) {
$result = $perfdata;
}
if (! $compact && $result !== '') {

View File

@ -9,7 +9,7 @@
<div>
<a href="<?= Url::fromPath('/monitoring/config/createbackend')->getAbsoluteUrl();?>">
<i class="icinga-icon-create"></i> Create New Monitoring Backend
<?= $this->img('img/icons/create.png') ?> Create New Monitoring Backend
</a>
</div>
<br/>

View File

@ -1,162 +1,137 @@
<?php
$dateHelper = $this->getHelper('DateFormat');
$dateHelper = $this->getHelper('DateFormat');
$commandHelper = $this->getHelper('CommandForm');
$viewHelper = $this->getHelper('MonitoringState');
/** @var Zend_View_Helper_CommandForm $commandHelper */
$commandHelper = $this->getHelper('CommandForm');
$viewHelper = $this->getHelper('MonitoringState');
?>
<div class="row">
<div class="pull-left">
<h1>Comments</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
<?= $this->sortControl->render($this); ?>
<?= $this->paginationControl($comments, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="single">
<div class="container pull-left">
<div class="content">
<table class="action">
<tbody>
<?php foreach ($comments as $comment):
<div class="row">
<div class="col-md-12">
<?= $this->sortControl->render($this); ?>
$objectType = ($comment->comment_objecttype_id === '1') ? 'host' : 'service';
$objectName = ($objectType === 'host') ? $comment->host_name : $comment->service_name;
$hrefParameters = array(
$objectType => $objectName,
'comment_id' => $comment->comment_id
);
if ($objectType === 'service') {
$hrefParameters['host'] = $comment->host_name;
}
$detailLink = $this->href(
'monitoring/show/' . $objectType,
$hrefParameters
);
$hostLink = $this->href(
'monitoring/show/host',
array(
'host' => $comment->host_name
)
);
?>
<tr>
<td>
<?= date('d.m. H:i', $comment->comment_timestamp); ?>
</td>
<td>
<?php if ($comment->comment_objecttype_id === '1'): ?>
<?= $this->img('img/icons/host.png', array('title' => 'Host comment')) ?>
<?php elseif ($comment->comment_objecttype_id === '2'): ?>
<?= $this->img('img/icons/service.png', array('title' => 'Service comment')) ?>
<?php endif; ?>
<small>
<?php
switch ($comment->comment_type) {
case 'flapping':
$icon = 'flapping';
$tooltip = 'Comment was caused by a flapping host or service.';
break;
case 'comment':
$icon = 'user';
$tooltip = 'Comment was created by an user.';
break;
case 'downtime':
$icon = 'down';
$tooltip = 'Comment was caused by a downtime.';
case 'ack':
$icon = 'acknowledgement';
$tooltip = 'Comment was caused by an acknowledgement.';
}
?>
<?= $this->img('img/icons/' . $icon . '.png', array('title' => $tooltip)) ?>
</small>
</td>
<td>
<a class="hidden" href="<?= $detailLink; ?>"></a>
<div rel="tooltip" title="Comment #<?=$comment->comment_id ?>">
For
<?php if ($comment->service_name): ?>
<a href="<?= $detailLink ?>">
<?= $comment->service_name ?>
on
<?= $comment->host_name; ?>
</a>
<?php else: ?>
<a href="<?= $hostLink ?>">
<?= $comment->host_name; ?>
</a>
<?php endif; ?>
by
<?= $comment->comment_author; ?>
<div class="small-row">
<?= $comment->comment_data; ?>
</div>
</div>
<div class="row">
<?= $this->paginationControl($comments, null, null, array('preserve' => $this->preserve)); ?>
</div>
<small>
<span>
<b>Persists: </b><?= ($comment->comment_is_persistent === '1') ? 'Yes' : 'No'; ?>
</span>
<span>
<b>Expires: </b> <?=
($comment->comment_expiration_timestamp) ?
'at ' . date('d.m H:i', $comment->comment_expiration_timestamp) :
'Never';
?>
</span>
</small>
<div class="row">
<?= $this->selectionToolbar('single'); ?>
</div>
</div>
<table class="table table-condensed pull-left">
<tbody>
<?php foreach ($comments as $comment): ?>
</td>
<td>
<?php
$objectType = ($comment->comment_objecttype_id === '1') ? 'host' : 'service';
$objectName = ($objectType === 'host') ? $comment->host_name : $comment->service_name;
$hrefParameters = array(
$objectType => $objectName,
'comment_id' => $comment->comment_id
$data = array(
'commentid' => $comment->comment_id,
'host' => $comment->host_name
);
if ($objectType === 'service') {
$hrefParameters['host'] = $comment->host_name;
$data['service'] = $comment->service_name;
}
$detailLink = $this->href(
'monitoring/show/' . $objectType,
$hrefParameters
);
$hostLink = $this->href(
'monitoring/show/host',
array(
'host' => $comment->host_name
)
echo $commandHelper->iconSubmitForm(
'img/icons/remove.png',
'Remove comment',
'btn-small',
'removecomment',
$data
);
?>
<tr>
<td>
<?= date('d.m. H:i', $comment->comment_timestamp); ?>
</td>
</td>
</div>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<td>
<?php if ($comment->comment_objecttype_id === '1'): ?>
<i class="icinga-icon-host" rel="tooltip" title="Host comment" ></i>
<?php elseif ($comment->comment_objecttype_id === '2'): ?>
<i class="icinga-icon-service" rel="tooltip" title="Service comment"></i>
<?php endif; ?>
<small>
<?php
switch ($comment->comment_type) {
case 'flapping':
$icon = 'icinga-icon-flapping';
$tooltip = 'Comment was caused by a flapping host or service.';
break;
case 'comment':
$icon = 'icinga-icon-user';
$tooltip = 'Comment was created by an user.';
break;
case 'downtime':
$icon = 'icinga-icon-down';
$tooltip = 'Comment was caused by a downtime.';
case 'ack':
$icon = 'icinga-icon-acknowledgement';
$tooltip = 'Comment was caused by an acknowledgement.';
}
?>
<i class="<?= $icon ?>" rel="tooltip" title="<?= $tooltip ?>"> </i>
</small>
</td>
<td>
<a class="hidden" href="<?= $detailLink; ?>"></a>
<div rel="tooltip" title="Comment #<?=$comment->comment_id ?>">
For
<?php if ($comment->service_name): ?>
<a href="<?= $detailLink ?>">
<?= $comment->service_name ?>
on
<?= $comment->host_name; ?>
</a>
<?php else: ?>
<a href="<?= $hostLink ?>">
<?= $comment->host_name; ?>
</a>
<?php endif; ?>
by
<?= $comment->comment_author; ?>
<div class="small-row">
<?= $comment->comment_data; ?>
</div>
<small>
<span>
<b>Persists: </b><?= ($comment->comment_is_persistent === '1') ? 'Yes' : 'No'; ?>
</span>
<span>
<b>Expires: </b> <?=
($comment->comment_expiration_timestamp) ?
'at ' . date('d.m H:i', $comment->comment_expiration_timestamp) :
'Never';
?>
</span>
</small>
</td>
<td>
<?php
$data = array(
'commentid' => $comment->comment_id,
'host' => $comment->host_name
);
if ($objectType === 'service') {
$data['service'] = $comment->service_name;
}
echo $commandHelper->iconSubmitForm(
'icinga-icon-remove',
'Remove comment',
'btn-small',
'removecomment',
$data
);
?>
</td>
</div>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="container pull-left">
<?= $this->paginationControl($comments, null, null, array('preserve' => $this->preserve)); ?>
</div>
</div>

View File

@ -1,51 +1,52 @@
<?php
$viewHelper = $this->getHelper('MonitoringState');
$knownGroups = array()
$knownGroups = array();
$contactgroups;
?>
<div class="row">
<div class="pull-left">
<h1>Contact Groups</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
</div>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="none">
<?= $this->sortControl->render($this); ?>
<?= $this->paginationControl($contactgroups, null, null, array('preserve' => $this->preserve)); ?>
<table class="table table-condensed">
<thead>
<tr>
<th> Group Name </th>
<th> Description </th>
<th> Member Name </th>
</tr>
</thead>
<tbody>
<div class="content">
<div class="summary">
<?php
foreach($contactgroups as $c):
$group = $c->contactgroup_name;
$periodLink = $this->href('monitoring/show/contacts', array('contact' => $c->contact_name));
if (! array_key_exists($group, $knownGroups)) {
$knownGroups[$group] = true;
$newRow = true;
if (! empty($knownGroups)) {
echo '</span>';
}
echo '<span class="state" style="background: #555; color: white">' . $this->escape($c->contactgroup_alias) . '<br />';
if ($c->contactgroup_alias !== $group) {
echo '(' . $this->escape($group) . ')';
} else {
echo '&nbsp;';
}
}
$methods = array();
foreach (array('email', 'pager') as $method) {
$prop = 'contact_' . $method;
if (isset($c->$prop) && ! empty($c->$prop)) {
$methods[] = $c->$prop;
}
}
?>
<span class="state" style="display:block; width: 90%; height: 80px; text-align: left; background: #eee; color: black; margin: 1em;">
<img style="border: 3px solid white; margin: 0.5em;" src="<?= $this->href('/static/gravatar', array('email' => $c->contact_email )) ?>" width="60" height="60" align="left" />
<a style="color: black; font-size: 1.1em; font-weight: bold;" href="<?= $periodLink ?>"><?= $this->escape($c->contact_alias) ?></a>
<p class="pluginoutput"><?= implode('<br />', $methods) ?></p>
</span>
<?php foreach($contactgroups as $contact): ?>
<?php $periodLink = $this->href('monitoring/show/contacts', array('contact' => $contact->contact_name)); ?>
<tr>
<?php
$groupName = $contact->contactgroup_name;
if (!array_key_exists($groupName, $knownGroups)) {
echo '<td>' . $groupName . '</td><td>' . $contact->contactgroup_alias . '</td>';
$knownGroups[$groupName] = True;
} else {
echo '<td></td><td></td>';
}
?>
<td>
<a href="<?= $periodLink ?>">
<?= $contact->contact_name ?>
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?= $this->paginationControl($contactgroups, null, null, array('preserve' => $this->preserve)); ?>
<?php if (! empty($knownGroups)): ?>
</span>
<? endif ?>
</div>
</div>

View File

@ -1,87 +1,59 @@
<?php
$commandHelper = $this->getHelper('CommandForm');
$helper = $this->getHelper('CommandForm');
?>
<div class="row">
<div class="pull-left">
<h1>Downtimes</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
</div>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="single">
<div class="container pull-left">
<div class="row">
<div class="col-md-12">
<?= $this->sortControl->render($this); ?>
</div>
</div>
<div class="row">
<?= $this->paginationControl($downtimes, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="row">
<?= $this->selectionToolbar('single'); ?>
</div>
</div>
<?= $this->paginationControl($downtimes, null, null, array('preserve' => $this->preserve)); ?>
<table class="table table-condensed">
<tbody>
<?php foreach ($downtimes as $downtime): ?>
<tr>
<td>
<?= $this->dateFormat()->formatDateTime((int) $downtime->downtime_start); ?> -
<?= $this->dateFormat()->formatDateTime((int) $downtime->downtime_end); ?>
<br />
<small>Duration: <?= $this->util()->showHourMin((int) $downtime->downtime_duration); ?></small>
<br />
<small>The <?php if($downtime->downtime_is_flexible): ?>flexible<?php else: ?>fixed<?php endif; ?> downtime is <?php if(!$downtime->downtime_is_in_effect): ?>not <?php endif; ?>in effect</small>
</td>
<td>
<?php if (isset($downtime->service)): ?>
<a href="<?= $this->href('monitoring/show/service', array(
'host' => (string) $downtime->host,
'service' => (string) $downtime->service
)); ?>"><?= $downtime->service ?></a>
<small>on <?= $downtime->host ?></small>
<?php else: ?>
<a href="<?= $this->href('monitoring/show/host', array(
'host' => (string) $downtime->host
)); ?>"><?= $downtime->host ?> </a>
<?php endif; ?>
<br />
<?= $downtime->downtime_author ?>: <?= $downtime->downtime_comment ?>
<br />
<small>Entry Time: <?= ($downtime->downtime_entry_time) ? $this->dateFormat()->formatDateTime((int) $downtime->downtime_entry_time) : ''; ?>
</small>
<td>
<?php
$data = array(
'downtimeid' => $downtime->downtime_internal_downtime_id,
'host' => $downtime->host
);
if (isset($downtime->service)) {
$data['service'] = $downtime->service;
}
echo $commandHelper->iconSubmitForm(
'icinga-icon-remove',
'Remove Downtime',
'btn-small',
'removedowntime',
$data
);
?>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<div class="container pull-left">
<?= $this->paginationControl($downtimes, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
<?= $this->sortControl->render($this); ?>
<?= $this->paginationControl($downtimes, null, null, array('preserve' => $this->preserve)); ?>
</div>
<table class="action">
<tbody>
<?php foreach ($downtimes as $downtime): ?>
<tr>
<td>
<?= $this->dateFormat()->formatDateTime((int) $downtime->downtime_start); ?> -
<?= $this->dateFormat()->formatDateTime((int) $downtime->downtime_end); ?>
<br />
<small>Duration: <?= $this->util()->showHourMin((int) $downtime->downtime_duration); ?></small>
<br />
<small>The <?php if($downtime->downtime_is_flexible): ?>flexible<?php else: ?>fixed<?php endif; ?> downtime is <?php if(!$downtime->downtime_is_in_effect): ?>not <?php endif; ?>in effect</small>
</td>
<td>
<?php if (isset($downtime->service)): ?>
<a href="<?= $this->href('monitoring/show/service', array(
'host' => (string) $downtime->host,
'service' => (string) $downtime->service
)); ?>"><?= $downtime->service ?></a>
<small>on <?= $downtime->host ?></small>
<?php else: ?>
<a href="<?= $this->href('monitoring/show/host', array(
'host' => (string) $downtime->host
)); ?>"><?= $downtime->host ?> </a>
<?php endif; ?>
<br />
<?= $downtime->downtime_author ?>: <?= $downtime->downtime_comment ?>
<br />
<small>Entry Time: <?= ($downtime->downtime_entry_time) ? $this->dateFormat()->formatDateTime((int) $downtime->downtime_entry_time) : ''; ?>
</small>
<td>
<?php
$data = array(
'downtimeid' => $downtime->downtime_internal_downtime_id,
'host' => $downtime->host
);
if (isset($downtime->service)) {
$data['service'] = $downtime->service;
}
echo $helper->iconSubmitForm(
'img/icons/remove.png',
'Remove Downtime',
'btn-small',
'removedowntime',
$data
);
?>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>

View File

@ -1,115 +1,181 @@
<div class="row">
<div class="pull-left">
<h1>Hostgroups</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
</div>
<div class="content">
<div class="summary" data-base-target="col2">
<?php foreach($hostgroups as $h): ?>
<span class="state">
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="single">
<div class="container pull-left">
<div class="row">
<div class="col-md-12">
<?= $this->sortControl->render($this); ?>
</div>
</div>
<table><tr><td>
<strong><a href="<?= $this->href(
'monitoring/list/services',
array('hostgroup' => $h->hostgroup))
?>"><?= $h->hostgroup; ?></a></strong>
<div class="row">
<div class="col-md-12">
<?= $this->paginationControl($hostgroups, null, null, array('preserve' => $this->preserve)); ?>
</div>
</div>
<?php if ($h->hosts_up): ?>
<!-- Hosts UP -->
<span class="state up">
<br />
<div class="row">
<?= $this->selectionToolbar('single'); ?>
</div>
</div>
<table class="table table-condensed pull-left">
<tbody>
<?php foreach($hostgroups as $hostgroup): ?>
<tr>
<td>
<a href="<?= $this->href('monitoring/list/services', array('hostgroup' => $hostgroup->hostgroup)); ?>">
<?= $hostgroup->hostgroup; ?>
</a>
</td>
<td>
<div class="nav navbar-nav topbar-host-status-summary">
<span class="topbar-status-up">
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 0, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Hosts Up">
<?= $hostgroup->hosts_up ?>
</a>
</span>
<span class="topbar-status-down">
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 1, 'host_unhandled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Hosts Down Unhandled">
<?= $hostgroup->hosts_down_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 1, 'host_handled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Hosts Down Handled">
<?= $hostgroup->hosts_down_handled ?>
</a>
</span>
<span class="topbar-status-unreachable">
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 2, 'host_unhandled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Hosts Unreachable Unhandled">
<?= $hostgroup->hosts_unreachable_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 2, 'host_handled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Hosts Unreachable Handled">
<?= $hostgroup->hosts_unreachable_handled ?>
</a>
</span>
<span class="topbar-status-pending">
<a href="<?= $this->href('monitoring/list/hosts', array('host_state' => 99)); ?>" title="Hosts Pending">
<?= $hostgroup->hosts_pending ?>
</a>
</span>
</div>
</td>
<td>
<div class="nav navbar-nav topbar-service-status-summary">
<span class="topbar-status-ok">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 0, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Ok">
<?= $hostgroup->services_ok ?>
</a>
</span>
<span class="topbar-status-critical">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 2, 'service_unhandled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Critical Unhandled">
<?= $hostgroup->services_critical_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 2, 'service_handled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Critical Handled">
<?= $hostgroup->services_critical_handled ?>
</a>
</span>
<span class="topbar-status-warning">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_unhandled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Warning Unhandled">
<?= $hostgroup->services_warning_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_handled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Warning Handled">
<?= $hostgroup->services_warning_handled ?>
</a>
</span>
<span class="topbar-status-unknown">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 3, 'service_unhandled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Unknown Unhandled">
<?= $hostgroup->services_unknown_unhandled ?>
</a>/
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 3, 'service_handled' => 1, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Unknown Handled">
<?= $hostgroup->services_unknown_handled ?>
</a>
</span>
<span class="topbar-status-pending">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 99, 'hostgroup' => $hostgroup->hostgroup)); ?>" title="Services Pending">
<?= $hostgroup->services_pending ?>
</a>
</span>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="<?= $this->href(
'monitoring/list/hosts',
array('host_state' => 0, 'hostgroup' => $h->hostgroup)
) ?>" title="Hosts Up"><?= $h->hosts_up ?> Hosts UP</a>
</span>
<!-- End of hosts UP -->
<?php endif ?>
<div class="container pull-left">
<?= $this->paginationControl($hostgroups, null, null, array('preserve' => $this->preserve)); ?>
</div>
<?php if ($h->hosts_down): ?>
<!-- Hosts DOWN -->
<span class="state down">
<a href="<?= $this->href(
'monitoring/list/hosts',
array('host_state' => 1, 'hostgroup' => $h->hostgroup)
) ?>" title="Hosts Up"><?= $h->hosts_down ?> Hosts DOWN: </a>
<?php if ($h->hosts_down_unhandled): ?>
<a href="<?= $this->href(
'monitoring/list/hosts',
array(
'host_state' => 1,
'host_unhandled' => 1,
'hostgroup' => $h->hostgroup
)
) ?>" title="Hosts Down Unhandled"><?= $h->hosts_down_unhandled ?> Unhandled</a>
<?php endif ?>
</span>
<?php if ($h->hosts_down_handled): ?>
<span class="state down handled">
<a href="<?= $this->href(
'monitoring/list/hosts',
array(
'host_state' => 1,
'host_handled' => 1,
'hostgroup' => $h->hostgroup
)
) ?>" title="Hosts Down Handled"><?= $h->hosts_down_handled ?></a>
</span>
<?php endif ?>
<!-- End of hosts DOWN -->
<?php endif ?>
<?php if ($h->hosts_pending): ?>
<!-- Hosts PENDING -->
<span class="state pending">
<a href="<?= $this->href(
'monitoring/list/hosts',
array('host_state' => 99)
) ?>" title="Hosts Pending"><?= $h->hosts_pending ?> pending</a>
</span>
<!-- End of hosts PENDING -->
<?php endif ?>
</td><td>
Services
<?php if ($h->services_ok): ?>
<!-- Services OK -->
<span class="state ok">
<a href="<?= $this->href(
'monitoring/list/services',
array(
'service_state' => 0,
'hostgroup' => $h->hostgroup)
) ?>" title="Services Ok"><?= $h->services_ok ?> OK</a>
</span>
<!-- End of services OK -->
<?php endif ?>
<?php if ($h->services_critical): ?>
<!-- Services CRITICAL -->
<span class="state critical">
<a href="<?= $this->href(
'monitoring/list/services',
array(
'service_state' => 2,
'hostgroup' => $h->hostgroup,
'sort' => 'service_severity'
)) ?>" title="Services Critical"><?= $h->services_critical ?> CRITICAL: </a>
<?php if ($h->services_critical_unhandled): ?>
<a href="<?= $this->href(
'monitoring/list/services',
array(
'service_state' => 2,
'service_unhandled' => 1,
'hostgroup' => $h->hostgroup,
'sort' => 'service_severity'
)
) ?>" title="Services Critical Unhandled"><?= $h->services_critical_unhandled ?> Unhandled</a>
<?php endif ?>
<?php if ($h->services_critical_handled): ?>
<span class="state critical handled">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 2, 'service_handled' => 1, 'hostgroup' => $h->hostgroup)); ?>" title="Services Critical Handled">
<?= $h->services_critical_handled ?> Handled
</a>
</span>
<?php endif ?>
</span>
<!-- End of services CRITICAL -->
<?php endif ?>
<?php if ($h->services_warning): ?>
<!-- Services WARNING -->
<span class="state warning">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'hostgroup' => $h->hostgroup)); ?>" title="Services Warning">
<?= $h->services_warning ?> WARNING: </a>
<?php if ($h->services_warning_unhandled): ?>
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_unhandled' => 1, 'hostgroup' => $h->hostgroup)); ?>" title="Services Warning Unhandled">
<?= $h->services_warning_unhandled ?> Unhandled</a>
<?php endif ?>
<?php if ($h->services_warning_handled): ?>
<span class="state warning handled">
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 1, 'service_handled' => 1, 'hostgroup' => $h->hostgroup)); ?>" title="Services Warning Handled">
<?= $h->services_warning_handled ?> Handled
</a>
</span>
<?php endif ?>
</span>
<!-- End of WARNING services -->
<?php endif ?>
<?php if ($h->services_unknown): ?>
<!-- Services UNKNOWN -->
<span class="state unknown">
<a href="<?= $this->href(
'monitoring/list/services',
array('service_state' => 3, 'hostgroup' => $h->hostgroup)
) ?>" title="Services Unknown"><?= $h->services_unknown ?> UNKNOWN: </a>
<?php if ($h->services_unknown_unhandled): ?>
<a href="<?= $this->href('monitoring/list/services', array('service_state' => 3, 'service_unhandled' => 1, 'hostgroup' => $h->hostgroup)); ?>" title="Services Unknown Unhandled">
<?= $h->services_unknown_unhandled ?> Unhandled</a>
<?php endif ?>
<?php if ($h->services_unknown_handled): ?>
<span class="state unknown handled">
<a href="<?= $this->href(
'monitoring/list/services',
array(
'service_state' => 3,
'service_handled' => 1,
'hostgroup' => $h->hostgroup
)
) ?>" title="Services Unknown Handled"><?= $h->services_unknown_handled ?> Handled</a>
</span>
<?php endif ?>
</span>
<!-- End of UNKNOWN services -->
<?php endif ?>
<?php if ($h->services_pending): ?>
<span class="state pending">
<a href="<?= $this->href(
'monitoring/list/services',
array('service_state' => 99, 'hostgroup' => $h->hostgroup)
) ?>" title="Services Pending"><?= $h->services_pending ?></a>
</span>
<?php endif ?>
</td></tr></table>
</span><!-- end of services -->
<?php endforeach; ?>
</div>
</div>

View File

@ -1,23 +1,26 @@
<h1><?= $this->escape($this->title) ?></h1>
<?php
$viewHelper = $this->getHelper('MonitoringState');
if ($hosts->count() === 0) {
echo '<p>No host found</p>';
return;
}
?><table class="action">
<tbody>
<?php
$helper = $this->getHelper('MonitoringState');
foreach($hosts as $host):
$hostStateName = strtolower($this->util()->getHostStateName($host->host_state));
$hostLink = $this->href('monitoring/show/host', array('host' => $host->host_name));
?>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="multi">
<table class="table table-condensed" style="font-size:9pt" >
<tbody>
<?php foreach($hosts as $host): ?>
<?php $hostStateName = strtolower($this->util()->getHostStateName($host->host_state)); ?>
<?php $hostLink = $this->href('monitoring/show/host', array('host' => $host->host_name)); ?>
<tr <?= ($this->activeRowHref === $hostLink) ? 'class="active"' : ''; ?> >
<!-- Color column -->
<td class="tacheader-status-<?= $hostStateName; ?>">
<a style="visibility:hidden" href="<?= $hostLink; ?>"></a>
</td>
<tr class="state <?= $hostStateName ?><?= $host->host_handled ? ' handled' : '' ?>">
<!-- Icons -->
<td>
<!-- <td>
<?php if (!$host->host_handled && $host->host_state > 0): ?>
<a href="#" title="Unhandled">
<i class="icon-table icinga-icon-unhandled"></i>
@ -60,28 +63,22 @@ $viewHelper = $this->getHelper('MonitoringState');
<?php endif; ?>
<?php endif; ?>
<?php if ($host->host_last_comment !== null): ?>
<?php if (isset($host->host_last_comment) && $host->host_last_comment !== null): ?>
<a href="#" title="Comments">
<i class="icon-table icinga-icon-comment"></i>
</a>
<?php endif; ?>
</td>
-->
<!-- State -->
<td title="<?= $viewHelper->getStateTitle($host, 'host'); ?>">
<a href="<?= $this->href('monitoring/list/services', array('host' => $host->host_name)) ?>">
<strong><?= $host->host_name ?></strong>
</a>
<td title="<?= $helper->getStateTitle($host, 'host') ?>" class="state">
<?= $this->timeSince($host->host_last_state_change) ?>
</td>
<td>
<div class="output-text">
<?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)); ?>
</div>
<a href="<?= $hostLink ?>"><?= $host->host_name ?></a><br />
<?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</tr>
<?php endforeach ?>
</tbody>
</table>

View File

@ -1,143 +1,116 @@
<?php
$viewHelper = $this->getHelper('MonitoringState');
$helper = $this->getHelper('MonitoringState');
?>
<div class="row">
<div class="pull-left">
<h1>Hosts Status</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->filterBox->render($this); ?>
</div>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="multi">
<div class="container pull-left">
<div class="row">
<div class="col-md-5">
<?= $this->filterBox->render($this); ?>
</div>
<div class="col-md-7">
<?= $this->sortControl->render($this); ?>
</div>
</div>
<div class="row">
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="row">
<?= $this->selectionToolbar('multi', $this->href('monitoring/multi/host',array( 'host' => '*' ))); ?>
</div>
</div>
<table class="table table-condensed pull-left">
<tbody>
<?php foreach($hosts as $host): ?>
<?php $hostStateName = strtolower($this->util()->getHostStateName($host->host_state)); ?>
<?php $hostLink = $this->href('monitoring/show/host', array('host' => $host->host_name)); ?>
<tr>
<!-- Color column -->
<td class="tacheader-status-<?= $hostStateName; ?>">
<a style="visibility:hidden" href="<?= $hostLink; ?>"></a>
</td>
<!-- Icons -->
<td>
<?php if (!$host->host_handled && $host->host_state > 0): ?>
<a href="#" title="Unhandled">
<i class="icon-table icinga-icon-unhandled"></i>
</a>
<?php endif; ?>
<?php if ($host->host_acknowledged && !$host->host_in_downtime): ?>
<a href="#" title="Acknowledged">
<i class="icon-table icinga-icon-acknowledgement"></i>
</a>
<?php endif; ?>
<?php if ($host->host_is_flapping): ?>
<a href="#" title="Flapping">
<i class="icon-table icinga-icon-flapping"></i>
</a>
<?php endif; ?>
<?php if (!$host->host_notifications_enabled): ?>
<a href="#" title="Notifications Disabled">
<i class="icon-table icinga-icon-notification-disabled"></i>
</a>
<?php endif; ?>
<?php if ($host->host_in_downtime): ?>
<a href="#" title="In Downtime">
<i class="icon-table icinga-icon-in-downtime"></i>
</a>
<?php endif; ?>
<?php if (!$host->host_active_checks_enabled): ?>
<?php if (!$host->host_passive_checks_enabled): ?>
<a href="#" title="Active And Passive Checks Disabled">
<i class="icinga-icon-active-passive-checks-disabled"></i>
</a>
<?php else: ?>
<a href="#" title="Active Checks Disabled">
<i class="icon-table icinga-icon-active-checks-disabled"></i>
</a>
<?php endif; ?>
<?php endif; ?>
<?php if ($host->host_last_comment !== null): ?>
<a href="#" title="Comments">
<i class="icon-table icinga-icon-comment"></i>
</a>
<?php endif; ?>
</td>
<!-- State -->
<td title="<?= $viewHelper->getStateTitle($host, 'host'); ?>">
<div>
<?php if ($host->host_unhandled_service_count): ?>
<span class="badge pull-right" title="<?= $host->host_unhandled_service_count; ?> Service Problems on Host">
<a data-icinga-target="detail" href="<?= $this->href('monitoring/list/services', array('host' => $host->host_name, 'service_problem' => 1)); ?>">
<?= $host->host_unhandled_service_count; ?>
</a>
</span>
<?php endif; ?>
<strong><?= ucfirst($viewHelper->monitoringState($host, 'host')); ?></strong><br />
<div class="small-row">
Since <?= $this->timeSince($host->host_last_state_change); ?>
<?php if ($host->host_state > 0): ?>
<br />
<strong>Attempt:</strong> <?= $host->host_current_check_attempt; ?>/<?= $host->host_max_check_attempts; ?>
(<?= ($host->host_state_type === '1') ? 'Hard' : 'Soft'; ?>)
<?php endif; ?>
</div>
</div>
</td>
<!-- Host / Status / Output -->
<td>
<?php if ($host->host_icon_image) : ?>
<div class="pull-left" style="margin-right: 2px;">
<i class="inline-image" style="background-image: url(<?= $this->escape($this->resolveMacros($host->host_icon_image, $host)); ?>);"></i>
</div>
<?php endif; ?>
<a href="<?= $this->href('monitoring/list/services', array('host' => $host->host_name)) ?>">
<strong><?= $host->host_name ?></strong>
</a>
<div class="output-text">
<?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)); ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="pull-left">
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->sortControl->render($this); ?>
</div><br />
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->selectionToolbar('multi', $this->href('monitoring/multi/host',array( 'host' => '*' ))); ?>
</div>
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="content">
<?php
if ($hosts->count() === 0) {
echo '<p>No host found</p>';
return;
}
?>
<table class="action multiselect">
<tbody>
<?php foreach($hosts as $host):
$hostStateName = strtolower($this->util()->getHostStateName($host->host_state));
$hostLink = $this->href('monitoring/show/host', array('host' => $host->host_name));
$icons = array();
if (!$host->host_handled && $host->host_state > 0){
$icons[] = $this->img('img/icons/unhandled.png', array(
'title' => 'Unhandled'
));
}
if ($host->host_acknowledged && !$host->host_in_downtime) {
$icons[] = $this->img('img/icons/acknowledgement.png', array(
'title' => 'Acknowledged'
));
}
if ($host->host_is_flapping) {
$icons[] = $this->img('img/icons/flapping.png', array(
'title' => 'Flapping'
));
}
if (!$host->host_notifications_enabled) {
$icons[] = $this->img('img/icons/notification_disabled.png', array(
'title' => 'Notifications Disabled'
));
}
if (!$host->host_in_downtime) {
$icons[] = $this->img('img/icons/in_downtime.png', array(
'title' => 'In Downtime'
));
}
if (!$host->host_active_checks_enabled) {
if (!$host->host_passive_checks_enabled) {
$icons[] = $this->img('img/icons/active_passive_checks_disabled.png', array(
'title' => 'Active And Passive Checks Disabled'
));
} else {
$icons[] = $this->img('img/icons/active_checks_disabled.png', array(
'title' => 'Active Checks Disabled'
));
}
}
// Not available right now:
if (isset($host->host_last_comment) && $host->host_last_comment !== null) {
$icons[] = $this->img('img/icons/comment.png', array(
'title' => 'Comments'
));
}
?>
<tr class="state <?= $hostStateName ?><?= $host->host_handled ? ' handled' : '' ?>">
<!-- State -->
<td class="state" title="<?= $helper->getStateTitle($host, 'host'); ?>">
<div>
<?php if (isset($host->host_unhandled_service_count) && $host->host_unhandled_service_count > 0): ?>
<span class="badge pull-right" title="<?= $host->host_unhandled_service_count; ?> Service Problems on Host">
<a href="<?= $this->href('monitoring/list/services', array('host' => $host->host_name, 'service_problem' => 1)) ?>"><?= $host->host_unhandled_service_count; ?></a>
</span>
<?php endif; ?>
<strong><?= ucfirst($helper->monitoringState($host, 'host')); ?></strong><br />
<div class="small-row">
Since <?= $this->timeSince($host->host_last_state_change); ?>
<?php if ($host->host_state > 0): ?>
<br />
<strong><?= ($host->host_state_type === '1') ? 'Hard' : 'Soft'; ?> </strong> <?= $host->host_current_check_attempt; ?>/<?= $host->host_max_check_attempts; ?>
<?php endif ?>
</div>
</div>
</td>
<!-- Host / Status / Output -->
<td>
<?php if ($host->host_icon_image) : ?>
<?= $this->img($this->resolveMacros($host->host_icon_image, $host), array('align' => 'right')) ?>
<?php endif ?>
<a href="<?= $this->href('monitoring/list/services', array('host' => $host->host_name)) ?>"><?= $host->host_name ?></a><br />
<?= $this->escape(substr(strip_tags($host->host_output), 0, 10000)); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@ -1,30 +1,30 @@
<h1><?= $this->escape($this->title) ?></h1>
<table class="action">
<tbody>
<?php
$viewHelper = $this->getHelper('MonitoringState');
?>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="multi">
$helper = $this->getHelper('MonitoringState');
<table class="table table-condensed pull-left">
<tbody>
<?php foreach ($services as $service): ?>
<?php
$serviceLink = $this->href(
'monitoring/show/service',
array(
'host' => $service->host_name,
'service' => $service->service_description
)
foreach ($services as $service):
$serviceLink = $this->href(
'monitoring/show/service',
array(
'host' => $service->host_name,
'service' => $service->service_description
)
);
$hostLink = $this->href(
'monitoring/show/host',
array(
'host' => $service->host_name,
)
'monitoring/show/host',
array('host' => $service->host_name)
);
$serviceStateName = strtolower($this->util()->getServiceStateName($service->service_state));
?>
<tr <?= ($this->activeRowHref === $serviceLink) ? 'class="active"' : ''; ?>>
?>
<!-- <tr <?= ($this->activeRowHref === $serviceLink) ? 'class="active"' : ''; ?>>-->
<tr class="state <?= $serviceStateName ?><?= $service->service_handled ? ' handled' : '' ?>">
<!-- Color column -->
<!--
<td class="tacheader-status-<?= $serviceStateName; ?>">
<a style="visibility:hidden" href="<?= $serviceLink; ?>"></a>
</td>
@ -72,36 +72,26 @@ $viewHelper = $this->getHelper('MonitoringState');
<?php endif; ?>
<?php endif; ?>
<?php if ($service->service_last_comment !== null): ?>
<?php if (isset($service->service_last_comment) && $service->service_last_comment !== null): ?>
<a href="#" title="Comments">
<i class="icon-table icinga-icon-comment"></i>
</a>
<?php endif; ?>
</td>
<td title="<?= $viewHelper->getStateTitle($service, 'service'); ?>">
<strong><?= ucfirst($viewHelper->monitoringState($service, 'service')); ?></strong><br />
<div class="small-row">
Since <?= $this->timeSince($service->service_last_state_change); ?>
<?php if ($service->service_state): ?>
<br />
<strong>Attempt:</strong>
<?= $service->service_attempt; ?>
(<?= ($service->service_state_type === '1') ? 'Hard' : 'Soft'; ?>)
<?php endif; ?>
</div>
-->
<td class="state" title="<?= $helper->getStateTitle($service, 'service'); ?>">
<?= $this->timeSince($service->service_last_state_change); ?>
</div>
</td>
<td title="<?= $viewHelper->getStateTitle($service, 'host'); ?>">
<td>
<a href="<?= $serviceLink ?>"><?= $service->service_display_name ?></a> on <a href="<?= $hostLink ?>"><?= $service->host_name; ?></a><br />
<div class="output-text">
<?= $this->escape(substr(strip_tags($service->service_output), 0, 10000)); ?>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@ -1,54 +1,43 @@
<?php
$viewHelper = $this->getHelper('MonitoringState');
$helper = $this->getHelper('MonitoringState');
?>
<div class="row">
<div class="pull-left">
<h1>Services Status</h1>
</div>
<div class="pull-right">
<?= $this->tabs->render($this); ?>
</div>
<div class="controls">
<?= $this->tabs ?>
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->filterBox->render($this); ?>
</div>
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->sortControl->render($this); ?>
</div><br />
<div style="display: inline-block; margin: 1em; vertical-align: top;">
<?= $this->selectionToolbar('multi', $this->href('monitoring/multi/service', array( 'service' => '*', 'host' => '*' ))); ?></div> <?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div data-icinga-component="app/mainDetailGrid" data-icinga-grid-selection-type="multi">
<div class="container pull-left">
<div class="row">
<div class="col-md-5">
<?= $this->filterBox->render($this); ?>
</div>
<div class="col-md-7">
<?= $this->sortControl->render($this); ?>
</div>
</div>
<div class="row">
<?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve)); ?>
</div>
<div class="row">
<?= $this->selectionToolbar('multi', $this->href('monitoring/multi/service', array( 'service' => '*', 'host' => '*' ))); ?>
</div>
</div>
<div class="content">
<table class="action multiselect">
<tbody>
<?php
<table class="table table-condensed pull-left">
<tbody>
<?php foreach ($services as $service): ?>
<?php
$serviceLink = $this->href(
'monitoring/show/service',
array(
'host' => $service->host_name,
'service' => $service->service_description
)
);
$hostLink = $this->href(
'monitoring/show/host',
array(
'host' => $service->host_name,
)
);
$serviceStateName = strtolower($this->util()->getServiceStateName($service->service_state));
?>
<tr <?= ($this->activeRowHref === $serviceLink) ? 'class="active"' : ''; ?>>
foreach ($services as $service):
$serviceLink = $this->href(
'monitoring/show/service',
array(
'host' => $service->host_name,
'service' => $service->service_description
)
);
$hostLink = $this->href(
'monitoring/show/host',
array(
'host' => $service->host_name,
)
);
$serviceStateName = strtolower($this->util()->getServiceStateName($service->service_state));
?>
<!-- <tr <?= ($this->activeRowHref === $serviceLink) ? 'class="active"' : ''; ?>>-->
<tr class="state <?= $serviceStateName ?><?= $service->service_handled ? ' handled' : '' ?>">
<!-- Color column -->
<!--
<td class="tacheader-status-<?= $serviceStateName; ?>">
<a style="visibility:hidden" href="<?= $serviceLink; ?>"></a>
</td>
@ -96,54 +85,43 @@ $viewHelper = $this->getHelper('MonitoringState');
<?php endif; ?>
<?php endif; ?>
<?php if ($service->service_last_comment !== null): ?>
<?php if (isset($service->service_last_comment) && $service->service_last_comment !== null): ?>
<a href="#" title="Comments">
<i class="icon-table icinga-icon-comment"></i>
</a>
<?php endif; ?>
</td>
<td title="<?= $viewHelper->getStateTitle($service, 'service'); ?>">
<strong><?= ucfirst($viewHelper->monitoringState($service, 'service')); ?></strong><br />
-->
<td class="state" title="<?= $helper->getStateTitle($service, 'service'); ?>">
<strong><?= strtoupper($helper->monitoringState($service, 'service')); ?></strong><br />
<div class="small-row">
Since <?= $this->timeSince($service->service_last_state_change); ?>
<?php if ($service->service_state): ?>
<br />
<strong>Attempt:</strong>
<strong><?= ($service->service_state_type === '1') ? 'Hard' : 'Soft'; ?> </strong>
<?= $service->service_attempt; ?>
(<?= ($service->service_state_type === '1') ? 'Hard' : 'Soft'; ?>)
<?php endif; ?>
</div>
</div>
</td>
<td title="<?= $viewHelper->getStateTitle($service, 'host'); ?>">
<?php if ($service->service_icon_image): ?>
<td title="<?= $helper->getStateTitle($service, 'host'); ?>">
<?= $this->perfdata($service->service_perfdata, true) ?>
<!-- <?php if ($service->service_icon_image): ?>
<div class="pull-left" style="margin-right: 2px;">
<i class="inline-image" style="background-image: url(<?= $this->escape($this->resolveMacros($service->service_icon_image, $service)); ?>);"></i>
</div>
<?php endif; ?>
<strong> <?= $service->service_display_name; ?></strong>
<small>
on <a href="<?= $this->href('monitoring/list/services', array('host' => $service->host_name)) ?>">
<?= $service->host_name; ?>
<?php if ($service->host_state != 0): ?>
(<?= ucfirst($viewHelper->monitoringState($service, 'host')); ?>)
<?php endif; ?>
</a>
</small>
<div class="output-text">
<?= $this->escape(substr(strip_tags($service->service_output), 0, 10000)); ?>
</div>
<?php endif; ?>-->
<a href="<?= $serviceLink ?>"><?= $service->service_display_name ?></a> on <a href="<?= $hostLink ?>"><?= $service->host_name; ?>
<?php if ($service->host_state != 0): ?>
(<?= ucfirst($helper->monitoringState($service, 'host')); ?>)
<?php endif; ?>
</a><br />
<p class="pluginoutput"><?= $this->escape(substr(strip_tags($service->service_output), 0, 10000)); ?></p>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="pull-left">
<?= $this->paginationControl($this->services, null, null, array('preserve' => $this->preserve)); ?>
</div>
<?php endforeach; ?>
</tbody>
</table>
</div>

View File

@ -0,0 +1,159 @@
<div class="controls">
<?= $this->tabs ?>
</div>
<style>
table.colorizedsummary td {
width: 1em;
height: 1em;
margin: 0.5em;
}
table.colorizedsummary a {
margin: 0;
display: block;
float: left;
width: 1em;
height: 1em;
}
</style>
<div class="content">
<?php
if (empty($this->summary)) {
echo 'No entries found</div>';
return;
}
$cols = array('cnt_events'/*, 'cnt_up', 'cnt_down', 'cnt_ok', 'cnt_critical'*/);
$show = array('cnt_events');
$max = (object) array();
foreach ($cols as $col) {
$max->$col = 0;
}
foreach ($this->summary as & $row) {
foreach ($cols as $col) {
if ($row->$col > $max->$col) {
$max->$col = $row->$col;
}
}
}
$colors->cnt_events = array(
$max->cnt_events * 0.80 => '#0b5',
$max->cnt_events * 0.60 => '#2b6',
$max->cnt_events * 0.40 => '#4b7',
$max->cnt_events * 0.20 => '#7b9',
0 => '#9ba',
);
$colors->cnt_up = array(
$max->cnt_up * 0.80 => '#0b5',
$max->cnt_up * 0.60 => '#2b6',
$max->cnt_up * 0.40 => '#4b7',
$max->cnt_up * 0.20 => '#7b9',
0 => '#9ba',
);
$colors->cnt_ok = array(
$max->cnt_ok * 0.80 => '#0b5',
$max->cnt_ok * 0.60 => '#2b6',
$max->cnt_ok * 0.40 => '#4b7',
$max->cnt_ok * 0.20 => '#7b9',
0 => '#9ba',
);
$colors->cnt_critical = array(
$max->cnt_critical * 0.8 => '#f34',
$max->cnt_critical * 0.6 => '#f56',
$max->cnt_critical * 0.4 => '#f67',
$max->cnt_critical * 0.2 => '#f9a',
0 => '#fcd',
);
$colors->cnt_down = array(
$max->cnt_down * 0.8 => '#f34',
$max->cnt_down * 0.6 => '#f56',
$max->cnt_down * 0.4 => '#f67',
$max->cnt_down * 0.2 => '#f9a',
0 => '#fcd',
);
function getColor(& $colors, $value, $what = 'cnt_events') {
foreach ($colors->$what as $level => $color) {
if ($value >= $level) {
return $color;
}
}
return 'red';
}
$startDay = '2014-20-02';
$start = strtotime($day);
$wday = date('w', $start);
$week = date('w', $start);
if ($wday === 0) {
$wday = 6;
} else {
$wday--;
}
?>
<table class="colorizedsummary">
<tr>
<th></th>
<th>M</th>
<th>T</th>
<th>W</th>
<th>T</th>
<th>F</th>
<th>S</th>
<th>S</th>
</tr>
<tr>
<!-- <th><?= $startDay ?></th>-->
<!--
<tr>
<?php
foreach (array_keys((array) $this->summary[0]) as $title) {
echo '<th>' . $this->escape($title) . '</th>';
}
?>
</tr>
-->
<?php
for ($i = 0; $i <= $wday; $i++) {
echo '<td></td>';
}
foreach ($this->summary as $row) {
$wday--;
if ($wday < 0) {
$wday = 6;
$week--;
echo '</tr><tr><!--<th>' . $row->day . '</th>-->';
}
echo '<td>';
foreach ($show as $col) {
echo '<a style="background-color: '
. getColor($colors, $row->$col, $col)
. '" title="'
. $this->escape($row->$col . ' ' . strtoupper(substr($col, 4)) . ' Events on ' . $row->day)
. '"></a>';
}
echo '</td>';
}
?>
</tr>
</table>
</div>

View File

@ -8,7 +8,7 @@
$this->target
);
?>" class="btn-common btn-small button">
<i class="icinga-icon-comment"></i>
<?= $this->img('img/icons/comment.png') ?>
</a>
<a rel="tooltip" title="Send custom notifications for all selected hosts or services" href="<?=
@ -17,7 +17,7 @@
$this->target
);
?>" class="btn-common btn-small button">
<i class="icinga-icon-notification"></i>
<?= $this->img('img/icons/notification.png') ?>"></i>
</a>
</div>
@ -43,7 +43,7 @@
$this->target
);
?>" class="button btn-common btn-small input-sm pull-right">
<i class="icinga-icon-remove"></i>
<?= $this->img('img/icons/remove.png') ?>"></i>
</a>
<?php } else { ?>
There are 0 comments assigned to the selected items.

View File

@ -8,7 +8,7 @@
$this->target
);
?>" class="button btn-common btn-small input-sm pull-right">
<i class="icinga-icon-in-downtime"></i>
<?= $this->img('img/icons/in_downtime.png') ?>
</a>
</div>
@ -30,7 +30,7 @@
$this->target
);
?>" class="button btn-common btn-small input-sm pull-right">
<i class="icinga-icon-remove"></i>
<?= $this->img('img/icons/remove.png') ?>
</a>
<?php } else { ?>
0 Selected items are currently in downtime.

View File

@ -1,33 +1,27 @@
<?php
/** @var Zend_View_Helper_CommandForm $cf */
$cf = $this->getHelper('CommandForm');
/** @var Zend_View_Helper_CommandForm $cf */
$cf = $this->getHelper('CommandForm');
$data = array('host' => $object->host_name);
if ($object->service_description) {
$data['service'] = $object->service_description;
}
?>
<div>
<div class="panel-heading">
<div class="panel-hostname">
Comments
<?php
$data = array(
'host' => $object->host_name
);
if ($object->service_description) {
$data['service'] = $object->service_description;
}
$addCommentHref = $this->href(
'monitoring/command/addComment',
$data
);
$sendNotificationHref = $this->href(
'monitoring/command/sendCustomNotification',
$data
);
?>
<div class="pull-right">
<a rel="tooltip" title="Add a comment" href="<?= $addCommentHref; ?>" class="btn-common btn-small button">
<i class="icinga-icon-comment"></i>
</a>
<a rel="tooltip" title="Send custom notification" href="<?= $sendNotificationHref; ?>" class="btn-common btn-small button">
<i class="icinga-icon-notification"></i>
<a rel="tooltip" title="Add a comment" href="<?= $this->href('monitoring/command/addComment', $data) ?>" class="btn-common btn-small button"><?=
$this->img('img/icons/comment.png')
?></a>
<a rel="tooltip" title="Send custom notification" href="<?= $this->href('monitoring/command/sendCustomNotification', $data
) ?>" class="btn-common btn-small button">
<?= $this->img('img/icons/notification.png') ?>
</a>
</div>
</div>
@ -50,7 +44,7 @@
$deleteData['commentid'] = $comment->comment_internal_id;
echo $cf->iconSubmitForm(
'icinga-icon-remove',
'img/icons/remove.png',
'Remove comment',
'btn-small',
'removecomment',

View File

@ -12,7 +12,7 @@
$scheduleDowntimeHref = $this->href('monitoring/command/scheduleDowntime', $scheduleDowntimeData);
?>
<a href="<?= $scheduleDowntimeHref; ?>" class="btn-common btn-small button" title="Schedule downtime">
<i class="icinga-icon-in-downtime"></i>
<?= $this->img('img/icons/in_downtime.png') ?>
</a>
</div>
Downtimes
@ -32,7 +32,7 @@
<td>
<div class="pull-right">
<?= $this->getHelper('CommandForm')->iconSubmitForm(
'icinga-icon-remove',
'img/icons/remove.png',
'Remove Downtime',
'btn-small',
'removedowntime',

View File

@ -1,57 +1,66 @@
<?php
$o = $this->object;
$isService = (isset($o->service_description)) ? true : false;
$transitionObject = new \stdClass();
$transitionObject->handled =
$obj = new \stdClass();
$obj->handled =
($isService) ? $o->service_handled : $o->host_handled;
$transitionObject->state =
$obj->state =
($isService) ? $o->service_state : $o->host_state;
$transitionObject->acknowledged =
$obj->acknowledged =
($isService) ? $o->service_acknowledged : $o->host_acknowledged;
$transitionObject->in_downtime =
$obj->in_downtime =
($isService) ? $o->in_downtime : $o->host_in_downtime;
$transitionObject->is_flapping =
$obj->is_flapping =
($isService) ? $o->is_flapping : $o->host_is_flapping;
$transitionObject->notifications_enabled =
$obj->notifications_enabled =
($isService) ? $o->notifications_enabled : $o->service_notifications_enabled;
$transitionObject->active_checks_enabled =
$obj->active_checks_enabled =
($isService) ? $o->active_checks_enabled : $o->host_active_checks_enabled;
$transitionObject->passive_checks_enabled =
$obj->passive_checks_enabled =
($isService) ? $o->passive_checks_enabled : $o->host_passive_checks_enabled;
$transitionObject->last_comment =
$obj->last_comment =
($isService) ? $o->last_comment : $o->host_last_comment;
?>
<span>
<?php if (!$transitionObject->handled && $transitionObject->state > 0): ?>
<i title="Unhandled" class="icinga-icon-unhandled"></i>
<?php endif; ?>
$i = array();
if (! $obj->handled && $obj->state > 0) {
$i[] = $this->img('img/icons/unhandled.png', array('title' => 'Unhandled'));
}
<?php if ($transitionObject->acknowledged && !$transitionObject->in_downtime): ?>
<i title="Acknowledged" class="icinga-icon-acknowledgement"></i>
<?php endif; ?>
if ($obj->acknowledged && ! $obj->in_downtime) {
$i[] = $this->img('img/icons/acknowledgement.png', array('title' => 'Acknowledged'));
}
<?php if ($transitionObject->is_flapping): ?>
<i title="Flapping" class="icinga-icon-flapping"></i>
<?php endif; ?>
if ($obj->is_flapping) {
$i[] = $this->img('img/icons/flapping.png', array('title' => 'Flapping'));
}
<?php if (!$transitionObject->notifications_enabled): ?>
<i title="Notifications Disabled" class="icinga-icon-notification-disabled"></i>
<?php endif; ?>
if (!$obj->notifications_enabled) {
$i[] = $this->img('img/icons/notification_disabled.png', array('title' => 'Notifications Disabled'));
}
<?php if ($transitionObject->in_downtime): ?>
<i title="In Downtime" class="icinga-icon-in-downtime"></i>
<?php endif; ?>
if ($obj->in_downtime) {
$i[] = $this->img('img/icons/in_downtime.png', array('title' => 'In Downtime'));
}
<?php if (!$transitionObject->active_checks_enabled): ?>
<?php if (!$transitionObject->passive_checks_enabled): ?>
<i title="Active And Passive Checks Disabled" class="icinga-icon-active-passive-checks-disabled"></i>
<?php else: ?>
<i title="Active Checks Disabled" class="icinga-icon-active-checks-disabled"></i>
<?php endif; ?>
<?php endif; ?>
if (! $obj->active_checks_enabled) {
if ($obj->passive_checks_enabled) {
$i[] = $this->img(
'img/icons/active_checks_disabled.png',
array('title' => 'Active Checks Disabled')
);
} else {
$i[] = $this->img(
'img/icons/active_passive_checks_disabled.png',
array('title' => 'Active And Passive Checks Disabled')
);
}
}
if ($obj->last_comment !== null) {
$i[] = $this->img('img/icons/comment.png', array('title' => 'Comments'));
}
?><span>
<?= implode("\n ", $i) . "\n" ?>
</span>
<?php if ($transitionObject->last_comment !== null): ?>
<i title="Comments" class="icinga-icon-comment"></i>
<?php endif; ?>
</span>

View File

@ -1,111 +1,130 @@
<?php
use Icinga\Module\Monitoring\Object\Service;
if ($object instanceof Service) {
$title = $object->service_description;
$params = array(
'host' => $object->host_name,
'service' => $object->service_description
);
} else {
$title = $object->host_name;
$params = array('host' => $object->host_name);
}
// TODO: Remove this once we have better helpers
$states = array(
'service' => array(
'ok',
'warning',
'critical',
'unknown',
99 => 'pending',
),
'host' => array(
'up',
'down',
'unreachable',
99 => 'pending',
)
);
?><div class="controls">
<?= $this->tabs->render($this); ?>
<a href="<?= $this->href('monitoring/list/eventhistory', $params); ?>">All events for <?= $title ?></a>
<h1>History</h1>
</div>
<?php if($history->count() === 0): ?>
<div class="alert alert-info">
No History Available For This Object
No History Available For This Object
</div>
<?php return; endif ?>
</div>
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
<table class="action">
<tbody>
<?php foreach ($history as $event):
if (array_key_exists($event->state, $states[$event->object_type])) {
$state_class = $states[$event->object_type][$event->state];
} else {
$state_class = 'invalid';
}
?>
<tr class="state <?= $state_class ?>">
<td class="state"><?= $this->timeSince($event->raw_timestamp) ?></td>
<td>
<?php
$output = $this->ticket_pattern ? preg_replace(
$this->ticket_pattern,
$ticket_link,
$this->pluginOutput($event->output)
) : $this->pluginOutput($event->output);
switch ($event->type) {
case 'notify':
$icon = 'notification';
$title = 'Notification';
break;
case 'comment':
$icon = 'comment';
$title = 'Comment';
break;
case 'ack':
$icon = 'acknowledgement';
$title = 'Acknowledgement';
break;
case 'dt_comment':
$icon = 'in_downtime';
$title = 'In Downtime';
break;
case 'flapping':
$icon = 'flapping';
$title = 'Flapping';
break;
case 'hard_state':
$icon = 'submit';
$title = 'Hard State';
break;
case 'soft_state':
$icon = 'softstate';
$title = 'Soft State';
break;
case 'dt_start':
$icon = 'downtime_start';
$title = 'Downtime Start';
break;
case 'dt_end':
$icon = 'downtime_end';
$title = 'Downtime End';
break;
}
echo $this->img('img/icons/' . $icon . '.png', array('title' => $title)) . ' ';
if ($object instanceof Service): ?>
<a href="<?= $this->href('monitoring/show/service', array(
'host' => $object->host_name,
'service' => $event->service_description
)); ?>"><?= $this->escape($event->service_description) ?></a>
<?php else: ?>
<a href="<?= $this->href('monitoring/show/host', array(
'host' => $object->host_name
)); ?>"><?= $this->escape($event->host_name) ?></a>
<?php endif;
<div data-icinga-component="app/mainDetailGrid">
if ($event->attempt !== null) {
printf('[ %d/%d ] ', $event->attempt, $event->max_attempts);
}
echo $output;
<?= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
<table class="table table-condensed">
<tbody>
?>
</td>
</tr>
<? endforeach; ?>
</tbody>
</table>
<?php foreach ($history as $event): ?>
<tr>
<td><?= date('d.m. H:i', $event->raw_timestamp); ?></td>
<td>
<?php if ($object instanceof Icinga\Module\Monitoring\Object\Service): ?>
<a href="<?= $this->href('monitoring/show/service', array(
'host' => $object->host_name,
'service' => $event->service_description
)); ?>">
<?= $event->service_description ?>
</a>
<?php else: ?>
<a href="<?= $this->href('monitoring/show/host', array(
'host' => $object->host_name
)); ?>">
<?= $event->host_name ?>
</a>
<?php endif; ?>
</td>
<td>
<?php
switch ($event->type) {
case 'notify':
$icon = '{{NOTIFICATION_ICON}}';
$title = 'Notification';
$msg = $event->output;
break;
case 'comment':
$icon = '{{COMMENT_ICON}}';
$title = 'Comment';
$msg = $event->output;
break;
case 'ack':
$icon = '{{ACKNOWLEDGEMENT_ICON}}';
$title = 'Acknowledgement';
$msg = '';
break;
case 'dt_comment':
$icon = '{{IN_DOWNTIME_ICON}}';
$title = 'In Downtime';
$msg = $event->output;
break;
case 'flapping':
$icon = '{{FLAPPING_ICON}}';
$title = 'Flapping';
$msg = '';
break;
case 'hard_state':
$icon = '{{HARDSTATE_ICON}}';
$title = 'Hard State';
$msg = '[' . $event->attempt . '/' . $event->max_attempts . ']';
break;
case 'soft_state':
$icon = '{{SOFTSTATE_ICON}}';
$title = 'Soft State';
$msg = '[' . $event->attempt . '/' . $event->max_attempts . ']';
break;
case 'dt_start':
$icon = '{{DOWNTIME_START_ICON}}';
$title = 'Downtime Start';
$msg = $event->output;
break;
case 'dt_end':
$icon = '{{DOWNTIME_END_ICON}}';
$title = 'Downtime End';
$msg = $event->output;
break;
}
?>
<a href="#" title="<?= $title ?>"><i><?= $icon ?></i></a>
<?php if (!empty($msg)) { echo $msg; } ?>
</td>
</tr>
<? endforeach; ?>
</tbody>
</table>
<?php if ($object instanceof Icinga\Module\Monitoring\Object\Service): ?>
<a href="<?= $this->href('monitoring/list/eventhistory', array(
'host' => $object->host_name,
'service' => $object->service_description
)); ?>">
All events for <?= $object->service_description ?>
</a>
<?php else: ?>
<a href="<?= $this->href('monitoring/list/eventhistory', array(
'host' => $object->host_name
)); ?>">
All events for <?= $object->host_name ?>
</a>
<?php endif; ?>
</div>
<?php endif; ?>

View File

@ -1,4 +1,6 @@
<?= $this->tabs->render($this); ?>
<div class="controls">
<?= $this->tabs ?>
</div>
<?= $this->render('show/components/status.phtml'); ?>
<?= $this->render('show/components/comments.phtml'); ?>
<?= $this->render('show/components/downtime.phtml'); ?>

View File

@ -1,4 +1,6 @@
<?= $this->tabs->render($this); ?>
<div class="controls">
<?= $this->tabs; ?>
</div>
<?= $this->render('show/components/status.phtml'); ?>
<?= $this->render('show/components/comments.phtml'); ?>
<?= $this->render('show/components/downtime.phtml'); ?>

View File

@ -1,7 +1,2 @@
<?= $this->tabs->render($this); ?>
<?= $this->partial(
'list/services-compact.phtml',
'monitoring', array(
'services' => $services
)
); ?>
<?= $this->render('show/components/header.phtml') ?>
<?= $services ?>

View File

@ -30,7 +30,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use \Zend_Db_Select;
use Zend_Db_Select;
class GroupSummaryQuery extends IdoQuery
{
@ -38,8 +38,10 @@ class GroupSummaryQuery extends IdoQuery
protected $columnMap = array(
'hoststatussummary' => array(
'hosts_up' => 'SUM(CASE WHEN object_type = \'host\' AND state = 0 THEN 1 ELSE 0 END)',
'hosts_unreachable' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 THEN 1 ELSE 0 END)',
'hosts_unreachable_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
'hosts_unreachable_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 2 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)',
'hosts_down' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 THEN 1 ELSE 0 END)',
'hosts_down_handled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime != 0 THEN 1 ELSE 0 END)',
'hosts_down_unhandled' => 'SUM(CASE WHEN object_type = \'host\' AND state = 1 AND acknowledged + in_downtime = 0 THEN 1 ELSE 0 END)',
'hosts_pending' => 'SUM(CASE WHEN object_type = \'host\' AND state = 99 THEN 1 ELSE 0 END)',
@ -48,8 +50,11 @@ class GroupSummaryQuery extends IdoQuery
'servicestatussummary' => array(
'services_ok' => 'SUM(CASE WHEN object_type = \'service\' AND state = 0 THEN 1 ELSE 0 END)',
'services_pending' => 'SUM(CASE WHEN object_type = \'service\' AND state = 99 THEN 1 ELSE 0 END)',
'services_warning' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 THEN 1 ELSE 0 END)',
'services_warning_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
'services_critical' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 THEN 1 ELSE 0 END)',
'services_critical_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
'services_unknown' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 THEN 1 ELSE 0 END)',
'services_unknown_handled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 3 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) > 0 THEN 1 ELSE 0 END)',
'services_warning_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 1 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) = 0 THEN 1 ELSE 0 END)',
'services_critical_unhandled' => 'SUM(CASE WHEN object_type = \'service\' AND state = 2 AND (acknowledged + in_downtime + COALESCE(host_state, 0)) = 0 THEN 1 ELSE 0 END)',

View File

@ -0,0 +1,42 @@
<?php
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
class StateHistorySummaryQuery extends IdoQuery
{
protected $columnMap = array(
'statehistory' => array(
'day' => 'DATE(sh.state_time)',
'cnt_events' => 'COUNT(*)',
'cnt_up' => 'SUM(CASE WHEN sho.objecttype_id = 1 AND sh.state = 0 THEN 1 ELSE 0 END)',
'cnt_down_hard' => 'SUM(CASE WHEN sho.objecttype_id = 1 AND sh.state = 1 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_down' => 'SUM(CASE WHEN sho.objecttype_id = 1 AND sh.state = 1 THEN 1 ELSE 0 END)',
'cnt_unreachable_hard' => 'SUM(CASE WHEN sho.objecttype_id = 1 AND sh.state = 2 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_unreachable' => 'SUM(CASE WHEN sho.objecttype_id = 1 AND sh.state = 2 THEN 1 ELSE 0 END)',
'cnt_unknown_hard' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 3 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_unknown' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 3 THEN 1 ELSE 0 END)',
'cnt_unknown_hard' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 3 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_critical' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 2 THEN 1 ELSE 0 END)',
'cnt_critical_hard' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 2 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_warning' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 1 THEN 1 ELSE 0 END)',
'cnt_warning_hard' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 1 AND state_type = 1 THEN 1 ELSE 0 END)',
'cnt_ok' => 'SUM(CASE WHEN sho.objecttype_id = 2 AND sh.state = 0 THEN 1 ELSE 0 END)',
)
);
protected function joinBaseTables()
{
$this->baseQuery = $this->db->select()->from(
array('sh' => $this->prefix . 'statehistory'),
array()
)->join(
array('sho' => $this->prefix . 'objects'),
'sh.object_id = sho.object_id AND sho.is_active = 1',
array()
)->where('sh.state_time >= ?', '2013-11-20 00:00:00')
->where('sh.state_type = 1')
->where('sh.state = 2')
->group('DATE(sh.state_time)');
$this->joinedVirtualTables = array('statehistory' => true);
}
}

View File

@ -194,13 +194,13 @@ class StatusQuery extends IdoQuery
'service_current_check_attempt' => 'ss.current_check_attempt',
'service_max_check_attempts' => 'ss.max_check_attempts',
'service_attempt' => 'ss.current_check_attempt || \'/\' || ss.max_check_attempts',
'service_last_check' => 'ss.last_check',
'service_next_check' => 'ss.next_check',
'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)',
'service_next_check' => 'UNIX_TIMESTAMP(ss.next_check)',
'service_check_type' => 'ss.check_type',
'service_last_hard_state_change' => 'ss.last_hard_state_change',
'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)',
'service_last_hard_state' => 'ss.last_hard_state',
'service_last_notification' => 'ss.last_notification',
'service_next_notification' => 'ss.next_notification',
'service_last_notification' => 'UNIX_TIMESTAMP(ss.last_notification)',
'service_next_notification' => 'UNIX_TIMESTAMP(ss.next_notification)',
'service_no_more_notifications' => 'ss.no_more_notifications',
'service_notifications_enabled' => 'ss.notifications_enabled',

View File

@ -71,10 +71,11 @@ class Controller extends ActionController
'service_acknowledged',
'service_handled',
'service_output',
'service_perfdata',
'service_attempt',
'service_last_state_change',
'service_icon_image',
'service_long_output',
// 'service_long_output',
'service_is_flapping',
'service_state_type',
'service_handled',
@ -83,7 +84,7 @@ class Controller extends ActionController
'service_notifications_enabled',
'service_action_url',
'service_notes_url',
'service_last_comment',
// 'service_last_comment',
'service_active_checks_enabled',
'service_passive_checks_enabled',
'current_check_attempt' => 'service_current_check_attempt',

View File

@ -33,7 +33,10 @@ class Contactgroup extends DataView
{
return array(
'contactgroup_name' => array(
'order' => self::SORT_DESC
'order' => self::SORT_ASC
),
'contactgroup_alias' => array(
'order' => self::SORT_ASC
)
);
}

View File

@ -42,16 +42,21 @@ class Groupsummary extends DataView
'servicegroup',
'hostgroup',
'hosts_up',
'hosts_unreachable',
'hosts_unreachable_handled',
'hosts_unreachable_unhandled',
'hosts_down',
'hosts_down_handled',
'hosts_down_unhandled',
'hosts_pending',
'services_ok',
'services_unknown',
'services_unknown_handled',
'services_unknown_unhandled',
'services_critical',
'services_critical_handled',
'services_critical_unhandled',
'services_warning',
'services_warning_handled',
'services_warning_unhandled',
'services_pending'

View File

@ -125,14 +125,14 @@ class HostStatus extends DataView
'host_severity',
'host_last_state_change',
),
'order' => self::SORT_ASC
'order' => self::SORT_DESC
)
);
}
public function getFilterColumns()
{
return array('hostgroup', 'servicegroup', 'service_problems');
return array('hostgroup', 'service_problems');
}
public function isValidFilterTarget($column)

View File

@ -151,6 +151,13 @@ class ServiceStatus extends DataView
'host_last_state_change',
),
'order' => self::SORT_ASC
),
'service_severity' => array(
'columns' => array(
'service_severity',
'service_last_state_change',
),
'order' => self::SORT_DESC
)
);
}

View File

@ -1,3 +1,4 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
@ -25,28 +26,43 @@
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
/*global Icinga:false, document: false, define:false require:false base_url:false console:false */
/**
* Ensures that our date/time controls will work on every browser (natively or javascript based)
*/
define(['jquery', 'datetimepicker'], function($) {
"use strict";
namespace Icinga\Module\Monitoring\DataView;
var DateTimePicker = function(target) {
$(target).datetimepicker({
format: 'yyyy-mm-dd hh:ii:ss',
minuteStep: 10,
autoclose: true,
todayBtn: true,
todayHighlight: true
});
class StateHistorySummary extends DataView
{
/**
* Retrieve columns provided by this view
*
* @return array
*/
public function getColumns()
{
return array(
'day',
'cnt_events',
'cnt_up',
'cnt_down_hard',
'cnt_down',
'cnt_unreachable_hard',
'cnt_unreachable',
'cnt_unknown_hard',
'cnt_unknown',
'cnt_unknown_hard',
'cnt_critical',
'cnt_critical_hard',
'cnt_warning',
'cnt_warning_hard',
'cnt_ok',
);
}
$(target).parent().find('a').click(function(e) {
e.preventDefault();
$(target).datetimepicker('show');
});
};
return DateTimePicker;
});
public function getSortRules()
{
return array(
'day' => array(
'order' => self::SORT_DESC
)
);
}
}

View File

@ -151,14 +151,14 @@ abstract class AbstractObject
'host_name',
'service_description',
'timestamp',
'raw_timestamp',
// 'raw_timestamp',
'state',
'attempt',
'max_attempts',
'output',
'type'
)
)->sort('timestamp', 'DESC')->getQuery();
)->sort('raw_timestamp', 'DESC')->getQuery();
return $this;
}

View File

@ -15,7 +15,6 @@ class Host extends AbstractObject
public function populate()
{
$this->fetchComments()
->fetchDowntimes()
->fetchHostgroups()
->fetchContacts()
->fetchContactGroups()

View File

@ -14,8 +14,6 @@ class Service extends AbstractObject
public function populate()
{
$this->fetchComments()
->fetchDowntimes()
->fetchHostgroups()
->fetchServicegroups()
->fetchContacts()
->fetchContactGroups()

32
public/css.php.in Normal file
View File

@ -0,0 +1,32 @@
<?php
use Icinga\Application\EmbeddedWeb;
use Icinga\Web\LessCompiler;
require_once dirname(__FILE__). '/../library/Icinga/Application/ApplicationBootstrap.php';
require_once dirname(__FILE__). '/../library/Icinga/Application/EmbeddedWeb.php';
$app = EmbeddedWeb::start('@icingaweb_config_path@');
$less = new LessCompiler();
header('Content-Type: text/css');
// TODO: Cache header
$lessfiles = array(
'css/icinga/defaults.less',
'css/icinga/layout-colors.less',
'css/icinga/layout-structure.less',
'css/icinga/menu.less',
'css/icinga/header-elements.less',
'css/icinga/main-content.less',
'css/icinga/tabs.less',
'css/icinga/forms.less',
'css/icinga/pagination.less',
'css/icinga/monitoring-colors.less',
'css/icinga/login.less',
);
$basedir = dirname(__FILE__);
foreach ($lessfiles as $file) {
$less->addFile($basedir . '/' . $file);
}
echo $less->addLoadedModules()->compile();

View File

View File

@ -0,0 +1,51 @@
/*** Base rules ***/
* {
font-size: 100%;
}
html, body {
height: 100%;
}
/*
TODO: -xy-text-resize-dings
*/
html, body, form, ul {
/* TODO: Really 0 ? */
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border: none;
}
body {
font-family: Ubuntu, Trebuchet MS, Calibri, Helvetica, sans-serif;
color: black;
background-color: white;
}
a {
color: #333;
text-decoration: underline;
}
a:hover {
color: black;
text-decoration: underline;
}
#fontsize-calc {
width: 1000em;
height: 1em;
font-size: 1em;
position: absolute;
top: -2em;
}
/*** END of Base rules */

View File

@ -0,0 +1,79 @@
.form-group {
margin-bottom: 1em;
}
label {
display: block;
font-weight: bold;
margin-bottom: 0.3em;
}
input, select {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
background: #f5f5f5;
padding: 0.2em;
border: 1px solid #777;
border-left-width:0.3em;
border-right-width: 0.3em;
}
select {
/* https://bugzilla.mozilla.org/show_bug.cgi?id=649849 */
-moz-appearance: none;
text-indent: 5px;
padding-right: 5px;
text-overflow: '';
-webkit-appearance: none;
cursor: pointer;
}
input[type=submit] {
font-weight: bold;
text-align: center;
color: #eee;
border-width: 1px;
background: #777;
outline: 0;
}
input:focus, select:focus {
border-color: #333;
background: white;
outline: 0;
}
input[type=submit]:focus {
background-color: #333;
}
input::-moz-focus-inner {
border: 0;
}
select::-moz-focus-inner {
border: 0;
outline: 0;
}
input[type=submit]:hover, a.button:hover {
cursor: pointer;
color: white;
background: #333;
}
form ul.errors {
list-style-type: none;
margin: 0;
padding: 0;
}
form ul.errors li {
color: @colorCritical;
font-weight: bold;
line-height: 1.5em;
}

View File

@ -0,0 +1,32 @@
#header div.user {
font-size: 1.1em;
margin-top: 0.8em;
margin-right: 2em;
float: right;
}
#responsive-debug {
font-size: 0.6em;
font-family: Courier new, monospace;
float: left;
padding-top: 0.5em;
width: 10em;
display: none;
}
#logo {
height: 3.6em;
width: 13em;
display: inline-block;
}
#logo a {
display: block;
outline: 0;
}
#logo img {
margin-left: 1.5em;
margin-top: 0.8em;
}

View File

@ -1,366 +0,0 @@
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
/* =========================================================================
Icinga Icon Set
========================================================================= */
.icinga-icon-mixin(@file) {
@iconpath : "img/icons";
background: transparent url("@{baseurl}/@{iconpath}/@{file}") center center no-repeat;
display: inline-block;
width: 16px;
height: 16px;
}
.icinga-icon-blank {
background: transparent;
display: inline-block;
width: 16px;
height: 16px;
}
.icinga-icon-acknowledgement-petrol {
.icinga-icon-mixin("acknowledgement_petrol.png");
}
.icinga-icon-acknowledgement {
.icinga-icon-mixin("acknowledgement.png");
}
.icinga-icon-active-checks-disabled-petrol {
.icinga-icon-mixin("active_checks_disabled_petrol.png");
}
.icinga-icon-active-checks-disabled {
.icinga-icon-mixin("active_checks_disabled.png");
}
.icinga-icon-active-passive-checks-disabled-petrol {
.icinga-icon-mixin("active_passive_checks_disabled_petrol.png");
}
.icinga-icon-active-passive-checks-disabled {
.icinga-icon-mixin("active_passive_checks_disabled.png");
}
.icinga-icon-comment-petrol {
.icinga-icon-mixin("comment_petrol.png");
}
.icinga-icon-comment {
.icinga-icon-mixin("comment.png");
}
.icinga-icon-configuration-petrol {
.icinga-icon-mixin("configuration_petrol.png");
}
.icinga-icon-configuration {
.icinga-icon-mixin("configuration.png");
}
.icinga-icon-create-petrol {
.icinga-icon-mixin("create_petrol.png");
}
.icinga-icon-create {
.icinga-icon-mixin("create.png");
}
.icinga-icon-csv-petrol {
.icinga-icon-mixin("csv_petrol.png");
}
.icinga-icon-csv {
.icinga-icon-mixin("csv.png");
}
.icinga-icon-dashboard-petrol {
.icinga-icon-mixin("dashboard_petrol.png");
}
.icinga-icon-dashboard {
.icinga-icon-mixin("dashboard.png");
}
.icinga-icon-disabled-petrol {
.icinga-icon-mixin("disabled_petrol.png");
}
.icinga-icon-disabled {
.icinga-icon-mixin("disabled.png");
}
.icinga-icon-down-petrol {
.icinga-icon-mixin("down_petrol.png");
}
.icinga-icon-down {
.icinga-icon-mixin("down.png");
}
.icinga-icon-downtime-end-petrol {
.icinga-icon-mixin("downtime_end_petrol.png");
}
.icinga-icon-downtime-end {
.icinga-icon-mixin("downtime_end.png");
}
.icinga-icon-downtime-start-petrol {
.icinga-icon-mixin("downtime_start__petrol.png");
}
.icinga-icon-downtime-start {
.icinga-icon-mixin("downtime_start.png");
}
.icinga-icon-edit-petrol {
.icinga-icon-mixin("edit_petrol.png");
}
.icinga-icon-edit {
.icinga-icon-mixin("edit.png");
}
.icinga-icon-error-petrol {
.icinga-icon-mixin("error_petrol.png");
}
.icinga-icon-error {
.icinga-icon-mixin("error.png");
}
.icinga-icon-expand-petrol {
.icinga-icon-mixin("expand_petrol.png");
}
.icinga-icon-expand {
.icinga-icon-mixin("expand.png");
}
.icinga-icon-flapping-petrol {
.icinga-icon-mixin("flapping_petrol.png");
}
.icinga-icon-flapping {
.icinga-icon-mixin("flapping.png");
}
.icinga-icon-history-petrol {
.icinga-icon-mixin("history_petrol.png");
}
.icinga-icon-history {
.icinga-icon-mixin("history.png");
}
.icinga-icon-hostgroup-petrol {
.icinga-icon-mixin("hostgroup_petrol.png");
}
.icinga-icon-hostgroup {
.icinga-icon-mixin("hostgroup.png");
}
.icinga-icon-host-petrol {
.icinga-icon-mixin("host_petrol.png");
}
.icinga-icon-host {
.icinga-icon-mixin("host.png");
}
.icinga-icon-in-downtime-petrol {
.icinga-icon-mixin("in_downtime_petrol.png");
}
.icinga-icon-in-downtime {
.icinga-icon-mixin("in_downtime.png");
}
.icinga-icon-json-petrol {
.icinga-icon-mixin("json_petrol.png");
}
.icinga-icon-json {
.icinga-icon-mixin("json.png");
}
.icinga-icon-logout-petrol {
.icinga-icon-mixin("logout_petrol.png");
}
.icinga-icon-logout {
.icinga-icon-mixin("logout.png");
}
.icinga-icon-next-petrol {
.icinga-icon-mixin("next_petrol.png");
}
.icinga-icon-next {
.icinga-icon-mixin("next.png");
}
.icinga-icon-notification-disabled-petrol {
.icinga-icon-mixin("notification_disabled_petrol.png");
}
.icinga-icon-notification-disabled {
.icinga-icon-mixin("notification_disabled.png");
}
.icinga-icon-notification-petrol {
.icinga-icon-mixin("notification_petrol.png");
}
.icinga-icon-notification {
.icinga-icon-mixin("notification.png");
}
.icinga-icon-pdf-petrol {
.icinga-icon-mixin("pdf_petrol.png");
}
.icinga-icon-pdf {
.icinga-icon-mixin("pdf.png");
}
.icinga-icon-prev-petrol {
.icinga-icon-mixin("prev_petrol.png");
}
.icinga-icon-prev {
.icinga-icon-mixin("prev.png");
}
.icinga-icon-refresh-petrol {
.icinga-icon-mixin("refresh_petrol.png");
}
.icinga-icon-refresh {
.icinga-icon-mixin("refresh.png");
}
.icinga-icon-remove-petrol {
.icinga-icon-mixin("remove_petrol.png");
}
.icinga-icon-remove {
.icinga-icon-mixin("remove.png");
}
.icinga-icon-reschedule-petrol {
.icinga-icon-mixin("reschedule_petrol.png");
}
.icinga-icon-reschedule {
.icinga-icon-mixin("reschedule.png");
}
.icinga-icon-save-petrol {
.icinga-icon-mixin("save_petrol.png");
}
.icinga-icon-save {
.icinga-icon-mixin("save.png");
}
.icinga-icon-search-petrol {
.icinga-icon-mixin("search_petrol.png");
}
.icinga-icon-search {
.icinga-icon-mixin("search.png");
}
.icinga-icon-servicegroup-petrol {
.icinga-icon-mixin("servicegroup_petrol.png");
}
.icinga-icon-servicegroup {
.icinga-icon-mixin("servicegroup.png");
}
.icinga-icon-service-petrol {
.icinga-icon-mixin("service_petrol.png");
}
.icinga-icon-service {
.icinga-icon-mixin("service.png");
}
.icinga-icon-softstate {
.icinga-icon-mixin("softstate.png");
}
.icinga-icon-submit-petrol {
.icinga-icon-mixin("submit_petrol.png");
}
.icinga-icon-submit {
.icinga-icon-mixin("submit.png");
}
.icinga-icon-success-petrol {
.icinga-icon-mixin("success_petrol.png");
}
.icinga-icon-success {
.icinga-icon-mixin("success.png");
}
.icinga-icon-uebersicht {
.icinga-icon-mixin("uebersicht.png");
}
.icinga-icon-unhandled-petrol {
.icinga-icon-mixin("unhandled_petrol.png");
}
.icinga-icon-unhandled {
.icinga-icon-mixin("unhandled.png");
}
.icinga-icon-up-petrol {
.icinga-icon-mixin("up_petrol.png");
}
.icinga-icon-up {
.icinga-icon-mixin("up.png");
}
.icinga-icon-user-petrol {
.icinga-icon-mixin("user_petrol.png");
}
.icinga-icon-user {
.icinga-icon-mixin("user.png");
}

View File

@ -0,0 +1,53 @@
/* Layout colors */
#sidebar {
background-color: #999;
-moz-box-shadow: inset -0.5em 0 0.5em -0.5em #555;
-webkit-box-shadow: inset -0.5em 0 0.5em -0.5em #555;
box-shadow: inset -0.5em 0 0.5em -0.5em #555;
}
#header {
background-color: #555;
background-image: -moz-linear-gradient(top, #777, #555);
background-image: -webkit-linear-gradient(top, #777, #555);
background-image: -o-linear-gradient(top, #777, #555);
background-image: -ms-linear-gradient(top, #777, #555);
background-image: linear-gradient(top, #777, #555);
color: #ddd;
color: #d0d0d0;
}
#header input {
background-color: #777;
}
#main {
background-color: white;
}
.container {
background-color: white;
}
#col1.impact, #col2.impact, #col3.impact {
background-color: #ddd;
.controls {
background-color: #ddd;
}
}
@colorLinkDefault: #049baf;
@colorTextDefault: #222222;
@colorOk: #44bb77;
@colorWarning: #ffaa44;
@colorWarningHandled: #ffcc66;
@colorCritical: #ff5566;
@colorCriticalHandled: #ff99aa;
@colorUnknown: #dd66ff;
@colorUnknownHandled: #ee99ff;
@colorPending: #77aaff;
@colorInvalid: #999;
@colorUnreachable: #dd66ff;
@colorUnreachableHandled: #ee99ff;

View File

@ -0,0 +1,237 @@
#layout {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
#header {
position: fixed;
top: 0;
left: 0;
right: 0;
}
#sidebar {
width: 13em;
position: fixed;
left: 0;
top: 3.6em;
bottom: 0;
}
#main {
position: fixed;
left: 13em;
top: 3.6em;
right: 0;
bottom: 0;
}
#layout.fullscreen #header {
display: none;
}
#layout.fullscreen #sidebar {
display: none;
}
#layout.fullscreen #main {
left: 0;
top: 0;
}
/* tmp */
#main > .container {
width: 100%;
height: 100%;
overflow: auto;
float: left;
}
#layout.twocols #main > .container {
width: 50%;
}
/*#layout.twocols #main > .container {*/
#layout.twocols #main .container {
/* width: 100%;*/
/* font-size: 0.9em; */
}
/* #layout.twocols #main > .container > .controls {*/
#layout.twocols #main .container > .controls {
width: 100%;
/* font-size: 0.9em; */
}
.container > div {
/* padding: 0 1.5% 0 1.5%; */
padding: 0;
}
.container .controls {
top: 0;
z-index: 1;
background-color: white;
padding: 0;
}
.controls h1 {
font-size: 1.5em;
margin-bottom: 0.2em;
border-bottom: 1px solid black;
}
.container .fake-controls {
padding: 0;
}
.container .controls .pagination {
display: inline;
}
#main .dashboard {
padding: 0;
}
.dashboard > div.container {
font-size: 0.9em;
vertical-align: top;
width: 48.5%;
display: inline-block;
padding: 0;
margin-top: 1em;
margin-left: 1%;
}
.dashboard > div.container td.state {
font-size: 1em;
width: 5em;
}
.dashboard > div.container h1 {
line-height: 2em;
font-size: 1em;
padding-left: 1em;
background-color: #555;
color: white;
border: none;
border-radius: 0.2em;
-moz-border-radius: 0.2em;
-webkit-border-radius: 0.2em;
}
.dashboard > div.container h1 a {
text-decoration: none;
color: inherit;
}
.dashboard > div.container h1 a:hover {
text-decoration: underline;
}
#layout.twocols .dashboard > div.container {
width: 96%;
margin-left: 2%;
margin-right: 2%;
}
.content {
padding: 1em;
}
/* Not growing larger than 3840px at 1em=16px right now */
@media screen and (min-width: 240em) {
#main {
width: 227em;
}
#header {
width: 240em;
}
/*
.container {
background-color: red;
}
*/
}
@media screen and (min-width: 100em) {
.dashboard > div.container {
width: 32%;
margin-left: 1%;
margin-right: 0;
}
}
@media screen and (max-width:72em) {
#layout {
font-size: 0.8em;
}
}
@media screen and (max-width: 47em) {
.dashboard > div.container {
width: 98%;
margin-left: 1%;
margin-right: 1%;
}
#layout.twocols {
#main > .container {
width: 99%;
}
#col1 {
display: none;
}
}
}
@media screen and (max-width: 36em) {
#sidebar {
display: none;
}
#logo img {
/* TODO: Quickfix, this needs improvement */
width: 0 !important;
top: -100px;
position: absolute;
}
#main {
left: 0;
}
}
@media screen and (min-width: 24em) and (max-width: 62em) {
/*
#layout .dashboard > div.container {
width: 96%;
margin-left: 2%;
margin-right: 2%;
}
*/
}
@media screen and (min-width: 48em) and (max-width: 62em) {
/* #main > .container { */
/*
#main .container {
font-size: 0.9em;
}
*/
/* TEST
.container {
background-color: blue;
}
*/
}

View File

@ -1,50 +1,67 @@
body.login {
position:absolute;
left:0px;
top:0px;
bottom:0px;
right:0px;
overflow:hidden;
.login .logo {
background-color: #555;
-moz-background-image: linear-gradient(to bottom, #333, #555);
-ms-background-image: linear-gradient(to bottom, #333, #555);
-o-background-image: linear-gradient(to bottom, #333, #555);
-webkit-background-image: linear-gradient(to bottom, #333, #555);
background-image: linear-gradient(to bottom, #333, #555);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 60%;
border-bottom: 1px solid #333;
text-align: center;
}
.logo-container {
background-color: #666666;
background-image: linear-gradient(to bottom, #444444, #666666);
-ms-background-image: linear-gradient(to bottom, #444444, #666666);
-webkit-background-image: linear-gradient(to bottom, #444444, #666666);
-moz-background-image: linear-gradient(to bottom, #444444, #666666);
-o-background-image: linear-gradient(to bottom, #444444, #666666);
position:absolute;
top:0px;
bottom:60%;
left:0px;
right:0px;
border-bottom:1px solid black;
.login .image {
position: absolute;
bottom: 1em;
left: 0px;
right: 0px;
text-align: center;
}
.image-container {
position:absolute;
bottom:1em;
left:0px;
right:0px;
text-align:center;
}
}
.login .image img {
width: 400px;
}
.form-container {
position:absolute;
top:45%;
left:0px;
bottom:0px;
right:0px;
border-bottom:1px solid black;
.login .form {
position: absolute;
font-size: 0.9em;
top: 42%;
left: 0;
bottom: 0;
right: 0;
}
overflow:auto;
overflow-x:hidden;
.login .form h1 {
text-align: left;
font-size: 1.5em;
margin-left: auto;
margin-right: auto;
width: 12em;
color: @colorTextDefault;
}
}
.login .form label {
display: none;
}
.login form {
margin-left: auto;
margin-right: auto;
width: 20em;
}
.login form input {
width: 100%;
padding: 0.5em;
}
.login .footer {
font-size: 0.9em;
text-align: center;
}
.footer {
font-size:0.7em;
text-align:center;
}
}

View File

@ -0,0 +1,131 @@
code {
background-color: #eee;
border: 1px solid #ddd;
padding: 1em;
display: block;
}
p code {
display: inline;
padding: 0.3em;
}
a {
color: #39a;
}
/** 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;
}
#notifications > li.warning {
background-color: @colorWarningHandled;
}
#notifications > li.error {
background-color: @colorCritical;
background-image: url(../img/icons/error_inv.png);
background-repeat: no-repeat;
background-position: 1em center;
}
/** END of Notifications **/
/* TODO: Remove once there is no more module container */
.container > div > pre {
margin: 1em;
}
.pull-right {
float: right;
}
table.avp {
table-layout: fixed;
width: 100%;
font-size: 0.9em;
}
table.avp a {
color: black;
text-decoration: underline;
}
table.avp th {
text-align: right;
margin: 0;
width: 11em;
vertical-align: top;
line-height: 2em;
}
table.avp td {
line-height: 2em;
margin: 0;
word-break: break-all;
vertical-align: top;
padding: 0em 0em 0em 0.5em;
}
.content table.avp dd, .content table.avp dd {
margin: 0;
padding: 0;
}
table.avp a {
color: @colorLinkDefault;
text-decoration: none;
}
table.avp a:hover {
text-decoration: underline;
}
/* Definitively monitoring-only: */
table.objectstate {
margin: 1em;
width: 100%;
border-collapse: separate;
border-spacing: 0.2em;
}
table.objectstate td {
font-size: 1.2em;
line-height: 1.5em;
padding-left: 1em;
}
table.objectstate tr.state td.state {
font-size: 1em;
width: 9em;
text-align: center;
padding-left: 0;
border-radius: 0;
}
table.objectstate tr.state.handled td.state {
}
table.perfdata {
min-width: 24em;
font-size: 0.9em;
}
table.perfdata th {
white-space: nowrap;
padding: 0;
text-align: left;
padding-right: 0.5em;
}

View File

@ -1,478 +0,0 @@
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
@orange : #ff3300;
@white : white;
@black : #262625;
@petrol : #049baf;
@lightgrey : #dddddd;
@darkgrey : #555555;
/* =========================================================================
Default elements
========================================================================= */
html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
overflow-y: scroll;
}
body {
margin: 0;
color: @black;
font-family: "Lucida Grande","Lucida Sans Unicode",Verdana,Helvetica,Arial,sans-serif;
font-size: 16px;
padding-top: 51px;
}
p {
line-height: 18px;
}
/* =========================================================================
Load Indicator
========================================================================= */
.load-indicator .mask {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: @darkgrey;
opacity: 0.3;
z-index: 998;
}
.load-indicator .label {
position: absolute;
top: 0;
left: 0;
color: @black;
background-color: @white;
font-weight: normal;
z-index: 999;
border: none;
}
/* =========================================================================
Common elements
========================================================================= */
.label-horizontal {
display: inline;
font-weight: normal;
}
.label-configuration {
cursor: pointer;
}
.inline-image {
display: inline-block;
width: 16px;
height: 16px;
background: @lightgrey center center no-repeat;
}
.small-row {
font-size: 12px;
line-height: 16px;
display: block;
font-weight: normal;
}
.inline-form {
display: inline;
}
.gap {
margin-bottom: 15px;
}
/* =========================================================================
Bootstrap overrides
========================================================================= */
.input-group-addon {
padding: 4px 12px;
}
.glyphicon-arrow-right {
background: transparent url("@{baseurl}/img/icons/next.png") center center no-repeat;
display: inline-block;
width: 16px;
height: 16px;
text-indent: -999px;
}
.glyphicon-arrow-right:before {
}
.glyphicon-arrow-left {
background: transparent url("@{baseurl}/img/icons/prev.png") center center no-repeat;
display: inline-block;
width: 16px;
height: 16px;
text-indent: -999px;
}
.glyphicon-arrow-left:before {
}
/* =========================================================================
Icinga Logo
========================================================================= */
.icinga-logo {
background: transparent url("@{baseurl}/img/logo_icinga-inv.png") center center no-repeat;
width: 94px;
height: 33px;
display: block;
text-indent: -999px;
margin: 8px 0 0 8px;
}
/* =========================================================================
Links
========================================================================= */
a {
color: @petrol;
text-decoration: none;
}
a.button {
height: 30px;
display: block;
}
a.btn-small {
height: 25px;
display: inline-block;
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
color: @petrol;
text-decoration: underline;
}
/* ==========================================================================
Typography
========================================================================== */
/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari 5, and Chrome.
*/
h1 {
color: @black;
font-size: 20px;
}
h2 {
color: @black;
font-size: 16px;
}
p {
margin-top: 0;
}
/* ==========================================================================
Tables
========================================================================== */
table, th, td {
text-align: left;
vertical-align: top;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
th {
font-weight: bold;
font-size: 18px;
padding: 8px 8px 10px 8px;
border-bottom: 2px solid @lightgrey;
}
.table-detail th {
font-size: 16px;
border-top: 0;
}
.table-detail thead > tr > th, .table tbody > tr > th,
.table-detail tbody > tr > td, .table tfoot > tr > td {
border-top: 0 !important;
}
.table-detail > thead {
border-top: 0 !important;
}
td {
padding: 8px 10px 8px 8px !important;
border-bottom: 1px dotted @lightgrey !important;
border-top: none;
}
.badge-container {
display: block;
overflow: hidden;
}
.badge {
background-color: @white;
border-radius: 2px;
color: @orange;
display: inline-block;
font-size: 12px;
font-weight: bold;
line-height: 1;
min-width: 10px;
padding-bottom: 3px;
padding-left: 10px;
padding-right: 10px;
padding-top: 3px;
text-align: center;
vertical-align: baseline;
white-space: nowrap;
border: 1px solid @orange;
}
.badge a,
.badge a:active,
.badge a:hover,
.badge:hover {
color: @orange !important;
display: block !important;
}
/* ==========================================================================
Forms
========================================================================== */
.form-inline .form-group {
display: inline-block;
margin-bottom: 0;
vertical-align: middle;
}
.form-group {
margin-bottom: 15px;
}
label {
display: inline-block;
font-weight: bold;
margin-bottom: 5px;
}
.input-sm {
border-radius: 3px;
font-size: 16px;
padding: 5px;
}
.form-control {
background-color: @white;
border: 1px solid @lightgrey;
border-radius: 4px;
padding: 5px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
color: @darkgrey;
display: block;
vertical-align: middle;
width: 100%;
}
select.input-sm {
}
/* ==========================================================================
Buttons
========================================================================== */
.button {
text-align: center;
padding: 3px;
border-width: 1px;
border-style: solid;
border-radius: 3px;
}
.btn-common {
border-color: @lightgrey;
color: @black;
background: rgb(255,255,255); /* Old browsers */
background: -moz-linear-gradient(top, rgb(255,255,255) 1%, rgb(245,245,245) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,rgb(255,255,255)), color-stop(100%,rgb(245,245,245))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* W3C */
}
.panel-row > a:hover,
.btn-common:hover {
border-color: @black !important;
color: @black !important;
text-decoration: none;
}
.btn-cta {
border-color: @petrol;
color: @petrol;
background: rgb(255,255,255); /* Old browsers */
background: -moz-linear-gradient(top, rgb(255,255,255) 1%, rgb(245,245,245) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,rgb(255,255,255)), color-stop(100%,rgb(245,245,245))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgb(255,255,255) 1%,rgb(245,245,245) 100%); /* W3C */
}
.btn-small {
width: 25px;
height: 25px;
display: inline-block;
}
.btn-wide {
width: 100%;
display: block;
}
.btn-half-left {
float: left;
width: 48%;
}
.btn-half-right {
float: right;
width: 48%;
}
/* ==========================================================================
Details Panel
========================================================================== */
.panel-heading {
border-bottom: 0;
margin-bottom: 0px !important;
padding-left: 5px;
padding-bottom: 3px;
padding-top: 5px;
overflow: hidden;
border-radius: 0;
}
.panel-hostname {
font-weight: bold;
}
.separator {
border-top: 2px solid @lightgrey;
border-bottom: 0;
margin: 0;
height: 2px;
}
.panel-header-status {
font-weight: normal;
}
.panel-row {
display: block;
margin-bottom: 10px;
overflow: hidden;
border-bottom: 1px dotted @lightgrey;
padding-bottom: 10px;
}
.panel-label {
float: left;
padding-right: 10px;
width: 30%;
clear: left;
}
.panel-content {
float: left;
padding-right: 10px;
display: inline-block;
max-width: 40%;
}
.panel-button {
float: right;
display: inline-block;
overflow: hidden;
}
.panel-body {
}
.dashboard-component {
border: 1px solid @lightgrey;
float:left;
width:45%;
padding:1%;
margin:1%;
}
.dashboard-component.row {
width:98%;
}
.pagination {
font-size: 11px;
}

View File

@ -1,9 +1,6 @@
#menu {
background: #999;
}
#menu a {
color: #121212;
outline: 0;
}
#menu .separator {
@ -19,6 +16,15 @@
border-bottom: 2em solid #888;
}
#menu > ul > li > ul {
display: none;
}
#menu > ul > li.active > ul {
display: block;
}
#menu > ul > li.active {
background-color: white;
padding-left: 0.5em;
@ -26,12 +32,25 @@
margin-right: 0;
}
#menu > ul > li > a {
text-shadow: #555 -1px 1px 0px;
}
#menu > ul > li.active > a {
color: #121212;
text-shadow: none;
}
#menu > ul > li.active li.active a {
color: #121212;
}
#menu > ul > li.active li a:hover {
text-decoration: underline;
}
#menu > ul > li {
border-bottom: 0.12em solid #888;
border-bottom: 1px solid #888;
}
#menu > ul > li li {
@ -71,6 +90,71 @@
}
#menu ul ul li a {
line-height: 1em;
margin-bottom: 1em;
line-height: 1.2em;
padding-bottom: 1em;
}
#menu > ul > li {
margin: 0 0 0 0.5em;
}
#menu > ul > li.active {
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
#menu input.search {
margin: 0 0 0 0.5em;
padding: 0 0.5em 0 2.5em;
border: none;
width: 13em;
border-radius: 0;
height: 2.5em;
display: block;
outline: none;
background-color: transparent;
background-image: url('../img/icons/search.png');
background-repeat: no-repeat;
background-position: 0.7em center;
color: #f5f5f5;
text-shadow: -1px 1px 0 #555555;
border-bottom: 1px solid #888;
}
#menu input.search:-ms-input-placeholder {
color: #f5f5f5;
}
#menu input.search::-webkit-input-placeholder {
color: #f5f5f5;
}
#menu input.search::-moz-placeholder {
color: #f5f5f5;
opacity: 1;
}
#menu input.search.active {
background-color: white;
color: #121212;
text-shadow: none;
padding-left: 3em;
margin-left: 0;
background-position: 1.2em center;
}
#menu input.search.active::-moz-placeholder {
color: #999;
}
#menu input.search.active::-webkit-input-placeholder {
color: #999;
}
#menu input.search.active:-ms-input-placeholder {
color: #999;
}
input:focus { outline: none; }

View File

@ -0,0 +1,372 @@
/* Special tables and states */
table.colors {
font-size: 0.8em;
width: 98%;
margin: 0 1%;
}
table.colors td {
text-align: center;
vertical-align: middle;
width: 10%;
height: 1.6em;
font-weight: normal;
border: 0.079em solid white;
}
/* Action table */
table.action {
border-collapse: separate;
border-spacing: 0.3em;
width: 98%;
table-layout: fixed;
margin: 0;
}
table.action tr {
/*border-bottom: 0.079em solid transparent;*/
}
table.action th {
text-align: left;
overflow: hidden;
}
table.action.wide td {
line-height: 2.5em;
}
table.action td {
padding: 0.3em 0.5em 0.3em 0.5em;
line-height: 1.5em;
border-bottom: 1px solid #dde;
overflow: hidden;
}
.dashboard table.action td {
line-height: 1.2em;
padding: 0.2 0.4em 0.2em 0.5em;
}
table.action td .pluginoutput {
font-size: 0.8em;
line-height: 1.2em;
padding: 0;
margin: 0;
}
table.action td a {
color: inherit;
text-decoration: none;
}
table.action td a:hover {
text-decoration: underline;
}
table.action div.inlinepie {
margin: 0.5em 0.25em 0.5em 0.25em;
}
.dashboard table.action div.inlinepie {
margin: 0em 0.25em 0em 0.25em;
}
/* END of Action table */
/* Table behaviour */
tr[href] {
cursor: pointer;
}
/* End of table behaviour */
table.action td.state {
font-size: 0.7em;
text-align: center;
}
table.action td.timesince {
width: 3.5em;
}
/* State row behaviour */
tr.state img.icon {
/* TODO: 1em? */
height: 16px;
width: 16px;
float: right;
}
tr.state a {
font-weight: bold;
}
tr.state a.active {
text-decoration: underline;
}
tr.state.new td.state {
font-weight: bold;
}
tr.state td.state strong {
font-size: 1.2em;
}
tr.state td.state {
width: 9em;
color: white;
border-bottom: none;
}
tr.state.handled td.state, tr.state.ok td.state, tr.state.up td.state, tr.state.pending td.state {
border-left-style: solid;
border-left-width: 1.5em;
padding-left: 0em;
padding-right: 0.5em;
color: black;
background-color: transparent;
}
tr[href]:hover, tr[href].active {
background-color: #ddd;
color: black;
}
tr.state[href]:hover, tr.state[href].active td.state {
}
tr.state.ok td.state, tr.state.up td.state {
border-left-color: @colorOk;
}
tr.state.warning td.state {
background-color: @colorWarning;
}
tr.state.warning.handled td.state {
border-left-color: @colorWarningHandled;
background-image: none;
}
tr.state.critical td.state, tr.state.down td.state {
background-color: @colorCritical;
}
tr.state.critical.handled td.state, tr.state.down.handled td.state {
border-left-color: @colorCriticalHandled;
background-image: none;
}
tr.state.unknown td.state {
background-color: @colorUnknown;
}
tr.state.unknown.handled td.state {
border-left-color: @colorUnknownHandled;
background-image: none;
}
tr.state.pending td.state {
border-left-color: @colorPending;
}
tr.state.invalid td.state {
background-color: @colorInvalid;
}
tr.state.handled td.state {
color: inherit;
background-color: transparent;
}
tr.state.unreachable td.state {
background-color: @colorUnreachable;
}
tr.state.unreachable.handled td.state {
border-left-color: @colorUnreachableHandled;
background-image: none;
}
/* END of special tables and states */
/* Generic colors */
a.critical {
color: @colorCritical;
}
/* END of Generic colors */
/* Been here before: */
/*
.state .ok, td.state.ok {
background-color: #44BB77;
color: white;
}
.state .ok:hover, td.state.ok:hover {
color: #44BB77;
background-color: white;
cursor: pointer;
}
.state .warning, td.state.warning {
color: white;
background-color: #FF8844;
}
.state .warning:hover, td.state.warning:hover {
color: #FF8844;
background-color: white;
cursor: pointer;
}
.state .warning.handled, td.state.warning.handled {
color: white;
background-color: #FFBB55;
}
.state .warning.handled:hover, td.state.warning.handled:hover {
color: #FF8855;
background-color: white;
cursor: pointer;
}
.state .critical, td.state.critical {
color: white;
background-color: #FF5566;
}
.state .critical.handled, td.state.critical.handled {
background-color: #FF99aa;
}
.state .unknown, td.state.unknown {
color: white;
background-color: #DD66FF;
}
.state .unknown.handled, td.state.unknown.handled {
background-color: #EE99FF;
}
.state .pending, td.state.pending {
color: white;
background-color: #77AAFF;
}
*/
/* Generic span.state */
span.state {
color: white;
border-radius: 0.5em;
-moz-border-radius: 0.5em;
padding: 0.3em 0.5em 0.3em 0.5em;
margin: 0.2em 0.5em 0.2em 0.5em;
}
span.state.ok, span.state.up {
background-color: @colorOk;
}
span.state.warning {
background-color: @colorWarning;
}
span.state.warning.handled {
background-color: @colorWarningHandled;
}
span.state.critical, span.state.down {
background-color: @colorCritical;
}
span.state.critical.handled, span.state.down.handled {
background-color: @colorCriticalHandled;
}
span.state.unknown, span.state.unreachable {
background-color: @colorUnknown;
}
span.state.unknown.handled, span.state.unreachable.handled {
background-color: @colorUnknownHandled;
}
span.state.invalid {
background-color: @colorInvalid;
}
.summary a {
color: white;
text-decoration: none;
}
.summary {
font-size: 0.85em;
vertical-align: top;
text-align: left;
}
.summary td {
vertical-align: top;
}
.summary > span.state {
border: 1px solid #555;
color: black;
}
.summary strong a {
color: black;
}
.summary span.state.handled a {
color: #333;
}
.summary span.state {
width: 26em;
vertical-align: top;
text-align: center;
display: inline-block;
}
.summary span.state span.state {
width: 12em;
font-size: 0.9em;
}
.summary span.state span.state span.state {
width: 12em;
}
span.state a {
white-space: nowrap;
}
span.state.handled {
color: #333;
}
span.state a.active {
text-decoration: underline;
}
/* End of generic span.state */
.controls {
font-size: 0.9em;
}
.controls a {
color: black;
}

View File

@ -1,206 +0,0 @@
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
@white: #ffffff;
@lightgrey : #dddddd;
/* =========================================================================
Icinga Navigation
========================================================================= */
.navbar {
background-image: linear-gradient(to bottom, #444444, #333333);
}
.navigation-tile-mixin {
border-style: solid;
border-width: 1px;
padding: 3px 5px 3px 5px;
border-radius: 3px;
font-size: 13px;
}
.nav-stacked > li + li {
margin-left: 0;
margin-top: 0;
}
.nav-stacked {
}
.icinga-subnavigation {
list-style: none;
}
.nav-stacked > li {
padding-left: 4px;
padding-top: 10px;
padding-bottom: 10px;
border-bottom: 1px solid @lightgrey;
border-right: 1px solid @lightgrey;
font-size: 11px;
background-color: rgb(248, 248, 248);
background-image: linear-gradient(rgb(255, 255, 255) 0px, rgb(248, 248, 248) 100%);
}
.nav-stacked > li > a {
letter-spacing: 1px;
padding-top: 0px;
padding-bottom: 3px;
}
.nav-stacked > li:first-child {
}
.submenu {
background-image: none;
padding-left: 15px;
}
.submenu > a {
color: red;
}
.active > a{
font-weight: bold;
text-decoration: underline;
}
.icinga-subnavigation > li {
padding-top: 8px;
padding-bottom: 8px;
border-bottom: 1px solid @lightgrey;
border-right: 1px solid @lightgrey;
}
ul.icinga-subnavigation {
border-bottom: 1px solid @lightgrey;
margin-left: 0;
padding-left: 15px;
}
.icinga-subnavigation > li:last-child {
padding-top: 8px;
padding-bottom: 8px;
border-bottom: 0;
}
.nav-stacked > li > a,
.icinga-subnavigation > li > a {
padding-left: 20px;
padding-right: 3px;
/* border-left: 6px solid @petrol; */
display: inline-block;
}
.nav-stacked > li > a.nav-notification,
.icinga-subnavigation > li > a.nav-notification {
border-left: 6px solid red !important;
}
.nav-stacked > li > a:hover,
.icinga-subnavigation > li > a:focus {
/* font-weight: bold;*/
background-color: transparent; !important;
display: inline-block;
}
.nav-stacked > li:hover,
.nav-stacked > li:focus,
.icinga-subnavigation > li:hover,
.icinga-subnavigation > li:focus {
background-color: @white;
}
.nav-stacked > li.active,
.icinga-subnavigation > li.active {
background: none;
border-right: none;
}
.badge-container-nav {
display: inline-block;
overflow: hidden;
padding-top: 0;
margin-bottom: 5px;
}
.badge-nav {
background-color: @white;
border-radius: 2px;
color: @orange;
display: inline-block;
font-size: 12px;
font-weight: bold;
line-height: 1;
min-width: 10px;
padding-bottom: 3px;
padding-left: 7px;
padding-right: 7px;
padding-top: 3px;
text-align: center;
vertical-align: baseline;
white-space: nowrap;
border: 1px solid @orange;
}
.badge-container-subnav {
position: absolute;
overflow: hidden;
padding-top: 0;
padding-bottom;
margin-left: 2px;
margin-top: -8px;
}
.badge-subnav {
background-color: @white;
border-radius: 2px;
color: @orange;
display: inline-block;
font-size: 10px;
font-weight: bold;
line-height: 1;
min-width: 10px;
padding-bottom: 2px;
padding-left: 5px;
padding-right: 5px;
padding-top: 2px;
text-align: center;
vertical-align: baseline;
white-space: nowrap;
border: 1px solid @orange;
}
.icinga-navbar-search-container {
border-left: 1px solid #ddd;
padding-left: 15px;
margin-top: 12px;
}
.nav > .subclass {
text-decoration: underline;
font-size: 16px;
}

Some files were not shown because too many files have changed in this diff Show More