diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 80f5cc54eb..7177364d2f 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1430,6 +1430,7 @@ phutil_register_library_map(array( 'ManiphestTaskEditBulkJobType' => 'applications/maniphest/bulk/ManiphestTaskEditBulkJobType.php', 'ManiphestTaskEditController' => 'applications/maniphest/controller/ManiphestTaskEditController.php', 'ManiphestTaskFulltextEngine' => 'applications/maniphest/search/ManiphestTaskFulltextEngine.php', + 'ManiphestTaskGraph' => 'infrastructure/graph/ManiphestTaskGraph.php', 'ManiphestTaskHasCommitEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasCommitEdgeType.php', 'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php', 'ManiphestTaskHasDuplicateTaskEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasDuplicateTaskEdgeType.php', @@ -5947,6 +5948,7 @@ phutil_register_library_map(array( 'ManiphestTaskEditBulkJobType' => 'PhabricatorWorkerBulkJobType', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskFulltextEngine' => 'PhabricatorFulltextEngine', + 'ManiphestTaskGraph' => 'PhabricatorObjectGraph', 'ManiphestTaskHasCommitEdgeType' => 'PhabricatorEdgeType', 'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship', 'ManiphestTaskHasDuplicateTaskEdgeType' => 'PhabricatorEdgeType', diff --git a/src/applications/maniphest/controller/ManiphestTaskDetailController.php b/src/applications/maniphest/controller/ManiphestTaskDetailController.php index 1a59bd2fd8..f544fa6b2c 100644 --- a/src/applications/maniphest/controller/ManiphestTaskDetailController.php +++ b/src/applications/maniphest/controller/ManiphestTaskDetailController.php @@ -31,8 +31,6 @@ final class ManiphestTaskDetailController extends ManiphestController { ->setTargetObject($task); $e_commit = ManiphestTaskHasCommitEdgeType::EDGECONST; - $e_dep_on = ManiphestTaskDependsOnTaskEdgeType::EDGECONST; - $e_dep_by = ManiphestTaskDependedOnByTaskEdgeType::EDGECONST; $e_rev = ManiphestTaskHasRevisionEdgeType::EDGECONST; $e_mock = ManiphestTaskHasMockEdgeType::EDGECONST; @@ -43,8 +41,6 @@ final class ManiphestTaskDetailController extends ManiphestController { ->withEdgeTypes( array( $e_commit, - $e_dep_on, - $e_dep_by, $e_rev, $e_mock, )); @@ -91,6 +87,15 @@ final class ManiphestTaskDetailController extends ManiphestController { ->addPropertySection(pht('Description'), $description) ->addPropertySection(pht('Details'), $details); + $task_graph = id(new ManiphestTaskGraph()) + ->setViewer($viewer) + ->setSeedPHID($task->getPHID()) + ->loadGraph(); + if (!$task_graph->isEmpty()) { + $graph_table = $task_graph->newGraphTable(); + $view->addPropertySection(pht('Task Graph'), $graph_table); + } + return $this->newPage() ->setTitle($title) ->setCrumbs($crumbs) @@ -186,9 +191,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $edit_uri = $this->getApplicationURI($edit_uri); } - $task_submenu = array(); - - $task_submenu[] = id(new PhabricatorActionView()) + $subtask_item = id(new PhabricatorActionView()) ->setName(pht('Create Subtask')) ->setHref($edit_uri) ->setIcon('fa-level-down') @@ -200,6 +203,7 @@ final class ManiphestTaskDetailController extends ManiphestController { $task); $submenu_actions = array( + $subtask_item, ManiphestTaskHasParentRelationship::RELATIONSHIPKEY, ManiphestTaskHasSubtaskRelationship::RELATIONSHIPKEY, ManiphestTaskMergeInRelationship::RELATIONSHIPKEY, @@ -280,10 +284,6 @@ final class ManiphestTaskDetailController extends ManiphestController { } $edge_types = array( - ManiphestTaskDependedOnByTaskEdgeType::EDGECONST - => pht('Parent Tasks'), - ManiphestTaskDependsOnTaskEdgeType::EDGECONST - => pht('Subtasks'), ManiphestTaskHasRevisionEdgeType::EDGECONST => pht('Differential Revisions'), ManiphestTaskHasMockEdgeType::EDGECONST diff --git a/src/applications/maniphest/storage/ManiphestTask.php b/src/applications/maniphest/storage/ManiphestTask.php index 9ac7190782..4fb9fc2861 100644 --- a/src/applications/maniphest/storage/ManiphestTask.php +++ b/src/applications/maniphest/storage/ManiphestTask.php @@ -179,6 +179,10 @@ final class ManiphestTask extends ManiphestDAO return 'T'.$this->getID(); } + public function getURI() { + return '/'.$this->getMonogram(); + } + public function attachGroupByProjectPHID($phid) { $this->groupByProjectPHID = $phid; return $this; diff --git a/src/applications/search/relationship/PhabricatorObjectRelationshipList.php b/src/applications/search/relationship/PhabricatorObjectRelationshipList.php index 31d05fa939..02917bd57d 100644 --- a/src/applications/search/relationship/PhabricatorObjectRelationshipList.php +++ b/src/applications/search/relationship/PhabricatorObjectRelationshipList.php @@ -52,6 +52,12 @@ final class PhabricatorObjectRelationshipList extends Phobject { $actions = array(); foreach ($keys as $key) { + // If we're passed a menu item, just include it verbatim. + if ($key instanceof PhabricatorActionView) { + $actions[] = $key; + continue; + } + $relationship = $this->getRelationship($key); if (!$relationship) { throw new Exception( diff --git a/src/infrastructure/diff/view/PHUIDiffGraphView.php b/src/infrastructure/diff/view/PHUIDiffGraphView.php index 02893cc5d4..11f93efc51 100644 --- a/src/infrastructure/diff/view/PHUIDiffGraphView.php +++ b/src/infrastructure/diff/view/PHUIDiffGraphView.php @@ -137,12 +137,31 @@ final class PHUIDiffGraphView extends Phobject { ); } - // If this is the last page in history, replace the "o" with an "x" so we - // do not draw a connecting line downward, and replace "^" with an "X" for - // repositories with exactly one commit. + // If this is the last page in history, replace any "o" characters at the + // bottom of columns with "x" characters so we do not draw a connecting + // line downward, and replace "^" with an "X" for repositories with + // exactly one commit. if ($this->getIsTail() && $graph) { + $terminated = array(); + foreach (array_reverse(array_keys($graph)) as $key) { + $line = $graph[$key]['line']; + $len = strlen($line); + for ($ii = 0; $ii < $len; $ii++) { + if (isset($terminated[$ii])) { + continue; + } + + $c = $line[$ii]; + if ($c == 'o') { + $terminated[$ii] = true; + $graph[$key]['line'][$ii] = 'x'; + } else if ($c != ' ') { + $terminated[$ii] = true; + } + } + } + $last = array_pop($graph); - $last['line'] = str_replace('o', 'x', $last['line']); $last['line'] = str_replace('^', 'X', $last['line']); $graph[] = $last; } diff --git a/src/infrastructure/graph/ManiphestTaskGraph.php b/src/infrastructure/graph/ManiphestTaskGraph.php new file mode 100644 index 0000000000..32cb45fa49 --- /dev/null +++ b/src/infrastructure/graph/ManiphestTaskGraph.php @@ -0,0 +1,87 @@ +getViewer(); + + if ($object) { + $status = $object->getStatus(); + $priority = $object->getPriority(); + $status_icon = ManiphestTaskStatus::getStatusIcon($status); + $status_name = ManiphestTaskStatus::getTaskStatusName($status); + $priority_color = ManiphestTaskPriority::getTaskPriorityColor($priority); + + + $status = array( + id(new PHUIIconView())->setIcon($status_icon, $priority_color), + ' ', + $status_name, + ); + + $owner_phid = $object->getOwnerPHID(); + if ($owner_phid) { + $assigned = $viewer->renderHandle($owner_phid); + } else { + $assigned = phutil_tag('em', array(), pht('None')); + } + + $link = phutil_tag( + 'a', + array( + 'href' => $object->getURI(), + ), + array( + $object->getMonogram(), + ' ', + $object->getTitle(), + )); + } else { + $status = null; + $assigned = null; + $link = $viewer->renderHandle($phid); + } + + return array( + $trace, + $status, + $assigned, + $link, + ); + } + + protected function newTable(AphrontTableView $table) { + return $table + ->setHeaders( + array( + null, + pht('Status'), + pht('Assigned'), + pht('Task'), + )) + ->setColumnClasses( + array( + 'threads', + null, + null, + 'wide', + )); + } + +} diff --git a/src/infrastructure/graph/PhabricatorObjectGraph.php b/src/infrastructure/graph/PhabricatorObjectGraph.php index 943ddaad29..2580512eb6 100644 --- a/src/infrastructure/graph/PhabricatorObjectGraph.php +++ b/src/infrastructure/graph/PhabricatorObjectGraph.php @@ -55,6 +55,8 @@ abstract class PhabricatorObjectGraph $map = array(); foreach ($nodes as $node) { + $map[$node] = array(); + foreach ($edge_types as $edge_type) { $dst_phids = $query->getDestinationPHIDs( array($node),