1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-27 07:50:57 +01:00

Allow EditEngine form fields to be locked and hidden

Summary:
Ref T9132. Allows fields to be locked (shown, but not modifiable) and hidden (not shown).

In both cases, default values are still respected.

This lets you do things like create a form that generates objects with specific projects, policies, etc.

Test Plan:
  - Set defaults.
  - Locked and hid a bunch of fields.
  - Created new objects using the resulting form.

{F975801}

{F975802}

{F975803}

{F975804}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9132

Differential Revision: https://secure.phabricator.com/D14509
This commit is contained in:
epriestley 2015-11-18 10:50:09 -08:00
parent 53d5cd3950
commit 269e0bfc94
11 changed files with 235 additions and 18 deletions

View file

@ -7,7 +7,7 @@
*/ */
return array( return array(
'names' => array( 'names' => array(
'core.pkg.css' => '0689cd7e', 'core.pkg.css' => '9f339987',
'core.pkg.js' => '47dc9ebb', 'core.pkg.js' => '47dc9ebb',
'darkconsole.pkg.js' => 'e7393ebb', 'darkconsole.pkg.js' => 'e7393ebb',
'differential.pkg.css' => '2de124c9', 'differential.pkg.css' => '2de124c9',
@ -130,7 +130,7 @@ return array(
'rsrc/css/phui/phui-document.css' => '765a9dac', 'rsrc/css/phui/phui-document.css' => '765a9dac',
'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23', 'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23',
'rsrc/css/phui/phui-fontkit.css' => '9cda225e', 'rsrc/css/phui/phui-fontkit.css' => '9cda225e',
'rsrc/css/phui/phui-form-view.css' => '621b21c5', 'rsrc/css/phui/phui-form-view.css' => 'c1d2ef29',
'rsrc/css/phui/phui-form.css' => 'afdb2c6e', 'rsrc/css/phui/phui-form.css' => 'afdb2c6e',
'rsrc/css/phui/phui-header-view.css' => '55bb32dd', 'rsrc/css/phui/phui-header-view.css' => '55bb32dd',
'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6', 'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6',
@ -795,7 +795,7 @@ return array(
'phui-font-icon-base-css' => 'ecbbb4c2', 'phui-font-icon-base-css' => 'ecbbb4c2',
'phui-fontkit-css' => '9cda225e', 'phui-fontkit-css' => '9cda225e',
'phui-form-css' => 'afdb2c6e', 'phui-form-css' => 'afdb2c6e',
'phui-form-view-css' => '621b21c5', 'phui-form-view-css' => 'c1d2ef29',
'phui-header-view-css' => '55bb32dd', 'phui-header-view-css' => '55bb32dd',
'phui-icon-view-css' => 'b0a6b1b6', 'phui-icon-view-css' => 'b0a6b1b6',
'phui-image-mask-css' => '5a8b09c8', 'phui-image-mask-css' => '5a8b09c8',

View file

@ -2117,6 +2117,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php', 'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php',
'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php', 'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php',
'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php', 'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php',
'PhabricatorEditEngineConfigurationLockController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php',
'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php', 'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php',
'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php', 'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php',
'PhabricatorEditEngineConfigurationReorderController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php', 'PhabricatorEditEngineConfigurationReorderController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php',
@ -6211,6 +6212,7 @@ phutil_register_library_map(array(
'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine', 'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine',
'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineConfigurationLockController' => 'PhabricatorEditEngineController',
'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType', 'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType',
'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorEditEngineConfigurationReorderController' => 'PhabricatorEditEngineController', 'PhabricatorEditEngineConfigurationReorderController' => 'PhabricatorEditEngineController',

View file

@ -49,6 +49,8 @@ final class PhabricatorTransactionsApplication extends PhabricatorApplication {
'PhabricatorEditEngineConfigurationReorderController', 'PhabricatorEditEngineConfigurationReorderController',
'defaults/(?P<key>[^/]+)/' => 'defaults/(?P<key>[^/]+)/' =>
'PhabricatorEditEngineConfigurationDefaultsController', 'PhabricatorEditEngineConfigurationDefaultsController',
'lock/(?P<key>[^/]+)/' =>
'PhabricatorEditEngineConfigurationLockController',
), ),
), ),
), ),

View file

@ -0,0 +1,109 @@
<?php
final class PhabricatorEditEngineConfigurationLockController
extends PhabricatorEditEngineController {
public function handleRequest(AphrontRequest $request) {
$engine_key = $request->getURIData('engineKey');
$this->setEngineKey($engine_key);
$key = $request->getURIData('key');
$viewer = $this->getViewer();
$config = id(new PhabricatorEditEngineConfigurationQuery())
->setViewer($viewer)
->withEngineKeys(array($engine_key))
->withIdentifiers(array($key))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$config) {
return id(new Aphront404Response());
}
$cancel_uri = "/transactions/editengine/{$engine_key}/view/{$key}/";
if ($request->isFormPost()) {
$xactions = array();
$locks = $request->getArr('locks');
$type_locks = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS;
$xactions[] = id(new PhabricatorEditEngineConfigurationTransaction())
->setTransactionType($type_locks)
->setNewValue($locks);
$editor = id(new PhabricatorEditEngineConfigurationEditor())
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true);
$editor->applyTransactions($config, $xactions);
return id(new AphrontRedirectResponse())
->setURI($cancel_uri);
}
$engine = $config->getEngine();
$fields = $engine->getFieldsForConfig($config);
$help = pht(<<<EOTEXT
**Locked** fields are visible in the form, but their values can not be changed
by the user.
**Hidden** fields are not visible in the form.
Any assigned default values are still respected, even if the field is locked
or hidden.
EOTEXT
);
$form = id(new AphrontFormView())
->setUser($viewer)
->appendRemarkupInstructions($help);
$locks = $config->getFieldLocks();
$lock_visible = PhabricatorEditEngineConfiguration::LOCK_VISIBLE;
$lock_locked = PhabricatorEditEngineConfiguration::LOCK_LOCKED;
$lock_hidden = PhabricatorEditEngineConfiguration::LOCK_HIDDEN;
$map = array(
$lock_visible => pht('Visible'),
$lock_locked => pht("\xF0\x9F\x94\x92 Locked"),
$lock_hidden => pht("\xE2\x9C\x98 Hidden"),
);
foreach ($fields as $field) {
if (!$field->getIsLockable()) {
continue;
}
$key = $field->getKey();
$label = $field->getLabel();
if (!strlen($label)) {
$label = $key;
}
$form->appendControl(
id(new AphrontFormSelectControl())
->setName('locks['.$key.']')
->setLabel($label)
->setValue(idx($locks, $key, $lock_visible))
->setOptions($map));
}
return $this->newDialog()
->setTitle(pht('Lock / Hide Fields'))
->setWidth(AphrontDialogView::WIDTH_FORM)
->appendForm($form)
->addSubmitButton(pht('Save Changes'))
->addCancelButton($cancel_uri);
}
}

View file

@ -139,6 +139,16 @@ final class PhabricatorEditEngineConfigurationViewController
->setWorkflow(true) ->setWorkflow(true)
->setDisabled(!$can_edit)); ->setDisabled(!$can_edit));
$lock_uri = "{$base_uri}/lock/{$form_key}/";
$view->addAction(
id(new PhabricatorActionView())
->setName(pht('Lock / Hide Fields'))
->setIcon('fa-lock')
->setHref($lock_uri)
->setWorkflow(true)
->setDisabled(!$can_edit));
return $view; return $view;
} }

