mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-17 18:21:11 +01:00
Allow Maniphest queries to be saved
Summary: There have been a couple of requests for this since bookmarks are "out this year like woah" and "totally uncool dude". Allow users to save named custom queries and make them the /maniphest/ default if they so desire. A little messy. :/ Test Plan: Saved, edited, deleted custom queries. Made custom query default; made 'no default' default. Verified default behavior. Issued a modified search from a custom query. Reviewers: btrahan Reviewed By: btrahan CC: aran, epriestley, 20after4 Maniphest Tasks: T923, T1034 Differential Revision: https://secure.phabricator.com/D1964
This commit is contained in:
parent
62a172af90
commit
488b1cf641
15 changed files with 766 additions and 141 deletions
13
resources/sql/patches/129.savedquery.sql
Normal file
13
resources/sql/patches/129.savedquery.sql
Normal file
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE phabricator_maniphest.maniphest_savedquery (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
userPHID varchar(64) COLLATE utf8_bin NOT NULL,
|
||||
queryKey varchar(64) COLLATE utf8_bin NOT NULL,
|
||||
name varchar(128) COLLATE utf8_general_ci NOT NULL,
|
||||
isDefault BOOL NOT NULL,
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
|
||||
KEY (userPHID, name),
|
||||
KEY (userPHID, isDefault, name)
|
||||
|
||||
) ENGINE=InnoDB, COLLATE utf8_general_ci;
|
|
@ -449,6 +449,10 @@ phutil_register_library_map(array(
|
|||
'ManiphestExportController' => 'applications/maniphest/controller/export',
|
||||
'ManiphestReplyHandler' => 'applications/maniphest/replyhandler',
|
||||
'ManiphestReportController' => 'applications/maniphest/controller/report',
|
||||
'ManiphestSavedQuery' => 'applications/maniphest/storage/savedquery',
|
||||
'ManiphestSavedQueryDeleteController' => 'applications/maniphest/controller/savedquerydelete',
|
||||
'ManiphestSavedQueryEditController' => 'applications/maniphest/controller/savedqueryedit',
|
||||
'ManiphestSavedQueryListController' => 'applications/maniphest/controller/savedquerylist',
|
||||
'ManiphestSubpriorityController' => 'applications/maniphest/controller/subpriority',
|
||||
'ManiphestTask' => 'applications/maniphest/storage/task',
|
||||
'ManiphestTaskAuxiliaryStorage' => 'applications/maniphest/storage/auxiliary',
|
||||
|
@ -1135,7 +1139,6 @@ phutil_register_library_map(array(
|
|||
'DarkConsoleRequestPlugin' => 'DarkConsolePlugin',
|
||||
'DarkConsoleServicesPlugin' => 'DarkConsolePlugin',
|
||||
'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin',
|
||||
'DefaultDatabaseConfigurationProvider' => 'DatabaseConfigurationProvider',
|
||||
'DifferentialActionHasNoEffectException' => 'DifferentialException',
|
||||
'DifferentialAddCommentView' => 'AphrontView',
|
||||
'DifferentialAffectedPath' => 'DifferentialDAO',
|
||||
|
@ -1332,6 +1335,10 @@ phutil_register_library_map(array(
|
|||
'ManiphestExportController' => 'ManiphestController',
|
||||
'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
'ManiphestReportController' => 'ManiphestController',
|
||||
'ManiphestSavedQuery' => 'ManiphestDAO',
|
||||
'ManiphestSavedQueryDeleteController' => 'ManiphestController',
|
||||
'ManiphestSavedQueryEditController' => 'ManiphestController',
|
||||
'ManiphestSavedQueryListController' => 'ManiphestController',
|
||||
'ManiphestSubpriorityController' => 'ManiphestController',
|
||||
'ManiphestTask' => 'ManiphestDAO',
|
||||
'ManiphestTaskAuxiliaryStorage' => 'ManiphestDAO',
|
||||
|
@ -1756,6 +1763,10 @@ phutil_register_library_map(array(
|
|||
),
|
||||
'requires_interface' =>
|
||||
array(
|
||||
'DefaultDatabaseConfigurationProvider' =>
|
||||
array(
|
||||
0 => 'DatabaseConfigurationProvider',
|
||||
),
|
||||
'DifferentialInlineComment' =>
|
||||
array(
|
||||
0 => 'PhabricatorInlineCommentInterface',
|
||||
|
|
|
@ -207,6 +207,11 @@ class AphrontDefaultApplicationConfiguration
|
|||
),
|
||||
'export/(?P<key>[^/]+)/' => 'ManiphestExportController',
|
||||
'subpriority/' => 'ManiphestSubpriorityController',
|
||||
'custom/' => array(
|
||||
'' => 'ManiphestSavedQueryListController',
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'ManiphestSavedQueryEditController',
|
||||
'delete/(?P<id>\d+)/' => 'ManiphestSavedQueryDeleteController',
|
||||
),
|
||||
),
|
||||
|
||||
'/T(?P<id>\d+)' => 'ManiphestTaskDetailController',
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
*/
|
||||
abstract class ManiphestController extends PhabricatorController {
|
||||
|
||||
private $defaultQuery;
|
||||
|
||||
public function buildStandardPageResponse($view, array $data) {
|
||||
$page = $this->buildStandardPageView();
|
||||
|
||||
|
@ -38,6 +40,29 @@ abstract class ManiphestController extends PhabricatorController {
|
|||
protected function buildBaseSideNav() {
|
||||
$nav = new AphrontSideNavFilterView();
|
||||
$nav->setBaseURI(new PhutilURI('/maniphest/view/'));
|
||||
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$custom = id(new ManiphestSavedQuery())->loadAllWhere(
|
||||
'userPHID = %s ORDER BY isDefault DESC, name ASC',
|
||||
$user->getPHID());
|
||||
|
||||
if ($custom) {
|
||||
$nav->addLabel('Saved Queries');
|
||||
foreach ($custom as $query) {
|
||||
if ($query->getIsDefault()) {
|
||||
$this->defaultQuery = $query;
|
||||
}
|
||||
$nav->addFilter(
|
||||
'Q:'.$query->getQueryKey(),
|
||||
$query->getName(),
|
||||
'/maniphest/view/custom/?key='.$query->getQueryKey());
|
||||
}
|
||||
$nav->addFilter('saved', 'Edit...', '/maniphest/custom/');
|
||||
$nav->addSpacer();
|
||||
}
|
||||
|
||||
$nav->addLabel('User Tasks');
|
||||
$nav->addFilter('action', 'Assigned');
|
||||
$nav->addFilter('created', 'Created');
|
||||
|
@ -61,4 +86,8 @@ abstract class ManiphestController extends PhabricatorController {
|
|||
return $nav;
|
||||
}
|
||||
|
||||
protected function getDefaultQuery() {
|
||||
return $this->defaultQuery;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
phutil_require_module('phabricator', 'aphront/response/webpage');
|
||||
phutil_require_module('phabricator', 'applications/base/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/storage/savedquery');
|
||||
phutil_require_module('phabricator', 'applications/search/constants/scope');
|
||||
phutil_require_module('phabricator', 'view/layout/sidenavfilter');
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group maniphest
|
||||
*/
|
||||
final class ManiphestSavedQueryDeleteController extends ManiphestController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = $data['id'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$id = $this->id;
|
||||
$query = id(new ManiphestSavedQuery())->load($id);
|
||||
if (!$query) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
if ($query->getUserPHID() != $user->getPHID()) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
|
||||
if ($request->isDialogFormPost()) {
|
||||
$query->delete();
|
||||
return id(new AphrontRedirectResponse())->setURI('/maniphest/custom/');
|
||||
}
|
||||
|
||||
$name = $query->getName();
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($user)
|
||||
->setTitle('Really delete this query?')
|
||||
->appendChild(
|
||||
'<p>'.
|
||||
'Really delete the query "'.phutil_escape_html($name).'"? '.
|
||||
'It will be lost forever!'.
|
||||
'</p>')
|
||||
->addCancelButton('/maniphest/custom/')
|
||||
->addSubmitButton('Delete');
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/400');
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'aphront/response/dialog');
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/storage/savedquery');
|
||||
phutil_require_module('phabricator', 'view/dialog');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('ManiphestSavedQueryDeleteController.php');
|
|
@ -0,0 +1,120 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group maniphest
|
||||
*/
|
||||
final class ManiphestSavedQueryEditController extends ManiphestController {
|
||||
|
||||
private $id;
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->id = idx($data, 'id');
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$key = $request->getStr('key');
|
||||
if (!$key) {
|
||||
$id = nonempty($this->id, $request->getInt('id'));
|
||||
if (!$id) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
$query = id(new ManiphestSavedQuery())->load($id);
|
||||
if (!$query) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
if ($query->getUserPHID() != $user->getPHID()) {
|
||||
return new Aphront400Response();
|
||||
}
|
||||
} else {
|
||||
$query = new ManiphestSavedQuery();
|
||||
$query->setUserPHID($user->getPHID());
|
||||
$query->setQueryKey($key);
|
||||
$query->setIsDefault(0);
|
||||
}
|
||||
|
||||
$e_name = true;
|
||||
$errors = array();
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$e_name = null;
|
||||
$query->setName($request->getStr('name'));
|
||||
if (!strlen($query->getName())) {
|
||||
$e_name = 'Required';
|
||||
$errors[] = 'Saved query name is required.';
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
$query->save();
|
||||
return id(new AphrontRedirectResponse())->setURI('/maniphest/custom/');
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$error_view = new AphrontErrorView();
|
||||
$error_view->setTitle('Form Errors');
|
||||
$error_view->setErrors($errors);
|
||||
} else {
|
||||
$error_view = null;
|
||||
}
|
||||
|
||||
if ($query->getID()) {
|
||||
$header = 'Edit Saved Query';
|
||||
$cancel_uri = '/maniphest/custom/';
|
||||
} else {
|
||||
$header = 'New Saved Query';
|
||||
$cancel_uri = '/maniphest/view/custom/?key='.$key;
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->addHiddenInput('key', $key)
|
||||
->addHiddenInput('id', $query->getID())
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel('Name')
|
||||
->setValue($query->getName())
|
||||
->setName('name')
|
||||
->setError($e_name))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($cancel_uri)
|
||||
->setValue('Save'));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader($header);
|
||||
$panel->appendChild($form);
|
||||
$panel->setWidth(AphrontPanelView::WIDTH_FORM);
|
||||
|
||||
$nav = $this->buildBaseSideNav();
|
||||
// The side nav won't show "Saved Queries..." until you have at least one.
|
||||
$nav->selectFilter('saved', 'custom');
|
||||
$nav->appendChild($error_view);
|
||||
$nav->appendChild($panel);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$nav,
|
||||
array(
|
||||
'title' => 'Saved Queries',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/400');
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/storage/savedquery');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||
phutil_require_module('phabricator', 'view/form/control/text');
|
||||
phutil_require_module('phabricator', 'view/form/error');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('ManiphestSavedQueryEditController.php');
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group maniphest
|
||||
*/
|
||||
final class ManiphestSavedQueryListController extends ManiphestController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$nav = $this->buildBaseSideNav();
|
||||
|
||||
$queries = id(new ManiphestSavedQuery())->loadAllWhere(
|
||||
'userPHID = %s ORDER BY name ASC',
|
||||
$user->getPHID());
|
||||
|
||||
$default = null;
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
$new_default = null;
|
||||
foreach ($queries as $query) {
|
||||
if ($query->getID() == $request->getInt('default')) {
|
||||
$new_default = $query;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getDefaultQuery()) {
|
||||
$this->getDefaultQuery()->setIsDefault(0)->save();
|
||||
}
|
||||
if ($new_default) {
|
||||
$new_default->setIsDefault(1)->save();
|
||||
}
|
||||
|
||||
return id(new AphrontRedirectResponse())->setURI('/maniphest/custom/');
|
||||
}
|
||||
|
||||
$rows = array();
|
||||
foreach ($queries as $query) {
|
||||
if ($query->getIsDefault()) {
|
||||
$default = $query;
|
||||
}
|
||||
$rows[] = array(
|
||||
phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'radio',
|
||||
'name' => 'default',
|
||||
'value' => $query->getID(),
|
||||
'checked' => ($query->getIsDefault() ? 'checked' : null),
|
||||
)),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/maniphest/view/custom/?key='.$query->getQueryKey(),
|
||||
),
|
||||
phutil_escape_html($query->getName())),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/maniphest/custom/edit/'.$query->getID().'/',
|
||||
'class' => 'grey small button',
|
||||
),
|
||||
'Edit'),
|
||||
javelin_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/maniphest/custom/delete/'.$query->getID().'/',
|
||||
'class' => 'grey small button',
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
'Delete'),
|
||||
);
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
phutil_render_tag(
|
||||
'input',
|
||||
array(
|
||||
'type' => 'radio',
|
||||
'name' => 'default',
|
||||
'value' => 0,
|
||||
'checked' => ($default === null ? 'checked' : null),
|
||||
)),
|
||||
'<em>No Default</em>',
|
||||
'',
|
||||
'',
|
||||
);
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'Default',
|
||||
'Name',
|
||||
'Edit',
|
||||
'Delete',
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'radio',
|
||||
'wide pri',
|
||||
'action',
|
||||
'action',
|
||||
));
|
||||
|
||||
$panel = new AphrontPanelView();
|
||||
$panel->setHeader('Saved Custom Queries');
|
||||
$panel->addButton(
|
||||
phutil_render_tag(
|
||||
'button',
|
||||
array(),
|
||||
'Save Default Query'));
|
||||
$panel->appendChild($table);
|
||||
|
||||
$form = phabricator_render_form(
|
||||
$user,
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'action' => $request->getRequestURI(),
|
||||
),
|
||||
$panel->render());
|
||||
|
||||
$nav->selectFilter('saved', 'saved');
|
||||
$nav->appendChild($form);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$nav,
|
||||
array(
|
||||
'title' => 'Saved Queries',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/maniphest/storage/savedquery');
|
||||
phutil_require_module('phabricator', 'infrastructure/javelin/markup');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('ManiphestSavedQueryListController.php');
|
|
@ -59,8 +59,6 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
|
||||
$nav = $this->buildBaseSideNav();
|
||||
|
||||
$this->view = $nav->selectFilter($this->view, 'action');
|
||||
|
||||
$has_filter = array(
|
||||
'action' => true,
|
||||
'created' => true,
|
||||
|
@ -70,56 +68,66 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
'projectall' => true,
|
||||
);
|
||||
|
||||
list($status_map, $status_control) = $this->renderStatusLinks();
|
||||
list($grouping, $group_control) = $this->renderGroupLinks();
|
||||
list($order, $order_control) = $this->renderOrderLinks();
|
||||
|
||||
$user_phids = $request->getStrList(
|
||||
'users',
|
||||
array($user->getPHID()));
|
||||
if ($this->view == 'projecttriage' || $this->view == 'projectall') {
|
||||
$project_query = new PhabricatorProjectQuery();
|
||||
$project_query->setMembers($user_phids);
|
||||
$projects = $project_query->execute();
|
||||
$project_phids = mpull($projects, 'getPHID');
|
||||
} else {
|
||||
$project_phids = $request->getStrList('projects');
|
||||
$query = null;
|
||||
$key = $request->getStr('key');
|
||||
if (!$key && !$this->view) {
|
||||
if ($this->getDefaultQuery()) {
|
||||
$key = $this->getDefaultQuery()->getQueryKey();
|
||||
}
|
||||
}
|
||||
$exclude_project_phids = $request->getStrList('xprojects');
|
||||
$task_ids = $request->getStrList('tasks');
|
||||
$owner_phids = $request->getStrList('owners');
|
||||
$author_phids = $request->getStrList('authors');
|
||||
|
||||
$page = $request->getInt('page');
|
||||
$page_size = self::DEFAULT_PAGE_SIZE;
|
||||
if ($key) {
|
||||
$query = id(new PhabricatorSearchQuery())->loadOneWhere(
|
||||
'queryKey = %s',
|
||||
$key);
|
||||
}
|
||||
|
||||
$query = new PhabricatorSearchQuery();
|
||||
$query->setQuery('<<maniphest>>');
|
||||
$query->setParameters(
|
||||
array(
|
||||
'view' => $this->view,
|
||||
'userPHIDs' => $user_phids,
|
||||
'projectPHIDs' => $project_phids,
|
||||
'excludeProjectPHIDs' => $exclude_project_phids,
|
||||
'ownerPHIDs' => $owner_phids,
|
||||
'authorPHIDs' => $author_phids,
|
||||
'taskIDs' => $task_ids,
|
||||
'group' => $grouping,
|
||||
'order' => $order,
|
||||
'offset' => $page,
|
||||
'limit' => $page_size,
|
||||
'status' => $status_map,
|
||||
));
|
||||
// If the user is running a saved query, load query parameters from that
|
||||
// query. Otherwise, build a new query object from the HTTP request.
|
||||
|
||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||
$query->save();
|
||||
unset($unguarded);
|
||||
if ($query) {
|
||||
$nav->selectFilter('Q:'.$query->getQueryKey(), 'custom');
|
||||
$this->view = 'custom';
|
||||
} else {
|
||||
$this->view = $nav->selectFilter($this->view, 'action');
|
||||
$query = $this->buildQueryFromRequest();
|
||||
}
|
||||
|
||||
// Execute the query.
|
||||
|
||||
list($tasks, $handles, $total_count) = self::loadTasks($query);
|
||||
|
||||
// Extract information we need to render the filters from the query.
|
||||
|
||||
$user_phids = $query->getParameter('userPHIDs', array());
|
||||
$task_ids = $query->getParameter('taskIDs', array());
|
||||
$owner_phids = $query->getParameter('ownerPHIDs', array());
|
||||
$author_phids = $query->getParameter('authorPHIDs', array());
|
||||
$project_phids = $query->getParameter('projectPHIDs', array());
|
||||
$exclude_project_phids = $query->getParameter(
|
||||
'excludeProjectPHIDs',
|
||||
array());
|
||||
$page_size = $query->getParameter('limit');
|
||||
$page = $query->getParameter('offset');
|
||||
|
||||
$q_status = $query->getParameter('status');
|
||||
$q_group = $query->getParameter('group');
|
||||
$q_order = $query->getParameter('order');
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->setAction($request->getRequestURI());
|
||||
->setAction(
|
||||
$request->getRequestURI()
|
||||
->alter('key', null)
|
||||
->alter(
|
||||
$this->getStatusRequestKey(),
|
||||
$this->getStatusRequestValue($q_status))
|
||||
->alter(
|
||||
$this->getOrderRequestKey(),
|
||||
$this->getOrderRequestValue($q_order))
|
||||
->alter(
|
||||
$this->getGroupRequestKey(),
|
||||
$this->getGroupRequestValue($q_group)));
|
||||
|
||||
if (isset($has_filter[$this->view])) {
|
||||
$tokens = array();
|
||||
|
@ -192,13 +200,24 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
}
|
||||
|
||||
$form
|
||||
->appendChild($status_control)
|
||||
->appendChild($group_control)
|
||||
->appendChild($order_control);
|
||||
->appendChild($this->renderStatusControl($q_status))
|
||||
->appendChild($this->renderGroupControl($q_group))
|
||||
->appendChild($this->renderOrderControl($q_order));
|
||||
|
||||
$form->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue('Filter Tasks'));
|
||||
$submit = id(new AphrontFormSubmitControl())
|
||||
->setValue('Filter Tasks');
|
||||
|
||||
// Only show "Save..." for novel queries which have some kind of query
|
||||
// parameters set.
|
||||
if ($this->view === 'custom'
|
||||
&& empty($key)
|
||||
&& $request->getRequestURI()->getQueryParams()) {
|
||||
$submit->addCancelButton(
|
||||
'/maniphest/custom/edit/?key='.$query->getQueryKey(),
|
||||
'Save Custom Query...');
|
||||
}
|
||||
|
||||
$form->appendChild($submit);
|
||||
|
||||
$create_uri = new PhutilURI('/maniphest/task/create/');
|
||||
if ($project_phids) {
|
||||
|
@ -216,7 +235,10 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
'class' => 'green button',
|
||||
),
|
||||
'Create New Task'));
|
||||
$filter->appendChild($form);
|
||||
|
||||
if (empty($key)) {
|
||||
$filter->appendChild($form);
|
||||
}
|
||||
|
||||
$nav->appendChild($filter);
|
||||
|
||||
|
@ -240,7 +262,7 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
'</h1>');
|
||||
} else {
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setURI($request->getRequestURI(), 'page');
|
||||
$pager->setURI($request->getRequestURI(), 'offset');
|
||||
$pager->setPageSize($page_size);
|
||||
$pager->setOffset($page);
|
||||
$pager->setCount($total_count);
|
||||
|
@ -533,95 +555,6 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
return array($data, $handles, $total_row_count);
|
||||
}
|
||||
|
||||
public function renderStatusLinks() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$statuses = array(
|
||||
'o' => array('open' => true),
|
||||
'c' => array('closed' => true),
|
||||
'oc' => array('open' => true, 'closed' => true),
|
||||
);
|
||||
|
||||
$status = $request->getStr('s');
|
||||
if (empty($statuses[$status])) {
|
||||
$status = 'o';
|
||||
}
|
||||
|
||||
$status_control = id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Status')
|
||||
->setValue($status)
|
||||
->setBaseURI($request->getRequestURI(), 's')
|
||||
->setButtons(
|
||||
array(
|
||||
'o' => 'Open',
|
||||
'c' => 'Closed',
|
||||
'oc' => 'All',
|
||||
));
|
||||
|
||||
return array($statuses[$status], $status_control);
|
||||
}
|
||||
|
||||
public function renderOrderLinks() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$order = $request->getStr('o');
|
||||
$orders = array(
|
||||
'u' => 'updated',
|
||||
'c' => 'created',
|
||||
'p' => 'priority',
|
||||
);
|
||||
if (empty($orders[$order])) {
|
||||
$order = 'p';
|
||||
}
|
||||
$order_by = $orders[$order];
|
||||
|
||||
$order_control = id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Order')
|
||||
->setValue($order)
|
||||
->setBaseURI($request->getRequestURI(), 'o')
|
||||
->setButtons(
|
||||
array(
|
||||
'p' => 'Priority',
|
||||
'u' => 'Updated',
|
||||
'c' => 'Created',
|
||||
));
|
||||
|
||||
return array($order_by, $order_control);
|
||||
}
|
||||
|
||||
public function renderGroupLinks() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$group = $request->getStr('g');
|
||||
$groups = array(
|
||||
'n' => 'none',
|
||||
'p' => 'priority',
|
||||
's' => 'status',
|
||||
'o' => 'owner',
|
||||
'j' => 'project',
|
||||
);
|
||||
if (empty($groups[$group])) {
|
||||
$group = 'p';
|
||||
}
|
||||
$group_by = $groups[$group];
|
||||
|
||||
|
||||
$group_control = id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Group')
|
||||
->setValue($group)
|
||||
->setBaseURI($request->getRequestURI(), 'g')
|
||||
->setButtons(
|
||||
array(
|
||||
'p' => 'Priority',
|
||||
'o' => 'Owner',
|
||||
's' => 'Status',
|
||||
'j' => 'Project',
|
||||
'n' => 'None',
|
||||
));
|
||||
|
||||
return array($group_by, $group_control);
|
||||
}
|
||||
|
||||
private function renderBatchEditor(PhabricatorSearchQuery $search_query) {
|
||||
Javelin::initBehavior(
|
||||
'maniphest-batch-selector',
|
||||
|
@ -690,4 +623,195 @@ final class ManiphestTaskListController extends ManiphestController {
|
|||
'</table>';
|
||||
}
|
||||
|
||||
private function buildQueryFromRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
|
||||
$status = $this->getStatusValueFromRequest();
|
||||
$group = $this->getGroupValueFromRequest();
|
||||
$order = $this->getOrderValueFromRequest();
|
||||
|
||||
$user_phids = $request->getStrList(
|
||||
'users',
|
||||
array($user->getPHID()));
|
||||
|
||||
if ($this->view == 'projecttriage' || $this->view == 'projectall') {
|
||||
$project_query = new PhabricatorProjectQuery();
|
||||
$project_query->setMembers($user_phids);
|
||||
$projects = $project_query->execute();
|
||||
$project_phids = mpull($projects, 'getPHID');
|
||||
} else {
|
||||
$project_phids = $request->getStrList('projects');
|
||||
}
|
||||
|
||||
$exclude_project_phids = $request->getStrList('xprojects');
|
||||
$task_ids = $request->getStrList('tasks');
|
||||
$owner_phids = $request->getStrList('owners');
|
||||
$author_phids = $request->getStrList('authors');
|
||||
|
||||
$page = $request->getInt('offset');
|
||||
$page_size = self::DEFAULT_PAGE_SIZE;
|
||||
|
||||
$query = new PhabricatorSearchQuery();
|
||||
$query->setQuery('<<maniphest>>');
|
||||
$query->setParameters(
|
||||
array(
|
||||
'view' => $this->view,
|
||||
'userPHIDs' => $user_phids,
|
||||
'projectPHIDs' => $project_phids,
|
||||
'excludeProjectPHIDs' => $exclude_project_phids,
|
||||
'ownerPHIDs' => $owner_phids,
|
||||
'authorPHIDs' => $author_phids,
|
||||
'taskIDs' => $task_ids,
|
||||
'group' => $group,
|
||||
'order' => $order,
|
||||
'offset' => $page,
|
||||
'limit' => $page_size,
|
||||
'status' => $status,
|
||||
));
|
||||
|
||||
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
|
||||
$query->save();
|
||||
unset($unguarded);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/* -( Toggle Button Controls )---------------------------------------------
|
||||
|
||||
These are a giant mess since we have several different values: the request
|
||||
key (GET param used in requests), the request value (short names used in
|
||||
requests to keep URIs readable), and the query value (complex value stored in
|
||||
the query).
|
||||
|
||||
*/
|
||||
|
||||
private function getStatusValueFromRequest() {
|
||||
$map = $this->getStatusMap();
|
||||
$val = $this->getRequest()->getStr($this->getStatusRequestKey());
|
||||
return idx($map, $val, head($map));
|
||||
}
|
||||
|
||||
private function getGroupValueFromRequest() {
|
||||
$map = $this->getGroupMap();
|
||||
$val = $this->getRequest()->getStr($this->getGroupRequestKey());
|
||||
return idx($map, $val, head($map));
|
||||
}
|
||||
|
||||
private function getOrderValueFromRequest() {
|
||||
$map = $this->getOrderMap();
|
||||
$val = $this->getRequest()->getStr($this->getOrderRequestKey());
|
||||
return idx($map, $val, head($map));
|
||||
}
|
||||
|
||||
private function getStatusRequestKey() {
|
||||
return 's';
|
||||
}
|
||||
|
||||
private function getGroupRequestKey() {
|
||||
return 'g';
|
||||
}
|
||||
|
||||
private function getOrderRequestKey() {
|
||||
return 'o';
|
||||
}
|
||||
|
||||
private function getStatusRequestValue($value) {
|
||||
return array_search($value, $this->getStatusMap());
|
||||
}
|
||||
|
||||
private function getGroupRequestValue($value) {
|
||||
return array_search($value, $this->getGroupMap());
|
||||
}
|
||||
|
||||
private function getOrderRequestValue($value) {
|
||||
return array_search($value, $this->getOrderMap());
|
||||
}
|
||||
|
||||
private function getStatusMap() {
|
||||
return array(
|
||||
'o' => array(
|
||||
'open' => true,
|
||||
),
|
||||
'c' => array(
|
||||
'closed' => true,
|
||||
),
|
||||
'oc' => array(
|
||||
'open' => true,
|
||||
'closed' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function getGroupMap() {
|
||||
return array(
|
||||
'p' => 'priority',
|
||||
'o' => 'owner',
|
||||
's' => 'status',
|
||||
'j' => 'project',
|
||||
'n' => 'none',
|
||||
);
|
||||
}
|
||||
|
||||
private function getOrderMap() {
|
||||
return array(
|
||||
'p' => 'priority',
|
||||
'u' => 'updated',
|
||||
'c' => 'created',
|
||||
);
|
||||
}
|
||||
|
||||
private function getStatusButtonMap() {
|
||||
return array(
|
||||
'o' => 'Open',
|
||||
'c' => 'Closed',
|
||||
'oc' => 'All',
|
||||
);
|
||||
}
|
||||
|
||||
private function getGroupButtonMap() {
|
||||
return array(
|
||||
'p' => 'Priority',
|
||||
'o' => 'Owner',
|
||||
's' => 'Status',
|
||||
'j' => 'Project',
|
||||
'n' => 'None',
|
||||
);
|
||||
}
|
||||
|
||||
private function getOrderButtonMap() {
|
||||
return array(
|
||||
'p' => 'Priority',
|
||||
'u' => 'Updated',
|
||||
'c' => 'Created',
|
||||
);
|
||||
}
|
||||
|
||||
public function renderStatusControl($value) {
|
||||
$request = $this->getRequest();
|
||||
return id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Status')
|
||||
->setValue($this->getStatusRequestValue($value))
|
||||
->setBaseURI($request->getRequestURI(), $this->getStatusRequestKey())
|
||||
->setButtons($this->getStatusButtonMap());
|
||||
}
|
||||
|
||||
public function renderOrderControl($value) {
|
||||
$request = $this->getRequest();
|
||||
return id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Order')
|
||||
->setValue($this->getOrderRequestValue($value))
|
||||
->setBaseURI($request->getRequestURI(), $this->getOrderRequestKey())
|
||||
->setButtons($this->getOrderButtonMap());
|
||||
}
|
||||
|
||||
public function renderGroupControl($value) {
|
||||
$request = $this->getRequest();
|
||||
return id(new AphrontFormToggleButtonsControl())
|
||||
->setLabel('Group')
|
||||
->setValue($this->getGroupRequestValue($value))
|
||||
->setBaseURI($request->getRequestURI(), $this->getGroupRequestKey())
|
||||
->setButtons($this->getGroupButtonMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group maniphest
|
||||
*/
|
||||
final class ManiphestSavedQuery extends ManiphestDAO {
|
||||
|
||||
protected $name;
|
||||
protected $queryKey;
|
||||
protected $userPHID;
|
||||
protected $isDefault;
|
||||
|
||||
}
|
12
src/applications/maniphest/storage/savedquery/__init__.php
Normal file
12
src/applications/maniphest/storage/savedquery/__init__.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/maniphest/storage/base');
|
||||
|
||||
|
||||
phutil_require_source('ManiphestSavedQuery.php');
|
|
@ -137,6 +137,11 @@ span.single-display-line-content {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.aphront-table-view td.radio {
|
||||
text-align: center;
|
||||
padding: 2px 4px 0px;
|
||||
}
|
||||
|
||||
.aphront-table-view th.aphront-table-view-sortable {
|
||||
padding: 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue