Merge branch 'master' into feature/organize-headings-7976

This commit is contained in:
Marius Hein 2015-02-17 15:21:29 +01:00
commit d3c79dae32
48 changed files with 405 additions and 241 deletions

View File

@ -0,0 +1,81 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Forms;
use Icinga\Application\Logger;
use Icinga\User\Preferences;
use Icinga\Web\Form;
use Icinga\Web\Notification;
use Icinga\Web\Session;
use Icinga\Web\Url;
/**
* Form class to adjust user auto refresh preferences
*/
class AutoRefreshForm extends Form
{
/**
* Initialize this form
*/
public function init()
{
$this->setName('form_auto_refresh');
}
/**
* Adjust preferences and persist them
*
* @see Form::onSuccess()
*/
public function onSuccess()
{
/** @var Preferences $preferences */
$preferences = $this->getRequest()->getUser()->getPreferences();
$icingaweb = $preferences->get('icingaweb');
if ((bool) $preferences->getValue('icingaweb', 'auto_refresh', true) === false) {
$icingaweb['auto_refresh'] = '1';
$notification = $this->translate('Auto refresh successfully enabled');
} else {
$icingaweb['auto_refresh'] = '0';
$notification = $this->translate('Auto refresh successfully disabled');
}
$preferences->icingaweb = $icingaweb;
Session::getSession()->user->setPreferences($preferences);
Notification::success($notification);
$this->getResponse()->setHeader('X-Icinga-Rerender-Layout', 'yes');
$this->setRedirectUrl(Url::fromRequest()->without('renderLayout'));
}
/**
* @see Form::createElements()
*/
public function createElements(array $formData)
{
$preferences = $this->getRequest()->getUser()->getPreferences();
if ((bool) $preferences->getValue('icingaweb', 'auto_refresh', true) === false) {
$value = $this->translate('Enable auto refresh');
} else {
$value = $this->translate('Disable auto refresh');
}
$this->addElements(array(
array(
'button',
'btn_submit',
array(
'ignore' => true,
'type' => 'submit',
'value' => $value,
'decorators' => array('ViewHelper'),
'escape' => false,
'class' => 'link-like'
)
)
));
}
}

View File

@ -185,6 +185,17 @@ class PreferenceForm extends Form
)
);
$this->addElement(
'checkbox',
'auto_refresh',
array(
'required' => false,
'label' => $this->translate('Enable auto refresh'),
'description' => $this->translate('This option allows you to enable or to disable the global page content auto refresh'),
'value' => 1
)
);
if ($this->store) {
$this->addElement(
'submit',

View File

@ -7,20 +7,6 @@ use Icinga\Authentication\Manager as Auth;
if (Auth::getInstance()->isAuthenticated()): ?>
<div id="header">
<div class="skip-links">
<h2 class="sr-only"><?= t('Accessibility Skip Links'); ?></h2>
<ul>
<li>
<a tabindex="0" href="#main"><?= t('Skip to Content'); ?></a>
</li>
<li>
<a tabindex="0" href="#search"><?= t('Skip to Search'); ?></a>
</li>
<li>
<a tabindex="0" href="#navigation"><?= t('Skip to Navigation'); ?></a>
</li>
</ul>
</div>
<ul id="notifications"><?php
$moduleName = $this->layout()->moduleName;
@ -42,8 +28,9 @@ if ($notifications->hasMessages()) {
}
}
?></ul>
<div id="logo" data-base-target="_main"><a href="<?= $this->href('/dashboard') ?>"><img aria-hidden="true" src="<?= $this->href('img/logo_icinga-inv.png') ?>" class="logo" alt="<?= t('Dashboard') ?>" /></a>
</div>
<div id="logo" data-base-target="_main">
<img aria-hidden="true" src="<?= $this->href('img/logo_icinga-inv.png') ?>" class="logo" alt="<?= t('Dashboard') ?>" />
</div>
</div>
<?php if (!$this->layout()->isIframe): ?>

View File

@ -10,6 +10,17 @@ if (! $this->auth()->isAuthenticated()) {
}
?>
<div class="skip-links">
<h1 class="sr-only"><?= t('Accessibility Skip Links'); ?></h1>
<ul>
<li>
<a tabindex="0" href="#main"><?= t('Skip to Content'); ?></a>
</li>
<li>
<?= $this->layout()->autoRefreshForm ?>
</li>
</ul>
</div>
<div id="menu" data-last-update="<?= (time() - 14) ?>000" data-base-target="_main" class="container"
data-icinga-url="<?= $this->href('layout/menu') ?>" data-icinga-refresh="15">
<?= $this->partial(

View File

@ -31,7 +31,7 @@ if ( isset($pdf) )
}
</script>
<?= $this->img('img/logo_icinga_big_dark.png', array('align' => 'right', 'width' => '75')) ?>
<?= $this->img('img/logo_icinga_big_dark.png', null, array('align' => 'right', 'width' => '75')) ?>
<!--<div id="page-header">
<table>
<tr>

View File

@ -7,7 +7,7 @@
<div class="form" data-base-target="layout">
<h1><?= $this->translate('Welcome to Icinga Web 2'); ?></h1>
<?php if ($requiresSetup): ?>
<p tabindex="0" class="config-note"><?= sprintf(
<p class="config-note"><?= sprintf(
$this->translate(
'It appears that you did not configure Icinga Web 2 yet so it\'s not possible to log in without any defined '
. 'authentication method. Please define a authentication method by following the instructions in the'
@ -18,7 +18,7 @@
'</a>'
); ?></p>
<?php elseif ($requiresExternalAuth): ?>
<p tabindex="0" class="info-box"><i aria-hidden="true" class="icon-info"></i><?= $this->translate(
<p class="info-box"><?= $this->icon('icon-info'); ?><?= $this->translate(
'You\'re currently not authenticated using any of the web server\'s authentication mechanisms.'
. ' Make sure you\'ll configure such, otherwise you\'ll not be able to login.'
); ?></p>

View File

@ -20,7 +20,7 @@
</h2>
<p>
<a href="<?= $this->href('/config/createAuthenticationBackend'); ?>">
<?= $this->icon('plus', null, array('aria-hidden' => 'true')); ?><?= $this->translate('Create A New Authentication Backend'); ?>
<?= $this->icon('plus'); ?><?= $this->translate('Create A New Authentication Backend'); ?>
</a>
</p>
<h2 tabindex="-1" id="authentication-reorder" class="sr-only">

View File

@ -10,17 +10,24 @@
<?php foreach ($modules as $module): ?>
<tr>
<td>
<?php if ($module->enabled): ?>
<?= $this->icon('thumbs-up', $this->translate('Module is enabled')) ?>
<?php else: ?>
<?= $this->icon('thumbs-down', $this->translate('Module is disabled')) ?>
<?php endif ?>
<a href="<?= $this->url(
'config/module/',
array('name' => $module->name)
) ?>"><?= $this->escape($module->name); ?></a> (<?=
$module->enabled ? ($module->loaded ? $this->translate('enabled') : $this->translate('failed')) : $this->translate('disabled')
?>)
<?php if ($module->enabled && $module->loaded) {
$icon = $this->icon('thumbs-up');
$title = sprintf($this->translate('Module %s is enabled'), $module->name);
} elseif (! $module->enabled) {
$icon = $this->icon('thumbs-down');
$title = sprintf($this->translate('Module %s is disabled'), $module->name);
} else { // ! $module->loaded
$icon = $this->icon('thumbs-down');
$title = sprintf($this->translate('Module %s has failed to load'), $module->name);
}
echo $this->qlink(
$icon . $this->escape($module->name),
'config/module/',
array('name' => $module->name),
array('title' => $title),
false
); ?>
</td>
</tr>
<?php endforeach ?>

View File

@ -20,7 +20,7 @@
</h2>
<p>
<a href="<?= $this->href('/config/createresource'); ?>">
<?= $this->icon('plus', null, array('aria-hidden' => 'true')); ?> <?= $this->translate('Create A New Resource'); ?>
<?= $this->icon('plus'); ?> <?= $this->translate('Create A New Resource'); ?>
</a>
</p>
<h2 tabindex="-1" id="resource-edit-resource" class="sr-only">
@ -35,14 +35,24 @@
<?php foreach ($this->resources as $name): ?>
<tr>
<td>
<a href="<?= $this->href('config/editresource', array('resource' => $name)); ?>">
<?= $this->icon('edit'); ?> <?= $this->escape($name); ?>
</a>
<?= $this->qlink(
$this->icon('edit') . ' ' . $this->escape($name),
'config/editresource',
array('resource' => $name),
array('title' => sprintf($this->translate('Edit resource %s'), $name)),
false
); ?>
</td>
<td style="text-align: center">
<a href="<?= $this->href('config/removeresource', array('resource' => $name)); ?>">
<?= $this->icon('cancel'); ?>
</a>
<td>
<center>
<?= $this->qlink(
$this->icon('cancel'),
'config/removeresource',
array('resource' => $name),
array('title' => sprintf($this->translate('Remove resource %s'), $name)),
false
); ?>
</center>
</td>
</tr>
<?php endforeach; ?>

View File

@ -1,5 +1,3 @@
<?php
?>
<div class="controls">
<?= $this->tabs ?>
</div>
@ -25,9 +23,13 @@
<?= $pane->getName(); ?>
</th>
<th>
<a href="<?= $this->href('dashboard/remove-pane', array('pane' => $pane->getName())); ?>">
<?= $this->icon('cancel'); ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'dashboard/remove-pane',
array('pane' => $pane->getName()),
array('title' => sprintf($this->translate('Remove pane %s'), $pane->getName())),
false
); ?>
</th>
</tr>
<?php $dashlets = $pane->getDashlets(); ?>
@ -50,9 +52,13 @@
<a href="<?= $this->href($dashlet->getUrl()); ?>"><?= $dashlet->getUrl(); ?></a>
</td>
<td>
<a href="<?= $this->href('dashboard/remove-dashlet', array('pane' => $pane->getName(), 'dashlet' => $dashlet->getTitle())); ?>">
<?= $this->icon('cancel'); ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'dashboard/remove-dashlet',
array('pane' => $pane->getName(), 'dashlet' => $dashlet->getTitle()),
array('title' => sprintf($this->translate('Remove dashlet %s from pane %s'), $dashlet->getTitle(), $pane->getName())),
false
); ?>
</td>
</tr>
<?php endforeach; ?>

View File

@ -1,4 +1,4 @@
<form id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>">
<form data-base-target="_self" id="<?= $form->getName(); ?>" name="<?= $form->getName(); ?>" enctype="<?= $form->getEncType(); ?>" method="<?= $form->getMethod(); ?>" action="<?= $form->getAction(); ?>">
<table class="action">
<thead>
<th>Backend</th>
@ -10,24 +10,50 @@
<?php for ($i = 0; $i < count($backendNames); $i++): ?>
<tr>
<td class="action">
<a href="<?= $this->href('config/editAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('edit'); ?> <?= $this->escape($backendNames[$i]); ?>
</a>
<?= $this->qlink(
$this->icon('edit') . ' ' . $this->escape($backendNames[$i]),
'config/editAuthenticationBackend',
array('auth_backend' => $backendNames[$i]),
array('title' => sprintf($this->translate('Edit authentication backend %s'), $backendNames[$i])),
false
); ?>
</td>
<td>
<a href="<?= $this->href('config/removeAuthenticationBackend', array('auth_backend' => $backendNames[$i])); ?>">
<?= $this->icon('cancel', $this->translate('Remove')); ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'config/removeAuthenticationBackend',
array('auth_backend' => $backendNames[$i]),
array('title' => sprintf($this->translate('Remove authentication backend %s'), $backendNames[$i])),
false
); ?>
</td>
<td>
<?php if ($i > 0): ?>
<button type="submit" name="backend_newpos" value="<?= sprintf('%s|%s', $backendNames[$i], $i - 1); ?>">
<?= $this->icon('up-big', $this->translate('Move up in authentication order')); ?>
<button type="submit" name="backend_newpos" value="<?= sprintf(
'%s|%s',
$backendNames[$i],
$i - 1
); ?>" title="<?= $this->translate(
'Move up in authentication order'
); ?>" aria-label="<?= sprintf(
$this->translate('Move authentication backend %s upwards'),
$backendNames[$i]
); ?>">
<?= $this->icon('up-big'); ?>
</button>
<?php endif; ?>
<?php if ($i + 1 < count($backendNames)): ?>
<button type="submit" name="backend_newpos" value="<?= sprintf('%s|%s', $backendNames[$i], $i + 1); ?>">
<?= $this->icon('down-big', $this->translate('Move down in authentication order')); ?>
<button type="submit" name="backend_newpos" value="<?= sprintf(
'%s|%s',
$backendNames[$i],
$i + 1
); ?>" title="<?= $this->translate(
'Move down in authentication order'
); ?>" aria-label="<?= sprintf(
$this->translate('Move authentication backend %s downwards'),
$backendNames[$i]
); ?>">
<?= $this->icon('down-big'); ?>
</button>
<?php endif; ?>
</td>

View File

@ -63,13 +63,13 @@
<td><?= $this->escape($role->users) ?></td>
<td><?= $this->escape($role->groups) ?></td>
<td>
<a href="<?= $this->url('roles/remove', array('role' => $name)) ?>"
title="<?= sprintf(
$this->translate('Remove role %s'),
$name
) ?>">
<?= $this->icon('cancel') ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'roles/remove',
array('role' => $name),
array('title' => sprintf($this->translate('Remove role %s'), $name)),
false
); ?>
</td>
</tr>
<?php endforeach ?>

View File

