diff --git a/application/controllers/ReportController.php b/application/controllers/ReportController.php index 8371382c..04837b55 100644 --- a/application/controllers/ReportController.php +++ b/application/controllers/ReportController.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Reporting\Controllers; +use Exception; use Icinga\Application\Hook; use Icinga\Module\Pdfexport\ProvidedHook\Pdfexport; use Icinga\Module\Reporting\Database; @@ -16,6 +17,7 @@ use Icinga\Module\Reporting\Web\Widget\CompatDropdown; use Icinga\Web\Notification; use ipl\Html\Error; +use ipl\Html\HtmlElement; use ipl\Stdlib\Filter; use ipl\Web\Url; use ipl\Web\Widget\ActionBar; @@ -47,17 +49,33 @@ public function init() public function indexAction() { + $this->getTabs()->getAttributes()->set('data-base-target', '_main'); $this->addTitleTab($this->report->getName()); + $this->controls->getAttributes()->add('class', 'default-layout'); $this->addControl($this->assembleActions()); + $contentId = $this->content->getAttributes()->get('id')->getValue(); + $this->sendExtraUpdates([ + $contentId => Url::fromPath('reporting/report/content', ['id' => $this->report->getId()]) + ]); + + // Will be replaced once the report content is rendered + $this->addContent(new HtmlElement('div')); + } + + public function contentAction() + { Environment::raiseExecutionTime(); Environment::raiseMemoryLimit(); + $this->view->compact = true; + $this->_helper->layout()->disableLayout(); + try { - $this->addContent($this->report->toHtml()); - } catch (\Exception $e) { - $this->addContent(Error::show($e)); + $this->getDocument()->addHtml($this->report->toHtml()); + } catch (Exception $e) { + $this->getDocument()->addHtml(Error::show($e)); } } @@ -89,7 +107,12 @@ public function cloneAction() ->setAction((string) Url::fromRequest()) ->populate($values) ->on(ReportForm::ON_SUCCESS, function () { - $this->redirectNow('__CLOSE__'); + Notification::success($this->translate('Cloned report successfully')); + + // Refresh the col1 container after cloning a report + $this->sendExtraUpdates(['#col1']); + + $this->redirectNow(Url::fromPath('reporting/report', ['id' => $this->report->getId()])); }) ->handleRequest($this->getServerRequest()); @@ -119,8 +142,20 @@ public function editAction() $form = ReportForm::fromId($this->report->getId()) ->setAction((string) Url::fromRequest()) ->populate($values) - ->on(ReportForm::ON_SUCCESS, function () { - $this->redirectNow('__CLOSE__'); + ->on(ReportForm::ON_SUCCESS, function (ReportForm $form) { + $url = '__CLOSE__'; + if ($form->getPressedSubmitElement()->getName() === 'remove') { + Notification::success($this->translate('Removed report successfully')); + } else { + $url = Url::fromPath('reporting/report', ['id' => $this->report->getId()]); + + // Refresh the col1 container after editing a report + $this->sendExtraUpdates(['#col1']); + + Notification::success($this->translate('Updated report successfully')); + } + + $this->redirectNow($url); }) ->handleRequest($this->getServerRequest()); @@ -138,7 +173,7 @@ public function sendAction() ->setReport($this->report) ->setAction((string) Url::fromRequest()) ->on(SendForm::ON_SUCCESS, function () { - $this->redirectNow("reporting/report?id={$this->report->getId()}"); + $this->redirectNow(Url::fromPath('reporting/report', ['id' => $this->report->getId()])); }) ->handleRequest($this->getServerRequest()); @@ -164,7 +199,7 @@ public function scheduleAction() Notification::success($this->translate('Created schedule successfully')); } - $this->redirectNow("reporting/report?id={$this->report->getId()}"); + $this->redirectNow(Url::fromPath('reporting/report', ['id' => $this->report->getId()])); }) ->handleRequest($this->getServerRequest()); diff --git a/application/controllers/ReportsController.php b/application/controllers/ReportsController.php index f1c60e61..89667e5d 100644 --- a/application/controllers/ReportsController.php +++ b/application/controllers/ReportsController.php @@ -11,11 +11,10 @@ use Icinga\Module\Reporting\Web\Controller; use Icinga\Module\Reporting\Web\Forms\ReportForm; use Icinga\Module\Reporting\Web\ReportsTimeframesAndTemplatesTabs; +use Icinga\Web\Notification; use ipl\Html\Html; use ipl\Web\Url; use ipl\Web\Widget\ButtonLink; -use ipl\Web\Widget\Icon; -use ipl\Web\Widget\Link; class ReportsController extends Controller { @@ -64,16 +63,7 @@ public function indexAction() Html::tag('td', null, $report->timeframe->name), Html::tag('td', null, $report->ctime->format('Y-m-d H:i')), Html::tag('td', null, $report->mtime->format('Y-m-d H:i')), - Html::tag('td', ['class' => 'icon-col'], [ - new Link( - new Icon('edit'), - Url::fromPath('reporting/report/edit', ['id' => $report->id]), - [ - 'data-icinga-modal' => true, - 'data-no-icinga-ajax' => true - ] - ) - ]) + Html::tag('td', null, $report->mtime->format('Y-m-d H:i')) ]); } @@ -127,14 +117,25 @@ public function newAction() $form = (new ReportForm()) ->setAction((string) Url::fromRequest()) + ->setRenderCreateAndShowButton($class !== null) ->populate([ 'filter' => $this->params->shift('filter'), 'reportlet' => $class ]) - ->on(ReportForm::ON_SUCCESS, function () { - $this->getResponse()->setHeader('X-Icinga-Container', 'modal-content', true); + ->on(ReportForm::ON_SUCCESS, function (ReportForm $form) use ($class) { + Notification::success($this->translate('Created report successfully')); - $this->redirectNow('__CLOSE__'); + $url = Url::fromPath('reporting/reports'); + if ($form->getPressedSubmitElement()->getName() === 'create_show') { + $url = Url::fromPath('reporting/report', ['id' => $form->getId()]); + } elseif ($class !== null) { + $url = '__CLOSE__'; + + // This will close only the modal view and leave the object detail view of Icinga DB Web untouched. + $this->getResponse()->setHeader('X-Icinga-Container', 'modal', true); + } + + $this->redirectNow($url); }) ->handleRequest($this->getServerRequest()); diff --git a/application/controllers/TemplateController.php b/application/controllers/TemplateController.php index e8cebb0b..26dbeb2d 100644 --- a/application/controllers/TemplateController.php +++ b/application/controllers/TemplateController.php @@ -7,12 +7,14 @@ use DateTime; use Exception; use GuzzleHttp\Psr7\ServerRequest; +use Icinga\Application\Version; use Icinga\Module\Reporting\Database; use Icinga\Module\Reporting\Model; use Icinga\Module\Reporting\Web\Controller; use Icinga\Module\Reporting\Web\Forms\TemplateForm; use Icinga\Module\Reporting\Web\Widget\Template; use Icinga\Web\Notification; +use ipl\Html\Form; use ipl\Stdlib\Filter; use ipl\Web\Url; @@ -62,8 +64,21 @@ public function editAction() $form = TemplateForm::fromTemplate($template) ->setAction((string) Url::fromRequest()) - ->on(TemplateForm::ON_SUCCESS, function () { - Notification::success($this->translate('Updated template successfully')); + ->on(TemplateForm::ON_SUCCESS, function (Form $form) { + $extraUpdates = ['#col1']; + if ($form->getPressedSubmitElement()->getName() === 'remove') { + Notification::success($this->translate('Removed template successfully')); + + $extraUpdates['col2'] = '__CLOSE__'; + } else { + Notification::success($this->translate('Updated template successfully')); + } + + // Older Icinga Web 2 versions close #col2 container automatically when redirecting using close. + // So, we need to send the extra updates only when using Icinga Web 2.12 or newer. + if (version_compare(Version::VERSION, '2.12', '>=')) { + $this->sendExtraUpdates($extraUpdates); + } $this->redirectNow('__CLOSE__'); }) diff --git a/application/controllers/TemplatesController.php b/application/controllers/TemplatesController.php index e300c53a..eee39c22 100644 --- a/application/controllers/TemplatesController.php +++ b/application/controllers/TemplatesController.php @@ -115,9 +115,7 @@ public function newAction() ->on(TemplateForm::ON_SUCCESS, function () { Notification::success($this->translate('Created template successfully')); - $this->getResponse()->setHeader('X-Icinga-Container', 'modal-content', true); - - $this->redirectNow('__CLOSE__'); + $this->redirectNow('reporting/templates'); }) ->handleRequest($this->getServerRequest()); diff --git a/application/controllers/TimeframeController.php b/application/controllers/TimeframeController.php index 667d5bf9..88783834 100644 --- a/application/controllers/TimeframeController.php +++ b/application/controllers/TimeframeController.php @@ -10,6 +10,8 @@ use Icinga\Module\Reporting\Timeframe; use Icinga\Module\Reporting\Web\Controller; use Icinga\Module\Reporting\Web\Forms\TimeframeForm; +use Icinga\Web\Notification; +use ipl\Html\Form; use ipl\Web\Url; use ipl\Stdlib\Filter; @@ -47,10 +49,14 @@ public function editAction() $form = TimeframeForm::fromId($this->timeframe->getId()) ->setAction((string) Url::fromRequest()) ->populate($values) - ->on(TimeframeForm::ON_SUCCESS, function () { - $this->getResponse()->setHeader('X-Icinga-Container', 'modal-content', true); + ->on(TimeframeForm::ON_SUCCESS, function (Form $form) { + if ($form->getPressedSubmitElement()->getName() === 'remove') { + Notification::success($this->translate('Removed timeframe successfully')); + } else { + Notification::success($this->translate('Update timeframe successfully')); + } - $this->redirectNow('__CLOSE__'); + $this->redirectNow('reporting/timeframes'); })->handleRequest($this->getServerRequest()); $this->addContent($form); diff --git a/application/controllers/TimeframesController.php b/application/controllers/TimeframesController.php index 698f16c7..ed5ed368 100644 --- a/application/controllers/TimeframesController.php +++ b/application/controllers/TimeframesController.php @@ -9,6 +9,7 @@ use Icinga\Module\Reporting\Web\Controller; use Icinga\Module\Reporting\Web\Forms\TimeframeForm; use Icinga\Module\Reporting\Web\ReportsTimeframesAndTemplatesTabs; +use Icinga\Web\Notification; use ipl\Html\Html; use ipl\Web\Url; use ipl\Web\Widget\ButtonLink; @@ -58,18 +59,11 @@ public function indexAction() if ($canManage) { $subject = new Link( $timeframe->name, - Url::fromPath('reporting/timeframe/edit', ['id' => $timeframe->id]), - [ - 'data-icinga-modal' => true, - 'data-no-icinga-ajax' => true - ] + Url::fromPath('reporting/timeframe/edit', ['id' => $timeframe->id]) ); } - $tableRows[] = Html::tag('tr', [ - 'data-icinga-modal' => true, - 'data-no-icinga-ajax' => true - ], [ + $tableRows[] = Html::tag('tr', null, [ Html::tag('td', null, $subject), Html::tag('td', null, $timeframe->start), Html::tag('td', null, $timeframe->end), @@ -81,7 +75,10 @@ public function indexAction() if (! empty($tableRows)) { $table = Html::tag( 'table', - ['class' => 'common-table table-row-selectable'], + [ + 'class' => 'common-table table-row-selectable', + 'data-base-target' => '_next' + ], [ Html::tag( 'thead', @@ -116,9 +113,9 @@ public function newAction() $form = (new TimeframeForm()) ->setAction((string) Url::fromRequest()) ->on(TimeframeForm::ON_SUCCESS, function () { - $this->getResponse()->setHeader('X-Icinga-Container', 'modal-content', true); + Notification::success($this->translate('Created timeframe successfully')); - $this->redirectNow('__CLOSE__'); + $this->redirectNow('reporting/timeframes'); })->handleRequest($this->getServerRequest()); $this->addContent($form); diff --git a/library/Reporting/Web/Forms/ReportForm.php b/library/Reporting/Web/Forms/ReportForm.php index 9b6e5c52..115d2832 100644 --- a/library/Reporting/Web/Forms/ReportForm.php +++ b/library/Reporting/Web/Forms/ReportForm.php @@ -22,6 +22,9 @@ class ReportForm extends CompatForm /** @var string Label to use for the submit button */ protected $submitButtonLabel; + /** @var bool Whether to render the create and show submit button (is only used from DB Web's object detail) */ + protected $renderCreateAndShowButton = false; + /** * Create a new form instance with the given report id * @@ -37,6 +40,11 @@ public static function fromId($id): self return $form; } + public function getId(): ?int + { + return $this->id; + } + /** * Set the label of the submit button * @@ -65,9 +73,27 @@ public function getSubmitButtonLabel(): string return $this->id === null ? $this->translate('Create Report') : $this->translate('Update Report'); } + /** + * Set whether the create and show submit button should be rendered + * + * @param bool $renderCreateAndShowButton + * + * @return $this + */ + public function setRenderCreateAndShowButton(bool $renderCreateAndShowButton): self + { + $this->renderCreateAndShowButton = $renderCreateAndShowButton; + + return $this; + } + public function hasBeenSubmitted(): bool { - return $this->hasBeenSent() && ($this->getPopulatedValue('submit') || $this->getPopulatedValue('remove')); + return $this->hasBeenSent() && ( + $this->getPopulatedValue('submit') + || $this->getPopulatedValue('create_show') + || $this->getPopulatedValue('remove') + ); } protected function assemble() @@ -149,6 +175,12 @@ protected function assemble() ]); $this->registerElement($removeButton); $this->getElement('submit')->getWrapper()->prepend($removeButton); + } elseif ($this->renderCreateAndShowButton) { + $createAndShow = $this->createElement('submit', 'create_show', [ + 'label' => $this->translate('Create and Show'), + ]); + $this->registerElement($createAndShow); + $this->getElement('submit')->getWrapper()->prepend($createAndShow); } } @@ -179,6 +211,9 @@ public function onSuccess() ]); $reportId = $db->lastInsertId(); + if ($this->getPressedSubmitElement()->getName() === 'create_show') { + $this->id = $reportId; + } } else { $db->update('report', [ 'name' => $values['name'], diff --git a/public/css/module.less b/public/css/module.less index b8175045..c4ad1bd6 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -1,5 +1,9 @@ // Icinga Reporting | (c) 2018 Icinga GmbH | GPLv2 +.content:focus { + outline: none; +} + .sla-column { border-radius: 0.5em; color: @text-color-on-icinga-blue; @@ -84,16 +88,20 @@ } } -.action-bar .dropdown:first-child:hover .dropdown-menu { - left: .25em; -} +.action-bar { + line-height: 2em; -.action-bar .dropdown:last-child:hover .dropdown-menu { - right: .25em; -} + .dropdown:first-child:hover .dropdown-menu { + left: .25em; + } + + .dropdown:last-child:hover .dropdown-menu { + right: .25em; + } -.action-bar > *:not(:last-child) { - margin-right: .5em; + > *:not(:last-child) { + margin-right: .5em; + } } /* Stuff that's missing in ipl <= 0.8 END */