From 3dec4c7dbdd2c734d5e713a9a1c59e3af4570ac9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 3 Nov 2015 05:38:06 -0800 Subject: [PATCH] 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 --- resources/celerity/map.php | 6 +- src/__phutil_library_map__.php | 2 + .../base/PhabricatorApplication.php | 4 + .../PhabricatorPasteApplication.php | 2 +- .../PhabricatorPasteListController.php | 2 +- .../editor/PhabricatorPasteEditEngine.php | 8 + .../PhabricatorApplicationEditEngine.php | 169 ++++++++- .../editfield/PhabricatorEditField.php | 14 + .../editfield/PhabricatorPolicyEditField.php | 4 + .../editfield/PhabricatorSelectEditField.php | 4 + .../editfield/PhabricatorSpaceEditField.php | 4 + .../PhabricatorTokenizerEditField.php | 4 + ...orApplicationEditHTTPParameterHelpView.php | 336 ++++++++++++++++++ webroot/rsrc/css/aphront/table-view.css | 4 + 14 files changed, 545 insertions(+), 18 deletions(-) create mode 100644 src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php diff --git a/resources/celerity/map.php b/resources/celerity/map.php index 2046d254c6..5a4bb90111 100644 --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -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', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index de98b8f92b..6f4c7254d0 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index f499bea5c9..080062a2d9 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -635,4 +635,8 @@ abstract class PhabricatorApplication return array(); } + protected function getEditRoutePattern($base) { + return $base.'(?:(?P[0-9]\d*)/)?(?:(?Pparameters)/)?'; + } + } diff --git a/src/applications/paste/application/PhabricatorPasteApplication.php b/src/applications/paste/application/PhabricatorPasteApplication.php index 7fe3ec41e7..e066d4cd9d 100644 --- a/src/applications/paste/application/PhabricatorPasteApplication.php +++ b/src/applications/paste/application/PhabricatorPasteApplication.php @@ -39,7 +39,7 @@ final class PhabricatorPasteApplication extends PhabricatorApplication { '/paste/' => array( '(query/(?P[^/]+)/)?' => 'PhabricatorPasteListController', 'create/' => 'PhabricatorPasteEditController', - 'edit/(?P[1-9]\d*)/' => 'PhabricatorPasteEditController', + $this->getEditRoutePattern('edit/') => 'PhabricatorPasteEditController', 'raw/(?P[1-9]\d*)/' => 'PhabricatorPasteRawController', 'comment/(?P[1-9]\d*)/' => 'PhabricatorPasteCommentController', ), diff --git a/src/applications/paste/controller/PhabricatorPasteListController.php b/src/applications/paste/controller/PhabricatorPasteListController.php index 4c3d9b3b06..e867b4e773 100644 --- a/src/applications/paste/controller/PhabricatorPasteListController.php +++ b/src/applications/paste/controller/PhabricatorPasteListController.php @@ -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; diff --git a/src/applications/paste/editor/PhabricatorPasteEditEngine.php b/src/applications/paste/editor/PhabricatorPasteEditEngine.php index 98f7399381..b92042f93f 100644 --- a/src/applications/paste/editor/PhabricatorPasteEditEngine.php +++ b/src/applications/paste/editor/PhabricatorPasteEditEngine.php @@ -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) diff --git a/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php b/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php index 4115a508ec..c5547a01e8 100644 --- a/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php +++ b/src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php @@ -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; + } } diff --git a/src/applications/transactions/editfield/PhabricatorEditField.php b/src/applications/transactions/editfield/PhabricatorEditField.php index 127fa2e0a5..fcbd496390 100644 --- a/src/applications/transactions/editfield/PhabricatorEditField.php +++ b/src/applications/transactions/editfield/PhabricatorEditField.php @@ -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'; + } + } diff --git a/src/applications/transactions/editfield/PhabricatorPolicyEditField.php b/src/applications/transactions/editfield/PhabricatorPolicyEditField.php index 26c606e307..beb3b9b770 100644 --- a/src/applications/transactions/editfield/PhabricatorPolicyEditField.php +++ b/src/applications/transactions/editfield/PhabricatorPolicyEditField.php @@ -51,4 +51,8 @@ final class PhabricatorPolicyEditField return $control; } + public function getHTTPParameterType() { + return 'phid'; + } + } diff --git a/src/applications/transactions/editfield/PhabricatorSelectEditField.php b/src/applications/transactions/editfield/PhabricatorSelectEditField.php index 496d95c7c4..f954acc9ae 100644 --- a/src/applications/transactions/editfield/PhabricatorSelectEditField.php +++ b/src/applications/transactions/editfield/PhabricatorSelectEditField.php @@ -22,4 +22,8 @@ final class PhabricatorSelectEditField ->setOptions($this->getOptions()); } + public function getHTTPParameterType() { + return 'select'; + } + } diff --git a/src/applications/transactions/editfield/PhabricatorSpaceEditField.php b/src/applications/transactions/editfield/PhabricatorSpaceEditField.php index d01350ee5f..4ac4a250b7 100644 --- a/src/applications/transactions/editfield/PhabricatorSpaceEditField.php +++ b/src/applications/transactions/editfield/PhabricatorSpaceEditField.php @@ -9,4 +9,8 @@ final class PhabricatorSpaceEditField return null; } + public function getHTTPParameterType() { + return 'phid'; + } + } diff --git a/src/applications/transactions/editfield/PhabricatorTokenizerEditField.php b/src/applications/transactions/editfield/PhabricatorTokenizerEditField.php index 98a131787c..1a8c1fd751 100644 --- a/src/applications/transactions/editfield/PhabricatorTokenizerEditField.php +++ b/src/applications/transactions/editfield/PhabricatorTokenizerEditField.php @@ -87,4 +87,8 @@ abstract class PhabricatorTokenizerEditField return $new; } + public function getHTTPParameterType() { + return 'list'; + } + } diff --git a/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php new file mode 100644 index 0000000000..9a085174ec --- /dev/null +++ b/src/applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php @@ -0,0 +1,336 @@ +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(<<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(<<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(<<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('')); + } + + $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(<< 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' => 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)); + } + +} diff --git a/webroot/rsrc/css/aphront/table-view.css b/webroot/rsrc/css/aphront/table-view.css index 254599625f..b235fd9c47 100644 --- a/webroot/rsrc/css/aphront/table-view.css +++ b/webroot/rsrc/css/aphront/table-view.css @@ -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%;