mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Add "Oldest" and "Fixed Last 7d" columns to Maniphest reports
Summary: Part of a user feature request, see T994. Test Plan: Looked at data in columns, seemed to line up with reality. Reviewers: btrahan Reviewed By: btrahan CC: aran, epriestley, sandra Maniphest Tasks: T994 Differential Revision: https://secure.phabricator.com/D1944
This commit is contained in:
parent
6a13b3ea7e
commit
7cfe006c7f
3 changed files with 160 additions and 1 deletions
|
@ -39,6 +39,18 @@ final class ManiphestTaskPriority extends ManiphestConstants {
|
|||
);
|
||||
}
|
||||
|
||||
public static function getTaskBriefPriorityMap() {
|
||||
return array(
|
||||
self::PRIORITY_UNBREAK_NOW => 'Unbreak!',
|
||||
self::PRIORITY_TRIAGE => 'Triage',
|
||||
self::PRIORITY_HIGH => 'High',
|
||||
self::PRIORITY_NORMAL => 'Normal',
|
||||
self::PRIORITY_LOW => 'Low',
|
||||
self::PRIORITY_WISH => 'Wish',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public static function getLoadMap() {
|
||||
return array(
|
||||
self::PRIORITY_UNBREAK_NOW => 16,
|
||||
|
|
|
@ -371,6 +371,8 @@ final class ManiphestReportController extends ManiphestController {
|
|||
|
||||
$tasks = $query->execute();
|
||||
|
||||
$recently_closed = $this->loadRecentlyClosedTasks();
|
||||
|
||||
$date = phabricator_date(time(), $user);
|
||||
|
||||
switch ($this->view) {
|
||||
|
@ -378,6 +380,11 @@ final class ManiphestReportController extends ManiphestController {
|
|||
$result = mgroup($tasks, 'getOwnerPHID');
|
||||
$leftover = idx($result, '', array());
|
||||
unset($result['']);
|
||||
|
||||
$result_closed = mgroup($recently_closed, 'getOwnerPHID');
|
||||
$leftover_closed = idx($result_closed, '', array());
|
||||
unset($result_closed['']);
|
||||
|
||||
$leftover_name = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
|
@ -390,6 +397,7 @@ final class ManiphestReportController extends ManiphestController {
|
|||
break;
|
||||
case 'project':
|
||||
$result = array();
|
||||
$leftover = array();
|
||||
foreach ($tasks as $task) {
|
||||
$phids = $task->getProjectPHIDs();
|
||||
if ($phids) {
|
||||
|
@ -400,6 +408,20 @@ final class ManiphestReportController extends ManiphestController {
|
|||
$leftover[] = $task;
|
||||
}
|
||||
}
|
||||
|
||||
$result_closed = array();
|
||||
$leftover_closed = array();
|
||||
foreach ($recently_closed as $task) {
|
||||
$phids = $task->getProjectPHIDs();
|
||||
if ($phids) {
|
||||
foreach ($phids as $project_phid) {
|
||||
$result_closed[$project_phid][] = $task;
|
||||
}
|
||||
} else {
|
||||
$leftover_closed[] = $task;
|
||||
}
|
||||
}
|
||||
|
||||
$leftover_name = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
|
@ -418,6 +440,9 @@ final class ManiphestReportController extends ManiphestController {
|
|||
|
||||
$order = $request->getStr('order', 'name');
|
||||
|
||||
require_celerity_resource('aphront-tooltip-css');
|
||||
Javelin::initBehavior('phabricator-tooltips', array());
|
||||
|
||||
$rows = array();
|
||||
$pri_total = array();
|
||||
foreach (array_merge($handles, array(null)) as $handle) {
|
||||
|
@ -429,11 +454,14 @@ final class ManiphestReportController extends ManiphestController {
|
|||
'href' => $link.$handle->getPHID(),
|
||||
),
|
||||
phutil_escape_html($handle->getName()));
|
||||
$closed = idx($result_closed, $handle->getPHID(), array());
|
||||
} else {
|
||||
$tasks = $leftover;
|
||||
$name = $leftover_name;
|
||||
$closed = $leftover_closed;
|
||||
}
|
||||
|
||||
$taskv = $tasks;
|
||||
$tasks = mgroup($tasks, 'getPriority');
|
||||
|
||||
$row = array();
|
||||
|
@ -450,6 +478,31 @@ final class ManiphestReportController extends ManiphestController {
|
|||
}
|
||||
$row[] = number_format($total);
|
||||
|
||||
$row[] = $this->renderOldest($taskv);
|
||||
|
||||
$normal_or_better = array();
|
||||
foreach ($taskv as $id => $task) {
|
||||
if ($task->getPriority() < ManiphestTaskPriority::PRIORITY_NORMAL) {
|
||||
continue;
|
||||
}
|
||||
$normal_or_better[$id] = $task;
|
||||
}
|
||||
|
||||
$row[] = $this->renderOldest($normal_or_better);
|
||||
|
||||
if ($closed) {
|
||||
$task_ids = implode(',', mpull($closed, 'getID'));
|
||||
$row[] = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/maniphest/view/custom/?s=oc&tasks='.$task_ids,
|
||||
'target' => '_blank',
|
||||
),
|
||||
phutil_escape_html(number_format(count($closed))));
|
||||
} else {
|
||||
$row[] = '-';
|
||||
}
|
||||
|
||||
switch ($order) {
|
||||
case 'total':
|
||||
$row['sort'] = $total;
|
||||
|
@ -470,12 +523,38 @@ final class ManiphestReportController extends ManiphestController {
|
|||
|
||||
$cname = array($col_header);
|
||||
$cclass = array('pri right wide');
|
||||
foreach (ManiphestTaskPriority::getTaskPriorityMap() as $pri => $label) {
|
||||
$pri_map = ManiphestTaskPriority::getTaskBriefPriorityMap();
|
||||
foreach ($pri_map as $pri => $label) {
|
||||
$cname[] = $label;
|
||||
$cclass[] = 'n';
|
||||
}
|
||||
$cname[] = 'Total';
|
||||
$cclass[] = 'n';
|
||||
$cname[] = javelin_render_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => 'Oldest open task.',
|
||||
'size' => 200,
|
||||
),
|
||||
),
|
||||
'Oldest (All)');
|
||||
$cclass[] = 'n';
|
||||
$cname[] = javelin_render_tag(
|
||||
'span',
|
||||
array(
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => 'Oldest open task, excluding those with Low or Wishlist '.
|
||||
'priority.',
|
||||
'size' => 200,
|
||||
),
|
||||
),
|
||||
'Oldest (Pri)');
|
||||
$cclass[] = 'n';
|
||||
$cname[] = 'Closed Last 7d';
|
||||
$cclass[] = 'n';
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders($cname);
|
||||
|
@ -505,4 +584,71 @@ final class ManiphestReportController extends ManiphestController {
|
|||
return array($filter, $panel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load all the tasks that have been recently closed.
|
||||
*/
|
||||
private function loadRecentlyClosedTasks() {
|
||||
$recent_window = (60 * 60 * 24 * 7);
|
||||
|
||||
$table = new ManiphestTask();
|
||||
$xtable = new ManiphestTransaction();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$tasks = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT t.* FROM %T t JOIN %T x ON x.taskID = t.id
|
||||
WHERE t.status != 0
|
||||
AND x.oldValue IN (null, %s, %s)
|
||||
AND x.newValue NOT IN (%s, %s)
|
||||
AND t.dateModified >= %d
|
||||
AND x.dateCreated >= %d',
|
||||
$table->getTableName(),
|
||||
$xtable->getTableName(),
|
||||
|
||||
// TODO: Gross. This table is not meant to be queried like this. Build
|
||||
// real stats tables.
|
||||
json_encode((int)ManiphestTaskStatus::STATUS_OPEN),
|
||||
json_encode((string)ManiphestTaskStatus::STATUS_OPEN),
|
||||
json_encode((int)ManiphestTaskStatus::STATUS_OPEN),
|
||||
json_encode((string)ManiphestTaskStatus::STATUS_OPEN),
|
||||
|
||||
(time() - $recent_window),
|
||||
(time() - $recent_window));
|
||||
|
||||
return id(new ManiphestTask())->loadAllFromArray($tasks);
|
||||
}
|
||||
|
||||
private function renderOldest(array $tasks) {
|
||||
$oldest = null;
|
||||
foreach ($tasks as $id => $task) {
|
||||
if (($oldest === null) ||
|
||||
($task->getDateCreated() < $tasks[$oldest]->getDateCreated())) {
|
||||
$oldest = $id;
|
||||
}
|
||||
}
|
||||
|
||||
if ($oldest === null) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$oldest = $tasks[$oldest];
|
||||
|
||||
$age = (time() - $oldest->getDateCreated());
|
||||
$age = number_format($age / (24 * 60 * 60)).' d';
|
||||
$age = phutil_escape_html($age);
|
||||
|
||||
return javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/T'.$oldest->getID(),
|
||||
'sigil' => 'has-tooltip',
|
||||
'meta' => array(
|
||||
'tip' => 'T'.$oldest->getID().': '.$oldest->getTitle(),
|
||||
),
|
||||
'target' => '_blank',
|
||||
),
|
||||
$age);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ phutil_require_module('phabricator', 'applications/maniphest/storage/transaction
|
|||
phutil_require_module('phabricator', 'applications/phid/handle/data');
|
||||
phutil_require_module('phabricator', 'infrastructure/celerity/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/api');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
|
|
Loading…
Reference in a new issue