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

On tasks, put Task Graph, Mocks and Mentions into a tabgroup

Summary:
Fixes T4788. This change:

- converts the "Task Graph" into a "Related Objects" tabgroup.
- makes "Task Graph" the first tab in the group.
- moves "Mocks" to become a tab.
- adds a new "Mentions" tab, which shows inbound and outbound mentions.

Primary goal of "mocks" is to give us room for a pinboard/thumbnail view after the next Pholio iteration. Might make sense to make it the default tab (if present) at that point, too, since mocks are probably more important than related tasks when they're present.

Primary goal of "mentions" is to provide a bit of general support for various freeform relationships between tasks: if you want to treat tasks as "siblings" or "related" or "following" or whatever, you can at least find them all in one place. I don't plan to formalize any of these weird one-off relationships in the upstream, although it's vaguely possible that some far-future update might just let you define arbitrary custom relationships and then you can do whatever you want.

Test Plan: {F1906974}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4788

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

+121 -28
+121 -28
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 30 30 ->setViewer($viewer) 31 31 ->setTargetObject($task); 32 32 33 - $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST; 34 - $e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST; 35 - $e_mock = ManiphestTaskHasMockEdgeType::EDGECONST; 33 + $edge_types = array( 34 + ManiphestTaskHasCommitEdgeType::EDGECONST, 35 + ManiphestTaskHasRevisionEdgeType::EDGECONST, 36 + ManiphestTaskHasMockEdgeType::EDGECONST, 37 + PhabricatorObjectMentionedByObjectEdgeType::EDGECONST, 38 + PhabricatorObjectMentionsObjectEdgeType::EDGECONST, 39 + ); 36 40 37 41 $phid = $task->getPHID(); 38 42 39 43 $query = id(new PhabricatorEdgeQuery()) 40 44 ->withSourcePHIDs(array($phid)) 41 - ->withEdgeTypes( 42 - array( 43 - $e_commit, 44 - $e_rev, 45 - $e_mock, 46 - )); 45 + ->withEdgeTypes($edge_types); 47 46 $edges = idx($query->execute(), $phid); 48 47 $phids = array_fill_keys($query->getDestinationPHIDs(), true); 49 48 ··· 77 76 $timeline->setQuoteRef($monogram); 78 77 $comment_view->setTransactionTimeline($timeline); 79 78 80 - $view = id(new PHUITwoColumnView()) 81 - ->setHeader($header) 82 - ->setCurtain($curtain) 83 - ->setMainColumn(array( 84 - $timeline, 85 - $comment_view, 86 - )) 87 - ->addPropertySection(pht('Description'), $description) 88 - ->addPropertySection(pht('Details'), $details); 79 + $related_tabs = array(); 80 + $graph_menu = null; 89 81 90 82 $graph_limit = 100; 91 83 $task_graph = id(new ManiphestTaskGraph()) ··· 159 151 ->setText($search_text) 160 152 ->setDropdownMenu($dropdown_menu); 161 153 162 - $graph_header = id(new PHUIHeaderView()) 163 - ->setHeader(pht('Task Graph')) 164 - ->addActionLink($graph_menu); 154 + $related_tabs[] = id(new PHUITabView()) 155 + ->setName(pht('Task Graph')) 156 + ->setKey('graph') 157 + ->appendChild($graph_table); 158 + } 159 + 160 + $related_tabs[] = $this->newMocksTab($task, $query); 161 + $related_tabs[] = $this->newMentionsTab($task, $query); 162 + 163 + $tab_view = null; 164 + 165 + $related_tabs = array_filter($related_tabs); 166 + if ($related_tabs) { 167 + $tab_group = new PHUITabGroupView(); 168 + foreach ($related_tabs as $tab) { 169 + $tab_group->addTab($tab); 170 + } 171 + 172 + $related_header = id(new PHUIHeaderView()) 173 + ->setHeader(pht('Related Objects')); 174 + 175 + if ($graph_menu) { 176 + $related_header->addActionLink($graph_menu); 177 + } 165 178 166 - $view->addPropertySection($graph_header, $graph_table); 179 + $tab_view = id(new PHUIObjectBoxView()) 180 + ->setHeader($related_header) 181 + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) 182 + ->addTabGroup($tab_group); 167 183 } 168 184 185 + $view = id(new PHUITwoColumnView()) 186 + ->setHeader($header) 187 + ->setCurtain($curtain) 188 + ->setMainColumn( 189 + array( 190 + $tab_view, 191 + $timeline, 192 + $comment_view, 193 + )) 194 + ->addPropertySection(pht('Description'), $description) 195 + ->addPropertySection(pht('Details'), $details); 196 + 197 + 169 198 return $this->newPage() 170 199 ->setTitle($title) 171 200 ->setCrumbs($crumbs) ··· 173 202 array( 174 203 $task->getPHID(), 175 204 )) 176 - ->appendChild( 177 - array( 178 - $view, 179 - )); 205 + ->appendChild($view); 180 206 181 207 } 182 208 ··· 356 382 $edge_types = array( 357 383 ManiphestTaskHasRevisionEdgeType::EDGECONST 358 384 => pht('Differential Revisions'), 359 - ManiphestTaskHasMockEdgeType::EDGECONST 360 - => pht('Pholio Mocks'), 361 385 ); 362 386 363 387 $revisions_commits = array(); ··· 433 457 } 434 458 435 459 return $section; 460 + } 461 + 462 + private function newMocksTab( 463 + ManiphestTask $task, 464 + PhabricatorEdgeQuery $edge_query) { 465 + 466 + $mock_type = ManiphestTaskHasMockEdgeType::EDGECONST; 467 + $mock_phids = $edge_query->getDestinationPHIDs(array(), array($mock_type)); 468 + if (!$mock_phids) { 469 + return null; 470 + } 471 + 472 + $viewer = $this->getViewer(); 473 + $handles = $viewer->loadHandles($mock_phids); 474 + 475 + // TODO: It would be nice to render this as pinboard-style thumbnails, 476 + // similar to "{M123}", instead of a list of links. 477 + 478 + $view = id(new PHUIPropertyListView()) 479 + ->addProperty(pht('Mocks'), $handles->renderList()); 480 + 481 + return id(new PHUITabView()) 482 + ->setName(pht('Mocks')) 483 + ->setKey('mocks') 484 + ->appendChild($view); 485 + } 486 + 487 + private function newMentionsTab( 488 + ManiphestTask $task, 489 + PhabricatorEdgeQuery $edge_query) { 490 + 491 + $in_type = PhabricatorObjectMentionedByObjectEdgeType::EDGECONST; 492 + $out_type = PhabricatorObjectMentionsObjectEdgeType::EDGECONST; 493 + 494 + $in_phids = $edge_query->getDestinationPHIDs(array(), array($in_type)); 495 + $out_phids = $edge_query->getDestinationPHIDs(array(), array($out_type)); 496 + 497 + // Filter out any mentioned users from the list. These are not generally 498 + // very interesting to show in a relationship summary since they usually 499 + // end up as subscribers anyway. 500 + 501 + $user_type = PhabricatorPeopleUserPHIDType::TYPECONST; 502 + foreach ($out_phids as $key => $out_phid) { 503 + if (phid_get_type($out_phid) == $user_type) { 504 + unset($out_phids[$key]); 505 + } 506 + } 507 + 508 + if (!$in_phids && !$out_phids) { 509 + return null; 510 + } 511 + 512 + $viewer = $this->getViewer(); 513 + $view = new PHUIPropertyListView(); 514 + 515 + if ($in_phids) { 516 + $in_handles = $viewer->loadHandles($in_phids); 517 + $view->addProperty(pht('Mentioned In'), $in_handles->renderList()); 518 + } 519 + 520 + if ($out_phids) { 521 + $out_handles = $viewer->loadHandles($out_phids); 522 + $view->addProperty(pht('Mentioned Here'), $out_handles->renderList()); 523 + } 524 + 525 + return id(new PHUITabView()) 526 + ->setName(pht('Mentions')) 527 + ->setKey('mentions') 528 + ->appendChild($view); 436 529 } 437 530 438 531 }