mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 23:02:42 +01:00
Allow Almanac service types to define default properties
Summary: Ref T5833. This allows Almanac ServiceTypes to define default properties for a service, which show up in the UI and are more easily editable. Overall, this makes it much easier to make structured/usable/consistent service records: you can check a checkbox that says "prevent new allocations" instead of needing to know the meaning of a key. Test Plan: {F251593} Reviewers: chad, btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T5833 Differential Revision: https://secure.phabricator.com/D10996
This commit is contained in:
parent
c85327ca3e
commit
3fa519da74
19 changed files with 361 additions and 77 deletions
|
@ -34,6 +34,7 @@ return array(
|
|||
'rsrc/css/aphront/transaction.css' => '5d0cae25',
|
||||
'rsrc/css/aphront/two-column.css' => '16ab3ad2',
|
||||
'rsrc/css/aphront/typeahead.css' => 'a989b5b3',
|
||||
'rsrc/css/application/almanac/almanac.css' => 'dbb9b3af',
|
||||
'rsrc/css/application/auth/auth.css' => '1e655982',
|
||||
'rsrc/css/application/base/main-menu-view.css' => '33e5f2f6',
|
||||
'rsrc/css/application/base/notification-menu.css' => '6aa0a74b',
|
||||
|
@ -497,6 +498,7 @@ return array(
|
|||
'rsrc/swf/aphlict.swf' => 'f19daffb',
|
||||
),
|
||||
'symbols' => array(
|
||||
'almanac-css' => 'dbb9b3af',
|
||||
'aphront-bars' => '231ac33c',
|
||||
'aphront-contextbar-view-css' => '1c3b0529',
|
||||
'aphront-dark-console-css' => '6378ef3d',
|
||||
|
|
|
@ -67,6 +67,7 @@ phutil_register_library_map(array(
|
|||
'AlmanacNetworkViewController' => 'applications/almanac/controller/AlmanacNetworkViewController.php',
|
||||
'AlmanacProperty' => 'applications/almanac/storage/AlmanacProperty.php',
|
||||
'AlmanacPropertyController' => 'applications/almanac/controller/AlmanacPropertyController.php',
|
||||
'AlmanacPropertyDeleteController' => 'applications/almanac/controller/AlmanacPropertyDeleteController.php',
|
||||
'AlmanacPropertyEditController' => 'applications/almanac/controller/AlmanacPropertyEditController.php',
|
||||
'AlmanacPropertyInterface' => 'applications/almanac/property/AlmanacPropertyInterface.php',
|
||||
'AlmanacPropertyQuery' => 'applications/almanac/query/AlmanacPropertyQuery.php',
|
||||
|
@ -3092,6 +3093,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'AlmanacPropertyController' => 'AlmanacController',
|
||||
'AlmanacPropertyDeleteController' => 'AlmanacDeviceController',
|
||||
'AlmanacPropertyEditController' => 'AlmanacDeviceController',
|
||||
'AlmanacPropertyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'AlmanacQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
|
|
|
@ -57,7 +57,8 @@ final class PhabricatorAlmanacApplication extends PhabricatorApplication {
|
|||
'(?P<id>\d+)/' => 'AlmanacNetworkViewController',
|
||||
),
|
||||
'property/' => array(
|
||||
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacPropertyEditController',
|
||||
'edit/' => 'AlmanacPropertyEditController',
|
||||
'delete/' => 'AlmanacPropertyDeleteController',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -9,13 +9,129 @@ abstract class AlmanacController
|
|||
$viewer = $this->getViewer();
|
||||
$properties = $object->getAlmanacProperties();
|
||||
|
||||
$this->requireResource('almanac-css');
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$object,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Before reading values from the object, read defaults.
|
||||
$defaults = mpull(
|
||||
$field_list->getFields(),
|
||||
'getValueForStorage',
|
||||
'getFieldKey');
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
||||
Javelin::initBehavior('phabricator-tooltips', array());
|
||||
|
||||
$icon_builtin = id(new PHUIIconView())
|
||||
->setIconFont('fa-circle')
|
||||
->addSigil('has-tooltip')
|
||||
->setMetadata(
|
||||
array(
|
||||
'tip' => pht('Builtin Property'),
|
||||
'align' => 'E',
|
||||
));
|
||||
|
||||
$icon_custom = id(new PHUIIconView())
|
||||
->setIconFont('fa-circle-o grey')
|
||||
->addSigil('has-tooltip')
|
||||
->setMetadata(
|
||||
array(
|
||||
'tip' => pht('Custom Property'),
|
||||
'align' => 'E',
|
||||
));
|
||||
|
||||
$builtins = $object->getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
// Sort fields so builtin fields appear first, then fields are ordered
|
||||
// alphabetically.
|
||||
$fields = $field_list->getFields();
|
||||
$fields = msort($fields, 'getFieldKey');
|
||||
|
||||
$head = array();
|
||||
$tail = array();
|
||||
foreach ($fields as $field) {
|
||||
$key = $field->getFieldKey();
|
||||
if (isset($builtins[$key])) {
|
||||
$head[$key] = $field;
|
||||
} else {
|
||||
$tail[$key] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
$fields = $head + $tail;
|
||||
|
||||
$rows = array();
|
||||
foreach ($properties as $property) {
|
||||
$value = $property->getFieldValue();
|
||||
foreach ($fields as $key => $field) {
|
||||
$value = $field->getValueForStorage();
|
||||
|
||||
$is_builtin = isset($builtins[$key]);
|
||||
|
||||
$delete_uri = $this->getApplicationURI('property/delete/');
|
||||
$delete_uri = id(new PhutilURI($delete_uri))
|
||||
->setQueryParams(
|
||||
array(
|
||||
'objectPHID' => $object->getPHID(),
|
||||
'key' => $key,
|
||||
));
|
||||
|
||||
$edit_uri = $this->getApplicationURI('property/edit/');
|
||||
$edit_uri = id(new PhutilURI($edit_uri))
|
||||
->setQueryParams(
|
||||
array(
|
||||
'objectPHID' => $object->getPHID(),
|
||||
'key' => $key,
|
||||
));
|
||||
|
||||
$delete = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => ($can_edit
|
||||
? 'button grey small'
|
||||
: 'button grey small disabled'),
|
||||
'sigil' => 'workflow',
|
||||
'href' => $delete_uri,
|
||||
),
|
||||
$is_builtin ? pht('Reset') : pht('Delete'));
|
||||
|
||||
$default = idx($defaults, $key);
|
||||
$is_default = ($default !== null && $default === $value);
|
||||
|
||||
$display_value = PhabricatorConfigJSON::prettyPrintJSON($value);
|
||||
if ($is_default) {
|
||||
$display_value = phutil_tag(
|
||||
'span',
|
||||
array(
|
||||
'class' => 'almanac-default-property-value',
|
||||
),
|
||||
$display_value);
|
||||
}
|
||||
|
||||
$display_key = $key;
|
||||
if ($can_edit) {
|
||||
$display_key = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $edit_uri,
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
$display_key);
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$property->getFieldName(),
|
||||
PhabricatorConfigJSON::prettyPrintJSON($value),
|
||||
($is_builtin ? $icon_builtin : $icon_custom),
|
||||
$display_key,
|
||||
$display_value,
|
||||
$delete,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -23,13 +139,17 @@ abstract class AlmanacController
|
|||
->setNoDataString(pht('No properties.'))
|
||||
->setHeaders(
|
||||
array(
|
||||
null,
|
||||
pht('Name'),
|
||||
pht('Value'),
|
||||
null,
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
null,
|
||||
'wide',
|
||||
'action',
|
||||
));
|
||||
|
||||
$phid = $object->getPHID();
|
||||
|
|
|
@ -11,7 +11,6 @@ final class AlmanacNetworkViewController
|
|||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$network = id(new AlmanacNetworkQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
final class AlmanacPropertyDeleteController
|
||||
extends AlmanacDeviceController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($request->getStr('objectPHID')))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if (!($object instanceof AlmanacPropertyInterface)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$key = $request->getStr('key');
|
||||
if (!strlen($key)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cancel_uri = $object->getURI();
|
||||
|
||||
$builtins = $object->getAlmanacPropertyFieldSpecifications();
|
||||
$is_builtin = isset($builtins[$key]);
|
||||
|
||||
if ($is_builtin) {
|
||||
// This is a builtin property, so we're going to reset it to the
|
||||
// default value.
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Note that we're NOT loading field values from the object: we just want
|
||||
// to get the field's default value so we can reset it.
|
||||
|
||||
$fields = $field_list->getFields();
|
||||
$field = $fields[$key];
|
||||
|
||||
$is_delete = false;
|
||||
$new_value = $field->getValueForStorage();
|
||||
|
||||
// Now, load the field to get the old value.
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
||||
$old_value = $field->getValueForStorage();
|
||||
|
||||
$title = pht('Reset Property');
|
||||
$body = pht('Reset this property to its default value?');
|
||||
$submit_text = pht('Reset');
|
||||
} else {
|
||||
// This is a custom property, so we're going to delete it outright.
|
||||
$is_delete = true;
|
||||
$old_value = $object->getAlmanacPropertyValue($key);
|
||||
$new_value = null;
|
||||
|
||||
$title = pht('Delete Property');
|
||||
$body = pht('Delete this property? TODO: DOES NOT WORK YET');
|
||||
$submit_text = pht('Delete');
|
||||
}
|
||||
|
||||
$validation_exception = null;
|
||||
if ($request->isFormPost()) {
|
||||
$xaction = $object->getApplicationTransactionTemplate()
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
|
||||
->setMetadataValue('customfield:key', $key)
|
||||
->setOldValue($old_value)
|
||||
->setNewValue($new_value);
|
||||
|
||||
// TODO: We aren't really deleting properties that we claim to delete
|
||||
// yet, but that needs to be specialized a little bit.
|
||||
|
||||
$editor = $object->getApplicationTransactionEditor()
|
||||
->setActor($viewer)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->setContinueOnMissingFields(true);
|
||||
|
||||
try {
|
||||
$editor->applyTransactions($object, array($xaction));
|
||||
return id(new AphrontRedirectResponse())->setURI($cancel_uri);
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle($title)
|
||||
->setValidationException($validation_exception)
|
||||
->addHiddenInput('objectPHID', $object->getPHID())
|
||||
->addHiddenInput('key', $key)
|
||||
->appendParagraph($body)
|
||||
->addCancelButton($cancel_uri)
|
||||
->addSubmitButton($submit_text);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,27 +6,6 @@ final class AlmanacPropertyEditController
|
|||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$id = $request->getURIData('id');
|
||||
if ($id) {
|
||||
$property = id(new AlmanacPropertyQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$property) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$object = $property->getObject();
|
||||
|
||||
$is_new = false;
|
||||
$title = pht('Edit Property');
|
||||
$save_button = pht('Save Changes');
|
||||
} else {
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs(array($request->getStr('objectPHID')))
|
||||
|
@ -40,17 +19,27 @@ final class AlmanacPropertyEditController
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$is_new = true;
|
||||
$title = pht('Add Property');
|
||||
$save_button = pht('Add Property');
|
||||
}
|
||||
|
||||
if (!($object instanceof AlmanacPropertyInterface)) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$cancel_uri = $object->getURI();
|
||||
|
||||
$key = $request->getStr('key');
|
||||
if ($key) {
|
||||
$property_key = $key;
|
||||
|
||||
$is_new = false;
|
||||
$title = pht('Edit Property');
|
||||
$save_button = pht('Save Changes');
|
||||
} else {
|
||||
$property_key = null;
|
||||
|
||||
$is_new = true;
|
||||
$title = pht('Add Property');
|
||||
$save_button = pht('Add Property');
|
||||
}
|
||||
|
||||
if ($is_new) {
|
||||
$errors = array();
|
||||
$property = null;
|
||||
|
@ -77,25 +66,11 @@ final class AlmanacPropertyEditController
|
|||
}
|
||||
|
||||
if (!$errors) {
|
||||
$property = id(new AlmanacPropertyQuery())
|
||||
->setViewer($viewer)
|
||||
->withObjectPHIDs(array($object->getPHID()))
|
||||
->withNames(array($name))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$property) {
|
||||
$property = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($name);
|
||||
}
|
||||
$property_key = $name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$property) {
|
||||
if ($property_key === null) {
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->appendChild(
|
||||
|
@ -115,17 +90,29 @@ final class AlmanacPropertyEditController
|
|||
}
|
||||
}
|
||||
|
||||
$v_name = $property->getFieldName();
|
||||
$e_name = true;
|
||||
// Make sure property key is appropriate.
|
||||
// TODO: It would be cleaner to put this safety check in the Editor.
|
||||
AlmanacNames::validateServiceOrDeviceName($property_key);
|
||||
|
||||
$v_value = $property->getFieldValue();
|
||||
$e_value = null;
|
||||
// If we're adding a new property, put a placeholder on the object so
|
||||
// that we can build a CustomField for it.
|
||||
if (!$object->hasAlmanacProperty($property_key)) {
|
||||
$temporary_property = id(new AlmanacProperty())
|
||||
->setObjectPHID($object->getPHID())
|
||||
->setFieldName($property_key);
|
||||
|
||||
$object->attachAlmanacProperties(array($property));
|
||||
$object->attachAlmanacProperties(array($temporary_property));
|
||||
}
|
||||
|
||||
$field_list = PhabricatorCustomField::getObjectFields(
|
||||
$object,
|
||||
PhabricatorCustomField::ROLE_EDIT);
|
||||
PhabricatorCustomField::ROLE_DEFAULT);
|
||||
|
||||
// Select only the field being edited.
|
||||
$fields = $field_list->getFields();
|
||||
$fields = array_select_keys($fields, array($property_key));
|
||||
$field_list = new PhabricatorCustomFieldList($fields);
|
||||
|
||||
$field_list
|
||||
->setViewer($viewer)
|
||||
->readFieldsFromStorage($object);
|
||||
|
@ -153,7 +140,8 @@ final class AlmanacPropertyEditController
|
|||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('objectPHID', $request->getStr('objectPHID'))
|
||||
->addHiddenInput('name', $request->getStr('name'))
|
||||
->addHiddenInput('key', $request->getStr('key'))
|
||||
->addHiddenInput('name', $property_key)
|
||||
->addHiddenInput('isValueEdit', true);
|
||||
|
||||
$field_list->appendFieldsToForm($form);
|
||||
|
|
|
@ -8,17 +8,29 @@ final class AlmanacCoreCustomField
|
|||
return 'almanac:core';
|
||||
}
|
||||
|
||||
public function createFields($object) {
|
||||
$specs = array();
|
||||
public function getFieldKey() {
|
||||
return $this->getProxy()->getRawStandardFieldKey();
|
||||
}
|
||||
|
||||
public function getFieldName() {
|
||||
return $this->getFieldKey();
|
||||
}
|
||||
|
||||
public function createFields($object) {
|
||||
|
||||
$specs = $object->getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
$default_specs = array();
|
||||
foreach ($object->getAlmanacProperties() as $property) {
|
||||
$specs[$property->getFieldName()] = array(
|
||||
$default_specs[$property->getFieldName()] = array(
|
||||
'name' => $property->getFieldName(),
|
||||
'type' => 'text',
|
||||
);
|
||||
}
|
||||
|
||||
return PhabricatorStandardCustomField::buildStandardFields($this, $specs);
|
||||
return PhabricatorStandardCustomField::buildStandardFields(
|
||||
$this,
|
||||
$specs + $default_specs);
|
||||
}
|
||||
|
||||
public function shouldUseStorage() {
|
||||
|
@ -26,9 +38,12 @@ final class AlmanacCoreCustomField
|
|||
}
|
||||
|
||||
public function readValueFromObject(PhabricatorCustomFieldInterface $object) {
|
||||
$key = $this->getProxy()->getRawStandardFieldKey();
|
||||
$key = $this->getFieldKey();
|
||||
|
||||
if ($object->hasAlmanacProperty($key)) {
|
||||
$this->setValueFromStorage($object->getAlmanacPropertyValue($key));
|
||||
}
|
||||
}
|
||||
|
||||
public function applyApplicationTransactionInternalEffects(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
@ -40,7 +55,7 @@ final class AlmanacCoreCustomField
|
|||
|
||||
$object = $this->getObject();
|
||||
$phid = $object->getPHID();
|
||||
$key = $this->getProxy()->getRawStandardFieldKey();
|
||||
$key = $this->getFieldKey();
|
||||
|
||||
$property = id(new AlmanacPropertyQuery())
|
||||
->setViewer($this->getViewer())
|
||||
|
|
|
@ -7,5 +7,6 @@ interface AlmanacPropertyInterface {
|
|||
public function hasAlmanacProperty($key);
|
||||
public function getAlmanacProperty($key);
|
||||
public function getAlmanacPropertyValue($key, $default = null);
|
||||
public function getAlmanacPropertyFieldSpecifications();
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ final class AlmanacPropertyQuery
|
|||
}
|
||||
|
||||
public function withObjectPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
$this->objectPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ abstract class AlmanacQuery
|
|||
$property_query = id(new AlmanacPropertyQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->setParentQuery($this)
|
||||
->withObjectPHIDs(mpull($objects, null, 'getPHID'));
|
||||
->withObjectPHIDs(mpull($objects, 'getPHID'));
|
||||
|
||||
// NOTE: We disable policy filtering and object attachment to avoid
|
||||
// a cyclic dependency where objects need their properties and properties
|
||||
|
@ -21,6 +21,7 @@ abstract class AlmanacQuery
|
|||
$property_query->setDisablePolicyFilteringAndAttachment(true);
|
||||
|
||||
$properties = $property_query->execute();
|
||||
|
||||
$properties = mgroup($properties, 'getObjectPHID');
|
||||
foreach ($objects as $object) {
|
||||
$object_properties = idx($properties, $object->getPHID(), array());
|
||||
|
|
|
@ -16,4 +16,19 @@ final class AlmanacClusterRepositoryServiceType
|
|||
'Defines a repository service for use in a Phabricator cluster.');
|
||||
}
|
||||
|
||||
public function getFieldSpecifications() {
|
||||
return array(
|
||||
'closed' => array(
|
||||
'type' => 'bool',
|
||||
'name' => pht('Closed'),
|
||||
'default' => false,
|
||||
'strings' => array(
|
||||
'edit.checkbox' => pht(
|
||||
'Prevent new repositories from being allocated on this '.
|
||||
'service.'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,6 +47,14 @@ abstract class AlmanacServiceType extends Phobject {
|
|||
}
|
||||
|
||||
|
||||
public function getDefaultPropertyMap() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getFieldSpecifications() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available service type implementations.
|
||||
*
|
||||
|
|
|
@ -119,6 +119,10 @@ final class AlmanacBinding
|
|||
}
|
||||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -97,6 +97,10 @@ final class AlmanacDevice
|
|||
}
|
||||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ final class AlmanacNetwork
|
|||
}
|
||||
|
||||
public function getURI() {
|
||||
return '/almanac/network/view/'.$this->getName().'/';
|
||||
return '/almanac/network/'.$this->getID().'/';
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -121,6 +121,10 @@ final class AlmanacService
|
|||
}
|
||||
}
|
||||
|
||||
public function getAlmanacPropertyFieldSpecifications() {
|
||||
return $this->getServiceType()->getFieldSpecifications();
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -22,9 +22,13 @@ final class PhabricatorStandardCustomFieldBool
|
|||
return $this->newNumericIndex(0);
|
||||
}
|
||||
|
||||
public function readValueFromRequest(AphrontRequest $request) {
|
||||
$this->setFieldValue((bool)$request->getBool($this->getFieldKey()));
|
||||
}
|
||||
|
||||
public function getValueForStorage() {
|
||||
$value = $this->getFieldValue();
|
||||
if (strlen($value)) {
|
||||
if ($value !== null) {
|
||||
return (int)$value;
|
||||
} else {
|
||||
return null;
|
||||
|
|
7
webroot/rsrc/css/application/almanac/almanac.css
Normal file
7
webroot/rsrc/css/application/almanac/almanac.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
/**
|
||||
* @provides almanac-css
|
||||
*/
|
||||
|
||||
.almanac-default-property-value {
|
||||
color: {$lightgreytext};
|
||||
}
|
Loading…
Reference in a new issue