Document UI Extension feature

Change-Id: I12877b51c81bc473a0590e51c3d2be609ba7edfc
This commit is contained in:
David Ostrovsky
2013-09-01 09:10:39 +02:00
committed by David Pursehouse
parent be31cd4ea5
commit f86bae579d

View File

@@ -328,7 +328,7 @@ abstract class:
}
====
If no Guice modules are declared in the manifest, UI commands may
If no Guice modules are declared in the manifest, UI actions may
use auto-registration by providing an `@Export` annotation:
====
@@ -351,7 +351,7 @@ Otherwise the capability must be bound in a plugin module:
====
With a plugin-owned capability defined in this way, it is possible to restrict
usage of an SSH command or UiAction to members of the group that were granted
usage of an SSH command or `UiAction` to members of the group that were granted
this capability in the usual way, using the `RequiresCapability` annotation:
====
@@ -361,7 +361,7 @@ this capability in the usual way, using the `RequiresCapability` annotation:
...
====
Or with UiAction:
Or with `UiAction`:
====
@RequiresCapability("printHello")
@@ -390,6 +390,186 @@ this can be specified by setting `scope = CapabilityScope.CORE`:
...
====
[[ui_extension]]
UI Extension
------------
Plugins can contribute their own UI commands on core Gerrit pages.
This is useful for workflow customization or exposing plugin functionality
through the UI in addition to SSH commands and the REST API.
For instance a plugin to integrate Jira with Gerrit changes may contribute its
own "File bug" button to allow filing a bug from the change page or plugins to
integrate continuous integration systems may contribute a "Schedule" button to
allow a CI build to be scheduled manually from the patch set panel.
Two different places on core Gerrit pages are currently supported:
* Change screen
* Project info screen
Plugins contribute UI actions by implementing the `UiAction` interface:
====
@RequiresCapability("printHello")
class HelloWorldAction implements UiAction<RevisionResource>,
RestModifyView<RevisionResource, HelloWorldAction.Input> {
static class Input {
boolean french;
String message;
}
private Provider<CurrentUser> cu;
@Inject
HelloWorldAction(Provider<CurrentUser> user) {
this.user = user;
}
@Override
public String apply(RevisionResource rev, Input input) {
final String greeting = input.french
? "Bonjour"
: "Hello";
return String.format("%s %s from change %s, patch set %d!",
greeting,
Strings.isNullOrEmpty(input.message)
? Objects.firstNonNull(user.get().getUserName(), "world")
: input.message,
rev.getChange().getId().toString(),
rev.getPatchSet().getPatchSetId());
}
@Override
public Description getDescription(
RevisionResource resource) {
return new Description()
.setLabel("Say hello")
.setTitle("Say hello in different languages");
}
}
====
`UiAction` must be bound in a plugin module:
====
public class Module extends AbstractModule {
@Override
protected void configure() {
install(new RestApiModule() {
@Override
protected void configure() {
post(REVISION_KIND, "say-hello")
.to(HelloWorldAction.class);
}
});
}
}
====
The module above must be declared in pom.xml for Maven driven plugins:
====
<manifestEntries>
<Gerrit-Module>com.googlesource.gerrit.plugins.cookbook.Module</Gerrit-Module>
</manifestEntries>
====
or in the BUCK configuration file for Buck driven plugins:
====
manifest_entries = [
'Gerrit-Module: com.googlesource.gerrit.plugins.cookbook.Module',
]
====
In some use cases more user input must be gathered, for that `UiAction` can be
combined with the JavaScript API. This would display a small popup near the
activation button to gather additional input from the user. The JS file is
typically put in the `static` folder within the plugin's directory:
====
Gerrit.install(function(self) {
function onSayHello(c) {
var f = c.textfield();
var t = c.checkbox();
var b = c.button('Say hello', {onclick: function(){
c.call(
{message: f.value, french: t.checked},
function(r) {
c.hide();
window.alert(r);
c.refresh();
});
}});
c.popup(c.div(
c.prependLabel('Greeting message', f),
c.br(),
c.label(t, 'french'),
c.br(),
b));
f.focus();
}
self.onAction('revision', 'say-hello', onSayHello);
});
====
The JS module must be exposed as a `WebUiPlugin` and bound as
an HTTP Module:
====
public class HttpModule extends HttpPluginModule {
@Override
protected void configureServlets() {
DynamicSet.bind(binder(), WebUiPlugin.class)
.toInstance(new JavaScriptPlugin("hello.js"));
}
}
====
The HTTP module above must be declared in pom.xml for Maven driven plugins:
====
<manifestEntries>
<Gerrit-HttpModule>com.googlesource.gerrit.plugins.cookbook.HttpModule</Gerrit-HttpModule>
</manifestEntries>
====
or in the BUCK configuration file for Buck driven plugins
====
manifest_entries = [
'Gerrit-HttpModule: com.googlesource.gerrit.plugins.cookbook.HttpModule',
]
====
If `UiAction` is annotated with the `@RequiresCapability` annotation, then the
capability check is done during the `UiAction` gathering, so the plugin author
doesn't have to set `UiAction.Description.setVisible()` explicitly in this
case.
The following prerequisities must be met, to satisfy the capability check:
* user is authenticated
* user is a member of the Administrators group, or
* user is a member of a group which has the required capability
The `apply` method is called when the button is clicked. If `UiAction` is
combined with JavaScript API (its own JavaScript function is provided),
then a popup dialog is normally opened to gather additional user input.
A new button is placed on the popup dialog to actually send the request.
Every `UiAction` exposes a REST API endpoint. The endpoint from the example above
can be accessed from any REST client, i. e.:
====
curl -X POST -H "Content-Type: application/json" \
-d '{message: "François", french: true}' \
--digest --user joe:secret \
http://host:port/a/changes/1/revisions/1/cookbook~say-hello
"Bonjour François from change 1, patch set 1!"
====
[[http]]
HTTP Servlets
-------------
@@ -573,6 +753,12 @@ command can be used.
Disabled plugins can be re-enabled using the
link:cmd-plugin-enable.html[plugin enable] command.
SEE ALSO
--------
* link:js-api.html[JavaScript API]
* link:dev-rest-api.html[REST API Developers' Notes]
GERRIT
------
Part of link:index.html[Gerrit Code Review]