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

Implement "Group by Owner" on Workboards

Summary: Depends on D20269. Ref T10333. Now that orderings are modularized, this is fairly easy to implement. This isn't super fancy for now (e.g., no profile images) but I'll touch it up in a general polish followup.

Test Plan: {F6264596}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T10333

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

+165
+2
src/__phutil_library_map__.php
··· 4056 4056 'PhabricatorProjectColumnHideController' => 'applications/project/controller/PhabricatorProjectColumnHideController.php', 4057 4057 'PhabricatorProjectColumnNaturalOrder' => 'applications/project/order/PhabricatorProjectColumnNaturalOrder.php', 4058 4058 'PhabricatorProjectColumnOrder' => 'applications/project/order/PhabricatorProjectColumnOrder.php', 4059 + 'PhabricatorProjectColumnOwnerOrder' => 'applications/project/order/PhabricatorProjectColumnOwnerOrder.php', 4059 4060 'PhabricatorProjectColumnPHIDType' => 'applications/project/phid/PhabricatorProjectColumnPHIDType.php', 4060 4061 'PhabricatorProjectColumnPosition' => 'applications/project/storage/PhabricatorProjectColumnPosition.php', 4061 4062 'PhabricatorProjectColumnPositionQuery' => 'applications/project/query/PhabricatorProjectColumnPositionQuery.php', ··· 10140 10141 'PhabricatorProjectColumnHideController' => 'PhabricatorProjectBoardController', 10141 10142 'PhabricatorProjectColumnNaturalOrder' => 'PhabricatorProjectColumnOrder', 10142 10143 'PhabricatorProjectColumnOrder' => 'Phobject', 10144 + 'PhabricatorProjectColumnOwnerOrder' => 'PhabricatorProjectColumnOrder', 10143 10145 'PhabricatorProjectColumnPHIDType' => 'PhabricatorPHIDType', 10144 10146 'PhabricatorProjectColumnPosition' => array( 10145 10147 'PhabricatorProjectDAO',
+163
src/applications/project/order/PhabricatorProjectColumnOwnerOrder.php
··· 1 + <?php 2 + 3 + final class PhabricatorProjectColumnOwnerOrder 4 + extends PhabricatorProjectColumnOrder { 5 + 6 + const ORDERKEY = 'owner'; 7 + 8 + public function getDisplayName() { 9 + return pht('Group by Owner'); 10 + } 11 + 12 + protected function newMenuIconIcon() { 13 + return 'fa-users'; 14 + } 15 + 16 + protected function newHeaderKeyForObject($object) { 17 + return $this->newHeaderKeyForOwnerPHID($object->getOwnerPHID()); 18 + } 19 + 20 + private function newHeaderKeyForOwnerPHID($owner_phid) { 21 + if ($owner_phid === null) { 22 + $owner_phid = '<null>'; 23 + } 24 + 25 + return sprintf('owner(%s)', $owner_phid); 26 + } 27 + 28 + protected function newSortVectorsForObjects(array $objects) { 29 + $owner_phids = mpull($objects, null, 'getOwnerPHID'); 30 + $owner_phids = array_keys($owner_phids); 31 + $owner_phids = array_filter($owner_phids); 32 + 33 + if ($owner_phids) { 34 + $owner_users = id(new PhabricatorPeopleQuery()) 35 + ->setViewer($this->getViewer()) 36 + ->withPHIDs($owner_phids) 37 + ->execute(); 38 + $owner_users = mpull($owner_users, null, 'getPHID'); 39 + } else { 40 + $owner_users = array(); 41 + } 42 + 43 + $vectors = array(); 44 + foreach ($objects as $vector_key => $object) { 45 + $owner_phid = $object->getOwnerPHID(); 46 + if (!$owner_phid) { 47 + $vector = $this->newSortVectorForUnowned(); 48 + } else { 49 + $owner = idx($owner_users, $owner_phid); 50 + if ($owner) { 51 + $vector = $this->newSortVectorForOwner($owner); 52 + } else { 53 + $vector = $this->newSortVectorForOwnerPHID($owner_phid); 54 + } 55 + } 56 + 57 + $vectors[$vector_key] = $vector; 58 + } 59 + 60 + return $vectors; 61 + } 62 + 63 + private function newSortVectorForUnowned() { 64 + // Always put unasssigned tasks at the top. 65 + return array( 66 + 0, 67 + ); 68 + } 69 + 70 + private function newSortVectorForOwner(PhabricatorUser $user) { 71 + // Put assigned tasks with a valid owner after "Unassigned", but above 72 + // assigned tasks with an invalid owner. Sort these tasks by the owner's 73 + // username. 74 + return array( 75 + 1, 76 + $user->getUsername(), 77 + ); 78 + } 79 + 80 + private function newSortVectorForOwnerPHID($owner_phid) { 81 + // If we have tasks with a nonempty owner but can't load the associated 82 + // "User" object, move them to the bottom. We can only sort these by the 83 + // PHID. 84 + return array( 85 + 2, 86 + $owner_phid, 87 + ); 88 + } 89 + 90 + protected function newHeadersForObjects(array $objects) { 91 + $owner_phids = mpull($objects, null, 'getOwnerPHID'); 92 + $owner_phids = array_keys($owner_phids); 93 + $owner_phids = array_filter($owner_phids); 94 + 95 + if ($owner_phids) { 96 + $owner_users = id(new PhabricatorPeopleQuery()) 97 + ->setViewer($this->getViewer()) 98 + ->withPHIDs($owner_phids) 99 + ->execute(); 100 + $owner_users = mpull($owner_users, null, 'getPHID'); 101 + } else { 102 + $owner_users = array(); 103 + } 104 + 105 + array_unshift($owner_phids, null); 106 + 107 + $headers = array(); 108 + foreach ($owner_phids as $owner_phid) { 109 + $header_key = $this->newHeaderKeyForOwnerPHID($owner_phid); 110 + 111 + if ($owner_phid === null) { 112 + $owner = null; 113 + $sort_vector = $this->newSortVectorForUnowned(); 114 + $owner_name = pht('Not Assigned'); 115 + } else { 116 + $owner = idx($owner_users, $owner_phid); 117 + if ($owner) { 118 + $sort_vector = $this->newSortVectorForOwner($owner); 119 + $owner_name = $owner->getUsername(); 120 + } else { 121 + $sort_vector = $this->newSortVectorForOwnerPHID($owner_phid); 122 + $owner_name = pht('Unknown User ("%s")', $owner_phid); 123 + } 124 + } 125 + 126 + $owner_icon = 'fa-user'; 127 + $owner_color = 'bluegrey'; 128 + 129 + $icon_view = id(new PHUIIconView()) 130 + ->setIcon($owner_icon, $owner_color); 131 + 132 + $header = $this->newHeader() 133 + ->setHeaderKey($header_key) 134 + ->setSortVector($sort_vector) 135 + ->setName($owner_name) 136 + ->setIcon($icon_view) 137 + ->setEditProperties( 138 + array( 139 + 'value' => $owner_phid, 140 + )); 141 + 142 + $headers[] = $header; 143 + } 144 + 145 + return $headers; 146 + } 147 + 148 + protected function newColumnTransactions($object, array $header) { 149 + $new_owner = idx($header, 'value'); 150 + 151 + if ($object->getOwnerPHID() === $new_owner) { 152 + return null; 153 + } 154 + 155 + $xactions = array(); 156 + $xactions[] = $this->newTransaction($object) 157 + ->setTransactionType(ManiphestTaskOwnerTransaction::TRANSACTIONTYPE) 158 + ->setNewValue($new_owner); 159 + 160 + return $xactions; 161 + } 162 + 163 + }