Page MenuHomePhabricator

D20164.diff
No OneTemporary

D20164.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -9,7 +9,7 @@
'names' => array(
'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf',
- 'core.pkg.css' => '4ed8ce1f',
+ 'core.pkg.css' => '85a1da99',
'core.pkg.js' => '5c737607',
'differential.pkg.css' => 'b8df73d4',
'differential.pkg.js' => '67c9ea4c',
@@ -30,7 +30,7 @@
'rsrc/css/aphront/notification.css' => '30240bd2',
'rsrc/css/aphront/panel-view.css' => '46923d46',
'rsrc/css/aphront/phabricator-nav-view.css' => 'f8a0c1bf',
- 'rsrc/css/aphront/table-view.css' => 'daa1f9df',
+ 'rsrc/css/aphront/table-view.css' => '205053cd',
'rsrc/css/aphront/tokenizer.css' => 'b52d0668',
'rsrc/css/aphront/tooltip.css' => 'e3f2412f',
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
@@ -520,7 +520,7 @@
'aphront-list-filter-view-css' => 'feb64255',
'aphront-multi-column-view-css' => 'fbc00ba3',
'aphront-panel-view-css' => '46923d46',
- 'aphront-table-view-css' => 'daa1f9df',
+ 'aphront-table-view-css' => '205053cd',
'aphront-tokenizer-control-css' => 'b52d0668',
'aphront-tooltip-css' => 'e3f2412f',
'aphront-typeahead-control-css' => '8779483d',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1714,6 +1714,7 @@
'ManiphestTaskFerretEngine' => 'applications/maniphest/search/ManiphestTaskFerretEngine.php',
'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php',
'ManiphestTaskGraph' => 'infrastructure/graph/ManiphestTaskGraph.php',
+ 'ManiphestTaskGraphController' => 'applications/maniphest/controller/ManiphestTaskGraphController.php',
'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php',
'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php',
'ManiphestTaskHasDuplicateTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasDuplicateTaskEdgeType.php',
@@ -7401,6 +7402,7 @@
'ManiphestTaskFerretEngine' => 'PhabricatorFerretEngine',
'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine',
'ManiphestTaskGraph' => 'PhabricatorObjectGraph',
+ 'ManiphestTaskGraphController' => 'ManiphestController',
'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType',
'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship',
'ManiphestTaskHasDuplicateTaskEdgeType' => 'PhabricatorEdgeType',
diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
--- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php
+++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
@@ -55,6 +55,7 @@
'subtask/(?P<id>[1-9]\d*)/' => 'ManiphestTaskSubtaskController',
),
'subpriority/' => 'ManiphestSubpriorityController',
+ 'graph/(?P<id>[1-9]\d*)/' => 'ManiphestTaskGraphController',
),
);
}
diff --git a/src/applications/maniphest/controller/ManiphestController.php b/src/applications/maniphest/controller/ManiphestController.php
--- a/src/applications/maniphest/controller/ManiphestController.php
+++ b/src/applications/maniphest/controller/ManiphestController.php
@@ -61,4 +61,102 @@
return $view;
}
+ final protected function newTaskGraphDropdownMenu(
+ ManiphestTask $task,
+ $has_parents,
+ $has_subtasks,
+ $include_standalone) {
+ $viewer = $this->getViewer();
+
+ $parents_uri = urisprintf(
+ '/?subtaskIDs=%d#R',
+ $task->getID());
+ $parents_uri = $this->getApplicationURI($parents_uri);
+
+ $subtasks_uri = urisprintf(
+ '/?parentIDs=%d#R',
+ $task->getID());
+ $subtasks_uri = $this->getApplicationURI($subtasks_uri);
+
+ $dropdown_menu = id(new PhabricatorActionListView())
+ ->setViewer($viewer)
+ ->addAction(
+ id(new PhabricatorActionView())
+ ->setHref($parents_uri)
+ ->setName(pht('Search Parent Tasks'))
+ ->setDisabled(!$has_parents)
+ ->setIcon('fa-chevron-circle-up'))
+ ->addAction(
+ id(new PhabricatorActionView())
+ ->setHref($subtasks_uri)
+ ->setName(pht('Search Subtasks'))
+ ->setDisabled(!$has_subtasks)
+ ->setIcon('fa-chevron-circle-down'));
+
+ if ($include_standalone) {
+ $standalone_uri = urisprintf('/graph/%d/', $task->getID());
+ $standalone_uri = $this->getApplicationURI($standalone_uri);
+
+ $dropdown_menu->addAction(
+ id(new PhabricatorActionView())
+ ->setHref($standalone_uri)
+ ->setName(pht('View Standalone Graph'))
+ ->setIcon('fa-code-fork'));
+ }
+
+ $graph_menu = id(new PHUIButtonView())
+ ->setTag('a')
+ ->setIcon('fa-search')
+ ->setText(pht('Search...'))
+ ->setDropdownMenu($dropdown_menu);
+
+ return $graph_menu;
+ }
+
+ final protected function newTaskGraphOverflowView(
+ ManiphestTask $task,
+ $overflow_message,
+ $include_standalone) {
+
+ $id = $task->getID();
+
+ if ($include_standalone) {
+ $standalone_uri = $this->getApplicationURI("graph/{$id}/");
+
+ $standalone_link = id(new PHUIButtonView())
+ ->setTag('a')
+ ->setHref($standalone_uri)
+ ->setColor(PHUIButtonView::GREY)
+ ->setIcon('fa-code-fork')
+ ->setText(pht('View Standalone Graph'));
+ } else {
+ $standalone_link = null;
+ }
+
+ $standalone_icon = id(new PHUIIconView())
+ ->setIcon('fa-exclamation-triangle', 'yellow')
+ ->addClass('object-graph-header-icon');
+
+ $standalone_view = phutil_tag(
+ 'div',
+ array(
+ 'class' => 'object-graph-header',
+ ),
+ array(
+ $standalone_link,
+ $standalone_icon,
+ phutil_tag(
+ 'div',
+ array(
+ 'class' => 'object-graph-header-message',
+ ),
+ array(
+ $overflow_message,
+ )),
+ ));
+
+ return $standalone_view;
+ }
+
+
}
diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
--- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php
+++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php
@@ -80,7 +80,8 @@
$related_tabs = array();
$graph_menu = null;
- $graph_limit = 100;
+ $graph_limit = 200;
+ $overflow_message = null;
$task_graph = id(new ManiphestTaskGraph())
->setViewer($viewer)
->setSeedPHID($task->getPHID())
@@ -96,61 +97,55 @@
$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 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);
+ $overflow_message = pht(
+ 'This task is directly connected to more than %s other tasks. '.
+ 'Use %s to browse parents or subtasks, or %s to show more of the '.
+ 'graph.',
+ new PhutilNumber($graph_limit),
+ phutil_tag('strong', array(), pht('Search...')),
+ phutil_tag('strong', array(), pht('View Standalone Graph')));
+
+ $graph_table = null;
} 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);
+
+ $overflow_message = pht(
+ 'This task is connected to more than %s other tasks. '.
+ 'Only direct parents and subtasks are shown here. Use '.
+ '%s to show more of the graph.',
+ new PhutilNumber($graph_limit),
+ phutil_tag('strong', array(), pht('View Standalone Graph')));
}
+
$graph_table = $task_graph->newGraphTable();
}
- $parents_uri = urisprintf(
- '/?subtaskIDs=%d#R',
- $task->getID());
- $parents_uri = $this->getApplicationURI($parents_uri);
-
- $subtasks_uri = urisprintf(
- '/?parentIDs=%d#R',
- $task->getID());
- $subtasks_uri = $this->getApplicationURI($subtasks_uri);
-
- $dropdown_menu = id(new PhabricatorActionListView())
- ->setViewer($viewer)
- ->addAction(
- id(new PhabricatorActionView())
- ->setHref($parents_uri)
- ->setName(pht('Search Parent Tasks'))
- ->setDisabled(!$has_parents)
- ->setIcon('fa-chevron-circle-up'))
- ->addAction(
- id(new PhabricatorActionView())
- ->setHref($subtasks_uri)
- ->setName(pht('Search Subtasks'))
- ->setDisabled(!$has_subtasks)
- ->setIcon('fa-chevron-circle-down'));
-
- $graph_menu = id(new PHUIButtonView())
- ->setTag('a')
- ->setIcon('fa-search')
- ->setText($search_text)
- ->setDropdownMenu($dropdown_menu);
+ if ($overflow_message) {
+ $overflow_view = $this->newTaskGraphOverflowView(
+ $task,
+ $overflow_message,
+ true);
+
+ $graph_table = array(
+ $overflow_view,
+ $graph_table,
+ );
+ }
+
+ $graph_menu = $this->newTaskGraphDropdownMenu(
+ $task,
+ $has_parents,
+ $has_subtasks,
+ true);
$related_tabs[] = id(new PHUITabView())
->setName(pht('Task Graph'))
diff --git a/src/applications/maniphest/controller/ManiphestTaskGraphController.php b/src/applications/maniphest/controller/ManiphestTaskGraphController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/controller/ManiphestTaskGraphController.php
@@ -0,0 +1,125 @@
+<?php
+
+final class ManiphestTaskGraphController
+ extends ManiphestController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+ $id = $request->getURIData('id');
+
+ $task = id(new ManiphestTaskQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->executeOne();
+ if (!$task) {
+ return new Aphront404Response();
+ }
+
+ $crumbs = $this->buildApplicationCrumbs()
+ ->addTextCrumb($task->getMonogram(), $task->getURI())
+ ->addTextCrumb(pht('Graph'))
+ ->setBorder(true);
+
+ $graph_limit = 2000;
+ $overflow_message = null;
+ $task_graph = id(new ManiphestTaskGraph())
+ ->setViewer($viewer)
+ ->setSeedPHID($task->getPHID())
+ ->setLimit($graph_limit)
+ ->loadGraph();
+ if (!$task_graph->isEmpty()) {
+ $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;
+
+ // 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) {
+ $overflow_message = pht(
+ 'This task is directly connected to more than %s other tasks, '.
+ 'which is too many tasks to display. Use %s to browse parents '.
+ 'or subtasks.',
+ new PhutilNumber($graph_limit),
+ phutil_tag('strong', array(), pht('Search...')));
+
+ $graph_table = null;
+ } 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);
+
+ $overflow_message = pht(
+ 'This task is connected to more than %s other tasks. '.
+ 'Only direct parents and subtasks are shown here.',
+ new PhutilNumber($graph_limit));
+ }
+
+ $graph_table = $task_graph->newGraphTable();
+ }
+
+ $graph_menu = $this->newTaskGraphDropdownMenu(
+ $task,
+ $has_parents,
+ $has_subtasks,
+ false);
+ } else {
+ $graph_menu = null;
+ $graph_table = null;
+
+ $overflow_message = pht(
+ 'This task has no parent tasks and no subtasks, so there is no '.
+ 'graph to draw.');
+ }
+
+ if ($overflow_message) {
+ $overflow_view = $this->newTaskGraphOverflowView(
+ $task,
+ $overflow_message,
+ false);
+
+ $graph_table = array(
+ $overflow_view,
+ $graph_table,
+ );
+ }
+
+ $header = id(new PHUIHeaderView())
+ ->setHeader(pht('Task Graph'));
+
+ if ($graph_menu) {
+ $header->addActionLink($graph_menu);
+ }
+
+ $tab_view = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
+ ->appendChild($graph_table);
+
+ $view = id(new PHUITwoColumnView())
+ ->setFooter($tab_view);
+
+ return $this->newPage()
+ ->setTitle(
+ array(
+ $task->getMonogram(),
+ pht('Graph'),
+ ))
+ ->setCrumbs($crumbs)
+ ->appendChild($view);
+ }
+
+
+}
diff --git a/webroot/rsrc/css/aphront/table-view.css b/webroot/rsrc/css/aphront/table-view.css
--- a/webroot/rsrc/css/aphront/table-view.css
+++ b/webroot/rsrc/css/aphront/table-view.css
@@ -327,3 +327,40 @@
.phui-object-box .aphront-table-view {
border: none;
}
+
+.object-graph-header {
+ padding: 8px 12px;
+ overflow: hidden;
+ background: {$lightyellow};
+ border-bottom: 1px solid {$lightblueborder};
+ vertical-align: middle;
+}
+
+.object-graph-header .object-graph-header-icon {
+ float: left;
+ margin-top: 10px;
+}
+
+.object-graph-header a.button {
+ float: right;
+}
+
+.object-graph-header-message {
+ margin: 8px 200px 8px 20px;
+}
+
+.device .object-graph-header .object-graph-header-icon {
+ display: none;
+}
+
+.device .object-graph-header-message {
+ clear: both;
+ margin: 0;
+}
+
+.device .object-graph-header a.button {
+ margin: 0 auto 12px;
+ display: block;
+ width: 180px;
+ float: none;
+}

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 1:09 AM (21 h, 37 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6790350
Default Alt Text
D20164.diff (15 KB)

Event Timeline