2016-07-01 17:50:16 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
final class ManiphestTaskGraph
|
|
|
|
extends PhabricatorObjectGraph {
|
|
|
|
|
2016-07-28 20:45:42 +02:00
|
|
|
private $seedMaps = array();
|
2019-03-22 17:57:12 +01:00
|
|
|
private $isStandalone;
|
2016-07-28 20:45:42 +02:00
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
protected function getEdgeTypes() {
|
|
|
|
return array(
|
|
|
|
ManiphestTaskDependedOnByTaskEdgeType::EDGECONST,
|
|
|
|
ManiphestTaskDependsOnTaskEdgeType::EDGECONST,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getParentEdgeType() {
|
|
|
|
return ManiphestTaskDependsOnTaskEdgeType::EDGECONST;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function newQuery() {
|
|
|
|
return new ManiphestTaskQuery();
|
|
|
|
}
|
|
|
|
|
2016-07-01 21:53:41 +02:00
|
|
|
protected function isClosed($object) {
|
|
|
|
return $object->isClosed();
|
|
|
|
}
|
|
|
|
|
2019-03-22 17:57:12 +01:00
|
|
|
public function setIsStandalone($is_standalone) {
|
|
|
|
$this->isStandalone = $is_standalone;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIsStandalone() {
|
|
|
|
return $this->isStandalone;
|
|
|
|
}
|
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
protected function newTableRow($phid, $object, $trace) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
2017-10-04 19:54:42 +02:00
|
|
|
Javelin::initBehavior('phui-hovercards');
|
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
if ($object) {
|
|
|
|
$status = $object->getStatus();
|
|
|
|
$priority = $object->getPriority();
|
|
|
|
$status_icon = ManiphestTaskStatus::getStatusIcon($status);
|
|
|
|
$status_name = ManiphestTaskStatus::getTaskStatusName($status);
|
|
|
|
|
2016-07-01 21:59:15 +02:00
|
|
|
$priority_color = ManiphestTaskPriority::getTaskPriorityColor($priority);
|
|
|
|
if ($object->isClosed()) {
|
|
|
|
$priority_color = 'grey';
|
|
|
|
}
|
2016-07-01 17:50:16 +02:00
|
|
|
|
|
|
|
$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'));
|
|
|
|
}
|
|
|
|
|
2017-10-04 19:54:42 +02:00
|
|
|
$link = javelin_tag(
|
2016-07-01 17:50:16 +02:00
|
|
|
'a',
|
|
|
|
array(
|
|
|
|
'href' => $object->getURI(),
|
2017-10-04 19:54:42 +02:00
|
|
|
'sigil' => 'hovercard',
|
|
|
|
'meta' => array(
|
2021-02-13 21:51:06 +01:00
|
|
|
'hovercardSpec' => array(
|
|
|
|
'objectPHID' => $object->getPHID(),
|
|
|
|
),
|
2017-10-04 19:54:42 +02:00
|
|
|
),
|
2016-07-01 17:50:16 +02:00
|
|
|
),
|
2017-10-04 19:54:42 +02:00
|
|
|
$object->getTitle());
|
2016-07-01 22:30:42 +02:00
|
|
|
|
|
|
|
$link = array(
|
2016-07-28 20:45:42 +02:00
|
|
|
phutil_tag(
|
|
|
|
'span',
|
|
|
|
array(
|
|
|
|
'class' => 'object-name',
|
|
|
|
),
|
|
|
|
$object->getMonogram()),
|
2016-07-01 22:30:42 +02:00
|
|
|
' ',
|
|
|
|
$link,
|
|
|
|
);
|
2019-09-27 19:51:13 +02:00
|
|
|
|
|
|
|
$subtype_tag = null;
|
|
|
|
|
|
|
|
$subtype = $object->newSubtypeObject();
|
|
|
|
if ($subtype && $subtype->hasTagView()) {
|
|
|
|
$subtype_tag = $subtype->newTagView()
|
|
|
|
->setSlimShady(true);
|
|
|
|
}
|
2016-07-01 17:50:16 +02:00
|
|
|
} else {
|
|
|
|
$status = null;
|
|
|
|
$assigned = null;
|
2019-09-27 19:51:13 +02:00
|
|
|
$subtype_tag = null;
|
2016-07-01 17:50:16 +02:00
|
|
|
$link = $viewer->renderHandle($phid);
|
|
|
|
}
|
|
|
|
|
2016-07-29 16:02:36 +02:00
|
|
|
if ($this->isParentTask($phid)) {
|
2016-07-28 20:45:42 +02:00
|
|
|
$marker = 'fa-chevron-circle-up bluegrey';
|
|
|
|
$marker_tip = pht('Direct Parent');
|
2016-07-29 16:02:36 +02:00
|
|
|
} else if ($this->isChildTask($phid)) {
|
2016-07-28 20:45:42 +02:00
|
|
|
$marker = 'fa-chevron-circle-down bluegrey';
|
|
|
|
$marker_tip = pht('Direct Subtask');
|
|
|
|
} else {
|
|
|
|
$marker = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($marker) {
|
|
|
|
$marker = id(new PHUIIconView())
|
|
|
|
->setIcon($marker)
|
|
|
|
->addSigil('has-tooltip')
|
|
|
|
->setMetadata(
|
|
|
|
array(
|
|
|
|
'tip' => $marker_tip,
|
|
|
|
'align' => 'E',
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
return array(
|
2016-07-28 20:45:42 +02:00
|
|
|
$marker,
|
2016-07-01 17:50:16 +02:00
|
|
|
$trace,
|
|
|
|
$status,
|
2019-09-27 19:51:13 +02:00
|
|
|
$subtype_tag,
|
2016-07-01 17:50:16 +02:00
|
|
|
$assigned,
|
|
|
|
$link,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function newTable(AphrontTableView $table) {
|
2019-09-27 19:51:13 +02:00
|
|
|
$subtype_map = id(new ManiphestTask())->newEditEngineSubtypeMap();
|
|
|
|
$has_subtypes = ($subtype_map->getCount() > 1);
|
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
return $table
|
|
|
|
->setHeaders(
|
|
|
|
array(
|
2016-07-28 20:45:42 +02:00
|
|
|
null,
|
2016-07-01 17:50:16 +02:00
|
|
|
null,
|
|
|
|
pht('Status'),
|
2019-09-27 19:51:13 +02:00
|
|
|
pht('Subtype'),
|
2016-07-01 17:50:16 +02:00
|
|
|
pht('Assigned'),
|
|
|
|
pht('Task'),
|
|
|
|
))
|
|
|
|
->setColumnClasses(
|
|
|
|
array(
|
2016-07-28 20:45:42 +02:00
|
|
|
'nudgeright',
|
2016-07-01 17:50:16 +02:00
|
|
|
'threads',
|
2016-07-01 21:53:41 +02:00
|
|
|
'graph-status',
|
2016-07-01 17:50:16 +02:00
|
|
|
null,
|
2019-09-27 19:51:13 +02:00
|
|
|
null,
|
2016-07-01 22:30:42 +02:00
|
|
|
'wide pri object-link',
|
2016-11-07 20:05:43 +01:00
|
|
|
))
|
|
|
|
->setColumnVisibility(
|
|
|
|
array(
|
|
|
|
true,
|
|
|
|
!$this->getRenderOnlyAdjacentNodes(),
|
2019-09-27 19:51:13 +02:00
|
|
|
true,
|
|
|
|
$has_subtypes,
|
2019-03-22 17:57:12 +01:00
|
|
|
))
|
|
|
|
->setDeviceVisibility(
|
|
|
|
array(
|
|
|
|
true,
|
|
|
|
|
|
|
|
// On mobile, we only show the actual graph drawing if we're on the
|
|
|
|
// standalone page, since it can take over the screen otherwise.
|
|
|
|
$this->getIsStandalone(),
|
2019-09-27 19:51:13 +02:00
|
|
|
true,
|
|
|
|
|
|
|
|
// On mobile, don't show subtypes since they're relatively less
|
|
|
|
// important and we're more pressured for space.
|
|
|
|
false,
|
2016-07-01 17:50:16 +02:00
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2016-07-29 16:02:36 +02:00
|
|
|
private function isParentTask($task_phid) {
|
2016-07-28 20:45:42 +02:00
|
|
|
$map = $this->getSeedMap(ManiphestTaskDependedOnByTaskEdgeType::EDGECONST);
|
2016-07-29 16:02:36 +02:00
|
|
|
return isset($map[$task_phid]);
|
2016-07-28 20:45:42 +02:00
|
|
|
}
|
|
|
|
|
2016-07-29 16:02:36 +02:00
|
|
|
private function isChildTask($task_phid) {
|
2016-07-28 20:45:42 +02:00
|
|
|
$map = $this->getSeedMap(ManiphestTaskDependsOnTaskEdgeType::EDGECONST);
|
2016-07-29 16:02:36 +02:00
|
|
|
return isset($map[$task_phid]);
|
2016-07-28 20:45:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private function getSeedMap($type) {
|
|
|
|
if (!isset($this->seedMaps[$type])) {
|
|
|
|
$maps = $this->getEdges($type);
|
|
|
|
$phids = idx($maps, $this->getSeedPHID(), array());
|
|
|
|
$phids = array_fuse($phids);
|
|
|
|
$this->seedMaps[$type] = $phids;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->seedMaps[$type];
|
|
|
|
}
|
2016-07-28 22:54:10 +02:00
|
|
|
|
|
|
|
protected function newEllipsisRow() {
|
|
|
|
return array(
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
null,
|
2019-09-27 19:51:13 +02:00
|
|
|
null,
|
2016-07-28 22:54:10 +02:00
|
|
|
pht("\xC2\xB7 \xC2\xB7 \xC2\xB7"),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-07-01 17:50:16 +02:00
|
|
|
}
|