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

When a task graph has too much stuff, only show adjacent nodes (direct parents/children)

Summary:
Ref T4788. This gives us a new level of graceful degradation, so now we show:

- Zero through 100 connected tasks: whole graph.
- More than 100 connnected tasks, but fewer than 100 direct parents/subtasks: just parents and subtasks, with "..." to hint that the graph is cut off.
- More than 100 parents and children: just the "sorry, too much stuff" error message.

Test Plan: {F1740882}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4788

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

+92 -14
+27 -14
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 94 94 ->setLimit($graph_limit) 95 95 ->loadGraph(); 96 96 if (!$task_graph->isEmpty()) { 97 - if ($task_graph->isOverLimit()) { 97 + $parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST; 98 + $subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST; 99 + $parent_map = $task_graph->getEdges($parent_type); 100 + $subtask_map = $task_graph->getEdges($subtask_type); 101 + $parent_list = idx($parent_map, $task->getPHID(), array()); 102 + $subtask_list = idx($subtask_map, $task->getPHID(), array()); 103 + $has_parents = (bool)$parent_list; 104 + $has_subtasks = (bool)$subtask_list; 105 + 106 + $search_text = pht('Search...'); 107 + 108 + // First, get a count of direct parent tasks and subtasks. If there 109 + // are too many of these, we just don't draw anything. You can use 110 + // the search button to browse tasks with the search UI instead. 111 + $direct_count = count($parent_list) + count($subtask_list); 112 + 113 + if ($direct_count > $graph_limit) { 98 114 $message = pht( 99 - 'Task graph too large to display (this task is connected to '. 100 - 'more than %s other tasks).', 101 - $graph_limit); 115 + 'Task graph too large to display (this task is directly connected '. 116 + 'to more than %s other tasks). Use %s to explore connected tasks.', 117 + $graph_limit, 118 + phutil_tag('strong', array(), $search_text)); 102 119 $message = phutil_tag('em', array(), $message); 103 120 $graph_table = id(new PHUIPropertyListView()) 104 121 ->addTextContent($message); 105 122 } else { 123 + // If there aren't too many direct tasks, but there are too many total 124 + // tasks, we'll only render directly connected tasks. 125 + if ($task_graph->isOverLimit()) { 126 + $task_graph->setRenderOnlyAdjacentNodes(true); 127 + } 106 128 $graph_table = $task_graph->newGraphTable(); 107 129 } 108 - 109 - $parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST; 110 - $subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST; 111 - 112 - $parent_map = $task_graph->getEdges($parent_type); 113 - $subtask_map = $task_graph->getEdges($subtask_type); 114 - 115 - $has_parents = (bool)idx($parent_map, $task->getPHID()); 116 - $has_subtasks = (bool)idx($subtask_map, $task->getPHID()); 117 130 118 131 $parents_uri = urisprintf( 119 132 '/?subtaskIDs=%d#R', ··· 143 156 $graph_menu = id(new PHUIButtonView()) 144 157 ->setTag('a') 145 158 ->setIcon('fa-search') 146 - ->setText(pht('Search...')) 159 + ->setText($search_text) 147 160 ->setDropdownMenu($dropdown_menu); 148 161 149 162 $graph_header = id(new PHUIHeaderView())
+12
src/infrastructure/graph/ManiphestTaskGraph.php
··· 148 148 149 149 return $this->seedMaps[$type]; 150 150 } 151 + 152 + protected function newEllipsisRow() { 153 + return array( 154 + null, 155 + null, 156 + null, 157 + null, 158 + pht("\xC2\xB7 \xC2\xB7 \xC2\xB7"), 159 + ); 160 + } 161 + 162 + 151 163 }
+53
src/infrastructure/graph/PhabricatorObjectGraph.php
··· 10 10 private $objects; 11 11 private $loadEntireGraph = false; 12 12 private $limit; 13 + private $adjacent; 13 14 14 15 public function setViewer(PhabricatorUser $viewer) { 15 16 $this->viewer = $viewer; ··· 33 34 return $this->limit; 34 35 } 35 36 37 + final public function setRenderOnlyAdjacentNodes($adjacent) { 38 + $this->adjacent = $adjacent; 39 + return $this; 40 + } 41 + 42 + final public function getRenderOnlyAdjacentNodes() { 43 + return $this->adjacent; 44 + } 45 + 36 46 abstract protected function getEdgeTypes(); 37 47 abstract protected function getParentEdgeType(); 38 48 abstract protected function newQuery(); 39 49 abstract protected function newTableRow($phid, $object, $trace); 40 50 abstract protected function newTable(AphrontTableView $table); 41 51 abstract protected function isClosed($object); 52 + 53 + protected function newEllipsisRow() { 54 + return array( 55 + '...', 56 + ); 57 + } 42 58 43 59 final public function setSeedPHID($phid) { 44 60 $this->seedPHID = $phid; ··· 139 155 140 156 $ancestry = $this->getEdges($this->getParentEdgeType()); 141 157 158 + $only_adjacent = $this->getRenderOnlyAdjacentNodes(); 159 + if ($only_adjacent) { 160 + $adjacent = array( 161 + $this->getSeedPHID() => $this->getSeedPHID(), 162 + ); 163 + 164 + foreach ($this->getEdgeTypes() as $edge_type) { 165 + $map = $this->getEdges($edge_type); 166 + $direct = idx($map, $this->getSeedPHID(), array()); 167 + $adjacent += array_fuse($direct); 168 + } 169 + 170 + foreach ($ancestry as $key => $list) { 171 + if (!isset($adjacent[$key])) { 172 + unset($ancestry[$key]); 173 + continue; 174 + } 175 + 176 + foreach ($list as $list_key => $item) { 177 + if (!isset($adjacent[$item])) { 178 + unset($ancestry[$key][$list_key]); 179 + } 180 + } 181 + } 182 + } 183 + 142 184 $objects = $this->newQuery() 143 185 ->setViewer($viewer) 144 186 ->withPHIDs(array_keys($ancestry)) ··· 157 199 $ii = 0; 158 200 $rows = array(); 159 201 $rowc = array(); 202 + 203 + if ($only_adjacent) { 204 + $rows[] = $this->newEllipsisRow(); 205 + $rowc[] = 'more'; 206 + } 207 + 160 208 foreach ($ancestry as $phid => $ignored) { 161 209 $object = idx($objects, $phid); 162 210 $rows[] = $this->newTableRow($phid, $object, $traces[$ii++]); ··· 179 227 } 180 228 181 229 $rowc[] = $classes; 230 + } 231 + 232 + if ($only_adjacent) { 233 + $rows[] = $this->newEllipsisRow(); 234 + $rowc[] = 'more'; 182 235 } 183 236 184 237 $table = id(new AphrontTableView($rows))