mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 08:42:41 +01:00
Give Drydock Leases more modern status treatment
Summary: Depends on D19073. Ref T13073. Give leases a normal header tag and try to wrangle their status constants a bit. Also, try to capture the "status class" pattern a bit. Since we target PHP 5.2.3 we can't use `static::` so the actual subclass is kind of a mess. Not exactly sure if I want to stick with this or not. We could consider targeting PHP 5.3.0 instead to get `static::` / late static binding. Test Plan: Viewed leases and lease lists, saw better and more conventional status information. Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam Maniphest Tasks: T13073 Differential Revision: https://secure.phabricator.com/D19074
This commit is contained in:
parent
07028cfc30
commit
27c3793d40
6 changed files with 242 additions and 72 deletions
|
@ -3416,6 +3416,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorObjectRelationshipSource' => 'applications/search/relationship/PhabricatorObjectRelationshipSource.php',
|
'PhabricatorObjectRelationshipSource' => 'applications/search/relationship/PhabricatorObjectRelationshipSource.php',
|
||||||
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
|
'PhabricatorObjectRemarkupRule' => 'infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php',
|
||||||
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
|
'PhabricatorObjectSelectorDialog' => 'view/control/PhabricatorObjectSelectorDialog.php',
|
||||||
|
'PhabricatorObjectStatus' => 'infrastructure/status/PhabricatorObjectStatus.php',
|
||||||
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
|
'PhabricatorOffsetPagedQuery' => 'infrastructure/query/PhabricatorOffsetPagedQuery.php',
|
||||||
'PhabricatorOldWorldContentSource' => 'infrastructure/contentsource/PhabricatorOldWorldContentSource.php',
|
'PhabricatorOldWorldContentSource' => 'infrastructure/contentsource/PhabricatorOldWorldContentSource.php',
|
||||||
'PhabricatorOlderInlinesSetting' => 'applications/settings/setting/PhabricatorOlderInlinesSetting.php',
|
'PhabricatorOlderInlinesSetting' => 'applications/settings/setting/PhabricatorOlderInlinesSetting.php',
|
||||||
|
@ -6290,7 +6291,7 @@ phutil_register_library_map(array(
|
||||||
'DrydockLeaseReleaseController' => 'DrydockLeaseController',
|
'DrydockLeaseReleaseController' => 'DrydockLeaseController',
|
||||||
'DrydockLeaseReleasedLogType' => 'DrydockLogType',
|
'DrydockLeaseReleasedLogType' => 'DrydockLogType',
|
||||||
'DrydockLeaseSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'DrydockLeaseSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
'DrydockLeaseStatus' => 'DrydockConstants',
|
'DrydockLeaseStatus' => 'PhabricatorObjectStatus',
|
||||||
'DrydockLeaseUpdateWorker' => 'DrydockWorker',
|
'DrydockLeaseUpdateWorker' => 'DrydockWorker',
|
||||||
'DrydockLeaseViewController' => 'DrydockLeaseController',
|
'DrydockLeaseViewController' => 'DrydockLeaseController',
|
||||||
'DrydockLeaseWaitingForResourcesLogType' => 'DrydockLogType',
|
'DrydockLeaseWaitingForResourcesLogType' => 'DrydockLogType',
|
||||||
|
@ -8994,6 +8995,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorObjectRelationshipSource' => 'Phobject',
|
'PhabricatorObjectRelationshipSource' => 'Phobject',
|
||||||
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
|
'PhabricatorObjectRemarkupRule' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorObjectSelectorDialog' => 'Phobject',
|
'PhabricatorObjectSelectorDialog' => 'Phobject',
|
||||||
|
'PhabricatorObjectStatus' => 'Phobject',
|
||||||
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
|
'PhabricatorOffsetPagedQuery' => 'PhabricatorQuery',
|
||||||
'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource',
|
'PhabricatorOldWorldContentSource' => 'PhabricatorContentSource',
|
||||||
'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting',
|
'PhabricatorOlderInlinesSetting' => 'PhabricatorSelectSetting',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class DrydockLeaseStatus extends DrydockConstants {
|
final class DrydockLeaseStatus
|
||||||
|
extends PhabricatorObjectStatus {
|
||||||
|
|
||||||
const STATUS_PENDING = 'pending';
|
const STATUS_PENDING = 'pending';
|
||||||
const STATUS_ACQUIRED = 'acquired';
|
const STATUS_ACQUIRED = 'acquired';
|
||||||
|
@ -9,24 +10,105 @@ final class DrydockLeaseStatus extends DrydockConstants {
|
||||||
const STATUS_BROKEN = 'broken';
|
const STATUS_BROKEN = 'broken';
|
||||||
const STATUS_DESTROYED = 'destroyed';
|
const STATUS_DESTROYED = 'destroyed';
|
||||||
|
|
||||||
|
public static function newStatusObject($key) {
|
||||||
|
return new self($key, id(new self())->getStatusSpecification($key));
|
||||||
|
}
|
||||||
|
|
||||||
public static function getStatusMap() {
|
public static function getStatusMap() {
|
||||||
return array(
|
$map = id(new self())->getStatusSpecifications();
|
||||||
self::STATUS_PENDING => pht('Pending'),
|
return ipull($map, 'name', 'key');
|
||||||
self::STATUS_ACQUIRED => pht('Acquired'),
|
|
||||||
self::STATUS_ACTIVE => pht('Active'),
|
|
||||||
self::STATUS_RELEASED => pht('Released'),
|
|
||||||
self::STATUS_BROKEN => pht('Broken'),
|
|
||||||
self::STATUS_DESTROYED => pht('Destroyed'),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getNameForStatus($status) {
|
public static function getNameForStatus($status) {
|
||||||
$map = self::getStatusMap();
|
$map = id(new self())->getStatusSpecification($status);
|
||||||
return idx($map, $status, pht('Unknown'));
|
return $map['name'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAllStatuses() {
|
public static function getAllStatuses() {
|
||||||
return array_keys(self::getStatusMap());
|
return array_keys(id(new self())->getStatusSpecifications());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActivating() {
|
||||||
|
return $this->getStatusProperty('isActivating');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActive() {
|
||||||
|
return ($this->getKey() === self::STATUS_ACTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRelease() {
|
||||||
|
return $this->getStatusProperty('isReleasable');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canReceiveCommands() {
|
||||||
|
return $this->getStatusProperty('isCommandable');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newStatusSpecifications() {
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_PENDING,
|
||||||
|
'name' => pht('Pending'),
|
||||||
|
'icon' => 'fa-clock-o',
|
||||||
|
'color' => 'blue',
|
||||||
|
'isReleasable' => true,
|
||||||
|
'isCommandable' => true,
|
||||||
|
'isActivating' => true,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_ACQUIRED,
|
||||||
|
'name' => pht('Acquired'),
|
||||||
|
'icon' => 'fa-refresh',
|
||||||
|
'color' => 'blue',
|
||||||
|
'isReleasable' => true,
|
||||||
|
'isCommandable' => true,
|
||||||
|
'isActivating' => true,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_ACTIVE,
|
||||||
|
'name' => pht('Active'),
|
||||||
|
'icon' => 'fa-check',
|
||||||
|
'color' => 'green',
|
||||||
|
'isReleasable' => true,
|
||||||
|
'isCommandable' => true,
|
||||||
|
'isActivating' => false,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_RELEASED,
|
||||||
|
'name' => pht('Released'),
|
||||||
|
'icon' => 'fa-circle-o',
|
||||||
|
'color' => 'blue',
|
||||||
|
'isReleasable' => false,
|
||||||
|
'isCommandable' => false,
|
||||||
|
'isActivating' => false,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_BROKEN,
|
||||||
|
'name' => pht('Broken'),
|
||||||
|
'icon' => 'fa-times',
|
||||||
|
'color' => 'indigo',
|
||||||
|
'isReleasable' => true,
|
||||||
|
'isCommandable' => true,
|
||||||
|
'isActivating' => false,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'key' => self::STATUS_DESTROYED,
|
||||||
|
'name' => pht('Destroyed'),
|
||||||
|
'icon' => 'fa-times',
|
||||||
|
'color' => 'red',
|
||||||
|
'isReleasable' => false,
|
||||||
|
'isCommandable' => false,
|
||||||
|
'isActivating' => false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newUnknownStatusSpecification($status) {
|
||||||
|
return array(
|
||||||
|
'isReleasable' => false,
|
||||||
|
'isCommandable' => false,
|
||||||
|
'isActivating' => false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,19 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
||||||
|
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
->setHeader($title)
|
->setHeader($title)
|
||||||
->setHeaderIcon('fa-link');
|
->setHeaderIcon('fa-link')
|
||||||
|
->setStatus(
|
||||||
|
$lease->getStatusIcon(),
|
||||||
|
$lease->getStatusColor(),
|
||||||
|
$lease->getStatusDisplayName());
|
||||||
|
|
||||||
if ($lease->isReleasing()) {
|
if ($lease->isReleasing()) {
|
||||||
$header->setStatus('fa-exclamation-triangle', 'red', pht('Releasing'));
|
$header->addTag(
|
||||||
|
id(new PHUITagView())
|
||||||
|
->setType(PHUITagView::TYPE_SHADE)
|
||||||
|
->setIcon('fa-exclamation-triangle')
|
||||||
|
->setColor('red')
|
||||||
|
->setName('Releasing'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$curtain = $this->buildCurtain($lease);
|
$curtain = $this->buildCurtain($lease);
|
||||||
|
@ -118,10 +127,6 @@ final class DrydockLeaseViewController extends DrydockLeaseController {
|
||||||
|
|
||||||
$view = new PHUIPropertyListView();
|
$view = new PHUIPropertyListView();
|
||||||
|
|
||||||
$view->addProperty(
|
|
||||||
pht('Status'),
|
|
||||||
DrydockLeaseStatus::getNameForStatus($lease->getStatus()));
|
|
||||||
|
|
||||||
$view->addProperty(
|
$view->addProperty(
|
||||||
pht('Resource Type'),
|
pht('Resource Type'),
|
||||||
$lease->getResourceType());
|
$lease->getResourceType());
|
||||||
|
|
|
@ -175,25 +175,6 @@ final class DrydockLease extends DrydockDAO
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isActivating() {
|
|
||||||
switch ($this->getStatus()) {
|
|
||||||
case DrydockLeaseStatus::STATUS_PENDING:
|
|
||||||
case DrydockLeaseStatus::STATUS_ACQUIRED:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isActive() {
|
|
||||||
switch ($this->getStatus()) {
|
|
||||||
case DrydockLeaseStatus::STATUS_ACTIVE:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setActivateWhenAcquired($activate) {
|
public function setActivateWhenAcquired($activate) {
|
||||||
$this->activateWhenAcquired = true;
|
$this->activateWhenAcquired = true;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -325,30 +306,6 @@ final class DrydockLease extends DrydockDAO
|
||||||
return $this->isActivated;
|
return $this->isActivated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function canRelease() {
|
|
||||||
if (!$this->getID()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($this->getStatus()) {
|
|
||||||
case DrydockLeaseStatus::STATUS_RELEASED:
|
|
||||||
case DrydockLeaseStatus::STATUS_DESTROYED:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function canReceiveCommands() {
|
|
||||||
switch ($this->getStatus()) {
|
|
||||||
case DrydockLeaseStatus::STATUS_RELEASED:
|
|
||||||
case DrydockLeaseStatus::STATUS_DESTROYED:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function scheduleUpdate($epoch = null) {
|
public function scheduleUpdate($epoch = null) {
|
||||||
PhabricatorWorker::scheduleTask(
|
PhabricatorWorker::scheduleTask(
|
||||||
'DrydockLeaseUpdateWorker',
|
'DrydockLeaseUpdateWorker',
|
||||||
|
@ -442,6 +399,46 @@ final class DrydockLease extends DrydockDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Status )------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getStatusObject() {
|
||||||
|
return DrydockLeaseStatus::newStatusObject($this->getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusIcon() {
|
||||||
|
return $this->getStatusObject()->getIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusColor() {
|
||||||
|
return $this->getStatusObject()->getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatusDisplayName() {
|
||||||
|
return $this->getStatusObject()->getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActivating() {
|
||||||
|
return $this->getStatusObject()->isActivating();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isActive() {
|
||||||
|
return $this->getStatusObject()->isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRelease() {
|
||||||
|
if (!$this->getID()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getStatusObject()->canRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canReceiveCommands() {
|
||||||
|
return $this->getStatusObject()->canReceiveCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,20 +26,20 @@ final class DrydockLeaseListView extends AphrontView {
|
||||||
if ($resource_phid) {
|
if ($resource_phid) {
|
||||||
$item->addAttribute(
|
$item->addAttribute(
|
||||||
$viewer->renderHandle($resource_phid));
|
$viewer->renderHandle($resource_phid));
|
||||||
|
} else {
|
||||||
|
$item->addAttribute(
|
||||||
|
pht(
|
||||||
|
'Resource: %s',
|
||||||
|
$lease->getResourceType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$status = DrydockLeaseStatus::getNameForStatus($lease->getStatus());
|
|
||||||
$item->addAttribute($status);
|
|
||||||
$item->setEpoch($lease->getDateCreated());
|
$item->setEpoch($lease->getDateCreated());
|
||||||
|
|
||||||
// TODO: Tailor this for clarity.
|
$icon = $lease->getStatusIcon();
|
||||||
if ($lease->isActivating()) {
|
$color = $lease->getStatusColor();
|
||||||
$item->setStatusIcon('fa-dot-circle-o yellow');
|
$label = $lease->getStatusDisplayName();
|
||||||
} else if ($lease->isActive()) {
|
|
||||||
$item->setStatusIcon('fa-dot-circle-o green');
|
$item->setStatusIcon("{$icon} {$color}", $label);
|
||||||
} else {
|
|
||||||
$item->setStatusIcon('fa-dot-circle-o red');
|
|
||||||
}
|
|
||||||
|
|
||||||
$view->addItem($item);
|
$view->addItem($item);
|
||||||
}
|
}
|
||||||
|
|
84
src/infrastructure/status/PhabricatorObjectStatus.php
Normal file
84
src/infrastructure/status/PhabricatorObjectStatus.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PhabricatorObjectStatus
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $key;
|
||||||
|
private $properties;
|
||||||
|
|
||||||
|
protected function __construct($key = null, array $properties = array()) {
|
||||||
|
$this->key = $key;
|
||||||
|
$this->properties = $properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getStatusProperty($key) {
|
||||||
|
if (!array_key_exists($key, $this->properties)) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Attempting to access unknown status property ("%s").',
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->properties[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getKey() {
|
||||||
|
return $this->key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIcon() {
|
||||||
|
return $this->getStatusProperty('icon');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDisplayName() {
|
||||||
|
return $this->getStatusProperty('name');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor() {
|
||||||
|
return $this->getStatusProperty('color');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getStatusSpecification($status) {
|
||||||
|
$map = self::getStatusSpecifications();
|
||||||
|
if (isset($map[$status])) {
|
||||||
|
return $map[$status];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'key' => $status,
|
||||||
|
'name' => pht('Unknown ("%s")', $status),
|
||||||
|
'icon' => 'fa-question-circle',
|
||||||
|
'color' => 'indigo',
|
||||||
|
) + $this->newUnknownStatusSpecification($status);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getStatusSpecifications() {
|
||||||
|
$map = $this->newStatusSpecifications();
|
||||||
|
|
||||||
|
$result = array();
|
||||||
|
foreach ($map as $item) {
|
||||||
|
if (!array_key_exists('key', $item)) {
|
||||||
|
throw new Exception(pht('Status specification has no "key".'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = $item['key'];
|
||||||
|
if (isset($result[$key])) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Multiple status definitions share the same key ("%s").',
|
||||||
|
$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$result[$key] = $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract protected function newStatusSpecifications();
|
||||||
|
|
||||||
|
protected function newUnknownStatusSpecification($status) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue