Merge branch 'master' into feature/redesign-7144

This commit is contained in:
Bernd Erk 2014-11-13 14:40:26 +01:00
commit ef2ec0442c
18 changed files with 232 additions and 103 deletions

View File

@ -4,6 +4,7 @@
namespace Icinga\Clicommands; namespace Icinga\Clicommands;
use Icinga\Application\Icinga;
use Icinga\Cli\Command; use Icinga\Cli\Command;
use Icinga\Exception\IcingaException; use Icinga\Exception\IcingaException;
@ -30,7 +31,7 @@ class WebCommand extends Command
// throw new IcingaException('Socket is required'); // throw new IcingaException('Socket is required');
} }
if ($basedir === null) { if ($basedir === null) {
$basedir = dirname(ICINGAWEB_APPDIR) . '/public'; $basedir = Icinga::app()->getBaseDir('public');
if (! file_exists($basedir) || ! is_dir($basedir)) { if (! file_exists($basedir) || ! is_dir($basedir)) {
throw new IcingaException('Basedir is required'); throw new IcingaException('Basedir is required');
} }

View File

@ -5,9 +5,11 @@
namespace Icinga\Form\Config\General; namespace Icinga\Form\Config\General;
use DateTimeZone; use DateTimeZone;
use Icinga\Web\Form; use Icinga\Application\Icinga;
use Icinga\Util\Translator;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Util\Translator;
use Icinga\Web\Form;
/** /**
* Form class to modify the general application configuration * Form class to modify the general application configuration
@ -71,12 +73,12 @@ class ApplicationConfigForm extends Form
array( array(
'label' => t('Module Path'), 'label' => t('Module Path'),
'required' => true, 'required' => true,
'value' => implode(':', Icinga::app()->getModuleManager()->getModuleDirs()),
'description' => t( 'description' => t(
'Contains the directories that will be searched for available modules, separated by ' 'Contains the directories that will be searched for available modules, separated by '
. 'colons. Modules that don\'t exist in these directories can still be symlinked in ' . 'colons. Modules that don\'t exist in these directories can still be symlinked in '
. 'the module folder, but won\'t show up in the list of disabled modules.' . 'the module folder, but won\'t show up in the list of disabled modules.'
), )
'value' => realpath(ICINGAWEB_APPDIR . '/../modules')
) )
); );

View File

@ -49,6 +49,34 @@ abstract class ApplicationBootstrap
*/ */
protected $baseDir; protected $baseDir;
/**
* Application directory
*
* @var string
*/
protected $appDir;
/**
* Vendor library directory
*
* @var string
*/
protected $vendorDir;
/**
* Library directory
*
* @var string
*/
protected $libDir;
/**
* Configuration directory
*
* @var string
*/
protected $configDir;
/** /**
* Icinga auto loader * Icinga auto loader
* *
@ -56,13 +84,6 @@ abstract class ApplicationBootstrap
*/ */
private $loader; private $loader;
/**
* Library directory
*
* @var string
*/
private $libDir;
/** /**
* Config object * Config object
* *
@ -70,20 +91,6 @@ abstract class ApplicationBootstrap
*/ */
protected $config; protected $config;
/**
* Configuration directory
*
* @var string
*/
private $configDir;
/**
* Application directory
*
* @var string
*/
private $appDir;
/** /**
* Module manager * Module manager
* *
@ -117,13 +124,8 @@ abstract class ApplicationBootstrap
$baseDir = dirname($this->getBootstrapDirectory()); $baseDir = dirname($this->getBootstrapDirectory());
} }
$this->baseDir = $baseDir; $this->baseDir = $baseDir;
if (! defined('ICINGAWEB_BASEDIR')) { $this->appDir = $baseDir . '/application';
define('ICINGAWEB_BASEDIR', dirname($this->getBootstrapDirectory())); $this->vendorDir = $baseDir . '/library/vendor';
}
define('ICINGAWEB_VENDORS', ICINGAWEB_BASEDIR . '/library/vendor');
define('ICINGAWEB_APPDIR', ICINGAWEB_BASEDIR . '/application');
$this->appDir = ICINGAWEB_APPDIR;
$this->libDir = realpath(__DIR__ . '/../..'); $this->libDir = realpath(__DIR__ . '/../..');
if ($configDir === null) { if ($configDir === null) {
@ -229,33 +231,43 @@ abstract class ApplicationBootstrap
*/ */
public function getBaseDir($subDir = null) public function getBaseDir($subDir = null)
{ {
return $this->getDirWithSubDir($subDir); return $this->getDirWithSubDir($this->baseDir, $subDir);
} }
/** /**
* Getter for application dir * Get the application directory
* *
* Optional append sub directory * @param string $subDir Optional sub directory to get
*
* @param string $subdir optional subdir
* *
* @return string * @return string
*/ */
public function getApplicationDir($subdir = null) public function getApplicationDir($subDir = null)
{ {
return $this->getDirWithSubDir($this->appDir, $subdir); return $this->getDirWithSubDir($this->appDir, $subDir);
} }
/** /**
* Getter for config dir * Get the vendor library directory
* *
* @param string $subdir * @param string $subDir Optional sub directory to get
* *
* @return string * @return string
*/ */
public function getConfigDir($subdir = null) public function getVendorDir($subDir = null)
{ {
return $this->getDirWithSubDir($this->configDir, $subdir); return $this->getDirWithSubDir($this->vendorDir, $subDir);
}
/**
* Get the configuration directory
*
* @param string $subDir Optional sub directory to get
*
* @return string
*/
public function getConfigDir($subDir = null)
{
return $this->getDirWithSubDir($this->configDir, $subDir);
} }
/** /**
@ -333,7 +345,7 @@ abstract class ApplicationBootstrap
$this->moduleManager = new ModuleManager( $this->moduleManager = new ModuleManager(
$this, $this,
$this->configDir . '/enabledModules', $this->configDir . '/enabledModules',
explode(':', $this->config->fromSection('global', 'modulePath', ICINGAWEB_APPDIR . '/../modules')) explode(':', $this->config->fromSection('global', 'modulePath', $this->baseDir . '/modules'))
); );
return $this; return $this;
} }

View File

@ -559,4 +559,14 @@ class Manager
ksort($this->installedBaseDirs); ksort($this->installedBaseDirs);
return $this; return $this;
} }
/**
* Get the directories where to look for installed modules
*
* @return array
*/
public function getModuleDirs()
{
return $this->modulePaths;
}
} }

View File

@ -66,7 +66,7 @@ class Loader
public function __construct(App $app) public function __construct(App $app)
{ {
$this->app = $app; $this->app = $app;
$this->coreAppDir = ICINGAWEB_APPDIR . '/clicommands'; $this->coreAppDir = $app->getBaseDir('clicommands');
} }
/** /**

View File

@ -0,0 +1,81 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Form\Element;
use Zend_Form_Element;
use Icinga\Web\Request;
use Icinga\Application\Icinga;
/**
* A button
*/
class Button extends Zend_Form_Element
{
/**
* Use formButton view helper by default
*
* @var string
*/
public $helper = 'formButton';
/**
* Constructor
*
* @param string|array|Zend_Config $spec Element name or configuration
* @param string|array|Zend_Config $options Element value or configuration
*/
public function __construct($spec, $options = null)
{
if (is_string($spec) && ((null !== $options) && is_string($options))) {
$options = array('label' => $options);
}
if (!isset($options['ignore'])) {
$options['ignore'] = true;
}
parent::__construct($spec, $options);
if ($label = $this->getLabel()) {
// Necessary to get the label shown on the generated HTML
$this->content = $label;
}
}
/**
* Validate element value (pseudo)
*
* There is no need to reset the value
*
* @param mixed $value Is always ignored
* @param mixed $context Is always ignored
*
* @return bool Returns always TRUE
*/
public function isValid($value, $context = null)
{
return true;
}
/**
* Has this button been selected?
*
* @return bool
*/
public function isChecked()
{
return $this->getRequest()->getParam($this->getName()) === $this->getValue();
}
/**
* Return the current request
*
* @return Request
*/
protected function getRequest()
{
return Icinga::app()->getFrontController()->getRequest();
}
}

