Page MenuHomePhabricator

D21627.diff
No OneTemporary

D21627.diff

diff --git a/resources/sql/autopatches/20210316.almanac.03.device-status.sql b/resources/sql/autopatches/20210316.almanac.03.device-status.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20210316.almanac.03.device-status.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20210316.almanac.04.device-status-value.sql b/resources/sql/autopatches/20210316.almanac.04.device-status-value.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20210316.almanac.04.device-status-value.sql
@@ -0,0 +1,2 @@
+UPDATE {$NAMESPACE}_almanac.almanac_device
+ SET status = 'active' WHERE status = '';
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
@@ -62,6 +62,8 @@
'AlmanacDeviceSearchConduitAPIMethod' => 'applications/almanac/conduit/AlmanacDeviceSearchConduitAPIMethod.php',
'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
'AlmanacDeviceSetPropertyTransaction' => 'applications/almanac/xaction/AlmanacDeviceSetPropertyTransaction.php',
+ 'AlmanacDeviceStatus' => 'applications/almanac/constants/AlmanacDeviceStatus.php',
+ 'AlmanacDeviceStatusTransaction' => 'applications/almanac/xaction/AlmanacDeviceStatusTransaction.php',
'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
'AlmanacDeviceTransactionType' => 'applications/almanac/xaction/AlmanacDeviceTransactionType.php',
@@ -6089,6 +6091,8 @@
'AlmanacDeviceSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
'AlmanacDeviceSetPropertyTransaction' => 'AlmanacDeviceTransactionType',
+ 'AlmanacDeviceStatus' => 'Phobject',
+ 'AlmanacDeviceStatusTransaction' => 'AlmanacDeviceTransactionType',
'AlmanacDeviceTransaction' => 'AlmanacModularTransaction',
'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacDeviceTransactionType' => 'AlmanacTransactionType',
diff --git a/src/applications/almanac/constants/AlmanacDeviceStatus.php b/src/applications/almanac/constants/AlmanacDeviceStatus.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/constants/AlmanacDeviceStatus.php
@@ -0,0 +1,89 @@
+<?php
+
+final class AlmanacDeviceStatus
+ extends Phobject {
+
+ const ACTIVE = 'active';
+ const DISABLED = 'disabled';
+
+ private $value;
+
+ public static function newStatusFromValue($value) {
+ $status = new self();
+ $status->value = $value;
+ return $status;
+ }
+
+ public function getValue() {
+ return $this->value;
+ }
+
+ public function getName() {
+ $name = $this->getDeviceStatusProperty('name');
+
+ if ($name === null) {
+ $name = pht('Unknown Almanac Device Status ("%s")', $this->getValue());
+ }
+
+ return $name;
+ }
+
+ public function getIconIcon() {
+ return $this->getDeviceStatusProperty('icon.icon');
+ }
+
+ public function getIconColor() {
+ return $this->getDeviceStatusProperty('icon.color');
+ }
+
+ public function isDisabled() {
+ return ($this->getValue() === self::DISABLED);
+ }
+
+ public function hasStatusTag() {
+ return ($this->getStatusTagIcon() !== null);
+ }
+
+ public function getStatusTagIcon() {
+ return $this->getDeviceStatusProperty('status-tag.icon');
+ }
+
+ public function getStatusTagColor() {
+ return $this->getDeviceStatusProperty('status-tag.color');
+ }
+
+ public static function getStatusMap() {
+ $result = array();
+
+ foreach (self::newDeviceStatusMap() as $status_value => $ignored) {
+ $result[$status_value] = self::newStatusFromValue($status_value);
+ }
+
+ return $result;
+ }
+
+ private function getDeviceStatusProperty($key, $default = null) {
+ $map = self::newDeviceStatusMap();
+ $properties = idx($map, $this->getValue(), array());
+ return idx($properties, $key, $default);
+ }
+
+ private static function newDeviceStatusMap() {
+ return array(
+ self::ACTIVE => array(
+ 'name' => pht('Active'),
+ 'icon.icon' => 'fa-server',
+ 'icon.color' => 'green',
+ ),
+ self::DISABLED => array(
+ 'name' => pht('Disabled'),
+ 'icon.icon' => 'fa-times',
+ 'icon.color' => 'grey',
+ 'status-tag.icon' => 'fa-times',
+ 'status-tag.color' => 'indigo',
+ ),
+ );
+ }
+
+
+}
diff --git a/src/applications/almanac/controller/AlmanacDeviceViewController.php b/src/applications/almanac/controller/AlmanacDeviceViewController.php
--- a/src/applications/almanac/controller/AlmanacDeviceViewController.php
+++ b/src/applications/almanac/controller/AlmanacDeviceViewController.php
@@ -31,6 +31,14 @@
->setPolicyObject($device)
->setHeaderIcon('fa-server');
+ $status = $device->getStatusObject();
+ if ($status->hasStatusTag()) {
+ $header->setStatus(
+ $status->getStatusTagIcon(),
+ $status->getStatusTagColor(),
+ $status->getName());
+ }
+
$issue = null;
if ($device->isClusterDevice()) {
$issue = $this->addClusterMessage(
diff --git a/src/applications/almanac/editor/AlmanacDeviceEditEngine.php b/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
--- a/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
+++ b/src/applications/almanac/editor/AlmanacDeviceEditEngine.php
@@ -76,6 +76,8 @@
}
protected function buildCustomEditFields($object) {
+ $status_map = $this->getDeviceStatusMap($object);
+
return array(
id(new PhabricatorTextEditField())
->setKey('name')
@@ -84,7 +86,32 @@
->setTransactionType(AlmanacDeviceNameTransaction::TRANSACTIONTYPE)
->setIsRequired(true)
->setValue($object->getName()),
+ id(new PhabricatorSelectEditField())
+ ->setKey('status')
+ ->setLabel(pht('Status'))
+ ->setDescription(pht('Device status.'))
+ ->setTransactionType(AlmanacDeviceStatusTransaction::TRANSACTIONTYPE)
+ ->setOptions($status_map)
+ ->setValue($object->getStatus()),
);
}
+
+ private function getDeviceStatusMap(AlmanacDevice $device) {
+ $status_map = AlmanacDeviceStatus::getStatusMap();
+
+ // If the device currently has an unknown status, add it to the list for
+ // the dropdown.
+ $status_value = $device->getStatus();
+ if (!isset($status_map[$status_value])) {
+ $status_map = array(
+ $status_value => AlmanacDeviceStatus::newStatusFromValue($status_value),
+ ) + $status_map;
+ }
+
+ $status_map = mpull($status_map, 'getName');
+
+ return $status_map;
+ }
+
}
diff --git a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
--- a/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
+++ b/src/applications/almanac/phid/AlmanacInterfacePHIDType.php
@@ -34,7 +34,8 @@
$id = $interface->getID();
- $device_name = $interface->getDevice()->getName();
+ $device = $interface->getDevice();
+ $device_name = $device->getName();
$address = $interface->getAddress();
$port = $interface->getPort();
$network = $interface->getNetwork()->getName();
@@ -48,6 +49,10 @@
$handle->setObjectName(pht('Interface %d', $id));
$handle->setName($name);
+
+ if ($device->isDisabled()) {
+ $handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);
+ }
}
}
diff --git a/src/applications/almanac/query/AlmanacDeviceQuery.php b/src/applications/almanac/query/AlmanacDeviceQuery.php
--- a/src/applications/almanac/query/AlmanacDeviceQuery.php
+++ b/src/applications/almanac/query/AlmanacDeviceQuery.php
@@ -9,6 +9,7 @@
private $namePrefix;
private $nameSuffix;
private $isClusterDevice;
+ private $statuses;
public function withIDs(array $ids) {
$this->ids = $ids;
@@ -35,6 +36,11 @@
return $this;
}
+ public function withStatuses(array $statuses) {
+ $this->statuses = $statuses;
+ return $this;
+ }
+
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new AlmanacDeviceNameNgrams(),
@@ -103,6 +109,13 @@
(int)$this->isClusterDevice);
}
+ if ($this->statuses !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'device.status IN (%Ls)',
+ $this->statuses);
+ }
+
return $where;
}
diff --git a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
--- a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
+++ b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
@@ -16,6 +16,9 @@
}
protected function buildCustomSearchFields() {
+ $status_options = AlmanacDeviceStatus::getStatusMap();
+ $status_options = mpull($status_options, 'getName');
+
return array(
id(new PhabricatorSearchTextField())
->setLabel(pht('Name Contains'))
@@ -25,6 +28,11 @@
->setLabel(pht('Exact Names'))
->setKey('names')
->setDescription(pht('Search for devices with specific names.')),
+ id(new PhabricatorSearchCheckboxesField())
+ ->setLabel(pht('Statuses'))
+ ->setKey('statuses')
+ ->setDescription(pht('Search for devices with given statuses.'))
+ ->setOptions($status_options),
id(new PhabricatorSearchThreeStateField())
->setLabel(pht('Cluster Device'))
->setKey('isClusterDevice')
@@ -50,6 +58,10 @@
$query->withIsClusterDevice($map['isClusterDevice']);
}
+ if ($map['statuses']) {
+ $query->withStatuses($map['statuses']);
+ }
+
return $query;
}
@@ -99,6 +111,19 @@
$item->addIcon('fa-sitemap', pht('Cluster Device'));
}
+ if ($device->isDisabled()) {
+ $item->setDisabled(true);
+ }
+
+ $status = $device->getStatusObject();
+ $icon_icon = $status->getIconIcon();
+ $icon_color = $status->getIconColor();
+ $icon_label = $status->getName();
+
+ $item->setStatusIcon(
+ "{$icon_icon} {$icon_color}",
+ $icon_label);
+
$list->addItem($item);
}
diff --git a/src/applications/almanac/storage/AlmanacDevice.php b/src/applications/almanac/storage/AlmanacDevice.php
--- a/src/applications/almanac/storage/AlmanacDevice.php
+++ b/src/applications/almanac/storage/AlmanacDevice.php
@@ -17,6 +17,7 @@
protected $nameIndex;
protected $viewPolicy;
protected $editPolicy;
+ protected $status;
protected $isBoundToClusterService;
private $almanacProperties = self::ATTACHABLE;
@@ -25,6 +26,7 @@
return id(new AlmanacDevice())
->setViewPolicy(PhabricatorPolicies::POLICY_USER)
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
+ ->setStatus(AlmanacDeviceStatus::ACTIVE)
->attachAlmanacProperties(array())
->setIsBoundToClusterService(0);
}
@@ -35,6 +37,7 @@
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text128',
'nameIndex' => 'bytes12',
+ 'status' => 'text32',
'isBoundToClusterService' => 'bool',
),
self::CONFIG_KEY_SCHEMA => array(
@@ -100,6 +103,18 @@
return $this->getIsBoundToClusterService();
}
+ public function getStatusObject() {
+ return $this->newStatusObject();
+ }
+
+ private function newStatusObject() {
+ return AlmanacDeviceStatus::newStatusFromValue($this->getStatus());
+ }
+
+ public function isDisabled() {
+ return $this->getStatusObject()->isDisabled();
+ }
+
/* -( AlmanacPropertyInterface )------------------------------------------- */
@@ -263,12 +278,22 @@
->setKey('name')
->setType('string')
->setDescription(pht('The name of the device.')),
+ id(new PhabricatorConduitSearchFieldSpecification())
+ ->setKey('status')
+ ->setType('map<string, wild>')
+ ->setDescription(pht('Device status information.')),
);
}
public function getFieldValuesForConduit() {
+ $status = $this->getStatusObject();
+
return array(
'name' => $this->getName(),
+ 'status' => array(
+ 'value' => $status->getValue(),
+ 'name' => $status->getName(),
+ ),
);
}
diff --git a/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php b/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
--- a/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
+++ b/src/applications/almanac/typeahead/AlmanacInterfaceDatasource.php
@@ -46,9 +46,16 @@
$results = array();
foreach ($handles as $handle) {
+ if ($handle->isClosed()) {
+ $closed = pht('Disabled');
+ } else {
+ $closed = null;
+ }
+
$results[] = id(new PhabricatorTypeaheadResult())
->setName($handle->getName())
- ->setPHID($handle->getPHID());
+ ->setPHID($handle->getPHID())
+ ->setClosed($closed);
}
return $results;
diff --git a/src/applications/almanac/xaction/AlmanacDeviceStatusTransaction.php b/src/applications/almanac/xaction/AlmanacDeviceStatusTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacDeviceStatusTransaction.php
@@ -0,0 +1,61 @@
+<?php
+
+final class AlmanacDeviceStatusTransaction
+ extends AlmanacDeviceTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:device:status';
+
+ public function generateOldValue($object) {
+ return $object->getStatus();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setStatus($value);
+ }
+
+ public function getTitle() {
+ $old_value = $this->getOldValue();
+ $new_value = $this->getNewValue();
+
+ $old_status = AlmanacDeviceStatus::newStatusFromValue($old_value);
+ $new_status = AlmanacDeviceStatus::newStatusFromValue($new_value);
+
+ $old_name = $old_status->getName();
+ $new_name = $new_status->getName();
+
+ return pht(
+ '%s changed the status of this device from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderValue($old_name),
+ $this->renderValue($new_name));
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ $status_map = AlmanacDeviceStatus::getStatusMap();
+
+ $old_value = $this->generateOldValue($object);
+ foreach ($xactions as $xaction) {
+ $new_value = $xaction->getNewValue();
+
+ if ($new_value === $old_value) {
+ continue;
+ }
+
+ if (!isset($status_map[$new_value])) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'Almanac device status "%s" is unrecognized. Valid status '.
+ 'values are: %s.',
+ $new_value,
+ implode(', ', array_keys($status_map))),
+ $xaction);
+ continue;
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/phid/PhabricatorObjectHandle.php b/src/applications/phid/PhabricatorObjectHandle.php
--- a/src/applications/phid/PhabricatorObjectHandle.php
+++ b/src/applications/phid/PhabricatorObjectHandle.php
@@ -197,6 +197,10 @@
return $this->status;
}
+ public function isClosed() {
+ return ($this->status === self::STATUS_CLOSED);
+ }
+
public function setFullName($full_name) {
$this->fullName = $full_name;
return $this;

File Metadata

Mime Type
text/plain
Expires
Mon, Dec 23, 6:46 PM (19 h, 11 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6920397
Default Alt Text
D21627.diff (15 KB)

Event Timeline