View file

@ -658,12 +658,22 @@ abstract class PhabricatorEditEngine
$validation_exception = null; $validation_exception = null;
if ($request->isFormPost()) { if ($request->isFormPost()) {
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->getIsLocked() || $field->getIsHidden()) {
continue;
}
$field->readValueFromSubmit($request); $field->readValueFromSubmit($request);
} }
$xactions = array(); $xactions = array();
foreach ($fields as $field) { foreach ($fields as $field) {
$xactions[] = $field->generateTransaction(clone $template); $xaction = $field->generateTransaction(clone $template);
if (!$xaction) {
continue;
}
$xactions[] = $xaction;
} }
$editor = $object->getApplicationTransactionEditor() $editor = $object->getApplicationTransactionEditor()
@ -683,6 +693,10 @@ abstract class PhabricatorEditEngine
} else { } else {
if ($this->getIsCreate()) { if ($this->getIsCreate()) {
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field->getIsLocked() || $field->getIsHidden()) {
continue;
}
$field->readValueFromRequest($request); $field->readValueFromRequest($request);
} }
} else { } else {

View file

@ -13,11 +13,16 @@ abstract class PhabricatorEditField extends Phobject {
private $metadata = array(); private $metadata = array();
private $description; private $description;
private $editTypeKey; private $editTypeKey;
private $isLocked; private $isLocked;
private $isHidden;
private $isPreview; private $isPreview;
private $isReorderable = true;
private $isEditDefaults; private $isEditDefaults;
private $isReorderable = true;
private $isDefaultable = true; private $isDefaultable = true;
private $isLockable = true;
public function setKey($key) { public function setKey($key) {
$this->key = $key; $this->key = $key;
@ -118,6 +123,24 @@ abstract class PhabricatorEditField extends Phobject {
return $this->isDefaultable; return $this->isDefaultable;
} }
public function setIsLockable($is_lockable) {
$this->isLockable = $is_lockable;
return $this;
}
public function getIsLockable() {
return $this->isLockable;
}
public function setIsHidden($is_hidden) {
$this->isHidden = $is_hidden;
return $this;
}
public function getIsHidden() {
return $this->isHidden;
}
protected function newControl() { protected function newControl() {
throw new PhutilMethodNotImplementedException(); throw new PhutilMethodNotImplementedException();
} }
@ -138,10 +161,17 @@ abstract class PhabricatorEditField extends Phobject {
if ($this->getIsPreview()) { if ($this->getIsPreview()) {
$disabled = true; $disabled = true;
$hidden = false;
} else if ($this->getIsEditDefaults()) { } else if ($this->getIsEditDefaults()) {
$disabled = false; $disabled = false;
$hidden = false;
} else { } else {
$disabled = $this->getIsLocked(); $disabled = $this->getIsLocked();
$hidden = $this->getIsHidden();
}
if ($hidden) {
return null;
} }
$control->setDisabled($disabled); $control->setDisabled($disabled);
@ -152,6 +182,18 @@ abstract class PhabricatorEditField extends Phobject {
public function appendToForm(AphrontFormView $form) { public function appendToForm(AphrontFormView $form) {
$control = $this->renderControl(); $control = $this->renderControl();
if ($control !== null) { if ($control !== null) {
if ($this->getIsPreview()) {
if ($this->getIsHidden()) {
$control
->addClass('aphront-form-preview-hidden')
->setError(pht('Hidden'));
} else if ($this->getIsLocked()) {
$control
->setError(pht('Locked'));
}
}
$form->appendControl($control); $form->appendControl($control);
} }
return $this; return $this;
@ -187,6 +229,10 @@ abstract class PhabricatorEditField extends Phobject {
public function generateTransaction( public function generateTransaction(
PhabricatorApplicationTransaction $xaction) { PhabricatorApplicationTransaction $xaction) {
if (!$this->getTransactionType()) {
return null;
}
$xaction $xaction
->setTransactionType($this->getTransactionType()) ->setTransactionType($this->getTransactionType())
->setNewValue($this->getValueForTransaction()); ->setNewValue($this->getValueForTransaction());

View file

@ -21,6 +21,7 @@ final class PhabricatorEditEngineConfigurationEditor
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT; $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT;
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS;
return $types; return $types;
} }
@ -67,6 +68,8 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
$field_key = $xaction->getMetadataValue('field.key'); $field_key = $xaction->getMetadataValue('field.key');
return $object->getFieldDefault($field_key); return $object->getFieldDefault($field_key);
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
return $object->getFieldLocks();
} }
} }
@ -79,6 +82,7 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER: case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER:
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
return $xaction->getNewValue(); return $xaction->getNewValue();
} }
} }
@ -101,6 +105,9 @@ final class PhabricatorEditEngineConfigurationEditor
$field_key = $xaction->getMetadataValue('field.key'); $field_key = $xaction->getMetadataValue('field.key');
$object->setFieldDefault($field_key, $xaction->getNewValue()); $object->setFieldDefault($field_key, $xaction->getNewValue());
return; return;
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
$object->setFieldLocks($xaction->getNewValue());
return;
} }
return parent::applyCustomInternalTransaction($object, $xaction); return parent::applyCustomInternalTransaction($object, $xaction);
@ -115,6 +122,7 @@ final class PhabricatorEditEngineConfigurationEditor
case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE; case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER; case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT: case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
return; return;
} }

View file

@ -17,6 +17,10 @@ final class PhabricatorEditEngineConfiguration
private $engine = self::ATTACHABLE; private $engine = self::ATTACHABLE;
const LOCK_VISIBLE = 'visible';
const LOCK_LOCKED = 'locked';
const LOCK_HIDDEN = 'hidden';
public function getTableName() { public function getTableName() {
return 'search_editengineconfiguration'; return 'search_editengineconfiguration';
} }
@ -97,6 +101,22 @@ final class PhabricatorEditEngineConfiguration
} }
} }
$locks = $this->getFieldLocks();
foreach ($fields as $field) {
$key = $field->getKey();
switch (idx($locks, $key)) {
case self::LOCK_LOCKED:
$field->setIsLocked(true);
break;
case self::LOCK_HIDDEN:
$field->setIsHidden(true);
break;
case self::LOCK_VISIBLE:
default:
break;
}
}
$fields = $this->reorderFields($fields); $fields = $this->reorderFields($fields);
$preamble = $this->getPreamble(); $preamble = $this->getPreamble();
@ -106,6 +126,7 @@ final class PhabricatorEditEngineConfiguration
->setKey('config.preamble') ->setKey('config.preamble')
->setIsReorderable(false) ->setIsReorderable(false)
->setIsDefaultable(false) ->setIsDefaultable(false)
->setIsLockable(false)
->setValue($preamble), ->setValue($preamble),
) + $fields; ) + $fields;
} }
@ -116,19 +137,7 @@ final class PhabricatorEditEngineConfiguration
private function reorderFields(array $fields) { private function reorderFields(array $fields) {
$keys = $this->getFieldOrder(); $keys = $this->getFieldOrder();
$fields = array_select_keys($fields, $keys) + $fields; $fields = array_select_keys($fields, $keys) + $fields;
return $fields;
// Now, move locked fields to the bottom.
$head = array();
$tail = array();
foreach ($fields as $key => $field) {
if (!$field->getIsLocked()) {
$head[$key] = $field;
} else {
$tail[$key] = $field;
}
}
return $head + $tail;
} }
public function getURI() { public function getURI() {
@ -176,6 +185,14 @@ final class PhabricatorEditEngineConfiguration
return $this->getProperty('order', array()); return $this->getProperty('order', array());
} }
public function setFieldLocks(array $field_locks) {
return $this->setProperty('locks', $field_locks);
}
public function getFieldLocks() {
return $this->getProperty('locks', array());
}
public function getFieldDefault($key) { public function getFieldDefault($key) {
$defaults = $this->getProperty('defaults', array()); $defaults = $this->getProperty('defaults', array());
return idx($defaults, $key); return idx($defaults, $key);

View file

@ -7,6 +7,7 @@ final class PhabricatorEditEngineConfigurationTransaction
const TYPE_PREAMBLE = 'editengine.config.preamble'; const TYPE_PREAMBLE = 'editengine.config.preamble';
const TYPE_ORDER = 'editengine.config.order'; const TYPE_ORDER = 'editengine.config.order';
const TYPE_DEFAULT = 'editengine.config.default'; const TYPE_DEFAULT = 'editengine.config.default';
const TYPE_LOCKS = 'editengine.config.locks';
public function getApplicationName() { public function getApplicationName() {
return 'search'; return 'search';
@ -55,6 +56,10 @@ final class PhabricatorEditEngineConfigurationTransaction
'%s changed the default value for field "%s".', '%s changed the default value for field "%s".',
$this->renderHandleLink($author_phid), $this->renderHandleLink($author_phid),
$key); $key);
case self::TYPE_LOCKS:
return pht(
'%s changed locked and hidden fields.',
$this->renderHandleLink($author_phid));
} }
return parent::getTitle(); return parent::getTitle();

View file

@ -527,3 +527,7 @@ properly, and submit values. */
.aphront-form-choose-table .aphront-form-choose-button-cell { .aphront-form-choose-table .aphront-form-choose-button-cell {
padding: 4px 8px; padding: 4px 8px;
} }
.aphront-form-preview-hidden {
opacity: 0.5;
}