@ -10,22 +10,9 @@
.icon-star:before {
content: "★";
}
.sr-only {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
</style>
</head>
<body>
<span tabindex="0">
<i class="icon-star" aria-hidden="true"></i>
<span class="sr-only">Top rated article</span>
</span>
<i role="img" class="icon-star" aria-label="Top rated article" title="Top rated article"></i>
</body>
</html>
</html>

View File

@ -10,6 +10,7 @@ use Icinga\Authentication\Manager;
use Icinga\Exception\IcingaException;
use Icinga\Exception\ProgrammingError;
use Icinga\File\Pdf;
use Icinga\Forms\AutoRefreshForm;
use Icinga\Security\SecurityException;
use Icinga\Util\Translator;
use Icinga\Web\Notification;
@ -379,6 +380,16 @@ class ActionController extends Zend_Controller_Action
}
}
/**
* @see Zend_Controller_Action::preDispatch()
*/
public function preDispatch()
{
$form = new AutoRefreshForm();
$form->handleRequest();
$this->_helper->layout()->autoRefreshForm = $form;
}
/**
* Detect whether the current request requires changes in the layout and apply them before rendering
*
@ -399,6 +410,10 @@ class ActionController extends Zend_Controller_Action
$layout->benchmark = $this->renderBenchmark();
}
}
if ((bool) $user->getPreferences()->getValue('icingaweb', 'auto_refresh', true) === false) {
$this->disableAutoRefresh();
}
}
if ($req->getParam('format') === 'pdf') {

View File

@ -25,7 +25,7 @@ class NoScriptApply extends Zend_Form_Decorator_Abstract
{
if ($content) {
$content .= '<noscript><button name="noscript_apply" style="margin-left: 0.5em;" type="submit" value="1">'
. Icinga::app()->getViewRenderer()->view->icon('refresh.png', null, array('aria-hidden' => 'true')) . '&nbsp;' . t('Apply')
. Icinga::app()->getViewRenderer()->view->icon('refresh.png') . '&nbsp;' . t('Apply')
. '</button></noscript>';
}

View File

@ -4,7 +4,6 @@
namespace Icinga\Web\Form\Element;
use DateTime;
use Icinga\Web\Form;
use Icinga\Web\Form\FormElement;
use Icinga\Web\Form\Validator\DateTimeValidator;
@ -126,10 +125,17 @@ class DateTimePicker extends FormElement
if (! parent::isValid($value, $context)) {
return false;
}
if (! $value instanceof DateTime) {
$format = $this->local === true ? 'Y-m-d\TH:i:s' : DateTime::RFC3339;
$this->setValue(DateTime::createFromFormat($format, $value));
$dateTime = DateTime::createFromFormat($format, $value);
if ($dateTime === false) {
$dateTime = DateTime::createFromFormat(substr($format, 0, strrpos($format, ':')), $value);
}
$this->setValue($dateTime);
}
return true;
}
}

View File

@ -57,14 +57,22 @@ class DateTimeValidator extends Zend_Validate_Abstract
$this->_error(self::INVALID_DATETIME_TYPE);
return false;
}
if (is_string($value)) {
$format = $this->local === true ? 'Y-m-d\TH:i:s' : DateTime::RFC3339;
if (! $value instanceof DateTime) {
$format = $baseFormat = $this->local === true ? 'Y-m-d\TH:i:s' : DateTime::RFC3339;
$dateTime = DateTime::createFromFormat($format, $value);
if ($dateTime === false) {
$format = substr($format, 0, strrpos($format, ':'));
$dateTime = DateTime::createFromFormat($format, $value);
}
if ($dateTime === false || $dateTime->format($format) !== $value) {
$this->_error(self::INVALID_DATETIME_FORMAT, DateTimeFactory::create()->format($format));
$this->_error(self::INVALID_DATETIME_FORMAT, DateTimeFactory::create()->format($baseFormat));
return false;
}
}
return true;
}
}

View File

@ -27,55 +27,68 @@ $this->addHelperFunction('url', function ($path = null, $params = null) {
return $url;
});
$this->addHelperFunction('qlink', function ($title, $url, $params = null, $properties = array(), $escape = true) use ($view) {
if (array_key_exists('title', $properties) && !array_key_exists('aria-label', $properties)) {
$properties['aria-label'] = $properties['title'];
}
$this->addHelperFunction('qlink', function ($title, $url, $params = null, $properties = array()) use ($view) {
return sprintf(
'<a href="%s"%s>%s</a>',
$view->url($url, $params),
$view->propertiesToString($properties),
$view->escape($title)
$escape ? $view->escape($title) : $title
);
});
$this->addHelperFunction('img', function ($url, array $properties = array()) use ($view) {
$this->addHelperFunction('img', function ($url, $params = null, array $properties = array()) use ($view) {
if (! array_key_exists('alt', $properties)) {
$properties['alt'] = '';
}
if (array_key_exists('title', $properties)) {
if (! array_key_exists('aria-label', $properties)) {
$properties['aria-label'] = $properties['title'];
}
} elseif (! array_key_exists('aria-hidden', $properties)) {
$properties['aria-hidden'] = 'true';
}
return sprintf(
'<img src="%s"%s />',
$view->url($url),
$view->url($url, $params),
$view->propertiesToString($properties)
);
});
$this->addHelperFunction('icon', function ($img, $title = null, array $properties = array()) use ($view) {
$isClass = strpos($img, '.') === false;
$class = null;
if ($isClass) {
$class = 'icon-' . $img;
} else {
$class = 'icon';
}
if ($title !== null) {
$properties['alt'] = $title;
$properties['title'] = $title;
}
if ($class !== null) {
if (isset($props['class'])) {
$properties['class'] .= ' ' . $class;
if (strpos($img, '.') !== false) {
if (array_key_exists('class', $properties)) {
$properties['class'] .= ' icon';
} else {
$properties['class'] = $class;
$properties['class'] = 'icon';
}
}
if ($isClass) {
return sprintf('<i %s ></i>', $view->propertiesToString($properties));
} else {
return $view->img('img/icons/' . $img, $properties);
}
if ($title !== null) {
$properties['role'] = 'img';
$properties['title'] = $title;
if (! array_key_exists('aria-label', $properties)) {
$properties['aria-label'] = $title;
}
} elseif (! array_key_exists('aria-hidden', $properties)) {
$properties['aria-hidden'] = 'true';
}
if (isset($properties['class'])) {
$properties['class'] .= ' icon-' . $img;
} else {
$properties['class'] = 'icon-' . $img;
}
return sprintf('<i %s></i>', $view->propertiesToString($properties));
});
$this->addHelperFunction('propertiesToString', function ($properties) use ($view) {

View File

@ -669,7 +669,7 @@ class FilterEditor extends AbstractWidget
. '" title="'
. $title
. '">'
. '<i class="icon-filter"></i>'
. '<i aria-hidden="true" class="icon-filter"></i>'
. '</a>';
}

View File

@ -215,9 +215,9 @@ class Tab extends AbstractWidget
if ($this->icon !== null) {
if (strpos($this->icon, '.') === false) {
$caption = $view->icon($this->icon, null, array('aria-hidden' => 'true')) . $caption;
$caption = $view->icon($this->icon) . $caption;
} else {
$caption = $view->img($this->icon, array('aria-hidden' => 'true', 'class' => 'icon')) . $caption;
$caption = $view->img($this->icon, null, array('class' => 'icon')) . $caption;
}
}
if ($this->url !== null) {

View File

@ -1,34 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
namespace Icinga\Web\Widget\Tabextension;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Url;
/**
* Tabextension that adds the basket command
*
* @TODO: Baskets are not supported in the codebase yet (Feature #4537)
*/
class BasketAction implements Tabextension
{
/**
* Applies the dashboard actions to the provided tabset
*
* @param Tabs $tabs The tabs object to extend with
*/
public function apply(Tabs $tabs)
{
$tabs->addAsDropdown(
'basket',
array(
'title' => 'URL Basket',
'url' => Url::fromPath('basket/add'),
'urlParams' => array(
'url' => Url::fromRequest()->getRelativeUrl()
)
)
);
}
}

View File

