Page MenuHomePhabricator

D14314.id.diff
No OneTemporary

D14314.id.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -373,6 +373,7 @@
'rsrc/js/application/diffusion/behavior-locate-file.js' => '6d3e1947',
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
'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-launch-icon-composer.js' => '48086888',
'rsrc/js/application/herald/HeraldRuleEditor.js' => '91a6031b',
@@ -576,6 +577,7 @@
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
'javelin-behavior-doorkeeper-tag' => 'e5822781',
+ 'javelin-behavior-drydock-live-operation-status' => '901935ef',
'javelin-behavior-durable-column' => 'c72aa091',
'javelin-behavior-error-log' => '6882e80a',
'javelin-behavior-event-all-day' => '38dcf3c8',
@@ -1518,6 +1520,11 @@
'javelin-dom',
'javelin-stratcom',
),
+ '901935ef' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-request',
+ ),
'91a6031b' => array(
'multirow-row-manager',
'javelin-install',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -885,6 +885,8 @@
'DrydockRepositoryOperationPHIDType' => 'applications/drydock/phid/DrydockRepositoryOperationPHIDType.php',
'DrydockRepositoryOperationQuery' => 'applications/drydock/query/DrydockRepositoryOperationQuery.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',
'DrydockRepositoryOperationUpdateWorker' => 'applications/drydock/worker/DrydockRepositoryOperationUpdateWorker.php',
'DrydockRepositoryOperationViewController' => 'applications/drydock/controller/DrydockRepositoryOperationViewController.php',
@@ -4672,6 +4674,8 @@
'DrydockRepositoryOperationPHIDType' => 'PhabricatorPHIDType',
'DrydockRepositoryOperationQuery' => 'DrydockQuery',
'DrydockRepositoryOperationSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'DrydockRepositoryOperationStatusController' => 'DrydockController',
+ 'DrydockRepositoryOperationStatusView' => 'AphrontView',
'DrydockRepositoryOperationType' => 'Phobject',
'DrydockRepositoryOperationUpdateWorker' => 'DrydockWorker',
'DrydockRepositoryOperationViewController' => 'DrydockController',
diff --git a/src/applications/differential/controller/DifferentialRevisionViewController.php b/src/applications/differential/controller/DifferentialRevisionViewController.php
--- a/src/applications/differential/controller/DifferentialRevisionViewController.php
+++ b/src/applications/differential/controller/DifferentialRevisionViewController.php
@@ -1060,30 +1060,13 @@
$operation = head(msort($operations, 'getID'));
- // TODO: This is completely made up for now, give it useful information and
- // a sweet progress bar.
-
- switch ($operation->getOperationState()) {
- case DrydockRepositoryOperation::STATE_WAIT:
- case DrydockRepositoryOperation::STATE_WORK:
- $severity = PHUIInfoView::SEVERITY_NOTICE;
- $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);
+ $box_view = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('Active Operations'));
- return id(new PHUIObjectBoxView())
- ->setHeaderText(pht('Active Operations (EXPERIMENTAL!)'))
- ->setInfoView($info_view);
+ return id(new DrydockRepositoryOperationStatusView())
+ ->setUser($viewer)
+ ->setBoxView($box_view)
+ ->setOperation($operation);
}
}
diff --git a/src/applications/drydock/application/PhabricatorDrydockApplication.php b/src/applications/drydock/application/PhabricatorDrydockApplication.php
--- a/src/applications/drydock/application/PhabricatorDrydockApplication.php
+++ b/src/applications/drydock/application/PhabricatorDrydockApplication.php
@@ -95,6 +95,7 @@
=> 'DrydockRepositoryOperationListController',
'(?P<id>[1-9]\d*)/' => array(
'' => 'DrydockRepositoryOperationViewController',
+ 'status/' => 'DrydockRepositoryOperationStatusController',
),
),
),
diff --git a/src/applications/drydock/controller/DrydockRepositoryOperationStatusController.php b/src/applications/drydock/controller/DrydockRepositoryOperationStatusController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/controller/DrydockRepositoryOperationStatusController.php
@@ -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'),
+ ),
+ ));
+ }
+
+}
diff --git a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
--- a/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
+++ b/src/applications/drydock/operation/DrydockLandRepositoryOperation.php
@@ -11,6 +11,30 @@
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(
DrydockRepositoryOperation $operation,
DrydockInterface $interface) {
diff --git a/src/applications/drydock/operation/DrydockRepositoryOperationType.php b/src/applications/drydock/operation/DrydockRepositoryOperationType.php
--- a/src/applications/drydock/operation/DrydockRepositoryOperationType.php
+++ b/src/applications/drydock/operation/DrydockRepositoryOperationType.php
@@ -12,6 +12,10 @@
DrydockRepositoryOperation $operation,
PhabricatorUser $viewer);
+ abstract public function getOperationCurrentStatus(
+ DrydockRepositoryOperation $operation,
+ PhabricatorUser $viewer);
+
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
return $this;
diff --git a/src/applications/drydock/storage/DrydockRepositoryOperation.php b/src/applications/drydock/storage/DrydockRepositoryOperation.php
--- a/src/applications/drydock/storage/DrydockRepositoryOperation.php
+++ b/src/applications/drydock/storage/DrydockRepositoryOperation.php
@@ -142,6 +142,22 @@
$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 )----------------------------------------- */
diff --git a/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php b/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php
new file mode 100644
--- /dev/null
+++ b/src/applications/drydock/view/DrydockRepositoryOperationStatusView.php
@@ -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);
+ }
+
+}
diff --git a/webroot/rsrc/js/application/drydock/drydock-live-operation-status.js b/webroot/rsrc/js/application/drydock/drydock-live-operation-status.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/application/drydock/drydock-live-operation-status.js
@@ -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();
+});

File Metadata

Mime Type
text/plain
Expires
Mar 16 2025, 5:05 AM (4 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7660866
Default Alt Text
D14314.id.diff (12 KB)

Event Timeline