mirror of
https://github.com/Icinga/icingaweb2-module-businessprocess.git
synced 2026-02-18 10:20:25 -05:00
editor: sorry, monster commit :)
This commit is contained in:
parent
65dba837d9
commit
e057e61567
41 changed files with 3071 additions and 368 deletions
30
application/controllers/IndexController.php
Normal file
30
application/controllers/IndexController.php
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Module\Businessprocess\Controller;
|
||||
|
||||
class Businessprocess_IndexController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show a welcome page if no process is available
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->tabs()->add('welcome', array(
|
||||
'label' => $this->translate('Business Processes'),
|
||||
'url' => $this->getRequest()->getUrl()
|
||||
))->activate('welcome');
|
||||
|
||||
$configs = $this->storage()->listProcesses();
|
||||
|
||||
if (! empty($configs)) {
|
||||
// Redirect to show the first process if there is any
|
||||
$this->redirectNow(
|
||||
'businessprocess/process/show',
|
||||
array('config' => key($configs))
|
||||
);
|
||||
}
|
||||
|
||||
// Check back from time to time, maybe someone created a process
|
||||
$this->setAutorefreshInterval(30);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +1,91 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Module\Businessprocess\Controller;
|
||||
use Icinga\Module\Businessprocess\Simulation;
|
||||
use Icinga\Module\Businessprocess\Forms\ProcessForm;
|
||||
use Icinga\Module\Businessprocess\Forms\SimulationForm;
|
||||
use Icinga\Web\Url;
|
||||
|
||||
/*
|
||||
config = <file>
|
||||
process = <node>
|
||||
|
||||
*/
|
||||
class Businessprocess_NodeController extends Controller
|
||||
{
|
||||
// rename to config
|
||||
public function editAction()
|
||||
{
|
||||
$bp = $this->loadBp();
|
||||
$bp = $this->loadModifiedBpConfig();
|
||||
$node = $bp->getNode($this->getParam('node'));
|
||||
$detail = Url::fromPath(
|
||||
'businessprocess/node/edit',
|
||||
array(
|
||||
'config' => $this->view->configName,
|
||||
'node' => $node
|
||||
)
|
||||
);
|
||||
|
||||
$form = new ProcessForm();
|
||||
$form->setProcess($bp)
|
||||
->setSession($this->session())
|
||||
->setNode($node)
|
||||
->handleRequest();
|
||||
$this->view->form = ProcessForm::construct()
|
||||
->setProcess($bp)
|
||||
->setSession($this->session())
|
||||
->setNode($node)
|
||||
->setRedirectUrl(
|
||||
sprintf(
|
||||
'businessprocess/process/show?config=%s&unlocked#!%s',
|
||||
$bp->getName(),
|
||||
$detail->getAbsoluteUrl()
|
||||
)
|
||||
)
|
||||
->handleRequest();
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->node = $node;
|
||||
}
|
||||
|
||||
public function simulateAction()
|
||||
{
|
||||
$bp = $this->loadBp();
|
||||
$bp = $this->loadBpConfig();
|
||||
$nodename = $this->getParam('node');
|
||||
$node = $bp->getNode($nodename);
|
||||
$detail = Url::fromPath(
|
||||
$details = Url::fromPath(
|
||||
'businessprocess/node/simulate',
|
||||
array('node' => $nodename)
|
||||
array(
|
||||
'config' => $this->view->configName,
|
||||
'node' => $nodename
|
||||
)
|
||||
);
|
||||
$url = sprintf(
|
||||
'businessprocess/process/show?unlocked&config=%s#!%s',
|
||||
$bp->getName(),
|
||||
$details->getAbsoluteUrl()
|
||||
);
|
||||
$form = new SimulationForm();
|
||||
|
||||
$form->setProcess($bp)
|
||||
->setSession($this->session())
|
||||
$this->view->form = SimulationForm::construct()
|
||||
->setSimulation(new Simulation($bp, $this->session()))
|
||||
->setNode($node)
|
||||
// TODO: find a better way to handle redirects
|
||||
->setRedirectUrl(
|
||||
sprintf(
|
||||
'businessprocess/process/show?simulation=1&processName=%s#!%s',
|
||||
$bp->getName(),
|
||||
$detail->getAbsoluteUrl()
|
||||
)
|
||||
)
|
||||
->setRedirectUrl($url)
|
||||
->handleRequest();
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->view->node = $node;
|
||||
}
|
||||
|
||||
public function addAction()
|
||||
{
|
||||
$bp = $this->loadBpConfig();
|
||||
|
||||
$redirectUrl = Url::fromPath(
|
||||
'businessprocess/process/show',
|
||||
array('config' => $bp->getName())
|
||||
);
|
||||
|
||||
$this->view->form = ProcessForm::construct()
|
||||
->setProcess($bp)
|
||||
->setSession($this->session())
|
||||
->setRedirectUrl($redirectUrl)
|
||||
->handleRequest();
|
||||
}
|
||||
|
||||
public function deleteAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,144 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Module\Businessprocess\Controller;
|
||||
use Icinga\Module\Businessprocess\ConfigDiff;
|
||||
use Icinga\Module\Businessprocess\Simulation;
|
||||
use Icinga\Module\Businessprocess\ProcessChanges;
|
||||
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
|
||||
use \Exception;
|
||||
use Icinga\Module\Businessprocess\Forms\BpConfigForm;
|
||||
use Icinga\Module\Businessprocess\Forms\DeleteConfigForm;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Widget\Tabextension\DashboardAction;
|
||||
|
||||
|
||||
class Businessprocess_ProcessController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new business process configuration
|
||||
*/
|
||||
public function createAction()
|
||||
{
|
||||
$this->setTitle($this->translate('Create a new business process'));
|
||||
$this->tabsForCreate()->activate('create');
|
||||
|
||||
$this->view->form = BpConfigForm::construct()
|
||||
->setStorage($this->storage())
|
||||
->setRedirectUrl('businessprocess/process/show')
|
||||
->handleRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload an existing business process configuration
|
||||
*/
|
||||
public function uploadAction()
|
||||
{
|
||||
$this->setTitle($this->translate('Upload a business process config file'));
|
||||
$this->tabsForCreate()->activate('upload');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a business process tree
|
||||
*/
|
||||
public function showAction()
|
||||
{
|
||||
$this->redirectIfConfigChosen();
|
||||
|
||||
if ($this->params->get('unlocked')) {
|
||||
$bp = $this->loadModifiedBpConfig();
|
||||
$bp->unlock();
|
||||
} else {
|
||||
$bp = $this->loadBpConfig();
|
||||
}
|
||||
|
||||
$this->setTitle('Business Process "%s"', $bp->getTitle());
|
||||
$this->tabsForShow()->activate('show');
|
||||
|
||||
// Do not lock empty configs
|
||||
if ($bp->isEmpty() && ! $this->view->compact && $bp->isLocked()) {
|
||||
$this->redirectNow($this->url()->with('unlocked', true));
|
||||
}
|
||||
|
||||
if ($node = $this->params->get('node')) {
|
||||
// Render a specific node
|
||||
$this->view->nodeName = $node;
|
||||
$this->view->bp = $bp->getNode($node);
|
||||
} else {
|
||||
// Render a single process
|
||||
$this->view->bp = $bp;
|
||||
if ($bp->hasWarnings()) {
|
||||
$this->view->warnings = $bp->getWarnings();
|
||||
}
|
||||
}
|
||||
$this->setAutorefreshInterval(10);
|
||||
|
||||
$bp->retrieveStatesFromBackend();
|
||||
|
||||
if ($bp->isLocked()) {
|
||||
$this->tabs()->extend(new DashboardAction());
|
||||
} else {
|
||||
$simulation = new Simulation($bp, $this->session());
|
||||
if ($this->params->get('dismissSimulations')) {
|
||||
Notification::success(
|
||||
sprintf(
|
||||
$this->translate('%d applied simulation(s) have been dropped'),
|
||||
$simulation->count()
|
||||
)
|
||||
);
|
||||
$simulation->clear();
|
||||
$this->redirectNow($this->url()->without('dismissSimulations')->without('unlocked'));
|
||||
}
|
||||
|
||||
$bp->applySimulation($simulation);
|
||||
}
|
||||
|
||||
if ($this->params->get('mode') === 'toplevel') {
|
||||
$this->render('toplevel');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a business process from a toplevel perspective
|
||||
*/
|
||||
public function toplevelAction()
|
||||
{
|
||||
$this->redirectIfConfigChosen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the source code for a process
|
||||
*/
|
||||
public function sourceAction()
|
||||
{
|
||||
$this->tabsForConfig()->activate('source');
|
||||
$bp = $this->loadModifiedBpConfig();
|
||||
|
||||
$this->view->source = $bp->toLegacyConfigString();
|
||||
$this->view->showDiff = (bool) $this->params->get('showDiff', false);
|
||||
|
||||
if ($this->view->showDiff) {
|
||||
$this->view->diff = ConfigDiff::create(
|
||||
$this->storage()->getSource($this->view->configName),
|
||||
$this->view->source
|
||||
);
|
||||
$this->view->title = sprintf(
|
||||
$this->translate('%s: Source Code Differences'),
|
||||
$bp->getTitle()
|
||||
);
|
||||
} else {
|
||||
$this->view->title = sprintf(
|
||||
$this->translate('%s: Source Code'),
|
||||
$bp->getTitle()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a process configuration file
|
||||
*/
|
||||
public function downloadAction()
|
||||
{
|
||||
$bp = $this->loadBp();
|
||||
$bp = $this->loadModifiedBpConfig();
|
||||
|
||||
header(
|
||||
sprintf(
|
||||
'Content-Disposition: attachment; filename="%s.conf";',
|
||||
|
|
@ -20,73 +150,83 @@ class Businessprocess_ProcessController extends Controller
|
|||
echo $bp->toLegacyConfigString();
|
||||
// Didn't have time to lookup how to correctly disable our renderers
|
||||
// TODO: no exit :)
|
||||
exit;
|
||||
$this->doNotRender();
|
||||
}
|
||||
|
||||
public function showAction()
|
||||
/**
|
||||
* Modify a business process configuration
|
||||
*/
|
||||
public function configAction()
|
||||
{
|
||||
if ($this->getRequest()->isPost()) {
|
||||
$this->redirectNow($this->getRequest()->getUrl()->with('processName', $this->getRequest()->getPost('processName')));
|
||||
}
|
||||
$this->view->compact = $this->params->get('view') === 'compact';
|
||||
$storage = new LegacyStorage($this->Config()->getSection('global'));
|
||||
$this->view->processList = $storage->listProcesses();
|
||||
$process = $this->params->get('processName', key($this->view->processList));
|
||||
$this->view->processName = $process;
|
||||
$this->tabsForConfig()->activate('config');
|
||||
$bp = $this->loadModifiedBpConfig();
|
||||
|
||||
$this->view->tabs = $this->tabs()->activate('show');
|
||||
$this->view->title = 'Business Processes';
|
||||
$this->setTitle(
|
||||
$this->translate('%s: Configuration'),
|
||||
$bp->getTitle()
|
||||
);
|
||||
|
||||
$bp = $this->loadBp();
|
||||
try {
|
||||
$bp->retrieveStatesFromBackend();
|
||||
} catch (Exception $e) {
|
||||
$this->view->errors = array(
|
||||
'Could not retrieve process state: ' . $e->getMessage()
|
||||
$url = sprintf(
|
||||
'businessprocess/process/show?config=%s&unlocked#!%s',
|
||||
$bp->getName(),
|
||||
$this->getRequest()->getUrl()
|
||||
);
|
||||
$this->view->form = BpConfigForm::construct()
|
||||
->setProcessConfig($bp)
|
||||
->setSession($this->session())
|
||||
->setRedirectUrl($url)
|
||||
->handleRequest();
|
||||
|
||||
$this->view->deleteForm = DeleteConfigForm::construct()
|
||||
->setStorage($this->storage())
|
||||
->setController($this)
|
||||
->setBpConfig($bp)
|
||||
->handleRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect to our URL plus the chosen config if someone switched the
|
||||
* config in the appropriate dropdown list
|
||||
*/
|
||||
protected function redirectIfConfigChosen()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
if ($request->isPost()) {
|
||||
// We switched the process in the config dropdown list
|
||||
$params = array(
|
||||
'config' => $request->getPost('config')
|
||||
);
|
||||
$this->redirectNow($this->url()->with($params));
|
||||
}
|
||||
if ($process = $this->params->get('process')) {
|
||||
$this->view->bp = $bp->getNode($process);
|
||||
} else {
|
||||
$this->view->bp = $bp;
|
||||
if ($bp->hasWarnings()) {
|
||||
$this->view->warnings = $bp->getWarnings();
|
||||
}
|
||||
}
|
||||
$this->setAutorefreshInterval(10);
|
||||
|
||||
if ($this->params->get('showSource')) {
|
||||
$this->view->source = $bp->toLegacyConfigString();
|
||||
$this->render('source');
|
||||
}
|
||||
if ($this->params->get('simulation')) {
|
||||
$bp->setSimulationMode();
|
||||
$this->addSimulation($bp);
|
||||
}
|
||||
|
||||
if ($this->params->get('edit')) {
|
||||
$bp->setEditMode();
|
||||
}
|
||||
|
||||
if ($this->params->get('store')) {
|
||||
$storage->storeProcess($bp);
|
||||
$this->redirectNow($this->getRequest()->getUrl()->without('store'));
|
||||
}
|
||||
|
||||
if ($this->params->get('mode') === 'toplevel') {
|
||||
$this->render('toplevel');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function addSimulation($bp)
|
||||
protected function tabsForShow()
|
||||
{
|
||||
$simulations = $this->session()->get('simulations', array());
|
||||
foreach ($simulations as $node => $s) {
|
||||
$bp->getNode($node)
|
||||
->setState($s->state)
|
||||
->setAck($s->acknowledged)
|
||||
->setDowntime($s->in_downtime);
|
||||
}
|
||||
return $this->tabs()->add('show', array(
|
||||
'label' => $this->translate('Business Process'),
|
||||
'url' => $this->url()
|
||||
));
|
||||
}
|
||||
|
||||
protected function tabsForCreate()
|
||||
{
|
||||
return $this->tabs()->add('create', array(
|
||||
'label' => $this->translate('Create'),
|
||||
'url' => 'businessprocess/process/create'
|
||||
))->add('upload', array(
|
||||
'label' => $this->translate('Upload'),
|
||||
'url' => 'businessprocess/process/upload'
|
||||
));
|
||||
}
|
||||
|
||||
protected function tabsForConfig()
|
||||
{
|
||||
return $this->tabs()->add('config', array(
|
||||
'label' => $this->translate('Process Configuration'),
|
||||
'url' => $this->getRequest()->getUrl()->without('nix')->setPath('businessprocess/process/config')
|
||||
))->add('source', array(
|
||||
'label' => $this->translate('Source'),
|
||||
'url' => $this->getRequest()->getUrl()->without('nix')->setPath('businessprocess/process/source')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
164
application/forms/BpConfigForm.php
Normal file
164
application/forms/BpConfigForm.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess\Forms;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Module\Businessprocess\BusinessProcess;
|
||||
use Icinga\Module\Businessprocess\Form;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Url;
|
||||
|
||||
class BpConfigForm extends Form
|
||||
{
|
||||
protected $storage;
|
||||
|
||||
protected $backend;
|
||||
|
||||
protected $config;
|
||||
|
||||
protected $node;
|
||||
|
||||
protected $objectList = array();
|
||||
|
||||
protected $processList = array();
|
||||
|
||||
protected $session;
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$this->addElement('text', 'name', array(
|
||||
'label' => $this->translate('Name'),
|
||||
'required' => true,
|
||||
'description' => $this->translate(
|
||||
'This is the unique identifier of this process'
|
||||
),
|
||||
));
|
||||
|
||||
$this->addElement('text', 'title', array(
|
||||
'label' => $this->translate('Title'),
|
||||
'description' => $this->translate(
|
||||
'Usually this title will be shown for this process. Equals name'
|
||||
. ' if not given'
|
||||
),
|
||||
));
|
||||
|
||||
$this->addElement('select', 'backend_name', array(
|
||||
'label' => $this->translate('Backend'),
|
||||
'description' => $this->translate(
|
||||
'Icinga Web Monitoring Backend where current object states for'
|
||||
. ' this process should be retrieved from'
|
||||
),
|
||||
'multiOptions' => array(
|
||||
null => $this->translate('Use the configured default backend'),
|
||||
) + $this->listAvailableBackends()
|
||||
));
|
||||
|
||||
$this->addElement('select', 'state_type', array(
|
||||
'label' => $this->translate('State Type'),
|
||||
'required' => true,
|
||||
'description' => $this->translate(
|
||||
'Whether this process should be based on Icinga hard or soft states'
|
||||
),
|
||||
'multiOptions' => array(
|
||||
'hard' => $this->translate('Use HARD states'),
|
||||
'soft' => $this->translate('Use SOFT states'),
|
||||
)
|
||||
));
|
||||
$this->addElement('submit', $this->translate('Store'));
|
||||
}
|
||||
|
||||
protected function listAvailableBackends()
|
||||
{
|
||||
$keys = array_keys(Config::module('monitoring', 'backends')->toArray());
|
||||
return array_combine($keys, $keys);
|
||||
}
|
||||
|
||||
public function XXsetBackend($backend)
|
||||
{
|
||||
$this->backend = $backend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStorage($storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setProcessConfig($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->getElement('name')->setValue($config->getName());
|
||||
|
||||
if ($config->hasTitle()) {
|
||||
$this->getElement('title')->setValue($config->getTitle());
|
||||
}
|
||||
|
||||
if ($config->hasBackend()) {
|
||||
$this->getElement('backend_name')->setValue(
|
||||
$config->getBackend()->getName()
|
||||
);
|
||||
}
|
||||
|
||||
if ($config->usesSoftStates()) {
|
||||
$this->getElement('state_type')->setValue('soft');
|
||||
} else {
|
||||
$this->getElement('state_type')->setValue('hard');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSession($session)
|
||||
{
|
||||
$this->session = $session;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onSuccess()
|
||||
{
|
||||
$name = $this->getValue('name');
|
||||
$title = $this->getValue('title');
|
||||
$backend = $this->getValue('backend');
|
||||
|
||||
if ($this->config === null) {
|
||||
// New config
|
||||
$config = new BusinessProcess();
|
||||
$config->setName($name);
|
||||
if ($title) {
|
||||
$config->setTitle($title);
|
||||
}
|
||||
if ($backend) {
|
||||
$config->setBackendName($backend);
|
||||
}
|
||||
if ($this->getValue('state_type') === 'soft') {
|
||||
$config->useSoftStates();
|
||||
} else {
|
||||
$config->useHardStates();
|
||||
}
|
||||
$this->storage->storeProcess($config);
|
||||
$this->setRedirectUrl(
|
||||
Url::fromPath(
|
||||
$this->getRedirectUrl(),
|
||||
array('config' => $name, 'unlocked' => true)
|
||||
)
|
||||
);
|
||||
|
||||
Notification::success(sprintf('Process %s has been created', $name));
|
||||
} else {
|
||||
Notification::success(sprintf('Process %s has NOT YET been modified', $name));
|
||||
}
|
||||
/*
|
||||
$storage->storeProcess($bp);
|
||||
$modifications = $this->session->get('modifications', array());
|
||||
$node = $this->config->getNode($this->getValue('name'));
|
||||
$node->setChildNames($this->getValue('children'));
|
||||
$node->setOperator($this->getValue('operator'));
|
||||
$modifications[$this->config->getName()] = $this->config->toLegacyConfigString();
|
||||
$this->session->set('modifications', $modifications);
|
||||
$message = 'Process %s has been modified';
|
||||
Notification::success(sprintf($message, $this->config->getName()));
|
||||
*/
|
||||
}
|
||||
}
|
||||
46
application/forms/DeleteConfigForm.php
Normal file
46
application/forms/DeleteConfigForm.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess\Forms;
|
||||
|
||||
use Icinga\Module\Businessprocess\BusinessProcess;
|
||||
use Icinga\Module\Businessprocess\Form;
|
||||
use Icinga\Web\Notification;
|
||||
|
||||
class DeleteConfigForm extends Form
|
||||
{
|
||||
protected $storage;
|
||||
|
||||
protected $controller;
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$this->addHidden('name');
|
||||
$this->addElement('submit', $this->translate('Delete this process'));
|
||||
}
|
||||
|
||||
public function setStorage($storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setController($controller)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBpConfig($bp)
|
||||
{
|
||||
$this->getElement('name')->setValue($bp->getName());
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onSuccess()
|
||||
{
|
||||
$name = $this->getValue('name');
|
||||
$this->storage->deleteProcess($name);
|
||||
$this->setRedirectUrl('businessprocess');
|
||||
Notification::success(sprintf('Process %s has been deleted', $name));
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess\Forms;
|
||||
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Module\Businessprocess\Node;
|
||||
use Icinga\Module\Businessprocess\BpNode;
|
||||
use Icinga\Module\Businessprocess\Form;
|
||||
use Icinga\Module\Businessprocess\ProcessChanges;
|
||||
|
||||
class ProcessForm extends Form
|
||||
{
|
||||
|
|
@ -21,17 +23,22 @@ class ProcessForm extends Form
|
|||
|
||||
protected $session;
|
||||
|
||||
public function __construct($options = null)
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
public function setup()
|
||||
{
|
||||
$this->addElement('text', 'name', array(
|
||||
'label' => $this->translate('Process name'),
|
||||
'label' => $this->translate('Name'),
|
||||
'required' => true,
|
||||
'description' => $this->translate(
|
||||
'This is the unique identifier of this process'
|
||||
),
|
||||
));
|
||||
|
||||
$this->addElement('text', 'alias', array(
|
||||
'label' => $this->translate('Title'),
|
||||
'description' => $this->translate(
|
||||
'Usually this title will be shown for this node. Equals name'
|
||||
. ' if not given'
|
||||
),
|
||||
));
|
||||
|
||||
$this->addElement('select', 'operator', array(
|
||||
|
|
@ -40,7 +47,27 @@ class ProcessForm extends Form
|
|||
'multiOptions' => array(
|
||||
'&' => $this->translate('AND'),
|
||||
'|' => $this->translate('OR'),
|
||||
'min' => $this->translate('min')
|
||||
'1' => $this->translate('MIN 1'),
|
||||
'2' => $this->translate('MIN 2'),
|
||||
'3' => $this->translate('MIN 3'),
|
||||
'4' => $this->translate('MIN 4'),
|
||||
'5' => $this->translate('MIN 5'),
|
||||
'6' => $this->translate('MIN 6'),
|
||||
'7' => $this->translate('MIN 7'),
|
||||
'8' => $this->translate('MIN 8'),
|
||||
'9' => $this->translate('MIN 9'),
|
||||
)
|
||||
));
|
||||
|
||||
$this->addElement('select', 'display', array(
|
||||
'label' => $this->translate('Visualization'),
|
||||
'required' => true,
|
||||
'description' => $this->translate(
|
||||
'Where to show this process'
|
||||
),
|
||||
'multiOptions' => array(
|
||||
'0' => $this->translate('Subprocess only'),
|
||||
'1' => $this->translate('Toplevel Process'),
|
||||
)
|
||||
));
|
||||
|
||||
|
|
@ -49,8 +76,19 @@ class ProcessForm extends Form
|
|||
'required' => true,
|
||||
'size' => 14,
|
||||
'style' => 'width: 25em;',
|
||||
'description' => $this->translate('Hosts, services or other processes that should be part of this business process')
|
||||
'description' => $this->translate(
|
||||
'Hosts, services or other processes that should be part of this'
|
||||
. ' business process'
|
||||
)
|
||||
));
|
||||
|
||||
$this->addElement('text', 'url', array(
|
||||
'label' => $this->translate('Info URL'),
|
||||
'description' => $this->translate(
|
||||
'URL pointing to more information about this node'
|
||||
)
|
||||
));
|
||||
|
||||
$this->addElement('submit', $this->translate('Store'));
|
||||
}
|
||||
|
||||
|
|
@ -64,12 +102,15 @@ class ProcessForm extends Form
|
|||
|
||||
protected function fillAvailableChildren()
|
||||
{
|
||||
$this->getElement('children')->setMultiOptions(
|
||||
array(
|
||||
if (empty($this->processList)) {
|
||||
$children = $this->objectList;
|
||||
} else {
|
||||
$children = array(
|
||||
$this->translate('Other Business Processes') => $this->processList
|
||||
) + $this->objectList
|
||||
);
|
||||
) + $this->objectList;
|
||||
}
|
||||
|
||||
$this->getElement('children')->setMultiOptions($children);
|
||||
}
|
||||
|
||||
public function setProcess($process)
|
||||
|
|
@ -88,14 +129,19 @@ class ProcessForm extends Form
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setNode($node)
|
||||
public function setNode(Node $node)
|
||||
{
|
||||
$this->node = $node;
|
||||
|
||||
$this->setDefaults(array(
|
||||
'name' => (string) $node,
|
||||
'alias' => $node->hasAlias() ? $node->getAlias() : '',
|
||||
'display' => $node->getDisplay(),
|
||||
'operator' => $node->getOperator(),
|
||||
'url' => $node->getInfoUrl(),
|
||||
'children' => array_keys($node->getChildren())
|
||||
));
|
||||
$this->getElement('name')->setAttrib('readonly', true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -140,13 +186,63 @@ class ProcessForm extends Form
|
|||
|
||||
public function onSuccess()
|
||||
{
|
||||
$modifications = $this->session->get('modifications', array());
|
||||
$node = $this->process->getNode($this->getValue('name'));
|
||||
$node->setChildNames($this->getValue('children'));
|
||||
$node->setOperator($this->getValue('operator'));
|
||||
$modifications[$this->process->getName()] = $this->process->toLegacyConfigString();
|
||||
$this->session->set('modifications', $modifications);
|
||||
$message = 'Process %s has been modified';
|
||||
Notification::success(sprintf($message, $this->process->getName()));
|
||||
$changes = ProcessChanges::construct($this->process, $this->session);
|
||||
|
||||
$modifications = array();
|
||||
$children = $this->getValue('children');
|
||||
$alias = $this->getValue('alias');
|
||||
$operator = $this->getValue('operator');
|
||||
$display = $this->getValue('display');
|
||||
$url = $this->getValue('url');
|
||||
if (empty($url)) {
|
||||
$url = null;
|
||||
}
|
||||
if (empty($alias)) {
|
||||
$alias = null;
|
||||
}
|
||||
ksort($children);
|
||||
// TODO: rename
|
||||
|
||||
if ($node = $this->node) {
|
||||
|
||||
if ($display !== $node->getDisplay()) {
|
||||
$modifications['display'] = $display;
|
||||
}
|
||||
if ($operator !== $node->getOperator()) {
|
||||
$modifications['operator'] = $operator;
|
||||
}
|
||||
if ($children !== $node->getChildNames()) {
|
||||
$modifications['childNames'] = $children;
|
||||
}
|
||||
if ($url !== $node->getInfoUrl()) {
|
||||
$modifications['infoUrl'] = $url;
|
||||
}
|
||||
if ($alias !== $node->getAlias()) {
|
||||
$modifications['alias'] = $alias;
|
||||
}
|
||||
} else {
|
||||
$modifications = array(
|
||||
'display' => $display,
|
||||
'operator' => $operator,
|
||||
'childNames' => $children,
|
||||
'infoUrl' => $url,
|
||||
'alias' => $alias,
|
||||
);
|
||||
}
|
||||
if (! empty($modifications)) {
|
||||
|
||||
if ($this->node === null) {
|
||||
$changes->createNode($this->getValue('name'), $modifications);
|
||||
} else {
|
||||
$changes->modifyNode($this->node, $modifications);
|
||||
}
|
||||
|
||||
Notification::success(
|
||||
sprintf(
|
||||
'Process %s has been modified',
|
||||
$this->process->getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,20 +2,17 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess\Forms;
|
||||
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Module\Businessprocess\BpNode;
|
||||
use Icinga\Module\Businessprocess\Form;
|
||||
use Icinga\Module\Businessprocess\Simulation;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Request;
|
||||
|
||||
class SimulationForm extends Form
|
||||
{
|
||||
protected $backend;
|
||||
|
||||
protected $process;
|
||||
|
||||
protected $node;
|
||||
|
||||
protected $session;
|
||||
protected $simulation;
|
||||
|
||||
public function __construct($options = null)
|
||||
{
|
||||
|
|
@ -33,6 +30,7 @@ class SimulationForm extends Form
|
|||
'1' => $this->translate('WARNING'),
|
||||
'2' => $this->translate('CRITICAL'),
|
||||
'3' => $this->translate('UNKNOWN'),
|
||||
'99' => $this->translate('PENDING'),
|
||||
)
|
||||
));
|
||||
|
||||
|
|
@ -51,19 +49,6 @@ class SimulationForm extends Form
|
|||
$this->addElement('submit', $this->translate('Apply'));
|
||||
}
|
||||
|
||||
public function setBackend($backend)
|
||||
{
|
||||
$this->backend = $backend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setProcess($process)
|
||||
{
|
||||
$this->process = $process;
|
||||
$this->setBackend($process->getBackend());
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNode($node)
|
||||
{
|
||||
$this->node = $node;
|
||||
|
|
@ -72,53 +57,41 @@ class SimulationForm extends Form
|
|||
'acknowledged' => $node->isAcknowledged(),
|
||||
'in_downtime' => $node->isInDowntime(),
|
||||
));
|
||||
return $this->checkNodeSession();
|
||||
return $this->checkDefaults();
|
||||
}
|
||||
|
||||
public function setSession($session)
|
||||
public function setSimulation($simulation)
|
||||
{
|
||||
$this->session = $session;
|
||||
return $this->checkNodeSession();
|
||||
$this->simulation = $simulation;
|
||||
return $this->checkDefaults();
|
||||
}
|
||||
|
||||
protected function checkNodeSession()
|
||||
protected function checkDefaults()
|
||||
{
|
||||
if ($this->node === null || $this->session === null) {
|
||||
return $this;
|
||||
if ($this->node !== null
|
||||
&& $this->simulation !== null
|
||||
&& $this->simulation->hasNode((string) $this->node)
|
||||
) {
|
||||
$this->setDefaults((array) $this->simulation->getNode((string) $this->node));
|
||||
}
|
||||
|
||||
$simulations = $this->session->get('simulations', array());
|
||||
$node = (string) $this->node;
|
||||
if (array_key_exists($node, $simulations)) {
|
||||
$this->setDefaults(array(
|
||||
'simulate' => true,
|
||||
'state' => $simulations[$node]->state,
|
||||
'in_downtime' => $simulations[$node]->in_downtime,
|
||||
'acknowledged' => $simulations[$node]->acknowledged,
|
||||
));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onSuccess()
|
||||
{
|
||||
$node = (string) $this->node;
|
||||
$simulations = $this->session->get('simulations', array());
|
||||
|
||||
if ($this->getValue('state') === '') {
|
||||
if (array_key_exists($node, $simulations)) {
|
||||
if ($this->simulation->remove($node)) {
|
||||
Notification::success($this->translate('Simulation has been removed'));
|
||||
unset($simulations[$node]);
|
||||
$this->session->set('simulations', $simulations);
|
||||
}
|
||||
} else {
|
||||
$simulations[$node] = (object) array(
|
||||
Notification::success($this->translate('Simulation has been set'));
|
||||
$this->simulation->set($node, (object) array(
|
||||
'state' => $this->getValue('state'),
|
||||
'acknowledged' => $this->getValue('acknowledged'),
|
||||
'in_downtime' => $this->getValue('in_downtime'),
|
||||
);
|
||||
$this->session->set('simulations', $simulations);
|
||||
'in_downtime' => $this->getValue('in_downtime'),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
101
application/forms/_CreateConfigForm.php
Normal file
101
application/forms/_CreateConfigForm.php
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess\Forms;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Module\Businessprocess\BusinessProcess;
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Request;
|
||||
|
||||
class CreateConfigForm extends Form
|
||||
{
|
||||
public function setup()
|
||||
{
|
||||
$this->addElement('text', 'name', array(
|
||||
'label' => $this->translate('Name'),
|
||||
'required' => true,
|
||||
'description' => $this->translate('This is the unique identifier of this process'),
|
||||
));
|
||||
|
||||
$this->addElement('text', 'title', array(
|
||||
'label' => $this->translate('Title'),
|
||||
'description' => $this->translate('Usually this title will be shown for this process. Equals name if not given'),
|
||||
));
|
||||
|
||||
$this->addElement('select', 'backend_name', array(
|
||||
'label' => $this->translate('Backend'),
|
||||
'required' => true,
|
||||
'description' => $this->translate('Icinga Web Monitoring Backend where current object states for this process should be retrieved from'),
|
||||
'multiOptions' => array(
|
||||
null => $this->translate('Use current default backend'),
|
||||
) + $this->listAvailableBackends()
|
||||
));
|
||||
|
||||
$this->addElement('select', 'state_type', array(
|
||||
'label' => $this->translate('State Type'),
|
||||
'required' => true,
|
||||
'description' => $this->translate('Whether this process should be based on Icinga hard or soft states'),
|
||||
'multiOptions' => array(
|
||||
'hard' => $this->translate('Use HARD states'),
|
||||
'soft' => $this->translate('Use SOFT states'),
|
||||
)
|
||||
));
|
||||
$this->addElement('submit', $this->translate('Store'));
|
||||
}
|
||||
|
||||
protected function listAvailableBackends()
|
||||
{
|
||||
$keys = array_keys(Config::module('monitoring', 'backends')->toArray());
|
||||
return array_combine($keys, $keys);
|
||||
}
|
||||
|
||||
public function setBackend($backend)
|
||||
{
|
||||
$this->backend = $backend;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setProcessConfig($config)
|
||||
{
|
||||
$this->process = $config;
|
||||
$this->getElement('name')->setValue($config->getName());
|
||||
|
||||
if ($config->hasTitle()) {
|
||||
$this->getElement('title')->setValue($config->getTitle());
|
||||
}
|
||||
|
||||
if ($config->hasBackend()) {
|
||||
$this->getElement('backend_name')->setValue($config->getBackend()->getName());
|
||||
}
|
||||
|
||||
if ($config->usesSoftStates()) {
|
||||
$this->getElement('state_type')->setValue('soft');
|
||||
} else {
|
||||
$this->getElement('state_type')->setValue('hard');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSession($session)
|
||||
{
|
||||
$this->session = $session;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function onSuccess()
|
||||
{
|
||||
/*
|
||||
$storage->storeProcess($bp);
|
||||
$modifications = $this->session->get('modifications', array());
|
||||
$node = $this->process->getNode($this->getValue('name'));
|
||||
$node->setChildNames($this->getValue('children'));
|
||||
$node->setOperator($this->getValue('operator'));
|
||||
$modifications[$this->process->getName()] = $this->process->toLegacyConfigString();
|
||||
$this->session->set('modifications', $modifications);
|
||||
$message = 'Process %s has been modified';
|
||||
Notification::success(sprintf($message, $this->process->getName()));
|
||||
*/
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -2,42 +2,125 @@
|
|||
# Copyright (C) 2015 Icinga Development Team
|
||||
# This file is distributed under the same license as Businessprocess Module.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Businessprocess Module (2.0.0-beta1)\n"
|
||||
"Report-Msgid-Bugs-To: dev@icinga.org\n"
|
||||
"POT-Creation-Date: 2015-03-03 13:25+0100\n"
|
||||
"PO-Revision-Date: 2015-03-03 13:25+0100\n"
|
||||
"POT-Creation-Date: 2015-03-16 06:19+0100\n"
|
||||
"PO-Revision-Date: 2015-03-16 09:04+0100\n"
|
||||
"Last-Translator: Thomas Gelf <thomas@gelf.net>\n"
|
||||
"Language: de_DE\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:41
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:83
|
||||
#, php-format
|
||||
msgid "%d applied simulation(s) have been dropped"
|
||||
msgstr "%d angewendete Simulation(en) wurde(n) entfernt"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/Controller.php:73
|
||||
#, php-format
|
||||
msgid "%d pending change(s) have been dropped"
|
||||
msgstr "%d vorgenommene Änderung(en) wurde(n) verworfen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:165
|
||||
#, php-format
|
||||
msgid "%s: Configuration"
|
||||
msgstr "%s: Konfiguration"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:129
|
||||
#, php-format
|
||||
msgid "%s: Source Code"
|
||||
msgstr "%s: Quellcode"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:124
|
||||
#, php-format
|
||||
msgid "%s: Source Code Differences"
|
||||
msgstr "%s: Quellcode Unterschiede"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:48
|
||||
msgid "AND"
|
||||
msgstr "UND"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:44
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:42
|
||||
msgid "Acknowledged"
|
||||
msgstr "Bestätigt"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:51
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/node/add.phtml:8
|
||||
msgid "Add new process node"
|
||||
msgstr "Neuen Knoten hinzufügen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:49
|
||||
msgid "Apply"
|
||||
msgstr "Anwenden"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/index/index.phtml:8
|
||||
#, php-format
|
||||
msgid ""
|
||||
"As no business process has been defined yet you might want to create a %s or "
|
||||
"upload an %s."
|
||||
msgstr ""
|
||||
"Nachdem noch kein Business-Prozess definiert wurde, möchtest du vermutlich "
|
||||
"einen %s erstellen oder einen %s hochladen."
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:47
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:27
|
||||
msgid "Backend"
|
||||
msgstr "Backend"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:206
|
||||
msgid "Business Process"
|
||||
msgstr "Business-Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/configuration.php:4
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/IndexController.php:13
|
||||
msgid "Business Processes"
|
||||
msgstr "Business-Prozesse"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:34
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:31
|
||||
msgid "CRITICAL"
|
||||
msgstr "KRITISCH"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:52
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/index/index.phtml:6
|
||||
msgid "Configure your first business process"
|
||||
msgstr "Konfiguriere deinen ersten Business-Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/BusinessProcess.php:297
|
||||
#, php-format
|
||||
msgid "Could not retrieve process state: %s"
|
||||
msgstr "Konnte den Prozess-Status nicht ermitteln: %s"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:214
|
||||
msgid "Create"
|
||||
msgstr "Erstelle"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:21
|
||||
msgid "Create a new business process"
|
||||
msgstr "Neuen Business-Prozess erstellen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/DeleteConfigForm.php:18
|
||||
msgid "Delete this process"
|
||||
msgstr "Lösche diesen Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:40
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:51
|
||||
msgid "Dismiss"
|
||||
msgstr "Verwerfen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/source.phtml:6
|
||||
msgid "Download process configuration"
|
||||
msgstr "Prozess-Konfiguration herunterladen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/source.phtml:10
|
||||
msgid "Highlight changes"
|
||||
msgstr "Änderungen hervorheben"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:80
|
||||
msgid ""
|
||||
"Hosts, services or other processes that should be part of this business "
|
||||
"process"
|
||||
|
|
@ -45,71 +128,261 @@ msgstr ""
|
|||
"Hosts, Services oder andere Prozesse welche Teil dieses Business-Prozesses "
|
||||
"sein sollen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:48
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:49
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:29
|
||||
msgid ""
|
||||
"Icinga Web Monitoring Backend where current object states for this process "
|
||||
"should be retrieved from"
|
||||
msgstr ""
|
||||
"Das Icinga Web Monitoring Backend von welchem die Status-Informationen für "
|
||||
"diesen Prozess bezogen werden sollen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:46
|
||||
msgid "In downtime"
|
||||
msgstr "In Downtime"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/Node.php:304
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:86
|
||||
msgid "Info URL"
|
||||
msgstr "Info-URL"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:13
|
||||
msgid "Lock this process"
|
||||
msgstr "Sperre diesen Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:50
|
||||
msgid "MIN 1"
|
||||
msgstr "MIN 1"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:51
|
||||
msgid "MIN 2"
|
||||
msgstr "MIN 2"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:52
|
||||
msgid "MIN 3"
|
||||
msgstr "MIN 3"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:53
|
||||
msgid "MIN 4"
|
||||
msgstr "MIN 4"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:54
|
||||
msgid "MIN 5"
|
||||
msgstr "MIN 5"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:55
|
||||
msgid "MIN 6"
|
||||
msgstr "MIN 6"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:56
|
||||
msgid "MIN 7"
|
||||
msgstr "MIN 7"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:57
|
||||
msgid "MIN 8"
|
||||
msgstr "MIN 8"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:58
|
||||
msgid "MIN 9"
|
||||
msgstr "MIN 9"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/node/edit.phtml:10
|
||||
#, php-format
|
||||
msgid "Modify process node: %s"
|
||||
msgstr "Bearbeite Knoten: %s"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/BpNode.php:268
|
||||
msgid "Modify this node"
|
||||
msgstr "Bearbeite diesen Knoten"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/Node.php:350
|
||||
msgid "More information"
|
||||
msgstr "Weitere Informationen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:32
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:31
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:16
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:29
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/BusinessProcess.php:519
|
||||
#, php-format
|
||||
msgid "No business process nodes for \"%s\" have been defined yet"
|
||||
msgstr "Es wurden noch keine Business-Prozess Knoten für \"%s\" definiert"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/BusinessProcess.php:467
|
||||
#, php-format
|
||||
msgid "Node \"%s\" has been defined twice"
|
||||
msgstr "Der Knoden \"%s\" wurde doppelt definiert"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:29
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:42
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:49
|
||||
msgid "OR"
|
||||
msgstr "ODER"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:38
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:45
|
||||
msgid "Operator"
|
||||
msgstr "Operator"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:69
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:109
|
||||
msgid "Other Business Processes"
|
||||
msgstr "Andere Business-Prozesse"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:40
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:33
|
||||
msgid "PENDING"
|
||||
msgstr "PENDING"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/BusinessProcess.php:538
|
||||
#, php-format
|
||||
msgid "Parser waring on %s:%s: %s"
|
||||
msgstr "Parse-Warnung an %s:%s: %s"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:38
|
||||
msgid "Plugin output"
|
||||
msgstr "Plugin-Ausgabe"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:48
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:225
|
||||
msgid "Process Configuration"
|
||||
msgstr "Prozess-Konfiguration"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:75
|
||||
msgid "Process components"
|
||||
msgstr "Prozess-Komponenten"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:33
|
||||
msgid "Process name"
|
||||
msgstr "Prozess-Name"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/configuration.php:3
|
||||
msgid "Reporting"
|
||||
msgstr "Reporting"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/library/Businessprocess/Controller.php:40
|
||||
msgid "Show"
|
||||
msgstr "Zeige"
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/source.phtml:8
|
||||
msgid "Show source code"
|
||||
msgstr "Quellcode anzeigen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:111
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:86
|
||||
msgid "Simulation has been removed"
|
||||
msgstr "Simulation wurde entfernt"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:29
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:89
|
||||
msgid "Simulation has been set"
|
||||
msgstr "Simulation wurde gesended"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:228
|
||||
msgid "Source"
|
||||
msgstr "Quelle"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:26
|
||||
msgid "State"
|
||||
msgstr "Status"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:54
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:58
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:36
|
||||
msgid "State Type"
|
||||
msgstr "Statustyp"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:36
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:68
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:44
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:92
|
||||
msgid "Store"
|
||||
msgstr "Speichern"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:35
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:69
|
||||
msgid "Subprocess only"
|
||||
msgstr "Nur Sub-Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/upload.phtml:8
|
||||
msgid "This has not been implemented yet"
|
||||
msgstr "Das wurde noch nicht implementiert"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:34
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:18
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:32
|
||||
msgid "This is the unique identifier of this process"
|
||||
msgstr "Das ist der eindeutige Identifier dieses Prozesses"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:33
|
||||
#, php-format
|
||||
msgid "This process has %d pending change(s)."
|
||||
msgstr "Dieser Prozess hat %d ungespeicherte Änderung(en)"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:48
|
||||
#, php-format
|
||||
msgid "This process shows %d simulated state(s)."
|
||||
msgstr "Dieser Prozess zeigt %d simulierte Zustände"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:39
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:22
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:37
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:70
|
||||
msgid "Toplevel Process"
|
||||
msgstr "Toplevel-Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:32
|
||||
msgid "UNKNOWN"
|
||||
msgstr "UNBEKANNT"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:31
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:88
|
||||
msgid "URL pointing to more information about this node"
|
||||
msgstr "URL zu mehr Informationen über diesen Knoten"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/process/show.phtml:10
|
||||
msgid "Unlock this process"
|
||||
msgstr "Entsperre diesen Prozess"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:217
|
||||
msgid "Upload"
|
||||
msgstr "Upload"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/controllers/ProcessController.php:35
|
||||
msgid "Upload a business process config file"
|
||||
msgstr "Lade eine Business-Prozess Konfigurationsdatei hoch"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:64
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:40
|
||||
msgid "Use HARD states"
|
||||
msgstr "HARD-States benutzen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:65
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:41
|
||||
msgid "Use SOFT states"
|
||||
msgstr "SOFT-States benutzen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:31
|
||||
msgid "Use current default backend"
|
||||
msgstr "Aktuelles Standard-Backend benutzen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:28
|
||||
msgid "Use current state"
|
||||
msgstr "Aktuellen Status benutzen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:33
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:53
|
||||
msgid "Use the configured default backend"
|
||||
msgstr "Benutze das konfigurierte Standard-Backend"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:39
|
||||
msgid ""
|
||||
"Usually this title will be shown for this node. Equals name if not given"
|
||||
msgstr ""
|
||||
"Für gewöhnlich wird dieser Titel für diesen Knoten angezeigt. Entspricht dem "
|
||||
"Namen, wenn nicht angegeben"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:41
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:23
|
||||
msgid ""
|
||||
"Usually this title will be shown for this process. Equals name if not given"
|
||||
msgstr ""
|
||||
"Für gewöhnlich wird dieser Titel für diesen Prozess angezeigt. Entspricht "
|
||||
"dem Namen, wenn nicht angegeben"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:63
|
||||
msgid "Visualization"
|
||||
msgstr "Darstellung"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/SimulationForm.php:30
|
||||
msgid "WARNING"
|
||||
msgstr "WARNUNG"
|
||||
|
||||
|
|
@ -117,6 +390,25 @@ msgstr "WARNUNG"
|
|||
msgid "Warnings"
|
||||
msgstr "Warnungen"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:43
|
||||
msgid "min"
|
||||
msgstr "min"
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/ProcessForm.php:66
|
||||
msgid "Where to show this process"
|
||||
msgstr "Wo soll dieser Prozess angezeigt werden"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/BpConfigForm.php:61
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/forms/_CreateConfigForm.php:38
|
||||
msgid "Whether this process should be based on Icinga hard or soft states"
|
||||
msgstr "Ob dieser Prozess auf Icinga's hard- oder soft-states basieren soll"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/index/index.phtml:10
|
||||
msgid "existing one"
|
||||
msgstr "einen existierenden"
|
||||
|
||||
#: /usr/local/icingaweb-modules/businessprocess/application/views/scripts/index/index.phtml:9
|
||||
msgid "new business process"
|
||||
msgstr "neuen Business-Prozess"
|
||||
|
||||
#~ msgid "Show"
|
||||
#~ msgstr "Zeige"
|
||||
|
||||
#~ msgid "min"
|
||||
#~ msgstr "min"
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
<a href="<?= $this->url('businessprocess/process/download', array(
|
||||
'process' => $this->processName
|
||||
)) ?>" target="_self" title="<?= $this->escape('Download process configuration') ?>"><?= $this->icon('download') ?></a>
|
||||
|
||||
12
application/views/scripts/index/index.phtml
Normal file
12
application/views/scripts/index/index.phtml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<h1><?= $this->translate('Configure your first business process') ?></h1>
|
||||
<p><?= sprintf (
|
||||
$this->translate('As no business process has been defined yet you might want to create a %s or upload an %s.'),
|
||||
$this->qlink($this->translate('new business process'), 'businessprocess/process/create'),
|
||||
$this->qlink($this->translate('existing one'), 'businessprocess/process/upload')
|
||||
) ?></p>
|
||||
</div>
|
||||
10
application/views/scripts/node/add.phtml
Normal file
10
application/views/scripts/node/add.phtml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Module\Businessprocess\HostNode;
|
||||
use Icinga\Module\Businessprocess\ServiceNode;
|
||||
use Icinga\Module\Businessprocess\BpNode;
|
||||
|
||||
?><div class="content">
|
||||
<h1><?= $this->translate('Add new process node') ?></h1>
|
||||
<?= $this->form ?>
|
||||
</div>
|
||||
|
|
@ -5,6 +5,11 @@ use Icinga\Module\Businessprocess\ServiceNode;
|
|||
use Icinga\Module\Businessprocess\BpNode;
|
||||
|
||||
?><div class="content">
|
||||
<h1><?= $this->escape($node) ?></h1>
|
||||
<h1><?= $this->escape(
|
||||
sprintf(
|
||||
$this->translate('Modify process node: %s'),
|
||||
$node
|
||||
)
|
||||
) ?></h1>
|
||||
<?= $this->form ?>
|
||||
</div>
|
||||
|
|
|
|||
16
application/views/scripts/process/config.phtml
Normal file
16
application/views/scripts/process/config.phtml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?>
|
||||
<a href="<?= $this->url('businessprocess/process/source', array(
|
||||
'config' => $this->configName
|
||||
)) ?>" title="<?= $this->escape('Show configuration source') ?>"><?= $this->icon('doc-text') ?></a>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<?= $this->form ?>
|
||||
<div data-base-target="_main">
|
||||
<?= $this->deleteForm ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
9
application/views/scripts/process/create.phtml
Normal file
9
application/views/scripts/process/create.phtml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?></h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<?= $this->form ?>
|
||||
</div>
|
||||
|
||||
|
|
@ -1,29 +1,66 @@
|
|||
<?php if (! $this->compact): ?>
|
||||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?>
|
||||
<a href="<?= $this->url()->with('mode', 'toplevel') ?>" title="<?= $this->escape('Switch to toplevel view') ?>"><?= $this->icon('dashboard') ?></a>
|
||||
<?= $this->render('simulationlink.phtml') ?>
|
||||
<?= $this->render('editlink.phtml') ?>
|
||||
<?= $this->render('downloadlink.phtml') ?>
|
||||
<h1><form method="post" action="<?= $this->url()->without('node')->without('unlocked') ?>">
|
||||
<?= $this->formSelect('config', $this->configName, array('class' => 'autosubmit'), $this->processList) ?>
|
||||
</form>
|
||||
|
||||
<a href="<?= $this->url()->with('mode', 'toplevel')->without('unlocked') ?>" title="<?= $this->escape('Switch to toplevel view') ?>" data-base-target="_main"><?= $this->icon('dashboard') ?></a>
|
||||
<?php if ($this->bpconfig->isLocked()): ?>
|
||||
<a href="<?= $this->url()->with('unlocked', true) ?>" title="<?= $this->escape($this->translate('Unlock this process')) ?>"><?= $this->icon('lock') ?></a>
|
||||
<?php else: ?>
|
||||
<?php if (! $this->bpconfig->isEmpty()): ?>
|
||||
<a href="<?= $this->url()->without('unlocked') ?>" style="color: red" title="<?= $this->escape($this->translate('Lock this process')) ?>" data-base-target="_main"><?= $this->icon('lock-open') ?></a>
|
||||
<?php endif ?>
|
||||
<a href="<?= $this->url('businessprocess/process/config', array('config' => $this->configName)) ?>" title="<?= $this->escape('Modify this process') ?>" data-base-target="_next"><?= $this->icon('wrench') ?></a>
|
||||
<?php endif ?>
|
||||
<a href="<?= $this->url('businessprocess/process/create') ?>" title="<?= $this->escape('Create a new business process configuration') ?>" data-base-target="_main"><?= $this->icon('plus') ?></a>
|
||||
</h1>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="content<?= $this->compact ? ' compact' : '' ?>" data-base-target="_next">
|
||||
<?php if (! $this->compact): ?>
|
||||
<form method="post" action="<?= $this->url()->without('process') ?>" data-base-target="_self">
|
||||
<?= $this->formSelect('processName', $this->processName, array('class' => 'autosubmit'), $this->processList) ?>
|
||||
</form>
|
||||
<?php if (! $this->bpconfig->isLocked()): ?>
|
||||
<?= $this->qlink('Add new node', 'businessprocess/node/add', array('config' => $this->configName)) ?>
|
||||
<?php endif ?>
|
||||
<?php if (! empty($this->errors)): ?>
|
||||
<?php if ($this->bpconfig->hasErrors() || $this->bpconfig->hasChanges() || $this->bpconfig->hasSimulations()): ?>
|
||||
<ul class="error">
|
||||
<?php foreach ($this->errors as $error): ?>
|
||||
<?php foreach ($this->bpconfig->getErrors() as $error): ?>
|
||||
<li><?= $this->escape($error) ?></li>
|
||||
<?php endforeach ?>
|
||||
<?php if ($this->bpconfig->hasChanges()): ?>
|
||||
<li><?= sprintf(
|
||||
$this->translate('This process has %d pending change(s).'),
|
||||
$this->bpconfig->countChanges()
|
||||
) ?> <?= $this->qlink(
|
||||
$this->translate('Store'),
|
||||
'businessprocess/process/config',
|
||||
array('config' => $this->configName)
|
||||
) ?> <?= $this->qlink(
|
||||
$this->translate('Dismiss'),
|
||||
$this->url()->with('dismissChanges', true),
|
||||
null,
|
||||
array('data-base-target' => '_main')
|
||||
) ?></li>
|
||||
<?php endif ?>
|
||||
<?php if ($this->bpconfig->hasSimulations()): ?>
|
||||
<li><?= sprintf(
|
||||
$this->translate('This process shows %d simulated state(s).'),
|
||||
$this->bpconfig->countSimulations()
|
||||
) ?> <?= $this->qlink(
|
||||
$this->translate('Dismiss'),
|
||||
$this->url()->with('dismissSimulations', true),
|
||||
null,
|
||||
array('data-base-target' => '_main')
|
||||
) ?></li>
|
||||
<?php endif ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
<div class="bp">
|
||||
<?= $this->bp->renderHtml($this) ?>
|
||||
<?php if (! $this->bpconfig->isLocked()): ?>
|
||||
<?= $this->bp->renderUnbound($this) ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?= $this->render('warnings.phtml') ?>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,37 @@
|
|||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?>
|
||||
<a href="<?= $this->url()->without('mode') ?>" title="<?= $this->escape('Switch to tree view') ?>" style="float: right"><?= $this->icon('sitemap') ?></a>
|
||||
<?= $this->render('simulationlink.phtml') ?>
|
||||
<?= $this->render('editlink.phtml') ?>
|
||||
<a href="<?= $this->url('businessprocess/process/download', array(
|
||||
'config' => $this->configName
|
||||
)) ?>" target="_self" title="<?= $this->escape($this->translate('Download process configuration')) ?>"><?= $this->icon('download') ?></a>
|
||||
<?php if ($this->showDiff): ?>
|
||||
<a href="<?= $this->url()->without('showDiff') ?>" title="<?= $this->escape($this->translate('Show source code')) ?>"><?= $this->icon('doc-text') ?></a>
|
||||
<?php else: ?>
|
||||
<a href="<?= $this->url()->with('showDiff', true) ?>" title="<?= $this->escape($this->translate('Highlight changes')) ?>"><?= $this->icon('flapping') ?></a>
|
||||
<?php endif ?>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="content" data-base-target="_next">
|
||||
<pre>
|
||||
<div class="content">
|
||||
<?php if ($this->showDiff): ?>
|
||||
<div class="diff">
|
||||
<?= $this->diff->renderHtml() ?>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<table class="sourcecode">
|
||||
<?php
|
||||
|
||||
$cnt = 0;
|
||||
$lines = preg_split('~\r?\n~', $this->source);
|
||||
$len = ceil(log(count($lines), 10));
|
||||
$rowhtml = sprintf('<tr><th>%%0%dd: </th><td>%%s<br></td></tr>', $len);
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$cnt++;
|
||||
printf("%0" . $len . "d: %s\n", $cnt, $this->escape($line));
|
||||
printf($rowhtml, $cnt, $this->escape($line));
|
||||
}
|
||||
|
||||
?>
|
||||
</pre>
|
||||
</table>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -14,28 +14,22 @@ if ($count < 20) {
|
|||
<?php if (! $this->compact): ?>
|
||||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?>
|
||||
<h1><form method="post" action="<?= $this->url()->without('process') ?>" data-base-target="_self">
|
||||
<?= $this->formSelect('node', $this->nodeName, array('class' => 'autosubmit'), $this->processList) ?>
|
||||
</form>
|
||||
<a href="<?= $this->url()->without('mode') ?>" title="<?= $this->escape('Switch to tree view') ?>" style="float: right"><?= $this->icon('sitemap') ?></a>
|
||||
<?= $this->render('simulationlink.phtml') ?>
|
||||
<?= $this->render('editlink.phtml') ?>
|
||||
<?= $this->render('downloadlink.phtml') ?>
|
||||
</h1>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<div class="content<?= $this->compact ? ' compact' : '' ?>" data-base-target="_next">
|
||||
<?php if (! $this->compact): ?>
|
||||
<form method="post" action="<?= $this->url()->without('process') ?>" data-base-target="_self">
|
||||
<?= $this->formSelect('processName', $this->processName, array('class' => 'autosubmit'), $this->processList) ?>
|
||||
</form>
|
||||
<?php endif ?>
|
||||
<div class="toplevel <?= $howMany ?>" data-base-target="_next">
|
||||
<?php foreach ($this->bp->getChildren() as $name => $node): ?>
|
||||
<div class="<?= strtolower($node->getStateName()) ?><?= $node->isHandled() ? ' handled' : '' ?>">
|
||||
<?php if ($node instanceof ImportedNode): ?>
|
||||
<a href="<?= $this->url('businessprocess/process/show', array('processName' => $node->getConfigName(), 'process' => $name)) ?>"><?= $this->escape($node->getAlias()) ?></a>
|
||||
<a href="<?= $this->url('businessprocess/process/show', array('config' => $this->configName, 'node' => $name)) ?>"><?= $this->escape($node->getAlias()) ?></a>
|
||||
<?php else: ?>
|
||||
<a href="<?= $this->url('businessprocess/process/show', array('processName' => $this->processName, 'process' => $name)) ?>"><?= $this->escape($node->getAlias()) ?></a>
|
||||
<a href="<?= $this->url('businessprocess/process/show', array('config' => $this->configName, 'node' => $this->nodeName)) ?>"><?= $this->escape($node->getAlias()) ?></a>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
|
|
|
|||
11
application/views/scripts/process/upload.phtml
Normal file
11
application/views/scripts/process/upload.phtml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<div class="controls">
|
||||
<?= $this->tabs ?>
|
||||
<h1><?= $this->escape($this->title) ?></h1>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<ul class="error">
|
||||
<li><?= $this->translate('This has not been implemented yet') ?></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
|
||||
$section = $this->menuSection($this->translate('Reporting'))
|
||||
->add($this->translate('Business Processes'))
|
||||
->setUrl('businessprocess/process/show');
|
||||
->setUrl('businessprocess');
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
|
||||
class BpNode extends Node
|
||||
{
|
||||
|
|
@ -37,7 +38,7 @@ class BpNode extends Node
|
|||
{
|
||||
if ($this->counters === null) {
|
||||
$this->getState();
|
||||
$this->counters = array(0, 0, 0, 0);
|
||||
$this->counters = array(0, 0, 0, 0, 99 => 0);
|
||||
foreach ($this->children as $child) {
|
||||
if ($child instanceof BpNode) {
|
||||
$counters = $child->getStateSummary();
|
||||
|
|
@ -160,36 +161,42 @@ class BpNode extends Node
|
|||
}
|
||||
switch ($this->operator) {
|
||||
case self::OP_AND:
|
||||
$state = max($sort_states);
|
||||
$sort_state = max($sort_states);
|
||||
break;
|
||||
case self::OP_OR:
|
||||
$state = min($sort_states);
|
||||
$sort_state = min($sort_states);
|
||||
break;
|
||||
default:
|
||||
// MIN:
|
||||
sort($sort_states);
|
||||
|
||||
// default -> unknown
|
||||
$state = 2 << self::SHIFT_FLAGS;
|
||||
$sort_state = 3 << self::SHIFT_FLAGS;
|
||||
|
||||
for ($i = 1; $i <= $this->operator; $i++) {
|
||||
$state = array_shift($sort_states);
|
||||
$sort_state = array_shift($sort_states);
|
||||
}
|
||||
}
|
||||
if ($state & self::FLAG_DOWNTIME) {
|
||||
if ($sort_state & self::FLAG_DOWNTIME) {
|
||||
$this->setDowntime(true);
|
||||
}
|
||||
if ($state & self::FLAG_ACK) {
|
||||
if ($sort_state & self::FLAG_ACK) {
|
||||
$this->setAck(true);
|
||||
}
|
||||
$state = $state >> self::SHIFT_FLAGS;
|
||||
$sort_state = $sort_state >> self::SHIFT_FLAGS;
|
||||
|
||||
if ($state === 3) {
|
||||
if ($sort_state === 4) {
|
||||
$this->state = 2;
|
||||
} elseif ($state === 2) {
|
||||
} elseif ($sort_state === 3) {
|
||||
$this->state = 3;
|
||||
} elseif ($sort_state === 2) {
|
||||
$this->state = 1;
|
||||
} elseif ($sort_state === 1) {
|
||||
$this->state = 99;
|
||||
} elseif ($sort_state === 0) {
|
||||
$this->state = 0;
|
||||
} else {
|
||||
$this->state = $state;
|
||||
throw new ProgrammingError('Got invalid sorting state %s', $sort_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,13 +216,24 @@ class BpNode extends Node
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getDisplay()
|
||||
{
|
||||
return $this->display;
|
||||
}
|
||||
|
||||
public function setChildNames($names)
|
||||
{
|
||||
sort($names);
|
||||
$this->child_names = $names;
|
||||
$this->children = null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChildNames()
|
||||
{
|
||||
return $this->child_names;
|
||||
}
|
||||
|
||||
public function getChildren()
|
||||
{
|
||||
if ($this->children === null) {
|
||||
|
|
@ -223,6 +241,7 @@ class BpNode extends Node
|
|||
natsort($this->child_names);
|
||||
foreach ($this->child_names as $name) {
|
||||
$this->children[$name] = $this->bp->getNode($name);
|
||||
$this->children[$name]->addParent($this);
|
||||
}
|
||||
}
|
||||
return $this->children;
|
||||
|
|
@ -235,15 +254,21 @@ class BpNode extends Node
|
|||
}
|
||||
}
|
||||
|
||||
public function renderLink($view)
|
||||
protected function getActionIcons($view)
|
||||
{
|
||||
if (! $this->bp->isEditMode()) {
|
||||
return parent::renderLink($view);
|
||||
$icons = array();
|
||||
if (! $this->bp->isLocked()) {
|
||||
$icons[] = $this->actionIcon(
|
||||
$view,
|
||||
'wrench',
|
||||
$view->url('businessprocess/node/edit', array(
|
||||
'config' => $this->bp->getName(),
|
||||
'node' => $this->name
|
||||
)),
|
||||
mt('businessprocess', 'Modify this node')
|
||||
);
|
||||
}
|
||||
return $view->qlink($this->name, 'businessprocess/node/edit', array(
|
||||
'node' => $this->name,
|
||||
'processName' => $this->bp->getName()
|
||||
));
|
||||
return $icons;
|
||||
}
|
||||
|
||||
public function toLegacyConfigString(& $rendered = array())
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Exception;
|
||||
|
|
@ -12,6 +13,13 @@ class BusinessProcess
|
|||
|
||||
const HARD_STATE = 1;
|
||||
|
||||
/**
|
||||
* Name of the configured monitoring backend
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $backendName;
|
||||
|
||||
/**
|
||||
* Monitoring backend to retrieve states from
|
||||
*
|
||||
|
|
@ -47,6 +55,13 @@ class BusinessProcess
|
|||
*/
|
||||
protected $warnings = array();
|
||||
|
||||
/**
|
||||
* Errors, usually filled at process build time
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errors = array();
|
||||
|
||||
/**
|
||||
* All used node objects
|
||||
*
|
||||
|
|
@ -76,11 +91,11 @@ class BusinessProcess
|
|||
protected $hosts = array();
|
||||
|
||||
/**
|
||||
* Whether we are in simulation mode
|
||||
* Applied state simulation
|
||||
*
|
||||
* @var boolean
|
||||
* @var Simulation
|
||||
*/
|
||||
protected $simulationMode = false;
|
||||
protected $simulation;
|
||||
|
||||
/**
|
||||
* Whether we are in edit mode
|
||||
|
|
@ -89,10 +104,55 @@ class BusinessProcess
|
|||
*/
|
||||
protected $editMode = false;
|
||||
|
||||
protected $locked = true;
|
||||
|
||||
protected $changeCount = 0;
|
||||
|
||||
protected $simulationCount = 0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function applyChanges(ProcessChanges $changes)
|
||||
{
|
||||
$cnt = 0;
|
||||
foreach ($changes->getChanges() as $change) {
|
||||
$cnt++;
|
||||
$change->applyTo($this);
|
||||
}
|
||||
$this->changeCount = $cnt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function applySimulation(Simulation $simulation)
|
||||
{
|
||||
$cnt = 0;
|
||||
|
||||
foreach ($simulation->simulations() as $node => $s) {
|
||||
if (! $this->hasNode($node)) {
|
||||
continue;
|
||||
}
|
||||
$cnt++;
|
||||
$this->getNode($node)
|
||||
->setState($s->state)
|
||||
->setAck($s->acknowledged)
|
||||
->setDowntime($s->in_downtime);
|
||||
}
|
||||
|
||||
$this->simulationCount = $cnt;
|
||||
}
|
||||
public function countChanges()
|
||||
{
|
||||
return $this->changeCount;
|
||||
}
|
||||
|
||||
public function hasChanges()
|
||||
{
|
||||
return $this->countChanges() > 0;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
|
|
@ -115,12 +175,27 @@ class BusinessProcess
|
|||
return $this->title ?: $this->getName();
|
||||
}
|
||||
|
||||
public function loadBackendByName($name)
|
||||
public function hasTitle()
|
||||
{
|
||||
$this->backend = MonitoringBackend::createBackend($name);
|
||||
return $this->title !== null;
|
||||
}
|
||||
|
||||
public function setBackendName($name)
|
||||
{
|
||||
$this->backendName = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBackendName()
|
||||
{
|
||||
return $this->backendName;
|
||||
}
|
||||
|
||||
public function hasBackendName()
|
||||
{
|
||||
return $this->backendName !== null;
|
||||
}
|
||||
|
||||
public function setBackend(MonitoringBackend $backend)
|
||||
{
|
||||
$this->backend = $backend;
|
||||
|
|
@ -130,8 +205,11 @@ class BusinessProcess
|
|||
public function getBackend()
|
||||
{
|
||||
if ($this->backend === null) {
|
||||
$this->backend = MonitoringBackend::createBackend();
|
||||
$this->backend = MonitoringBackend::createBackend(
|
||||
$this->getBackendName()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->backend;
|
||||
}
|
||||
|
||||
|
|
@ -145,15 +223,30 @@ class BusinessProcess
|
|||
return false;
|
||||
}
|
||||
|
||||
public function setSimulationMode($mode = true)
|
||||
public function isLocked()
|
||||
{
|
||||
$this->simulationMode = (bool) $mode;
|
||||
return $this->locked;
|
||||
}
|
||||
|
||||
public function lock($lock = true)
|
||||
{
|
||||
$this->locked = (bool) $lock;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isSimulationMode()
|
||||
public function unlock()
|
||||
{
|
||||
return $this->simulationMode;
|
||||
return $this->lock(false);
|
||||
}
|
||||
|
||||
public function hasSimulations()
|
||||
{
|
||||
return $this->countSimulations() > 0;
|
||||
}
|
||||
|
||||
public function countSimulations()
|
||||
{
|
||||
return $this->simulationCount;
|
||||
}
|
||||
|
||||
public function setEditMode($mode = true)
|
||||
|
|
@ -197,6 +290,19 @@ class BusinessProcess
|
|||
|
||||
public function retrieveStatesFromBackend()
|
||||
{
|
||||
try {
|
||||
$this->reallyRetrieveStatesFromBackend();
|
||||
} catch (Exception $e) {
|
||||
$this->error(
|
||||
$this->translate('Could not retrieve process state: %s'),
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function reallyRetrieveStatesFromBackend()
|
||||
{
|
||||
Benchmark::measure('Retrieving states for business process ' . $this->getName());
|
||||
$backend = $this->getBackend();
|
||||
// TODO: Split apart, create a dedicated function.
|
||||
// Separate "parse-logic" from "retrieve-state-logic"
|
||||
|
|
@ -221,6 +327,10 @@ class BusinessProcess
|
|||
$filter->addFilter(Filter::where('host_name', $host));
|
||||
}
|
||||
|
||||
if ($filter->isEmpty()) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$hostStatus = $backend->select()->from('hostStatus', array(
|
||||
'hostname' => 'host_name',
|
||||
'last_state_change' => $hostStateChangeColumn,
|
||||
|
|
@ -263,6 +373,8 @@ class BusinessProcess
|
|||
}
|
||||
}
|
||||
ksort($this->root_nodes);
|
||||
Benchmark::measure('Got states for business process ' . $this->getName());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -352,7 +464,7 @@ class BusinessProcess
|
|||
if (array_key_exists($name, $this->nodes)) {
|
||||
$this->warn(
|
||||
sprintf(
|
||||
'Node "%s" has been defined twice',
|
||||
mt('businessprocess', 'Node "%s" has been defined twice'),
|
||||
$name
|
||||
)
|
||||
);
|
||||
|
|
@ -362,6 +474,27 @@ class BusinessProcess
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getUnboundNodes()
|
||||
{
|
||||
$nodes = array();
|
||||
|
||||
foreach ($this->nodes as $node) {
|
||||
if (! $node instanceof BpNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($node->hasParents()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($node->getDisplay() === '0') {
|
||||
$nodes[(string) $node] = $node;
|
||||
}
|
||||
}
|
||||
|
||||
return $nodes;
|
||||
}
|
||||
|
||||
public function hasWarnings()
|
||||
{
|
||||
return ! empty($this->warnings);
|
||||
|
|
@ -372,35 +505,73 @@ class BusinessProcess
|
|||
return $this->warnings;
|
||||
}
|
||||
|
||||
public function hasErrors()
|
||||
{
|
||||
return ! empty($this->errors) || $this->isEmpty();
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
$errors = $this->errors;
|
||||
if ($this->isEmpty()) {
|
||||
$errors[] = sprintf(
|
||||
$this->translate(
|
||||
'No business process nodes for "%s" have been defined yet'
|
||||
),
|
||||
$this->getTitle()
|
||||
);
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
|
||||
protected function translate($msg)
|
||||
{
|
||||
return mt('businessprocess', $msg);
|
||||
}
|
||||
|
||||
protected function warn($msg)
|
||||
{
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
if (isset($this->parsing_line_number)) {
|
||||
$this->warnings[] = sprintf(
|
||||
'Parser waring on %s:%s: %s',
|
||||
$this->translate('Parser waring on %s:%s: %s'),
|
||||
$this->filename,
|
||||
$this->parsing_line_number,
|
||||
$msg
|
||||
vsprintf($msg, $args)
|
||||
);
|
||||
} else {
|
||||
$this->warnings[] = $msg;
|
||||
$this->warnings[] = vsprintf($msg, $args);
|
||||
}
|
||||
}
|
||||
|
||||
protected function error($msg)
|
||||
{
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
$this->errors[] = vsprintf($msg, $args);
|
||||
}
|
||||
|
||||
public function toLegacyConfigString()
|
||||
{
|
||||
$conf = sprintf(
|
||||
"### Busines Process Config File ###\n"
|
||||
. "#\n"
|
||||
. "# Title : %s\n"
|
||||
// . "# Owner : %s\n"
|
||||
. "# Backend : %s\n"
|
||||
. "# Statetype : %s\n",
|
||||
$this->getTitle(),
|
||||
$this->backend->getName(),
|
||||
$this->state_type = self::SOFT_STATE ? 'soft' : 'hard'
|
||||
);
|
||||
$settings = array();
|
||||
if ($this->hasTitle()) {
|
||||
$settings['Title'] = $this->getTitle();
|
||||
}
|
||||
// TODO: backendName?
|
||||
if ($this->backend) {
|
||||
$settings['Backend'] = $this->backend->getName();
|
||||
}
|
||||
$settings['Statetype'] = $this->usesSoftStates() ? 'soft' : 'hard';
|
||||
|
||||
if (false) $conf .= sprintf("# xSLA Hosts: %s\n", implode(', ', array()));
|
||||
if (false) {
|
||||
$settings['SLA Hosts'] = implode(', ', array());
|
||||
}
|
||||
|
||||
$conf = "### Business Process Config File ###\n#\n";
|
||||
foreach ($settings as $key => $value) {
|
||||
$conf .= sprintf("# %-9s : %s\n", $key, $value);
|
||||
}
|
||||
|
||||
$conf .= sprintf(
|
||||
"#\n"
|
||||
|
|
@ -412,17 +583,46 @@ class BusinessProcess
|
|||
foreach ($this->getChildren() as $child) {
|
||||
$conf .= $child->toLegacyConfigString($rendered);
|
||||
}
|
||||
foreach ($this->getUnboundNodes() as $node) {
|
||||
$conf .= $node->toLegacyConfigString($rendered);
|
||||
}
|
||||
return $conf . "\n";
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->countChildren() === 0;
|
||||
}
|
||||
|
||||
public function renderHtml($view)
|
||||
{
|
||||
$html = '<div class="bp">';
|
||||
$html = '';
|
||||
foreach ($this->getRootNodes() as $name => $node) {
|
||||
// showNode($this, $node, $this->slas, $this->opened, 'bp_')
|
||||
$html .= $node->renderHtml($view);
|
||||
}
|
||||
$html .= '</div>';
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function renderUnbound($view)
|
||||
{
|
||||
$html = '';
|
||||
$unbound = $this->getUnboundNodes();
|
||||
if (empty($unbound)) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
$parent = new BpNode($this, (object) array(
|
||||
'name' => '__unbound__',
|
||||
'operator' => '|',
|
||||
'child_names' => array_keys($unbound)
|
||||
));
|
||||
$parent->getState();
|
||||
$parent->setMissing()
|
||||
->setDowntime(false)
|
||||
->setAck(false)
|
||||
->setAlias('Unbound nodes');
|
||||
|
||||
$html .= $parent->renderHtml($view);
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
40
library/Businessprocess/ConfigDiff.php
Normal file
40
library/Businessprocess/ConfigDiff.php
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use FineDiff;
|
||||
|
||||
class ConfigDiff
|
||||
{
|
||||
protected $a;
|
||||
|
||||
protected $b;
|
||||
|
||||
protected $diff;
|
||||
protected $opcodes;
|
||||
|
||||
protected function __construct($a, $b)
|
||||
{
|
||||
$this->a = $a;
|
||||
$this->b = $b;
|
||||
require_once dirname(__DIR__) . '/vendor/PHP-FineDiff/finediff.php';
|
||||
$granularity = FineDiff::$paragraphGranularity; // character, word, sentence, paragraph
|
||||
$this->diff = new FineDiff($a, $b, $granularity);
|
||||
}
|
||||
|
||||
public function renderHtml()
|
||||
{
|
||||
return $this->diff->renderDiffToHTML();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->renderHtml();
|
||||
}
|
||||
|
||||
public static function create($a, $b)
|
||||
{
|
||||
$diff = new static($a, $b);
|
||||
return $diff;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,26 +2,27 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Exception;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Web\Controller\ModuleActionController;
|
||||
use Icinga\Module\Monitoring\Backend;
|
||||
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
|
||||
use Icinga\Module\Businessprocess\BusinessProcess;
|
||||
use Icinga\Module\Businessprocess\Form\ProcessForm;
|
||||
use Icinga\Module\Businessprocess\Form\SimulationForm;
|
||||
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
|
||||
use Icinga\Module\Monitoring\Backend;
|
||||
use Icinga\Web\Controller as ModuleController;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Url;
|
||||
use Icinga\Web\Widget;
|
||||
use Exception;
|
||||
|
||||
class Controller extends ModuleActionController
|
||||
class Controller extends ModuleController
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected $backend;
|
||||
|
||||
protected $views;
|
||||
private $storage;
|
||||
|
||||
protected $aliases;
|
||||
private $url;
|
||||
|
||||
public function init()
|
||||
{
|
||||
|
|
@ -29,26 +30,25 @@ class Controller extends ModuleActionController
|
|||
if (! $m->hasLoaded('monitoring') && $m->hasInstalled('monitoring')) {
|
||||
$m->loadModule('monitoring');
|
||||
}
|
||||
$this->view->errors = array();
|
||||
|
||||
$this->config = $this->Config();
|
||||
$this->view->compact = $this->params->get('view') === 'compact';
|
||||
}
|
||||
|
||||
protected function url()
|
||||
{
|
||||
if ($this->url === null) {
|
||||
$this->url = clone $this->getRequest()->getUrl();
|
||||
}
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
protected function tabs()
|
||||
{
|
||||
$url = Url::fromRequest();
|
||||
$tabs = Widget::create('tabs')->add('show', array(
|
||||
'title' => $this->translate('Show'),
|
||||
'url' => 'businessprocess/process/show',
|
||||
));
|
||||
foreach (array('processName', 'process') as $param) {
|
||||
if ($process = $this->params->get($param)) {
|
||||
foreach ($tabs->getTabs() as $tab) {
|
||||
$tab->setUrlParams(array($param => $process));
|
||||
}
|
||||
}
|
||||
if ($this->view->tabs === null) {
|
||||
$this->view->tabs = Widget::create('tabs');
|
||||
}
|
||||
|
||||
return $tabs;
|
||||
return $this->view->tabs;
|
||||
}
|
||||
|
||||
protected function session()
|
||||
|
|
@ -56,15 +56,54 @@ class Controller extends ModuleActionController
|
|||
return $this->Window()->getSessionNamespace('businessprocess');
|
||||
}
|
||||
|
||||
protected function loadBp()
|
||||
protected function setTitle($title)
|
||||
{
|
||||
$storage = new LegacyStorage($this->Config()->getSection('global'));
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
$this->view->title = vsprintf($title, $args);
|
||||
}
|
||||
|
||||
protected function loadModifiedBpConfig()
|
||||
{
|
||||
$bp = $this->loadBpConfig();
|
||||
$changes = ProcessChanges::construct($bp, $this->session());
|
||||
if ($this->params->get('dismissChanges')) {
|
||||
Notification::success(
|
||||
sprintf(
|
||||
$this->translate('%d pending change(s) have been dropped'),
|
||||
$changes->count()
|
||||
)
|
||||
);
|
||||
$changes->clear();
|
||||
$this->redirectNow($this->url()->without('dismissChanges')->without('unlocked'));
|
||||
}
|
||||
$bp->applyChanges($changes);
|
||||
return $bp;
|
||||
}
|
||||
|
||||
protected function loadBpConfig()
|
||||
{
|
||||
$storage = $this->storage();
|
||||
$this->view->processList = $storage->listProcesses();
|
||||
$process = $this->params->get('processName', key($this->view->processList));
|
||||
$this->view->processName = $process;
|
||||
|
||||
$bp = $storage->loadProcess($process);
|
||||
// No process found? Go to welcome page
|
||||
if (empty($this->view->processList)) {
|
||||
$this->redirectNow('businessprocess');
|
||||
}
|
||||
|
||||
$name = $this->params->get(
|
||||
'config',
|
||||
key($this->view->processList)
|
||||
);
|
||||
|
||||
$modifications = $this->session()->get('modifications', array());
|
||||
if (array_key_exists($name, $modifications)) {
|
||||
$bp = $storage->loadFromString($name, $modifications[$name]);
|
||||
} else {
|
||||
$bp = $storage->loadProcess($name);
|
||||
}
|
||||
|
||||
// allow URL parameter to override configured state type
|
||||
if (null !== ($stateType = $this->params->get('state_type'))) {
|
||||
if ($stateType === 'soft') {
|
||||
$bp->useSoftStates();
|
||||
|
|
@ -74,9 +113,23 @@ class Controller extends ModuleActionController
|
|||
}
|
||||
}
|
||||
|
||||
$this->view->bpconfig = $bp;
|
||||
$this->view->configName = $bp->getName();
|
||||
|
||||
return $bp;
|
||||
}
|
||||
|
||||
protected function storage()
|
||||
{
|
||||
if ($this->storage === null) {
|
||||
$this->storage = new LegacyStorage(
|
||||
$this->Config()->getSection('global')
|
||||
);
|
||||
}
|
||||
|
||||
return $this->storage;
|
||||
}
|
||||
|
||||
protected function loadSlas()
|
||||
{
|
||||
$bpconf = $this->bpconf;
|
||||
|
|
|
|||
36
library/Businessprocess/Form.php
Normal file
36
library/Businessprocess/Form.php
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Form as WebForm;
|
||||
|
||||
class Form extends WebForm
|
||||
{
|
||||
public function __construct($options = null)
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
public function addHidden($name, $value = null)
|
||||
{
|
||||
$this->addElement('hidden', $name);
|
||||
$this->getElement($name)->setDecorators(array('ViewHelper'));
|
||||
if ($value !== null) {
|
||||
$this->setDefault($name, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function handleRequest(Request $request = null)
|
||||
{
|
||||
parent::handleRequest();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function construct()
|
||||
{
|
||||
return new static;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,13 +22,13 @@ class HostNode extends Node
|
|||
{
|
||||
if ($this->bp->isSimulationMode()) {
|
||||
return $view->qlink($this->getHostname(), 'businessprocess/host/simulate', array(
|
||||
'node' => $this->name,
|
||||
'processName' => $this->bp->getName()
|
||||
'config' => $this->bp->getName(),
|
||||
'node' => $this->name
|
||||
));
|
||||
} else {
|
||||
return $view->qlink($this->getHostname(), 'monitoring/host/show', array(
|
||||
'host' => $this->getHostname(),
|
||||
'processName' => $this->bp->getName()
|
||||
'config' => $this->bp->getName(),
|
||||
'host' => $this->getHostname()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Web\Url;
|
||||
use Icinga\Module\Businessprocess\Storage\LegacyStorage;
|
||||
|
||||
class ImportedNode extends Node
|
||||
|
|
@ -38,11 +39,6 @@ class ImportedNode extends Node
|
|||
return $this->state;
|
||||
}
|
||||
|
||||
public function getSortingState()
|
||||
{
|
||||
return $this->importedNode()->getSortingState();
|
||||
}
|
||||
|
||||
public function getAlias()
|
||||
{
|
||||
return $this->importedNode()->getAlias();
|
||||
|
|
@ -50,7 +46,8 @@ class ImportedNode extends Node
|
|||
|
||||
public function isMissing()
|
||||
{
|
||||
return $this->getState() === null;
|
||||
return $this->importedNode()->isMissing();
|
||||
// TODO: WHY? return $this->getState() === null;
|
||||
}
|
||||
|
||||
public function isInDowntime()
|
||||
|
|
@ -86,19 +83,34 @@ class ImportedNode extends Node
|
|||
}
|
||||
return $this->importedNode;
|
||||
}
|
||||
|
||||
protected function getActionIcons($view)
|
||||
{
|
||||
$icons = array();
|
||||
|
||||
if (! $this->bp->isLocked()) {
|
||||
|
||||
$url = Url::fromPath( 'businessprocess/node/simulate', array(
|
||||
'config' => $this->bp->getName(),
|
||||
'node' => $this->name
|
||||
));
|
||||
|
||||
$icons[] = $this->actionIcon(
|
||||
$view,
|
||||
'magic',
|
||||
$url,
|
||||
'Simulation'
|
||||
);
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
public function renderLink($view)
|
||||
{
|
||||
if ($this->bp->isSimulationMode()) {
|
||||
return $view->qlink($this->getAlias(), 'businessprocess/importednode/simulate', array(
|
||||
'processName' => $this->configName,
|
||||
'node' => $this->name
|
||||
));
|
||||
} else {
|
||||
return $view->qlink($this->getAlias(), 'businessprocess/process/show', array(
|
||||
'processName' => $this->configName,
|
||||
'process' => $this->name
|
||||
));
|
||||
}
|
||||
return $view->qlink($this->getAlias(), 'businessprocess/process/show', array(
|
||||
'config' => $this->configName,
|
||||
'process' => $this->name
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Web\Url;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Exception;
|
||||
|
||||
abstract class Node
|
||||
|
|
@ -12,6 +14,15 @@ abstract class Node
|
|||
const FLAG_NONE = 8;
|
||||
const SHIFT_FLAGS = 4;
|
||||
|
||||
const ICINGA_OK = 0;
|
||||
const ICINGA_WARNING = 1;
|
||||
const ICINGA_CRITICAL = 2;
|
||||
const ICINGA_UNKNOWN = 3;
|
||||
const ICINGA_UP = 0;
|
||||
const ICINGA_DOWN = 1;
|
||||
const ICINGA_UNREACHABLE = 2;
|
||||
const ICINGA_PENDING = 99;
|
||||
|
||||
/**
|
||||
* Main business process object
|
||||
*
|
||||
|
|
@ -20,11 +31,11 @@ abstract class Node
|
|||
protected $bp;
|
||||
|
||||
/**
|
||||
* Parent node
|
||||
* Parent nodes
|
||||
*
|
||||
* @var Node
|
||||
* @var array
|
||||
*/
|
||||
protected $parent;
|
||||
protected $parents = array();
|
||||
|
||||
/**
|
||||
* Node identifier
|
||||
|
|
@ -70,7 +81,8 @@ abstract class Node
|
|||
'OK',
|
||||
'WARNING',
|
||||
'CRITICAL',
|
||||
'UNKNOWN'
|
||||
'UNKNOWN',
|
||||
99 => 'PENDING'
|
||||
);
|
||||
|
||||
abstract public function __construct(BusinessProcess $bp, $object);
|
||||
|
|
@ -107,7 +119,7 @@ abstract class Node
|
|||
);
|
||||
}
|
||||
$this->childs[(string) $node] = $node;
|
||||
$node->setParent($this);
|
||||
$node->addParent($this);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +149,7 @@ abstract class Node
|
|||
public function getState()
|
||||
{
|
||||
if ($this->state === null) {
|
||||
throw new Exception(
|
||||
throw new ProgrammingError(
|
||||
sprintf(
|
||||
'Node %s is unable to retrieve it\'s state',
|
||||
$this->name
|
||||
|
|
@ -150,18 +162,32 @@ abstract class Node
|
|||
public function getSortingState()
|
||||
{
|
||||
$state = $this->getState();
|
||||
if ($state === 3) {
|
||||
$state = 2;
|
||||
} elseif ($state === 2) {
|
||||
$state = 3;
|
||||
switch ($state) {
|
||||
case 0:
|
||||
$sort = 0;
|
||||
break;
|
||||
case 1:
|
||||
$sort = 2;
|
||||
break;
|
||||
case 2:
|
||||
$sort = 4;
|
||||
break;
|
||||
case 3:
|
||||
$sort = 3;
|
||||
break;
|
||||
case 99:
|
||||
$sort = 1;
|
||||
break;
|
||||
default:
|
||||
throw new ProgrammingError('Got invalid state %d', $state);
|
||||
}
|
||||
$state = ($state << self::SHIFT_FLAGS)
|
||||
$sort = ($sort << self::SHIFT_FLAGS)
|
||||
+ ($this->isInDowntime() ? self::FLAG_DOWNTIME : 0)
|
||||
+ ($this->isAcknowledged() ? self::FLAG_ACK : 0);
|
||||
if (! ($state & (self::FLAG_DOWNTIME | self::FLAG_ACK))) {
|
||||
$state |= self::FLAG_NONE;
|
||||
if (! ($sort & (self::FLAG_DOWNTIME | self::FLAG_ACK))) {
|
||||
$sort |= self::FLAG_NONE;
|
||||
}
|
||||
return $state;
|
||||
return $sort;
|
||||
}
|
||||
|
||||
public function getLastStateChange()
|
||||
|
|
@ -175,9 +201,9 @@ abstract class Node
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setParent(Node $parent)
|
||||
public function addParent(Node $parent)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
$this->parents[] = $parent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
@ -242,6 +268,11 @@ abstract class Node
|
|||
return $this->name;
|
||||
}
|
||||
|
||||
public function hasParents()
|
||||
{
|
||||
return count($this->parents) > 0;
|
||||
}
|
||||
|
||||
protected function renderHtmlForChildren($view)
|
||||
{
|
||||
$html = '';
|
||||
|
|
@ -304,19 +335,22 @@ abstract class Node
|
|||
$this->renderLink($view)
|
||||
);
|
||||
|
||||
$icons = array();
|
||||
|
||||
foreach ($this->getActionIcons($view) as $icon) {
|
||||
$icons[] = $icon;
|
||||
}
|
||||
|
||||
if ($this->hasInfoUrl()) {
|
||||
$url = $this->getInfoUrl();
|
||||
$target = preg_match('~^https?://~', $url) ? ' target="_blank"' : '';
|
||||
$title = sprintf(
|
||||
' <a href="%s" %stitle="%s: %s" style="float: right">%s</a>%s',
|
||||
$icons[] = $this->actionIcon(
|
||||
$view,
|
||||
'help',
|
||||
$url,
|
||||
$target,
|
||||
mt('businessprocess', 'More information'),
|
||||
$url,
|
||||
$view->icon('help'),
|
||||
$title
|
||||
sprintf('%s: %s', mt('businessprocess', 'More information'), $url)
|
||||
);
|
||||
}
|
||||
$title = implode("\n", $icons) . $title;
|
||||
|
||||
$html .= sprintf(
|
||||
'<td>%s</td></tr>',
|
||||
|
|
@ -329,6 +363,28 @@ abstract class Node
|
|||
return $html;
|
||||
}
|
||||
|
||||
protected function getActionIcons($view)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
protected function actionIcon($view, $icon, $url, $title)
|
||||
{
|
||||
if ($url instanceof Url || ! preg_match('~^https?://~', $url)) {
|
||||
$target = '';
|
||||
} else {
|
||||
$target = ' target="_blank"';
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
' <a href="%s" %stitle="%s" style="float: right">%s</a>',
|
||||
$url,
|
||||
$target,
|
||||
$view->escape($title),
|
||||
$view->icon($icon)
|
||||
);
|
||||
}
|
||||
|
||||
public function renderLink($view)
|
||||
{
|
||||
return '<a href="#">' . ($this->hasAlias() ? $this->getAlias() : $this->name) . '</a>';
|
||||
|
|
@ -361,6 +417,6 @@ abstract class Node
|
|||
|
||||
public function __destruct()
|
||||
{
|
||||
unset($this->parent);
|
||||
$this->parents = array();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
93
library/Businessprocess/NodeAction.php
Normal file
93
library/Businessprocess/NodeAction.php
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
|
||||
abstract class NodeAction
|
||||
{
|
||||
const TYPE_CREATE = 'create';
|
||||
|
||||
const TYPE_REMOVE = 'remove';
|
||||
|
||||
const TYPE_MODIFY = 'modify';
|
||||
|
||||
const TYPE_CHILD_ADD = 'childRemove';
|
||||
|
||||
const TYPE_CHILD_REMOVE = 'childAdd';
|
||||
|
||||
protected $nodeName;
|
||||
|
||||
protected $actionName;
|
||||
|
||||
protected $preserveProperties = array();
|
||||
|
||||
public function __construct($node)
|
||||
{
|
||||
$this->nodeName = (string) $node;
|
||||
}
|
||||
|
||||
abstract public function applyTo(BusinessProcess $bp);
|
||||
|
||||
public function getNodeName()
|
||||
{
|
||||
return $this->nodeName;
|
||||
}
|
||||
|
||||
public function is($actionName)
|
||||
{
|
||||
return $this->getActionName() === $actionName;
|
||||
}
|
||||
|
||||
public static function create($actionName, $nodeName)
|
||||
{
|
||||
$classname = __NAMESPACE__ . '\\Node' . ucfirst($actionName) . 'Action';
|
||||
$object = new $classname($nodeName);
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
$object = (object) array(
|
||||
'actionName' => $this->getActionName(),
|
||||
'nodeName' => $this->getNodeName(),
|
||||
'properties' => array()
|
||||
);
|
||||
|
||||
foreach ($this->preserveProperties as $key) {
|
||||
$func = 'get' . ucfirst($key);
|
||||
$object->properties[$key] = $this->$func();
|
||||
}
|
||||
|
||||
return json_encode($object);
|
||||
}
|
||||
|
||||
public static function unserialize($string)
|
||||
{
|
||||
$object = json_decode($string);
|
||||
$action = self::create($object->actionName, $object->nodeName);
|
||||
|
||||
foreach ($object->properties as $key => $val) {
|
||||
$func = 'set' . ucfirst($key);
|
||||
$action->$func($val);
|
||||
}
|
||||
|
||||
return $action;
|
||||
}
|
||||
|
||||
public function getActionName()
|
||||
{
|
||||
if ($this->actionName === null) {
|
||||
if (! preg_match('/\\\Node(\w+)Action$/', get_class($this), $m)) {
|
||||
throw new ProgrammingError(
|
||||
'"%s" is not a NodeAction class',
|
||||
get_class($this)
|
||||
);
|
||||
}
|
||||
$this->actionName = lcfirst($m[1]);
|
||||
}
|
||||
|
||||
return $this->actionName;
|
||||
}
|
||||
|
||||
}
|
||||
69
library/Businessprocess/NodeCreateAction.php
Normal file
69
library/Businessprocess/NodeCreateAction.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
class NodeCreateAction extends NodeAction
|
||||
{
|
||||
protected $parentName;
|
||||
|
||||
protected $properties = array();
|
||||
|
||||
protected $preserveProperties = array('parentName', 'properties');
|
||||
|
||||
public function setParent(Node $name)
|
||||
{
|
||||
$this->parentName = $name;
|
||||
}
|
||||
|
||||
public function hasParent()
|
||||
{
|
||||
return $this->parentName !== null;
|
||||
}
|
||||
|
||||
public function getParentName()
|
||||
{
|
||||
return $this->parentName;
|
||||
}
|
||||
|
||||
public function setParentName($name)
|
||||
{
|
||||
$this->parentName = $name;
|
||||
}
|
||||
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
public function setProperties($properties)
|
||||
{
|
||||
$this->properties = $properties;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function appliesTo(BusinessProcess $bp)
|
||||
{
|
||||
return ! $bp->hasNode($this->getNodeName());
|
||||
}
|
||||
|
||||
public function applyTo(BusinessProcess $bp)
|
||||
{
|
||||
$node = new BpNode($bp, (object) array(
|
||||
'name' => $this->getNodeName(),
|
||||
'operator' => $this->properties->operator,
|
||||
'child_names' => $this->properties->childNames
|
||||
));
|
||||
|
||||
foreach ($this->properties as $key => $val) {
|
||||
$func = 'set' . ucfirst($key);
|
||||
$node->$func($val);
|
||||
}
|
||||
|
||||
$bp->addNode($this->getNodeName(), $node);
|
||||
if ($this->hasParent()) {
|
||||
$node->addParent($bp->getNode($this->getParentName()));
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
86
library/Businessprocess/NodeModifyAction.php
Normal file
86
library/Businessprocess/NodeModifyAction.php
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
class NodeModifyAction extends NodeAction
|
||||
{
|
||||
protected $properties = array();
|
||||
|
||||
protected $formerProperties = array();
|
||||
|
||||
protected $preserveProperties = array('formerProperties', 'properties');
|
||||
|
||||
// Can be called multiple times
|
||||
public function setNodeProperties(Node $node, $properties)
|
||||
{
|
||||
$old = array();
|
||||
|
||||
foreach (array_keys($properties) as $key) {
|
||||
|
||||
$this->properties[$key] = $properties[$key];
|
||||
|
||||
if (array_key_exists($key, $this->formerProperties)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$func = 'get' . ucfirst($key);
|
||||
$this->formerProperties[$key] = $node->$func();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function appliesTo(BusinessProcess $bp)
|
||||
{
|
||||
$name = $this->getNodeName();
|
||||
|
||||
if (! $bp->hasNode($name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$node = $bp->getNode($name);
|
||||
|
||||
foreach ($this->properties as $key => $val) {
|
||||
$func = 'get' . ucfirst($key);
|
||||
if ($this->formerProperties[$key] !== $node->$func()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function applyTo(BusinessProcess $bp)
|
||||
{
|
||||
$node = $bp->getNode($this->getNodeName());
|
||||
|
||||
foreach ($this->properties as $key => $val) {
|
||||
$func = 'set' . ucfirst($key);
|
||||
$node->$func($val);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setProperties($properties)
|
||||
{
|
||||
$this->properties = $properties;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setFormerProperties($properties)
|
||||
{
|
||||
$this->formerProperties = $properties;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
public function getFormerProperties()
|
||||
{
|
||||
return $this->formerProperties;
|
||||
}
|
||||
}
|
||||
16
library/Businessprocess/NodeRemoveAction.php
Normal file
16
library/Businessprocess/NodeRemoveAction.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
class NodeRemoveAction extends NodeAction
|
||||
{
|
||||
public function appliesTo(BusinessProcess $bp)
|
||||
{
|
||||
return $bp->hasNode($this->getNodeName());
|
||||
}
|
||||
|
||||
public function applyTo(BusinessProcess $bp)
|
||||
{
|
||||
$bp->removeNode($this->getNodeName());
|
||||
}
|
||||
}
|
||||
143
library/Businessprocess/ProcessChanges.php
Normal file
143
library/Businessprocess/ProcessChanges.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Web\Session\SessionNamespace as Session;
|
||||
use Icinga\Module\Businessprocess\NodeAction;
|
||||
|
||||
class ProcessChanges
|
||||
{
|
||||
protected $changes = array();
|
||||
|
||||
protected $session;
|
||||
|
||||
protected $hasBeenModified = false;
|
||||
|
||||
protected $sessionKey;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function construct(BusinessProcess $bp, Session $session)
|
||||
{
|
||||
$key = 'changes.' . $bp->getName();
|
||||
$changes = new ProcessChanges();
|
||||
$changes->sessionKey = $key;
|
||||
|
||||
if ($actions = $session->get($key)) {
|
||||
foreach ($actions as $string) {
|
||||
$changes->push(NodeAction::unserialize($string));
|
||||
}
|
||||
}
|
||||
$changes->session = $session;
|
||||
|
||||
return $changes;
|
||||
}
|
||||
|
||||
public function modifyNode(Node $node, $properties)
|
||||
{
|
||||
$action = new NodeModifyAction($node);
|
||||
$action->setNodeProperties($node, $properties);
|
||||
return $this->push($action);
|
||||
}
|
||||
|
||||
public function createNode($nodeName, $properties, Node $parent = null)
|
||||
{
|
||||
$action = new NodeCreateAction($nodeName);
|
||||
$action->setProperties($properties);
|
||||
if ($parent !== null) {
|
||||
$action->setParent($parent);
|
||||
}
|
||||
return $this->push($action);
|
||||
}
|
||||
|
||||
public function deleteNode(Node $node)
|
||||
{
|
||||
return $this->push(new NodeDeleteAction($node));
|
||||
}
|
||||
|
||||
public function push(NodeAction $change)
|
||||
{
|
||||
$this->changes[] = $change;
|
||||
$this->hasBeenModified = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChanges()
|
||||
{
|
||||
return $this->changes;
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->hasBeenModified = true;
|
||||
$this->changes = array();
|
||||
$this->session->set($this->getSessionKey(), null);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->count() === 0;
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->changes);
|
||||
}
|
||||
|
||||
public function shift()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->hasBeenModified = true;
|
||||
return array_shift($this->changes);
|
||||
}
|
||||
|
||||
public function pop()
|
||||
{
|
||||
if ($this->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->hasBeenModified = true;
|
||||
return array_pop($this->changes);
|
||||
}
|
||||
|
||||
protected function getSessionKey()
|
||||
{
|
||||
return $this->sessionKey;
|
||||
}
|
||||
|
||||
protected function hasBeenModified()
|
||||
{
|
||||
return $this->hasBeenModified;
|
||||
}
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
$serialized = array();
|
||||
foreach ($this->getChanges() as $change) {
|
||||
$serialized[] = $change->serialize();
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (! $this->hasBeenModified()) {
|
||||
unset($this->session);
|
||||
return;
|
||||
}
|
||||
$session = $this->session;
|
||||
$key = $this->getSessionKey();
|
||||
if (! $this->isEmpty()) {
|
||||
$session->set($key, $this->serialize());
|
||||
}
|
||||
unset($this->session);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Web\Url;
|
||||
|
||||
class ServiceNode extends Node
|
||||
{
|
||||
protected $hostname;
|
||||
|
||||
protected $service;
|
||||
|
||||
public function __construct(BusinessProcess $bp, $object)
|
||||
|
|
@ -22,18 +25,40 @@ class ServiceNode extends Node
|
|||
|
||||
public function renderLink($view)
|
||||
{
|
||||
if ($this->bp->isSimulationMode()) {
|
||||
return $view->qlink($this->getAlias(), 'businessprocess/node/simulate', array(
|
||||
'node' => $this->name,
|
||||
'processName' => $this->bp->getName()
|
||||
));
|
||||
} else {
|
||||
return $view->qlink($this->getAlias(), 'monitoring/service/show', array(
|
||||
'host' => $this->getHostname(),
|
||||
'service' => $this->getServiceDescription(),
|
||||
'processName' => $this->bp->getName()
|
||||
));
|
||||
if ($this->isMissing()) {
|
||||
return '<span class="missing">' . $view->escape($this->getAlias()) . '</span>';
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'host' => $this->getHostname(),
|
||||
'service' => $this->getServiceDescription()
|
||||
);
|
||||
if ($this->bp->hasBackendName()) {
|
||||
$params['backend'] = $this->bp->getBackendName();
|
||||
}
|
||||
return $view->qlink($this->getAlias(), 'monitoring/service/show', $params);
|
||||
}
|
||||
|
||||
protected function getActionIcons($view)
|
||||
{
|
||||
$icons = array();
|
||||
|
||||
if (! $this->bp->isLocked()) {
|
||||
|
||||
$url = Url::fromPath( 'businessprocess/node/simulate', array(
|
||||
'config' => $this->bp->getName(),
|
||||
'node' => $this->name
|
||||
));
|
||||
|
||||
$icons[] = $this->actionIcon(
|
||||
$view,
|
||||
'magic',
|
||||
$url,
|
||||
'Simulation'
|
||||
);
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
public function getHostname()
|
||||
|
|
|
|||
106
library/Businessprocess/Simulation.php
Normal file
106
library/Businessprocess/Simulation.php
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Businessprocess;
|
||||
|
||||
use Icinga\Web\Session\SessionNamespace;
|
||||
|
||||
class Simulation
|
||||
{
|
||||
/**
|
||||
* @var Session
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
/**
|
||||
* @var BusinessProcess
|
||||
*/
|
||||
protected $bp;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $key;
|
||||
|
||||
protected $simulations;
|
||||
|
||||
public function __construct(BusinessProcess $bp, SessionNamespace $session)
|
||||
{
|
||||
$this->bp = $bp;
|
||||
$this->session = $session;
|
||||
$this->key = 'simulations.' . $bp->getName();
|
||||
}
|
||||
|
||||
public function simulations()
|
||||
{
|
||||
if ($this->simulations === null) {
|
||||
$this->simulations = $this->fetchSimulations();
|
||||
}
|
||||
|
||||
return $this->simulations;
|
||||
}
|
||||
|
||||
protected function setSimulations($simulations)
|
||||
{
|
||||
$this->simulations = $simulations;
|
||||
$this->session->set($this->key, $simulations);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function fetchSimulations()
|
||||
{
|
||||
return $this->session->get($this->key, array());
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->simulations = array();
|
||||
$this->session->set($this->key, array());
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->simulations());
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->count() === 0;
|
||||
}
|
||||
|
||||
public function set($node, $properties)
|
||||
{
|
||||
$simulations = $this->simulations();
|
||||
$simulations[$node] = $properties;
|
||||
$this->setSimulations($simulations);
|
||||
}
|
||||
|
||||
public function hasNode($name)
|
||||
{
|
||||
$simulations = $this->simulations();
|
||||
return array_key_exists($name, $simulations);
|
||||
}
|
||||
|
||||
public function getNode($name)
|
||||
{
|
||||
$simulations = $this->simulations();
|
||||
if (! array_key_exists($name, $simulations)) {
|
||||
throw new ProgrammingError('Trying to access invalid node %s', $name);
|
||||
}
|
||||
return $simulations[$name];
|
||||
}
|
||||
|
||||
public function remove($node)
|
||||
{
|
||||
$simulations = $this->simulations();
|
||||
if (array_key_exists($node, $simulations)) {
|
||||
|
||||
unset($simulations[$node]);
|
||||
$this->setSimulations($simulations);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use Icinga\Module\Businessprocess\BpNode;
|
|||
use Icinga\Module\Businessprocess\Storage\Storage;
|
||||
use DirectoryIterator;
|
||||
use Icinga\Exception\SystemPermissionException;
|
||||
use Icinga\Application\Benchmark;
|
||||
|
||||
class LegacyStorage extends Storage
|
||||
{
|
||||
|
|
@ -61,7 +62,11 @@ class LegacyStorage extends Storage
|
|||
if (substr($filename, -5) === '.conf') {
|
||||
$name = substr($filename, 0, -5);
|
||||
$header = $this->readHeader($file->getPathname(), $name);
|
||||
$files[$name] = $header['Title'];
|
||||
if ($header['Title'] === null) {
|
||||
$files[$name] = $name;
|
||||
} else {
|
||||
$files[$name] = sprintf('%s (%s)', $header['Title'], $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
|
|
@ -72,7 +77,7 @@ class LegacyStorage extends Storage
|
|||
$fh = fopen($file, 'r');
|
||||
$cnt = 0;
|
||||
$header = array(
|
||||
'Title' => $name,
|
||||
'Title' => null,
|
||||
'Owner' => null,
|
||||
'Backend' => null,
|
||||
'Statetype' => 'soft',
|
||||
|
|
@ -101,6 +106,11 @@ class LegacyStorage extends Storage
|
|||
);
|
||||
}
|
||||
|
||||
public function getSource($name)
|
||||
{
|
||||
return file_get_contents($this->getFilename($name));
|
||||
}
|
||||
|
||||
public function getFilename($name)
|
||||
{
|
||||
return $this->getConfigDir() . '/' . $name . '.conf';
|
||||
|
|
@ -115,15 +125,22 @@ class LegacyStorage extends Storage
|
|||
return $bp;
|
||||
}
|
||||
|
||||
public function deleteProcess($name)
|
||||
{
|
||||
unlink($this->getFilename($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BusinessProcess
|
||||
*/
|
||||
public function loadProcess($name)
|
||||
{
|
||||
Benchmark::measure('Loading business process ' . $name);
|
||||
$bp = new BusinessProcess();
|
||||
$bp->setName($name);
|
||||
$this->parseFile($name, $bp);
|
||||
$this->loadHeader($name, $bp);
|
||||
Benchmark::measure('Business process ' . $name . ' loaded');
|
||||
return $bp;
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +151,10 @@ class LegacyStorage extends Storage
|
|||
$header = $this->readHeader($file, $name);
|
||||
$bp->setTitle($header['Title']);
|
||||
if ($header['Backend']) {
|
||||
$bp->loadBackendByName($header['Backend']);
|
||||
$bp->setBackendName($header['Backend']);
|
||||
}
|
||||
if ($header['Statetype'] === 'soft') {
|
||||
$bp->useSoftStates();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,4 +32,6 @@ abstract class Storage
|
|||
/**
|
||||
*/
|
||||
abstract public function storeProcess(BusinessProcess $name);
|
||||
|
||||
abstract public function deleteProcess($name);
|
||||
}
|
||||
|
|
|
|||
688
library/vendor/PHP-FineDiff/finediff.php
vendored
Normal file
688
library/vendor/PHP-FineDiff/finediff.php
vendored
Normal file
|
|
@ -0,0 +1,688 @@
|
|||
<?php
|
||||
/**
|
||||
* FINE granularity DIFF
|
||||
*
|
||||
* Computes a set of instructions to convert the content of
|
||||
* one string into another.
|
||||
*
|
||||
* Copyright (c) 2011 Raymond Hill (http://raymondhill.net/blog/?p=441)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @copyright Copyright 2011 (c) Raymond Hill (http://raymondhill.net/blog/?p=441)
|
||||
* @link http://www.raymondhill.net/finediff/
|
||||
* @version 0.6
|
||||
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Usage (simplest):
|
||||
*
|
||||
* include 'finediff.php';
|
||||
*
|
||||
* // for the stock stack, granularity values are:
|
||||
* // FineDiff::$paragraphGranularity = paragraph/line level
|
||||
* // FineDiff::$sentenceGranularity = sentence level
|
||||
* // FineDiff::$wordGranularity = word level
|
||||
* // FineDiff::$characterGranularity = character level [default]
|
||||
*
|
||||
* $opcodes = FineDiff::getDiffOpcodes($from_text, $to_text [, $granularityStack = null] );
|
||||
* // store opcodes for later use...
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* // restore $to_text from $from_text + $opcodes
|
||||
* include 'finediff.php';
|
||||
* $to_text = FineDiff::renderToTextFromOpcodes($from_text, $opcodes);
|
||||
*
|
||||
* ...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Persisted opcodes (string) are a sequence of atomic opcode.
|
||||
* A single opcode can be one of the following:
|
||||
* c | c{n} | d | d{n} | i:{c} | i{length}:{s}
|
||||
* 'c' = copy one character from source
|
||||
* 'c{n}' = copy n characters from source
|
||||
* 'd' = skip one character from source
|
||||
* 'd{n}' = skip n characters from source
|
||||
* 'i:{c} = insert character 'c'
|
||||
* 'i{n}:{s}' = insert string s, which is of length n
|
||||
*
|
||||
* Do not exist as of now, under consideration:
|
||||
* 'm{n}:{o} = move n characters from source o characters ahead.
|
||||
* It would be essentially a shortcut for a delete->copy->insert
|
||||
* command (swap) for when the inserted segment is exactly the same
|
||||
* as the deleted one, and with only a copy operation in between.
|
||||
* TODO: How often this case occurs? Is it worth it? Can only
|
||||
* be done as a postprocessing method (->optimize()?)
|
||||
*/
|
||||
abstract class FineDiffOp {
|
||||
abstract public function getFromLen();
|
||||
abstract public function getToLen();
|
||||
abstract public function getOpcode();
|
||||
}
|
||||
|
||||
class FineDiffDeleteOp extends FineDiffOp {
|
||||
public function __construct($len) {
|
||||
$this->fromLen = $len;
|
||||
}
|
||||
public function getFromLen() {
|
||||
return $this->fromLen;
|
||||
}
|
||||
public function getToLen() {
|
||||
return 0;
|
||||
}
|
||||
public function getOpcode() {
|
||||
if ( $this->fromLen === 1 ) {
|
||||
return 'd';
|
||||
}
|
||||
return "d{$this->fromLen}";
|
||||
}
|
||||
}
|
||||
|
||||
class FineDiffInsertOp extends FineDiffOp {
|
||||
public function __construct($text) {
|
||||
$this->text = $text;
|
||||
}
|
||||
public function getFromLen() {
|
||||
return 0;
|
||||
}
|
||||
public function getToLen() {
|
||||
return strlen($this->text);
|
||||
}
|
||||
public function getText() {
|
||||
return $this->text;
|
||||
}
|
||||
public function getOpcode() {
|
||||
$to_len = strlen($this->text);
|
||||
if ( $to_len === 1 ) {
|
||||
return "i:{$this->text}";
|
||||
}
|
||||
return "i{$to_len}:{$this->text}";
|
||||
}
|
||||
}
|
||||
|
||||
class FineDiffReplaceOp extends FineDiffOp {
|
||||
public function __construct($fromLen, $text) {
|
||||
$this->fromLen = $fromLen;
|
||||
$this->text = $text;
|
||||
}
|
||||
public function getFromLen() {
|
||||
return $this->fromLen;
|
||||
}
|
||||
public function getToLen() {
|
||||
return strlen($this->text);
|
||||
}
|
||||
public function getText() {
|
||||
return $this->text;
|
||||
}
|
||||
public function getOpcode() {
|
||||
if ( $this->fromLen === 1 ) {
|
||||
$del_opcode = 'd';
|
||||
}
|
||||
else {
|
||||
$del_opcode = "d{$this->fromLen}";
|
||||
}
|
||||
$to_len = strlen($this->text);
|
||||
if ( $to_len === 1 ) {
|
||||
return "{$del_opcode}i:{$this->text}";
|
||||
}
|
||||
return "{$del_opcode}i{$to_len}:{$this->text}";
|
||||
}
|
||||
}
|
||||
|
||||
class FineDiffCopyOp extends FineDiffOp {
|
||||
public function __construct($len) {
|
||||
$this->len = $len;
|
||||
}
|
||||
public function getFromLen() {
|
||||
return $this->len;
|
||||
}
|
||||
public function getToLen() {
|
||||
return $this->len;
|
||||
}
|
||||
public function getOpcode() {
|
||||
if ( $this->len === 1 ) {
|
||||
return 'c';
|
||||
}
|
||||
return "c{$this->len}";
|
||||
}
|
||||
public function increase($size) {
|
||||
return $this->len += $size;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FineDiff ops
|
||||
*
|
||||
* Collection of ops
|
||||
*/
|
||||
class FineDiffOps {
|
||||
public function appendOpcode($opcode, $from, $from_offset, $from_len) {
|
||||
if ( $opcode === 'c' ) {
|
||||
$edits[] = new FineDiffCopyOp($from_len);
|
||||
}
|
||||
else if ( $opcode === 'd' ) {
|
||||
$edits[] = new FineDiffDeleteOp($from_len);
|
||||
}
|
||||
else /* if ( $opcode === 'i' ) */ {
|
||||
$edits[] = new FineDiffInsertOp(substr($from, $from_offset, $from_len));
|
||||
}
|
||||
}
|
||||
public $edits = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* FineDiff class
|
||||
*
|
||||
* TODO: Document
|
||||
*
|
||||
*/
|
||||
class FineDiff {
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
*
|
||||
* Public section
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* ...
|
||||
* The $granularityStack allows FineDiff to be configurable so that
|
||||
* a particular stack tailored to the specific content of a document can
|
||||
* be passed.
|
||||
*/
|
||||
public function __construct($from_text = '', $to_text = '', $granularityStack = null) {
|
||||
// setup stack for generic text documents by default
|
||||
$this->granularityStack = $granularityStack ? $granularityStack : FineDiff::$characterGranularity;
|
||||
$this->edits = array();
|
||||
$this->from_text = $from_text;
|
||||
$this->doDiff($from_text, $to_text);
|
||||
}
|
||||
|
||||
public function getOps() {
|
||||
return $this->edits;
|
||||
}
|
||||
|
||||
public function getOpcodes() {
|
||||
$opcodes = array();
|
||||
foreach ( $this->edits as $edit ) {
|
||||
$opcodes[] = $edit->getOpcode();
|
||||
}
|
||||
return implode('', $opcodes);
|
||||
}
|
||||
|
||||
public function renderDiffToHTML() {
|
||||
$in_offset = 0;
|
||||
ob_start();
|
||||
foreach ( $this->edits as $edit ) {
|
||||
$n = $edit->getFromLen();
|
||||
if ( $edit instanceof FineDiffCopyOp ) {
|
||||
FineDiff::renderDiffToHTMLFromOpcode('c', $this->from_text, $in_offset, $n);
|
||||
}
|
||||
else if ( $edit instanceof FineDiffDeleteOp ) {
|
||||
FineDiff::renderDiffToHTMLFromOpcode('d', $this->from_text, $in_offset, $n);
|
||||
}
|
||||
else if ( $edit instanceof FineDiffInsertOp ) {
|
||||
FineDiff::renderDiffToHTMLFromOpcode('i', $edit->getText(), 0, $edit->getToLen());
|
||||
}
|
||||
else /* if ( $edit instanceof FineDiffReplaceOp ) */ {
|
||||
FineDiff::renderDiffToHTMLFromOpcode('d', $this->from_text, $in_offset, $n);
|
||||
FineDiff::renderDiffToHTMLFromOpcode('i', $edit->getText(), 0, $edit->getToLen());
|
||||
}
|
||||
$in_offset += $n;
|
||||
}
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* Return an opcodes string describing the diff between a "From" and a
|
||||
* "To" string
|
||||
*/
|
||||
public static function getDiffOpcodes($from, $to, $granularities = null) {
|
||||
$diff = new FineDiff($from, $to, $granularities);
|
||||
return $diff->getOpcodes();
|
||||
}
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* Return an iterable collection of diff ops from an opcodes string
|
||||
*/
|
||||
public static function getDiffOpsFromOpcodes($opcodes) {
|
||||
$diffops = new FineDiffOps();
|
||||
FineDiff::renderFromOpcodes(null, $opcodes, array($diffops,'appendOpcode'));
|
||||
return $diffops->edits;
|
||||
}
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* Re-create the "To" string from the "From" string and an "Opcodes" string
|
||||
*/
|
||||
public static function renderToTextFromOpcodes($from, $opcodes) {
|
||||
ob_start();
|
||||
FineDiff::renderFromOpcodes($from, $opcodes, array('FineDiff','renderToTextFromOpcode'));
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* Render the diff to an HTML string
|
||||
*/
|
||||
public static function renderDiffToHTMLFromOpcodes($from, $opcodes) {
|
||||
ob_start();
|
||||
FineDiff::renderFromOpcodes($from, $opcodes, array('FineDiff','renderDiffToHTMLFromOpcode'));
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* Generic opcodes parser, user must supply callback for handling
|
||||
* single opcode
|
||||
*/
|
||||
public static function renderFromOpcodes($from, $opcodes, $callback) {
|
||||
if ( !is_callable($callback) ) {
|
||||
return;
|
||||
}
|
||||
$opcodes_len = strlen($opcodes);
|
||||
$from_offset = $opcodes_offset = 0;
|
||||
while ( $opcodes_offset < $opcodes_len ) {
|
||||
$opcode = substr($opcodes, $opcodes_offset, 1);
|
||||
$opcodes_offset++;
|
||||
$n = intval(substr($opcodes, $opcodes_offset));
|
||||
if ( $n ) {
|
||||
$opcodes_offset += strlen(strval($n));
|
||||
}
|
||||
else {
|
||||
$n = 1;
|
||||
}
|
||||
if ( $opcode === 'c' ) { // copy n characters from source
|
||||
call_user_func($callback, 'c', $from, $from_offset, $n, '');
|
||||
$from_offset += $n;
|
||||
}
|
||||
else if ( $opcode === 'd' ) { // delete n characters from source
|
||||
call_user_func($callback, 'd', $from, $from_offset, $n, '');
|
||||
$from_offset += $n;
|
||||
}
|
||||
else /* if ( $opcode === 'i' ) */ { // insert n characters from opcodes
|
||||
call_user_func($callback, 'i', $opcodes, $opcodes_offset + 1, $n);
|
||||
$opcodes_offset += 1 + $n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stock granularity stacks and delimiters
|
||||
*/
|
||||
|
||||
const paragraphDelimiters = "\n\r";
|
||||
public static $paragraphGranularity = array(
|
||||
FineDiff::paragraphDelimiters
|
||||
);
|
||||
const sentenceDelimiters = ".\n\r";
|
||||
public static $sentenceGranularity = array(
|
||||
FineDiff::paragraphDelimiters,
|
||||
FineDiff::sentenceDelimiters
|
||||
);
|
||||
const wordDelimiters = " \t.\n\r";
|
||||
public static $wordGranularity = array(
|
||||
FineDiff::paragraphDelimiters,
|
||||
FineDiff::sentenceDelimiters,
|
||||
FineDiff::wordDelimiters
|
||||
);
|
||||
const characterDelimiters = "";
|
||||
public static $characterGranularity = array(
|
||||
FineDiff::paragraphDelimiters,
|
||||
FineDiff::sentenceDelimiters,
|
||||
FineDiff::wordDelimiters,
|
||||
FineDiff::characterDelimiters
|
||||
);
|
||||
|
||||
public static $textStack = array(
|
||||
".",
|
||||
" \t.\n\r",
|
||||
""
|
||||
);
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
*
|
||||
* Private section
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entry point to compute the diff.
|
||||
*/
|
||||
private function doDiff($from_text, $to_text) {
|
||||
$this->last_edit = false;
|
||||
$this->stackpointer = 0;
|
||||
$this->from_text = $from_text;
|
||||
$this->from_offset = 0;
|
||||
// can't diff without at least one granularity specifier
|
||||
if ( empty($this->granularityStack) ) {
|
||||
return;
|
||||
}
|
||||
$this->_processGranularity($from_text, $to_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the recursive function which is responsible for
|
||||
* handling/increasing granularity.
|
||||
*
|
||||
* Incrementally increasing the granularity is key to compute the
|
||||
* overall diff in a very efficient way.
|
||||
*/
|
||||
private function _processGranularity($from_segment, $to_segment) {
|
||||
$delimiters = $this->granularityStack[$this->stackpointer++];
|
||||
$has_next_stage = $this->stackpointer < count($this->granularityStack);
|
||||
foreach ( FineDiff::doFragmentDiff($from_segment, $to_segment, $delimiters) as $fragment_edit ) {
|
||||
// increase granularity
|
||||
if ( $fragment_edit instanceof FineDiffReplaceOp && $has_next_stage ) {
|
||||
$this->_processGranularity(
|
||||
substr($this->from_text, $this->from_offset, $fragment_edit->getFromLen()),
|
||||
$fragment_edit->getText()
|
||||
);
|
||||
}
|
||||
// fuse copy ops whenever possible
|
||||
else if ( $fragment_edit instanceof FineDiffCopyOp && $this->last_edit instanceof FineDiffCopyOp ) {
|
||||
$this->edits[count($this->edits)-1]->increase($fragment_edit->getFromLen());
|
||||
$this->from_offset += $fragment_edit->getFromLen();
|
||||
}
|
||||
else {
|
||||
/* $fragment_edit instanceof FineDiffCopyOp */
|
||||
/* $fragment_edit instanceof FineDiffDeleteOp */
|
||||
/* $fragment_edit instanceof FineDiffInsertOp */
|
||||
$this->edits[] = $this->last_edit = $fragment_edit;
|
||||
$this->from_offset += $fragment_edit->getFromLen();
|
||||
}
|
||||
}
|
||||
$this->stackpointer--;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the core algorithm which actually perform the diff itself,
|
||||
* fragmenting the strings as per specified delimiters.
|
||||
*
|
||||
* This function is naturally recursive, however for performance purpose
|
||||
* a local job queue is used instead of outright recursivity.
|
||||
*/
|
||||
private static function doFragmentDiff($from_text, $to_text, $delimiters) {
|
||||
// Empty delimiter means character-level diffing.
|
||||
// In such case, use code path optimized for character-level
|
||||
// diffing.
|
||||
if ( empty($delimiters) ) {
|
||||
return FineDiff::doCharDiff($from_text, $to_text);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
|
||||
// fragment-level diffing
|
||||
$from_text_len = strlen($from_text);
|
||||
$to_text_len = strlen($to_text);
|
||||
$from_fragments = FineDiff::extractFragments($from_text, $delimiters);
|
||||
$to_fragments = FineDiff::extractFragments($to_text, $delimiters);
|
||||
|
||||
$jobs = array(array(0, $from_text_len, 0, $to_text_len));
|
||||
|
||||
$cached_array_keys = array();
|
||||
|
||||
while ( $job = array_pop($jobs) ) {
|
||||
|
||||
// get the segments which must be diff'ed
|
||||
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
|
||||
|
||||
// catch easy cases first
|
||||
$from_segment_length = $from_segment_end - $from_segment_start;
|
||||
$to_segment_length = $to_segment_end - $to_segment_start;
|
||||
if ( !$from_segment_length || !$to_segment_length ) {
|
||||
if ( $from_segment_length ) {
|
||||
$result[$from_segment_start * 4] = new FineDiffDeleteOp($from_segment_length);
|
||||
}
|
||||
else if ( $to_segment_length ) {
|
||||
$result[$from_segment_start * 4 + 1] = new FineDiffInsertOp(substr($to_text, $to_segment_start, $to_segment_length));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// find longest copy operation for the current segments
|
||||
$best_copy_length = 0;
|
||||
|
||||
$from_base_fragment_index = $from_segment_start;
|
||||
|
||||
$cached_array_keys_for_current_segment = array();
|
||||
|
||||
while ( $from_base_fragment_index < $from_segment_end ) {
|
||||
$from_base_fragment = $from_fragments[$from_base_fragment_index];
|
||||
$from_base_fragment_length = strlen($from_base_fragment);
|
||||
// performance boost: cache array keys
|
||||
if ( !isset($cached_array_keys_for_current_segment[$from_base_fragment]) ) {
|
||||
if ( !isset($cached_array_keys[$from_base_fragment]) ) {
|
||||
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment] = array_keys($to_fragments, $from_base_fragment, true);
|
||||
}
|
||||
else {
|
||||
$to_all_fragment_indices = $cached_array_keys[$from_base_fragment];
|
||||
}
|
||||
// get only indices which falls within current segment
|
||||
if ( $to_segment_start > 0 || $to_segment_end < $to_text_len ) {
|
||||
$to_fragment_indices = array();
|
||||
foreach ( $to_all_fragment_indices as $to_fragment_index ) {
|
||||
if ( $to_fragment_index < $to_segment_start ) { continue; }
|
||||
if ( $to_fragment_index >= $to_segment_end ) { break; }
|
||||
$to_fragment_indices[] = $to_fragment_index;
|
||||
}
|
||||
$cached_array_keys_for_current_segment[$from_base_fragment] = $to_fragment_indices;
|
||||
}
|
||||
else {
|
||||
$to_fragment_indices = $to_all_fragment_indices;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$to_fragment_indices = $cached_array_keys_for_current_segment[$from_base_fragment];
|
||||
}
|
||||
// iterate through collected indices
|
||||
foreach ( $to_fragment_indices as $to_base_fragment_index ) {
|
||||
$fragment_index_offset = $from_base_fragment_length;
|
||||
// iterate until no more match
|
||||
for (;;) {
|
||||
$fragment_from_index = $from_base_fragment_index + $fragment_index_offset;
|
||||
if ( $fragment_from_index >= $from_segment_end ) {
|
||||
break;
|
||||
}
|
||||
$fragment_to_index = $to_base_fragment_index + $fragment_index_offset;
|
||||
if ( $fragment_to_index >= $to_segment_end ) {
|
||||
break;
|
||||
}
|
||||
if ( $from_fragments[$fragment_from_index] !== $to_fragments[$fragment_to_index] ) {
|
||||
break;
|
||||
}
|
||||
$fragment_length = strlen($from_fragments[$fragment_from_index]);
|
||||
$fragment_index_offset += $fragment_length;
|
||||
}
|
||||
if ( $fragment_index_offset > $best_copy_length ) {
|
||||
$best_copy_length = $fragment_index_offset;
|
||||
$best_from_start = $from_base_fragment_index;
|
||||
$best_to_start = $to_base_fragment_index;
|
||||
}
|
||||
}
|
||||
$from_base_fragment_index += strlen($from_base_fragment);
|
||||
// If match is larger than half segment size, no point trying to find better
|
||||
// TODO: Really?
|
||||
if ( $best_copy_length >= $from_segment_length / 2) {
|
||||
break;
|
||||
}
|
||||
// no point to keep looking if what is left is less than
|
||||
// current best match
|
||||
if ( $from_base_fragment_index + $best_copy_length >= $from_segment_end ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $best_copy_length ) {
|
||||
$jobs[] = array($from_segment_start, $best_from_start, $to_segment_start, $best_to_start);
|
||||
$result[$best_from_start * 4 + 2] = new FineDiffCopyOp($best_copy_length);
|
||||
$jobs[] = array($best_from_start + $best_copy_length, $from_segment_end, $best_to_start + $best_copy_length, $to_segment_end);
|
||||
}
|
||||
else {
|
||||
$result[$from_segment_start * 4 ] = new FineDiffReplaceOp($from_segment_length, substr($to_text, $to_segment_start, $to_segment_length));
|
||||
}
|
||||
}
|
||||
|
||||
ksort($result, SORT_NUMERIC);
|
||||
return array_values($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a character-level diff.
|
||||
*
|
||||
* The algorithm is quite similar to doFragmentDiff(), except that
|
||||
* the code path is optimized for character-level diff -- strpos() is
|
||||
* used to find out the longest common subequence of characters.
|
||||
*
|
||||
* We try to find a match using the longest possible subsequence, which
|
||||
* is at most the length of the shortest of the two strings, then incrementally
|
||||
* reduce the size until a match is found.
|
||||
*
|
||||
* I still need to study more the performance of this function. It
|
||||
* appears that for long strings, the generic doFragmentDiff() is more
|
||||
* performant. For word-sized strings, doCharDiff() is somewhat more
|
||||
* performant.
|
||||
*/
|
||||
private static function doCharDiff($from_text, $to_text) {
|
||||
$result = array();
|
||||
$jobs = array(array(0, strlen($from_text), 0, strlen($to_text)));
|
||||
while ( $job = array_pop($jobs) ) {
|
||||
// get the segments which must be diff'ed
|
||||
list($from_segment_start, $from_segment_end, $to_segment_start, $to_segment_end) = $job;
|
||||
$from_segment_len = $from_segment_end - $from_segment_start;
|
||||
$to_segment_len = $to_segment_end - $to_segment_start;
|
||||
|
||||
// catch easy cases first
|
||||
if ( !$from_segment_len || !$to_segment_len ) {
|
||||
if ( $from_segment_len ) {
|
||||
$result[$from_segment_start * 4 + 0] = new FineDiffDeleteOp($from_segment_len);
|
||||
}
|
||||
else if ( $to_segment_len ) {
|
||||
$result[$from_segment_start * 4 + 1] = new FineDiffInsertOp(substr($to_text, $to_segment_start, $to_segment_len));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( $from_segment_len >= $to_segment_len ) {
|
||||
$copy_len = $to_segment_len;
|
||||
while ( $copy_len ) {
|
||||
$to_copy_start = $to_segment_start;
|
||||
$to_copy_start_max = $to_segment_end - $copy_len;
|
||||
while ( $to_copy_start <= $to_copy_start_max ) {
|
||||
$from_copy_start = strpos(substr($from_text, $from_segment_start, $from_segment_len), substr($to_text, $to_copy_start, $copy_len));
|
||||
if ( $from_copy_start !== false ) {
|
||||
$from_copy_start += $from_segment_start;
|
||||
break 2;
|
||||
}
|
||||
$to_copy_start++;
|
||||
}
|
||||
$copy_len--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$copy_len = $from_segment_len;
|
||||
while ( $copy_len ) {
|
||||
$from_copy_start = $from_segment_start;
|
||||
$from_copy_start_max = $from_segment_end - $copy_len;
|
||||
while ( $from_copy_start <= $from_copy_start_max ) {
|
||||
$to_copy_start = strpos(substr($to_text, $to_segment_start, $to_segment_len), substr($from_text, $from_copy_start, $copy_len));
|
||||
if ( $to_copy_start !== false ) {
|
||||
$to_copy_start += $to_segment_start;
|
||||
break 2;
|
||||
}
|
||||
$from_copy_start++;
|
||||
}
|
||||
$copy_len--;
|
||||
}
|
||||
}
|
||||
// match found
|
||||
if ( $copy_len ) {
|
||||
$jobs[] = array($from_segment_start, $from_copy_start, $to_segment_start, $to_copy_start);
|
||||
$result[$from_copy_start * 4 + 2] = new FineDiffCopyOp($copy_len);
|
||||
$jobs[] = array($from_copy_start + $copy_len, $from_segment_end, $to_copy_start + $copy_len, $to_segment_end);
|
||||
}
|
||||
// no match, so delete all, insert all
|
||||
else {
|
||||
$result[$from_segment_start * 4] = new FineDiffReplaceOp($from_segment_len, substr($to_text, $to_segment_start, $to_segment_len));
|
||||
}
|
||||
}
|
||||
ksort($result, SORT_NUMERIC);
|
||||
return array_values($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Efficiently fragment the text into an array according to
|
||||
* specified delimiters.
|
||||
* No delimiters means fragment into single character.
|
||||
* The array indices are the offset of the fragments into
|
||||
* the input string.
|
||||
* A sentinel empty fragment is always added at the end.
|
||||
* Careful: No check is performed as to the validity of the
|
||||
* delimiters.
|
||||
*/
|
||||
private static function extractFragments($text, $delimiters) {
|
||||
// special case: split into characters
|
||||
if ( empty($delimiters) ) {
|
||||
$chars = str_split($text, 1);
|
||||
$chars[strlen($text)] = '';
|
||||
return $chars;
|
||||
}
|
||||
$fragments = array();
|
||||
$start = $end = 0;
|
||||
for (;;) {
|
||||
$end += strcspn($text, $delimiters, $end);
|
||||
$end += strspn($text, $delimiters, $end);
|
||||
if ( $end === $start ) {
|
||||
break;
|
||||
}
|
||||
$fragments[$start] = substr($text, $start, $end - $start);
|
||||
$start = $end;
|
||||
}
|
||||
$fragments[$start] = '';
|
||||
return $fragments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stock opcode renderers
|
||||
*/
|
||||
private static function renderToTextFromOpcode($opcode, $from, $from_offset, $from_len) {
|
||||
if ( $opcode === 'c' || $opcode === 'i' ) {
|
||||
echo substr($from, $from_offset, $from_len);
|
||||
}
|
||||
}
|
||||
|
||||
private static function renderDiffToHTMLFromOpcode($opcode, $from, $from_offset, $from_len) {
|
||||
if ( $opcode === 'c' ) {
|
||||
echo htmlentities(substr($from, $from_offset, $from_len));
|
||||
}
|
||||
else if ( $opcode === 'd' ) {
|
||||
$deletion = substr($from, $from_offset, $from_len);
|
||||
if ( strcspn($deletion, " \n\r") === 0 ) {
|
||||
$deletion = str_replace(array("\n","\r"), array('\n','\r'), $deletion);
|
||||
}
|
||||
echo '<del>', htmlentities($deletion), '</del>';
|
||||
}
|
||||
else /* if ( $opcode === 'i' ) */ {
|
||||
echo '<ins>', htmlentities(substr($from, $from_offset, $from_len)), '</ins>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9,6 +9,10 @@ h1 {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.controls h1 form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
h1 a:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
|
@ -52,11 +56,6 @@ table.bp {
|
|||
}
|
||||
}
|
||||
|
||||
/* We try our best to avoid flickering */
|
||||
table.bp th, table.bp td a {
|
||||
/* SHIT margin-bottom: 5px; */
|
||||
}
|
||||
|
||||
table.bp th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
@ -123,7 +122,7 @@ table.bp.process {
|
|||
}
|
||||
}
|
||||
|
||||
table.bp th > a, table.bp td > a {
|
||||
table.bp th > a, table.bp td > a, table.bp td > span {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
|
@ -174,26 +173,28 @@ table.bp {
|
|||
border-color: transparent;
|
||||
}
|
||||
|
||||
table.bp tr, table.bp tbody, table.bp th, table.bp td, table.bp.node td > a {
|
||||
table.bp tr, table.bp tbody, table.bp th, table.bp td, table.bp.node td > a, table.node.missing td > span {
|
||||
border-width: 0;
|
||||
border-style: inherit;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
table.bp td > a {
|
||||
table.bp td > a, table.node.missing td > span {
|
||||
line-height: 2em;
|
||||
padding-left: 0.5em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.bp.node td > a:last-child {
|
||||
table.bp.node td > a:last-child, table.node.missing td > span {
|
||||
padding-left: 2.5em;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0.5em 0.5em;
|
||||
border-left-width: 0.8em;
|
||||
}
|
||||
|
||||
table.bp.node.handled td > a:last-child, table.bp.node.ok td > a:last-child {
|
||||
table.bp.node.handled td > a:last-child, table.bp.node.ok td > a:last-child,
|
||||
table.node.missing td > span
|
||||
{
|
||||
border-left-width: 0.3em;
|
||||
background-position: 1em 0.5em;
|
||||
padding-left: 3em;
|
||||
|
|
@ -214,6 +215,7 @@ table.bp.operator > tbody > tr:first-child > * {
|
|||
border-top-width: 1px;
|
||||
border-top-style: dotted;
|
||||
}
|
||||
|
||||
table.bp.operator.hovered > tbody > tr:first-child > * {
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
|
@ -227,6 +229,7 @@ table.bp {
|
|||
&.critical.handled { border-color: @colorCriticalHandled; }
|
||||
&.unknown { border-color: @colorUnknown; }
|
||||
&.unknown.handled { border-color: @colorUnknownHandled; }
|
||||
&.pending { border-color: @colorPending; }
|
||||
&.missing { border-color: #ccc; }
|
||||
&.hovered {
|
||||
&.ok > tbody > tr > {
|
||||
|
|
@ -250,8 +253,11 @@ table.bp {
|
|||
&.unknown.handled > tbody > tr > {
|
||||
th, td > a { background-color: @colorCUnknownHandled; }
|
||||
}
|
||||
&.pending > tbody > tr > {
|
||||
th, td > a { background-color: @colorPending; }
|
||||
}
|
||||
&.missing > tbody > tr > {
|
||||
th, td > a { background-color: #ccc; }
|
||||
th, td > a, td > span { background-color: #ccc; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -275,7 +281,7 @@ table.bp {
|
|||
-o-transition: @val1, @val2;
|
||||
-webkit-transition: @val1, @val2;
|
||||
}
|
||||
> tbody > tr > td > a:last-child, > tbody > tr > th {
|
||||
> tbody > tr > td > a:last-child, > tbody > tr > td > span, > tbody > tr > th {
|
||||
// Fade out
|
||||
.transition(color 0.5s 0.1s step-start,
|
||||
background-color 0.5s 0.1s ease-out
|
||||
|
|
@ -283,7 +289,7 @@ table.bp {
|
|||
}
|
||||
|
||||
&.hovered > tbody > tr {
|
||||
> td > a:last-child, > th {
|
||||
> td > a:last-child, > td > span, > th {
|
||||
// Fade in
|
||||
.transition(color 0.0s 0.0s step-start,
|
||||
background-color 0.0s 0.0s ease-out
|
||||
|
|
@ -401,4 +407,47 @@ ul.error {
|
|||
color: white;
|
||||
padding: 0.3em 0.8em;
|
||||
}
|
||||
|
||||
li a {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
table.sourcecode {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
|
||||
th {
|
||||
vertical-align: top;
|
||||
padding-right: 0.5em;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
-o-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.diff {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
|
||||
del, ins {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
del {
|
||||
color: @colorCritical;
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
ins {
|
||||
color: @colorOk;
|
||||
background-color: #dfd;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
this.module.on('mouseenter', 'table.bp > tbody > tr > td > a', this.procMouseOver);
|
||||
this.module.on('mouseenter', 'table.bp > tbody > tr > th', this.procMouseOver);
|
||||
this.module.on('mouseenter', 'table.node.missing > tbody > tr > td > span', this.procMouseOver);
|
||||
this.module.on('mouseleave', 'div.bp', this.procMouseOut);
|
||||
|
||||
this.module.icinga.logger.debug('BP module loaded');
|
||||
|
|
|
|||
Loading…
Reference in a new issue