@ -41,7 +41,7 @@ EOT;
*/
private $dropdownTpl = <<< 'EOT'
<li class="dropdown">
<a href="#" class="dropdown-toggle"><i class="icon-down-open"></i></a>
<a href="#" class="dropdown-toggle"><i aria-hidden="true" class="icon-down-open"></i></a>
<ul class="dropdown-menu">
{TABS}
</ul>

View File

@ -42,11 +42,11 @@
<span>
<?php if ($this->trend->trend === 'up'): ?>
<?= $this->icon('up-open', null, array('aria-hidden' => 'true')); ?>
<?= $this->icon('up-open'); ?>
<?php elseif ($this->trend->trend === 'unchanged'): ?>
<?= $this->icon('right-open', null, array('aria-hidden' => 'true')); ?>
<?= $this->icon('right-open'); ?>
<?php else: ?>
<?= $this->icon('down-open', null, array('aria-hidden' => 'true')); ?>
<?= $this->icon('down-open'); ?>
<?php endif; ?>
</span>
</div>

View File

@ -6,7 +6,7 @@
<div class="content" data-base-target="_next">
<p>
<a href="<?= $this->href('/monitoring/config/createbackend'); ?>">
<?= $this->icon('plus', null, array('aria-hidden' => 'true')); ?> <?= $this->translate('Create New Monitoring Backend'); ?>
<?= $this->icon('plus'); ?> <?= $this->translate('Create New Monitoring Backend'); ?>
</a>
</p>
<table class="action">
@ -18,18 +18,26 @@
<?php foreach ($this->backendsConfig as $backendName => $config): ?>
<tr>
<td>
<a href="<?= $this->href('/monitoring/config/editbackend', array('backend' => $backendName)); ?>">
<?= $this->icon('edit'); ?> <?= $this->escape($backendName); ?>
</a>
<?= $this->qlink(
$this->icon('edit') . ' ' . $this->escape($backendName),
'/monitoring/config/editbackend',
array('backend' => $backendName),
array('title' => sprintf($this->translate('Edit monitoring backend %s'), $backendName)),
false
); ?>
<small>(<?= sprintf(
$this->translate('Type: %s'),
$this->escape($config->type === 'ido' ? 'IDO' : ucfirst($config->type))
); ?>)</small>
</td>
<td>
<a href="<?= $this->href('/monitoring/config/removebackend', array('backend' => $backendName)); ?>">
<?= $this->icon('cancel'); ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'/monitoring/config/removebackend',
array('backend' => $backendName),
array('title' => sprintf($this->translate('Remove monitoring backend %s'), $backendName)),
false
); ?>
</td>
</tr>
<?php endforeach; ?>
@ -38,7 +46,7 @@
<h1><?= $this->translate('Monitoring Instances') ?></h1>
<p>
<a href="<?= $this->href('/monitoring/config/createinstance'); ?>">
<?= $this->icon('plus', null, array('aria-hidden' => 'true')); ?> <?= $this->translate('Create New Instance'); ?>
<?= $this->icon('plus'); ?> <?= $this->translate('Create New Instance'); ?>
</a>
</p>
<table class="action">
@ -50,18 +58,26 @@
<?php foreach ($this->instancesConfig as $instanceName => $config): ?>
<tr>
<td>
<a href="<?= $this->href('/monitoring/config/editinstance', array('instance' => $instanceName)); ?>">
<?= $this->icon('edit'); ?> <?= $this->escape($instanceName); ?>
</a>
<?= $this->qlink(
$this->icon('edit') . ' ' . $this->escape($instanceName),
'/monitoring/config/editinstance',
array('instance' => $instanceName),
array('title' => sprintf($this->translate('Edit monitoring instance %s'), $instanceName)),
false
); ?>
<small>(<?= sprintf(
$this->translate('Type: %s'),
$config->host !== null ? $this->translate('Remote') : $this->translate('Local')
); ?>)</small>
</td>
<td>
<a href="<?= $this->href('/monitoring/config/removeinstance', array('instance' => $instanceName)); ?>">
<?= $this->icon('cancel'); ?>
</a>
<?= $this->qlink(
$this->icon('cancel'),
'/monitoring/config/removeinstance',
array('instance' => $instanceName),
array('title' => sprintf($this->translate('Remove monitoring instance %s'), $instanceName)),
false
); ?>
</td>
</tr>
<?php endforeach; ?>

View File

