Document UI Extension feature
Change-Id: I12877b51c81bc473a0590e51c3d2be609ba7edfc
This commit is contained in:
committed by
David Pursehouse
parent
be31cd4ea5
commit
f86bae579d
@@ -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:
|
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
|
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:
|
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")
|
@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]]
|
||||||
HTTP Servlets
|
HTTP Servlets
|
||||||
-------------
|
-------------
|
||||||
@@ -573,6 +753,12 @@ command can be used.
|
|||||||
Disabled plugins can be re-enabled using the
|
Disabled plugins can be re-enabled using the
|
||||||
link:cmd-plugin-enable.html[plugin enable] command.
|
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
|
GERRIT
|
||||||
------
|
------
|
||||||
Part of link:index.html[Gerrit Code Review]
|
Part of link:index.html[Gerrit Code Review]
|
||||||
|
|||||||
Reference in New Issue
Block a user