mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-18 12:52:42 +01:00
Show a more reasonable status element for pull requests
Summary: Ref T182. Replace the total mess we had before with a sort-of-reasonable element. This automatically updates using "javascript". Test Plan: {F901983} {F901984} Used "Land Revision", saw the land status go from "Waiting" -> "Working" -> "Landed" without having to mash reload over and over again. Reviewers: chad Reviewed By: chad Maniphest Tasks: T182 Differential Revision: https://secure.phabricator.com/D14314
This commit is contained in:
parent
421c2453e5
commit
5b619862cb
10 changed files with 237 additions and 23 deletions
|
@ -373,6 +373,7 @@ return array(
|
||||||
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
|
||||||
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
|
||||||
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781',
|
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => 'e5822781',
|
||||||
|
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
|
||||||
'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58',
|
'rsrc/js/application/files/behavior-icon-composer.js' => '8ef9ab58',
|
||||||
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
|
||||||
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
|
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
|
||||||
|
@ -576,6 +577,7 @@ return array(
|
||||||
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
|
||||||
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
'javelin-behavior-doorkeeper-tag' => 'e5822781',
|
||||||
|
'javelin-behavior-drydock-live-operation-status' => '901935ef',
|
||||||
'javelin-behavior-durable-column' => 'c72aa091',
|
'javelin-behavior-durable-column' => 'c72aa091',
|
||||||
'javelin-behavior-error-log' => '6882e80a',
|
'javelin-behavior-error-log' => '6882e80a',
|
||||||
'javelin-behavior-event-all-day' => '38dcf3c8',
|
'javelin-behavior-event-all-day' => '38dcf3c8',
|
||||||
|
@ -1518,6 +1520,11 @@ return array(
|
||||||
'javelin-dom',
|
'javelin-dom',
|
||||||
'javelin-stratcom',
|
'javelin-stratcom',
|
||||||
),
|
),
|
||||||
|
'901935ef' => array(
|
||||||
|
'javelin-behavior',
|
||||||
|
'javelin-dom',
|
||||||
|
'javelin-request',
|
||||||
|
),
|
||||||
'91a6031b' => array(
|
'91a6031b' => array(
|
||||||
'multirow-row-manager',
|
'multirow-row-manager',
|
||||||
'javelin-install',
|
'javelin-install',
|
||||||
|
|
|
@ -885,6 +885,8 @@ phutil_register_library_map(array(
|
||||||
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
|
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
|
||||||
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php',
|
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.php',
|
||||||
'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php',
|
'DrydockRepositoryOperationSearchEngine' => 'applications/drydock/query/DrydockRepositoryOperationSearchEngine.php',
|
||||||
|
'DrydockRepositoryOperationStatusController' => 'applications/drydock/controller/DrydockRepositoryOperationStatusController.php',
|
||||||
|
'DrydockRepositoryOperationStatusView' => 'applications/drydock/view/DrydockRepositoryOperationStatusView.php',
|
||||||
'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php',
|
'DrydockRepositoryOperationType' => 'applications/drydock/operation/DrydockRepositoryOperationType.php',
|
||||||
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
|
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
|
||||||
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
|
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
|
||||||
|
@ -4672,6 +4674,8 @@ phutil_register_library_map(array(
|
||||||
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
|
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
|
||||||
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
|
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
|
||||||
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'DrydockRepositoryOperationStatusController' => 'DrydockController',
|
||||||
|
'DrydockRepositoryOperationStatusView' => 'AphrontView',
|
||||||
'DrydockRepositoryOperationType' => 'Phobject',
|
'DrydockRepositoryOperationType' => 'Phobject',
|
||||||
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
|
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
|
||||||
'DrydockRepositoryOperationViewController' => 'DrydockController',
|
'DrydockRepositoryOperationViewController' => 'DrydockController',
|
||||||
|
|
|
@ -1060,30 +1060,13 @@ final class DifferentialRevisionViewController extends DifferentialController {
|
||||||
|
|
||||||
$operation = head(msort($operations, 'getID'));
|
$operation = head(msort($operations, 'getID'));
|
||||||
|
|
||||||
// TODO: This is completely made up for now, give it useful information and
|
$box_view = id(new PHUIObjectBoxView())
|
||||||
// a sweet progress bar.
|
->setHeaderText(pht('Active Operations'));
|
||||||
|
|
||||||
switch ($operation->getOperationState()) {
|
return id(new DrydockRepositoryOperationStatusView())
|
||||||
case DrydockRepositoryOperation::STATE_WAIT:
|
->setUser($viewer)
|
||||||
case DrydockRepositoryOperation::STATE_WORK:
|
->setBoxView($box_view)
|
||||||
$severity = PHUIInfoView::SEVERITY_NOTICE;
|
->setOperation($operation);
|
||||||
$text = pht(
|
|
||||||
'Some sort of repository operation is currently running.');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$severity = PHUIInfoView::SEVERITY_ERROR;
|
|
||||||
$text = pht(
|
|
||||||
'Some sort of repository operation failed.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$info_view = id(new PHUIInfoView())
|
|
||||||
->setSeverity($severity)
|
|
||||||
->appendChild($text);
|
|
||||||
|
|
||||||
return id(new PHUIObjectBoxView())
|
|
||||||
->setHeaderText(pht('Active Operations (EXPERIMENTAL!)'))
|
|
||||||
->setInfoView($info_view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,7 @@ final class PhabricatorDrydockApplication extends PhabricatorApplication {
|
||||||
=> 'DrydockRepositoryOperationListController',
|
=> 'DrydockRepositoryOperationListController',
|
||||||
'(?P<id>[1-9]\d*)/' => array(
|
'(?P<id>[1-9]\d*)/' => array(
|
||||||
'' => 'DrydockRepositoryOperationViewController',
|
'' => 'DrydockRepositoryOperationViewController',
|
||||||
|
'status/' => 'DrydockRepositoryOperationStatusController',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockRepositoryOperationStatusController
|
||||||
|
extends DrydockController {
|
||||||
|
|
||||||
|
public function shouldAllowPublic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $request->getViewer();
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
|
$operation = id(new DrydockRepositoryOperationQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$operation) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$status_view = id(new DrydockRepositoryOperationStatusView())
|
||||||
|
->setUser($viewer)
|
||||||
|
->setOperation($operation);
|
||||||
|
|
||||||
|
if ($request->isAjax()) {
|
||||||
|
$payload = array(
|
||||||
|
'markup' => $status_view->renderUnderwayState(),
|
||||||
|
'isUnderway' => $operation->isUnderway(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
$title = pht('Repository Operation %d', $id);
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
$crumbs->addTextCrumb(
|
||||||
|
pht('Operations'),
|
||||||
|
$this->getApplicationURI('operation/'));
|
||||||
|
$crumbs->addTextCrumb($title);
|
||||||
|
|
||||||
|
return $this->buildApplicationPage(
|
||||||
|
array(
|
||||||
|
$crumbs,
|
||||||
|
$status_view,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => array(
|
||||||
|
$title,
|
||||||
|
pht('Status'),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,30 @@ final class DrydockLandRepositoryOperation
|
||||||
return pht('Land Revision');
|
return pht('Land Revision');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOperationCurrentStatus(
|
||||||
|
DrydockRepositoryOperation $operation,
|
||||||
|
PhabricatorUser $viewer) {
|
||||||
|
|
||||||
|
$target = $operation->getRepositoryTarget();
|
||||||
|
$repository = $operation->getRepository();
|
||||||
|
switch ($operation->getOperationState()) {
|
||||||
|
case DrydockRepositoryOperation::STATE_WAIT:
|
||||||
|
return pht(
|
||||||
|
'Waiting to land revision into %s on %s...',
|
||||||
|
$repository->getMonogram(),
|
||||||
|
$target);
|
||||||
|
case DrydockRepositoryOperation::STATE_WORK:
|
||||||
|
return pht(
|
||||||
|
'Landing revision into %s on %s...',
|
||||||
|
$repository->getMonogram(),
|
||||||
|
$target);
|
||||||
|
case DrydockRepositoryOperation::STATE_DONE:
|
||||||
|
return pht(
|
||||||
|
'Revision landed into %s.',
|
||||||
|
$repository->getMonogram());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function applyOperation(
|
public function applyOperation(
|
||||||
DrydockRepositoryOperation $operation,
|
DrydockRepositoryOperation $operation,
|
||||||
DrydockInterface $interface) {
|
DrydockInterface $interface) {
|
||||||
|
|
|
@ -12,6 +12,10 @@ abstract class DrydockRepositoryOperationType extends Phobject {
|
||||||
DrydockRepositoryOperation $operation,
|
DrydockRepositoryOperation $operation,
|
||||||
PhabricatorUser $viewer);
|
PhabricatorUser $viewer);
|
||||||
|
|
||||||
|
abstract public function getOperationCurrentStatus(
|
||||||
|
DrydockRepositoryOperation $operation,
|
||||||
|
PhabricatorUser $viewer);
|
||||||
|
|
||||||
final public function setViewer(PhabricatorUser $viewer) {
|
final public function setViewer(PhabricatorUser $viewer) {
|
||||||
$this->viewer = $viewer;
|
$this->viewer = $viewer;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -142,6 +142,22 @@ final class DrydockRepositoryOperation extends DrydockDAO
|
||||||
$viewer);
|
$viewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOperationCurrentStatus(PhabricatorUser $viewer) {
|
||||||
|
return $this->getImplementation()->getOperationCurrentStatus(
|
||||||
|
$this,
|
||||||
|
$viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isUnderway() {
|
||||||
|
switch ($this->getOperationState()) {
|
||||||
|
case self::STATE_WAIT:
|
||||||
|
case self::STATE_WORK:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class DrydockRepositoryOperationStatusView
|
||||||
|
extends AphrontView {
|
||||||
|
|
||||||
|
private $operation;
|
||||||
|
private $boxView;
|
||||||
|
|
||||||
|
public function setOperation(DrydockRepositoryOperation $operation) {
|
||||||
|
$this->operation = $operation;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getOperation() {
|
||||||
|
return $this->operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setBoxView(PHUIObjectBoxView $box_view) {
|
||||||
|
$this->boxView = $box_view;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBoxView() {
|
||||||
|
return $this->boxView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
$viewer = $this->getUser();
|
||||||
|
$operation = $this->getOperation();
|
||||||
|
|
||||||
|
$list = $this->renderUnderwayState();
|
||||||
|
|
||||||
|
// If the operation is currently underway, refresh the status view.
|
||||||
|
if ($operation->isUnderway()) {
|
||||||
|
$status_id = celerity_generate_unique_node_id();
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$list->setID($status_id);
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'drydock-live-operation-status',
|
||||||
|
array(
|
||||||
|
'statusID' => $status_id,
|
||||||
|
'updateURI' => "/drydock/operation/{$id}/status/",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$box_view = $this->getBoxView();
|
||||||
|
if (!$box_view) {
|
||||||
|
$box_view = id(new PHUIObjectBoxView())
|
||||||
|
->setHeaderText(pht('Operation Status'));
|
||||||
|
}
|
||||||
|
$box_view->setObjectList($list);
|
||||||
|
|
||||||
|
return $box_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function renderUnderwayState() {
|
||||||
|
$viewer = $this->getUser();
|
||||||
|
$operation = $this->getOperation();
|
||||||
|
|
||||||
|
$id = $operation->getID();
|
||||||
|
|
||||||
|
$state = $operation->getOperationState();
|
||||||
|
$icon = DrydockRepositoryOperation::getOperationStateIcon($state);
|
||||||
|
$name = DrydockRepositoryOperation::getOperationStateName($state);
|
||||||
|
|
||||||
|
$item = id(new PHUIObjectItemView())
|
||||||
|
->setHref("/drydock/operation/{$id}/")
|
||||||
|
->setHeader($operation->getOperationDescription($viewer))
|
||||||
|
->setStatusIcon($icon, $name);
|
||||||
|
|
||||||
|
if ($state != DrydockRepositoryOperation::STATE_FAIL) {
|
||||||
|
$item->addAttribute($operation->getOperationCurrentStatus($viewer));
|
||||||
|
} else {
|
||||||
|
// TODO: Make this more useful.
|
||||||
|
$item->addAttribute(pht('Operation encountered an error.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PHUIObjectItemListView())
|
||||||
|
->addItem($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-drydock-live-operation-status
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-request
|
||||||
|
* @javelin
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('drydock-live-operation-status', function(config) {
|
||||||
|
var node = JX.$(config.statusID);
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
new JX.Request(config.updateURI, onresponse)
|
||||||
|
.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onresponse(r) {
|
||||||
|
var new_node = JX.$H(r.markup).getNode();
|
||||||
|
JX.DOM.replace(node, new_node);
|
||||||
|
node = new_node;
|
||||||
|
|
||||||
|
if (r.isUnderway) {
|
||||||
|
poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function poll() {
|
||||||
|
setTimeout(update, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
poll();
|
||||||
|
});
|
Loading…
Reference in a new issue