mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 20:10:55 +01:00
Provide contextual documentation explaining how to prefill ApplicationEditor create forms
Summary: Ref T9132. Although forms do generally support prefilling right now, you have to guess how to do it. Provide an explicit action showing you which values are supported and how to prefill them. This is generated automatically when an application switches to ApplicationEditor. Test Plan: {F939804} {F939805} {F939806} Reviewers: chad Reviewed By: chad Maniphest Tasks: T9132 Differential Revision: https://secure.phabricator.com/D14392
This commit is contained in:
parent
105cbaaee1
commit
3dec4c7dbd
14 changed files with 545 additions and 18 deletions
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
return array(
|
||||
'names' => array(
|
||||
'core.pkg.css' => 'dd913c69',
|
||||
'core.pkg.css' => 'bbeb85d2',
|
||||
'core.pkg.js' => '47dc9ebb',
|
||||
'darkconsole.pkg.js' => 'e7393ebb',
|
||||
'differential.pkg.css' => '2de124c9',
|
||||
|
@ -25,7 +25,7 @@ return array(
|
|||
'rsrc/css/aphront/notification.css' => '9c279160',
|
||||
'rsrc/css/aphront/panel-view.css' => '8427b78d',
|
||||
'rsrc/css/aphront/phabricator-nav-view.css' => 'a24cb589',
|
||||
'rsrc/css/aphront/table-view.css' => '61543e7a',
|
||||
'rsrc/css/aphront/table-view.css' => '6d01d468',
|
||||
'rsrc/css/aphront/tokenizer.css' => '04875312',
|
||||
'rsrc/css/aphront/tooltip.css' => '7672b60f',
|
||||
'rsrc/css/aphront/typeahead-browse.css' => 'd8581d2c',
|
||||
|
@ -498,7 +498,7 @@ return array(
|
|||
'aphront-list-filter-view-css' => '5d6f0526',
|
||||
'aphront-multi-column-view-css' => 'fd18389d',
|
||||
'aphront-panel-view-css' => '8427b78d',
|
||||
'aphront-table-view-css' => '61543e7a',
|
||||
'aphront-table-view-css' => '6d01d468',
|
||||
'aphront-tokenizer-control-css' => '04875312',
|
||||
'aphront-tooltip-css' => '7672b60f',
|
||||
'aphront-typeahead-control-css' => '0e403212',
|
||||
|
|
|
@ -1571,6 +1571,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
|
||||
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
|
||||
'PhabricatorApplicationEditEngine' => 'applications/transactions/editengine/PhabricatorApplicationEditEngine.php',
|
||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
||||
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
||||
'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php',
|
||||
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
||||
|
@ -5500,6 +5501,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationEditEngine' => 'Phobject',
|
||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
||||
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationLaunchView' => 'AphrontTagView',
|
||||
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
||||
|
|
|
@ -635,4 +635,8 @@ abstract class PhabricatorApplication
|
|||
return array();
|
||||
}
|
||||
|
||||
protected function getEditRoutePattern($base) {
|
||||
return $base.'(?:(?P<id>[0-9]\d*)/)?(?:(?P<editAction>parameters)/)?';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ final class PhabricatorPasteApplication extends PhabricatorApplication {
|
|||
'/paste/' => array(
|
||||
'(query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorPasteListController',
|
||||
'create/' => 'PhabricatorPasteEditController',
|
||||
'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteEditController',
|
||||
$this->getEditRoutePattern('edit/') => 'PhabricatorPasteEditController',
|
||||
'raw/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteRawController',
|
||||
'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteCommentController',
|
||||
),
|
||||
|
|
|
@ -18,7 +18,7 @@ final class PhabricatorPasteListController extends PhabricatorPasteController {
|
|||
$crumbs->addAction(
|
||||
id(new PHUIListItemView())
|
||||
->setName(pht('Create Paste'))
|
||||
->setHref($this->getApplicationURI('create/'))
|
||||
->setHref($this->getApplicationURI('edit/'))
|
||||
->setIcon('fa-plus-square'));
|
||||
|
||||
return $crumbs;
|
||||
|
|
|
@ -41,11 +41,17 @@ final class PhabricatorPasteEditEngine
|
|||
id(new PhabricatorTextEditField())
|
||||
->setKey('title')
|
||||
->setLabel(pht('Title'))
|
||||
->setDescription(pht('Name of the paste.'))
|
||||
->setTransactionType(PhabricatorPasteTransaction::TYPE_TITLE)
|
||||
->setValue($object->getTitle()),
|
||||
id(new PhabricatorSelectEditField())
|
||||
->setKey('language')
|
||||
->setLabel(pht('Language'))
|
||||
->setDescription(
|
||||
pht(
|
||||
'Programming language to interpret the paste as for syntax '.
|
||||
'highlighting. By default, the language is inferred from the '.
|
||||
'title.'))
|
||||
->setAliases(array('lang'))
|
||||
->setTransactionType(PhabricatorPasteTransaction::TYPE_LANGUAGE)
|
||||
->setValue($object->getLanguage())
|
||||
|
@ -53,12 +59,14 @@ final class PhabricatorPasteEditEngine
|
|||
id(new PhabricatorSelectEditField())
|
||||
->setKey('status')
|
||||
->setLabel(pht('Status'))
|
||||
->setDescription(pht('Archive the paste.'))
|
||||
->setTransactionType(PhabricatorPasteTransaction::TYPE_STATUS)
|
||||
->setValue($object->getStatus())
|
||||
->setOptions(PhabricatorPaste::getStatusNameMap()),
|
||||
id(new PhabricatorTextAreaEditField())
|
||||
->setKey('text')
|
||||
->setLabel(pht('Text'))
|
||||
->setDescription(pht('The main body text of the paste.'))
|
||||
->setTransactionType(PhabricatorPasteTransaction::TYPE_CONTENT)
|
||||
->setMonospaced(true)
|
||||
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL)
|
||||
|
|
|
@ -4,6 +4,7 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
|
||||
private $viewer;
|
||||
private $controller;
|
||||
private $isCreate;
|
||||
|
||||
final public function setViewer(PhabricatorUser $viewer) {
|
||||
$this->viewer = $viewer;
|
||||
|
@ -44,16 +45,22 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
'key' => 'policy.view',
|
||||
'aliases' => array('view'),
|
||||
'capability' => PhabricatorPolicyCapability::CAN_VIEW,
|
||||
'label' => pht('View Policy'),
|
||||
'description' => pht('Controls who can view the object.'),
|
||||
),
|
||||
PhabricatorTransactions::TYPE_EDIT_POLICY => array(
|
||||
'key' => 'policy.edit',
|
||||
'aliases' => array('edit'),
|
||||
'capability' => PhabricatorPolicyCapability::CAN_EDIT,
|
||||
'label' => pht('Edit Policy'),
|
||||
'description' => pht('Controls who can edit the object.'),
|
||||
),
|
||||
PhabricatorTransactions::TYPE_JOIN_POLICY => array(
|
||||
'key' => 'policy.join',
|
||||
'aliases' => array('join'),
|
||||
'capability' => PhabricatorPolicyCapability::CAN_JOIN,
|
||||
'label' => pht('Join Policy'),
|
||||
'description' => pht('Controls who can join the object.'),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -65,9 +72,13 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
$capability = $spec['capability'];
|
||||
$key = $spec['key'];
|
||||
$aliases = $spec['aliases'];
|
||||
$label = $spec['label'];
|
||||
$description = $spec['description'];
|
||||
|
||||
$policy_field = id(new PhabricatorPolicyEditField())
|
||||
->setKey($key)
|
||||
->setLabel($label)
|
||||
->setDescription($description)
|
||||
->setAliases($aliases)
|
||||
->setCapability($capability)
|
||||
->setPolicies($policies)
|
||||
|
@ -81,6 +92,9 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
if (isset($types[$type_space])) {
|
||||
$space_field = id(new PhabricatorSpaceEditField())
|
||||
->setKey('spacePHID')
|
||||
->setLabel(pht('Space'))
|
||||
->setDescription(
|
||||
pht('Shifts the object in the Spaces application.'))
|
||||
->setAliases(array('space', 'policy.space'))
|
||||
->setTransactionType($type_space)
|
||||
->setValue($object->getSpacePHID());
|
||||
|
@ -112,6 +126,9 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
$edge_field = id(new PhabricatorDatasourceEditField())
|
||||
->setKey('projectPHIDs')
|
||||
->setLabel(pht('Projects'))
|
||||
->setDescription(
|
||||
pht(
|
||||
'Add or remove associated projects.'))
|
||||
->setDatasource(new PhabricatorProjectDatasource())
|
||||
->setAliases(array('project', 'projects'))
|
||||
->setTransactionType($edge_type)
|
||||
|
@ -137,6 +154,7 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
$subscribers_field = id(new PhabricatorDatasourceEditField())
|
||||
->setKey('subscriberPHIDs')
|
||||
->setLabel(pht('Subscribers'))
|
||||
->setDescription(pht('Manage subscribers.'))
|
||||
->setDatasource(new PhabricatorMetaMTAMailableDatasource())
|
||||
->setAliases(array('subscriber', 'subscribers'))
|
||||
->setTransactionType($subscribers_type)
|
||||
|
@ -158,6 +176,10 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
abstract protected function getObjectEditShortText($object);
|
||||
abstract protected function getObjectViewURI($object);
|
||||
|
||||
protected function getObjectEditURI($object) {
|
||||
return $this->getController()->getApplicationURI('edit/');
|
||||
}
|
||||
|
||||
protected function getObjectCreateCancelURI($object) {
|
||||
return $this->getController()->getApplicationURI();
|
||||
}
|
||||
|
@ -174,6 +196,31 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
return pht('Save Changes');
|
||||
}
|
||||
|
||||
protected function getEditURI($object, $path = null) {
|
||||
$parts = array(
|
||||
$this->getObjectEditURI($object),
|
||||
);
|
||||
|
||||
if (!$this->getIsCreate()) {
|
||||
$parts[] = $object->getID().'/';
|
||||
}
|
||||
|
||||
if ($path !== null) {
|
||||
$parts[] = $path;
|
||||
}
|
||||
|
||||
return implode('', $parts);
|
||||
}
|
||||
|
||||
final protected function setIsCreate($is_create) {
|
||||
$this->isCreate = $is_create;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final protected function getIsCreate() {
|
||||
return $this->isCreate;
|
||||
}
|
||||
|
||||
final public function buildResponse() {
|
||||
$controller = $this->getController();
|
||||
$viewer = $this->getViewer();
|
||||
|
@ -194,11 +241,11 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$is_create = false;
|
||||
$this->setIsCreate(false);
|
||||
} else {
|
||||
$object = $this->newEditableObject();
|
||||
|
||||
$is_create = true;
|
||||
$this->setIsCreate(true);
|
||||
}
|
||||
|
||||
$fields = $this->buildEditFields($object);
|
||||
|
@ -209,6 +256,12 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
->setObject($object);
|
||||
}
|
||||
|
||||
$action = $request->getURIData('editAction');
|
||||
switch ($action) {
|
||||
case 'parameters':
|
||||
return $this->buildParametersResponse($object, $fields);
|
||||
}
|
||||
|
||||
$validation_exception = null;
|
||||
if ($request->isFormPost()) {
|
||||
foreach ($fields as $field) {
|
||||
|
@ -238,7 +291,7 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
$validation_exception = $ex;
|
||||
}
|
||||
} else {
|
||||
if ($is_create) {
|
||||
if ($this->getIsCreate()) {
|
||||
foreach ($fields as $field) {
|
||||
$field->readValueFromRequest($request);
|
||||
}
|
||||
|
@ -252,28 +305,28 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
$box = id(new PHUIObjectBoxView())
|
||||
->setUser($viewer);
|
||||
|
||||
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
|
||||
$crumbs = $this->buildCrumbs($object, $final = true);
|
||||
|
||||
if ($is_create) {
|
||||
if ($this->getIsCreate()) {
|
||||
$header_text = $this->getObjectCreateTitleText($object);
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
$this->getObjectCreateShortText($object));
|
||||
|
||||
$cancel_uri = $this->getObjectCreateCancelURI($object);
|
||||
$submit_button = $this->getObjectCreateButtonText($object);
|
||||
} else {
|
||||
$header_text = $this->getObjectEditTitleText($object);
|
||||
|
||||
$crumbs->addTextCrumb(
|
||||
$this->getObjectEditShortText($object),
|
||||
$this->getObjectViewURI($object));
|
||||
|
||||
$cancel_uri = $this->getObjectEditCancelURI($object);
|
||||
$submit_button = $this->getObjectEditButtonText($object);
|
||||
}
|
||||
|
||||
$box->setHeaderText($header_text);
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($header_text);
|
||||
|
||||
$action_button = $this->buildEditFormActionButton($object);
|
||||
|
||||
$header->addActionLink($action_button);
|
||||
|
||||
$box->setHeader($header);
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
|
@ -299,5 +352,95 @@ abstract class PhabricatorApplicationEditEngine extends Phobject {
|
|||
->appendChild($box);
|
||||
}
|
||||
|
||||
private function buildParametersResponse($object, array $fields) {
|
||||
$controller = $this->getController();
|
||||
$viewer = $this->getViewer();
|
||||
$request = $controller->getRequest();
|
||||
|
||||
$crumbs = $this->buildCrumbs($object);
|
||||
$crumbs->addTextCrumb(pht('HTTP Parameters'));
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(
|
||||
pht(
|
||||
'HTTP Parameters: %s',
|
||||
$this->getObjectCreateShortText($object)));
|
||||
|
||||
// TODO: Upgrade to DocumentViewPro.
|
||||
|
||||
$document = id(new PHUIDocumentView())
|
||||
->setUser($viewer)
|
||||
->setHeader($header);
|
||||
|
||||
$document->appendChild(
|
||||
id(new PhabricatorApplicationEditHTTPParameterHelpView())
|
||||
->setUser($viewer)
|
||||
->setFields($fields));
|
||||
|
||||
return $controller->newPage()
|
||||
->setTitle(pht('HTTP Parameters'))
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild($document);
|
||||
}
|
||||
|
||||
private function buildCrumbs($object, $final = false) {
|
||||
$controller = $this->getcontroller();
|
||||
|
||||
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
|
||||
if ($this->getIsCreate()) {
|
||||
$create_text = $this->getObjectCreateShortText($object);
|
||||
if ($final) {
|
||||
$crumbs->addTextCrumb($create_text);
|
||||
} else {
|
||||
$edit_uri = $this->getEditURI($object);
|
||||
$crumbs->addTextCrumb($create_text, $edit_uri);
|
||||
}
|
||||
} else {
|
||||
$crumbs->addTextCrumb(
|
||||
$this->getObjectEditShortText($object),
|
||||
$this->getObjectViewURI($object));
|
||||
|
||||
$edit_text = pht('Edit');
|
||||
if ($final) {
|
||||
$crumbs->addTextCrumb($edit_text);
|
||||
} else {
|
||||
$edit_uri = $this->getEditURI($object);
|
||||
$crumbs->addTextCrumb($edit_text, $edit_uri);
|
||||
}
|
||||
}
|
||||
|
||||
return $crumbs;
|
||||
}
|
||||
|
||||
private function buildEditFormActionButton($object) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$action_view = id(new PhabricatorActionListView())
|
||||
->setUser($viewer);
|
||||
|
||||
foreach ($this->buildEditFormActions($object) as $action) {
|
||||
$action_view->addAction($action);
|
||||
}
|
||||
|
||||
$action_button = id(new PHUIButtonView())
|
||||
->setTag('a')
|
||||
->setText(pht('Actions'))
|
||||
->setHref('#')
|
||||
->setIconFont('fa-bars')
|
||||
->setDropdownMenu($action_view);
|
||||
|
||||
return $action_button;
|
||||
}
|
||||
|
||||
private function buildEditFormActions($object) {
|
||||
$actions = array();
|
||||
|
||||
$actions[] = id(new PhabricatorActionView())
|
||||
->setName(pht('Show HTTP Parameters'))
|
||||
->setIcon('fa-crosshairs')
|
||||
->setHref($this->getEditURI($object, 'parameters/'));
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
private $object;
|
||||
private $transactionType;
|
||||
private $metadata = array();
|
||||
private $description;
|
||||
|
||||
public function setKey($key) {
|
||||
$this->key = $key;
|
||||
|
@ -57,6 +58,15 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
return $this->object;
|
||||
}
|
||||
|
||||
public function setDescription($description) {
|
||||
$this->description = $description;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription() {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
abstract protected function newControl();
|
||||
|
||||
protected function renderControl() {
|
||||
|
@ -209,4 +219,8 @@ abstract class PhabricatorEditField extends Phobject {
|
|||
return $list;
|
||||
}
|
||||
|
||||
public function getHTTPParameterType() {
|
||||
return 'string';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,4 +51,8 @@ final class PhabricatorPolicyEditField
|
|||
return $control;
|
||||
}
|
||||
|
||||
public function getHTTPParameterType() {
|
||||
return 'phid';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,4 +22,8 @@ final class PhabricatorSelectEditField
|
|||
->setOptions($this->getOptions());
|
||||
}
|
||||
|
||||
public function getHTTPParameterType() {
|
||||
return 'select';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,4 +9,8 @@ final class PhabricatorSpaceEditField
|
|||
return null;
|
||||
}
|
||||
|
||||
public function getHTTPParameterType() {
|
||||
return 'phid';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,4 +87,8 @@ abstract class PhabricatorTokenizerEditField
|
|||
return $new;
|
||||
}
|
||||
|
||||
public function getHTTPParameterType() {
|
||||
return 'list<phid>';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Renders the "HTTP Parameters" help page for edit engines.
|
||||
*
|
||||
* This page has a ton of text and specialized rendering on it, this class
|
||||
* just pulls it out of the main @{class:PhabricatorApplicationEditEngine}.
|
||||
*/
|
||||
final class PhabricatorApplicationEditHTTPParameterHelpView
|
||||
extends AphrontView {
|
||||
|
||||
private $object;
|
||||
private $fields;
|
||||
|
||||
public function setObject($object) {
|
||||
$this->object = $object;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getObject() {
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
public function setFields(array $fields) {
|
||||
$this->fields = $fields;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFields() {
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$object = $this->getObject();
|
||||
$fields = $this->getFields();
|
||||
|
||||
$uri = 'https://your.install.com/application/edit/';
|
||||
|
||||
// Remove fields which do not expose an HTTP parameter type.
|
||||
$types = array();
|
||||
foreach ($fields as $key => $field) {
|
||||
$type = $field->getHTTPParameterType();
|
||||
if ($type === null) {
|
||||
unset($fields[$key]);
|
||||
}
|
||||
$types[$type][] = $field;
|
||||
}
|
||||
|
||||
$intro = pht(<<<EOTEXT
|
||||
When creating objects in the web interface, you can use HTTP parameters to
|
||||
prefill fields in the form. This allows you to quickly create a link to a
|
||||
form with some of the fields already filled in with default values.
|
||||
|
||||
To prefill a form, start by finding the URI for the form you want to prefill.
|
||||
Do this by navigating to the relevant application, clicking the "Create" button
|
||||
for the type of object you want to create, and then copying the URI out of your
|
||||
browser's address bar. It will usually look something like this:
|
||||
|
||||
```
|
||||
%s
|
||||
```
|
||||
|
||||
However, `your.install.com` will be the domain where your copy of Phabricator
|
||||
is installed, and `application/` will be the URI for an application. Some
|
||||
applications have multiple forms for creating objects or URIs that look a little
|
||||
different than this example, so the URI may not look exactly like this.
|
||||
|
||||
To prefill the form, add properly encoded HTTP parameters to the URI. You
|
||||
should end up with something like this:
|
||||
|
||||
```
|
||||
%s?title=Platyplus&body=Ornithopter
|
||||
```
|
||||
|
||||
If the form has `title` and `body` fields of the correct types, visiting this
|
||||
link will prefill those fields with the values "Platypus" and "Ornithopter"
|
||||
respectively.
|
||||
|
||||
The rest of this document shows which parameters you can add to this form and
|
||||
how to format them.
|
||||
|
||||
|
||||
Supported Fields
|
||||
----------------
|
||||
|
||||
This form supports these fields:
|
||||
|
||||
EOTEXT
|
||||
,
|
||||
$uri,
|
||||
$uri);
|
||||
|
||||
$rows = array();
|
||||
foreach ($fields as $field) {
|
||||
$rows[] = array(
|
||||
$field->getLabel(),
|
||||
$field->getKey(),
|
||||
$field->getHTTPParameterType(),
|
||||
$field->getDescription(),
|
||||
);
|
||||
}
|
||||
|
||||
$main_table = id(new AphrontTableView($rows))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Label'),
|
||||
pht('Key'),
|
||||
pht('Type'),
|
||||
pht('Description'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri',
|
||||
null,
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
$aliases_text = pht(<<<EOTEXT
|
||||
Aliases
|
||||
-------
|
||||
|
||||
Aliases are alternate recognized keys for a field. For example, a field with
|
||||
a complex key like `examplePHIDs` might be have a simple version of that key
|
||||
as an alias, like `example`.
|
||||
|
||||
Aliases work just like the primary key when prefilling forms. They make it
|
||||
easier to remember and use HTTP parameters by providing more natural ways to do
|
||||
some prefilling.
|
||||
|
||||
For example, if a field has `examplePHIDs` as a key but has aliases `example`
|
||||
and `examples`, these three URIs will all do the same thing:
|
||||
|
||||
```
|
||||
%s?examplePHIDs=...
|
||||
%s?examples=...
|
||||
%s?example=...
|
||||
```
|
||||
|
||||
If a URI specifies multiple default values for a field, the value using the
|
||||
primary key has precedence. Generally, you can not mix different aliases in
|
||||
a single URI.
|
||||
|
||||
EOTEXT
|
||||
,
|
||||
$uri,
|
||||
$uri,
|
||||
$uri);
|
||||
|
||||
$rows = array();
|
||||
foreach ($fields as $field) {
|
||||
$aliases = $field->getAliases();
|
||||
if (!$aliases) {
|
||||
continue;
|
||||
}
|
||||
$rows[] = array(
|
||||
$field->getLabel(),
|
||||
$field->getKey(),
|
||||
implode(', ', $aliases),
|
||||
);
|
||||
}
|
||||
|
||||
$alias_table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(pht('This object has no fields with aliases.'))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Label'),
|
||||
pht('Key'),
|
||||
pht('Aliases'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri',
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
$select_text = pht(<<<EOTEXT
|
||||
Select Fields
|
||||
-------------
|
||||
|
||||
Some fields support selection from a specific set of values. When prefilling
|
||||
these fields, use the value in the **Value** column to select the appropriate
|
||||
setting.
|
||||
|
||||
EOTEXT
|
||||
);
|
||||
|
||||
$rows = array();
|
||||
foreach ($fields as $field) {
|
||||
if (!($field instanceof PhabricatorSelectEditField)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$options = $field->getOptions();
|
||||
$label = $field->getLabel();
|
||||
foreach ($options as $option_key => $option_value) {
|
||||
if (strlen($option_key)) {
|
||||
$option_display = $option_key;
|
||||
} else {
|
||||
$option_display = phutil_tag('em', array(), pht('<empty>'));
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$label,
|
||||
$option_display,
|
||||
$option_value,
|
||||
);
|
||||
$label = null;
|
||||
}
|
||||
}
|
||||
|
||||
$select_table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(pht('This object has no select fields.'))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Field'),
|
||||
pht('Value'),
|
||||
pht('Label'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri',
|
||||
null,
|
||||
'wide',
|
||||
));
|
||||
|
||||
$types_text = pht(<<<EOTEXT
|
||||
Field Types
|
||||
-----------
|
||||
|
||||
Fields in this form have the types described in the table below. This table
|
||||
shows how to format values for each field type.
|
||||
EOTEXT
|
||||
);
|
||||
|
||||
// TODO: This should be formalized and modularized.
|
||||
$type_spec = array(
|
||||
'string' => array(
|
||||
'format' => pht('URL encoded text.'),
|
||||
'examples' => array(
|
||||
'v=simple',
|
||||
'v=properly%20escaped%20text',
|
||||
),
|
||||
),
|
||||
'select' => array(
|
||||
'format' => pht('Value from allowed set.'),
|
||||
'examples' => array(
|
||||
'v=value',
|
||||
),
|
||||
),
|
||||
'list<phid>' => array(
|
||||
'format' => array(
|
||||
pht('Comma-separated list of PHIDs.'),
|
||||
pht('List of PHIDs, as array.'),
|
||||
),
|
||||
'examples' => array(
|
||||
'v=PHID-XXXX-1111,PHID-XXXX-2222',
|
||||
'v[]=PHID-XXXX-1111&v[]=PHID-XXXX-2222',
|
||||
),
|
||||
),
|
||||
'phid' => array(
|
||||
'format' => pht('Single PHID.'),
|
||||
'examples' => pht('v=PHID-XXX-1111'),
|
||||
),
|
||||
);
|
||||
|
||||
$rows = array();
|
||||
$br = phutil_tag('br');
|
||||
foreach ($types as $type => $fields) {
|
||||
$spec = idx($type_spec, $type, array());
|
||||
|
||||
$field_list = mpull($fields, 'getKey');
|
||||
$field_list = phutil_implode_html($br, $field_list);
|
||||
|
||||
$format_list = idx($spec, 'format', array());
|
||||
$format_list = phutil_implode_html($br, (array)$format_list);
|
||||
|
||||
$example_list = idx($spec, 'examples', array());
|
||||
$example_list = phutil_implode_html($br, (array)$example_list);
|
||||
|
||||
$rows[] = array(
|
||||
$type,
|
||||
$field_list,
|
||||
$format_list,
|
||||
$example_list,
|
||||
);
|
||||
}
|
||||
|
||||
$types_table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(pht('This object has no fields with types.'))
|
||||
->setHeaders(
|
||||
array(
|
||||
pht('Type'),
|
||||
pht('Fields'),
|
||||
pht('Formats'),
|
||||
pht('Examples'),
|
||||
))
|
||||
->setColumnClasses(
|
||||
array(
|
||||
'pri top',
|
||||
'top',
|
||||
'top',
|
||||
'wide top prewrap',
|
||||
));
|
||||
|
||||
return array(
|
||||
$this->renderInstructions($intro),
|
||||
$this->renderTable($main_table),
|
||||
$this->renderInstructions($aliases_text),
|
||||
$this->renderTable($alias_table),
|
||||
$this->renderInstructions($select_text),
|
||||
$this->renderTable($select_table),
|
||||
$this->renderInstructions($types_text),
|
||||
$this->renderTable($types_table),
|
||||
);
|
||||
}
|
||||
|
||||
protected function renderTable(AphrontTableView $table) {
|
||||
return id(new PHUIBoxView())
|
||||
->addMargin(PHUI::MARGIN_LARGE_LEFT)
|
||||
->addMargin(PHUI::MARGIN_LARGE_RIGHT)
|
||||
->addMargin(PHUI::MARGIN_LARGE_BOTTOM)
|
||||
->appendChild($table);
|
||||
}
|
||||
|
||||
protected function renderInstructions($corpus) {
|
||||
$viewer = $this->getUser();
|
||||
|
||||
return id(new PHUIBoxView())
|
||||
->addMargin(PHUI::MARGIN_SMALL_TOP)
|
||||
->addMargin(PHUI::MARGIN_SMALL_BOTTOM)
|
||||
->appendChild(new PHUIRemarkupView($viewer, $corpus));
|
||||
}
|
||||
|
||||
}
|
|
@ -155,6 +155,10 @@ th.aphront-table-view-sortable-selected {
|
|||
color: {$darkbluetext};
|
||||
}
|
||||
|
||||
.aphront-table-view td.top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.aphront-table-view td.wide {
|
||||
white-space: normal;
|
||||
width: 100%;
|
||||
|
|
Loading…
Reference in a new issue