2011-02-08 10:53:59 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Copyright 2011 Facebook, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
class ManiphestTaskListController extends ManiphestController {
|
|
|
|
|
|
|
|
|
|
private $view;
|
|
|
|
|
|
|
|
|
|
public function willProcessRequest(array $data) {
|
|
|
|
|
$this->view = idx($data, 'view');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function processRequest() {
|
|
|
|
|
|
2011-04-11 02:03:30 -07:00
|
|
|
$request = $this->getRequest();
|
|
|
|
|
$user = $request->getUser();
|
|
|
|
|
$uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
|
|
if ($request->isFormPost()) {
|
|
|
|
|
$phid_arr = $request->getArr('view_user');
|
|
|
|
|
$view_target = head($phid_arr);
|
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
|
->setURI($request->getRequestURI()->alter('phid', $view_target));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-02-08 10:53:59 -08:00
|
|
|
$views = array(
|
2011-04-11 02:03:30 -07:00
|
|
|
'User Tasks',
|
2011-02-11 10:28:37 -08:00
|
|
|
'action' => 'Assigned',
|
2011-02-08 10:53:59 -08:00
|
|
|
'created' => 'Created',
|
|
|
|
|
'triage' => 'Need Triage',
|
2011-02-11 10:28:37 -08:00
|
|
|
// 'touched' => 'Touched',
|
2011-02-09 16:29:46 -08:00
|
|
|
'<hr />',
|
2011-02-11 10:28:37 -08:00
|
|
|
'All Tasks',
|
2011-02-09 16:29:46 -08:00
|
|
|
'alltriage' => 'Need Triage',
|
|
|
|
|
'unassigned' => 'Unassigned',
|
2011-02-11 10:28:37 -08:00
|
|
|
'all' => 'All Tasks',
|
2011-02-08 10:53:59 -08:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (empty($views[$this->view])) {
|
2011-02-09 16:29:46 -08:00
|
|
|
$this->view = 'action';
|
2011-02-08 10:53:59 -08:00
|
|
|
}
|
|
|
|
|
|
2011-04-11 02:03:30 -07:00
|
|
|
$has_filter = array(
|
|
|
|
|
'action' => true,
|
|
|
|
|
'created' => true,
|
|
|
|
|
'triage' => true,
|
|
|
|
|
);
|
2011-02-08 10:53:59 -08:00
|
|
|
|
|
|
|
|
$nav = new AphrontSideNavView();
|
|
|
|
|
foreach ($views as $view => $name) {
|
2011-02-09 16:29:46 -08:00
|
|
|
if (is_integer($view)) {
|
|
|
|
|
$nav->addNavItem(
|
|
|
|
|
phutil_render_tag(
|
|
|
|
|
'span',
|
|
|
|
|
array(),
|
|
|
|
|
$name));
|
|
|
|
|
} else {
|
2011-02-11 10:28:37 -08:00
|
|
|
$uri->setPath('/maniphest/view/'.$view.'/');
|
2011-02-09 16:29:46 -08:00
|
|
|
$nav->addNavItem(
|
|
|
|
|
phutil_render_tag(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
2011-02-11 10:28:37 -08:00
|
|
|
'href' => $uri,
|
2011-02-09 16:29:46 -08:00
|
|
|
'class' => ($this->view == $view)
|
|
|
|
|
? 'aphront-side-nav-selected'
|
|
|
|
|
: null,
|
|
|
|
|
),
|
|
|
|
|
phutil_escape_html($name)));
|
|
|
|
|
}
|
2011-02-08 10:53:59 -08:00
|
|
|
}
|
|
|
|
|
|
2011-02-11 10:28:37 -08:00
|
|
|
list($status_map, $status_links) = $this->renderStatusLinks();
|
|
|
|
|
list($grouping, $group_links) = $this->renderGroupLinks();
|
|
|
|
|
list($order, $order_links) = $this->renderOrderLinks();
|
|
|
|
|
|
2011-04-11 02:03:30 -07:00
|
|
|
$view_phid = nonempty($request->getStr('phid'), $user->getPHID());
|
|
|
|
|
|
2011-02-11 10:28:37 -08:00
|
|
|
list($tasks, $handles) = $this->loadTasks(
|
2011-04-11 02:03:30 -07:00
|
|
|
$view_phid,
|
2011-02-11 10:28:37 -08:00
|
|
|
array(
|
|
|
|
|
'status' => $status_map,
|
|
|
|
|
'group' => $grouping,
|
|
|
|
|
'order' => $order,
|
|
|
|
|
));
|
2011-02-08 10:53:59 -08:00
|
|
|
|
|
|
|
|
|
2011-04-03 15:50:06 -07:00
|
|
|
$form = id(new AphrontFormView())
|
2011-04-11 02:03:30 -07:00
|
|
|
->setUser($user);
|
|
|
|
|
|
|
|
|
|
if (isset($has_filter[$this->view])) {
|
|
|
|
|
$form->appendChild(
|
|
|
|
|
id(new AphrontFormTokenizerControl())
|
|
|
|
|
->setLimit(1)
|
|
|
|
|
->setDatasource('/typeahead/common/users/')
|
|
|
|
|
->setName('view_user')
|
|
|
|
|
->setLabel('View User')
|
|
|
|
|
->setValue(
|
|
|
|
|
array(
|
|
|
|
|
$view_phid => $handles[$view_phid]->getFullName(),
|
|
|
|
|
)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$form
|
2011-04-03 15:50:06 -07:00
|
|
|
->appendChild(
|
|
|
|
|
id(new AphrontFormToggleButtonsControl())
|
|
|
|
|
->setLabel('Status')
|
|
|
|
|
->setValue($status_links))
|
|
|
|
|
->appendChild(
|
|
|
|
|
id(new AphrontFormToggleButtonsControl())
|
|
|
|
|
->setLabel('Group')
|
|
|
|
|
->setValue($group_links))
|
|
|
|
|
->appendChild(
|
|
|
|
|
id(new AphrontFormToggleButtonsControl())
|
|
|
|
|
->setLabel('Order')
|
|
|
|
|
->setValue($order_links));
|
|
|
|
|
|
|
|
|
|
$filter = new AphrontListFilterView();
|
|
|
|
|
$filter->addButton(
|
|
|
|
|
phutil_render_tag(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
|
|
|
|
'href' => '/maniphest/task/create/',
|
|
|
|
|
'class' => 'green button',
|
|
|
|
|
),
|
|
|
|
|
'Create New Task'));
|
|
|
|
|
$filter->appendChild($form);
|
|
|
|
|
|
|
|
|
|
$nav->appendChild($filter);
|
2011-02-11 10:28:37 -08:00
|
|
|
|
|
|
|
|
$have_tasks = false;
|
|
|
|
|
foreach ($tasks as $group => $list) {
|
|
|
|
|
if (count($list)) {
|
|
|
|
|
$have_tasks = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-03 15:50:06 -07:00
|
|
|
require_celerity_resource('maniphest-task-summary-css');
|
|
|
|
|
|
2011-02-11 10:28:37 -08:00
|
|
|
if (!$have_tasks) {
|
|
|
|
|
$nav->appendChild(
|
|
|
|
|
'<h1 class="maniphest-task-group-header">'.
|
|
|
|
|
'No matching tasks.'.
|
|
|
|
|
'</h1>');
|
|
|
|
|
} else {
|
|
|
|
|
foreach ($tasks as $group => $list) {
|
|
|
|
|
$task_list = new ManiphestTaskListView();
|
|
|
|
|
$task_list->setTasks($list);
|
|
|
|
|
$task_list->setHandles($handles);
|
|
|
|
|
|
|
|
|
|
$nav->appendChild(
|
|
|
|
|
'<h1 class="maniphest-task-group-header">'.
|
|
|
|
|
phutil_escape_html($group).
|
|
|
|
|
'</h1>');
|
|
|
|
|
$nav->appendChild($task_list);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-08 10:53:59 -08:00
|
|
|
|
|
|
|
|
return $this->buildStandardPageResponse(
|
|
|
|
|
$nav,
|
|
|
|
|
array(
|
|
|
|
|
'title' => 'Task List',
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-11 02:03:30 -07:00
|
|
|
private function loadTasks($view_phid, array $dict) {
|
|
|
|
|
$phids = array($view_phid);
|
2011-02-08 10:53:59 -08:00
|
|
|
|
2011-02-11 10:28:37 -08:00
|
|
|
$task = new ManiphestTask();
|
|
|
|
|
|
|
|
|
|
$argv = array();
|
|
|
|
|
|
|
|
|
|
$status = $dict['status'];
|
|
|
|
|
if (!empty($status['open']) && !empty($status['closed'])) {
|
|
|
|
|
$status_clause = '1 = 1';
|
|
|
|
|
} else if (!empty($status['open'])) {
|
|
|
|
|
$status_clause = 'status = %d';
|
|
|
|
|
$argv[] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
$status_clause = 'status > %d';
|
|
|
|
|
$argv[] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$extra_clause = '1 = 1';
|
2011-02-08 10:53:59 -08:00
|
|
|
switch ($this->view) {
|
|
|
|
|
case 'action':
|
2011-02-11 10:28:37 -08:00
|
|
|
$extra_clause = 'ownerPHID in (%Ls)';
|
|
|
|
|
$argv[] = $phids;
|
|
|
|
|
break;
|
2011-02-08 10:53:59 -08:00
|
|
|
case 'created':
|
2011-02-11 10:28:37 -08:00
|
|
|
$extra_clause = 'authorPHID in (%Ls)';
|
|
|
|
|
$argv[] = $phids;
|
|
|
|
|
break;
|
2011-02-08 10:53:59 -08:00
|
|
|
case 'triage':
|
2011-02-24 14:34:58 -08:00
|
|
|
$extra_clause = 'ownerPHID in (%Ls) AND priority = %d';
|
2011-02-11 10:28:37 -08:00
|
|
|
$argv[] = $phids;
|
|
|
|
|
$argv[] = ManiphestTaskPriority::PRIORITY_TRIAGE;
|
|
|
|
|
break;
|
2011-02-09 16:29:46 -08:00
|
|
|
case 'alltriage':
|
2011-02-24 14:34:58 -08:00
|
|
|
$extra_clause = 'priority = %d';
|
2011-02-11 10:28:37 -08:00
|
|
|
$argv[] = ManiphestTaskPriority::PRIORITY_TRIAGE;
|
|
|
|
|
break;
|
2011-02-09 16:29:46 -08:00
|
|
|
case 'unassigned':
|
2011-02-11 10:28:37 -08:00
|
|
|
$extra_clause = 'ownerPHID is NULL';
|
|
|
|
|
break;
|
|
|
|
|
case 'all':
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ($dict['order']) {
|
|
|
|
|
case 'priority':
|
|
|
|
|
$order = 'priority DESC, dateModified DESC';
|
|
|
|
|
break;
|
|
|
|
|
case 'created':
|
|
|
|
|
$order = 'id DESC';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$order = 'dateModified DESC';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$sql = "({$status_clause}) AND ({$extra_clause}) ORDER BY {$order}";
|
|
|
|
|
|
|
|
|
|
array_unshift($argv, $sql);
|
|
|
|
|
|
|
|
|
|
$data = call_user_func_array(array($task, 'loadAllWhere'), $argv);
|
|
|
|
|
|
|
|
|
|
$handle_phids = mpull($data, 'getOwnerPHID');
|
2011-04-11 02:03:30 -07:00
|
|
|
$handle_phids[] = $view_phid;
|
2011-02-11 10:28:37 -08:00
|
|
|
$handles = id(new PhabricatorObjectHandleData($handle_phids))
|
|
|
|
|
->loadHandles();
|
|
|
|
|
|
|
|
|
|
switch ($dict['group']) {
|
|
|
|
|
case 'priority':
|
|
|
|
|
$data = mgroup($data, 'getPriority');
|
|
|
|
|
krsort($data);
|
|
|
|
|
|
|
|
|
|
$out = array();
|
|
|
|
|
foreach ($data as $pri => $tasks) {
|
|
|
|
|
$out[ManiphestTaskPriority::getTaskPriorityName($pri)] = $tasks;
|
|
|
|
|
}
|
|
|
|
|
$data = $out;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case 'status':
|
|
|
|
|
$data = mgroup($data, 'getStatus');
|
|
|
|
|
ksort($data);
|
|
|
|
|
|
|
|
|
|
$out = array();
|
|
|
|
|
foreach ($data as $status => $tasks) {
|
|
|
|
|
$out[ManiphestTaskStatus::getTaskStatusFullName($status)] = $tasks;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$data = $out;
|
|
|
|
|
break;
|
|
|
|
|
case 'owner':
|
|
|
|
|
$data = mgroup($data, 'getOwnerPHID');
|
|
|
|
|
|
|
|
|
|
$out = array();
|
|
|
|
|
foreach ($data as $phid => $tasks) {
|
|
|
|
|
if ($phid) {
|
|
|
|
|
$out[$handles[$phid]->getFullName()] = $tasks;
|
|
|
|
|
} else {
|
|
|
|
|
$out['Unassigned'] = $tasks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isset($out['Unassigned'])) {
|
|
|
|
|
// If any tasks are unassigned, move them to the front of the list.
|
|
|
|
|
$data = array('Unassigned' => $out['Unassigned']) + $out;
|
|
|
|
|
} else {
|
|
|
|
|
$data = $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ksort($data);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
$data = array(
|
|
|
|
|
'Tasks' => $data,
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return array($data, $handles);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function renderStatusLinks() {
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
|
|
|
|
$sel = array(
|
|
|
|
|
'open' => false,
|
|
|
|
|
'closed' => false,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$status = $request->getStr('s');
|
|
|
|
|
if ($status == 'c') {
|
|
|
|
|
$sel['closed'] = true;
|
|
|
|
|
} else if ($status == 'oc') {
|
|
|
|
|
$sel['closed'] = true;
|
|
|
|
|
$sel['open'] = true;
|
|
|
|
|
} else {
|
|
|
|
|
$sel['open'] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$just_one = (count(array_filter($sel)) == 1);
|
|
|
|
|
|
|
|
|
|
$flag_map = array(
|
|
|
|
|
'Open' => 'open',
|
|
|
|
|
'Closed' => 'closed',
|
|
|
|
|
);
|
|
|
|
|
$button_names = array(
|
|
|
|
|
'Open' => 'o',
|
|
|
|
|
'Closed' => 'c',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$base_flags = array();
|
|
|
|
|
foreach ($flag_map as $name => $key) {
|
|
|
|
|
$base_flags[$button_names[$name]] = $sel[$key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($button_names as $name => $letter) {
|
|
|
|
|
$flags = $base_flags;
|
|
|
|
|
$flags[$letter] = !$flags[$letter];
|
|
|
|
|
$button_names[$name] = implode('', array_keys(array_filter($flags)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
|
|
$links = array();
|
|
|
|
|
foreach ($button_names as $name => $value) {
|
|
|
|
|
$selected = $sel[$flag_map[$name]];
|
|
|
|
|
$fixed = ($selected && $just_one);
|
|
|
|
|
|
|
|
|
|
$more = null;
|
|
|
|
|
if ($fixed) {
|
|
|
|
|
$href = null;
|
|
|
|
|
$more .= ' toggle-fixed';
|
|
|
|
|
} else {
|
|
|
|
|
$href = $uri->alter('s', $value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($selected) {
|
|
|
|
|
$more .= ' toggle-selected';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$links[] = phutil_render_tag(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
|
|
|
|
'href' => $href,
|
|
|
|
|
'class' => 'toggle'.$more,
|
|
|
|
|
),
|
|
|
|
|
$name);
|
|
|
|
|
}
|
|
|
|
|
$status_links = implode("\n", $links);
|
|
|
|
|
|
|
|
|
|
return array($sel, $status_links);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function renderOrderLinks() {
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
|
|
|
|
$order = $request->getStr('o');
|
|
|
|
|
$orders = array(
|
|
|
|
|
'u' => 'updated',
|
|
|
|
|
'c' => 'created',
|
|
|
|
|
'p' => 'priority',
|
|
|
|
|
);
|
|
|
|
|
if (empty($orders[$order])) {
|
2011-02-18 21:57:34 -08:00
|
|
|
$order = 'p';
|
2011-02-11 10:28:37 -08:00
|
|
|
}
|
|
|
|
|
$order_by = $orders[$order];
|
|
|
|
|
|
|
|
|
|
$order_names = array(
|
2011-02-18 21:57:34 -08:00
|
|
|
'Priority' => 'p',
|
2011-02-11 10:28:37 -08:00
|
|
|
'Updated' => 'u',
|
|
|
|
|
'Created' => 'c',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
|
|
$links = array();
|
|
|
|
|
foreach ($order_names as $name => $param_key) {
|
|
|
|
|
if ($param_key == $order) {
|
|
|
|
|
$more = ' toggle-selected toggle-fixed';
|
|
|
|
|
$href = null;
|
|
|
|
|
} else {
|
|
|
|
|
$more = null;
|
|
|
|
|
$href = $uri->alter('o', $param_key);
|
|
|
|
|
}
|
|
|
|
|
$links[] = phutil_render_tag(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
|
|
|
|
'class' => 'toggle'.$more,
|
|
|
|
|
'href' => $href,
|
|
|
|
|
),
|
|
|
|
|
$name);
|
|
|
|
|
}
|
|
|
|
|
$order_links = implode("\n", $links);
|
|
|
|
|
|
|
|
|
|
return array($order_by, $order_links);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function renderGroupLinks() {
|
|
|
|
|
$request = $this->getRequest();
|
|
|
|
|
|
|
|
|
|
$group = $request->getStr('g');
|
|
|
|
|
$groups = array(
|
|
|
|
|
'n' => 'none',
|
|
|
|
|
'p' => 'priority',
|
|
|
|
|
's' => 'status',
|
|
|
|
|
'o' => 'owner',
|
|
|
|
|
);
|
|
|
|
|
if (empty($groups[$group])) {
|
2011-02-18 21:57:34 -08:00
|
|
|
$group = 'p';
|
2011-02-11 10:28:37 -08:00
|
|
|
}
|
|
|
|
|
$group_by = $groups[$group];
|
|
|
|
|
|
|
|
|
|
$group_names = array(
|
|
|
|
|
'Priority' => 'p',
|
|
|
|
|
'Owner' => 'o',
|
|
|
|
|
'Status' => 's',
|
2011-02-18 21:57:34 -08:00
|
|
|
'None' => 'n',
|
2011-02-11 10:28:37 -08:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$uri = $request->getRequestURI();
|
|
|
|
|
|
|
|
|
|
$links = array();
|
|
|
|
|
foreach ($group_names as $name => $param_key) {
|
|
|
|
|
if ($param_key == $group) {
|
|
|
|
|
$more = ' toggle-selected toggle-fixed';
|
|
|
|
|
$href = null;
|
|
|
|
|
} else {
|
|
|
|
|
$more = null;
|
|
|
|
|
$href = $uri->alter('g', $param_key);
|
|
|
|
|
}
|
|
|
|
|
$links[] = phutil_render_tag(
|
|
|
|
|
'a',
|
|
|
|
|
array(
|
|
|
|
|
'class' => 'toggle'.$more,
|
|
|
|
|
'href' => $href,
|
|
|
|
|
),
|
|
|
|
|
$name);
|
2011-02-08 10:53:59 -08:00
|
|
|
}
|
2011-02-11 10:28:37 -08:00
|
|
|
$group_links = implode("\n", $links);
|
2011-02-08 10:53:59 -08:00
|
|
|
|
2011-02-11 10:28:37 -08:00
|
|
|
return array($group_by, $group_links);
|
2011-02-08 10:53:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|