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

Add "Authored Tasks" view / item to user profile menu

Summary:
The sidebar menu items in the People view (user profiles) currently include `User`, `Tasks`, `Revisions`, `Commits`, `Badges`, `Manage`.
`Tasks` implicitly refers to assigned tasks, while Revisions implicitly refers to authored revisions.
However, some (maybe less developer workflow oriented) users have expected `Tasks` to link to their authored tasks instead.
Thus add an additional menu item called `Authored Tasks` which allows a quick view of the tasks created by the user.

Also be more explicit about the relationship between user and objects by adding an adjective ("Authored", "Assigned", "Received") to their names.
We have two Tasks related items now, so we need to differentiate anyway.

Closes T15998

fix some lint stuff

Test Plan:
* As user1, create tasks and assign tasks to yourself.
* Go to http://phorge.localhost/p/user1/ and click the menu items in the sidebar, including the new option "Authored Tasks".
* Click both "Assigned Tasks" and "Authored Tasks" in the sidebar on http://phorge.localhost/p/user1/ and get results displayed.
* Being logged in, on a default installation go to http://phorge.localhost/maniphest/ to still see your assigned tasks and "Assigned" and "Authored" as Query options in the sidebar (no change in behavior).
* Go to the direct URIs http://phorge.localhost/people/tasks/assigned/1/ and its legacy URI http://phorge.localhost/people/tasks/1/ and still get the assigned tasks of that user within their profile view.
* Go to the direct URI http://phorge.localhost/people/tasks/authored/1/ and get the authored tasks of that user within their profile view.

Reviewers: O1 Blessed Committers, mainframe98

Reviewed By: O1 Blessed Committers, mainframe98

Subscribers: mainframe98, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15998

Differential Revision: https://we.phorge.it/D25889

