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

Use ApplicationSearch in the calendar event list view

Summary: Ref T4375. Basic ApplicationSearch integration to power this more flexibly.

Test Plan: {F108762}

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T4375

Differential Revision: https://secure.phabricator.com/D8148
This commit is contained in:
epriestley 2014-02-06 10:10:18 -08:00
parent 8410cbecb0
commit 0ae0f352b0
7 changed files with 262 additions and 89 deletions

View file

@ -1267,6 +1267,7 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventListController' => 'applications/calendar/controller/PhabricatorCalendarEventListController.php',
'PhabricatorCalendarEventOverlapException' => 'applications/calendar/exception/PhabricatorCalendarEventOverlapException.php',
'PhabricatorCalendarEventQuery' => 'applications/calendar/query/PhabricatorCalendarEventQuery.php',
'PhabricatorCalendarEventSearchEngine' => 'applications/calendar/query/PhabricatorCalendarEventSearchEngine.php',
'PhabricatorCalendarHoliday' => 'applications/calendar/storage/PhabricatorCalendarHoliday.php',
'PhabricatorCalendarHolidayTestCase' => 'applications/calendar/storage/__tests__/PhabricatorCalendarHolidayTestCase.php',
'PhabricatorCampfireProtocolAdapter' => 'infrastructure/daemon/bot/adapter/PhabricatorCampfireProtocolAdapter.php',
@ -3907,9 +3908,14 @@ phutil_register_library_map(array(
'PhabricatorCalendarEventDeleteController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventEditController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventInvalidEpochException' => 'Exception',
'PhabricatorCalendarEventListController' => 'PhabricatorCalendarController',
'PhabricatorCalendarEventListController' =>
array(
0 => 'PhabricatorCalendarController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'PhabricatorCalendarEventOverlapException' => 'Exception',
'PhabricatorCalendarEventQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorCalendarEventSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorCalendarHoliday' => 'PhabricatorCalendarDAO',
'PhabricatorCalendarHolidayTestCase' => 'PhabricatorTestCase',
'PhabricatorCampfireProtocolAdapter' => 'PhabricatorBotBaseStreamingProtocolAdapter',

View file

@ -37,7 +37,8 @@ final class PhabricatorApplicationCalendar extends PhabricatorApplication {
'/calendar/' => array(
'' => 'PhabricatorCalendarBrowseController',
'event/' => array(
'' => 'PhabricatorCalendarEventListController',
'(?:query/(?P<queryKey>[^/]+)/)?' =>
'PhabricatorCalendarEventListController',
'create/' =>
'PhabricatorCalendarEventEditController',
'edit/(?P<id>[1-9]\d*)/' =>

View file

@ -1,62 +1,66 @@
<?php
final class PhabricatorCalendarEventListController
extends PhabricatorCalendarController {
extends PhabricatorCalendarController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $phid;
private $queryKey;
public function willProcessRequest(array $data) {
$user = $this->getRequest()->getUser();
$this->phid = idx($data, 'phid', $user->getPHID());
$this->loadHandles(array($this->phid));
$this->queryKey = idx($data, 'queryKey');
}
public function processRequest() {
$request = $this->getRequest();
$user = $request->getUser();
$handle = $this->getHandle($this->phid);
$statuses = id(new PhabricatorCalendarEventQuery())
->setViewer($user)
->withInvitedPHIDs(array($this->phid))
->withDateRange(time(), strtotime('2037-01-01 12:00:00'))
->execute();
$nav = $this->buildSideNavView();
$nav->selectFilter($this->getFilter());
$page_title = $this->getPageTitle();
$status_list = $this->buildStatusList($statuses);
$status_list->setNoDataString($this->getNoDataString());
$nav->appendChild(
array(
id(new PHUIHeaderView())->setHeader($page_title),
$status_list,
));
return $this->buildApplicationPage(
$nav,
array(
'title' => $page_title,
'device' => true
));
$request = $this->getRequest();
$controller = id(new PhabricatorApplicationSearchController($request))
->setQueryKey($this->queryKey)
->setSearchEngine(new PhabricatorCalendarEventSearchEngine())
->setNavigation($this->buildSideNav());
return $this->delegateToController($controller);
}
private function buildStatusList(array $statuses) {
assert_instances_of($statuses, 'PhabricatorCalendarEvent');
public function buildSideNav() {
$user = $this->getRequest()->getUser();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
id(new PhabricatorCalendarEventSearchEngine())
->setViewer($user)
->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
return $nav;
}
public function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$crumbs->addAction(
id(new PHUIListItemView())
->setIcon('create')
->setName(pht('Create Event'))
->setHref($this->getApplicationURI().'create/'));
return $crumbs;
}
public function renderResultsList(
array $events,
PhabricatorSavedQuery $query) {
assert_instances_of($events, 'PhabricatorCalendarEvent');
$viewer = $this->getRequest()->getUser();
$list = new PHUIObjectItemListView();
foreach ($statuses as $status) {
if ($status->getUserPHID() == $user->getPHID()) {
$href = $this->getApplicationURI('/event/edit/'.$status->getID().'/');
foreach ($events as $event) {
if ($event->getUserPHID() == $viewer->getPHID()) {
$href = $this->getApplicationURI('/event/edit/'.$event->getID().'/');
} else {
$from = $status->getDateFrom();
$month = phabricator_format_local_time($from, $user, 'm');
$year = phabricator_format_local_time($from, $user, 'Y');
$from = $event->getDateFrom();
$month = phabricator_format_local_time($from, $viewer, 'm');
$year = phabricator_format_local_time($from, $viewer, 'Y');
$uri = new PhutilURI($this->getApplicationURI());
$uri->setQueryParams(
array(
@ -65,20 +69,20 @@ final class PhabricatorCalendarEventListController
));
$href = (string) $uri;
}
$from = phabricator_datetime($status->getDateFrom(), $user);
$to = phabricator_datetime($status->getDateTo(), $user);
$from = phabricator_datetime($event->getDateFrom(), $viewer);
$to = phabricator_datetime($event->getDateTo(), $viewer);
$color = ($status->getStatus() == PhabricatorCalendarEvent::STATUS_AWAY)
$color = ($event->getStatus() == PhabricatorCalendarEvent::STATUS_AWAY)
? 'red'
: 'yellow';
$item = id(new PHUIObjectItemView())
->setHeader($status->getTerseSummary($user))
->setHeader($event->getTerseSummary($viewer))
->setHref($href)
->setBarColor($color)
->addAttribute(pht('From %s to %s', $from, $to))
->addAttribute(
phutil_utf8_shorten($status->getDescription(), 64));
phutil_utf8_shorten($event->getDescription(), 64));
$list->addItem($item);
}
@ -86,38 +90,4 @@ final class PhabricatorCalendarEventListController
return $list;
}
private function getNoDataString() {
if ($this->isUserRequest()) {
$no_data =
pht('You do not have any upcoming status events.');
} else {
$no_data =
pht('%s does not have any upcoming status events.',
$this->getHandle($this->phid)->getName());
}
return $no_data;
}
private function getFilter() {
$filter = 'event/';
return $filter;
}
private function getPageTitle() {
if ($this->isUserRequest()) {
$page_title = pht('Upcoming Statuses');
} else {
$page_title = pht(
'Upcoming Statuses for %s',
$this->getHandle($this->phid)->getName());
}
return $page_title;
}
private function isUserRequest() {
$user = $this->getRequest()->getUser();
return $this->phid == $user->getPHID();
}
}

View file

@ -7,6 +7,7 @@ final class PhabricatorCalendarEventQuery
private $rangeBegin;
private $rangeEnd;
private $invitedPHIDs;
private $creatorPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
@ -24,6 +25,11 @@ final class PhabricatorCalendarEventQuery
return $this;
}
public function withCreatorPHIDs(array $phids) {
$this->creatorPHIDs = $phids;
return $this;
}
protected function loadPage() {
$table = new PhabricatorCalendarEvent();
$conn_r = $table->establishConnection('r');
@ -49,14 +55,23 @@ final class PhabricatorCalendarEventQuery
$this->ids);
}
if ($this->rangeBegin || $this->rangeEnd) {
if ($this->rangeBegin) {
$where[] = qsprintf(
$conn_r,
'dateTo >= %d AND dateFrom <= %d',
$this->rangeBegin,
'dateTo >= %d',
$this->rangeBegin);
}
if ($this->rangeEnd) {
$where[] = qsprintf(
$conn_r,
'dateFrom <= %d',
$this->rangeEnd);
}
// TODO: Currently, the creator is always the only invitee, but you can
// query them separately since this won't always be true.
if ($this->invitedPHIDs) {
$where[] = qsprintf(
$conn_r,
@ -64,6 +79,13 @@ final class PhabricatorCalendarEventQuery
$this->invitedPHIDs);
}
if ($this->creatorPHIDs) {
$where[] = qsprintf(
$conn_r,
'userPHID IN (%Ls)',
$this->creatorPHIDs);
}
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);

View file

@ -0,0 +1,163 @@
<?php
final class PhabricatorCalendarEventSearchEngine
extends PhabricatorApplicationSearchEngine {
public function buildSavedQueryFromRequest(AphrontRequest $request) {
$saved = new PhabricatorSavedQuery();
$saved->setParameter(
'rangeStart',
$this->readDateFromRequest($request, 'rangeStart'));
$saved->setParameter(
'rangeEnd',
$this->readDateFromRequest($request, 'rangeEnd'));
$saved->setParameter(
'upcoming',
$this->readBoolFromRequest($request, 'upcoming'));
$saved->setParameter(
'invitedPHIDs',
$this->readUsersFromRequest($request, 'invited'));
$saved->setParameter(
'creatorPHIDs',
$this->readUsersFromRequest($request, 'creators'));
return $saved;
}
public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
$query = id(new PhabricatorCalendarEventQuery());
$min_range = null;
$max_range = null;
if ($saved->getParameter('rangeStart')) {
$min_range = $saved->getParameter('rangeStart');
}
if ($saved->getParameter('rangeEnd')) {
$max_range = $saved->getParameter('rangeEnd');
}
if ($saved->getParameter('upcoming')) {
if ($min_range) {
$min_range = max(time(), $min_range);
} else {
$min_range = time();
}
}
if ($min_range || $max_range) {
$query->withDateRange($min_range, $max_range);
}
$invited_phids = $saved->getParameter('invitedPHIDs');
if ($invited_phids) {
$query->withInvitedPHIDs($invited_phids);
}
$creator_phids = $saved->getParameter('creatorPHIDs');
if ($creator_phids) {
$query->withCreatorPHIDs($creator_phids);
}
return $query;
}
public function buildSearchForm(
AphrontFormView $form,
PhabricatorSavedQuery $saved) {
$range_start = $saved->getParameter('rangeStart');
$range_end = $saved->getParameter('rangeEnd');
$upcoming = $saved->getParameter('upcoming');
$invited_phids = $saved->getParameter('invitedPHIDs', array());
$creator_phids = $saved->getParameter('creatorPHIDs', array());
$all_phids = array_merge(
$invited_phids,
$creator_phids);
if ($all_phids) {
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->requireViewer())
->withPHIDs($all_phids)
->execute();
} else {
$handles = array();
}
$invited_handles = array_select_keys($handles, $invited_phids);
$creator_handles = array_select_keys($handles, $creator_phids);
$form
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/accounts/')
->setName('creators')
->setLabel(pht('Created By'))
->setValue($creator_handles))
->appendChild(
id(new AphrontFormTokenizerControl())
->setDatasource('/typeahead/common/accounts/')
->setName('invited')
->setLabel(pht('Invited'))
->setValue($invited_handles))
->appendChild(
id(new AphrontFormDateControl())
->setLabel(pht('Occurs After'))
->setUser($this->requireViewer())
->setName('rangeStart')
->setAllowNull(true)
->setValue($range_start))
->appendChild(
id(new AphrontFormDateControl())
->setLabel(pht('Occurs Before'))
->setUser($this->requireViewer())
->setName('rangeEnd')
->setAllowNull(true)
->setValue($range_end))
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
'upcoming',
1,
pht('Show only upcoming events.'),
$upcoming));
}
protected function getURI($path) {
return '/calendar/event/'.$path;
}
public function getBuiltinQueryNames() {
$names = array(
'upcoming' => pht('Upcoming Events'),
'all' => pht('All Events'),
);
return $names;
}
public function buildSavedQueryFromBuiltin($query_key) {
$query = $this->newSavedQuery();
$query->setQueryKey($query_key);
switch ($query_key) {
case 'upcoming':
return $query->setParameter('upcoming', true);
case 'all':
return $query;
}
return parent::buildSavedQueryFromBuiltin($query_key);
}
}

View file

@ -368,6 +368,17 @@ abstract class PhabricatorApplicationSearchEngine {
return $list;
}
protected function readDateFromRequest(
AphrontRequest $request,
$key) {
return id(new AphrontFormDateControl())
->setUser($this->requireViewer())
->setName($key)
->setAllowNull(true)
->readValueFromRequest($request);
}
protected function readBoolFromRequest(
AphrontRequest $request,
$key) {

View file

@ -87,7 +87,7 @@ final class AphrontFormDateControl extends AphrontFormControl {
$result = parent::setValue($epoch);
if ($epoch === null) {
return;
return $result;
}
$readable = $this->formatTime($epoch, 'Y!m!d!g:i A');