View File

@ -8,6 +8,7 @@ use LogicException;
use InvalidArgumentException; use InvalidArgumentException;
use Icinga\Web\Session\SessionNamespace; use Icinga\Web\Session\SessionNamespace;
use Icinga\Web\Form\Decorator\ElementDoubler; use Icinga\Web\Form\Decorator\ElementDoubler;
use Icinga\Web\Form\Element\Button;
/** /**
* Container and controller for form based wizards * Container and controller for form based wizards
@ -426,55 +427,60 @@ class Wizard
$index = array_search($page, $pages, true); $index = array_search($page, $pages, true);
if ($index === 0) { if ($index === 0) {
$page->addElement( $page->addElement(
'button', new Button(
static::BTN_NEXT, static::BTN_NEXT,
array( array(
'type' => 'submit', 'type' => 'submit',
'value' => $pages[1]->getName(), 'value' => $pages[1]->getName(),
'label' => t('Next'), 'label' => t('Next'),
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)
) )
); );
} elseif ($index < count($pages) - 1) { } elseif ($index < count($pages) - 1) {
$page->addElement( $page->addElement(
'button', new Button(
static::BTN_PREV, static::BTN_PREV,
array( array(
'type' => 'submit', 'type' => 'submit',
'value' => $pages[$index - 1]->getName(), 'value' => $pages[$index - 1]->getName(),
'label' => t('Back'), 'label' => t('Back'),
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)
) )
); );
$page->addElement( $page->addElement(
'button', new Button(
static::BTN_NEXT, static::BTN_NEXT,
array( array(
'type' => 'submit', 'type' => 'submit',
'value' => $pages[$index + 1]->getName(), 'value' => $pages[$index + 1]->getName(),
'label' => t('Next'), 'label' => t('Next'),
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)
) )
); );
} else { } else {
$page->addElement( $page->addElement(
'button', new Button(
static::BTN_PREV, static::BTN_PREV,
array( array(
'type' => 'submit', 'type' => 'submit',
'value' => $pages[$index - 1]->getName(), 'value' => $pages[$index - 1]->getName(),
'label' => t('Back'), 'label' => t('Back'),
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)
) )
); );
$page->addElement( $page->addElement(
'button', new Button(
static::BTN_NEXT, static::BTN_NEXT,
array( array(
'type' => 'submit', 'type' => 'submit',
'value' => $page->getName(), 'value' => $page->getName(),
'label' => t('Finish'), 'label' => t('Finish'),
'decorators' => array('ViewHelper') 'decorators' => array('ViewHelper')
)
) )
); );
} }

View File

@ -0,0 +1,6 @@
<?php
$helpMessage = $this->translate('Press and hold the Ctrl key while clicking on rows to select multiple rows or press and hold the Shift key to select a range of rows.', 'multiselection');
?>
<div class="selection-info">
<span class="selection-info-count">0</span> <?= $this->translate('row(s) selected', 'multiselection') ?> <?= $this->icon('unhandled.png', $helpMessage) ?>
</div>

View File

@ -14,8 +14,8 @@
<div class="content"> <div class="content">
<?= $this->filterEditor ?> <?= $this->filterEditor ?>
<?php if (empty($downtimes)): ?> <?php if (count($downtimes) === 0): ?>
<?= $this->translate('No downtimes matching the filter'); ?> <?= $this->translate('No active downtimes'); ?>
</div> </div>
<?php return; endif ?> <?php return; endif ?>

View File

@ -16,6 +16,7 @@ if ($this->compact): ?>
<?= $this->widget('limiter')->setMaxLimit($this->hosts->count()) ?> <?= $this->widget('limiter')->setMaxLimit($this->hosts->count()) ?>
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?> <?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?>
<?= $this->selectionToolbar('multi', $this->href('monitoring/hosts/show?' . $this->filter->toQueryString())) ?> <?= $this->selectionToolbar('multi', $this->href('monitoring/hosts/show?' . $this->filter->toQueryString())) ?>
<?= $this->render('list/components/selectioninfo.phtml') ?>
</div> </div>
<div class="content"> <div class="content">

View File

@ -20,6 +20,7 @@ if (!$this->compact): ?>
<?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve)) ?> <?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve)) ?>
<?php endif ?> <?php endif ?>
<?= $this->selectionToolbar('multi', $this->href('monitoring/services/show?' . $this->filter->toQueryString())) ?> <?= $this->selectionToolbar('multi', $this->href('monitoring/services/show?' . $this->filter->toQueryString())) ?>
<?= $this->render('list/components/selectioninfo.phtml') ?>
</div> </div>
<div class="content"> <div class="content">

View File

@ -1,6 +1,6 @@
<div class="controls"> <div class="controls">
<?= $this->render('show/components/header.phtml') ?> <?= $this->render('show/components/header.phtml') ?>
<h1><?= $this->translate("This service's current state") ?></h1> <h1><?= $this->translate("Service detail information") ?></h1>
</div> </div>
<div class="content" data-base-target="_next"> <div class="content" data-base-target="_next">
<?= $this->render('show/components/output.phtml') ?> <?= $this->render('show/components/output.phtml') ?>

View File

@ -1,7 +1,7 @@
<?php if ($object->host_name !== false): ?> <?php if ($object->host_name !== false): ?>
<div class="controls"> <div class="controls">
<?= $this->render('show/components/header.phtml') ?> <?= $this->render('show/components/header.phtml') ?>
<h1><?= $this->translate("This service's current state") ?></h1> <h1><?= $this->translate("Service detail information") ?></h1>
</div> </div>
<div class="content" data-base-target="_next"> <div class="content" data-base-target="_next">
<?= $this->render('show/components/output.phtml') ?> <?= $this->render('show/components/output.phtml') ?>

View File

@ -155,3 +155,7 @@ table.avp .customvar ul {
padding: 0; padding: 0;
padding-left: 1.5em; padding-left: 1.5em;
} }
div.selection-info {
padding-top:1em;
}

View File

@ -4,6 +4,8 @@
namespace Icinga\Module\Setup\Exception; namespace Icinga\Module\Setup\Exception;
use Icinga\Exception\IcingaException;
/** /**
* Class SetupException * Class SetupException
* *

View File

@ -5,7 +5,6 @@
namespace Icinga\Module\Setup; namespace Icinga\Module\Setup;
use PDOException; use PDOException;
use Zend_Version;
use Icinga\Web\Form; use Icinga\Web\Form;
use Icinga\Web\Wizard; use Icinga\Web\Wizard;
use Icinga\Web\Request; use Icinga\Web\Request;
@ -384,20 +383,6 @@ class WebWizard extends Wizard implements SetupWizard
sprintf(mt('setup', 'You are running PHP version %s.'), $phpVersion) sprintf(mt('setup', 'You are running PHP version %s.'), $phpVersion)
); );
// The only reason for requiring 1.12.2 is a bug in Zend_Form_Decorator_ViewHelper in older versions causing a
// Zend_Form_Element_Button's value not being rendered. Feel free to adjust this in case we require an earlier
// version!
$zendVersion = Zend_Version::VERSION;
$requirements->addMandatory(
mt('setup', 'Zend Framework 1'),
mt(
'setup',
'Icinga Web 2 requires at least Zend Framework 1.12.2 to work properly.'
),
Zend_Version::compareVersion('1.12.2') !== 1,
sprintf(mt('setup', 'You have got Zend Framwork %s installed.'), $zendVersion)
);
$defaultTimezone = Platform::getPhpConfig('date.timezone'); $defaultTimezone = Platform::getPhpConfig('date.timezone');
$requirements->addMandatory( $requirements->addMandatory(
mt('setup', 'Default Timezone'), mt('setup', 'Default Timezone'),
@ -507,8 +492,7 @@ class WebWizard extends Wizard implements SetupWizard
) )
); );
// TODO(7464): Re-enable or remove this entirely once a decision has been made regarding shipping Zend with Iw2 $mysqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Mysql');
/*$mysqlAdapterFound = Platform::zendClassExists('Zend_Db_Adapter_Pdo_Mysql');
$requirements->addOptional( $requirements->addOptional(
mt('setup', 'Zend Database Adapter For MySQL'), mt('setup', 'Zend Database Adapter For MySQL'),
mt('setup', 'The Zend database adapter for MySQL is required to access a MySQL database.'), mt('setup', 'The Zend database adapter for MySQL is required to access a MySQL database.'),
@ -526,7 +510,7 @@ class WebWizard extends Wizard implements SetupWizard
$pgsqlAdapterFound ? mt('setup', 'The Zend database adapter for PostgreSQL is available.') : ( $pgsqlAdapterFound ? mt('setup', 'The Zend database adapter for PostgreSQL is available.') : (
mt('setup', 'The Zend database adapter for PostgreSQL is missing.') mt('setup', 'The Zend database adapter for PostgreSQL is missing.')
) )
);*/ );
$configDir = $this->getConfigDir(); $configDir = $this->getConfigDir();
$requirements->addMandatory( $requirements->addMandatory(

View File

@ -306,17 +306,20 @@
var query = icinga.ui.selectionDataToQuery(selectionData); var query = icinga.ui.selectionDataToQuery(selectionData);
icinga.loader.loadUrl(url + '?' + query, $target); icinga.loader.loadUrl(url + '?' + query, $target);
icinga.ui.storeSelectionData(selectionData); icinga.ui.storeSelectionData(selectionData);
icinga.ui.provideSelectionCount();
} else if ($trs.length === 1) { } else if ($trs.length === 1) {
// display a single row // display a single row
$tr = $trs.first(); $tr = $trs.first();
icinga.loader.loadUrl($tr.attr('href'), $target); icinga.loader.loadUrl($tr.attr('href'), $target);
icinga.ui.storeSelectionData($tr.attr('href')); icinga.ui.storeSelectionData($tr.attr('href'));
icinga.ui.provideSelectionCount();
} else { } else {
// display nothing // display nothing
if ($target.attr('id') === 'col2') { if ($target.attr('id') === 'col2') {
icinga.ui.layout1col(); icinga.ui.layout1col();
} }
icinga.ui.storeSelectionData(null); icinga.ui.storeSelectionData(null);
icinga.ui.provideSelectionCount();
} }
return false; return false;

View File

@ -470,9 +470,25 @@
* (when only a single row was selected) or Null when nothing was selected. * (when only a single row was selected) or Null when nothing was selected.
*/ */
loadSelectionData: function() { loadSelectionData: function() {
this.provideSelectionCount();
return selectionData; return selectionData;
}, },
/**
* Set the selections row count hint info
*/
provideSelectionCount: function() {
var $count = $('.selection-info-count');
if (typeof selectionData === 'string') {
$count.text(1);
} else if (selectionData.length > 1) {
$count.text(selectionData.length);
} else {
$count.text(0);
}
},
/** /**
* Focus the given table by deselecting all selections on all other tables. * Focus the given table by deselecting all selections on all other tables.
* *