Make various small quality-of-life improvements for Almanac properties

Summary:
Depends on D19341. Ref T12414. Ref T13120.

  - Fix a bug where default-valued properties didn't get rendered in grey as they're supposed to (as a hint that the value isn't customized).
  - When resetting a builtin property won't do anything, visually disable the button as a hint.
  - Allow Services to specify properties on their Bindings.
  - Specify that repository bindings have a "protocol" property, so it becomes an explicit thing in the UI. Previously, you had to read the documentation to figure this out.
  - When editing bindings, use the EditField and its configuration if possible. This turns the "Protocol" property into a dropdown in the UI where you select between "http", "https" and "ssh".
  - Give the "protocol" binding a smart default based on the port number of the corresponding interface.

Test Plan:
  - Viewed properties on Services, Devices and Bindings.
  - Saw them render sensibly, and grey out + grey button when a builtin value has a default setting.
  - Saw "Protocol" appear as a default property on repository cluster bindings and get a smart value.
  - Edited "protocol", got a nice dropdown.

{F5518791}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13120, T12414

Differential Revision: https://secure.phabricator.com/D19342
This commit is contained in:
epriestley 2018-04-11 08:36:05 -07:00
parent d56a37b636
commit c1558031c2
7 changed files with 60 additions and 5 deletions

View file

@ -38,7 +38,7 @@ abstract class AlmanacController
)); ));
$builtins = $object->getAlmanacPropertyFieldSpecifications(); $builtins = $object->getAlmanacPropertyFieldSpecifications();
$defaults = mpull($builtins, null, 'getValueForTransaction'); $defaults = mpull($builtins, 'getValueForTransaction');
// Sort fields so builtin fields appear first, then fields are ordered // Sort fields so builtin fields appear first, then fields are ordered
// alphabetically. // alphabetically.
@ -65,6 +65,7 @@ abstract class AlmanacController
$value = $property->getFieldValue(); $value = $property->getFieldValue();
$is_builtin = isset($builtins[$key]); $is_builtin = isset($builtins[$key]);
$is_persistent = (bool)$property->getID();
$delete_uri = id(new PhutilURI($delete_base)) $delete_uri = id(new PhutilURI($delete_base))
->setQueryParams( ->setQueryParams(
@ -83,7 +84,7 @@ abstract class AlmanacController
$delete = javelin_tag( $delete = javelin_tag(
'a', 'a',
array( array(
'class' => ($can_edit 'class' => (($can_edit && $is_persistent)
? 'button button-grey small' ? 'button button-grey small'
: 'button button-grey small disabled'), : 'button button-grey small disabled'),
'sigil' => 'workflow', 'sigil' => 'workflow',

View file

@ -66,8 +66,15 @@ abstract class AlmanacPropertyEditEngine
$property_key = $this->getPropertyKey(); $property_key = $this->getPropertyKey();
$xaction_type = $object->getAlmanacPropertySetTransactionType(); $xaction_type = $object->getAlmanacPropertySetTransactionType();
$specs = $object->getAlmanacPropertyFieldSpecifications();
if (isset($specs[$property_key])) {
$field_template = clone $specs[$property_key];
} else {
$field_template = new PhabricatorTextEditField();
}
return array( return array(
id(new PhabricatorTextEditField()) $field_template
->setKey('value') ->setKey('value')
->setMetadataValue('almanac.property', $property_key) ->setMetadataValue('almanac.property', $property_key)
->setLabel($property_key) ->setLabel($property_key)

View file

@ -34,10 +34,12 @@ abstract class AlmanacQuery
$specs = $object->getAlmanacPropertyFieldSpecifications(); $specs = $object->getAlmanacPropertyFieldSpecifications();
foreach ($specs as $key => $spec) { foreach ($specs as $key => $spec) {
if (empty($object_properties[$key])) { if (empty($object_properties[$key])) {
$default_value = $spec->getValueForTransaction();
$object_properties[$key] = id(new AlmanacProperty()) $object_properties[$key] = id(new AlmanacProperty())
->setObjectPHID($object->getPHID()) ->setObjectPHID($object->getPHID())
->setFieldName($key) ->setFieldName($key)
->setFieldValue($spec->getValueForTransaction()); ->setFieldValue($default_value);
} }
} }

View file

@ -24,4 +24,36 @@ final class AlmanacClusterRepositoryServiceType
); );
} }
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
$protocols = array(
array(
'value' => 'http',
'port' => 80,
),
array(
'value' => 'https',
'port' => 443,
),
array(
'value' => 'ssh',
'port' => 22,
),
);
$default_value = 'http';
if ($binding->hasInterface()) {
$interface = $binding->getInterface();
$port = $interface->getPort();
$default_ports = ipull($protocols, 'value', 'port');
$default_value = idx($default_ports, $port, $default_value);
}
return array(
'protocol' => id(new PhabricatorSelectEditField())
->setOptions(ipull($protocols, 'value', 'value'))
->setValue($default_value),
);
}
} }

View file

@ -60,6 +60,10 @@ abstract class AlmanacServiceType extends Phobject {
return array(); return array();
} }
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
return array();
}
/** /**
* List all available service type implementations. * List all available service type implementations.
* *

View file

@ -88,6 +88,10 @@ final class AlmanacBinding
return $this; return $this;
} }
public function hasInterface() {
return ($this->interface !== self::ATTACHABLE);
}
public function getInterface() { public function getInterface() {
return $this->assertAttached($this->interface); return $this->assertAttached($this->interface);
} }
@ -129,7 +133,7 @@ final class AlmanacBinding
} }
public function getAlmanacPropertyFieldSpecifications() { public function getAlmanacPropertyFieldSpecifications() {
return array(); return $this->getService()->getBindingFieldSpecifications($this);
} }
public function newAlmanacPropertyEditEngine() { public function newAlmanacPropertyEditEngine() {

View file

@ -156,6 +156,11 @@ final class AlmanacService
return $this->getServiceImplementation()->getFieldSpecifications(); return $this->getServiceImplementation()->getFieldSpecifications();
} }
public function getBindingFieldSpecifications(AlmanacBinding $binding) {
$impl = $this->getServiceImplementation();
return $impl->getBindingFieldSpecifications($binding);
}
public function newAlmanacPropertyEditEngine() { public function newAlmanacPropertyEditEngine() {
return new AlmanacServicePropertyEditEngine(); return new AlmanacServicePropertyEditEngine();
} }