@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Combine the "View", "Arrange", and "Manage" modes of Dashboards into a single mode

Summary:
Depends on D20361. Ref T13272. Currently, Dashboards have three separate modes: view, arrange, manage.

With the advent of Portals, I think we can simplify this, and make the dashboard view a combined view/edit/manage page. To view it in a cleaner standalone way, you can add it to a portal/home/project. I'll also improve the "Install" workflow.

Test Plan:
Viewed a dashboard page, clicked through all the actions, grepped for affected URIs.

{F6327027}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13272

Differential Revision: https://secure.phabricator.com/D20362

+43 -270
+4 -8
src/__phutil_library_map__.php
··· 2905 2905 'PhabricatorDashboard' => 'applications/dashboard/storage/PhabricatorDashboard.php', 2906 2906 'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php', 2907 2907 'PhabricatorDashboardApplication' => 'applications/dashboard/application/PhabricatorDashboardApplication.php', 2908 - 'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardArchiveController.php', 2909 - 'PhabricatorDashboardArrangeController' => 'applications/dashboard/controller/PhabricatorDashboardArrangeController.php', 2908 + 'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardArchiveController.php', 2910 2909 'PhabricatorDashboardConsoleController' => 'applications/dashboard/controller/PhabricatorDashboardConsoleController.php', 2911 2910 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', 2912 2911 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 2913 2912 'PhabricatorDashboardDashboardHasPanelEdgeType' => 'applications/dashboard/edge/PhabricatorDashboardDashboardHasPanelEdgeType.php', 2914 2913 'PhabricatorDashboardDashboardPHIDType' => 'applications/dashboard/phid/PhabricatorDashboardDashboardPHIDType.php', 2915 2914 'PhabricatorDashboardDatasource' => 'applications/dashboard/typeahead/PhabricatorDashboardDatasource.php', 2916 - 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', 2915 + 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardEditController.php', 2917 2916 'PhabricatorDashboardIconSet' => 'applications/dashboard/icon/PhabricatorDashboardIconSet.php', 2918 2917 'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php', 2919 - 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/PhabricatorDashboardInstallController.php', 2918 + 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php', 2920 2919 'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php', 2921 2920 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 2922 - 'PhabricatorDashboardManageController' => 'applications/dashboard/controller/PhabricatorDashboardManageController.php', 2923 2921 'PhabricatorDashboardMovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardMovePanelController.php', 2924 2922 'PhabricatorDashboardNgrams' => 'applications/dashboard/storage/PhabricatorDashboardNgrams.php', 2925 2923 'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php', ··· 2981 2979 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 2982 2980 'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php', 2983 2981 'PhabricatorDashboardTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardTransactionQuery.php', 2984 - 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php', 2982 + 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php', 2985 2983 'PhabricatorDataCacheSpec' => 'applications/cache/spec/PhabricatorDataCacheSpec.php', 2986 2984 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 2987 2985 'PhabricatorDatabaseRef' => 'infrastructure/cluster/PhabricatorDatabaseRef.php', ··· 8868 8866 'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController', 8869 8867 'PhabricatorDashboardApplication' => 'PhabricatorApplication', 8870 8868 'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController', 8871 - 'PhabricatorDashboardArrangeController' => 'PhabricatorDashboardProfileController', 8872 8869 'PhabricatorDashboardConsoleController' => 'PhabricatorDashboardController', 8873 8870 'PhabricatorDashboardController' => 'PhabricatorController', 8874 8871 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', ··· 8881 8878 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 8882 8879 'PhabricatorDashboardLayoutConfig' => 'Phobject', 8883 8880 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 8884 - 'PhabricatorDashboardManageController' => 'PhabricatorDashboardProfileController', 8885 8881 'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController', 8886 8882 'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams', 8887 8883 'PhabricatorDashboardPanel' => array(
-2
src/applications/dashboard/application/PhabricatorDashboardApplication.php
··· 41 41 => 'PhabricatorDashboardListController', 42 42 'view/(?P<id>\d+)/' => 'PhabricatorDashboardViewController', 43 43 'archive/(?P<id>\d+)/' => 'PhabricatorDashboardArchiveController', 44 - 'manage/(?P<id>\d+)/' => 'PhabricatorDashboardManageController', 45 - 'arrange/(?P<id>\d+)/' => 'PhabricatorDashboardArrangeController', 46 44 'create/' => 'PhabricatorDashboardEditController', 47 45 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController', 48 46 'install/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardInstallController',
+1 -1
src/applications/dashboard/controller/PhabricatorDashboardArchiveController.php src/applications/dashboard/controller/dashboard/PhabricatorDashboardArchiveController.php
··· 20 20 return new Aphront404Response(); 21 21 } 22 22 23 - $view_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); 23 + $view_uri = $dashboard->getURI(); 24 24 25 25 if ($request->isFormPost()) { 26 26 if ($dashboard->isArchived()) {
-79
src/applications/dashboard/controller/PhabricatorDashboardArrangeController.php
··· 1 - <?php 2 - 3 - final class PhabricatorDashboardArrangeController 4 - extends PhabricatorDashboardProfileController { 5 - 6 - public function shouldAllowPublic() { 7 - return true; 8 - } 9 - 10 - public function handleRequest(AphrontRequest $request) { 11 - $viewer = $request->getViewer(); 12 - $id = $request->getURIData('id'); 13 - 14 - $dashboard = id(new PhabricatorDashboardQuery()) 15 - ->setViewer($viewer) 16 - ->withIDs(array($id)) 17 - ->needPanels(true) 18 - ->executeOne(); 19 - if (!$dashboard) { 20 - return new Aphront404Response(); 21 - } 22 - $this->setDashboard($dashboard); 23 - 24 - $can_edit = PhabricatorPolicyFilter::hasCapability( 25 - $viewer, 26 - $dashboard, 27 - PhabricatorPolicyCapability::CAN_EDIT); 28 - 29 - $title = $dashboard->getName(); 30 - $crumbs = $this->buildApplicationCrumbs(); 31 - $crumbs->addTextCrumb(pht('Arrange')); 32 - $header = $this->buildHeaderView(); 33 - 34 - $info_view = null; 35 - if (!$can_edit) { 36 - $no_edit = pht( 37 - 'You do not have permission to edit this dashboard.'); 38 - 39 - $info_view = id(new PHUIInfoView()) 40 - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 41 - ->setErrors(array($no_edit)); 42 - } 43 - 44 - $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) 45 - ->setViewer($viewer) 46 - ->setDashboard($dashboard) 47 - ->setArrangeMode($can_edit) 48 - ->renderDashboard(); 49 - 50 - $dashboard_box = id(new PHUIBoxView()) 51 - ->addClass('dashboard-preview-box') 52 - ->appendChild($rendered_dashboard); 53 - 54 - $install_button = id(new PHUIButtonView()) 55 - ->setTag('a') 56 - ->setText('Install Dashboard') 57 - ->setIcon('fa-plus') 58 - ->setWorkflow(true) 59 - ->setHref($this->getApplicationURI("/install/{$id}/")); 60 - $header->addActionLink($install_button); 61 - 62 - $view = id(new PHUITwoColumnView()) 63 - ->setHeader($header) 64 - ->setFooter(array( 65 - $info_view, 66 - $dashboard_box, 67 - )); 68 - 69 - $navigation = $this->buildSideNavView('arrange'); 70 - 71 - return $this->newPage() 72 - ->setTitle($title) 73 - ->setCrumbs($crumbs) 74 - ->setNavigation($navigation) 75 - ->appendChild($view); 76 - 77 - } 78 - 79 - }
+3 -8
src/applications/dashboard/controller/PhabricatorDashboardEditController.php src/applications/dashboard/controller/dashboard/PhabricatorDashboardEditController.php
··· 55 55 56 56 $crumbs->addTextCrumb(pht('Create Dashboard')); 57 57 } else { 58 - $id = $dashboard->getID(); 59 - $cancel_uri = $this->getApplicationURI('manage/'.$id.'/'); 58 + $cancel_uri = $dashboard->getURI(); 60 59 61 60 $title = pht('Edit Dashboard: %s', $dashboard->getName()); 62 61 $header_icon = 'fa-pencil'; ··· 117 116 ->setContentSourceFromRequest($request) 118 117 ->applyTransactions($dashboard, $xactions); 119 118 120 - $uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/'); 121 - 122 - return id(new AphrontRedirectResponse())->setURI($uri); 119 + return id(new AphrontRedirectResponse())->setURI($dashboard->getURI()); 123 120 } catch (PhabricatorApplicationTransactionValidationException $ex) { 124 121 $validation_exception = $ex; 125 122 ··· 346 343 ->setContentSourceFromRequest($request) 347 344 ->applyTransactions($dashboard, $xactions); 348 345 349 - $manage_uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/'); 350 - 351 346 return id(new AphrontRedirectResponse()) 352 - ->setURI($manage_uri); 347 + ->setURI($dashboard->getURI()); 353 348 } 354 349 355 350 private function newPanel(
+1 -2
src/applications/dashboard/controller/PhabricatorDashboardInstallController.php src/applications/dashboard/controller/dashboard/PhabricatorDashboardInstallController.php
··· 15 15 return new Aphront404Response(); 16 16 } 17 17 18 - $cancel_uri = $this->getApplicationURI( 19 - 'view/'.$dashboard->getID().'/'); 18 + $cancel_uri = $dashboard->getURI(); 20 19 21 20 $home_app = new PhabricatorHomeApplication(); 22 21
+22 -48
src/applications/dashboard/controller/PhabricatorDashboardManageController.php src/applications/dashboard/controller/dashboard/PhabricatorDashboardViewController.php
··· 1 1 <?php 2 2 3 - final class PhabricatorDashboardManageController 3 + final class PhabricatorDashboardViewController 4 4 extends PhabricatorDashboardProfileController { 5 5 6 6 public function shouldAllowPublic() { ··· 11 11 $viewer = $request->getViewer(); 12 12 $id = $request->getURIData('id'); 13 13 14 - // TODO: This UI should drop a lot of capabilities if the user can't 15 - // edit the dashboard, but we should still let them in for "Install" and 16 - // "View History". 17 - 18 14 $dashboard = id(new PhabricatorDashboardQuery()) 19 15 ->setViewer($viewer) 20 16 ->withIDs(array($id)) ··· 31 27 PhabricatorPolicyCapability::CAN_EDIT); 32 28 33 29 $title = $dashboard->getName(); 34 - 35 30 $crumbs = $this->buildApplicationCrumbs(); 36 - $crumbs->addTextCrumb(pht('Manage')); 37 - 38 31 $header = $this->buildHeaderView(); 32 + 39 33 $curtain = $this->buildCurtainView($dashboard); 40 - $properties = $this->buildPropertyView($dashboard); 41 34 42 35 $timeline = $this->buildTransactionTimeline( 43 36 $dashboard, 44 37 new PhabricatorDashboardTransactionQuery()); 45 38 $timeline->setShouldTerminate(true); 46 39 47 - $info_view = null; 48 - if (!$can_edit) { 49 - $no_edit = pht( 50 - 'You do not have permission to edit this dashboard.'); 40 + $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) 41 + ->setViewer($viewer) 42 + ->setDashboard($dashboard) 43 + ->setArrangeMode($can_edit) 44 + ->renderDashboard(); 51 45 52 - $info_view = id(new PHUIInfoView()) 53 - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 54 - ->setErrors(array($no_edit)); 55 - } 46 + $dashboard_box = id(new PHUIBoxView()) 47 + ->addClass('dashboard-preview-box') 48 + ->appendChild($rendered_dashboard); 56 49 57 50 $view = id(new PHUITwoColumnView()) 58 51 ->setHeader($header) 59 52 ->setCurtain($curtain) 60 - ->setMainColumn(array( 61 - $info_view, 62 - $properties, 63 - $timeline, 64 - )); 65 - 66 - $navigation = $this->buildSideNavView('manage'); 53 + ->setMainColumn( 54 + array( 55 + $dashboard_box, 56 + $timeline, 57 + )); 67 58 68 59 return $this->newPage() 69 60 ->setTitle($title) 70 61 ->setCrumbs($crumbs) 71 - ->setNavigation($navigation) 72 62 ->appendChild($view); 73 63 74 64 } ··· 91 81 ->setHref($this->getApplicationURI("edit/{$id}/")) 92 82 ->setDisabled(!$can_edit)); 93 83 84 + $curtain->addAction( 85 + id(new PhabricatorActionView()) 86 + ->setName(pht('Install Dashboard')) 87 + ->setIcon('fa-wrench') 88 + ->setHref($this->getApplicationURI("/install/{$id}/")) 89 + ->setWorkflow(true)); 90 + 94 91 if ($dashboard->isArchived()) { 95 92 $curtain->addAction( 96 93 id(new PhabricatorActionView()) ··· 112 109 return $curtain; 113 110 } 114 111 115 - private function buildPropertyView(PhabricatorDashboard $dashboard) { 116 - $viewer = $this->getViewer(); 117 - 118 - $properties = id(new PHUIPropertyListView()) 119 - ->setUser($viewer); 120 - 121 - $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( 122 - $viewer, 123 - $dashboard); 124 - 125 - $properties->addProperty( 126 - pht('Editable By'), 127 - $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); 128 - 129 - $properties->addProperty( 130 - pht('Panels'), 131 - $viewer->renderHandleList($dashboard->getPanelPHIDs())); 132 - 133 - return id(new PHUIObjectBoxView()) 134 - ->setHeaderText(pht('Details')) 135 - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 136 - ->addPropertyList($properties); 137 - } 138 112 139 113 }
+1 -45
src/applications/dashboard/controller/PhabricatorDashboardProfileController.php
··· 14 14 return $this->dashboard; 15 15 } 16 16 17 - public function buildApplicationMenu() { 18 - return $this->buildSideNavView()->getMenu(); 19 - } 20 - 21 17 protected function buildHeaderView() { 22 18 $viewer = $this->getViewer(); 23 19 $dashboard = $this->getDashboard(); ··· 49 45 50 46 $dashboard = $this->getDashboard(); 51 47 if ($dashboard) { 52 - $id = $dashboard->getID(); 53 - $dashboard_uri = $this->getApplicationURI("/view/{$id}/"); 54 - $crumbs->addTextCrumb($dashboard->getName(), $dashboard_uri); 48 + $crumbs->addTextCrumb($dashboard->getName(), $dashboard->getURI()); 55 49 } 56 50 57 51 return $crumbs; 58 - } 59 - 60 - protected function buildSideNavView($filter = null) { 61 - $viewer = $this->getViewer(); 62 - $dashboard = $this->getDashboard(); 63 - $id = $dashboard->getID(); 64 - 65 - $can_edit = PhabricatorPolicyFilter::hasCapability( 66 - $viewer, 67 - $dashboard, 68 - PhabricatorPolicyCapability::CAN_EDIT); 69 - 70 - $nav = id(new AphrontSideNavFilterView()) 71 - ->setBaseURI(new PhutilURI($this->getApplicationURI())); 72 - 73 - $nav->addLabel(pht('Dashboard')); 74 - 75 - $nav->addFilter( 76 - 'view', 77 - pht('View Dashboard'), 78 - $this->getApplicationURI("/view/{$id}/"), 79 - 'fa-dashboard'); 80 - 81 - $nav->addFilter( 82 - 'arrange', 83 - pht('Arrange Panels'), 84 - $this->getApplicationURI("/arrange/{$id}/"), 85 - 'fa-columns'); 86 - 87 - $nav->addFilter( 88 - 'manage', 89 - pht('Manage Dashboard'), 90 - $this->getApplicationURI("/manage/{$id}/"), 91 - 'fa-gears'); 92 - 93 - $nav->selectFilter($filter); 94 - 95 - return $nav; 96 52 } 97 53 98 54 }
+1 -1
src/applications/dashboard/controller/PhabricatorDashboardQueryPanelInstallController.php
··· 75 75 } 76 76 77 77 if (!$errors) { 78 - $redirect_uri = "/dashboard/arrange/{$v_dashboard}/"; 78 + $redirect_uri = "/dashboard/view/{$v_dashboard}/"; 79 79 80 80 $panel_type = id(new PhabricatorDashboardQueryPanelType()) 81 81 ->getPanelTypeKey();
-68
src/applications/dashboard/controller/PhabricatorDashboardViewController.php
··· 1 - <?php 2 - 3 - final class PhabricatorDashboardViewController 4 - extends PhabricatorDashboardProfileController { 5 - 6 - public function shouldAllowPublic() { 7 - return true; 8 - } 9 - 10 - public function handleRequest(AphrontRequest $request) { 11 - $viewer = $request->getViewer(); 12 - $id = $request->getURIData('id'); 13 - 14 - $dashboard = id(new PhabricatorDashboardQuery()) 15 - ->setViewer($viewer) 16 - ->withIDs(array($id)) 17 - ->needPanels(true) 18 - ->executeOne(); 19 - if (!$dashboard) { 20 - return new Aphront404Response(); 21 - } 22 - $this->setDashboard($dashboard); 23 - 24 - $dashboard_uri = $this->getApplicationURI("view/{$id}/"); 25 - $title = $dashboard->getName(); 26 - $crumbs = $this->buildApplicationCrumbs(); 27 - $crumbs->addTextCrumb(pht('View')); 28 - 29 - if ($dashboard->getPanelPHIDs()) { 30 - $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) 31 - ->setViewer($viewer) 32 - ->setDashboard($dashboard) 33 - ->renderDashboard(); 34 - $content = id(new PHUIBoxView()) 35 - ->addClass('dashboard-preview-box') 36 - ->appendChild($rendered_dashboard); 37 - } else { 38 - $content = id(new PHUIInfoView()) 39 - ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) 40 - ->appendChild(pht('This dashboard has no panels yet.')); 41 - } 42 - 43 - $navigation = $this->buildSideNavView('view'); 44 - $header = $this->buildHeaderView(); 45 - 46 - $install_button = id(new PHUIButtonView()) 47 - ->setTag('a') 48 - ->setText('Install Dashboard') 49 - ->setIcon('fa-plus') 50 - ->setColor(PHUIButtonView::GREEN) 51 - ->setWorkflow(true) 52 - ->setHref($this->getApplicationURI("/install/{$id}/")); 53 - $header->addActionLink($install_button); 54 - 55 - $view = id(new PHUITwoColumnView()) 56 - ->setHeader($header) 57 - ->setFooter(array( 58 - $content, 59 - )); 60 - 61 - return $this->newPage() 62 - ->setTitle($title) 63 - ->setCrumbs($crumbs) 64 - ->setNavigation($navigation) 65 - ->appendChild($view); 66 - } 67 - 68 - }
+4 -5
src/applications/dashboard/query/PhabricatorDashboardSearchEngine.php
··· 123 123 $handles = $viewer->loadHandles($phids); 124 124 125 125 $list = id(new PHUIObjectItemListView()) 126 - ->setUser($viewer); 126 + ->setViewer($viewer); 127 127 128 128 foreach ($dashboards as $dashboard) { 129 - $id = $dashboard->getID(); 130 - 131 129 $item = id(new PHUIObjectItemView()) 132 - ->setUser($viewer) 130 + ->setViewer($viewer) 131 + ->setObjectName($dashboard->getObjectName()) 133 132 ->setHeader($dashboard->getName()) 134 - ->setHref($this->getApplicationURI("view/{$id}/")) 133 + ->setHref($dashboard->getURI()) 135 134 ->setObject($dashboard); 136 135 137 136 $bg_color = 'bg-dark';
+5 -2
src/applications/dashboard/storage/PhabricatorDashboard.php
··· 118 118 return ($this->getStatus() == self::STATUS_ARCHIVED); 119 119 } 120 120 121 - public function getViewURI() { 122 - return '/dashboard/view/'.$this->getID().'/'; 121 + public function getURI() { 122 + return urisprintf('/dashboard/view/%d/', $this->getID()); 123 123 } 124 124 125 + public function getObjectName() { 126 + return pht('Dashboard %d', $this->getID()); 127 + } 125 128 126 129 /* -( PhabricatorApplicationTransactionInterface )------------------------- */ 127 130
+1 -1
src/applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php
··· 153 153 $icon = $dashboard->getIcon(); 154 154 $name = $this->getDisplayName($config); 155 155 $is_disabled = false; 156 - $action_uri = '/dashboard/arrange/'.$dashboard->getID().'/'; 156 + $action_uri = $dashboard->getURI(); 157 157 } 158 158 } else { 159 159 $icon = 'fa-ban';