+178 -23
+8 -4
src/__phutil_library_map__.php
··· 4216 4216 'PhabricatorPeopleProfileMenuEngine' => 'applications/people/engine/PhabricatorPeopleProfileMenuEngine.php', 4217 4217 'PhabricatorPeopleProfilePictureController' => 'applications/people/controller/PhabricatorPeopleProfilePictureController.php', 4218 4218 'PhabricatorPeopleProfileRevisionsController' => 'applications/people/controller/PhabricatorPeopleProfileRevisionsController.php', 4219 - 'PhabricatorPeopleProfileTasksController' => 'applications/people/controller/PhabricatorPeopleProfileTasksController.php', 4219 + 'PhabricatorPeopleProfileTasksAssignedController' => 'applications/people/controller/PhabricatorPeopleProfileTasksAssignedController.php', 4220 + 'PhabricatorPeopleProfileTasksAuthoredController' => 'applications/people/controller/PhabricatorPeopleProfileTasksAuthoredController.php', 4220 4221 'PhabricatorPeopleProfileViewController' => 'applications/people/controller/PhabricatorPeopleProfileViewController.php', 4221 4222 'PhabricatorPeopleQuery' => 'applications/people/query/PhabricatorPeopleQuery.php', 4222 4223 'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', 4223 4224 'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php', 4224 4225 'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', 4225 - 'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php', 4226 + 'PhabricatorPeopleTasksAssignedProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksAssignedProfileMenuItem.php', 4227 + 'PhabricatorPeopleTasksAuthoredProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksAuthoredProfileMenuItem.php', 4226 4228 'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', 4227 4229 'PhabricatorPeopleTransactionQuery' => 'applications/people/query/PhabricatorPeopleTransactionQuery.php', 4228 4230 'PhabricatorPeopleUserEmailPHIDType' => 'applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php', ··· 10813 10815 'PhabricatorPeopleProfileMenuEngine' => 'PhabricatorProfileMenuEngine', 10814 10816 'PhabricatorPeopleProfilePictureController' => 'PhabricatorPeopleProfileController', 10815 10817 'PhabricatorPeopleProfileRevisionsController' => 'PhabricatorPeopleProfileController', 10816 - 'PhabricatorPeopleProfileTasksController' => 'PhabricatorPeopleProfileController', 10818 + 'PhabricatorPeopleProfileTasksAssignedController' => 'PhabricatorPeopleProfileController', 10819 + 'PhabricatorPeopleProfileTasksAuthoredController' => 'PhabricatorPeopleProfileController', 10817 10820 'PhabricatorPeopleProfileViewController' => 'PhabricatorPeopleProfileController', 10818 10821 'PhabricatorPeopleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 10819 10822 'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', 10820 10823 'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem', 10821 10824 'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', 10822 - 'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem', 10825 + 'PhabricatorPeopleTasksAssignedProfileMenuItem' => 'PhabricatorProfileMenuItem', 10826 + 'PhabricatorPeopleTasksAuthoredProfileMenuItem' => 'PhabricatorProfileMenuItem', 10823 10827 'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', 10824 10828 'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 10825 10829 'PhabricatorPeopleUserEmailPHIDType' => 'PhabricatorPHIDType',
+6 -1
src/applications/people/application/PhabricatorPeopleApplication.php
··· 68 68 'PhabricatorPeopleProfileEditController', 69 69 'badges/(?P<id>[1-9]\d*)/' => 70 70 'PhabricatorPeopleProfileBadgesController', 71 + // Legacy route only kept for backward compatibility after T15998 71 72 'tasks/(?P<id>[1-9]\d*)/' => 72 - 'PhabricatorPeopleProfileTasksController', 73 + 'PhabricatorPeopleProfileTasksAssignedController', 74 + 'tasks/assigned/(?P<id>[1-9]\d*)/' => 75 + 'PhabricatorPeopleProfileTasksAssignedController', 76 + 'tasks/authored/(?P<id>[1-9]\d*)/' => 77 + 'PhabricatorPeopleProfileTasksAuthoredController', 73 78 'commits/(?P<id>[1-9]\d*)/' => 74 79 'PhabricatorPeopleProfileCommitsController', 75 80 'revisions/(?P<id>[1-9]\d*)/' =>
+81
src/applications/people/controller/PhabricatorPeopleProfileTasksAuthoredController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPeopleProfileTasksAuthoredController 4 + extends PhabricatorPeopleProfileController { 5 + 6 + public function handleRequest(AphrontRequest $request) { 7 + $viewer = $this->getViewer(); 8 + $id = $request->getURIData('id'); 9 + 10 + $user = id(new PhabricatorPeopleQuery()) 11 + ->setViewer($viewer) 12 + ->withIDs(array($id)) 13 + ->needProfile(true) 14 + ->needProfileImage(true) 15 + ->needAvailability(true) 16 + ->executeOne(); 17 + if (!$user) { 18 + return new Aphront404Response(); 19 + } 20 + 21 + $class = 'PhabricatorManiphestApplication'; 22 + if (!PhabricatorApplication::isClassInstalledForViewer($class, $viewer)) { 23 + return new Aphront404Response(); 24 + } 25 + 26 + $this->setUser($user); 27 + $title = array(pht('Authored Tasks'), $user->getUsername()); 28 + $header = $this->buildProfileHeader(); 29 + $tasks = $this->buildTasksView($user); 30 + 31 + $crumbs = $this->buildApplicationCrumbs(); 32 + $crumbs->addTextCrumb(pht('Authored Tasks')); 33 + $crumbs->setBorder(true); 34 + 35 + $nav = $this->newNavigation( 36 + $user, 37 + PhabricatorPeopleProfileMenuEngine::ITEM_TASKS_AUTHORED); 38 + 39 + $view = id(new PHUITwoColumnView()) 40 + ->setHeader($header) 41 + ->addClass('project-view-home') 42 + ->addClass('project-view-people-home') 43 + ->setFooter(array( 44 + $tasks, 45 + )); 46 + 47 + return $this->newPage() 48 + ->setTitle($title) 49 + ->setCrumbs($crumbs) 50 + ->setNavigation($nav) 51 + ->appendChild($view); 52 + } 53 + 54 + private function buildTasksView(PhabricatorUser $user) { 55 + $viewer = $this->getViewer(); 56 + 57 + $open = ManiphestTaskStatus::getOpenStatusConstants(); 58 + 59 + $tasks = id(new ManiphestTaskQuery()) 60 + ->setViewer($viewer) 61 + ->withAuthors(array($user->getPHID())) 62 + ->needProjectPHIDs(true) 63 + ->setLimit(100) 64 + ->execute(); 65 + 66 + $handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks); 67 + 68 + $list = id(new ManiphestTaskListView()) 69 + ->setUser($viewer) 70 + ->setHandles($handles) 71 + ->setTasks($tasks) 72 + ->setNoDataString(pht('No authored tasks.')); 73 + 74 + $view = id(new PHUIObjectBoxView()) 75 + ->setHeaderText(pht('Authored Tasks')) 76 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 77 + ->appendChild($list); 78 + 79 + return $view; 80 + } 81 + }
+2 -2
src/applications/people/controller/PhabricatorPeopleProfileTasksController.php src/applications/people/controller/PhabricatorPeopleProfileTasksAssignedController.php
··· 1 1 <?php 2 2 3 - final class PhabricatorPeopleProfileTasksController 3 + final class PhabricatorPeopleProfileTasksAssignedController 4 4 extends PhabricatorPeopleProfileController { 5 5 6 6 public function handleRequest(AphrontRequest $request) { ··· 34 34 35 35 $nav = $this->newNavigation( 36 36 $user, 37 - PhabricatorPeopleProfileMenuEngine::ITEM_TASKS); 37 + PhabricatorPeopleProfileMenuEngine::ITEM_TASKS_ASSIGNED); 38 38 39 39 $view = id(new PHUITwoColumnView()) 40 40 ->setHeader($header)
+9 -3
src/applications/people/engine/PhabricatorPeopleProfileMenuEngine.php
··· 7 7 const ITEM_MANAGE = 'people.manage'; 8 8 const ITEM_PICTURE = 'people.picture'; 9 9 const ITEM_BADGES = 'people.badges'; 10 - const ITEM_TASKS = 'people.tasks'; 10 + const ITEM_TASKS_ASSIGNED = 'people.tasks.assigned'; 11 + const ITEM_TASKS_AUTHORED = 'people.tasks.authored'; 11 12 const ITEM_COMMITS = 'people.commits'; 12 13 const ITEM_REVISIONS = 'people.revisions'; 13 14 ··· 40 41 $viewer); 41 42 if ($have_maniphest) { 42 43 $items[] = $this->newItem() 43 - ->setBuiltinKey(self::ITEM_TASKS) 44 - ->setMenuItemKey(PhabricatorPeopleTasksProfileMenuItem::MENUITEMKEY); 44 + ->setBuiltinKey(self::ITEM_TASKS_ASSIGNED) 45 + ->setMenuItemKey( 46 + PhabricatorPeopleTasksAssignedProfileMenuItem::MENUITEMKEY); 47 + $items[] = $this->newItem() 48 + ->setBuiltinKey(self::ITEM_TASKS_AUTHORED) 49 + ->setMenuItemKey( 50 + PhabricatorPeopleTasksAuthoredProfileMenuItem::MENUITEMKEY); 45 51 } 46 52 47 53 $have_differential = PhabricatorApplication::isClassInstalledForViewer(
+2 -2
src/applications/people/menuitem/PhabricatorPeopleBadgesProfileMenuItem.php
··· 6 6 const MENUITEMKEY = 'people.badges'; 7 7 8 8 public function getMenuItemTypeName() { 9 - return pht('Badges'); 9 + return pht('Received Badges'); 10 10 } 11 11 12 12 private function getDefaultName() { 13 - return pht('Badges'); 13 + return pht('Received Badges'); 14 14 } 15 15 16 16 public function canHideMenuItem(
+2 -2
src/applications/people/menuitem/PhabricatorPeopleCommitsProfileMenuItem.php
··· 6 6 const MENUITEMKEY = 'people.commits'; 7 7 8 8 public function getMenuItemTypeName() { 9 - return pht('Commits'); 9 + return pht('Authored Commits'); 10 10 } 11 11 12 12 private function getDefaultName() { 13 - return pht('Commits'); 13 + return pht('Authored Commits'); 14 14 } 15 15 16 16 public function canHideMenuItem(
+1 -1
src/applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php
··· 45 45 46 46 $item = $this->newItemView() 47 47 ->setURI($uri) 48 - ->setName(pht('Profile')) 48 + ->setName(pht('User Profile')) 49 49 ->setIcon('fa-user'); 50 50 51 51 return array(
+1 -1
src/applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php
··· 10 10 } 11 11 12 12 private function getDefaultName() { 13 - return pht('Manage'); 13 + return pht('Manage User'); 14 14 } 15 15 16 16 public function canHideMenuItem(
+2 -2
src/applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php
··· 6 6 const MENUITEMKEY = 'people.revisions'; 7 7 8 8 public function getMenuItemTypeName() { 9 - return pht('Revisions'); 9 + return pht('Authored Revisions'); 10 10 } 11 11 12 12 private function getDefaultName() { 13 - return pht('Revisions'); 13 + return pht('Authored Revisions'); 14 14 } 15 15 16 16 public function canHideMenuItem(
+59
src/applications/people/menuitem/PhabricatorPeopleTasksAuthoredProfileMenuItem.php
··· 1 + <?php 2 + 3 + final class PhabricatorPeopleTasksAuthoredProfileMenuItem 4 + extends PhabricatorProfileMenuItem { 5 + 6 + const MENUITEMKEY = 'people.tasks.authored'; 7 + 8 + public function getMenuItemTypeName() { 9 + return pht('Authored Tasks'); 10 + } 11 + 12 + private function getDefaultName() { 13 + return pht('Authored Tasks'); 14 + } 15 + 16 + public function canHideMenuItem( 17 + PhabricatorProfileMenuItemConfiguration $config) { 18 + return true; 19 + } 20 + 21 + public function getDisplayName( 22 + PhabricatorProfileMenuItemConfiguration $config) { 23 + $name = $config->getMenuItemProperty('name'); 24 + 25 + if (phutil_nonempty_string($name)) { 26 + return $name; 27 + } 28 + 29 + return $this->getDefaultName(); 30 + } 31 + 32 + public function buildEditEngineFields( 33 + PhabricatorProfileMenuItemConfiguration $config) { 34 + return array( 35 + id(new PhabricatorTextEditField()) 36 + ->setKey('name') 37 + ->setLabel(pht('Name')) 38 + ->setPlaceholder($this->getDefaultName()) 39 + ->setValue($config->getMenuItemProperty('name')), 40 + ); 41 + } 42 + 43 + protected function newMenuItemViewList( 44 + PhabricatorProfileMenuItemConfiguration $config) { 45 + 46 + $user = $config->getProfileObject(); 47 + $id = $user->getID(); 48 + 49 + $item = $this->newItemView() 50 + ->setURI("/people/tasks/authored/{$id}/") 51 + ->setName($this->getDisplayName($config)) 52 + ->setIcon('fa-anchor'); 53 + 54 + return array( 55 + $item, 56 + ); 57 + } 58 + 59 + }
+5 -5
src/applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php src/applications/people/menuitem/PhabricatorPeopleTasksAssignedProfileMenuItem.php
··· 1 1 <?php 2 2 3 - final class PhabricatorPeopleTasksProfileMenuItem 3 + final class PhabricatorPeopleTasksAssignedProfileMenuItem 4 4 extends PhabricatorProfileMenuItem { 5 5 6 - const MENUITEMKEY = 'people.tasks'; 6 + const MENUITEMKEY = 'people.tasks.assigned'; 7 7 8 8 public function getMenuItemTypeName() { 9 - return pht('Tasks'); 9 + return pht('Assigned Tasks'); 10 10 } 11 11 12 12 private function getDefaultName() { 13 - return pht('Tasks'); 13 + return pht('Assigned Tasks'); 14 14 } 15 15 16 16 public function canHideMenuItem( ··· 47 47 $id = $user->getID(); 48 48 49 49 $item = $this->newItemView() 50 - ->setURI("/people/tasks/{$id}/") 50 + ->setURI("/people/tasks/assigned/{$id}/") 51 51 ->setName($this->getDisplayName($config)) 52 52 ->setIcon('fa-anchor'); 53 53