From a72d18765f85cf116331fcc9bad0ff05471378bb Mon Sep 17 00:00:00 2001 From: Chad Little Date: Tue, 14 Mar 2017 14:21:43 -0700 Subject: [PATCH] Basic "Install Dashboard" workflow Summary: Ref T12264. This allows users to install a dashboard they are viewing to their personal home menu or as a global home menu item. Has some basic ability to be extended later for maybe projects. Test Plan: Build a dashboard, click "Install Dashboard". - As user only get personal option - As HomeApp edit person, see both options - Try installation as either, with and without label set - Fake "global" form as user, get error - Don't set anything, get error Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T12264 Differential Revision: https://secure.phabricator.com/D17492 --- resources/celerity/map.php | 10 +- src/__phutil_library_map__.php | 2 + .../PhabricatorDashboardApplication.php | 1 + .../PhabricatorDashboardArrangeController.php | 8 + .../PhabricatorDashboardInstallController.php | 141 ++++++++++++++++++ .../PhabricatorDashboardViewController.php | 8 + webroot/rsrc/css/aphront/dialog-view.css | 4 +- webroot/rsrc/css/phui/phui-form-view.css | 5 +- 8 files changed, 169 insertions(+), 10 deletions(-) create mode 100644 src/applications/dashboard/controller/PhabricatorDashboardInstallController.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index c6039fa138..46bb152704 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -9,7 +9,7 @@ return array( 'names' => array( 'conpherence.pkg.css' => '32f2c040', 'conpherence.pkg.js' => '6249a1cf', - 'core.pkg.css' => '35645dec', + 'core.pkg.css' => 'c0c87dac', 'core.pkg.js' => '1fa7c0c5', 'darkconsole.pkg.js' => 'e7393ebb', 'differential.pkg.css' => '90b30783', @@ -21,7 +21,7 @@ return array( 'maniphest.pkg.js' => '5ab2753f', 'rsrc/css/aphront/aphront-bars.css' => '231ac33c', 'rsrc/css/aphront/dark-console.css' => 'f54bf286', - 'rsrc/css/aphront/dialog-view.css' => '5e5aa60b', + 'rsrc/css/aphront/dialog-view.css' => '685c7e2d', 'rsrc/css/aphront/list-filter-view.css' => '5d6f0526', 'rsrc/css/aphront/multi-column.css' => '84cc6640', 'rsrc/css/aphront/notification.css' => '3f6c89c9', @@ -146,7 +146,7 @@ return array( 'rsrc/css/phui/phui-document.css' => 'c32e8dec', 'rsrc/css/phui/phui-feed-story.css' => '44a9c8e9', 'rsrc/css/phui/phui-fontkit.css' => 'b78a0059', - 'rsrc/css/phui/phui-form-view.css' => 'adca31ce', + 'rsrc/css/phui/phui-form-view.css' => 'cf198e10', 'rsrc/css/phui/phui-form.css' => 'b62c01d8', 'rsrc/css/phui/phui-head-thing.css' => 'fd311e5f', 'rsrc/css/phui/phui-header-view.css' => 'fef6a54e', @@ -548,7 +548,7 @@ return array( 'almanac-css' => 'dbb9b3af', 'aphront-bars' => '231ac33c', 'aphront-dark-console-css' => 'f54bf286', - 'aphront-dialog-view-css' => '5e5aa60b', + 'aphront-dialog-view-css' => '685c7e2d', 'aphront-list-filter-view-css' => '5d6f0526', 'aphront-multi-column-view-css' => '84cc6640', 'aphront-panel-view-css' => '8427b78d', @@ -859,7 +859,7 @@ return array( 'phui-font-icon-base-css' => '870a7360', 'phui-fontkit-css' => 'b78a0059', 'phui-form-css' => 'b62c01d8', - 'phui-form-view-css' => 'adca31ce', + 'phui-form-view-css' => 'cf198e10', 'phui-head-thing-view-css' => 'fd311e5f', 'phui-header-view-css' => 'fef6a54e', 'phui-hovercard' => '1bd28176', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1279ae4077..59e2feb7d0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2496,6 +2496,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', 'PhabricatorDashboardIconSet' => 'applications/dashboard/icon/PhabricatorDashboardIconSet.php', 'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php', + 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/PhabricatorDashboardInstallController.php', 'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php', 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 'PhabricatorDashboardManageController' => 'applications/dashboard/controller/PhabricatorDashboardManageController.php', @@ -7562,6 +7563,7 @@ phutil_register_library_map(array( 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', 'PhabricatorDashboardIconSet' => 'PhabricatorIconSet', 'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', + 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 'PhabricatorDashboardLayoutConfig' => 'Phobject', 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 'PhabricatorDashboardManageController' => 'PhabricatorDashboardProfileController', diff --git a/src/applications/dashboard/application/PhabricatorDashboardApplication.php b/src/applications/dashboard/application/PhabricatorDashboardApplication.php index 123dcc9f6e..c0ce2ff09e 100644 --- a/src/applications/dashboard/application/PhabricatorDashboardApplication.php +++ b/src/applications/dashboard/application/PhabricatorDashboardApplication.php @@ -30,6 +30,7 @@ final class PhabricatorDashboardApplication extends PhabricatorApplication { 'arrange/(?P\d+)/' => 'PhabricatorDashboardArrangeController', 'create/' => 'PhabricatorDashboardEditController', 'edit/(?:(?P\d+)/)?' => 'PhabricatorDashboardEditController', + 'install/(?:(?P\d+)/)?' => 'PhabricatorDashboardInstallController', 'addpanel/(?P\d+)/' => 'PhabricatorDashboardAddPanelController', 'movepanel/(?P\d+)/' => 'PhabricatorDashboardMovePanelController', 'removepanel/(?P\d+)/' diff --git a/src/applications/dashboard/controller/PhabricatorDashboardArrangeController.php b/src/applications/dashboard/controller/PhabricatorDashboardArrangeController.php index ed8d24d737..1ef482b7f4 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardArrangeController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardArrangeController.php @@ -51,6 +51,14 @@ final class PhabricatorDashboardArrangeController ->addClass('dashboard-preview-box') ->appendChild($rendered_dashboard); + $install_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText('Install Dashboard') + ->setIcon('fa-plus') + ->setWorkflow(true) + ->setHref($this->getApplicationURI("/install/{$id}/")); + $header->addActionLink($install_button); + $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( diff --git a/src/applications/dashboard/controller/PhabricatorDashboardInstallController.php b/src/applications/dashboard/controller/PhabricatorDashboardInstallController.php new file mode 100644 index 0000000000..145c6f530e --- /dev/null +++ b/src/applications/dashboard/controller/PhabricatorDashboardInstallController.php @@ -0,0 +1,141 @@ +getViewer(); + $id = $request->getURIData('id'); + + $dashboard = id(new PhabricatorDashboardQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->executeOne(); + if (!$dashboard) { + return new Aphront404Response(); + } + + $cancel_uri = $this->getApplicationURI( + 'view/'.$dashboard->getID().'/'); + + $home_app = new PhabricatorHomeApplication(); + + $options = array(); + $options['home'] = array( + 'personal' => + array( + 'capability' => PhabricatorPolicyCapability::CAN_VIEW, + 'application' => $home_app, + 'name' => pht('Personal Dashboard'), + 'value' => 'personal', + 'description' => pht('Places this dashboard as a menu item on home '. + 'as a personal menu item. It will only be on your personal '. + 'home.'), + ), + 'global' => + array( + 'capability' => PhabricatorPolicyCapability::CAN_EDIT, + 'application' => $home_app, + 'name' => pht('Global Dashboard'), + 'value' => 'global', + 'description' => pht('Places this dashboard as a menu item on home '. + 'as a global menu item. It will be available to all users.'), + ), + ); + + + $errors = array(); + $v_name = null; + if ($request->isFormPost()) { + $menuitem = new PhabricatorDashboardProfileMenuItem(); + $dashboard_phid = $dashboard->getPHID(); + $home = new PhabricatorHomeApplication(); + $v_name = $request->getStr('name'); + $v_home = $request->getStr('home'); + + if ($v_home) { + $application = $options['home'][$v_home]['application']; + $capability = $options['home'][$v_home]['capability']; + + $can_edit_home = PhabricatorPolicyFilter::hasCapability( + $viewer, + $application, + $capability); + + if (!$can_edit_home) { + $errors[] = pht( + 'You do not have permission to install a dashboard on home.'); + } + } else { + $errors[] = pht( + 'You must select a destination to install this dashboard.'); + } + + $v_phid = $viewer->getPHID(); + if ($v_home == 'global') { + $v_phid = null; + } + + if (!$errors) { + $install = PhabricatorProfileMenuItemConfiguration::initializeNewItem( + $home, + $menuitem, + $v_phid); + + $install->setMenuItemProperty('dashboardPHID', $dashboard_phid); + $install->setMenuItemProperty('name', $v_name); + $install->setMenuItemOrder(1); + + $xactions = array(); + + $editor = id(new PhabricatorProfileMenuEditor()) + ->setActor($viewer) + ->setContinueOnNoEffect(true) + ->setContinueOnMissingFields(true) + ->setContentSourceFromRequest($request); + + $editor->applyTransactions($install, $xactions); + + $view_uri = '/home/menu/view/'.$install->getID().'/'; + + return id(new AphrontRedirectResponse())->setURI($view_uri); + } + } + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel(pht('Menu Label')) + ->setName('name') + ->setValue($v_name)); + + $radio = id(new AphrontFormRadioButtonControl()) + ->setLabel(pht('Home Menu')) + ->setName('home'); + + foreach ($options['home'] as $type => $option) { + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $option['application'], + $option['capability']); + if ($can_edit) { + $radio->addButton( + $option['value'], + $option['name'], + $option['description']); + } + } + + $form->appendChild($radio); + + return $this->newDialog() + ->setTitle(pht('Install Dashboard')) + ->setErrors($errors) + ->setWidth(AphrontDialogView::WIDTH_FORM) + ->appendChild($form->buildLayoutView()) + ->addCancelButton($cancel_uri) + ->addSubmitButton(pht('Install Dashboard')); + } + +} diff --git a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php index 547398f3fd..07faee8f05 100644 --- a/src/applications/dashboard/controller/PhabricatorDashboardViewController.php +++ b/src/applications/dashboard/controller/PhabricatorDashboardViewController.php @@ -43,6 +43,14 @@ final class PhabricatorDashboardViewController $navigation = $this->buildSideNavView('view'); $header = $this->buildHeaderView(); + $install_button = id(new PHUIButtonView()) + ->setTag('a') + ->setText('Install Dashboard') + ->setIcon('fa-plus') + ->setWorkflow(true) + ->setHref($this->getApplicationURI("/install/{$id}/")); + $header->addActionLink($install_button); + $view = id(new PHUITwoColumnView()) ->setHeader($header) ->setFooter(array( diff --git a/webroot/rsrc/css/aphront/dialog-view.css b/webroot/rsrc/css/aphront/dialog-view.css index 3b2de1cee6..0e6f6d4cfc 100644 --- a/webroot/rsrc/css/aphront/dialog-view.css +++ b/webroot/rsrc/css/aphront/dialog-view.css @@ -3,7 +3,7 @@ */ .aphront-dialog-view { - width: 540px; + width: 560px; margin: 32px auto 16px; border: 1px solid {$lightblueborder}; border-radius: 3px; @@ -32,7 +32,7 @@ } .aphront-dialog-view-width-form { - width: 600px; + width: 640px; } .aphront-dialog-view-width-full { diff --git a/webroot/rsrc/css/phui/phui-form-view.css b/webroot/rsrc/css/phui/phui-form-view.css index cc33808c5a..9dce0a4476 100644 --- a/webroot/rsrc/css/phui/phui-form-view.css +++ b/webroot/rsrc/css/phui/phui-form-view.css @@ -208,14 +208,13 @@ table.aphront-form-control-radio-layout, table.aphront-form-control-checkbox-layout { - margin-top: 3px; + margin-top: 4px !important; font-size: {$normalfontsize}; } table.aphront-form-control-radio-layout th { - padding-top: 3px; padding-left: 8px; - padding-bottom: 4px; + padding-bottom: 8px; font-weight: bold; color: {$darkgreytext}; }