Merge branch 'master' into bugfix/make-all-views-dashboard-compliant-7876

This commit is contained in:
Johannes Meyer 2015-04-20 11:15:04 +02:00
commit 54a370ca22
13 changed files with 212 additions and 85 deletions

View File

@ -107,7 +107,7 @@ Icinga Web 2 uses the MD5 based BSD password algorithm. For generating a passwor
command: command:
```` ````
openssl passwd -1 "password" openssl passwd -1 password
```` ````
> Note: The switch to `openssl passwd` is the **number one** (`-1`) for using the MD5 based BSD password algorithm. > Note: The switch to `openssl passwd` is the **number one** (`-1`) for using the MD5 based BSD password algorithm.

View File

@ -3,21 +3,133 @@
The preferred way of installing Icinga Web 2 is to use the official package repositories depending on which operating The preferred way of installing Icinga Web 2 is to use the official package repositories depending on which operating
system and distribution you are running. But it is also possible to install Icinga Web 2 directly from source. system and distribution you are running. But it is also possible to install Icinga Web 2 directly from source.
## <a id="installation-requirements"></a> Installing Requirements ## <a id="installing-requirements"></a> Installing Requirements
* A web server, e.g. Apache or nginx * A web server, e.g. Apache or nginx
* PHP >= 5.3.0 w/ gettext and OpenSSL support * PHP >= 5.3.0 w/ gettext, intl and OpenSSL support
* MySQL or PostgreSQL PHP libraries when using a database for authentication or storing user preferences into a database * MySQL or PostgreSQL PHP libraries when using a database for authentication or for storing preferences into a database
* LDAP PHP library when using Active Directory or LDAP for authentication * LDAP PHP library when using Active Directory or LDAP for authentication
* Icinga 1.x w/ Livestatus or IDO, Icinga 2 w/ Livestatus or IDO feature enabled * Icinga 1.x w/ Livestatus or IDO; Icinga 2.x w/ Livestatus or IDO feature enabled
* MySQL or PostgreSQL PHP libraries when using IDO
## <a id="installation-from-package"></a> Installing Icinga Web 2 from Package ## <a id="installing-from-package"></a> Installing Icinga Web 2 from Package
A guide on how to install Icinga Web 2 from package will follow shortly. Below is a list of official package repositories for installing Icinga Web 2 for various operating systems.
## <a id="installation-from-source"></a> Installing Icinga Web 2 from Source Distribution | Repository
------------------------|---------------------------
Debian | [debmon](http://debmon.org/packages/debmon-wheezy/icingaweb2), [Icinga Repository](http://packages.icinga.org/debian/)
Ubuntu | [Icinga Repository](http://packages.icinga.org/ubuntu/)
RHEL/CentOS | [Icinga Repository](http://packages.icinga.org/epel/)
openSUSE | [Icinga Repository](http://packages.icinga.org/openSUSE/)
SLES | [Icinga Repository](http://packages.icinga.org/SUSE/)
Gentoo | -
FreeBSD | -
ArchLinux | [Upstream](https://aur.archlinux.org/packages/icingaweb2)
**Step 1: Getting the Source** Packages for distributions other than the ones listed above may also be available.
Please contact your distribution packagers.
### <a id="package-repositories"></a> Setting up Package Repositories
You need to add the Icinga repository to your package management configuration for installing Icinga Web 2.
Below is a list with examples for various distributions.
Debian (debmon):
````
wget -O - http://debmon.org/debmon/repo.key 2>/dev/null | apt-key add -
echo 'deb http://debmon.org/debmon debmon-wheezy main' >/etc/apt/sources.list.d/debmon.list
apt-get update
````
Ubuntu Trusty:
````
wget -O - http://packages.icinga.org/icinga.key | apt-key add -
add-apt-repository 'deb http://packages.icinga.org/ubuntu icinga-trusty main'
apt-get update
````
For other Ubuntu versions just replace trusty with your distribution's code name.
RHEL and CentOS:
````
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/epel/ICINGA-release.repo
yum makecache
````
Fedora:
````
rpm --import http://packages.icinga.org/icinga.key
curl -o /etc/yum.repos.d/ICINGA-release.repo http://packages.icinga.org/fedora/ICINGA-release.repo
yum makecache
````
SLES 11:
````
zypper ar http://packages.icinga.org/SUSE/ICINGA-release-11.repo
zypper ref
````
SLES 12:
````
zypper ar http://packages.icinga.org/SUSE/ICINGA-release.repo
zypper ref
````
openSUSE:
````
zypper ar http://packages.icinga.org/openSUSE/ICINGA-release.repo
zypper ref
````
The packages for RHEL/CentOS depend on other packages which are distributed as part of the
[EPEL repository](http://fedoraproject.org/wiki/EPEL). Please make sure to enable this repository by following
[these instructions](http://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F).
### <a id="installing-from-package-example"></a> Installing Icinga Web 2
You can install Icinga Web 2 by using your distribution's package manager to install the `icingaweb2` package.
Below is a list with examples for various distributions.
Debian and Ubuntu:
````
apt-get install icingaweb2
````
RHEL, CentOS and Fedora:
````
yum install icingaweb2
````
SLES and openSUSE:
````
zypper install icingaweb2
````
### <a id="preparing-web-setup-from-package"></a> Preparing Web Setup
You can set up Icinga Web 2 quickly and easily with the Icinga Web 2 setup wizard which is available the first time
you visit Icinga Web 2 in your browser. When using the web setup you are required to authenticate using a token.
In order to generate a token use the `icingacli`:
````
icingacli setup token create
````
In case you do not remember the token you can show it using the `icingacli`:
````
icingacli setup token show
````
Finally visit Icinga Web 2 in your browser to access the setup wizard and complete the installation:
`/icingaweb2/setup`.
## <a id="installing-from-source"></a> Installing Icinga Web 2 from Source
Although the preferred way of installing Icinga Web 2 is to use packages, it is also possible to install Icinga Web 2
directly from source.
### <a id="getting-the-source"></a> Getting the Source
First of all, you need to download the sources. Icinga Web 2 is available through a Git repository. You can clone this First of all, you need to download the sources. Icinga Web 2 is available through a Git repository. You can clone this
repository either via git or http protocol using the following URLs: repository either via git or http protocol using the following URLs:
@ -33,7 +145,7 @@ This version also offers snapshots for easy download which you can use if you do
git clone git://git.icinga.org/icingaweb2.git git clone git://git.icinga.org/icingaweb2.git
```` ````
**Step 2: Install the Source** ### <a id="installing-from-source-example"></a> Installing Icinga Web 2
Choose a target directory and move Icinga Web 2 there. Choose a target directory and move Icinga Web 2 there.
@ -41,7 +153,7 @@ Choose a target directory and move Icinga Web 2 there.
mv icingaweb2 /usr/share/icingaweb2 mv icingaweb2 /usr/share/icingaweb2
```` ````
**Step 3: Configuring the Web Server** ### <a id="configuring-web-server"></a> Configuring the Web Server
Use `icingacli` to generate web server configuration for either Apache or nginx. Use `icingacli` to generate web server configuration for either Apache or nginx.
@ -57,13 +169,15 @@ nginx:
Save the output as new file in your webserver's configuration directory. Save the output as new file in your webserver's configuration directory.
Example for Apache on RHEL/CentOS: Example for Apache on RHEL or CentOS:
```` ````
./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/httpd/conf.d/icingaweb2.conf ./bin/icingacli setup config webserver apache --document-root /usr/share/icingaweb2/public > /etc/httpd/conf.d/icingaweb2.conf
```` ````
### <a id="preparing-web-setup-from-source"></a> Preparing Web Setup
**Step 4: Preparing Web Setup** You can set up Icinga Web 2 quickly and easily with the Icinga Web 2 setup wizard which is available the first time
you visit Icinga Web 2 in your browser. Please follow the steps listed below for preparing the web setup.
Because both web and CLI must have access to configuration and logs, permissions will be managed using a special Because both web and CLI must have access to configuration and logs, permissions will be managed using a special
system group. The web server user and CLI user have to be added to this system group. system group. The web server user and CLI user have to be added to this system group.
@ -102,6 +216,7 @@ Use `icingacli` to create the configuration directory which defaults to **/etc/i
./bin/icingacli setup config directory ./bin/icingacli setup config directory
```` ````
When using the web setup you are required to authenticate using a token. In order to generate a token use the When using the web setup you are required to authenticate using a token. In order to generate a token use the
`icingacli`: `icingacli`:
```` ````
@ -113,11 +228,10 @@ In case you do not remember the token you can show it using the `icingacli`:
./bin/icingacli setup token show ./bin/icingacli setup token show
```` ````
**Step 5: Web Setup** Finally visit Icinga Web 2 in your browser to access the setup wizard and complete the installation:
`/icingaweb2/setup`.
Visit Icinga Web 2 in your browser and complete installation using the web setup: /icingaweb2/setup ## <a id="upgrading-to-beta2"></a> Upgrading to Icinga Web 2 Beta 2
## Upgrading to Icinga Web 2 Beta 2
Icinga Web 2 Beta 2 introduces access control based on roles for secured actions. If you've already set up Icinga Web 2, Icinga Web 2 Beta 2 introduces access control based on roles for secured actions. If you've already set up Icinga Web 2,
you are required to create the file **roles.ini** beneath Icinga Web 2's configuration directory with the following you are required to create the file **roles.ini** beneath Icinga Web 2's configuration directory with the following
@ -134,7 +248,7 @@ If you delegated authentication to your web server using the `autologin` backend
authentication backend to be able to log in again. The new name better reflects whats going on. A similar change authentication backend to be able to log in again. The new name better reflects whats going on. A similar change
affects environments that opted for not storing preferences, your new backend is `none`. affects environments that opted for not storing preferences, your new backend is `none`.
## Upgrading to Icinga Web 2 Beta 3 ## <a id="upgrading-to-beta3"></a> Upgrading to Icinga Web 2 Beta 3
Because Icinga Web 2 Beta 3 does not introduce any backward incompatible change you don't have to change your Because Icinga Web 2 Beta 3 does not introduce any backward incompatible change you don't have to change your
configuration files after upgrading to Icinga Web 2 Beta 3. configuration files after upgrading to Icinga Web 2 Beta 3.

View File

@ -12,7 +12,6 @@ use Icinga\Exception\ConfigurationError;
use Icinga\Exception\SystemPermissionException; use Icinga\Exception\SystemPermissionException;
use Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
use Icinga\Exception\NotReadableError; use Icinga\Exception\NotReadableError;
use Icinga\Exception\NotFoundError;
/** /**
* Module manager that handles detecting, enabling and disabling of modules * Module manager that handles detecting, enabling and disabling of modules
@ -199,7 +198,6 @@ class Manager
* *
* @return $this * @return $this
* @throws ConfigurationError When trying to enable a module that is not installed * @throws ConfigurationError When trying to enable a module that is not installed
* @throws NotFoundError In case the "enabledModules" directory does not exist
* @throws SystemPermissionException When insufficient permissions for the application exist * @throws SystemPermissionException When insufficient permissions for the application exist
*/ */
public function enableModule($name) public function enableModule($name)
@ -218,14 +216,15 @@ class Manager
if (! is_dir($this->enableDir) && !@mkdir($this->enableDir, 02770, true)) { if (! is_dir($this->enableDir) && !@mkdir($this->enableDir, 02770, true)) {
$error = error_get_last(); $error = error_get_last();
throw new SystemPermissionException( throw new SystemPermissionException(
'Failed to create enabledModule directory "%s" (%s)', 'Failed to create enabledModules directory "%s" (%s)',
$this->enableDir, $this->enableDir,
$error['message'] $error['message']
); );
} elseif (! is_writable($this->enableDir)) { } elseif (! is_writable($this->enableDir)) {
throw new SystemPermissionException( throw new SystemPermissionException(
'Cannot enable module "%s". Insufficient system permissions for enabling modules.', 'Cannot enable module "%s". Check the permissions for the enabledModules directory: %s',
$name $name,
$this->enableDir
); );
} }
@ -237,10 +236,11 @@ class Manager
$error = error_get_last(); $error = error_get_last();
if (strstr($error["message"], "File exists") === false) { if (strstr($error["message"], "File exists") === false) {
throw new SystemPermissionException( throw new SystemPermissionException(
'Could not enable module "%s" due to file system errors. ' 'Cannot enable module "%s" at %s due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. ' . 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: %s', . 'Primary error was: %s',
$name, $name,
$this->enableDir,
$error['message'] $error['message']
); );
} }
@ -259,32 +259,37 @@ class Manager
* @return $this * @return $this
* *
* @throws ConfigurationError When the module is not installed or it's not a symlink * @throws ConfigurationError When the module is not installed or it's not a symlink
* @throws SystemPermissionException When the module can't be disabled * @throws SystemPermissionException When insufficient permissions for the application exist
*/ */
public function disableModule($name) public function disableModule($name)
{ {
if (! $this->hasEnabled($name)) { if (! $this->hasEnabled($name)) {
return $this; return $this;
} }
if (! is_writable($this->enableDir)) { if (! is_writable($this->enableDir)) {
throw new SystemPermissionException( throw new SystemPermissionException(
'Could not disable module. Module path is not writable.' 'Cannot disable module "%s". Check the permissions for the enabledModules directory: %s',
$name,
$this->enableDir
); );
} }
$link = $this->enableDir . DIRECTORY_SEPARATOR . $name; $link = $this->enableDir . DIRECTORY_SEPARATOR . $name;
if (! file_exists($link)) { if (! file_exists($link)) {
throw new ConfigurationError( throw new ConfigurationError(
'Could not disable module. The module %s was not found.', 'Cannot disable module "%s". Module is not installed.',
$name $name
); );
} }
if (! is_link($link)) { if (! is_link($link)) {
throw new ConfigurationError( throw new ConfigurationError(
'Could not disable module. The module "%s" is not a symlink. ' 'Cannot disable module %s at %s. '
. 'It looks like you have installed this module manually and moved it to your module folder. ' . 'It looks like you have installed this module manually and moved it to your module folder. '
. 'In order to dynamically enable and disable modules, you have to create a symlink to ' . 'In order to dynamically enable and disable modules, you have to create a symlink to '
. 'the enabled_modules folder.', . 'the enabledModules folder.',
$name $name,
$this->enableDir
); );
} }
@ -292,10 +297,11 @@ class Manager
if (! @unlink($link)) { if (! @unlink($link)) {
$error = error_get_last(); $error = error_get_last();
throw new SystemPermissionException( throw new SystemPermissionException(
'Could not disable module "%s" due to file system errors. ' 'Cannot enable module "%s" at %s due to file system errors. '
. 'Please check path and mounting points because this is not a permission error. ' . 'Please check path and mounting points because this is not a permission error. '
. 'Primary error was: %s', . 'Primary error was: %s',
$name, $name,
$this->enableDir,
$error['message'] $error['message']
); );
} }

View File

@ -127,7 +127,8 @@ class HistoryColorGrid extends AbstractWidget {
. ' opacity: ' . $this->opacity . ';" ' . . ' opacity: ' . $this->opacity . ';" ' .
'aria-label="' . $entry['caption'] . '" ' . 'aria-label="' . $entry['caption'] . '" ' .
'title="' . $entry['caption'] . '" ' . 'title="' . $entry['caption'] . '" ' .
'href="' . $entry['url'] . '"' . 'href="' . $entry['url'] . '" ' .
'data-tooltip-delay="0"' .
'></a>'; '></a>';
} else { } else {
return '<span ' . return '<span ' .

View File

@ -49,7 +49,7 @@ EOT;
*/ */
private $closeTpl = <<< 'EOT' private $closeTpl = <<< 'EOT'
<li class="dropdown" style="float: right;"> <li class="dropdown" style="float: right;">
<a href="#" class="dropdown-toggle close-toggle">X</a> <a href="#" class="dropdown-toggle close-toggle"> <i aria-hidden="true" class="icon-cancel"></i> </a>
</li> </li>
EOT; EOT;

View File

@ -17,29 +17,20 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
public function init() public function init()
{ {
$this->addDescription( $this->addDescription(
$this->translate( $this->translate('This command is used to send custom notifications about hosts or services.')
'This command is used to send custom notifications for hosts or'
. ' services.'
)
); );
} }
/** /**
* (non-PHPDoc) * {@inheritdoc}
* @see \Icinga\Web\Form::getSubmitLabel() For the method documentation.
*/ */
public function getSubmitLabel() public function getSubmitLabel()
{ {
return $this->translatePlural( return $this->translatePlural('Send custom notification', 'Send custom notifications', count($this->objects));
'Send custom notification',
'Send custom notifications',
count($this->objects)
);
} }
/** /**
* (non-PHPDoc) * {@inheritdoc}
* @see \Icinga\Web\Form::createElements() For the method documentation.
*/ */
public function createElements(array $formData = array()) public function createElements(array $formData = array())
{ {
@ -64,9 +55,8 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
'label' => $this->translate('Forced'), 'label' => $this->translate('Forced'),
'value' => false, 'value' => false,
'description' => $this->translate( 'description' => $this->translate(
'If you check this option, a notification is sent' 'If you check this option, the notification is sent out regardless of time restrictions and'
. 'regardless of the current time and whether' . ' whether or not notifications are enabled.'
. ' notifications are enabled.'
) )
) )
), ),
@ -77,8 +67,7 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
'label' => $this->translate('Broadcast'), 'label' => $this->translate('Broadcast'),
'value' => false, 'value' => false,
'description' => $this->translate( 'description' => $this->translate(
'If you check this option, a notification is sent to' 'If you check this option, the notification is sent out to all normal and escalated contacts.'
. ' all normal and escalated contacts.'
) )
) )
) )
@ -87,24 +76,24 @@ class SendCustomNotificationCommandForm extends ObjectsCommandForm
} }
/** /**
* (non-PHPDoc) * {@inheritdoc}
* @see \Icinga\Web\Form::onSuccess() For the method documentation.
*/ */
public function onSuccess() public function onSuccess()
{ {
foreach ($this->objects as $object) { foreach ($this->objects as $object) {
/** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */ /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */
$comment = new SendCustomNotificationCommand(); $notification = new SendCustomNotificationCommand();
$comment->setObject($object); $notification
$comment->setComment($this->getElement('comment')->getValue()); ->setObject($object)
$comment->setAuthor($this->request->getUser()->getUsername()); ->setComment($this->getElement('comment')->getValue())
$comment->setForced($this->getElement('forced')->isChecked()); ->setAuthor($this->request->getUser()->getUsername())
$comment->setBroadcast($this->getElement('broadcast')->isChecked()); ->setForced($this->getElement('forced')->isChecked())
$this->getTransport($this->request)->send($comment); ->setBroadcast($this->getElement('broadcast')->isChecked());
$this->getTransport($this->request)->send($notification);
} }
Notification::success($this->translatePlural( Notification::success($this->translatePlural(
'Send custom notification..', 'Sending custom notification..',
'Send custom notifications..', 'Sending custom notifications..',
count($this->objects) count($this->objects)
)); ));
return true; return true;

View File

@ -34,10 +34,12 @@ if (count($comments) === 0) {
$icon = 'plug'; $icon = 'plug';
$title = $this->translate('Downtime'); $title = $this->translate('Downtime');
$tooltip = $this->translate('Comment was caused by a downtime.'); $tooltip = $this->translate('Comment was caused by a downtime.');
break;
case 'ack': case 'ack':
$icon = 'ok'; $icon = 'ok';
$title = $this->translate('Acknowledgement'); $title = $this->translate('Acknowledgement');
$tooltip = $this->translate('Comment was caused by an acknowledgement.'); $tooltip = $this->translate('Comment was caused by an acknowledgement.');
break;
} }
?> ?>
<tr class="state invalid"> <tr class="state invalid">

View File

@ -50,7 +50,8 @@ foreach ($serviceDescriptions as $service_description): ?>
'service_description' => $service_description 'service_description' => $service_description
), ),
array( array(
'title' => sprintf($this->translate('List all services with the name "%s" on all reported hosts'), $service_description) 'title' => sprintf($this->translate('List all services with the name "%s" on all reported hosts'), $service_description),
'data-tooltip-gravity' => 's'
), ),
false false
); ?> ); ?>

