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:
parent
53d5cd3950
commit
269e0bfc94
11 changed files with 235 additions and 18 deletions
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
return array(
|
||||
'names' => array(
|
||||
'core.pkg.css' => '0689cd7e',
|
||||
'core.pkg.css' => '9f339987',
|
||||
'core.pkg.js' => '47dc9ebb',
|
||||
'darkconsole.pkg.js' => 'e7393ebb',
|
||||
'differential.pkg.css' => '2de124c9',
|
||||
|
@ -130,7 +130,7 @@ return array(
|
|||
'rsrc/css/phui/phui-document.css' => '765a9dac',
|
||||
'rsrc/css/phui/phui-feed-story.css' => 'b7b26d23',
|
||||
'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-header-view.css' => '55bb32dd',
|
||||
'rsrc/css/phui/phui-icon.css' => 'b0a6b1b6',
|
||||
|
@ -795,7 +795,7 @@ return array(
|
|||
'phui-font-icon-base-css' => 'ecbbb4c2',
|
||||
'phui-fontkit-css' => '9cda225e',
|
||||
'phui-form-css' => 'afdb2c6e',
|
||||
'phui-form-view-css' => '621b21c5',
|
||||
'phui-form-view-css' => 'c1d2ef29',
|
||||
'phui-header-view-css' => '55bb32dd',
|
||||
'phui-icon-view-css' => 'b0a6b1b6',
|
||||
'phui-image-mask-css' => '5a8b09c8',
|
||||
|
|
|
@ -2117,6 +2117,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEditEngineConfigurationEditEngine' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php',
|
||||
'PhabricatorEditEngineConfigurationEditor' => 'applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php',
|
||||
'PhabricatorEditEngineConfigurationListController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationListController.php',
|
||||
'PhabricatorEditEngineConfigurationLockController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationLockController.php',
|
||||
'PhabricatorEditEngineConfigurationPHIDType' => 'applications/transactions/phid/PhabricatorEditEngineConfigurationPHIDType.php',
|
||||
'PhabricatorEditEngineConfigurationQuery' => 'applications/transactions/query/PhabricatorEditEngineConfigurationQuery.php',
|
||||
'PhabricatorEditEngineConfigurationReorderController' => 'applications/transactions/controller/PhabricatorEditEngineConfigurationReorderController.php',
|
||||
|
@ -6211,6 +6212,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorEditEngineConfigurationEditEngine' => 'PhabricatorEditEngine',
|
||||
'PhabricatorEditEngineConfigurationEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhabricatorEditEngineConfigurationListController' => 'PhabricatorEditEngineController',
|
||||
'PhabricatorEditEngineConfigurationLockController' => 'PhabricatorEditEngineController',
|
||||
'PhabricatorEditEngineConfigurationPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorEditEngineConfigurationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorEditEngineConfigurationReorderController' => 'PhabricatorEditEngineController',
|
||||
|
|
|
@ -49,6 +49,8 @@ final class PhabricatorTransactionsApplication extends PhabricatorApplication {
|
|||
'PhabricatorEditEngineConfigurationReorderController',
|
||||
'defaults/(?P<key>[^/]+)/' =>
|
||||
'PhabricatorEditEngineConfigurationDefaultsController',
|
||||
'lock/(?P<key>[^/]+)/' =>
|
||||
'PhabricatorEditEngineConfigurationLockController',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -139,6 +139,16 @@ final class PhabricatorEditEngineConfigurationViewController
|
|||
->setWorkflow(true)
|
||||
->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -658,12 +658,22 @@ abstract class PhabricatorEditEngine
|
|||
$validation_exception = null;
|
||||
if ($request->isFormPost()) {
|
||||
foreach ($fields as $field) {
|
||||
if ($field->getIsLocked() || $field->getIsHidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field->readValueFromSubmit($request);
|
||||
}
|
||||
|
||||
$xactions = array();
|
||||
foreach ($fields as $field) {
|
||||
$xactions[] = $field->generateTransaction(clone $template);
|
||||
$xaction = $field->generateTransaction(clone $template);
|
||||
|
||||
if (!$xaction) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$xactions[] = $xaction;
|
||||
}
|
||||
|
||||
$editor = $object->getApplicationTransactionEditor()
|
||||
|
@ -683,6 +693,10 @@ abstract class PhabricatorEditEngine
|
|||
} else {
|
||||
if ($this->getIsCreate()) {
|
||||
foreach ($fields as $field) {
|
||||
if ($field->getIsLocked() || $field->getIsHidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field->readValueFromRequest($request);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -13,11 +13,16 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
private $metadata = array();
|
||||
private $description;
|
||||
private $editTypeKey;
|
||||
|
||||
private $isLocked;
|
||||
private $isHidden;
|
||||
|
||||
private $isPreview;
|
||||
private $isReorderable = true;
|
||||
private $isEditDefaults;
|
||||
|
||||
private $isReorderable = true;
|
||||
private $isDefaultable = true;
|
||||
private $isLockable = true;
|
||||
|
||||
public function setKey($key) {
|
||||
$this->key = $key;
|
||||
|
@ -118,6 +123,24 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
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() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
}
|
||||
|
@ -138,10 +161,17 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
|
||||
if ($this->getIsPreview()) {
|
||||
$disabled = true;
|
||||
$hidden = false;
|
||||
} else if ($this->getIsEditDefaults()) {
|
||||
$disabled = false;
|
||||
$hidden = false;
|
||||
} else {
|
||||
$disabled = $this->getIsLocked();
|
||||
$hidden = $this->getIsHidden();
|
||||
}
|
||||
|
||||
if ($hidden) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$control->setDisabled($disabled);
|
||||
|
@ -152,6 +182,18 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
public function appendToForm(AphrontFormView $form) {
|
||||
$control = $this->renderControl();
|
||||
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);
|
||||
}
|
||||
return $this;
|
||||
|
@ -187,6 +229,10 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
public function generateTransaction(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
if (!$this->getTransactionType()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$xaction
|
||||
->setTransactionType($this->getTransactionType())
|
||||
->setNewValue($this->getValueForTransaction());
|
||||
|
|
|
@ -21,6 +21,7 @@ final class PhabricatorEditEngineConfigurationEditor
|
|||
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
|
||||
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
|
||||
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT;
|
||||
$types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS;
|
||||
|
||||
return $types;
|
||||
}
|
||||
|
@ -67,6 +68,8 @@ final class PhabricatorEditEngineConfigurationEditor
|
|||
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
|
||||
$field_key = $xaction->getMetadataValue('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_ORDER:
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
|
||||
return $xaction->getNewValue();
|
||||
}
|
||||
}
|
||||
|
@ -101,6 +105,9 @@ final class PhabricatorEditEngineConfigurationEditor
|
|||
$field_key = $xaction->getMetadataValue('field.key');
|
||||
$object->setFieldDefault($field_key, $xaction->getNewValue());
|
||||
return;
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
|
||||
$object->setFieldLocks($xaction->getNewValue());
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||
|
@ -115,6 +122,7 @@ final class PhabricatorEditEngineConfigurationEditor
|
|||
case PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_ORDER;
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_DEFAULT:
|
||||
case PhabricatorEditEngineConfigurationTransaction::TYPE_LOCKS:
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@ final class PhabricatorEditEngineConfiguration
|
|||
|
||||
private $engine = self::ATTACHABLE;
|
||||
|
||||
const LOCK_VISIBLE = 'visible';
|
||||
const LOCK_LOCKED = 'locked';
|
||||
const LOCK_HIDDEN = 'hidden';
|
||||
|
||||
public function getTableName() {
|
||||
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);
|
||||
|
||||
$preamble = $this->getPreamble();
|
||||
|
@ -106,6 +126,7 @@ final class PhabricatorEditEngineConfiguration
|
|||
->setKey('config.preamble')
|
||||
->setIsReorderable(false)
|
||||
->setIsDefaultable(false)
|
||||
->setIsLockable(false)
|
||||
->setValue($preamble),
|
||||
) + $fields;
|
||||
}
|
||||
|
@ -116,19 +137,7 @@ final class PhabricatorEditEngineConfiguration
|
|||
private function reorderFields(array $fields) {
|
||||
$keys = $this->getFieldOrder();
|
||||
$fields = array_select_keys($fields, $keys) + $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;
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
|
@ -176,6 +185,14 @@ final class PhabricatorEditEngineConfiguration
|
|||
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) {
|
||||
$defaults = $this->getProperty('defaults', array());
|
||||
return idx($defaults, $key);
|
||||
|
|
|
@ -7,6 +7,7 @@ final class PhabricatorEditEngineConfigurationTransaction
|
|||
const TYPE_PREAMBLE = 'editengine.config.preamble';
|
||||
const TYPE_ORDER = 'editengine.config.order';
|
||||
const TYPE_DEFAULT = 'editengine.config.default';
|
||||
const TYPE_LOCKS = 'editengine.config.locks';
|
||||
|
||||
public function getApplicationName() {
|
||||
return 'search';
|
||||
|
@ -55,6 +56,10 @@ final class PhabricatorEditEngineConfigurationTransaction
|
|||
'%s changed the default value for field "%s".',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$key);
|
||||
case self::TYPE_LOCKS:
|
||||
return pht(
|
||||
'%s changed locked and hidden fields.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
}
|
||||
|
||||
return parent::getTitle();
|
||||
|
|
|
@ -527,3 +527,7 @@ properly, and submit values. */
|
|||
.aphront-form-choose-table .aphront-form-choose-button-cell {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.aphront-form-preview-hidden {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue