diff --git a/application/controllers/DashboardsController.php b/application/controllers/DashboardsController.php new file mode 100644 index 000000000..af288f8d5 --- /dev/null +++ b/application/controllers/DashboardsController.php @@ -0,0 +1,375 @@ +dashboard = new Dashboard(); + $this->dashboard->setUser($this->Auth()->getUser()); + $this->dashboard->setTabs($this->getTabs()); + $this->dashboard->load(); + } + + public function indexAction() + { + $this->createTabs(); + + $activeHome = $this->dashboard->getActiveHome(); + if (!$activeHome || ! $activeHome->hasPanes()) { + $this->getTabs()->add('dashboard', [ + 'active' => true, + 'title' => $this->translate('Welcome'), + 'url' => Url::fromRequest() + ]); + + // Setup dashboard introduction form + $welcomeForm = new WelcomeForm($this->dashboard); + $welcomeForm->on(WelcomeForm::ON_SUCCESS, function () use ($welcomeForm) { + $this->redirectNow($welcomeForm->getRedirectUrl()); + })->handleRequest(ServerRequest::fromGlobals()); + + $this->dashboard->setWelcomeForm($welcomeForm); + } elseif (empty($activeHome->getPanes(true))) { + // TODO(TBD): What to do when the user has only disabled dashboards? Should we render the welcome screen? + } else { + if ($this->getParam('pane')) { + $pane = $this->getParam('pane'); + $this->getTabs()->activate($pane); + } + } + + $this->content = $this->dashboard; + } + + /** + * Display all the dashboards assigned to a Home set in the `home` request param + * + * If no pane param is submitted, the default pane is displayed (usually the first one) + */ + public function homeAction() + { + $home = $this->params->getRequired('home'); + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf(t('Home "%s" not found'), $home)); + } + + $this->createTabs(); + + $activeHome = $this->dashboard->getActiveHome(); + if (! $activeHome || empty($activeHome->getPanes(true))) { + $this->getTabs()->add($home, [ + 'active' => true, + 'title' => $home, + 'url' => Url::fromRequest() + ]); + } elseif (($pane = $this->getParam('param'))) { + $this->dashboard->activate($pane); + } + + $this->content = $this->dashboard; + } + + public function renameHomeAction() + { + $this->setTitle(t('Update Home')); + + $home = $this->params->getRequired('home'); + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Home "%s" not found'), $home)); + } + + $homeForm = new HomePaneForm($this->dashboard); + $homeForm->on(HomePaneForm::ON_SUCCESS, function () { + $this->redirectNow('__CLOSE__'); + })->handleRequest(ServerRequest::fromGlobals()); + + $homeForm->load($this->dashboard->getActiveHome()); + $this->addContent($homeForm); + } + + public function removeHomeAction() + { + $this->setTitle(t('Remove Home')); + + $home = $this->params->getRequired('home'); + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Home "%s" not found'), $home)); + } + + $homeForm = (new RemoveHomePaneForm($this->dashboard)) + ->on(RemoveHomePaneForm::ON_SUCCESS, function () { + $this->redirectNow('__CLOSE__'); + }) + ->handleRequest(ServerRequest::fromGlobals()); + + $this->addContent($homeForm); + } + + public function editPaneAction() + { + $this->setTitle(t('Update Pane')); + + $pane = $this->params->getRequired('pane'); + $home = $this->params->getRequired('home'); + + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Home "%s" not found'), $home)); + } + + if (! $this->dashboard->getActiveHome()->hasPane($pane)) { + $this->httpNotFound(sprintf($this->translate('Pane "%s" not found'), $pane)); + } + + $paneForm = new HomePaneForm($this->dashboard); + $paneForm->on(HomePaneForm::ON_SUCCESS, function () use ($pane) { + $this->redirectNow('__CLOSE__'); + })->handleRequest(ServerRequest::fromGlobals()); + + $paneForm->load($this->dashboard->getActiveHome()->getPane($pane)); + + $this->addContent($paneForm); + } + + public function removePaneAction() + { + $this->setTitle(t('Remove Pane')); + + $home = $this->params->getRequired('home'); + $paneParam = $this->params->getRequired('pane'); + + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Home "%s" not found'), $home)); + } + + if (! $this->dashboard->getActiveHome()->hasPane($paneParam)) { + $this->httpNotFound(sprintf($this->translate('Pane "%s" not found'), $paneParam)); + } + + $paneForm = new RemoveHomePaneForm($this->dashboard); + $paneForm->populate(['org_name' => $paneParam]); + $paneForm->on(RemoveHomePaneForm::ON_SUCCESS, function () { + $this->redirectNow('__CLOSE__'); + })->handleRequest(ServerRequest::fromGlobals()); + + $paneForm->getElement('btn_remove')->setLabel(t('Remove Pane')); + $paneForm->prependHtml(HtmlElement::create('h1', null, sprintf( + t('Please confirm removal of dashboard pane "%s"'), + $paneParam + ))); + + $this->addContent($paneForm); + } + + public function newDashletAction() + { + $this->setTitle(t('Add Dashlet To Dashboard')); + + $dashletForm = new DashletForm($this->dashboard); + $dashletForm->populate($this->getRequest()->getPost()); + $dashletForm->on(DashletForm::ON_SUCCESS, function () use ($dashletForm) { + $this->redirectNow('__CLOSE__'); + })->handleRequest(ServerRequest::fromGlobals()); + + $params = $this->getAllParams(); + if ($this->getParam('url')) { + $params['url'] = rawurldecode($this->getParam('url')); + } + + $dashletForm->populate($params); + + $this->addContent($dashletForm); + } + + public function editDashletAction() + { + $this->setTitle(t('Edit Dashlet')); + + $pane = $this->validateDashletParams(); + $dashlet = $pane->getDashlet($this->getParam('dashlet')); + + $dashletForm = new DashletForm($this->dashboard); + $dashletForm->on(DashletForm::ON_SUCCESS, function () use ($dashletForm, $pane) { + $this->redirectNow('__CLOSE__'); + })->handleRequest(ServerRequest::fromGlobals()); + + $dashletForm->getElement('submit')->setLabel(t('Update Dashlet')); + + $dashletForm->load($dashlet); + $this->addContent($dashletForm); + } + + public function removeDashletAction() + { + $this->validateDashletParams(); + $this->setTitle(t('Remove Dashlet')); + + $removeForm = (new RemoveDashletForm($this->dashboard)) + ->on(RemoveDashletForm::ON_SUCCESS, function () { + $this->redirectNow('__CLOSE__'); + }) + ->handleRequest(ServerRequest::fromGlobals()); + + $this->addContent($removeForm); + } + + public function reorderDashletsAction() + { + $this->assertHttpMethod('post'); + if (! $this->getRequest()->isApiRequest()) { + $this->httpBadRequest('No API request'); + } + + if ( + ! preg_match('/([^;]*);?/', $this->getRequest()->getHeader('Content-Type'), $matches) + || $matches[1] !== 'application/json' + ) { + $this->httpBadRequest('No JSON content'); + } + + $dashboards = $this->getRequest()->getPost(); + foreach ($dashboards as $home => $panes) { + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Dashboard home "%s" not found'), $home)); + } + + $home = $this->dashboard->getHome($home); + $home->setActive(); + $home->loadDashboardsFromDB(); + + foreach ($panes as $pane => $dashlets) { + if (! $home->hasPane($pane)) { + $this->httpNotFound(sprintf($this->translate('Dashboard pane "%s" not found'), $pane)); + } + + $pane = $home->getPane($pane); + foreach ($dashlets as $order => $dashlet) { + if (! $pane->hasDashlet($dashlet)) { + $this->httpNotFound(sprintf($this->translate('Dashlet "%s" not found'), $pane)); + } + + Dashboard::getConn()->update(Dashlet::TABLE, ['priority' => $order], [ + 'id = ?' => $pane->getDashlet($dashlet)->getUuid(), + 'dashboard_id = ?' => $pane->getUuid() + ]); + } + } + } + + exit; + } + + /** + * Provides a mini wizard which guides a new user through the dashboard creation + * process and helps them get a first impression of Icinga Web 2. + */ + public function setupDashboardAction() + { + if (isset($this->getRequest()->getPost()['btn_next'])) { + // Set compact view to prevent the controls from being + // rendered in the modal view when redirecting + $this->view->compact = true; + + $this->getResponse()->setHeader('X-Icinga-Title', 'Configure Dashlets', true); + } else { + $this->setTitle($this->translate('Add Dashlet')); + } + + $query = ModuleDashlet::on(Dashboard::getConn()); + + $setupForm = new SetupNewDashboard($this->dashboard); + $setupForm->initDashlets(Dashboard::getModuleDashlets($query)); + $setupForm->on(SetupNewDashboard::ON_SUCCESS, function () use ($setupForm) { + if ($setupForm->getPopulatedValue('btn_cancel')) { + $this->redirectNow('__CLOSE__'); + } + + $this->redirectNow($setupForm->getRedirectUrl()); + })->handleRequest(ServerRequest::fromGlobals()); + + $this->addContent($setupForm); + } + + public function settingsAction() + { + $this->createTabs(); + // TODO(yh): This may raise an exception when the given tab name doesn't exist. + // But as ipl::Tabs() doesn't offer the possibility to check this beforehand, just ignore it for now!! + $this->dashboard->activate('dashboard_settings'); + + $this->addControl(new ActionLink( + $this->translate('Add new Home'), + Url::fromPath(Dashboard::BASE_ROUTE . '/new-dashlet'), + 'plus', + [ + 'class' => 'add-home', + 'data-icinga-modal' => true, + 'data-no-icinga-ajax' => true + ] + )); + + $this->content = new Settings($this->dashboard); + } + + /** + * Create tab aggregation + */ + private function createTabs() + { + $tabs = $this->dashboard->getTabs(); + $activeHome = $this->dashboard->getActiveHome(); + if ($activeHome && $activeHome->hasPanes()) { + $tabs->extend(new DashboardSettings()); + } + + return $tabs; + } + + private function validateDashletParams() + { + $home = $this->params->getRequired('home'); + $pane = $this->params->getRequired('pane'); + $dashlet = $this->params->getRequired('dashlet'); + + if (! $this->dashboard->hasHome($home)) { + $this->httpNotFound(sprintf($this->translate('Home "%s" not found'), $home)); + } + + if (! $this->dashboard->getActiveHome()->hasPane($pane)) { + $this->httpNotFound(sprintf($this->translate('Pane "%s" not found'), $pane)); + } + + $pane = $this->dashboard->getActiveHome()->getPane($pane); + if (! $pane->hasDashlet($dashlet)) { + $this->httpNotFound(sprintf($this->translate('Dashlet "%s" not found'), $dashlet)); + } + + return $pane; + } +}