View File

@ -9,8 +9,7 @@ namespace Icinga\Module\Monitoring\Command\Object;
class ScheduleServiceCheckCommand extends ObjectCommand class ScheduleServiceCheckCommand extends ObjectCommand
{ {
/** /**
* (non-PHPDoc) * {@inheritdoc}
* @see \Icinga\Module\Monitoring\Command\Object\ObjectCommand::$allowedObjects For the property documentation.
*/ */
protected $allowedObjects = array( protected $allowedObjects = array(
self::TYPE_SERVICE self::TYPE_SERVICE
@ -74,7 +73,7 @@ class ScheduleServiceCheckCommand extends ObjectCommand
} }
/** /**
* Is the check forced? * Get whether the check is forced
* *
* @return bool * @return bool
*/ */
@ -84,8 +83,7 @@ class ScheduleServiceCheckCommand extends ObjectCommand
} }
/** /**
* (non-PHPDoc) * {@inheritdoc}
* @see \Icinga\Module\Monitoring\Command\Object\IcingaCommand::getName() For the method documentation.
*/ */
public function getName() public function getName()
{ {

View File

@ -15,29 +15,27 @@ class SendCustomNotificationCommand extends WithCommentCommand
self::TYPE_HOST, self::TYPE_HOST,
self::TYPE_SERVICE self::TYPE_SERVICE
); );
/** /**
* Whether a notification is forced to send * Whether the notification is forced
* *
* Forced notifications are send regardless of time and if notifications * Forced notifications are sent out regardless of time restrictions and whether or not notifications are enabled.
* are enabled.
* *
* @var bool * @var bool
*/ */
protected $forced; protected $forced;
/** /**
* Broadcast the notification * Whether to broadcast the notification
* *
* If broadcast is true, the notification is send to all normal and * Broadcast notifications are sent out to all normal and escalated contacts.
* escalated contacts for the object
* *
* @var bool * @var bool
*/ */
protected $broadcast; protected $broadcast;
/** /**
* Get notification force flag * Get whether to force the notification
* *
* @return bool * @return bool
*/ */
@ -47,17 +45,20 @@ class SendCustomNotificationCommand extends WithCommentCommand
} }
/** /**
* Set whether notification should be forced * Set whether to force the notification
* *
* @param bool $forced * @param bool $forced
*
* @return $this
*/ */
public function setForced($forced = true) public function setForced($forced = true)
{ {
$this->forced = $forced; $this->forced = $forced;
return $this;
} }
/** /**
* Get notification broadcast flag * Get whether to broadcast the notification
* *
* @return bool * @return bool
*/ */
@ -67,12 +68,15 @@ class SendCustomNotificationCommand extends WithCommentCommand
} }
/** /**
* Set notification to broadcast * Set whether to broadcast the notification
* *
* @param bool $broadcast * @param bool $broadcast
*
* @return $this
*/ */
public function setBroadcast($broadcast = true) public function setBroadcast($broadcast = true)
{ {
$this->broadcast = $broadcast; $this->broadcast = $broadcast;
return $this;
} }
} }

View File

@ -28,9 +28,19 @@
$el.attr('title', $el.data('title-rich') || $el.attr('title')); $el.attr('title', $el.data('title-rich') || $el.attr('title'));
}); });
$('svg .chart-data', el).tipsy({ gravity: 'se', html: true }); $('svg .chart-data', el).tipsy({ gravity: 'se', html: true });
$('.historycolorgrid a[title]', el).tipsy({ gravity: 's', offset: 2 }); $('i[title]', el).tipsy({ gravity: $.fn.tipsy.autoNS, offset: 2 });
$('img.icon[title]', el).tipsy({ gravity: $.fn.tipsy.autoNS, offset: 2 }); $('[title]', el).each(function (i, el) {
$('[title]', el).tipsy({ gravity: $.fn.tipsy.autoNS, delayIn: 500 }); var $el = $(el);
var delay = 500;
if ($el.data('tooltip-delay') !== undefined) {
delay = $el.data('tooltip-delay');
}
var gravity = $.fn.tipsy.autoNS;
if ($el.data('tooltip-gravity')) {
gravity = $el.data('tooltip-gravity');
}
$el.tipsy({ gravity: gravity, delayIn: delay });
});
// migrate or remove all orphaned tooltips // migrate or remove all orphaned tooltips
$('.tipsy').each(function () { $('.tipsy').each(function () {

View File

@ -100,6 +100,7 @@
// Destroy Icinga, clean up and interrupt pending requests on unload // Destroy Icinga, clean up and interrupt pending requests on unload
$( window ).on('unload', { self: this }, this.onUnload); $( window ).on('unload', { self: this }, this.onUnload);
$( window ).on('beforeunload', { self: this }, this.onUnload);
// We catch scroll events in our containers // We catch scroll events in our containers
$('.container').on('scroll', { self: this }, this.icinga.events.onContainerScroll); $('.container').on('scroll', { self: this }, this.icinga.events.onContainerScroll);
@ -555,6 +556,7 @@
$(window).off('resize', this.onWindowResize); $(window).off('resize', this.onWindowResize);
$(window).off('load', this.onLoad); $(window).off('load', this.onLoad);
$(window).off('unload', this.onUnload); $(window).off('unload', this.onUnload);
$(window).off('beforeunload', this.onUnload);
$(document).off('scroll', '.container', this.onContainerScroll); $(document).off('scroll', '.container', this.onContainerScroll);
$(document).off('click', 'a', this.linkClicked); $(document).off('click', 'a', this.linkClicked);
$(document).off('click', 'table.action tr[href]', this.rowSelected); $(document).off('click', 'table.action tr[href]', this.rowSelected);

View File

@ -640,7 +640,7 @@
this.icinga.logger.error( this.icinga.logger.error(
req.status, req.status,
errorThrown + ':', errorThrown + ':',
$(req.responseText).text().slice(0, 100) $(req.responseText).text().replace(/\s+/g, ' ').slice(0, 100)
); );
this.renderContentToContainer( this.renderContentToContainer(
req.responseText, req.responseText,