1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 21:40:55 +01:00

Use ApplicationSearch in projects

Summary: Ref T2715. I stripped a bunch of stuff from the list since it was buggy, slow, or both. Some day, we'll rebuild it.

Test Plan: {F51128}

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2715

Differential Revision: https://secure.phabricator.com/D6525
This commit is contained in:
epriestley 2013-07-22 08:34:35 -07:00
parent 7cbe82d777
commit b574b3ff8e
6 changed files with 161 additions and 150 deletions

View file

@ -1402,6 +1402,7 @@ phutil_register_library_map(array(
'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php', 'PhabricatorProjectProfileController' => 'applications/project/controller/PhabricatorProjectProfileController.php',
'PhabricatorProjectProfileEditController' => 'applications/project/controller/PhabricatorProjectProfileEditController.php', 'PhabricatorProjectProfileEditController' => 'applications/project/controller/PhabricatorProjectProfileEditController.php',
'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php', 'PhabricatorProjectQuery' => 'applications/project/query/PhabricatorProjectQuery.php',
'PhabricatorProjectSearchEngine' => 'applications/project/query/PhabricatorProjectSearchEngine.php',
'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php', 'PhabricatorProjectStatus' => 'applications/project/constants/PhabricatorProjectStatus.php',
'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php', 'PhabricatorProjectTestDataGenerator' => 'applications/project/lipsum/PhabricatorProjectTestDataGenerator.php',
'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php', 'PhabricatorProjectTransaction' => 'applications/project/storage/PhabricatorProjectTransaction.php',
@ -3394,13 +3395,18 @@ phutil_register_library_map(array(
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
'PhabricatorProjectEditor' => 'PhabricatorEditor', 'PhabricatorProjectEditor' => 'PhabricatorEditor',
'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase', 'PhabricatorProjectEditorTestCase' => 'PhabricatorTestCase',
'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectListController' =>
array(
0 => 'PhabricatorProjectController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController', 'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
'PhabricatorProjectNameCollisionException' => 'Exception', 'PhabricatorProjectNameCollisionException' => 'Exception',
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO', 'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorProjectQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorProjectSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorProjectTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO', 'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO',
'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants', 'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants',

View file

@ -35,7 +35,7 @@ final class PhabricatorApplicationProject extends PhabricatorApplication {
public function getRoutes() { public function getRoutes() {
return array( return array(
'/project/' => array( '/project/' => array(
'' => 'PhabricatorProjectListController', '(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorProjectListController',
'filter/(?P<filter>[^/]+)/' => 'PhabricatorProjectListController', 'filter/(?P<filter>[^/]+)/' => 'PhabricatorProjectListController',
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectProfileEditController', 'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorProjectProfileEditController',
'members/(?P<id>[1-9]\d*)/' 'members/(?P<id>[1-9]\d*)/'

View file

@ -14,15 +14,6 @@ final class PhabricatorProjectStatus {
return idx($map, coalesce($status, '?'), pht('Unknown')); return idx($map, coalesce($status, '?'), pht('Unknown'));
} }
public static function getIconForStatus($status) {
$map = array(
self::STATUS_ACTIVE => 'check',
self::STATUS_ARCHIVED => 'disable',
);
return idx($map, $status);
}
public static function getStatusMap() { public static function getStatusMap() {
return array( return array(
self::STATUS_ACTIVE => pht('Active'), self::STATUS_ACTIVE => pht('Active'),

View file

@ -2,23 +2,22 @@
abstract class PhabricatorProjectController extends PhabricatorController { abstract class PhabricatorProjectController extends PhabricatorController {
public function buildSideNavView($filter = null, $for_app = false) { public function buildSideNavView($for_app = false) {
$user = $this->getRequest()->getUser(); $user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView(); $nav = new AphrontSideNavFilterView();
$nav $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
->setBaseURI(new PhutilURI('/project/filter/'))
->addLabel(pht('User'))
->addFilter('active', pht('Active'))
->addLabel(pht('All'))
->addFilter('all', pht('All Projects'))
->addFilter('allactive', pht('Active Projects'))
->selectFilter($filter, 'active');
if ($for_app) { if ($for_app) {
$nav->addFilter('create/', pht('Create Project')); $nav->addFilter('create', pht('Create Project'));
} }
id(new PhabricatorProjectSearchEngine())
->setViewer($user)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav; return $nav;
} }

View file

@ -1,151 +1,54 @@
<?php <?php
final class PhabricatorProjectListController final class PhabricatorProjectListController
extends PhabricatorProjectController { extends PhabricatorProjectController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $filter; private $queryKey;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) { public function willProcessRequest(array $data) {
$this->filter = idx($data, 'filter'); $this->queryKey = idx($data, 'queryKey');
} }
public function processRequest() { public function processRequest() {
$request = $this->getRequest(); $request = $this->getRequest();
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setSearchEngine(new PhabricatorProjectSearchEngine())
->setNavigation($this->buildSideNavView());
$nav = $this->buildSideNavView($this->filter); return $this->delegateToController($controller);
$this->filter = $nav->selectFilter($this->filter, 'active');
$pager = new AphrontPagerView();
$pager->setPageSize(250);
$pager->setURI($request->getRequestURI(), 'page');
$pager->setOffset($request->getInt('page'));
$query = new PhabricatorProjectQuery();
$query->setViewer($request->getUser());
$query->needMembers(true);
$view_phid = $request->getUser()->getPHID();
switch ($this->filter) {
case 'active':
$table_header = pht('Your Projects');
$query->withMemberPHIDs(array($view_phid));
$query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
break;
case 'allactive':
$table_header = pht('Active Projects');
$query->withStatus(PhabricatorProjectQuery::STATUS_ACTIVE);
break;
case 'all':
$table_header = pht('All Projects');
$query->withStatus(PhabricatorProjectQuery::STATUS_ANY);
break;
} }
$projects = $query->executeWithOffsetPager($pager); public function renderResultsList(
array $projects,
$project_phids = mpull($projects, 'getPHID'); PhabricatorSavedQuery $query) {
assert_instances_of($projects, 'PhabricatorProject');
$profiles = array(); $viewer = $this->getRequest()->getUser();
if ($projects) {
$profiles = id(new PhabricatorProjectProfile())->loadAllWhere(
'projectPHID in (%Ls)',
$project_phids);
$profiles = mpull($profiles, null, 'getProjectPHID');
}
$tasks = array();
$groups = array();
if ($project_phids) {
$query = id(new ManiphestTaskQuery())
->withAnyProjects($project_phids)
->withStatus(ManiphestTaskQuery::STATUS_OPEN)
->setLimit(PHP_INT_MAX);
$tasks = $query->execute();
foreach ($tasks as $task) {
foreach ($task->getProjectPHIDs() as $phid) {
$groups[$phid][] = $task;
}
}
}
$rows = array();
foreach ($projects as $project) {
$phid = $project->getPHID();
$profile = idx($profiles, $phid);
$members = $project->getMemberPHIDs();
$group = idx($groups, $phid, array());
$task_count = count($group);
$population = count($members);
if ($profile) {
$blurb = $profile->getBlurb();
$blurb = phutil_utf8_shorten($blurb, 64);
} else {
$blurb = null;
}
$tasks_href = pht('%d Open Task(s)', $task_count);
$rows[] = array(
$project->getName(),
'/project/view/'.$project->getID().'/',
PhabricatorProjectStatus::getNameForStatus($project->getStatus()),
PhabricatorProjectStatus::getIconForStatus($project->getStatus()),
$blurb,
pht('%d Member(s)', $population),
phutil_tag(
'a',
array(
'href' => '/maniphest/view/all/?projects='.$phid,
),
$tasks_href),
'/project/edit/'.$project->getID().'/',
);
}
$list = new PhabricatorObjectItemListView(); $list = new PhabricatorObjectItemListView();
$list->setStackable(true); $list->setUser($viewer);
foreach ($rows as $row) { foreach ($projects as $project) {
$id = $project->getID();
$item = id(new PhabricatorObjectItemView()) $item = id(new PhabricatorObjectItemView())
->setHeader($row[0]) ->setHeader($project->getName())
->setHref($row[1]) ->setHref($this->getApplicationURI("view/{$id}/"));
->addIcon($row[3], $row[2])
->addIcon('edit', pht('Edit Project'), array('href' => $row[7])); if ($project->getStatus() == PhabricatorProjectStatus::STATUS_ARCHIVED) {
if ($row[4]) { $item->addIcon('delete-grey', pht('Archived'));
$item->addAttribute($row[4]); $item->setDisabled(true);
} }
$item->addAttribute($row[5]);
$item->addAttribute($row[6]);
$list->addItem($item); $list->addItem($item);
} }
$nav->appendChild( return $list;
array(
$list,
$pager,
));
$crumbs = $this->buildApplicationCrumbs($this->buildSideNavView());
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
->setName($table_header)
->setHref($this->getApplicationURI()));
$nav->setCrumbs($crumbs);
return $this->buildApplicationPage(
$nav,
array(
'title' => pht('Projects'),
'device' => true,
'dust' => true,
));
} }
public function buildApplicationMenu() {
return $this->buildSideNavView(null, true)->getMenu();
}
} }

View file

@ -0,0 +1,112 @@
<?php
final class PhabricatorProjectSearchEngine
extends PhabricatorApplicationSearchEngine {
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter('memberPHIDs', $request->getArr('memberPHIDs'));
$saved->setParameter('status', $request->getStr('status'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorProjectQuery());
$member_phids = $saved->getParameter('memberPHIDs', array());
if ($member_phids && is_array($member_phids)) {
$query->withMemberPHIDs($member_phids);
}
$status = $saved->getParameter('status');
$status = idx($this->getStatusValues(), $status);
if ($status) {
$query->withStatus($status);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved_query) {
$phids = $saved_query->getParameter('memberPHIDs', array());
$handles = id(new PhabricatorObjectHandleData($phids))
->setViewer($this->requireViewer())
->loadHandles();
$member_tokens = mpull($handles, 'getFullName', 'getPHID');
$status = $saved_query->getParameter('status');
$form
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/users/')
->setName('memberPHIDs')
->setLabel(pht('Members'))
->setValue($member_tokens))
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Status'))
->setName('status')
->setOptions($this->getStatusOptions())
->setValue($status));
}
protected function getURI($path) {
return '/project/'.$path;
}
public function getBuiltinQueryNames() {
$names = array();
if ($this->requireViewer()->isLoggedIn()) {
$names['joined'] = pht('Joined');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
$viewer_phid = $this->requireViewer()->getPHID();
switch ($query_key) {
case 'all':
return $query;
case 'active':
return $query
->setParameter('status', 'active');
case 'joined':
return $query
->setParameter('memberPHIDs', array($viewer_phid))
->setParameter('status', 'active');
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
private function getStatusOptions() {
return array(
'active' => pht('Show Only Active Projects'),
'all' => pht('Show All Projects'),
);
}
private function getStatusValues() {
return array(
'active' => PhabricatorProjectQuery::STATUS_ACTIVE,
'all' => PhabricatorProjectQuery::STATUS_ANY,
);
}
}