@ -31,21 +31,21 @@
<div>
<a href="<?= $rescheduleAllLink ?>">
<?= $this->icon('reschedule', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('reschedule'); ?>
<?= $this->translate('Reschedule host checks') ?>
</a>
</div>
<div>
<a href="<?= $downtimeAllLink ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= $this->translate('Schedule host downtimes') ?>
</a>
</div>
<div>
<a href="<?= $processCheckResultAllLink; ?>">
<?= $this->icon('reply', null, array('aria-hidden' => 'true')); ?>
<?= $this->icon('reply'); ?>
<?= $this->translate('Submit passive check results'); ?>
</a>
</div>
@ -71,7 +71,7 @@
),
$unhandledCount
) ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= sprintf(
$this->translatePlural(
'Schedule downtime for unhandled host problem',
@ -91,7 +91,7 @@
),
$unhandledCount
) ?>">
<?= $this->icon('ok', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('ok'); ?>
<?= sprintf(
$this->translatePlural(
'Acknowledge unhandled host problem',
@ -133,7 +133,7 @@
),
$inDowntimeCount
) ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= sprintf(
$this->translatePlural(
'List %u host currently in downtime',
@ -158,7 +158,7 @@
),
$commentCount
) ?>">
<?= $this->icon('comment', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('comment'); ?>
<?= sprintf(
$this->translatePlural(
'List %u host comment',

View File

@ -50,16 +50,16 @@
</td>
<td>
<?php if ($comment->objecttype === 'service'): ?>
<?= $this->icon('service') ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$comment->service, $comment->service_display_name, $comment->host, $comment->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host') ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($comment->host, $comment->host_display_name) ?>
<?php endif ?>
<br>
<?= $this->icon('comment', null, array('aria-hidden' => 'true')); ?> <?= isset($comment->author)
<?= $this->icon('comment', $this->translate('Comment')); ?> <?= isset($comment->author)
? '[' . $comment->author . '] '
: '';
?><?= $this->escape($comment->comment); ?>

View File

@ -20,7 +20,7 @@ foreach ($groupData as $groupName => $groupInfo): ?>
<div class="box contents">
<?php foreach ($groupInfo['contacts'] as $c): ?>
<div class="box entry">
<img aria-hidden="true" src="<?= $this->href('/static/gravatar', array('email' => $c->contact_email )) ?>" />
<?= $this->img('/static/gravatar', array('email' => $c->contact_email)); ?>
<a href="<?= $this->href(
'monitoring/show/contact',
array('contact' => $c->contact_name)

View File

@ -14,7 +14,7 @@
}
foreach ($contacts as $contact): ?>
<div class="contact">
<img aria-hidden="true" src="<?= $this->href('/static/gravatar', array('email' => $contact->contact_email )) ?>" />
<?= $this->img('/static/gravatar', array('email' => $contact->contact_email)); ?>
<a href="<?= $this->href(
'monitoring/show/contact',
array('contact' => $contact->contact_name)

View File

@ -55,16 +55,16 @@ use Icinga\Module\Monitoring\Object\Service;
</td>
<td>
<?php if ($isService): ?>
<?= $this->icon('service') ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$downtime->service, $downtime->service_display_name, $downtime->host, $downtime->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host') ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($downtime->host, $downtime->host_display_name) ?>
<?php endif ?>
<br>
<?= $this->icon('comment') ?> [<?= $this->escape($downtime->author) ?>] <?= $this->escape($downtime->comment) ?>
<?= $this->icon('comment', $this->translate('Comment')); ?> [<?= $this->escape($downtime->author) ?>] <?= $this->escape($downtime->comment) ?>
<br>
<small>
<?php if ($downtime->is_flexible): ?>

View File

@ -74,7 +74,7 @@ if ($hosts->count() === 0) {
}
if (isset($host->host_last_comment) && $host->host_last_comment !== null) {
$icons[] = $this->icon('comment', $this->translate('Comment: ') . $host->host_last_comment);
$icons[] = $this->icon('comment', $this->translate('Last Comment: ') . $host->host_last_comment);
}
?>
<tr class="state <?= $hostStateName ?><?= $host->host_handled ? ' handled' : '' ?>">

View File

@ -42,7 +42,7 @@ use Icinga\Module\Monitoring\Object\Service;
</td>
<td style="font-size: 0.8em">
<?php if ($isService): ?>
<?= $this->icon('service') ?>
<?= $this->icon('service', $this->translate('Service')); ?>
<?= $this->link()->service(
$notification->service,
$notification->service_display_name,
@ -50,7 +50,7 @@ use Icinga\Module\Monitoring\Object\Service;
$notification->host_display_name
) ?>
<?php else: ?>
<?= $this->icon('host') ?>
<?= $this->icon('host', $this->translate('Host')); ?>
<?= $this->link()->host($notification->host, $notification->host_display_name) ?>
<?php endif ?>
<br>

View File

@ -90,7 +90,7 @@ foreach ($services as $service):
<?php endif ?>
<?php if (isset($service->service_last_comment) && $service->service_last_comment !== null): ?>
<?= $this->icon('comment', $this->translate('Comment: ') . $service->service_last_comment) ?>
<?= $this->icon('comment', $this->translate('Last Comment: ') . $service->service_last_comment) ?>
<?php endif ?>
<?php if (!$service->service_active_checks_enabled): ?>

View File

@ -9,8 +9,8 @@
<table class="objectlist">
<thead>
<tr>
<th><?= $this->icon('host', null, array('aria-hidden' => 'true')); ?> <?= $this->translate('Host'); ?></th>
<th><?= $this->icon('conf', null, array('aria-hidden' => 'true')); ?> <?= $this->translate('Service'); ?></th>
<th><?= $this->icon('host'); ?> <?= $this->translate('Host'); ?></th>
<th><?= $this->icon('conf'); ?> <?= $this->translate('Service'); ?></th>
</tr>
</thead>
<tbody>

View File

@ -19,21 +19,21 @@
<div>
<a href="<?= $rescheduleAllLink ?>">
<?= $this->icon('reschedule', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('reschedule'); ?>
<?= $this->translate('Reschedule service checks') ?>
</a>
</div>
<div>
<a href="<?= $downtimeAllLink ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= $this->translate('Schedule service downtimes') ?>
</a>
</div>
<div>
<a href="<?= $processCheckResultAllLink; ?>">
<?= $this->icon('reply', null, array('aria-hidden' => 'true')); ?>
<?= $this->icon('reply'); ?>
<?= $this->translate('Submit passive check results'); ?>
</a>
</div>
@ -59,7 +59,7 @@
),
$unhandledCount
) ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= sprintf(
$this->translatePlural(
'Schedule downtime for unhandled service problem',
@ -79,7 +79,7 @@
),
$unhandledCount
) ?>">
<?= $this->icon('ok', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('ok'); ?>
<?= sprintf(
$this->translatePlural(
'Acknowledge unhandled service problem',
@ -119,7 +119,7 @@
$inDowntimeCount
),
$inDowntimeCount) ?>">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug'); ?>
<?= sprintf(
$this->translatePlural(
'List %u service currently in downtime',
@ -143,7 +143,7 @@
),
$commentCount
) ?>">
<?= $this->icon('comment', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('comment'); ?>
<?= sprintf(
$this->translatePlural(
'List %u service comment',

View File

@ -36,7 +36,7 @@ if ($object->acknowledged): ?>
}
?>
<a href="<?= $ackLink ?>" data-base-target="_self">
<?= $this->icon('ok', null, array('aria-hidden' => 'true')) ?> <?= $this->translate('Acknowledge') ?>
<?= $this->icon('ok') ?> <?= $this->translate('Acknowledge') ?>
</a>
<?php } else {
echo '&#45;';

View File

@ -40,7 +40,7 @@ if ($object->getType() === $object::TYPE_HOST) {
}
?>
<a href="<?= $reschedule ?>" data-base-target="_self">
<?= $this->icon('reschedule', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('reschedule') ?>
<?= $this->translate('Reschedule') ?>
</a>
<?php } // endif ?>

View File

@ -22,7 +22,7 @@ $command = array_shift($parts);
);
} ?>
<a href="<?= $processCheckResult ?>" data-base-target="_self">
<?= $this->icon('reply', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('reply') ?>
<?= $this->translate('Process check result') ?>
</a>
<?php endif ?>

View File

@ -16,7 +16,7 @@
}
?>
<a href="<?= $addCommentLink ?>" data-base-target="_self">
<?= $this->icon('comment', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('comment') ?>
<?= $this->translate('Add comment') ?>
</a>
<?php } else {

View File

@ -12,7 +12,7 @@ if (! empty($object->contacts)) {
printf(
"<tr><th>%s</th><td>%s %s</td></tr>\n",
$this->translate('Contacts'),
$this->icon('user', null, array('aria-hidden' => 'true')),
$this->icon('user'),
implode(', ', $list)
);
@ -31,7 +31,7 @@ if (! empty($object->contactgroups)) {
printf(
"<tr><th>%s</th><td>%s %s</td></tr>\n",
$this->translate('Contactgroups'),
$this->icon('users', null, array('aria-hidden' => 'true')),
$this->icon('users'),
implode(', ', $list)
);

View File

@ -16,7 +16,7 @@
}
?>
<a href="<?= $scheduleDowntimeLink ?>" data-base-target="_self">
<?= $this->icon('plug', null, array('aria-hidden' => 'true')) ?>
<?= $this->icon('plug') ?>
<?= $this->translate('Schedule downtime') ?>
</a>
<?php } else {

View File

@ -11,7 +11,7 @@ foreach ($object->hostgroups as $name => $alias) {
printf(
"<tr><th>%s</th><td>%s %s</td></tr>\n",
$this->translate('Hostgroups'),
$this->icon('host', null, array('aria-hidden' => 'true')),
$this->icon('host'),
implode(', ', $list)
);

View File

@ -12,7 +12,7 @@ foreach ($object->servicegroups as $name => $alias) {
printf(
"<tr><th>%s</th><td>%s %s</td></tr>\n",
$this->translate('Servicegroups'),
$this->icon('services', null, array('aria-hidden' => 'true')),
$this->icon('services'),
implode(', ', $list)
);

View File

@ -290,7 +290,12 @@ abstract class IdoQuery extends DbQuery
&& strpos($filter->getColumn(), 'LOWER') !== 0
) {
$filter->setColumn('LOWER(' . $filter->getColumn() . ')');
$filter->setExpression(strtolower($filter->getExpression()));
$expression = $filter->getExpression();
if (is_array($expression)) {
$filter->setExpression(array_map('strtolower', $expression));
} else {
$filter->setExpression(strtolower($expression));
}
}
} else {
foreach ($filter->filters() as $chainedFilter) {

View File

@ -41,7 +41,7 @@ class AuthenticationPage extends Form
'note',
'external_note',
array(
'value' => $this->translate(
'value' => '<i aria-hidden="true" class="icon-info"></i>' . $this->translate(
'You\'re currently not authenticated using any of the web server\'s authentication '
. 'mechanisms. Make sure you\'ll configure such, otherwise you\'ll not be able to '
. 'log into Icinga Web 2.'
@ -50,7 +50,7 @@ class AuthenticationPage extends Form
'ViewHelper',
array(
'HtmlTag',
array('tag' => 'p', 'class' => 'icon-info info-box')
array('tag' => 'p', 'class' => 'info-box')
)
)
)

View File

@ -280,26 +280,26 @@ a:focus {
display: inline;
margin: 0;
padding: 0;
a {
a, button[type="submit"] {
position: absolute;
display: block;
left: -999em;
width: 10.4em;
top: 0.4em;
box-sizing: content-box;
width: 10.4em !important;
top: 0em;
text-align: left !important;
padding: 0.8em;
background-color: white;
z-index: 4;
border: 1px @colorGray solid;
&:focus {
left: 0;
outline: 1px dotted black !important;
}
}
}
}
}
.skip-links-inline {
margin-top: -4em;
ul > li > a {
width: 16em;
}
margin-top: -3.5em;
}

View File

@ -362,6 +362,7 @@
var self = event.data.self;
var icinga = self.icinga;
var $a = $(this);
var $eventTarget = $(event.target);
var href = $a.attr('href');
var linkTarget = $a.attr('target');
var $target;
@ -398,9 +399,17 @@
return false;
}
// Ignore form elements in action rows
if ($(event.target).is('input') || $(event.target).is('button')) {
return;
if (! $eventTarget.is($a)) {
if ($eventTarget.is('input') || $eventTarget.is('button')) {
// Ignore form elements in action rows
return;
} else {
var $button = $('input[type=submit]:focus').add('button[type=submit]:focus');
if ($button.length > 0 && $.contains($button[0], $eventTarget[0])) {
// Ignore any descendant of form elements
return;
}
}
}
// ignore multiselect table row clicks
@ -516,14 +525,6 @@
return $target;
},
/*
hrefIsHashtag: function(href) {
// WARNING: IE gives full URL :(
// Also it doesn't support negativ indexes in substr
return href.substr(href.length - 1, 1) == '#';
},
*/
unbindGlobalHandlers: function () {
$.each(self.icinga.behaviors, function (name, behavior) {
behavior.unbind($(document));

View File

@ -92,7 +92,7 @@
// TODO: update navigation
// Did we find any URL? Then push it!
if (url !== '') {
window.history.pushState({icinga: true}, null, this.cleanupUrl(url));
this.push(url);
}
},
@ -101,15 +101,18 @@
if (!this.enabled) {
return;
}
window.history.pushState({icinga: true}, null, this.cleanupUrl(url));
this.push(url);
},
cleanupUrl: function(url) {
url = url.replace(/_render=[a-z0-9]+&/, '').replace(/&_render=[a-z0-9]+/, '').replace(/\?_render=[a-z0-9]+$/, '');
url = url.replace(/_reload=[a-z0-9]+&/, '').replace(/&_reload=[a-z0-9]+/, '').replace(/\?_reload=[a-z0-9]+$/, '');
return url;
push: function (url) {
url = url.replace(/[\?&]?_(render|reload)=[a-z0-9]+/g, '');
if (this.lastPushUrl === url) {
return;
}
this.lastPushUrl = url;
window.history.pushState({icinga: true}, null, url);
},
/**
* Event handler for pop events
*
@ -155,7 +158,7 @@
icinga.loader.loadUrl(
main,
$('#col1')
).historyTriggered = true;
).addToHistory = false;
}
if (document.location.hash && document.location.hash.match(/^#!/)) {
@ -172,7 +175,7 @@
icinga.loader.loadUrl(
parts[1],
$('#col2')
).historyTriggered = true;
).addToHistory = false;
}
}

View File

@ -114,10 +114,10 @@
req.done(this.onResponse);
req.fail(this.onFailure);
req.complete(this.onComplete);
req.historyTriggered = false;
req.autorefresh = autorefresh;
req.action = action;
req.failure = false;
req.addToHistory = true;
if (id) {
this.requests[id] = req;
@ -420,8 +420,6 @@
var $el = $(el);
if ($el.hasClass('dashboard')) {
return;
} else {
}
var url = $el.data('icingaUrl');
targets[i].data('icingaUrl', url);
@ -555,7 +553,7 @@
// Update history when necessary. Don't do so for requests triggered
// by history or autorefresh events
if (! req.historyTriggered && ! req.autorefresh) {
if (! req.autorefresh && req.addToHistory) {
if (req.$target.hasClass('container') && ! req.failure) {
// We only want to care about top-level containers
if (req.$target.parent().closest('.container').length === 0) {
@ -564,7 +562,7 @@
} else {
// Request wasn't for a container, so it's usually the body
// or the full layout. Push request URL to history:
this.icinga.history.pushUrl(req.url);
this.icinga.history.pushCurrentState();
}
}
@ -594,10 +592,12 @@
req.failure = true;
req.$target.data('icingaUrl', req.url);
/*
* Test if a manual actions comes in and autorefresh is active: Stop refreshing
*/
if (! req.historyTriggered && ! req.autorefresh && req.$target.data('icingaRefresh') > 0
if (req.addToHistory && ! req.autorefresh && req.$target.data('icingaRefresh') > 0
&& req.$target.data('icingaUrl') !== url) {
req.$target.data('icingaRefresh', 0);
req.$target.data('icingaUrl', url);
@ -621,6 +621,9 @@
'Request to ' + url + ' has been aborted for ',
req.$target
);
// Aborted requests should not be added to browser history
req.addToHistory = false;
} else {
if (this.failureNotice === null) {
this.failureNotice = this.createNotice(
@ -672,7 +675,6 @@
// Container update happens here
var scrollPos = false;
var self = this;
var origFocus = self.icinga.utils.getDomPath(document.activeElement);
var containerId = $container.attr('id');
if (typeof containerId !== 'undefined') {
if (autorefresh) {
@ -681,6 +683,9 @@
scrollPos = 0;
}
}
if (autorefresh && $.contains($container[0], document.activeElement)) {
var origFocus = self.icinga.utils.getDomPath(document.activeElement);
}
$container.trigger('beforerender');
@ -737,7 +742,7 @@
}
this.icinga.ui.assignUniqueContainerIds();
if (origFocus.length == origFocus[0] !== '') {
if (origFocus && origFocus.length > 0 && origFocus[0] !== '') {
setTimeout(function() {
$(self.icinga.utils.getElementByDomPath(origFocus)).focus();
}, 0);