Changeset View
Changeset View
Standalone View
Standalone View
src/applications/maniphest/controller/ManiphestReportController.php
<?php | <?php | ||||
final class ManiphestReportController extends ManiphestController { | final class ManiphestReportController extends ManiphestController { | ||||
private $view; | private $view; | ||||
public function willProcessRequest(array $data) { | public function handleRequest(AphrontRequest $request) { | ||||
$this->view = idx($data, 'view'); | $viewer = $this->getViewer(); | ||||
} | $this->view = $request->getURIData('view'); | ||||
public function processRequest() { | |||||
$request = $this->getRequest(); | |||||
$user = $request->getUser(); | |||||
if ($request->isFormPost()) { | if ($request->isFormPost()) { | ||||
$uri = $request->getRequestURI(); | $uri = $request->getRequestURI(); | ||||
$project = head($request->getArr('set_project')); | $project = head($request->getArr('set_project')); | ||||
$project = nonempty($project, null); | $project = nonempty($project, null); | ||||
$uri = $uri->alter('project', $project); | $uri = $uri->alter('project', $project); | ||||
Show All 37 Lines | return $this->buildApplicationPage( | ||||
array( | array( | ||||
'title' => pht('Maniphest Reports'), | 'title' => pht('Maniphest Reports'), | ||||
'device' => false, | 'device' => false, | ||||
)); | )); | ||||
} | } | ||||
public function renderBurn() { | public function renderBurn() { | ||||
$request = $this->getRequest(); | $request = $this->getRequest(); | ||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$handle = null; | $handle = null; | ||||
$project_phid = $request->getStr('project'); | $project_phid = $request->getStr('project'); | ||||
if ($project_phid) { | if ($project_phid) { | ||||
$phids = array($project_phid); | $phids = array($project_phid); | ||||
$handles = $this->loadViewerHandles($phids); | $handles = $this->loadViewerHandles($phids); | ||||
$handle = $handles[$project_phid]; | $handle = $handles[$project_phid]; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | foreach ($data as $key => $row) { | ||||
if (!$is_open && !$is_close) { | if (!$is_open && !$is_close) { | ||||
// This is either some kind of bogus event, or a resolution change | // This is either some kind of bogus event, or a resolution change | ||||
// (e.g., resolved -> invalid). Just skip it. | // (e.g., resolved -> invalid). Just skip it. | ||||
continue; | continue; | ||||
} | } | ||||
$day_bucket = phabricator_format_local_time( | $day_bucket = phabricator_format_local_time( | ||||
$row['dateCreated'], | $row['dateCreated'], | ||||
$user, | $viewer, | ||||
'Yz'); | 'Yz'); | ||||
$day_buckets[$day_bucket] = $row['dateCreated']; | $day_buckets[$day_bucket] = $row['dateCreated']; | ||||
if (empty($stats[$day_bucket])) { | if (empty($stats[$day_bucket])) { | ||||
$stats[$day_bucket] = array( | $stats[$day_bucket] = array( | ||||
'open' => 0, | 'open' => 0, | ||||
'close' => 0, | 'close' => 0, | ||||
); | ); | ||||
} | } | ||||
Show All 17 Lines | public function renderBurn() { | ||||
$last = last_key($stats) - 1; | $last = last_key($stats) - 1; | ||||
$period = $template; | $period = $template; | ||||
foreach ($stats as $bucket => $info) { | foreach ($stats as $bucket => $info) { | ||||
$epoch = $day_buckets[$bucket]; | $epoch = $day_buckets[$bucket]; | ||||
$week_bucket = phabricator_format_local_time( | $week_bucket = phabricator_format_local_time( | ||||
$epoch, | $epoch, | ||||
$user, | $viewer, | ||||
'YW'); | 'YW'); | ||||
if ($week_bucket != $last_week) { | if ($week_bucket != $last_week) { | ||||
if ($week) { | if ($week) { | ||||
$rows[] = $this->formatBurnRow( | $rows[] = $this->formatBurnRow( | ||||
pht('Week of %s', phabricator_date($last_week_epoch, $user)), | pht('Week of %s', phabricator_date($last_week_epoch, $viewer)), | ||||
$week); | $week); | ||||
$rowc[] = 'week'; | $rowc[] = 'week'; | ||||
} | } | ||||
$week = $template; | $week = $template; | ||||
$last_week = $week_bucket; | $last_week = $week_bucket; | ||||
$last_week_epoch = $epoch; | $last_week_epoch = $epoch; | ||||
} | } | ||||
$month_bucket = phabricator_format_local_time( | $month_bucket = phabricator_format_local_time( | ||||
$epoch, | $epoch, | ||||
$user, | $viewer, | ||||
'Ym'); | 'Ym'); | ||||
if ($month_bucket != $last_month) { | if ($month_bucket != $last_month) { | ||||
if ($month) { | if ($month) { | ||||
$rows[] = $this->formatBurnRow( | $rows[] = $this->formatBurnRow( | ||||
phabricator_format_local_time($last_month_epoch, $user, 'F, Y'), | phabricator_format_local_time($last_month_epoch, $viewer, 'F, Y'), | ||||
$month); | $month); | ||||
$rowc[] = 'month'; | $rowc[] = 'month'; | ||||
} | } | ||||
$month = $template; | $month = $template; | ||||
$last_month = $month_bucket; | $last_month = $month_bucket; | ||||
$last_month_epoch = $epoch; | $last_month_epoch = $epoch; | ||||
} | } | ||||
$rows[] = $this->formatBurnRow(phabricator_date($epoch, $user), $info); | $rows[] = $this->formatBurnRow(phabricator_date($epoch, $viewer), $info); | ||||
$rowc[] = null; | $rowc[] = null; | ||||
$week['open'] += $info['open']; | $week['open'] += $info['open']; | ||||
$week['close'] += $info['close']; | $week['close'] += $info['close']; | ||||
$month['open'] += $info['open']; | $month['open'] += $info['open']; | ||||
$month['close'] += $info['close']; | $month['close'] += $info['close']; | ||||
$period['open'] += $info['open']; | $period['open'] += $info['open']; | ||||
$period['close'] += $info['close']; | $period['close'] += $info['close']; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Lines | Javelin::initBehavior('line-chart', array( | ||||
'yformat' => 'int', | 'yformat' => 'int', | ||||
)); | )); | ||||
return array($filter, $chart, $panel); | return array($filter, $chart, $panel); | ||||
} | } | ||||
private function renderReportFilters(array $tokens, $has_window) { | private function renderReportFilters(array $tokens, $has_window) { | ||||
$request = $this->getRequest(); | $request = $this->getRequest(); | ||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$form = id(new AphrontFormView()) | $form = id(new AphrontFormView()) | ||||
->setUser($user) | ->setUser($viewer) | ||||
->appendControl( | ->appendControl( | ||||
id(new AphrontFormTokenizerControl()) | id(new AphrontFormTokenizerControl()) | ||||
->setDatasource(new PhabricatorProjectDatasource()) | ->setDatasource(new PhabricatorProjectDatasource()) | ||||
->setLabel(pht('Project')) | ->setLabel(pht('Project')) | ||||
->setLimit(1) | ->setLimit(1) | ||||
->setName('set_project') | ->setName('set_project') | ||||
// TODO: This is silly, but this is Maniphest reports. | // TODO: This is silly, but this is Maniphest reports. | ||||
->setValue(mpull($tokens, 'getPHID'))); | ->setValue(mpull($tokens, 'getPHID'))); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | return array( | ||||
number_format($info['open']), | number_format($info['open']), | ||||
number_format($info['close']), | number_format($info['close']), | ||||
$fmt, | $fmt, | ||||
); | ); | ||||
} | } | ||||
public function renderOpenTasks() { | public function renderOpenTasks() { | ||||
$request = $this->getRequest(); | $request = $this->getRequest(); | ||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$query = id(new ManiphestTaskQuery()) | $query = id(new ManiphestTaskQuery()) | ||||
->setViewer($user) | ->setViewer($viewer) | ||||
->withStatuses(ManiphestTaskStatus::getOpenStatusConstants()); | ->withStatuses(ManiphestTaskStatus::getOpenStatusConstants()); | ||||
switch ($this->view) { | switch ($this->view) { | ||||
case 'project': | case 'project': | ||||
$query->needProjectPHIDs(true); | $query->needProjectPHIDs(true); | ||||
break; | break; | ||||
} | } | ||||
Show All 9 Lines | if ($project_phid) { | ||||
PhabricatorQueryConstraint::OPERATOR_OR, | PhabricatorQueryConstraint::OPERATOR_OR, | ||||
$phids); | $phids); | ||||
} | } | ||||
$tasks = $query->execute(); | $tasks = $query->execute(); | ||||
$recently_closed = $this->loadRecentlyClosedTasks(); | $recently_closed = $this->loadRecentlyClosedTasks(); | ||||
$date = phabricator_date(time(), $user); | $date = phabricator_date(time(), $viewer); | ||||
switch ($this->view) { | switch ($this->view) { | ||||
case 'user': | case 'user': | ||||
$result = mgroup($tasks, 'getOwnerPHID'); | $result = mgroup($tasks, 'getOwnerPHID'); | ||||
$leftover = idx($result, '', array()); | $leftover = idx($result, '', array()); | ||||
unset($result['']); | unset($result['']); | ||||
$result_closed = mgroup($recently_closed, 'getOwnerPHID'); | $result_closed = mgroup($recently_closed, 'getOwnerPHID'); | ||||
▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | $cname[] = javelin_tag( | ||||
'Oldest open task, excluding those with Low or Wishlist priority.'), | 'Oldest open task, excluding those with Low or Wishlist priority.'), | ||||
'size' => 200, | 'size' => 200, | ||||
), | ), | ||||
), | ), | ||||
pht('Oldest (Pri)')); | pht('Oldest (Pri)')); | ||||
$cclass[] = 'n'; | $cclass[] = 'n'; | ||||
list($ignored, $window_epoch) = $this->getWindow(); | list($ignored, $window_epoch) = $this->getWindow(); | ||||
$edate = phabricator_datetime($window_epoch, $user); | $edate = phabricator_datetime($window_epoch, $viewer); | ||||
$cname[] = javelin_tag( | $cname[] = javelin_tag( | ||||
'span', | 'span', | ||||
array( | array( | ||||
'sigil' => 'has-tooltip', | 'sigil' => 'has-tooltip', | ||||
'meta' => array( | 'meta' => array( | ||||
'tip' => pht('Closed after %s', $edate), | 'tip' => pht('Closed after %s', $edate), | ||||
'size' => 260, | 'size' => 260, | ||||
), | ), | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | final class ManiphestReportController extends ManiphestController { | ||||
* Parse the "Recently Means" filter into: | * Parse the "Recently Means" filter into: | ||||
* | * | ||||
* - A string representation, like "12 AM 7 days ago" (default); | * - A string representation, like "12 AM 7 days ago" (default); | ||||
* - a locale-aware epoch representation; and | * - a locale-aware epoch representation; and | ||||
* - a possible error. | * - a possible error. | ||||
*/ | */ | ||||
private function getWindow() { | private function getWindow() { | ||||
$request = $this->getRequest(); | $request = $this->getRequest(); | ||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$window_str = $this->getRequest()->getStr('window', '12 AM 7 days ago'); | $window_str = $this->getRequest()->getStr('window', '12 AM 7 days ago'); | ||||
$error = null; | $error = null; | ||||
$window_epoch = null; | $window_epoch = null; | ||||
// Do locale-aware parsing so that the user's timezone is assumed for | // Do locale-aware parsing so that the user's timezone is assumed for | ||||
// time windows like "3 PM", rather than assuming the server timezone. | // time windows like "3 PM", rather than assuming the server timezone. | ||||
$window_epoch = PhabricatorTime::parseLocalTime($window_str, $user); | $window_epoch = PhabricatorTime::parseLocalTime($window_str, $viewer); | ||||
if (!$window_epoch) { | if (!$window_epoch) { | ||||
$error = 'Invalid'; | $error = 'Invalid'; | ||||
$window_epoch = time() - (60 * 60 * 24 * 7); | $window_epoch = time() - (60 * 60 * 24 * 7); | ||||
} | } | ||||
// If the time ends up in the future, convert it to the corresponding time | // If the time ends up in the future, convert it to the corresponding time | ||||
// and equal distance in the past. This is so users can type "6 days" (which | // and equal distance in the past. This is so users can type "6 days" (which | ||||
// means "6 days from now") and get the behavior of "6 days ago", rather | // means "6 days from now") and get the behavior of "6 days ago", rather | ||||
▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines |