92a1fa89f247ceed3ec88a040d15e442a3f67670

This is the first step in building a public JavaScript API that can be utilized by plugins to manage interaction with the web UI. This commit makes the following plugin JavaScript possible: Gerrit.install(function(self) { function onCallMe(c) { var f = c.textfield(); var t = c.checkbox(); var b = c.button('Phone', {onclick: function(){ c.call( {message: f.value, dial: t.checked}, function(r) { c.hide(); window.alert("Said " + r); c.refresh(); }); }}); c.popup(c.div( f, c.br(), c.label(t, 'Dial'), c.br(), b)); f.focus(); } self.onAction('revision', 'callme', onCallMe); }); JavaScript plugins are encouraged to protect the global namespace by running Gerrit.install(f), passing an anonymous function Gerrit can call to initialize the plugin. Gerrit.install() performs some black magic to identify which plugin the JavaScript is running from, exporting as Gerrit.getPluginName(). Obtaining the name is faster within the install() invocation as the string is cached in a global variable. A plugin's install function is given a reference to the plugin JavaScript object. This object has many helper methods to support communication with the server. Gerrit.onAction() accepts the type of view and the RestView name as defined in the plugin and a JavaScript function to execute when the user has activated the action button. An action callback is given a context object declaring a number of useful properties: change: The ChangeInfo object. revision: The RevisionInfo object. action: The ActionInfo object that invoked this callback. popup(e): Display a popup containing element e. hide(): Hide the popup that was created by popup. call(in,cb): Executes the RPC using action.method. get(cb): Executes the RPC using GET. post(in,cb): Executes the RPC using POST. put(in,cb): Executes the RPC using PUT. delete(cb): Executes the RPC using DELETE. HTML: br, hr, button, checkbox, div, label, span, textfield These make it easier to construct a tiny UI for use in a popup, such as gathering a small amount if input from the user to supply to the RPC. go(token): Navigate the web UI to the application URL. refresh(): Redisplay the current web UI view. Any result data from the server is parsed as JSON and passed as-is to the callback function. A JSON string result is given as a string, a JSON object or array is passed as-is. A corresponding REST API view on revisions can be declared: class Module extends RestApiModule { @Override protected void configure() { post(RevisionResource.REVISION_KIND, "callme").to(CallMe.class); } } class CallMe implements RestModifyView<RevisionResource, CallMe.Input>, UiAction<RevisionResource> { static class Input { String message; } @Override public String apply(RevisionResource resource, Input input) { return "You said: " + input.message; } @Override public UiAction.Description getDescription(RevisionResource resource) { return new UiAction.Description().setLabel("Call Me"); } } Currently the JavaScript code must be registered at the server side to appear in the host page download: class Web extends AbstractModule { @Override protected void configure() { DynamicSet.bind(binder(), WebUiPlugin.class) .toInstance(new JavaScriptPlugin("maybe.js")); } I find this binding method for JavaScript code is awkard and would like to improve on it in the future. Finally both modules must be registered in the plugin manifest: gerrit_plugin( name = 'actiondemo', srcs = glob(['src/main/java/**/*.java']), resources = glob(['src/main/resources/**/*']), manifest_entries = [ "Gerrit-Module: com.googlesource.gerrit.plugins.actiondemo.Module", "Gerrit-HttpModule: com.googlesource.gerrit.plugins.actiondemo.Web", ], ) Change-Id: I2d572279ac978e644772b1cedbecc080746a2306
Description
RETIRED, Gerrit as used by OpenStack