Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14400146
D21627.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D21627.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21627: Add a "status" property to Almanac devices
Attached
Detach File
Event Timeline
Log In to Comment