Touch up basic usability of Dashboards
Summary: Ref T10390. This mostly shuffles layout into "View" and keepts "Manage" around for Edit/Copy/History. This feels better to me overall. Also tweaked some spacing and color.
Test Plan:
New Dashboard, edit Dashboard, shuffle panels. Create new panels.
{F2684043}
Reviewers: epriestley
Reviewed By: epriestley
Subscribers: Korvin
Maniphest Tasks: T10390
Differential Revision: https://secure.phabricator.com/D17326
			
			
This commit is contained in:
		| @@ -9,7 +9,7 @@ return array( | ||||
|   'names' => array( | ||||
|     'conpherence.pkg.css' => 'a520d619', | ||||
|     'conpherence.pkg.js' => '6249a1cf', | ||||
|     'core.pkg.css' => '72ab63ef', | ||||
|     'core.pkg.css' => '2a5c3505', | ||||
|     'core.pkg.js' => '1fa7c0c5', | ||||
|     'darkconsole.pkg.js' => 'e7393ebb', | ||||
|     'differential.pkg.css' => '4815647b', | ||||
| @@ -55,7 +55,7 @@ return array( | ||||
|     'rsrc/css/application/contentsource/content-source-view.css' => '4b8b05d4', | ||||
|     'rsrc/css/application/countdown/timer.css' => '16c52f5c', | ||||
|     'rsrc/css/application/daemon/bulk-job.css' => 'df9c1d4a', | ||||
|     'rsrc/css/application/dashboard/dashboard.css' => '226c4dc6', | ||||
|     'rsrc/css/application/dashboard/dashboard.css' => '005e064e', | ||||
|     'rsrc/css/application/diff/inline-comment-summary.css' => '51efda3a', | ||||
|     'rsrc/css/application/differential/add-comment.css' => 'c47f8c40', | ||||
|     'rsrc/css/application/differential/changeset-view.css' => '6a9bdf9c', | ||||
| @@ -102,7 +102,7 @@ return array( | ||||
|     'rsrc/css/application/releeph/releeph-preview-branch.css' => 'b7a6f4a5', | ||||
|     'rsrc/css/application/releeph/releeph-request-differential-create-dialog.css' => '8d8b92cd', | ||||
|     'rsrc/css/application/releeph/releeph-request-typeahead.css' => '667a48ae', | ||||
|     'rsrc/css/application/search/application-search-view.css' => '20ae9d85', | ||||
|     'rsrc/css/application/search/application-search-view.css' => '66ee5d46', | ||||
|     'rsrc/css/application/search/search-results.css' => '64ad079a', | ||||
|     'rsrc/css/application/slowvote/slowvote.css' => 'a94b7230', | ||||
|     'rsrc/css/application/tokens/tokens.css' => '3d0f239e', | ||||
| @@ -556,7 +556,7 @@ return array( | ||||
|     'aphront-tokenizer-control-css' => '9a8cb501', | ||||
|     'aphront-tooltip-css' => '173b9431', | ||||
|     'aphront-typeahead-control-css' => 'd4f16145', | ||||
|     'application-search-view-css' => '20ae9d85', | ||||
|     'application-search-view-css' => '66ee5d46', | ||||
|     'auth-css' => '0877ed6e', | ||||
|     'bulk-job-css' => 'df9c1d4a', | ||||
|     'changeset-view-manager' => 'a2828756', | ||||
| @@ -786,7 +786,7 @@ return array( | ||||
|     'phabricator-content-source-view-css' => '4b8b05d4', | ||||
|     'phabricator-core-css' => '9f4cb463', | ||||
|     'phabricator-countdown-css' => '16c52f5c', | ||||
|     'phabricator-dashboard-css' => '226c4dc6', | ||||
|     'phabricator-dashboard-css' => '005e064e', | ||||
|     'phabricator-drag-and-drop-file-upload' => '58dea2fa', | ||||
|     'phabricator-draggable-list' => 'bea6e7f4', | ||||
|     'phabricator-fatal-config-template-css' => '8f18fa41', | ||||
|   | ||||
| @@ -2464,6 +2464,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardAddPanelController' => 'applications/dashboard/controller/PhabricatorDashboardAddPanelController.php', | ||||
|     'PhabricatorDashboardApplication' => 'applications/dashboard/application/PhabricatorDashboardApplication.php', | ||||
|     'PhabricatorDashboardArchiveController' => 'applications/dashboard/controller/PhabricatorDashboardArchiveController.php', | ||||
|     'PhabricatorDashboardArrangeController' => 'applications/dashboard/controller/PhabricatorDashboardArrangeController.php', | ||||
|     'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', | ||||
|     'PhabricatorDashboardCopyController' => 'applications/dashboard/controller/PhabricatorDashboardCopyController.php', | ||||
|     'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', | ||||
| @@ -2503,6 +2504,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php', | ||||
|     'PhabricatorDashboardPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardPanelType.php', | ||||
|     'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', | ||||
|     'PhabricatorDashboardProfileController' => 'applications/dashboard/controller/PhabricatorDashboardProfileController.php', | ||||
|     'PhabricatorDashboardProfileMenuItem' => 'applications/search/menuitem/PhabricatorDashboardProfileMenuItem.php', | ||||
|     'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', | ||||
|     'PhabricatorDashboardQueryPanelType' => 'applications/dashboard/paneltype/PhabricatorDashboardQueryPanelType.php', | ||||
| @@ -7471,6 +7473,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardAddPanelController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardApplication' => 'PhabricatorApplication', | ||||
|     'PhabricatorDashboardArchiveController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardArrangeController' => 'PhabricatorDashboardProfileController', | ||||
|     'PhabricatorDashboardController' => 'PhabricatorController', | ||||
|     'PhabricatorDashboardCopyController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', | ||||
| @@ -7482,7 +7485,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', | ||||
|     'PhabricatorDashboardLayoutConfig' => 'Phobject', | ||||
|     'PhabricatorDashboardListController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardManageController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardManageController' => 'PhabricatorDashboardProfileController', | ||||
|     'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardNgrams' => 'PhabricatorSearchNgrams', | ||||
|     'PhabricatorDashboardPanel' => array( | ||||
| @@ -7521,6 +7524,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'PhabricatorDashboardPanelType' => 'Phobject', | ||||
|     'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardProfileController' => 'PhabricatorController', | ||||
|     'PhabricatorDashboardProfileMenuItem' => 'PhabricatorProfileMenuItem', | ||||
|     'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||
|     'PhabricatorDashboardQueryPanelType' => 'PhabricatorDashboardPanelType', | ||||
| @@ -7535,7 +7539,7 @@ phutil_register_library_map(array( | ||||
|     'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', | ||||
|     'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||
|     'PhabricatorDashboardUninstallController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardViewController' => 'PhabricatorDashboardController', | ||||
|     'PhabricatorDashboardViewController' => 'PhabricatorDashboardProfileController', | ||||
|     'PhabricatorDataCacheSpec' => 'PhabricatorCacheSpec', | ||||
|     'PhabricatorDataNotAttachedException' => 'Exception', | ||||
|     'PhabricatorDatabaseHealthRecord' => 'Phobject', | ||||
|   | ||||
| @@ -27,6 +27,7 @@ final class PhabricatorDashboardApplication extends PhabricatorApplication { | ||||
|         'view/(?P<id>\d+)/' => 'PhabricatorDashboardViewController', | ||||
|         'archive/(?P<id>\d+)/' => 'PhabricatorDashboardArchiveController', | ||||
|         'manage/(?P<id>\d+)/' => 'PhabricatorDashboardManageController', | ||||
|         'arrange/(?P<id>\d+)/' => 'PhabricatorDashboardArrangeController', | ||||
|         'create/' => 'PhabricatorDashboardEditController', | ||||
|         'copy/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardCopyController', | ||||
|         'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController', | ||||
|   | ||||
| @@ -20,7 +20,8 @@ final class PhabricatorDashboardAddPanelController | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $redirect_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|     $redirect_uri = $this->getApplicationURI( | ||||
|       'arrange/'.$dashboard->getID().'/'); | ||||
|  | ||||
|     $v_panel = $request->getStr('panel'); | ||||
|     $e_panel = true; | ||||
|   | ||||
| @@ -0,0 +1,72 @@ | ||||
| <?php | ||||
|  | ||||
| final class PhabricatorDashboardArrangeController | ||||
|   extends PhabricatorDashboardProfileController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|     $id = $request->getURIData('id'); | ||||
|  | ||||
|     $dashboard = id(new PhabricatorDashboardQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withIDs(array($id)) | ||||
|       ->needPanels(true) | ||||
|       ->executeOne(); | ||||
|     if (!$dashboard) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|     $this->setDashboard($dashboard); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $dashboard, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $title = $dashboard->getName(); | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb(pht('Arrange')); | ||||
|     $header = $this->buildHeaderView(); | ||||
|  | ||||
|     $info_view = null; | ||||
|     if (!$can_edit) { | ||||
|       $no_edit = pht( | ||||
|         'You do not have permission to edit this dashboard. If you want to '. | ||||
|         'make changes, make a copy first.'); | ||||
|  | ||||
|       $info_view = id(new PHUIInfoView()) | ||||
|         ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) | ||||
|         ->setErrors(array($no_edit)); | ||||
|     } | ||||
|  | ||||
|     $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setDashboard($dashboard) | ||||
|       ->setArrangeMode($can_edit) | ||||
|       ->renderDashboard(); | ||||
|  | ||||
|     $dashboard_box = id(new PHUIBoxView()) | ||||
|       ->addClass('dashboard-preview-box') | ||||
|       ->appendChild($rendered_dashboard); | ||||
|  | ||||
|     $view = id(new PHUITwoColumnView()) | ||||
|       ->setHeader($header) | ||||
|       ->setFooter(array( | ||||
|         $info_view, | ||||
|         $dashboard_box, | ||||
|       )); | ||||
|  | ||||
|     $navigation = $this->buildSideNavView('arrange'); | ||||
|  | ||||
|     return $this->newPage() | ||||
|       ->setTitle($title) | ||||
|       ->setCrumbs($crumbs) | ||||
|       ->setNavigation($navigation) | ||||
|       ->appendChild($view); | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -16,7 +16,7 @@ final class PhabricatorDashboardCopyController | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|  | ||||
|     $manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|     $cancel_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|  | ||||
| @@ -45,8 +45,8 @@ final class PhabricatorDashboardCopyController | ||||
|         ->setContinueOnNoEffect(true) | ||||
|         ->applyTransactions($copy, $xactions); | ||||
|  | ||||
|       $manage_uri = $this->getApplicationURI('edit/'.$copy->getID().'/'); | ||||
|       return id(new AphrontRedirectResponse())->setURI($manage_uri); | ||||
|       $cancel_uri = $this->getApplicationURI('edit/'.$copy->getID().'/'); | ||||
|       return id(new AphrontRedirectResponse())->setURI($cancel_uri); | ||||
|     } | ||||
|  | ||||
|     return $this->newDialog() | ||||
| @@ -55,7 +55,7 @@ final class PhabricatorDashboardCopyController | ||||
|         pht( | ||||
|           'Create a copy of the dashboard "%s"?', | ||||
|           phutil_tag('strong', array(), $dashboard->getName()))) | ||||
|       ->addCancelButton($manage_uri) | ||||
|       ->addCancelButton($cancel_uri) | ||||
|       ->addSubmitButton(pht('Create Copy')); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -117,7 +117,7 @@ final class PhabricatorDashboardEditController | ||||
|           ->setContentSourceFromRequest($request) | ||||
|           ->applyTransactions($dashboard, $xactions); | ||||
|  | ||||
|         $uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|         $uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/'); | ||||
|  | ||||
|         return id(new AphrontRedirectResponse())->setURI($uri); | ||||
|       } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
| @@ -351,7 +351,7 @@ final class PhabricatorDashboardEditController | ||||
|       ->setContentSourceFromRequest($request) | ||||
|       ->applyTransactions($dashboard, $xactions); | ||||
|  | ||||
|     $manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|     $manage_uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/'); | ||||
|  | ||||
|     return id(new AphrontRedirectResponse()) | ||||
|       ->setURI($manage_uri); | ||||
|   | ||||
| @@ -1,14 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| final class PhabricatorDashboardManageController | ||||
|   extends PhabricatorDashboardController { | ||||
|   extends PhabricatorDashboardProfileController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|     $id = $request->getURIData('id'); | ||||
|  | ||||
|     $dashboard_uri = $this->getApplicationURI('view/'.$id.'/'); | ||||
|  | ||||
|     // TODO: This UI should drop a lot of capabilities if the user can't | ||||
|     // edit the dashboard, but we should still let them in for "Install" and | ||||
|     // "View History". | ||||
| @@ -21,6 +23,7 @@ final class PhabricatorDashboardManageController | ||||
|     if (!$dashboard) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|     $this->setDashboard($dashboard); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
| @@ -30,19 +33,16 @@ final class PhabricatorDashboardManageController | ||||
|     $title = $dashboard->getName(); | ||||
|  | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb( | ||||
|       pht('Dashboard %d', $dashboard->getID()), | ||||
|       $dashboard_uri); | ||||
|     $crumbs->addTextCrumb(pht('Manage')); | ||||
|     $crumbs->setBorder(true); | ||||
|  | ||||
|     $header = $this->buildHeaderView($dashboard); | ||||
|     $header = $this->buildHeaderView(); | ||||
|     $curtain = $this->buildCurtainview($dashboard); | ||||
|     $properties = $this->buildPropertyView($dashboard); | ||||
|  | ||||
|     $timeline = $this->buildTransactionTimeline( | ||||
|       $dashboard, | ||||
|       new PhabricatorDashboardTransactionQuery()); | ||||
|     $timeline->setShouldTerminate(true); | ||||
|  | ||||
|     $info_view = null; | ||||
|     if (!$can_edit) { | ||||
| @@ -55,16 +55,6 @@ final class PhabricatorDashboardManageController | ||||
|         ->setErrors(array($no_edit)); | ||||
|     } | ||||
|  | ||||
|     $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) | ||||
|       ->setViewer($viewer) | ||||
|       ->setDashboard($dashboard) | ||||
|       ->setArrangeMode($can_edit) | ||||
|       ->renderDashboard(); | ||||
|  | ||||
|     $dashboard_box = id(new PHUIBoxView()) | ||||
|       ->addClass('dashboard-preview-box') | ||||
|       ->appendChild($rendered_dashboard); | ||||
|  | ||||
|     $view = id(new PHUITwoColumnView()) | ||||
|       ->setHeader($header) | ||||
|       ->setCurtain($curtain) | ||||
| @@ -72,47 +62,18 @@ final class PhabricatorDashboardManageController | ||||
|         $info_view, | ||||
|         $properties, | ||||
|         $timeline, | ||||
|       )) | ||||
|       ->setFooter($dashboard_box); | ||||
|       )); | ||||
|  | ||||
|     $navigation = $this->buildSideNavView('manage'); | ||||
|  | ||||
|     return $this->newPage() | ||||
|       ->setTitle($title) | ||||
|       ->setCrumbs($crumbs) | ||||
|       ->setNavigation($navigation) | ||||
|       ->appendChild($view); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private function buildHeaderView(PhabricatorDashboard $dashboard) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $dashboard->getID(); | ||||
|  | ||||
|     if ($dashboard->isArchived()) { | ||||
|       $status_icon = 'fa-ban'; | ||||
|       $status_color = 'dark'; | ||||
|     } else { | ||||
|       $status_icon = 'fa-check'; | ||||
|       $status_color = 'bluegrey'; | ||||
|     } | ||||
|  | ||||
|     $status_name = idx( | ||||
|       PhabricatorDashboard::getStatusNameMap(), | ||||
|       $dashboard->getStatus()); | ||||
|  | ||||
|     $button = id(new PHUIButtonView()) | ||||
|       ->setTag('a') | ||||
|       ->setText(pht('View Dashboard')) | ||||
|       ->setIcon('fa-columns') | ||||
|       ->setHref($this->getApplicationURI("view/{$id}/")); | ||||
|  | ||||
|     return id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($dashboard->getName()) | ||||
|       ->setPolicyObject($dashboard) | ||||
|       ->setStatus($status_icon, $status_color, $status_name) | ||||
|       ->setHeaderIcon($dashboard->getIcon()) | ||||
|       ->addActionLink($button); | ||||
|   } | ||||
|  | ||||
|   private function buildCurtainView(PhabricatorDashboard $dashboard) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $id = $dashboard->getID(); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ final class PhabricatorDashboardPanelEditController | ||||
|         return new Aphront404Response(); | ||||
|       } | ||||
|  | ||||
|       $manage_uri = $this->getApplicationURI('manage/'.$dashboard_id.'/'); | ||||
|       $manage_uri = $this->getApplicationURI('arrange/'.$dashboard_id.'/'); | ||||
|     } | ||||
|  | ||||
|     if ($id) { | ||||
| @@ -372,7 +372,7 @@ final class PhabricatorDashboardPanelEditController | ||||
|  | ||||
|     $viewer = $request->getUser(); | ||||
|  | ||||
|     $manage_uri = $this->getApplicationURI('manage/'.$dashboard->getID().'/'); | ||||
|     $manage_uri = $this->getApplicationURI('arrange/'.$dashboard->getID().'/'); | ||||
|  | ||||
|     return $this->newDialog() | ||||
|       ->setTitle(pht('Copy Panel?')) | ||||
|   | ||||
| @@ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| abstract class PhabricatorDashboardProfileController | ||||
|   extends PhabricatorController { | ||||
|  | ||||
|   private $dashboard; | ||||
|  | ||||
|   public function setDashboard(PhabricatorDashboard $dashboard) { | ||||
|     $this->dashboard = $dashboard; | ||||
|     return $this; | ||||
|   } | ||||
|  | ||||
|   public function getDashboard() { | ||||
|     return $this->dashboard; | ||||
|   } | ||||
|  | ||||
|   public function buildApplicationMenu() { | ||||
|     return $this->buildSideNavView()->getMenu(); | ||||
|   } | ||||
|  | ||||
|   protected function buildHeaderView() { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $dashboard = $this->getDashboard(); | ||||
|     $id = $dashboard->getID(); | ||||
|  | ||||
|     if ($dashboard->isArchived()) { | ||||
|       $status_icon = 'fa-ban'; | ||||
|       $status_color = 'dark'; | ||||
|     } else { | ||||
|       $status_icon = 'fa-check'; | ||||
|       $status_color = 'bluegrey'; | ||||
|     } | ||||
|  | ||||
|     $status_name = idx( | ||||
|       PhabricatorDashboard::getStatusNameMap(), | ||||
|       $dashboard->getStatus()); | ||||
|  | ||||
|     return id(new PHUIHeaderView()) | ||||
|       ->setUser($viewer) | ||||
|       ->setHeader($dashboard->getName()) | ||||
|       ->setPolicyObject($dashboard) | ||||
|       ->setStatus($status_icon, $status_color, $status_name) | ||||
|       ->setHeaderIcon($dashboard->getIcon()); | ||||
|   } | ||||
|  | ||||
|   protected function buildApplicationCrumbs() { | ||||
|     $dashboard = $this->getDashboard(); | ||||
|     $id = $dashboard->getID(); | ||||
|     $dashboard_uri = $this->getApplicationURI("/view/{$id}/"); | ||||
|  | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|     $crumbs->addTextCrumb($dashboard->getName(), $dashboard_uri); | ||||
|     $crumbs->setBorder(true); | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
|   protected function buildSideNavView($filter = null) { | ||||
|     $viewer = $this->getViewer(); | ||||
|     $dashboard = $this->getDashboard(); | ||||
|     $id = $dashboard->getID(); | ||||
|  | ||||
|     $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|       $viewer, | ||||
|       $dashboard, | ||||
|       PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|     $nav = id(new AphrontSideNavFilterView()) | ||||
|       ->setBaseURI(new PhutilURI($this->getApplicationURI())); | ||||
|  | ||||
|     $nav->addLabel(pht('Dashboard')); | ||||
|  | ||||
|     $nav->addFilter( | ||||
|       'view', | ||||
|       pht('View Dashboard'), | ||||
|       $this->getApplicationURI("/view/{$id}/"), | ||||
|       'fa-dashboard'); | ||||
|  | ||||
|     $nav->addFilter( | ||||
|       'arrange', | ||||
|       pht('Arrange Panels'), | ||||
|       $this->getApplicationURI("/arrange/{$id}/"), | ||||
|       'fa-columns'); | ||||
|  | ||||
|     $nav->addFilter( | ||||
|       'manage', | ||||
|       pht('Manage Dashboard'), | ||||
|       $this->getApplicationURI("/manage/{$id}/"), | ||||
|       'fa-gears'); | ||||
|  | ||||
|     $nav->selectFilter($filter); | ||||
|  | ||||
|     return $nav; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -43,7 +43,7 @@ final class PhabricatorDashboardRemovePanelController | ||||
|     } | ||||
|  | ||||
|     $redirect_uri = $this->getApplicationURI( | ||||
|       'manage/'.$dashboard->getID().'/'); | ||||
|       'arrange/'.$dashboard->getID().'/'); | ||||
|     $layout_config = $dashboard->getLayoutConfigObject(); | ||||
|  | ||||
|     if ($request->isFormPost()) { | ||||
|   | ||||
| @@ -1,9 +1,7 @@ | ||||
| <?php | ||||
|  | ||||
| final class PhabricatorDashboardViewController | ||||
|   extends PhabricatorDashboardController { | ||||
|  | ||||
|   private $id; | ||||
|   extends PhabricatorDashboardProfileController { | ||||
|  | ||||
|   public function shouldAllowPublic() { | ||||
|     return true; | ||||
| @@ -11,63 +9,51 @@ final class PhabricatorDashboardViewController | ||||
|  | ||||
|   public function handleRequest(AphrontRequest $request) { | ||||
|     $viewer = $request->getViewer(); | ||||
|     $this->id = $request->getURIData('id'); | ||||
|     $id = $request->getURIData('id'); | ||||
|  | ||||
|     $dashboard = id(new PhabricatorDashboardQuery()) | ||||
|       ->setViewer($viewer) | ||||
|       ->withIDs(array($this->id)) | ||||
|       ->withIDs(array($id)) | ||||
|       ->needPanels(true) | ||||
|       ->executeOne(); | ||||
|     if (!$dashboard) { | ||||
|       return new Aphront404Response(); | ||||
|     } | ||||
|     $this->setDashboard($dashboard); | ||||
|  | ||||
|     $dashboard_uri = $this->getApplicationURI("view/{$id}/"); | ||||
|     $title = $dashboard->getName(); | ||||
|     $crumbs = $this->buildApplicationCrumbs(); | ||||
|     $crumbs->setBorder(true); | ||||
|     $crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID())); | ||||
|     $crumbs->addTextCrumb(pht('View')); | ||||
|  | ||||
|     if ($dashboard->getPanelPHIDs()) { | ||||
|       $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) | ||||
|         ->setViewer($viewer) | ||||
|         ->setDashboard($dashboard) | ||||
|         ->renderDashboard(); | ||||
|       $content = id(new PHUIBoxView()) | ||||
|         ->addClass('dashboard-preview-box') | ||||
|         ->appendChild($rendered_dashboard); | ||||
|     } else { | ||||
|       $rendered_dashboard = $this->buildEmptyView(); | ||||
|       $content = id(new PHUIInfoView()) | ||||
|         ->setSeverity(PHUIInfoView::SEVERITY_NOTICE) | ||||
|         ->appendChild(pht('This dashboard has no panels yet.')); | ||||
|     } | ||||
|  | ||||
|     $navigation = $this->buildSideNavView('view'); | ||||
|     $header = $this->buildHeaderView(); | ||||
|  | ||||
|     $view = id(new PHUITwoColumnView()) | ||||
|       ->setHeader($header) | ||||
|       ->setFooter(array( | ||||
|         $content, | ||||
|       )); | ||||
|  | ||||
|     return $this->newPage() | ||||
|       ->setTitle($title) | ||||
|       ->setCrumbs($crumbs) | ||||
|       ->appendChild($rendered_dashboard); | ||||
|   } | ||||
|  | ||||
|   protected function buildApplicationCrumbs() { | ||||
|     $crumbs = parent::buildApplicationCrumbs(); | ||||
|     $id = $this->id; | ||||
|  | ||||
|     $crumbs->addAction( | ||||
|       id(new PHUIListItemView()) | ||||
|         ->setIcon('fa-th') | ||||
|         ->setName(pht('Manage Dashboard')) | ||||
|         ->setHref($this->getApplicationURI("manage/{$id}/"))); | ||||
|  | ||||
|     return $crumbs; | ||||
|   } | ||||
|  | ||||
|   public function buildEmptyView() { | ||||
|     $id = $this->id; | ||||
|     $manage_uri = $this->getApplicationURI("manage/{$id}/"); | ||||
|  | ||||
|     return id(new PHUIInfoView()) | ||||
|       ->setSeverity(PHUIInfoView::SEVERITY_NODATA) | ||||
|       ->appendChild( | ||||
|         pht('This dashboard has no panels '. | ||||
|           'yet. Use %s to add panels.', | ||||
|           phutil_tag( | ||||
|             'a', | ||||
|             array('href' => $manage_uri), | ||||
|             pht('Manage Dashboard')))); | ||||
|       ->setNavigation($navigation) | ||||
|       ->appendChild($view); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -81,17 +81,43 @@ final class PhabricatorDashboardRenderingEngine extends Phobject { | ||||
|     } | ||||
|  | ||||
|     if ($this->arrangeMode) { | ||||
|       $footer = null; | ||||
|       Javelin::initBehavior( | ||||
|         'dashboard-move-panels', | ||||
|         array( | ||||
|           'dashboardID' => $dashboard_id, | ||||
|           'moveURI' => '/dashboard/movepanel/'.$dashboard->getID().'/', | ||||
|         )); | ||||
|     } else { | ||||
|       $name = $dashboard->getName(); | ||||
|       $icon = id(new PHUIIconView()) | ||||
|         ->setIcon($dashboard->getIcon()) | ||||
|         ->addClass('msr'); | ||||
|       $footer_left = phutil_tag( | ||||
|         'a', | ||||
|         array( | ||||
|           'class' => 'dashboard-footer-name', | ||||
|           'href' => '/dashboard/view/'.$dashboard->getID().'/', | ||||
|         ), | ||||
|         array( | ||||
|           $icon, | ||||
|           $name, | ||||
|         )); | ||||
|  | ||||
|       $footer = phutil_tag( | ||||
|         'div', | ||||
|         array( | ||||
|           'class' => 'dashboard-footer-view', | ||||
|         ), | ||||
|         array( | ||||
|           $footer_left, | ||||
|         )); | ||||
|     } | ||||
|  | ||||
|     $view = id(new PHUIBoxView()) | ||||
|       ->addClass('dashboard-view') | ||||
|       ->appendChild($result); | ||||
|       ->appendChild($result) | ||||
|       ->appendChild($footer); | ||||
|  | ||||
|     return $view; | ||||
|   } | ||||
| @@ -123,7 +149,6 @@ final class PhabricatorDashboardRenderingEngine extends Phobject { | ||||
|       ->setTag('a') | ||||
|       ->setHref($create_uri) | ||||
|       ->setWorkflow(true) | ||||
|       ->setColor(PHUIButtonView::GREY) | ||||
|       ->setText(pht('Create Panel')) | ||||
|       ->addClass(PHUI::MARGIN_MEDIUM); | ||||
|  | ||||
| @@ -131,7 +156,6 @@ final class PhabricatorDashboardRenderingEngine extends Phobject { | ||||
|       ->setTag('a') | ||||
|       ->setHref($add_uri) | ||||
|       ->setWorkflow(true) | ||||
|       ->setColor(PHUIButtonView::GREY) | ||||
|       ->setText(pht('Add Existing Panel')) | ||||
|       ->addClass(PHUI::MARGIN_MEDIUM); | ||||
|  | ||||
|   | ||||
| @@ -101,20 +101,6 @@ final class PhabricatorDashboardSearchEngine | ||||
|     $dashboards = mpull($dashboards, null, 'getPHID'); | ||||
|     $viewer = $this->requireViewer(); | ||||
|  | ||||
|     if ($dashboards) { | ||||
|       $installs = id(new PhabricatorDashboardInstall()) | ||||
|         ->loadAllWhere( | ||||
|           'objectPHID IN (%Ls) AND dashboardPHID IN (%Ls)', | ||||
|           array( | ||||
|             PhabricatorHomeApplication::DASHBOARD_DEFAULT, | ||||
|             $viewer->getPHID(), | ||||
|           ), | ||||
|           array_keys($dashboards)); | ||||
|       $installs = mpull($installs, null, 'getDashboardPHID'); | ||||
|     } else { | ||||
|       $installs = array(); | ||||
|     } | ||||
|  | ||||
|     $proj_phids = array(); | ||||
|     foreach ($dashboards as $dashboard) { | ||||
|       foreach ($dashboard->getProjectPHIDs() as $project_phid) { | ||||
| @@ -127,37 +113,18 @@ final class PhabricatorDashboardSearchEngine | ||||
|       ->withPHIDs($proj_phids) | ||||
|       ->execute(); | ||||
|  | ||||
|     $list = new PHUIObjectItemListView(); | ||||
|     $list->setUser($viewer); | ||||
|     $list->initBehavior('phabricator-tooltips', array()); | ||||
|     $list->requireResource('aphront-tooltip-css'); | ||||
|     $list = id(new PHUIObjectItemListView()) | ||||
|       ->setUser($viewer); | ||||
|  | ||||
|     foreach ($dashboards as $dashboard_phid => $dashboard) { | ||||
|       $id = $dashboard->getID(); | ||||
|  | ||||
|       $item = id(new PHUIObjectItemView()) | ||||
|         ->setObjectName(pht('Dashboard %d', $id)) | ||||
|         ->setUser($viewer) | ||||
|         ->setHeader($dashboard->getName()) | ||||
|         ->setHref($this->getApplicationURI("view/{$id}/")) | ||||
|         ->setObject($dashboard); | ||||
|  | ||||
|       if (isset($installs[$dashboard_phid])) { | ||||
|         $install = $installs[$dashboard_phid]; | ||||
|         if ($install->getObjectPHID() == $viewer->getPHID()) { | ||||
|           $attrs = array( | ||||
|             'tip' => pht( | ||||
|               'This dashboard is installed to your personal homepage.'), | ||||
|           ); | ||||
|           $item->addIcon('fa-user', pht('Installed'), $attrs); | ||||
|         } else { | ||||
|           $attrs = array( | ||||
|             'tip' => pht( | ||||
|               'This dashboard is the default homepage for all users.'), | ||||
|           ); | ||||
|           $item->addIcon('fa-globe', pht('Installed'), $attrs); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       $project_handles = array_select_keys( | ||||
|         $proj_handles, | ||||
|         $dashboard->getProjectPHIDs()); | ||||
| @@ -173,25 +140,11 @@ final class PhabricatorDashboardSearchEngine | ||||
|         $item->setDisabled(true); | ||||
|       } | ||||
|  | ||||
|       $can_edit = PhabricatorPolicyFilter::hasCapability( | ||||
|         $viewer, | ||||
|         $dashboard, | ||||
|         PhabricatorPolicyCapability::CAN_EDIT); | ||||
|  | ||||
|       $href_view = $this->getApplicationURI("manage/{$id}/"); | ||||
|       $item->addAction( | ||||
|         id(new PHUIListItemView()) | ||||
|           ->setName(pht('Manage')) | ||||
|           ->setIcon('fa-th') | ||||
|           ->setHref($href_view)); | ||||
|  | ||||
|       $href_edit = $this->getApplicationURI("edit/{$id}/"); | ||||
|       $item->addAction( | ||||
|         id(new PHUIListItemView()) | ||||
|           ->setName(pht('Edit')) | ||||
|           ->setIcon('fa-pencil') | ||||
|           ->setHref($href_edit) | ||||
|           ->setDisabled(!$can_edit)); | ||||
|       $icon = id(new PHUIIconView()) | ||||
|         ->setIcon($dashboard->getIcon()) | ||||
|         ->setBackground('bg-dark'); | ||||
|       $item->setImageIcon($icon); | ||||
|       $item->setEpoch($dashboard->getDateModified()); | ||||
|  | ||||
|       $list->addItem($item); | ||||
|     } | ||||
|   | ||||
| @@ -56,11 +56,11 @@ final class PhabricatorDashboardTransaction | ||||
|       case self::TYPE_STATUS: | ||||
|         if ($new == PhabricatorDashboard::STATUS_ACTIVE) { | ||||
|           return pht( | ||||
|             '%s activated this dashboard', | ||||
|             '%s activated this dashboard.', | ||||
|             $author_link); | ||||
|         } else { | ||||
|           return pht( | ||||
|             '%s archived this dashboard', | ||||
|             '%s archived this dashboard.', | ||||
|             $author_link); | ||||
|         } | ||||
|         break; | ||||
|   | ||||
| @@ -35,63 +35,88 @@ | ||||
| } | ||||
|  | ||||
| .device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up | ||||
| .aphront-multi-column-column-outer.half { | ||||
|   width: 50%; | ||||
|   .aphront-multi-column-column-outer.half { | ||||
|     width: 50%; | ||||
| } | ||||
|  | ||||
| .device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up | ||||
| .aphront-multi-column-column-outer.third { | ||||
|   width: 33.34%; | ||||
|   .aphront-multi-column-column-outer.third { | ||||
|     width: 33.34%; | ||||
| } | ||||
|  | ||||
| .device-desktop .aphront-multi-column-fluid .aphront-multi-column-2-up | ||||
| .aphront-multi-column-column-outer.thirds { | ||||
|   width: 66.66%; | ||||
|   .aphront-multi-column-column-outer.thirds { | ||||
|     width: 66.66%; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column-outer.grippable | ||||
| .aphront-multi-column-column .dashboard-pane { | ||||
| .grippable .aphront-multi-column-column .dashboard-pane .phui-object-box { | ||||
|   cursor: move; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column .drag-ghost { | ||||
| .grippable .aphront-multi-column-column .dashboard-pane .phui-object-box:hover { | ||||
|   box-shadow: {$dropshadow}; | ||||
| } | ||||
|  | ||||
| .grippable .aphront-multi-column-column .dashboard-pane .phui-object-box:hover | ||||
|   .phui-object-box { | ||||
|     box-shadow: none; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid .aphront-multi-column-column .drag-ghost { | ||||
|   list-style-type: none; | ||||
|   margin: 16px; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column | ||||
| .dashboard-panel-placeholder { | ||||
|   display: none; | ||||
| .aphront-multi-column-fluid .aphront-multi-column-column | ||||
|   .dashboard-panel-placeholder { | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column.dashboard-column-empty | ||||
| .dashboard-panel-placeholder { | ||||
|   display: block; | ||||
|   padding: 20px; | ||||
|   margin: 0 0 12px 0; | ||||
|   text-decoration: none; | ||||
|   border: 1px {$greyborder} dashed; | ||||
|   color: {$greytext}; | ||||
| .aphront-multi-column-fluid .aphront-multi-column-column.dashboard-column-empty | ||||
|   .dashboard-panel-placeholder { | ||||
|     display: block; | ||||
|     padding: 20px; | ||||
|     margin: 0 0 12px 0; | ||||
|     text-decoration: none; | ||||
|     border: 1px {$greyborder} dashed; | ||||
|     color: {$greytext}; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column.drag-target-list | ||||
| .dashboard-panel-placeholder { | ||||
|   display: none; | ||||
| .aphront-multi-column-fluid .aphront-multi-column-column.drag-target-list | ||||
|   .dashboard-panel-placeholder { | ||||
|     display: none; | ||||
| } | ||||
|  | ||||
| .aphront-multi-column-fluid | ||||
| .aphront-multi-column-column-outer | ||||
| .aphront-multi-column-column .phui-info-view { | ||||
|   margin: 0; | ||||
| .aphront-multi-column-fluid .aphront-multi-column-column-outer | ||||
|   .aphront-multi-column-column .phui-info-view { | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| .dashboard-preview-box { | ||||
|   border: 1px solid {$lightblueborder}; | ||||
|   border-radius: 3px; | ||||
|   background-color: rgba(255,255,255,.33); | ||||
|   margin: -16px -16px 16px; | ||||
| } | ||||
|  | ||||
| .phui-info-view + .dashboard-preview-box { | ||||
|   margin-top: 0; | ||||
| } | ||||
|  | ||||
| .drag-frame .phui-object-box { | ||||
|   box-shadow: {$dropshadow}; | ||||
| } | ||||
|  | ||||
| .drag-frame .phui-object-box .phui-object-box { | ||||
|   box-shadow: none; | ||||
| } | ||||
|  | ||||
| /*** Footer *******************************************************************/ | ||||
|  | ||||
| .dashboard-footer-view { | ||||
|   background-color: {$page.sidenav}; | ||||
|   padding: 8px 16px; | ||||
|   border-radius: 3px; | ||||
| } | ||||
|  | ||||
| .dashboard-footer-name { | ||||
|   color: {$darkbluetext}; | ||||
|   font-weight: bold; | ||||
|   -webkit-font-smoothing: antialiased; | ||||
| } | ||||
|   | ||||
| @@ -67,3 +67,7 @@ | ||||
| .device-phone .application-search-pager { | ||||
|   margin: 12px; | ||||
| } | ||||
|  | ||||
| .application-search-view .phui-oi-list-view.phui-oi-list-big { | ||||
|   margin-top: 12px; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Chad Little
					Chad Little