@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

Add edit/view plumbing for dashboards and panels

Summary: Ref T3583. This doesn't add any dashboard/panel-specific code beyond headers/titles/buttons/etc., but allows you to create and view dashboards and panel skeletons.

Test Plan: See screenshots.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3583

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

+1040 -13
+21
resources/sql/autopatches/20140130.dash.3.boardxaction.sql
··· 1 + CREATE TABLE {$NAMESPACE}_dashboard.dashboard_transaction ( 2 + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 3 + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, 4 + authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 5 + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 6 + viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 7 + editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 8 + commentPHID VARCHAR(64) COLLATE utf8_bin, 9 + commentVersion INT UNSIGNED NOT NULL, 10 + transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin, 11 + oldValue LONGTEXT NOT NULL COLLATE utf8_bin, 12 + newValue LONGTEXT NOT NULL COLLATE utf8_bin, 13 + contentSource LONGTEXT NOT NULL COLLATE utf8_bin, 14 + metadata LONGTEXT NOT NULL COLLATE utf8_bin, 15 + dateCreated INT UNSIGNED NOT NULL, 16 + dateModified INT UNSIGNED NOT NULL, 17 + 18 + UNIQUE KEY `key_phid` (phid), 19 + KEY `key_object` (objectPHID) 20 + 21 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+21
resources/sql/autopatches/20140130.dash.4.panelxaction.sql
··· 1 + CREATE TABLE {$NAMESPACE}_dashboard.dashboard_paneltransaction ( 2 + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, 3 + phid VARCHAR(64) NOT NULL COLLATE utf8_bin, 4 + authorPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 5 + objectPHID VARCHAR(64) NOT NULL COLLATE utf8_bin, 6 + viewPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 7 + editPolicy VARCHAR(64) NOT NULL COLLATE utf8_bin, 8 + commentPHID VARCHAR(64) COLLATE utf8_bin, 9 + commentVersion INT UNSIGNED NOT NULL, 10 + transactionType VARCHAR(32) NOT NULL COLLATE utf8_bin, 11 + oldValue LONGTEXT NOT NULL COLLATE utf8_bin, 12 + newValue LONGTEXT NOT NULL COLLATE utf8_bin, 13 + contentSource LONGTEXT NOT NULL COLLATE utf8_bin, 14 + metadata LONGTEXT NOT NULL COLLATE utf8_bin, 15 + dateCreated INT UNSIGNED NOT NULL, 16 + dateModified INT UNSIGNED NOT NULL, 17 + 18 + UNIQUE KEY `key_phid` (phid), 19 + KEY `key_object` (objectPHID) 20 + 21 + ) ENGINE=InnoDB, COLLATE utf8_general_ci;
+25 -1
src/__phutil_library_map__.php
··· 1390 1390 'PhabricatorDashboard' => 'applications/dashboard/storage/PhabricatorDashboard.php', 1391 1391 'PhabricatorDashboardController' => 'applications/dashboard/controller/PhabricatorDashboardController.php', 1392 1392 'PhabricatorDashboardDAO' => 'applications/dashboard/storage/PhabricatorDashboardDAO.php', 1393 + 'PhabricatorDashboardEditController' => 'applications/dashboard/controller/PhabricatorDashboardEditController.php', 1393 1394 'PhabricatorDashboardListController' => 'applications/dashboard/controller/PhabricatorDashboardListController.php', 1394 1395 'PhabricatorDashboardPHIDTypeDashboard' => 'applications/dashboard/phid/PhabricatorDashboardPHIDTypeDashboard.php', 1395 1396 'PhabricatorDashboardPHIDTypePanel' => 'applications/dashboard/phid/PhabricatorDashboardPHIDTypePanel.php', 1396 1397 'PhabricatorDashboardPanel' => 'applications/dashboard/storage/PhabricatorDashboardPanel.php', 1398 + 'PhabricatorDashboardPanelEditController' => 'applications/dashboard/controller/PhabricatorDashboardPanelEditController.php', 1397 1399 'PhabricatorDashboardPanelListController' => 'applications/dashboard/controller/PhabricatorDashboardPanelListController.php', 1398 1400 'PhabricatorDashboardPanelQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelQuery.php', 1399 1401 'PhabricatorDashboardPanelSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardPanelSearchEngine.php', 1402 + 'PhabricatorDashboardPanelTransaction' => 'applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php', 1403 + 'PhabricatorDashboardPanelTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php', 1404 + 'PhabricatorDashboardPanelTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php', 1405 + 'PhabricatorDashboardPanelViewController' => 'applications/dashboard/controller/PhabricatorDashboardPanelViewController.php', 1400 1406 'PhabricatorDashboardQuery' => 'applications/dashboard/query/PhabricatorDashboardQuery.php', 1401 1407 'PhabricatorDashboardSearchEngine' => 'applications/dashboard/query/PhabricatorDashboardSearchEngine.php', 1408 + 'PhabricatorDashboardTransaction' => 'applications/dashboard/storage/PhabricatorDashboardTransaction.php', 1409 + 'PhabricatorDashboardTransactionEditor' => 'applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php', 1410 + 'PhabricatorDashboardTransactionQuery' => 'applications/dashboard/query/PhabricatorDashboardTransactionQuery.php', 1411 + 'PhabricatorDashboardViewController' => 'applications/dashboard/controller/PhabricatorDashboardViewController.php', 1402 1412 'PhabricatorDataNotAttachedException' => 'infrastructure/storage/lisk/PhabricatorDataNotAttachedException.php', 1403 1413 'PhabricatorDebugController' => 'applications/system/PhabricatorDebugController.php', 1404 1414 'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/PhabricatorDefaultFileStorageEngineSelector.php', ··· 4046 4056 ), 4047 4057 'PhabricatorDashboardController' => 'PhabricatorController', 4048 4058 'PhabricatorDashboardDAO' => 'PhabricatorLiskDAO', 4059 + 'PhabricatorDashboardEditController' => 'PhabricatorDashboardController', 4049 4060 'PhabricatorDashboardListController' => 4050 4061 array( 4051 4062 0 => 'PhabricatorDashboardController', ··· 4053 4064 ), 4054 4065 'PhabricatorDashboardPHIDTypeDashboard' => 'PhabricatorPHIDType', 4055 4066 'PhabricatorDashboardPHIDTypePanel' => 'PhabricatorPHIDType', 4056 - 'PhabricatorDashboardPanel' => 'PhabricatorDashboardDAO', 4067 + 'PhabricatorDashboardPanel' => 4068 + array( 4069 + 0 => 'PhabricatorDashboardDAO', 4070 + 1 => 'PhabricatorPolicyInterface', 4071 + ), 4072 + 'PhabricatorDashboardPanelEditController' => 'PhabricatorDashboardController', 4057 4073 'PhabricatorDashboardPanelListController' => 4058 4074 array( 4059 4075 0 => 'PhabricatorDashboardController', ··· 4061 4077 ), 4062 4078 'PhabricatorDashboardPanelQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4063 4079 'PhabricatorDashboardPanelSearchEngine' => 'PhabricatorApplicationSearchEngine', 4080 + 'PhabricatorDashboardPanelTransaction' => 'PhabricatorApplicationTransaction', 4081 + 'PhabricatorDashboardPanelTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 4082 + 'PhabricatorDashboardPanelTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 4083 + 'PhabricatorDashboardPanelViewController' => 'PhabricatorDashboardController', 4064 4084 'PhabricatorDashboardQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 4065 4085 'PhabricatorDashboardSearchEngine' => 'PhabricatorApplicationSearchEngine', 4086 + 'PhabricatorDashboardTransaction' => 'PhabricatorApplicationTransaction', 4087 + 'PhabricatorDashboardTransactionEditor' => 'PhabricatorApplicationTransactionEditor', 4088 + 'PhabricatorDashboardTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 4089 + 'PhabricatorDashboardViewController' => 'PhabricatorDashboardController', 4066 4090 'PhabricatorDataNotAttachedException' => 'Exception', 4067 4091 'PhabricatorDebugController' => 'PhabricatorController', 4068 4092 'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector',
+6 -1
src/applications/dashboard/application/PhabricatorApplicationDashboard.php
··· 11 11 } 12 12 13 13 public function getIconName() { 14 - return 'dashboard'; 14 + return 'fancyhome'; 15 15 } 16 16 17 17 public function getRoutes() { ··· 21 21 '(?:query/(?P<queryKey>[^/]+)/)?' 22 22 => 'PhabricatorDashboardListController', 23 23 'view/(?P<id>\d+)/' => 'PhabricatorDashboardViewController', 24 + 'create/' => 'PhabricatorDashboardEditController', 25 + 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardEditController', 26 + 24 27 'panel/' => array( 25 28 '(?:query/(?P<queryKey>[^/]+)/)?' 26 29 => 'PhabricatorDashboardPanelListController', 30 + 'create/' => 'PhabricatorDashboardPanelEditController', 31 + 'edit/(?:(?P<id>\d+)/)?' => 'PhabricatorDashboardPanelEditController', 27 32 ), 28 33 ), 29 34 );
+119
src/applications/dashboard/controller/PhabricatorDashboardEditController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardEditController 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 + if ($this->id) { 17 + $dashboard = id(new PhabricatorDashboardQuery()) 18 + ->setViewer($viewer) 19 + ->withIDs(array($this->id)) 20 + ->requireCapabilities( 21 + array( 22 + PhabricatorPolicyCapability::CAN_VIEW, 23 + PhabricatorPolicyCapability::CAN_EDIT, 24 + )) 25 + ->executeOne(); 26 + if (!$dashboard) { 27 + return new Aphront404Response(); 28 + } 29 + 30 + $is_new = false; 31 + } else { 32 + $dashboard = PhabricatorDashboard::initializeNewDashboard($viewer); 33 + 34 + $is_new = true; 35 + } 36 + 37 + $crumbs = $this->buildApplicationCrumbs(); 38 + 39 + if ($is_new) { 40 + $title = pht('Create Dashboard'); 41 + $header = pht('Create Dashboard'); 42 + $button = pht('Create Dashboard'); 43 + $cancel_uri = $this->getApplicationURI(); 44 + 45 + $crumbs->addTextCrumb('Create Dashboard'); 46 + } else { 47 + $id = $dashboard->getID(); 48 + $cancel_uri = $this->getApplicationURI('view/'.$id.'/'); 49 + 50 + $title = pht('Edit Dashboard %d', $dashboard->getID()); 51 + $header = pht('Edit Dashboard "%s"', $dashboard->getName()); 52 + $button = pht('Save Changes'); 53 + 54 + $crumbs->addTextCrumb(pht('Dashboard %d', $id), $cancel_uri); 55 + $crumbs->addTextCrumb(pht('Edit')); 56 + } 57 + 58 + $v_name = $dashboard->getName(); 59 + $e_name = true; 60 + 61 + $validation_exception = null; 62 + if ($request->isFormPost()) { 63 + $v_name = $request->getStr('name'); 64 + 65 + $xactions = array(); 66 + 67 + $type_name = PhabricatorDashboardTransaction::TYPE_NAME; 68 + 69 + $xactions[] = id(new PhabricatorDashboardTransaction()) 70 + ->setTransactionType($type_name) 71 + ->setNewValue($v_name); 72 + 73 + try { 74 + $editor = id(new PhabricatorDashboardTransactionEditor()) 75 + ->setActor($viewer) 76 + ->setContinueOnNoEffect(true) 77 + ->setContentSourceFromRequest($request) 78 + ->applyTransactions($dashboard, $xactions); 79 + 80 + return id(new AphrontRedirectResponse()) 81 + ->setURI($this->getApplicationURI('view/'.$dashboard->getID().'/')); 82 + } catch (PhabricatorApplicationTransactionValidationException $ex) { 83 + $validation_exception = $ex; 84 + 85 + $e_name = $validation_exception->getShortMessage($type_name); 86 + } 87 + } 88 + 89 + $form = id(new AphrontFormView()) 90 + ->setUser($viewer) 91 + ->appendChild( 92 + id(new AphrontFormTextControl()) 93 + ->setLabel(pht('Name')) 94 + ->setName('name') 95 + ->setValue($v_name) 96 + ->setError($e_name)) 97 + ->appendChild( 98 + id(new AphrontFormSubmitControl()) 99 + ->setValue($button) 100 + ->addCancelButton($cancel_uri)); 101 + 102 + 103 + $box = id(new PHUIObjectBoxView()) 104 + ->setHeaderText($header) 105 + ->setForm($form) 106 + ->setValidationException($validation_exception); 107 + 108 + return $this->buildApplicationPage( 109 + array( 110 + $crumbs, 111 + $box, 112 + ), 113 + array( 114 + 'title' => $title, 115 + 'device' => true, 116 + )); 117 + } 118 + 119 + }
+28 -1
src/applications/dashboard/controller/PhabricatorDashboardListController.php
··· 33 33 return $nav; 34 34 } 35 35 36 + public function buildApplicationCrumbs() { 37 + $crumbs = parent::buildApplicationCrumbs(); 38 + 39 + $crumbs->addAction( 40 + id(new PHUIListItemView()) 41 + ->setIcon('create') 42 + ->setName(pht('Create Dashboard')) 43 + ->setHref($this->getApplicationURI().'create/')); 44 + 45 + return $crumbs; 46 + } 47 + 36 48 public function renderResultsList( 37 49 array $dashboards, 38 50 PhabricatorSavedQuery $query) { 51 + $viewer = $this->getRequest()->getUser(); 39 52 40 - return 'got '.count($dashboards).' ok'; 53 + $list = new PHUIObjectItemListView(); 54 + $list->setUser($viewer); 55 + foreach ($dashboards as $dashboard) { 56 + $id = $dashboard->getID(); 57 + 58 + $item = id(new PHUIObjectItemView()) 59 + ->setObjectName(pht('Dashboard %d', $id)) 60 + ->setHeader($dashboard->getName()) 61 + ->setHref($this->getApplicationURI("view/{$id}/")) 62 + ->setObject($dashboard); 63 + 64 + $list->addItem($item); 65 + } 66 + 67 + return $list; 41 68 } 42 69 43 70 }
+123
src/applications/dashboard/controller/PhabricatorDashboardPanelEditController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelEditController 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 + if ($this->id) { 17 + $is_create = false; 18 + 19 + $panel = id(new PhabricatorDashboardPanelQuery()) 20 + ->setViewer($viewer) 21 + ->withIDs(array($this->id)) 22 + ->requireCapabilities( 23 + array( 24 + PhabricatorPolicyCapability::CAN_VIEW, 25 + PhabricatorPolicyCapability::CAN_EDIT, 26 + )) 27 + ->executeOne(); 28 + if (!$panel) { 29 + return new Aphront404Response(); 30 + } 31 + 32 + } else { 33 + $is_create = true; 34 + 35 + $panel = PhabricatorDashboardPanel::initializeNewPanel($viewer); 36 + } 37 + 38 + if ($is_create) { 39 + $title = pht('New Panel'); 40 + $header = pht('Create New Panel'); 41 + $button = pht('Create Panel'); 42 + $cancel_uri = $this->getApplicationURI('panel/'); 43 + } else { 44 + $title = pht('Edit %s', $panel->getMonogram()); 45 + $header = pht('Edit %s %s', $panel->getMonogram(), $panel->getName()); 46 + $button = pht('Save Panel'); 47 + $cancel_uri = '/'.$panel->getMonogram(); 48 + } 49 + 50 + $v_name = $panel->getName(); 51 + $e_name = true; 52 + 53 + $validation_exception = null; 54 + if ($request->isFormPost()) { 55 + $v_name = $request->getStr('name'); 56 + 57 + $xactions = array(); 58 + 59 + $type_name = PhabricatorDashboardPanelTransaction::TYPE_NAME; 60 + 61 + $xactions[] = id(new PhabricatorDashboardPanelTransaction()) 62 + ->setTransactionType($type_name) 63 + ->setNewValue($v_name); 64 + 65 + try { 66 + $editor = id(new PhabricatorDashboardPanelTransactionEditor()) 67 + ->setActor($viewer) 68 + ->setContinueOnNoEffect(true) 69 + ->setContentSourceFromRequest($request) 70 + ->applyTransactions($panel, $xactions); 71 + 72 + return id(new AphrontRedirectResponse()) 73 + ->setURI('/'.$panel->getMonogram()); 74 + } catch (PhabricatorApplicationTransactionValidationException $ex) { 75 + $validation_exception = $ex; 76 + 77 + $e_name = $validation_exception->getShortMessage($type_name); 78 + } 79 + } 80 + 81 + $form = id(new AphrontFormView()) 82 + ->setUser($viewer) 83 + ->appendChild( 84 + id(new AphrontFormTextControl()) 85 + ->setLabel(pht('Name')) 86 + ->setName('name') 87 + ->setValue($v_name) 88 + ->setError($e_name)) 89 + ->appendChild( 90 + id(new AphrontFormSubmitControl()) 91 + ->setValue($button) 92 + ->addCancelButton($cancel_uri)); 93 + 94 + $crumbs = $this->buildApplicationCrumbs(); 95 + $crumbs->addTextCrumb( 96 + pht('Panels'), 97 + $this->getApplicationURI('panel/')); 98 + if ($is_create) { 99 + $crumbs->addTextCrumb(pht('New Panel')); 100 + } else { 101 + $crumbs->addTextCrumb( 102 + $panel->getMonogram(), 103 + '/'.$panel->getMonogram()); 104 + $crumbs->addTextCrumb(pht('Edit')); 105 + } 106 + 107 + $box = id(new PHUIObjectBoxView()) 108 + ->setHeaderText($header) 109 + ->setValidationException($validation_exception) 110 + ->setForm($form); 111 + 112 + return $this->buildApplicationPage( 113 + array( 114 + $crumbs, 115 + $box, 116 + ), 117 + array( 118 + 'title' => $title, 119 + 'device' => true, 120 + )); 121 + } 122 + 123 + }
+29 -1
src/applications/dashboard/controller/PhabricatorDashboardPanelListController.php
··· 33 33 return $nav; 34 34 } 35 35 36 + public function buildApplicationCrumbs() { 37 + $crumbs = parent::buildApplicationCrumbs(); 38 + 39 + $crumbs->addTextCrumb(pht('Panels'), $this->getApplicationURI().'panel/'); 40 + 41 + $crumbs->addAction( 42 + id(new PHUIListItemView()) 43 + ->setIcon('create') 44 + ->setName(pht('Create Panel')) 45 + ->setHref($this->getApplicationURI().'panel/create/')); 46 + 47 + return $crumbs; 48 + } 49 + 36 50 public function renderResultsList( 37 51 array $panels, 38 52 PhabricatorSavedQuery $query) { 39 53 40 - return 'got '.count($panels).' ok'; 54 + $viewer = $this->getRequest()->getUser(); 55 + 56 + $list = new PHUIObjectItemListView(); 57 + $list->setUser($viewer); 58 + foreach ($panels as $panel) { 59 + $item = id(new PHUIObjectItemView()) 60 + ->setObjectName($panel->getMonogram()) 61 + ->setHeader($panel->getName()) 62 + ->setHref('/'.$panel->getMonogram()) 63 + ->setObject($panel); 64 + 65 + $list->addItem($item); 66 + } 67 + 68 + return $list; 41 69 } 42 70 43 71 }
+123
src/applications/dashboard/controller/PhabricatorDashboardPanelViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelViewController 4 + extends PhabricatorDashboardController { 5 + 6 + private $id; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->id = $data['id']; 10 + } 11 + 12 + public function processRequest() { 13 + $request = $this->getRequest(); 14 + $viewer = $request->getUser(); 15 + 16 + $panel = id(new PhabricatorDashboardPanelQuery()) 17 + ->setViewer($viewer) 18 + ->withIDs(array($this->id)) 19 + ->executeOne(); 20 + if (!$panel) { 21 + return new Aphront404Response(); 22 + } 23 + 24 + $title = $panel->getMonogram().' '.$panel->getName(); 25 + $crumbs = $this->buildApplicationCrumbs(); 26 + $crumbs->addTextCrumb( 27 + pht('Panels'), 28 + $this->getApplicationURI('panel/')); 29 + $crumbs->addTextCrumb($panel->getMonogram()); 30 + 31 + $header = $this->buildHeaderView($panel); 32 + $actions = $this->buildActionView($panel); 33 + $properties = $this->buildPropertyView($panel); 34 + $timeline = $this->buildTransactions($panel); 35 + 36 + $properties->setActionList($actions); 37 + $box = id(new PHUIObjectBoxView()) 38 + ->setHeader($header) 39 + ->addPropertyList($properties); 40 + 41 + return $this->buildApplicationPage( 42 + array( 43 + $crumbs, 44 + $box, 45 + $timeline, 46 + ), 47 + array( 48 + 'title' => $title, 49 + 'device' => true, 50 + )); 51 + } 52 + 53 + private function buildHeaderView(PhabricatorDashboardPanel $panel) { 54 + $viewer = $this->getRequest()->getUser(); 55 + 56 + return id(new PHUIHeaderView()) 57 + ->setUser($viewer) 58 + ->setHeader($panel->getName()) 59 + ->setPolicyObject($panel); 60 + } 61 + 62 + private function buildActionView(PhabricatorDashboardPanel $panel) { 63 + $viewer = $this->getRequest()->getUser(); 64 + $id = $panel->getID(); 65 + 66 + $actions = id(new PhabricatorActionListView()) 67 + ->setObjectURI('/'.$panel->getMonogram()) 68 + ->setUser($viewer); 69 + 70 + $can_edit = PhabricatorPolicyFilter::hasCapability( 71 + $viewer, 72 + $panel, 73 + PhabricatorPolicyCapability::CAN_EDIT); 74 + 75 + $actions->addAction( 76 + id(new PhabricatorActionView()) 77 + ->setName(pht('Edit Panel')) 78 + ->setIcon('edit') 79 + ->setHref($this->getApplicationURI("panel/edit/{$id}/")) 80 + ->setDisabled(!$can_edit) 81 + ->setWorkflow(!$can_edit)); 82 + 83 + return $actions; 84 + } 85 + 86 + private function buildPropertyView(PhabricatorDashboardPanel $panel) { 87 + $viewer = $this->getRequest()->getUser(); 88 + 89 + $properties = id(new PHUIPropertyListView()) 90 + ->setUser($viewer) 91 + ->setObject($panel); 92 + 93 + $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( 94 + $viewer, 95 + $panel); 96 + 97 + $properties->addProperty( 98 + pht('Editable By'), 99 + $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); 100 + 101 + return $properties; 102 + } 103 + 104 + private function buildTransactions(PhabricatorDashboardPanel $panel) { 105 + $viewer = $this->getRequest()->getUser(); 106 + 107 + $xactions = id(new PhabricatorDashboardPanelTransactionQuery()) 108 + ->setViewer($viewer) 109 + ->withObjectPHIDs(array($panel->getPHID())) 110 + ->execute(); 111 + 112 + $engine = id(new PhabricatorMarkupEngine()) 113 + ->setViewer($viewer); 114 + 115 + $timeline = id(new PhabricatorApplicationTransactionView()) 116 + ->setUser($viewer) 117 + ->setObjectPHID($panel->getPHID()) 118 + ->setTransactions($xactions); 119 + 120 + return $timeline; 121 + } 122 + 123 + }
+120
src/applications/dashboard/controller/PhabricatorDashboardViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardViewController 4 + extends PhabricatorDashboardController { 5 + 6 + private $id; 7 + 8 + public function willProcessRequest(array $data) { 9 + $this->id = $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 + 24 + $title = $dashboard->getName(); 25 + $crumbs = $this->buildApplicationCrumbs(); 26 + $crumbs->addTextCrumb(pht('Dashboard %d', $dashboard->getID())); 27 + 28 + $header = $this->buildHeaderView($dashboard); 29 + $actions = $this->buildActionView($dashboard); 30 + $properties = $this->buildPropertyView($dashboard); 31 + $timeline = $this->buildTransactions($dashboard); 32 + 33 + $properties->setActionList($actions); 34 + $box = id(new PHUIObjectBoxView()) 35 + ->setHeader($header) 36 + ->addPropertyList($properties); 37 + 38 + return $this->buildApplicationPage( 39 + array( 40 + $crumbs, 41 + $box, 42 + $timeline, 43 + ), 44 + array( 45 + 'title' => $title, 46 + 'device' => true, 47 + )); 48 + } 49 + 50 + private function buildHeaderView(PhabricatorDashboard $dashboard) { 51 + $viewer = $this->getRequest()->getUser(); 52 + 53 + return id(new PHUIHeaderView()) 54 + ->setUser($viewer) 55 + ->setHeader($dashboard->getName()) 56 + ->setPolicyObject($dashboard); 57 + } 58 + 59 + private function buildActionView(PhabricatorDashboard $dashboard) { 60 + $viewer = $this->getRequest()->getUser(); 61 + $id = $dashboard->getID(); 62 + 63 + $actions = id(new PhabricatorActionListView()) 64 + ->setObjectURI($this->getApplicationURI('view/'.$dashboard->getID().'/')) 65 + ->setUser($viewer); 66 + 67 + $can_edit = PhabricatorPolicyFilter::hasCapability( 68 + $viewer, 69 + $dashboard, 70 + PhabricatorPolicyCapability::CAN_EDIT); 71 + 72 + $actions->addAction( 73 + id(new PhabricatorActionView()) 74 + ->setName(pht('Edit Dashboard')) 75 + ->setIcon('edit') 76 + ->setHref($this->getApplicationURI("edit/{$id}/")) 77 + ->setDisabled(!$can_edit) 78 + ->setWorkflow(!$can_edit)); 79 + 80 + return $actions; 81 + } 82 + 83 + private function buildPropertyView(PhabricatorDashboard $dashboard) { 84 + $viewer = $this->getRequest()->getUser(); 85 + 86 + $properties = id(new PHUIPropertyListView()) 87 + ->setUser($viewer) 88 + ->setObject($dashboard); 89 + 90 + $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( 91 + $viewer, 92 + $dashboard); 93 + 94 + $properties->addProperty( 95 + pht('Editable By'), 96 + $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); 97 + 98 + return $properties; 99 + } 100 + 101 + private function buildTransactions(PhabricatorDashboard $dashboard) { 102 + $viewer = $this->getRequest()->getUser(); 103 + 104 + $xactions = id(new PhabricatorDashboardTransactionQuery()) 105 + ->setViewer($viewer) 106 + ->withObjectPHIDs(array($dashboard->getPHID())) 107 + ->execute(); 108 + 109 + $engine = id(new PhabricatorMarkupEngine()) 110 + ->setViewer($viewer); 111 + 112 + $timeline = id(new PhabricatorApplicationTransactionView()) 113 + ->setUser($viewer) 114 + ->setObjectPHID($dashboard->getPHID()) 115 + ->setTransactions($xactions); 116 + 117 + return $timeline; 118 + } 119 + 120 + }
+101
src/applications/dashboard/editor/PhabricatorDashboardPanelTransactionEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelTransactionEditor 4 + extends PhabricatorApplicationTransactionEditor { 5 + 6 + public function getTransactionTypes() { 7 + $types = parent::getTransactionTypes(); 8 + 9 + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 10 + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 11 + 12 + $types[] = PhabricatorDashboardPanelTransaction::TYPE_NAME; 13 + 14 + return $types; 15 + } 16 + 17 + protected function getCustomTransactionOldValue( 18 + PhabricatorLiskDAO $object, 19 + PhabricatorApplicationTransaction $xaction) { 20 + switch ($xaction->getTransactionType()) { 21 + case PhabricatorDashboardPanelTransaction::TYPE_NAME: 22 + if ($this->getIsNewObject()) { 23 + return null; 24 + } 25 + return $object->getName(); 26 + } 27 + 28 + return parent::getCustomTransactionOldValue($object, $xaction); 29 + } 30 + 31 + protected function getCustomTransactionNewValue( 32 + PhabricatorLiskDAO $object, 33 + PhabricatorApplicationTransaction $xaction) { 34 + switch ($xaction->getTransactionType()) { 35 + case PhabricatorDashboardPanelTransaction::TYPE_NAME: 36 + return $xaction->getNewValue(); 37 + } 38 + return parent::getCustomTransactionNewValue($object, $xaction); 39 + } 40 + 41 + protected function applyCustomInternalTransaction( 42 + PhabricatorLiskDAO $object, 43 + PhabricatorApplicationTransaction $xaction) { 44 + switch ($xaction->getTransactionType()) { 45 + case PhabricatorDashboardPanelTransaction::TYPE_NAME: 46 + $object->setName($xaction->getNewValue()); 47 + return; 48 + case PhabricatorTransactions::TYPE_VIEW_POLICY: 49 + $object->setViewPolicy($xaction->getNewValue()); 50 + return; 51 + case PhabricatorTransactions::TYPE_EDIT_POLICY: 52 + $object->setEditPolicy($xaction->getNewValue()); 53 + return; 54 + } 55 + 56 + return parent::applyCustomInternalTransaction($object, $xaction); 57 + } 58 + 59 + protected function applyCustomExternalTransaction( 60 + PhabricatorLiskDAO $object, 61 + PhabricatorApplicationTransaction $xaction) { 62 + 63 + switch ($xaction->getTransactionType()) { 64 + case PhabricatorDashboardPanelTransaction::TYPE_NAME: 65 + return; 66 + } 67 + 68 + return parent::applyCustomExternalTransaction($object, $xaction); 69 + } 70 + 71 + protected function validateTransaction( 72 + PhabricatorLiskDAO $object, 73 + $type, 74 + array $xactions) { 75 + 76 + $errors = parent::validateTransaction($object, $type, $xactions); 77 + 78 + switch ($type) { 79 + case PhabricatorDashboardPanelTransaction::TYPE_NAME: 80 + $missing = $this->validateIsEmptyTextField( 81 + $object->getName(), 82 + $xactions); 83 + 84 + if ($missing) { 85 + $error = new PhabricatorApplicationTransactionValidationError( 86 + $type, 87 + pht('Required'), 88 + pht('Panel name is required.'), 89 + nonempty(last($xactions), null)); 90 + 91 + $error->setIsMissingFieldError(true); 92 + $errors[] = $error; 93 + } 94 + break; 95 + } 96 + 97 + return $errors; 98 + } 99 + 100 + 101 + }
+101
src/applications/dashboard/editor/PhabricatorDashboardTransactionEditor.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardTransactionEditor 4 + extends PhabricatorApplicationTransactionEditor { 5 + 6 + public function getTransactionTypes() { 7 + $types = parent::getTransactionTypes(); 8 + 9 + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 10 + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 11 + 12 + $types[] = PhabricatorDashboardTransaction::TYPE_NAME; 13 + 14 + return $types; 15 + } 16 + 17 + protected function getCustomTransactionOldValue( 18 + PhabricatorLiskDAO $object, 19 + PhabricatorApplicationTransaction $xaction) { 20 + switch ($xaction->getTransactionType()) { 21 + case PhabricatorDashboardTransaction::TYPE_NAME: 22 + if ($this->getIsNewObject()) { 23 + return null; 24 + } 25 + return $object->getName(); 26 + } 27 + 28 + return parent::getCustomTransactionOldValue($object, $xaction); 29 + } 30 + 31 + protected function getCustomTransactionNewValue( 32 + PhabricatorLiskDAO $object, 33 + PhabricatorApplicationTransaction $xaction) { 34 + switch ($xaction->getTransactionType()) { 35 + case PhabricatorDashboardTransaction::TYPE_NAME: 36 + return $xaction->getNewValue(); 37 + } 38 + return parent::getCustomTransactionNewValue($object, $xaction); 39 + } 40 + 41 + protected function applyCustomInternalTransaction( 42 + PhabricatorLiskDAO $object, 43 + PhabricatorApplicationTransaction $xaction) { 44 + switch ($xaction->getTransactionType()) { 45 + case PhabricatorDashboardTransaction::TYPE_NAME: 46 + $object->setName($xaction->getNewValue()); 47 + return; 48 + case PhabricatorTransactions::TYPE_VIEW_POLICY: 49 + $object->setViewPolicy($xaction->getNewValue()); 50 + return; 51 + case PhabricatorTransactions::TYPE_EDIT_POLICY: 52 + $object->setEditPolicy($xaction->getNewValue()); 53 + return; 54 + } 55 + 56 + return parent::applyCustomInternalTransaction($object, $xaction); 57 + } 58 + 59 + protected function applyCustomExternalTransaction( 60 + PhabricatorLiskDAO $object, 61 + PhabricatorApplicationTransaction $xaction) { 62 + 63 + switch ($xaction->getTransactionType()) { 64 + case PhabricatorDashboardTransaction::TYPE_NAME: 65 + return; 66 + } 67 + 68 + return parent::applyCustomExternalTransaction($object, $xaction); 69 + } 70 + 71 + protected function validateTransaction( 72 + PhabricatorLiskDAO $object, 73 + $type, 74 + array $xactions) { 75 + 76 + $errors = parent::validateTransaction($object, $type, $xactions); 77 + 78 + switch ($type) { 79 + case PhabricatorDashboardTransaction::TYPE_NAME: 80 + $missing = $this->validateIsEmptyTextField( 81 + $object->getName(), 82 + $xactions); 83 + 84 + if ($missing) { 85 + $error = new PhabricatorApplicationTransactionValidationError( 86 + $type, 87 + pht('Required'), 88 + pht('Dashboard name is required.'), 89 + nonempty(last($xactions), null)); 90 + 91 + $error->setIsMissingFieldError(true); 92 + $errors[] = $error; 93 + } 94 + break; 95 + } 96 + 97 + return $errors; 98 + } 99 + 100 + 101 + }
+10
src/applications/dashboard/query/PhabricatorDashboardPanelTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + public function getTemplateApplicationTransaction() { 7 + return new PhabricatorDashboardPanelTransaction(); 8 + } 9 + 10 + }
+10
src/applications/dashboard/query/PhabricatorDashboardTransactionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardTransactionQuery 4 + extends PhabricatorApplicationTransactionQuery { 5 + 6 + public function getTemplateApplicationTransaction() { 7 + return new PhabricatorDashboardTransaction(); 8 + } 9 + 10 + }
+10 -3
src/applications/dashboard/storage/PhabricatorDashboard.php
··· 6 6 final class PhabricatorDashboard extends PhabricatorDashboardDAO 7 7 implements PhabricatorPolicyInterface { 8 8 9 - private $name; 10 - private $viewPolicy; 11 - private $editPolicy; 9 + protected $name; 10 + protected $viewPolicy; 11 + protected $editPolicy; 12 + 13 + public static function initializeNewDashboard(PhabricatorUser $actor) { 14 + return id(new PhabricatorDashboard()) 15 + ->setName('') 16 + ->setViewPolicy(PhabricatorPolicies::POLICY_USER) 17 + ->setEditPolicy($actor->getPHID()); 18 + } 12 19 13 20 public function getConfiguration() { 14 21 return array(
+15 -6
src/applications/dashboard/storage/PhabricatorDashboardPanel.php
··· 3 3 /** 4 4 * An individual dashboard panel. 5 5 */ 6 - final class PhabricatorDashboardPanel extends PhabricatorDashboardDAO { 6 + final class PhabricatorDashboardPanel 7 + extends PhabricatorDashboardDAO 8 + implements PhabricatorPolicyInterface { 9 + 10 + protected $name; 11 + protected $viewPolicy; 12 + protected $editPolicy; 13 + protected $properties = array(); 7 14 8 - private $name; 9 - private $viewPolicy; 10 - private $editPolicy; 11 - private $properties = array(); 15 + public static function initializeNewPanel(PhabricatorUser $actor) { 16 + return id(new PhabricatorDashboardPanel()) 17 + ->setName('') 18 + ->setViewPolicy(PhabricatorPolicies::POLICY_USER) 19 + ->setEditPolicy($actor->getPHID()); 20 + } 12 21 13 22 public function getConfiguration() { 14 23 return array( ··· 21 30 22 31 public function generatePHID() { 23 32 return PhabricatorPHID::generateNewPHID( 24 - PhabricatorDashboardPHIDTypeDashboard::TYPECONST); 33 + PhabricatorDashboardPHIDTypePanel::TYPECONST); 25 34 } 26 35 27 36 public function getProperty($key, $default = null) {
+89
src/applications/dashboard/storage/PhabricatorDashboardPanelTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardPanelTransaction 4 + extends PhabricatorApplicationTransaction { 5 + 6 + const TYPE_NAME = 'dashpanel:name'; 7 + 8 + public function getApplicationName() { 9 + return 'dashboard'; 10 + } 11 + 12 + public function getApplicationTransactionType() { 13 + return PhabricatorDashboardPHIDTypePanel::TYPECONST; 14 + } 15 + 16 + public function getTitle() { 17 + $author_phid = $this->getAuthorPHID(); 18 + $object_phid = $this->getObjectPHID(); 19 + 20 + $old = $this->getOldValue(); 21 + $new = $this->getNewValue(); 22 + 23 + $author_link = $this->renderHandleLink($author_phid); 24 + 25 + $type = $this->getTransactionType(); 26 + switch ($type) { 27 + case self::TYPE_NAME: 28 + if (!strlen($old)) { 29 + return pht( 30 + '%s created this panel.', 31 + $author_link); 32 + } else { 33 + return pht( 34 + '%s renamed this panel from "%s" to "%s".', 35 + $author_link, 36 + $old, 37 + $new); 38 + } 39 + } 40 + 41 + return parent::getTitle(); 42 + } 43 + 44 + public function getTitleForFeed(PhabricatorFeedStory $story) { 45 + $author_phid = $this->getAuthorPHID(); 46 + $object_phid = $this->getObjectPHID(); 47 + 48 + $old = $this->getOldValue(); 49 + $new = $this->getNewValue(); 50 + 51 + $author_link = $this->renderHandleLink($author_phid); 52 + $object_link = $this->renderHandleLink($object_phid); 53 + 54 + $type = $this->getTransactionType(); 55 + switch ($type) { 56 + case self::TYPE_NAME: 57 + if (!strlen($old)) { 58 + return pht( 59 + '%s created dashboard panel %s.', 60 + $author_link, 61 + $object_link); 62 + } else { 63 + return pht( 64 + '%s renamed dashboard panel %s from "%s" to "%s".', 65 + $author_link, 66 + $object_link, 67 + $old, 68 + $new); 69 + } 70 + } 71 + 72 + return parent::getTitleForFeed($story); 73 + } 74 + 75 + public function getColor() { 76 + $old = $this->getOldValue(); 77 + $new = $this->getNewValue(); 78 + 79 + switch ($this->getTransactionType()) { 80 + case self::TYPE_NAME: 81 + if (!strlen($old)) { 82 + return PhabricatorTransactions::COLOR_GREEN; 83 + } 84 + break; 85 + } 86 + 87 + return parent::getColor(); 88 + } 89 + }
+89
src/applications/dashboard/storage/PhabricatorDashboardTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorDashboardTransaction 4 + extends PhabricatorApplicationTransaction { 5 + 6 + const TYPE_NAME = 'dashboard:name'; 7 + 8 + public function getApplicationName() { 9 + return 'dashboard'; 10 + } 11 + 12 + public function getApplicationTransactionType() { 13 + return PhabricatorDashboardPHIDTypeDashboard::TYPECONST; 14 + } 15 + 16 + public function getTitle() { 17 + $author_phid = $this->getAuthorPHID(); 18 + $object_phid = $this->getObjectPHID(); 19 + 20 + $old = $this->getOldValue(); 21 + $new = $this->getNewValue(); 22 + 23 + $author_link = $this->renderHandleLink($author_phid); 24 + 25 + $type = $this->getTransactionType(); 26 + switch ($type) { 27 + case self::TYPE_NAME: 28 + if (!strlen($old)) { 29 + return pht( 30 + '%s created this dashboard.', 31 + $author_link); 32 + } else { 33 + return pht( 34 + '%s renamed this dashboard from "%s" to "%s".', 35 + $author_link, 36 + $old, 37 + $new); 38 + } 39 + } 40 + 41 + return parent::getTitle(); 42 + } 43 + 44 + public function getTitleForFeed(PhabricatorFeedStory $story) { 45 + $author_phid = $this->getAuthorPHID(); 46 + $object_phid = $this->getObjectPHID(); 47 + 48 + $old = $this->getOldValue(); 49 + $new = $this->getNewValue(); 50 + 51 + $author_link = $this->renderHandleLink($author_phid); 52 + $object_link = $this->renderHandleLink($object_phid); 53 + 54 + $type = $this->getTransactionType(); 55 + switch ($type) { 56 + case self::TYPE_NAME: 57 + if (!strlen($old)) { 58 + return pht( 59 + '%s created dashboard %s.', 60 + $author_link, 61 + $object_link); 62 + } else { 63 + return pht( 64 + '%s renamed dashboard %s from "%s" to "%s".', 65 + $author_link, 66 + $object_link, 67 + $old, 68 + $new); 69 + } 70 + } 71 + 72 + return parent::getTitleForFeed($story); 73 + } 74 + 75 + public function getColor() { 76 + $old = $this->getOldValue(); 77 + $new = $this->getNewValue(); 78 + 79 + switch ($this->getTransactionType()) { 80 + case self::TYPE_NAME: 81 + if (!strlen($old)) { 82 + return PhabricatorTransactions::COLOR_GREEN; 83 + } 84 + break; 85 + } 86 + 87 + return parent::getColor(); 88 + } 89 + }