@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.

Dashboards - add ability to install dashboard as home

Summary:
See title. Adds PhabricatorDashboardInstall data object which scopes installs to objectPHID + applicationClass. This is because we already have a collision for user home pages and user profiles. Assume only one dashboard per objectPHID + applicationClass though at the database level.

Fixes T5076.

Test Plan: From dashboard view, installed a dashboard - success! Went back to dashboard view and uninstalled it!

Reviewers: chad, epriestley

Reviewed By: epriestley

Subscribers: epriestley, Korvin

Maniphest Tasks: T5076

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

+380 -15
+10
resources/sql/autopatches/20140519.dashboardinstall.sql
··· 1 + CREATE TABLE {$NAMESPACE}_dashboard.dashboard_install ( 2 + id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 + installerPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 4 + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 5 + applicationClass VARCHAR(64) NOT NULL COLLATE utf8_bin, 6 + dashboardPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 7 + dateCreated INT UNSIGNED NOT NULL, 8 + dateModified INT UNSIGNED NOT NULL, 9 + UNIQUE KEY (objectPHID, applicationClass) 10 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+6
src/__phutil_library_map__.php
··· 1463 1463 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', 1464 1464 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 1465 1465 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', 1466 + 'PhabricatorDashboardInstall' => 'applications/dashboard/storage/PhabricatorDashboardInstall.php', 1467 + 'PhabricatorDashboardInstallController' => 'applications/dashboard/controller/PhabricatorDashboardInstallController.php', 1466 1468 'PhabricatorDashboardLayoutConfig' => 'applications/dashboard/layoutconfig/PhabricatorDashboardLayoutConfig.php', 1467 1469 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 1468 1470 'PhabricatorDashboardMovePanelController' => 'applications/dashboard/controller/PhabricatorDashboardMovePanelController.php', ··· 1493 1495 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 1494 1496 'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php', 1495 1497 'PhabricatorDashboardTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardTransactionQuery.php', 1498 + 'PhabricatorDashboardUninstallController' => 'applications/dashboard/controller/PhabricatorDashboardUninstallController.php', 1496 1499 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php', 1497 1500 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 1498 1501 'PhabricatorDebugController' => 'applications/system/controller/PhabricatorDebugController.php', ··· 4247 4250 'PhabricatorDashboardController' => 'PhabricatorController', 4248 4251 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 4249 4252 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', 4253 + 'PhabricatorDashboardInstall' => 'PhabricatorDashboardDAO', 4254 + 'PhabricatorDashboardInstallController' => 'PhabricatorDashboardController', 4250 4255 'PhabricatorDashboardListController' => 'PhabricatorDashboardController', 4251 4256 'PhabricatorDashboardMovePanelController' => 'PhabricatorDashboardController', 4252 4257 'PhabricatorDashboardPHIDTypeDashboard' => 'PhabricatorPHIDType', ··· 4285 4290 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 4286 4291 'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 4287 4292 'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 4293 + 'PhabricatorDashboardUninstallController' => 'PhabricatorDashboardController', 4288 4294 'PhabricatorDashboardViewController' => 'PhabricatorDashboardController', 4289 4295 'PhabricatorDataNotAttachedException' => 'Exception', 4290 4296 'PhabricatorDebugController' => 'PhabricatorController',
+2
src/applications/dashboard/application/PhabricatorApplicationDashboard.php
··· 24 24 'arrange/(?P<id>\d+)/' => 'PhabricatorDashboardArrangeController', 25 25 'create/' => 'PhabricatorDashboardEditController', 26 26 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController', 27 + 'install/(?P<id>\d+)/' => 'PhabricatorDashboardInstallController', 28 + 'uninstall/(?P<id>\d+)/' => 'PhabricatorDashboardUninstallController', 27 29 'addpanel/(?P<id>\d+)/' => 'PhabricatorDashboardAddPanelController', 28 30 'movepanel/(?P<id>\d+)/' => 'PhabricatorDashboardMovePanelController', 29 31 'removepanel/(?P<id>\d+)/'
+139
src/applications/dashboard/controller/PhabricatorDashboardInstallController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardInstallController 4 + extends PhabricatorDashboardController { 5 + 6 + private $id; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->id = idx($data, 'id'); 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + $dashboard = id(new PhabricatorDashboardQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($this->id)) 19 + ->executeOne(); 20 + if (!$dashboard) { 21 + return new Aphront404Response(); 22 + } 23 + $dashboard_phid = $dashboard->getPHID(); 24 + 25 + $object_phid = $request->getStr('objectPHID', $viewer->getPHID()); 26 + $object = id(new PhabricatorObjectQuery()) 27 + ->setViewer($viewer) 28 + ->requireCapabilities( 29 + array( 30 + PhabricatorPolicyCapability::CAN_VIEW, 31 + PhabricatorPolicyCapability::CAN_EDIT, 32 + )) 33 + ->withPHIDs(array($object_phid)) 34 + ->executeOne(); 35 + if (!$object) { 36 + return new Aphront404Response(); 37 + } 38 + 39 + $installer_phid = $viewer->getPHID(); 40 + $application_class = $request->getStr( 41 + 'applicationClass', 42 + 'PhabricatorApplicationHome'); 43 + 44 + $handles = $this->loadHandles(array( 45 + $object_phid, 46 + $installer_phid)); 47 + 48 + if ($request->isFormPost()) { 49 + $dashboard_install = id(new PhabricatorDashboardInstall()) 50 + ->loadOneWhere( 51 + 'objectPHID = %s AND applicationClass = %s', 52 + $object_phid, 53 + $application_class); 54 + if (!$dashboard_install) { 55 + $dashboard_install = id(new PhabricatorDashboardInstall()) 56 + ->setObjectPHID($object_phid) 57 + ->setApplicationClass($application_class); 58 + } 59 + $dashboard_install 60 + ->setInstallerPHID($installer_phid) 61 + ->setDashboardPHID($dashboard_phid) 62 + ->save(); 63 + return id(new AphrontRedirectResponse()) 64 + ->setURI($this->getRedirectURI($application_class, $object_phid)); 65 + } 66 + 67 + $body = $this->getBodyContent( 68 + $application_class, 69 + $object_phid, 70 + $installer_phid); 71 + 72 + $form = id(new AphrontFormView()) 73 + ->setUser($viewer) 74 + ->appendChild($body); 75 + 76 + return $this->newDialog() 77 + ->setTitle(pht('Install Dashboard')) 78 + ->appendChild($form->buildLayoutView()) 79 + ->addCancelButton($this->getCancelURI( 80 + $application_class, $object_phid)) 81 + ->addSubmitButton(pht('Install Dashboard')); 82 + } 83 + 84 + private function getBodyContent( 85 + $application_class, 86 + $object_phid, 87 + $installer_phid) { 88 + 89 + $body = array(); 90 + switch ($application_class) { 91 + case 'PhabricatorApplicationHome': 92 + if ($installer_phid == $object_phid) { 93 + $body[] = phutil_tag( 94 + 'p', 95 + array(), 96 + pht( 97 + 'Are you sure you want to install this dashboard as your '. 98 + 'home page?')); 99 + $body[] = phutil_tag( 100 + 'p', 101 + array(), 102 + pht( 103 + 'You will be re-directed to your spiffy new home page if you '. 104 + 'choose to install this dashboard.')); 105 + } else { 106 + $body[] = phutil_tag( 107 + 'p', 108 + array(), 109 + pht( 110 + 'Are you sure you want to install this dashboard as the home '. 111 + 'page for %s?', 112 + $this->getHandle($object_phid)->getName())); 113 + } 114 + break; 115 + } 116 + return $body; 117 + } 118 + 119 + private function getCancelURI($application_class, $object_phid) { 120 + $uri = null; 121 + switch ($application_class) { 122 + case 'PhabricatorApplicationHome': 123 + $uri = '/dashboard/view/'.$this->id.'/'; 124 + break; 125 + } 126 + return $uri; 127 + } 128 + 129 + private function getRedirectURI($application_class, $object_phid) { 130 + $uri = null; 131 + switch ($application_class) { 132 + case 'PhabricatorApplicationHome': 133 + $uri = '/'; 134 + break; 135 + } 136 + return $uri; 137 + } 138 + 139 + }
+136
src/applications/dashboard/controller/PhabricatorDashboardUninstallController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardUninstallController 4 + extends PhabricatorDashboardController { 5 + 6 + private $id; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->id = idx($data, 'id'); 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + $dashboard = id(new PhabricatorDashboardQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($this->id)) 19 + ->executeOne(); 20 + if (!$dashboard) { 21 + return new Aphront404Response(); 22 + } 23 + $dashboard_phid = $dashboard->getPHID(); 24 + 25 + $object_phid = $request->getStr('objectPHID', $viewer->getPHID()); 26 + $object = id(new PhabricatorObjectQuery()) 27 + ->setViewer($viewer) 28 + ->requireCapabilities( 29 + array( 30 + PhabricatorPolicyCapability::CAN_VIEW, 31 + PhabricatorPolicyCapability::CAN_EDIT, 32 + )) 33 + ->withPHIDs(array($object_phid)) 34 + ->executeOne(); 35 + if (!$object) { 36 + return new Aphront404Response(); 37 + } 38 + 39 + $application_class = $request->getStr( 40 + 'applicationClass', 41 + 'PhabricatorApplicationHome'); 42 + 43 + $dashboard_install = id(new PhabricatorDashboardInstall()) 44 + ->loadOneWhere( 45 + 'objectPHID = %s AND applicationClass = %s', 46 + $object_phid, 47 + $application_class); 48 + if (!$dashboard_install) { 49 + return new Aphront404Response(); 50 + } 51 + if ($dashboard_install->getDashboardPHID() != $dashboard_phid) { 52 + return new Aphront404Response(); 53 + } 54 + 55 + $installer_phid = $viewer->getPHID(); 56 + $handles = $this->loadHandles(array($object_phid, $installer_phid)); 57 + 58 + if ($request->isFormPost()) { 59 + $dashboard_install->delete(); 60 + return id(new AphrontRedirectResponse()) 61 + ->setURI($this->getRedirectURI($application_class, $object_phid)); 62 + } 63 + 64 + $body = $this->getBodyContent( 65 + $application_class, 66 + $object_phid, 67 + $installer_phid); 68 + 69 + $form = id(new AphrontFormView()) 70 + ->setUser($viewer) 71 + ->appendChild($body); 72 + 73 + return $this->newDialog() 74 + ->setTitle(pht('Uninstall Dashboard')) 75 + ->appendChild($form->buildLayoutView()) 76 + ->addCancelButton($this->getCancelURI( 77 + $application_class, $object_phid)) 78 + ->addSubmitButton(pht('Uninstall Dashboard')); 79 + } 80 + 81 + private function getBodyContent( 82 + $application_class, 83 + $object_phid, 84 + $installer_phid) { 85 + 86 + $body = array(); 87 + switch ($application_class) { 88 + case 'PhabricatorApplicationHome': 89 + if ($installer_phid == $object_phid) { 90 + $body[] = phutil_tag( 91 + 'p', 92 + array(), 93 + pht( 94 + 'Are you sure you want to uninstall this dashboard as your '. 95 + 'home page?')); 96 + $body[] = phutil_tag( 97 + 'p', 98 + array(), 99 + pht( 100 + 'You will be re-directed to your bland, default home page if '. 101 + 'you choose to uninstall this dashboard.')); 102 + } else { 103 + $body[] = phutil_tag( 104 + 'p', 105 + array(), 106 + pht( 107 + 'Are you sure you want to uninstall this dashboard as the home '. 108 + 'page for %s?', 109 + $this->getHandle($object_phid)->getName())); 110 + } 111 + break; 112 + } 113 + return $body; 114 + } 115 + 116 + private function getCancelURI($application_class, $object_phid) { 117 + $uri = null; 118 + switch ($application_class) { 119 + case 'PhabricatorApplicationHome': 120 + $uri = '/dashboard/view/'.$this->id.'/'; 121 + break; 122 + } 123 + return $uri; 124 + } 125 + 126 + private function getRedirectURI($application_class, $object_phid) { 127 + $uri = null; 128 + switch ($application_class) { 129 + case 'PhabricatorApplicationHome': 130 + $uri = '/'; 131 + break; 132 + } 133 + return $uri; 134 + } 135 + 136 + }
+20
src/applications/dashboard/controller/PhabricatorDashboardViewController.php
··· 92 92 ->setDisabled(!$can_edit) 93 93 ->setWorkflow(!$can_edit)); 94 94 95 + $installed_dashboard = id(new PhabricatorDashboardInstall()) 96 + ->loadOneWhere( 97 + 'objectPHID = %s AND applicationClass = %s', 98 + $viewer->getPHID(), 99 + 'PhabricatorApplicationHome'); 100 + if ($installed_dashboard && 101 + $installed_dashboard->getDashboardPHID() == $dashboard->getPHID()) { 102 + $title_install = pht('Uninstall Dashboard'); 103 + $href_install = "uninstall/{$id}/"; 104 + } else { 105 + $title_install = pht('Install Dashboard'); 106 + $href_install = "install/{$id}/"; 107 + } 108 + $actions->addAction( 109 + id(new PhabricatorActionView()) 110 + ->setName($title_install) 111 + ->setIcon('fa-wrench') 112 + ->setHref($this->getApplicationURI($href_install)) 113 + ->setWorkflow(true)); 114 + 95 115 $actions->addAction( 96 116 id(new PhabricatorActionView()) 97 117 ->setName(pht('Add Panel'))
+38
src/applications/dashboard/storage/PhabricatorDashboardInstall.php
··· 1 + <?php 2 + 3 + /** 4 + * An install of a dashboard. Examples might be 5 + * - the home page for a user 6 + * - the profile page for a user 7 + * - the profile page for a project 8 + */ 9 + final class PhabricatorDashboardInstall 10 + extends PhabricatorDashboardDAO { 11 + 12 + protected $installerPHID; 13 + protected $objectPHID; 14 + protected $applicationClass; 15 + protected $dashboardPHID; 16 + 17 + public static function getDashboard( 18 + PhabricatorUser $viewer, 19 + $object_phid, 20 + $application_class) { 21 + 22 + $dashboard = null; 23 + $dashboard_install = id(new PhabricatorDashboardInstall()) 24 + ->loadOneWhere( 25 + 'objectPHID = %s AND applicationClass = %s', 26 + $object_phid, 27 + $application_class); 28 + if ($dashboard_install) { 29 + $dashboard = id(new PhabricatorDashboardQuery()) 30 + ->setViewer($viewer) 31 + ->withPHIDs(array($dashboard_install->getDashboardPHID())) 32 + ->needPanels(true) 33 + ->executeOne(); 34 + } 35 + 36 + return $dashboard; 37 + } 38 + }
+29 -15
src/applications/home/controller/PhabricatorHomeMainController.php
··· 20 20 if ($this->filter == 'jump') { 21 21 return $this->buildJumpResponse(); 22 22 } 23 + $nav = $this->buildNav(); 24 + 25 + $dashboard = PhabricatorDashboardInstall::getDashboard( 26 + $user, 27 + $user->getPHID(), 28 + get_class($this->getCurrentApplication())); 29 + if ($dashboard) { 30 + $rendered_dashboard = id(new PhabricatorDashboardRenderingEngine()) 31 + ->setViewer($user) 32 + ->setDashboard($dashboard) 33 + ->renderDashboard(); 34 + $nav->appendChild($rendered_dashboard); 35 + } else { 36 + $project_query = new PhabricatorProjectQuery(); 37 + $project_query->setViewer($user); 38 + $project_query->withMemberPHIDs(array($user->getPHID())); 39 + $projects = $project_query->execute(); 23 40 24 - $nav = $this->buildNav(); 41 + $nav = $this->buildMainResponse($nav, $projects); 42 + } 25 43 26 - $project_query = new PhabricatorProjectQuery(); 27 - $project_query->setViewer($user); 28 - $project_query->withMemberPHIDs(array($user->getPHID())); 29 - $projects = $project_query->execute(); 44 + $nav->appendChild(id(new PhabricatorGlobalUploadTargetView()) 45 + ->setUser($user)); 30 46 31 - return $this->buildMainResponse($nav, $projects); 47 + return $this->buildApplicationPage( 48 + $nav, 49 + array( 50 + 'title' => 'Phabricator', 51 + 'device' => true, 52 + )); 32 53 } 33 54 34 55 private function buildMainResponse($nav, array $projects) { ··· 91 112 $this->minipanels, 92 113 ); 93 114 94 - $user = $this->getRequest()->getUser(); 95 115 $nav->appendChild($content); 96 - $nav->appendChild(id(new PhabricatorGlobalUploadTargetView()) 97 - ->setUser($user)); 98 116 99 - return $this->buildApplicationPage( 100 - $nav, 101 - array( 102 - 'title' => 'Phabricator', 103 - 'device' => true, 104 - )); 117 + return $nav; 118 + 105 119 } 106 120 107 121 private function buildJumpResponse() {