mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 13:30:55 +01:00
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
This commit is contained in:
parent
ef5cb0630f
commit
15c7eb1425
3 changed files with 92 additions and 14 deletions
|
@ -94,27 +94,40 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
|||
->setLimit($graph_limit)
|
||||
->loadGraph();
|
||||
if (!$task_graph->isEmpty()) {
|
||||
if ($task_graph->isOverLimit()) {
|
||||
$parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
|
||||
$subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
|
||||
$parent_map = $task_graph->getEdges($parent_type);
|
||||
$subtask_map = $task_graph->getEdges($subtask_type);
|
||||
$parent_list = idx($parent_map, $task->getPHID(), array());
|
||||
$subtask_list = idx($subtask_map, $task->getPHID(), array());
|
||||
$has_parents = (bool)$parent_list;
|
||||
$has_subtasks = (bool)$subtask_list;
|
||||
|
||||
$search_text = pht('Search...');
|
||||
|
||||
// First, get a count of direct parent tasks and subtasks. If there
|
||||
// are too many of these, we just don't draw anything. You can use
|
||||
// the search button to browse tasks with the search UI instead.
|
||||
$direct_count = count($parent_list) + count($subtask_list);
|
||||
|
||||
if ($direct_count > $graph_limit) {
|
||||
$message = pht(
|
||||
'Task graph too large to display (this task is connected to '.
|
||||
'more than %s other tasks).',
|
||||
$graph_limit);
|
||||
'Task graph too large to display (this task is directly connected '.
|
||||
'to more than %s other tasks). Use %s to explore connected tasks.',
|
||||
$graph_limit,
|
||||
phutil_tag('strong', array(), $search_text));
|
||||
$message = phutil_tag('em', array(), $message);
|
||||
$graph_table = id(new PHUIPropertyListView())
|
||||
->addTextContent($message);
|
||||
} else {
|
||||
// If there aren't too many direct tasks, but there are too many total
|
||||
// tasks, we'll only render directly connected tasks.
|
||||
if ($task_graph->isOverLimit()) {
|
||||
$task_graph->setRenderOnlyAdjacentNodes(true);
|
||||
}
|
||||
$graph_table = $task_graph->newGraphTable();
|
||||
}
|
||||
|
||||
$parent_type = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST;
|
||||
$subtask_type = ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
|
||||
|
||||
$parent_map = $task_graph->getEdges($parent_type);
|
||||
$subtask_map = $task_graph->getEdges($subtask_type);
|
||||
|
||||
$has_parents = (bool)idx($parent_map, $task->getPHID());
|
||||
$has_subtasks = (bool)idx($subtask_map, $task->getPHID());
|
||||
|
||||
$parents_uri = urisprintf(
|
||||
'/?subtaskIDs=%d#R',
|
||||
$task->getID());
|
||||
|
@ -143,7 +156,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
|
|||
$graph_menu = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setIcon('fa-search')
|
||||
->setText(pht('Search...'))
|
||||
->setText($search_text)
|
||||
->setDropdownMenu($dropdown_menu);
|
||||
|
||||
$graph_header = id(new PHUIHeaderView())
|
||||
|
|
|
@ -148,4 +148,16 @@ final class ManiphestTaskGraph
|
|||
|
||||
return $this->seedMaps[$type];
|
||||
}
|
||||
|
||||
protected function newEllipsisRow() {
|
||||
return array(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
pht("\xC2\xB7 \xC2\xB7 \xC2\xB7"),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ abstract class PhabricatorObjectGraph
|
|||
private $objects;
|
||||
private $loadEntireGraph = false;
|
||||
private $limit;
|
||||
private $adjacent;
|
||||
|
||||
public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
|
@ -33,6 +34,15 @@ abstract class PhabricatorObjectGraph
|
|||
return $this->limit;
|
||||
}
|
||||
|
||||
final public function setRenderOnlyAdjacentNodes($adjacent) {
|
||||
$this->adjacent = $adjacent;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getRenderOnlyAdjacentNodes() {
|
||||
return $this->adjacent;
|
||||
}
|
||||
|
||||
abstract protected function getEdgeTypes();
|
||||
abstract protected function getParentEdgeType();
|
||||
abstract protected function newQuery();
|
||||
|
@ -40,6 +50,12 @@ abstract class PhabricatorObjectGraph
|
|||
abstract protected function newTable(AphrontTableView $table);
|
||||
abstract protected function isClosed($object);
|
||||
|
||||
protected function newEllipsisRow() {
|
||||
return array(
|
||||
'...',
|
||||
);
|
||||
}
|
||||
|
||||
final public function setSeedPHID($phid) {
|
||||
$this->seedPHID = $phid;
|
||||
$this->edgeReach[$phid] = array_fill_keys($this->getEdgeTypes(), true);
|
||||
|
@ -139,6 +155,32 @@ abstract class PhabricatorObjectGraph
|
|||
|
||||
$ancestry = $this->getEdges($this->getParentEdgeType());
|
||||
|
||||
$only_adjacent = $this->getRenderOnlyAdjacentNodes();
|
||||
if ($only_adjacent) {
|
||||
$adjacent = array(
|
||||
$this->getSeedPHID() => $this->getSeedPHID(),
|
||||
);
|
||||
|
||||
foreach ($this->getEdgeTypes() as $edge_type) {
|
||||
$map = $this->getEdges($edge_type);
|
||||
$direct = idx($map, $this->getSeedPHID(), array());
|
||||
$adjacent += array_fuse($direct);
|
||||
}
|
||||
|
||||
foreach ($ancestry as $key => $list) {
|
||||
if (!isset($adjacent[$key])) {
|
||||
unset($ancestry[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($list as $list_key => $item) {
|
||||
if (!isset($adjacent[$item])) {
|
||||
unset($ancestry[$key][$list_key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$objects = $this->newQuery()
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array_keys($ancestry))
|
||||
|
@ -157,6 +199,12 @@ abstract class PhabricatorObjectGraph
|
|||
$ii = 0;
|
||||
$rows = array();
|
||||
$rowc = array();
|
||||
|
||||
if ($only_adjacent) {
|
||||
$rows[] = $this->newEllipsisRow();
|
||||
$rowc[] = 'more';
|
||||
}
|
||||
|
||||
foreach ($ancestry as $phid => $ignored) {
|
||||
$object = idx($objects, $phid);
|
||||
$rows[] = $this->newTableRow($phid, $object, $traces[$ii++]);
|
||||
|
@ -181,6 +229,11 @@ abstract class PhabricatorObjectGraph
|
|||
$rowc[] = $classes;
|
||||
}
|
||||
|
||||
if ($only_adjacent) {
|
||||
$rows[] = $this->newEllipsisRow();
|
||||
$rowc[] = 'more';
|
||||
}
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setClassName('object-graph-table')
|
||||
->setRowClasses($rowc);
|
||||
|
|
Loading…
Reference in a new issue