mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Add contextual typeahead function documentation
Summary: Ref T4100. This integration into the "Browse" dialog is probably a little more heavy-handed than we should shoot for. Test Plan: {F377131} {F377132} Reviewers: btrahan, chad Reviewed By: chad Subscribers: epriestley Maniphest Tasks: T4100 Differential Revision: https://secure.phabricator.com/D12482
This commit is contained in:
parent
6193548b46
commit
bae0a85dbc
12 changed files with 292 additions and 7 deletions
|
@ -2639,6 +2639,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorTypeaheadCompositeDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadCompositeDatasource.php',
|
||||
'PhabricatorTypeaheadDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadDatasource.php',
|
||||
'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadDatasourceController.php',
|
||||
'PhabricatorTypeaheadFunctionHelpController' => 'applications/typeahead/controller/PhabricatorTypeaheadFunctionHelpController.php',
|
||||
'PhabricatorTypeaheadInvalidTokenException' => 'applications/typeahead/exception/PhabricatorTypeaheadInvalidTokenException.php',
|
||||
'PhabricatorTypeaheadModularDatasourceController' => 'applications/typeahead/controller/PhabricatorTypeaheadModularDatasourceController.php',
|
||||
'PhabricatorTypeaheadMonogramDatasource' => 'applications/typeahead/datasource/PhabricatorTypeaheadMonogramDatasource.php',
|
||||
|
@ -6054,6 +6055,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorTypeaheadCompositeDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorTypeaheadDatasource' => 'Phobject',
|
||||
'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController',
|
||||
'PhabricatorTypeaheadFunctionHelpController' => 'PhabricatorTypeaheadDatasourceController',
|
||||
'PhabricatorTypeaheadInvalidTokenException' => 'Exception',
|
||||
'PhabricatorTypeaheadModularDatasourceController' => 'PhabricatorTypeaheadDatasourceController',
|
||||
'PhabricatorTypeaheadMonogramDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
|
|
|
@ -20,7 +20,20 @@ final class ManiphestNoOwnerDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'none' => array(
|
||||
'name' => pht('Find results which are not assigned.'),
|
||||
'name' => pht('No Owner'),
|
||||
'summary' => pht('Find results which are not assigned.'),
|
||||
'description' => pht(
|
||||
'This function includes results which have no owner. Use a query '.
|
||||
'like this to find unassigned results:'.
|
||||
"\n\n".
|
||||
'> none()'.
|
||||
"\n\n".
|
||||
'If you combine this function with other functions, the query will '.
|
||||
'return results which match the other selectors //or// have no '.
|
||||
'owner. For example, this query will find results which are owned '.
|
||||
'by `alincoln`, and will also find results which have no owner:'.
|
||||
"\n\n".
|
||||
'> alincoln, none()'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,10 +24,54 @@ final class PhabricatorProjectLogicalOrNotDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'any' => array(
|
||||
'name' => pht('Find results in any of several projects.'),
|
||||
'name' => pht('In Any: ...'),
|
||||
'arguments' => pht('project'),
|
||||
'summary' => pht('Find results in any of several projects.'),
|
||||
'description' => pht(
|
||||
'This function allows you to find results in one of several '.
|
||||
'projects. Another way to think of this function is that it '.
|
||||
'allows you to perform an "or" query.'.
|
||||
"\n\n".
|
||||
'By default, if you enter several projects, results are returned '.
|
||||
'only if they belong to all of the projects you enter. That is, '.
|
||||
'this query will only return results in //both// projects:'.
|
||||
"\n\n".
|
||||
'> ios, android'.
|
||||
"\n\n".
|
||||
'If you want to find results in any of several projects, you can '.
|
||||
'use the `any()` function. For example, you can use this query to '.
|
||||
'find results which are in //either// project:'.
|
||||
"\n\n".
|
||||
'> any(ios), any(android)'.
|
||||
"\n\n".
|
||||
'You can combine the `any()` function with normal project tokens '.
|
||||
'to refine results. For example, use this query to find bugs in '.
|
||||
'//either// iOS or Android:'.
|
||||
"\n\n".
|
||||
'> bug, any(ios), any(android)'),
|
||||
),
|
||||
'not' => array(
|
||||
'name' => pht('Find results not in specific projects.'),
|
||||
'name' => pht('Not In: ...'),
|
||||
'arguments' => pht('project'),
|
||||
'summary' => pht('Find results not in specific projects.'),
|
||||
'description' => pht(
|
||||
'This function allows you to find results which are not in '.
|
||||
'one or more projects. For example, use this query to find '.
|
||||
'results which are not associated with a specific project:'.
|
||||
"\n\n".
|
||||
'> not(vanilla)'.
|
||||
"\n\n".
|
||||
'You can exclude multiple projects. This will cause the query '.
|
||||
'to return only results which are not in any of the excluded '.
|
||||
'projects:'.
|
||||
"\n\n".
|
||||
'> not(vanilla), not(chocolate)'.
|
||||
"\n\n".
|
||||
'You can combine this function with other functions to refine '.
|
||||
'results. For example, use this query to find iOS results which '.
|
||||
'are not bugs:'.
|
||||
"\n\n".
|
||||
'> ios, not(bug)'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,17 @@ final class PhabricatorProjectLogicalUserDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'projects' => array(
|
||||
'name' => pht("Find results in any of a user's projects."),
|
||||
'name' => pht('Projects: ...'),
|
||||
'arguments' => pht('username'),
|
||||
'summary' => pht("Find results in any of a user's projects."),
|
||||
'description' => pht(
|
||||
'This function allows you to find results associated with any '.
|
||||
'of the projects a specified user is a member of. For example, '.
|
||||
'this will find results associated with all of the projects '.
|
||||
'`alincoln` is a member of:'.
|
||||
"\n\n".
|
||||
'> projects(alincoln)'.
|
||||
"\n\n"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,19 @@ final class PhabricatorProjectLogicalViewerDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'viewerprojects' => array(
|
||||
'name' => pht("Find results in any of the current viewer's projects."),
|
||||
'name' => pht("Current Viewer's Projects"),
|
||||
'summary' => pht(
|
||||
"Find results in any of the current viewer's projects."),
|
||||
'description' => pht(
|
||||
"This function matches results in any of the current viewing ".
|
||||
"user's projects:".
|
||||
"\n\n".
|
||||
"> viewerprojects()".
|
||||
"\n\n".
|
||||
"This normally means //your// projects, but if you save a query ".
|
||||
"using this function and send it to someone else, it will mean ".
|
||||
"//their// projects when they run it (they become the currnet ".
|
||||
"viewer). This can be useful for building dashboard panels."),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,14 @@ final class PhabricatorProjectMembersDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'members' => array(
|
||||
'name' => pht('Find results for members of a project.'),
|
||||
'name' => pht('Members: ...'),
|
||||
'arguments' => pht('project'),
|
||||
'summary' => pht('Find results for members of a project.'),
|
||||
'description' => pht(
|
||||
'This function allows you to find results for any of the members '.
|
||||
'of a project:'.
|
||||
"\n\n".
|
||||
'> members(frontend)'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,15 @@ final class PhabricatorProjectNoProjectsDatasource
|
|||
public function getDatasourceFunctions() {
|
||||
return array(
|
||||
'null' => array(
|
||||
'name' => pht('Find results which are not in any projects.'),
|
||||
'name' => pht('Not In Any Projects'),
|
||||
'summary' => pht('Find results which are not in any projects.'),
|
||||
'description' => pht(
|
||||
'This function matches results which are not associated with any '.
|
||||
'projects. It is usually most often used to find objects which '.
|
||||
'might have slipped through the cracks and not been organized '.
|
||||
'properly.'.
|
||||
"\n\n".
|
||||
"> null()"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ final class PhabricatorTypeaheadApplication extends PhabricatorApplication {
|
|||
'/typeahead/' => array(
|
||||
'(?P<action>browse|class)/(?:(?P<class>\w+)/)?'
|
||||
=> 'PhabricatorTypeaheadModularDatasourceController',
|
||||
'help/(?P<class>\w+)/'
|
||||
=> 'PhabricatorTypeaheadFunctionHelpController',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorTypeaheadFunctionHelpController
|
||||
extends PhabricatorTypeaheadDatasourceController {
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $this->getViewer();
|
||||
$class = $request->getURIData('class');
|
||||
|
||||
$sources = id(new PhutilSymbolLoader())
|
||||
->setAncestorClass('PhabricatorTypeaheadDatasource')
|
||||
->loadObjects();
|
||||
if (!isset($sources[$class])) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$source = $sources[$class];
|
||||
|
||||
$application_class = $source->getDatasourceApplicationClass();
|
||||
if ($application_class) {
|
||||
$result = id(new PhabricatorApplicationQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withClasses(array($application_class))
|
||||
->execute();
|
||||
if (!$result) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
}
|
||||
|
||||
$source->setViewer($viewer);
|
||||
|
||||
$title = pht('Typeahead Function Help');
|
||||
|
||||
$functions = $source->getAllDatasourceFunctions();
|
||||
ksort($functions);
|
||||
|
||||
$content = array();
|
||||
|
||||
$content[] = '= '.pht('Overview');
|
||||
$content[] = pht(
|
||||
'Typeahead functions are an advanced feature which allow you to build '.
|
||||
'more powerful queries. This document explains functions available '.
|
||||
'for the selected control.'.
|
||||
"\n\n".
|
||||
'Note that different controls support //different// functions '.
|
||||
'(depending on what the control is doing), so these specific functions '.
|
||||
'may not work everywhere. You can always check the help for a control '.
|
||||
'to review which functions are available for that control.');
|
||||
|
||||
$table = array();
|
||||
|
||||
$table_header = array(
|
||||
pht('Function'),
|
||||
pht('Token Name'),
|
||||
pht('Summary'),
|
||||
);
|
||||
$table[] = '| '.implode(' | ', $table_header).' |';
|
||||
$table[] = '|---|---|---|';
|
||||
|
||||
foreach ($functions as $function => $spec) {
|
||||
$spec = $spec + array(
|
||||
'summary' => null,
|
||||
'arguments' => null,
|
||||
);
|
||||
|
||||
if (idx($spec, 'arguments')) {
|
||||
$signature = '**'.$function.'(**//'.$spec['arguments'].'//**)**';
|
||||
} else {
|
||||
$signature = '**'.$function.'()**';
|
||||
}
|
||||
|
||||
$name = idx($spec, 'name', '');
|
||||
$summary = idx($spec, 'summary', '');
|
||||
|
||||
$table[] = '| '.$signature.' | '.$name.' | '.$summary.' |';
|
||||
}
|
||||
|
||||
$table = implode("\n", $table);
|
||||
$content[] = '= '.pht('Function Quick Reference');
|
||||
$content[] = pht(
|
||||
'This table briefly describes available functions for this control. '.
|
||||
'For details on a particular function, see the corresponding section '.
|
||||
'below.');
|
||||
$content[] = $table;
|
||||
|
||||
$content[] = '= '.pht('Using Typeahead Functions');
|
||||
$content[] = pht(
|
||||
'In addition to typing user and project names to build queries, you can '.
|
||||
'also type the names of special functions which give you more options '.
|
||||
'and the ability to express more complex queries.'.
|
||||
"\n\n".
|
||||
'Functions have an internal name (like `viewer()`) and a '.
|
||||
'human-readable name, like `Current Viewer`. In general, you can type '.
|
||||
'either one to select the function. You can also click the '.
|
||||
'{nav icon=search} button on any typeahead control to browse available '.
|
||||
'functions and find this documentation.'.
|
||||
"\n\n".
|
||||
'This documentation uses the internal names to make it clear where '.
|
||||
'tokens begin and end. Specifically, you will find queries written '.
|
||||
'out like this in the documentation: '.
|
||||
"\n\n".
|
||||
'> viewer(), alincoln'.
|
||||
"\n\n".
|
||||
'When this query is actually shown in the control, it will look more '.
|
||||
'like this:'.
|
||||
"\n\n".
|
||||
'> {nav Current Viewer} {nav alincoln (Abraham Lincoln)}');
|
||||
|
||||
|
||||
$middot = "\xC2\xB7";
|
||||
foreach ($functions as $function => $spec) {
|
||||
$arguments = idx($spec, 'arguments', '');
|
||||
$name = idx($spec, 'name');
|
||||
$content[] = '= '.$function.'('.$arguments.') '.$middot.' '.$name;
|
||||
$content[] = $spec['description'];
|
||||
}
|
||||
|
||||
$content = implode("\n\n", $content);
|
||||
|
||||
$content_box = PhabricatorMarkupEngine::renderOneObject(
|
||||
id(new PhabricatorMarkupOneOff())->setContent($content),
|
||||
'default',
|
||||
$viewer);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader($title);
|
||||
|
||||
$document = id(new PHUIDocumentView())
|
||||
->setHeader($header)
|
||||
->setFontKit(PHUIDocumentView::FONT_SOURCE_SANS)
|
||||
->appendChild($content_box);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(pht('Function Help'));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$document,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
|
@ -222,11 +222,32 @@ final class PhabricatorTypeaheadModularDatasourceController
|
|||
$frame,
|
||||
);
|
||||
|
||||
$function_help = null;
|
||||
if ($source->getAllDatasourceFunctions()) {
|
||||
$reference_uri = '/typeahead/help/'.get_class($source).'/';
|
||||
|
||||
$reference_link = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $reference_uri,
|
||||
'target' => '_blank',
|
||||
),
|
||||
pht('Reference: Advanced Functions'));
|
||||
|
||||
$function_help = array(
|
||||
id(new PHUIIconView())
|
||||
->setIconFont('fa-book'),
|
||||
' ',
|
||||
$reference_link,
|
||||
);
|
||||
}
|
||||
|
||||
return $this->newDialog()
|
||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||
->setRenderDialogAsDiv(true)
|
||||
->setTitle($source->getBrowseTitle())
|
||||
->appendChild($browser)
|
||||
->addFooter($function_help)
|
||||
->addCancelButton('/', pht('Close'));
|
||||
}
|
||||
|
||||
|
|
|
@ -117,6 +117,14 @@ abstract class PhabricatorTypeaheadCompositeDatasource
|
|||
return $this->usable;
|
||||
}
|
||||
|
||||
public function getAllDatasourceFunctions() {
|
||||
$results = parent::getAllDatasourceFunctions();
|
||||
foreach ($this->getUsableDatasources() as $source) {
|
||||
$results += $source->getAllDatasourceFunctions();
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function didEvaluateTokens(array $results) {
|
||||
foreach ($this->getUsableDatasources() as $source) {
|
||||
$results = $source->didEvaluateTokens($results);
|
||||
|
|
|
@ -276,6 +276,14 @@ abstract class PhabricatorTypeaheadDatasource extends Phobject {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task functions
|
||||
*/
|
||||
public function getAllDatasourceFunctions() {
|
||||
return $this->getDatasourceFunctions();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @task functions
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue