mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Rough in a Nuance "work" controller
Summary: Ref T12738. This is mostly just laying in groundwork and prerequisites, like the ability to query items by queue. Eventually, this will become the main UI which staff use to process a queue of items. For now, it does nothing and renders nonsense. This and probably the next big chunk of changes are all going to be made-up, nonfinal things that just make basic operations work until we have fundamental flows -- like "assign", "comment", "close" -- working at a basic level and can think more about UI/workflow. Test Plan: Visited the page, it loaded a mostly-reasonable item and then rendered nonsense: {F4975050} Reviewers: chad Reviewed By: chad Maniphest Tasks: T12738 Differential Revision: https://secure.phabricator.com/D18008
This commit is contained in:
parent
272a5d668f
commit
cbf9008d15
7 changed files with 197 additions and 4 deletions
|
@ -1663,6 +1663,7 @@ phutil_register_library_map(array(
|
||||||
'NuanceQueueTransactionQuery' => 'applications/nuance/query/NuanceQueueTransactionQuery.php',
|
'NuanceQueueTransactionQuery' => 'applications/nuance/query/NuanceQueueTransactionQuery.php',
|
||||||
'NuanceQueueTransactionType' => 'applications/nuance/xaction/NuanceQueueTransactionType.php',
|
'NuanceQueueTransactionType' => 'applications/nuance/xaction/NuanceQueueTransactionType.php',
|
||||||
'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php',
|
'NuanceQueueViewController' => 'applications/nuance/controller/NuanceQueueViewController.php',
|
||||||
|
'NuanceQueueWorkController' => 'applications/nuance/controller/NuanceQueueWorkController.php',
|
||||||
'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php',
|
'NuanceSchemaSpec' => 'applications/nuance/storage/NuanceSchemaSpec.php',
|
||||||
'NuanceSource' => 'applications/nuance/storage/NuanceSource.php',
|
'NuanceSource' => 'applications/nuance/storage/NuanceSource.php',
|
||||||
'NuanceSourceActionController' => 'applications/nuance/controller/NuanceSourceActionController.php',
|
'NuanceSourceActionController' => 'applications/nuance/controller/NuanceSourceActionController.php',
|
||||||
|
@ -6788,6 +6789,7 @@ phutil_register_library_map(array(
|
||||||
'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
'NuanceQueueTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||||
'NuanceQueueTransactionType' => 'PhabricatorModularTransactionType',
|
'NuanceQueueTransactionType' => 'PhabricatorModularTransactionType',
|
||||||
'NuanceQueueViewController' => 'NuanceQueueController',
|
'NuanceQueueViewController' => 'NuanceQueueController',
|
||||||
|
'NuanceQueueWorkController' => 'NuanceQueueController',
|
||||||
'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'NuanceSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
'NuanceSource' => array(
|
'NuanceSource' => array(
|
||||||
'NuanceDAO',
|
'NuanceDAO',
|
||||||
|
|
|
@ -51,6 +51,7 @@ final class PhabricatorNuanceApplication extends PhabricatorApplication {
|
||||||
$this->getQueryRoutePattern() => 'NuanceQueueListController',
|
$this->getQueryRoutePattern() => 'NuanceQueueListController',
|
||||||
$this->getEditRoutePattern('edit/') => 'NuanceQueueEditController',
|
$this->getEditRoutePattern('edit/') => 'NuanceQueueEditController',
|
||||||
'view/(?P<id>[1-9]\d*)/' => 'NuanceQueueViewController',
|
'view/(?P<id>[1-9]\d*)/' => 'NuanceQueueViewController',
|
||||||
|
'work/(?P<id>[1-9]\d*)/' => 'NuanceQueueWorkController',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'/action/' => array(
|
'/action/' => array(
|
||||||
|
|
|
@ -70,6 +70,14 @@ final class NuanceQueueViewController
|
||||||
->setDisabled(!$can_edit)
|
->setDisabled(!$can_edit)
|
||||||
->setWorkflow(!$can_edit));
|
->setWorkflow(!$can_edit));
|
||||||
|
|
||||||
|
$curtain->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('Begin Work'))
|
||||||
|
->setIcon('fa-play-circle-o')
|
||||||
|
->setHref($this->getApplicationURI("queue/work/{$id}/"))
|
||||||
|
->setDisabled(!$can_edit)
|
||||||
|
->setWorkflow(!$can_edit));
|
||||||
|
|
||||||
return $curtain;
|
return $curtain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class NuanceQueueWorkController
|
||||||
|
extends NuanceQueueController {
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$queue = id(new NuanceQueueQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($request->getURIData('id')))
|
||||||
|
->executeOne();
|
||||||
|
if (!$queue) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = $queue->getName();
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb(pht('Queues'), $this->getApplicationURI('queue/'));
|
||||||
|
$crumbs->addTextCrumb($queue->getName(), $queue->getURI());
|
||||||
|
$crumbs->addTextCrumb(pht('Work'));
|
||||||
|
$crumbs->setBorder(true);
|
||||||
|
|
||||||
|
// For now, just pick the first open item.
|
||||||
|
|
||||||
|
$items = id(new NuanceItemQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withQueuePHIDs(
|
||||||
|
array(
|
||||||
|
$queue->getPHID(),
|
||||||
|
))
|
||||||
|
->withStatuses(
|
||||||
|
array(
|
||||||
|
NuanceItem::STATUS_OPEN,
|
||||||
|
))
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->setLimit(5)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
if (!$items) {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Queue Empty'))
|
||||||
|
->appendParagraph(
|
||||||
|
pht(
|
||||||
|
'This queue has no open items which you have permission to '.
|
||||||
|
'work on.'))
|
||||||
|
->addCancelButton($queue->getURI());
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = head($items);
|
||||||
|
|
||||||
|
$curtain = $this->buildCurtain($queue);
|
||||||
|
|
||||||
|
$timeline = $this->buildTransactionTimeline(
|
||||||
|
$item,
|
||||||
|
new NuanceItemTransactionQuery());
|
||||||
|
$timeline->setShouldTerminate(true);
|
||||||
|
|
||||||
|
$view = id(new PHUITwoColumnView())
|
||||||
|
->setCurtain($curtain)
|
||||||
|
->setMainColumn($timeline);
|
||||||
|
|
||||||
|
return $this->newPage()
|
||||||
|
->setTitle($title)
|
||||||
|
->setCrumbs($crumbs)
|
||||||
|
->appendChild($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildCurtain(NuanceQueue $queue) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $queue->getID();
|
||||||
|
|
||||||
|
$curtain = $this->newCurtainView();
|
||||||
|
|
||||||
|
$curtain->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setType(PhabricatorActionView::TYPE_DIVIDER));
|
||||||
|
|
||||||
|
$curtain->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setType(PhabricatorActionView::TYPE_LABEL)
|
||||||
|
->setName(pht('Queue Actions')));
|
||||||
|
|
||||||
|
$curtain->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName(pht('Manage Queue'))
|
||||||
|
->setIcon('fa-cog')
|
||||||
|
->setHref($this->getApplicationURI("queue/view/{$id}/")));
|
||||||
|
|
||||||
|
return $curtain;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,9 +6,11 @@ final class NuanceItemQuery
|
||||||
private $ids;
|
private $ids;
|
||||||
private $phids;
|
private $phids;
|
||||||
private $sourcePHIDs;
|
private $sourcePHIDs;
|
||||||
|
private $queuePHIDs;
|
||||||
private $itemTypes;
|
private $itemTypes;
|
||||||
private $itemKeys;
|
private $itemKeys;
|
||||||
private $containerKeys;
|
private $containerKeys;
|
||||||
|
private $statuses;
|
||||||
|
|
||||||
public function withIDs(array $ids) {
|
public function withIDs(array $ids) {
|
||||||
$this->ids = $ids;
|
$this->ids = $ids;
|
||||||
|
@ -25,6 +27,11 @@ final class NuanceItemQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withQueuePHIDs(array $queue_phids) {
|
||||||
|
$this->queuePHIDs = $queue_phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withItemTypes(array $item_types) {
|
public function withItemTypes(array $item_types) {
|
||||||
$this->itemTypes = $item_types;
|
$this->itemTypes = $item_types;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -35,6 +42,11 @@ final class NuanceItemQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withStatuses(array $statuses) {
|
||||||
|
$this->statuses = $statuses;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withItemContainerKeys(array $container_keys) {
|
public function withItemContainerKeys(array $container_keys) {
|
||||||
$this->containerKeys = $container_keys;
|
$this->containerKeys = $container_keys;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -49,13 +61,11 @@ final class NuanceItemQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function willFilterPage(array $items) {
|
protected function willFilterPage(array $items) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
$source_phids = mpull($items, 'getSourcePHID');
|
$source_phids = mpull($items, 'getSourcePHID');
|
||||||
|
|
||||||
// NOTE: We always load sources, even if the viewer can't formally see
|
|
||||||
// them. If they can see the item, they're allowed to be aware of the
|
|
||||||
// source in some sense.
|
|
||||||
$sources = id(new NuanceSourceQuery())
|
$sources = id(new NuanceSourceQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer($viewer)
|
||||||
->withPHIDs($source_phids)
|
->withPHIDs($source_phids)
|
||||||
->execute();
|
->execute();
|
||||||
$sources = mpull($sources, null, 'getPHID');
|
$sources = mpull($sources, null, 'getPHID');
|
||||||
|
@ -81,6 +91,43 @@ final class NuanceItemQuery
|
||||||
$item->attachImplementation($type);
|
$item->attachImplementation($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$queue_phids = array();
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$queue_phid = $item->getQueuePHID();
|
||||||
|
if ($queue_phid) {
|
||||||
|
$queue_phids[$queue_phid] = $queue_phid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($queue_phids) {
|
||||||
|
$queues = id(new NuanceQueueQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withPHIDs($queue_phids)
|
||||||
|
->execute();
|
||||||
|
$queues = mpull($queues, null, 'getPHID');
|
||||||
|
} else {
|
||||||
|
$queues = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($items as $key => $item) {
|
||||||
|
$queue_phid = $item->getQueuePHID();
|
||||||
|
|
||||||
|
if (!$queue_phid) {
|
||||||
|
$item->attachQueue(null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$queue = idx($queues, $queue_phid);
|
||||||
|
|
||||||
|
if (!$queue) {
|
||||||
|
unset($items[$key]);
|
||||||
|
$this->didRejectResult($item);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->attachQueue($queue);
|
||||||
|
}
|
||||||
|
|
||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +141,13 @@ final class NuanceItemQuery
|
||||||
$this->sourcePHIDs);
|
$this->sourcePHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->queuePHIDs !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'queuePHID IN (%Ls)',
|
||||||
|
$this->queuePHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->ids !== null) {
|
if ($this->ids !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
|
@ -108,6 +162,13 @@ final class NuanceItemQuery
|
||||||
$this->phids);
|
$this->phids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->statuses !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'status IN (%Ls)',
|
||||||
|
$this->statuses);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->itemTypes !== null) {
|
if ($this->itemTypes !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
|
|
|
@ -72,6 +72,19 @@ final class NuanceItemSearchEngine
|
||||||
$impl->getItemTypeDisplayIcon(),
|
$impl->getItemTypeDisplayIcon(),
|
||||||
$impl->getItemTypeDisplayName());
|
$impl->getItemTypeDisplayName());
|
||||||
|
|
||||||
|
$queue = $item->getQueue();
|
||||||
|
if ($queue) {
|
||||||
|
$view->addAttribute(
|
||||||
|
phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $queue->getURI(),
|
||||||
|
),
|
||||||
|
$queue->getName()));
|
||||||
|
} else {
|
||||||
|
$view->addAttribute(phutil_tag('em', array(), pht('Not in Queue')));
|
||||||
|
}
|
||||||
|
|
||||||
$list->addItem($view);
|
$list->addItem($view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ final class NuanceItem
|
||||||
protected $data = array();
|
protected $data = array();
|
||||||
protected $mailKey;
|
protected $mailKey;
|
||||||
|
|
||||||
|
private $queue = self::ATTACHABLE;
|
||||||
private $source = self::ATTACHABLE;
|
private $source = self::ATTACHABLE;
|
||||||
private $implementation = self::ATTACHABLE;
|
private $implementation = self::ATTACHABLE;
|
||||||
|
|
||||||
|
@ -176,6 +177,15 @@ final class NuanceItem
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getQueue() {
|
||||||
|
return $this->assertAttached($this->queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachQueue(NuanceQueue $queue = null) {
|
||||||
|
$this->queue = $queue;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue