gerrit/Documentation/pg-plugin-dev.txt
Viktar Donich 8b3455518a Support for GWT to PolyGerrit integration plugin migration
Detect migration scenario based on UI script files to have same name and
different extensions (.html and .js).

Allow for multiple `Gerrit.install()` calls, reusing `plugin` instance
for purposes of migration.

Cleanup plugin interface between tests.

Change-Id: I1a98a2b8660ce4a1700766dc722d587817ede884
2018-01-10 23:41:23 +00:00

252 lines
5.6 KiB
Plaintext

= Gerrit Code Review - PolyGerrit Plugin Development
CAUTION: Work in progress. Hard hat area. Please
link:https://bugs.chromium.org/p/gerrit/issues/entry?template=PolyGerrit%20plugins[send
feedback] if something's not right.
For migrating existing GWT UI plugins, please check out the
link:pg-plugin-migration.html#migration[migration guide].
[[loading]]
== Plugin loading and initialization
link:js-api.html#_entry_point[Entry point] for the plugin and the loading method
is based on link:http://w3c.github.io/webcomponents/spec/imports/[HTML Imports]
spec.
* The plugin provides pluginname.html, and can be a standalone file or a static
asset in a jar as a link:dev-plugins.html#deployment[Web UI plugin].
* pluginname.html contains a `dom-module` tag with a script that uses
`Gerrit.install()`. There should only be single `Gerrit.install()` per file.
* PolyGerrit imports pluginname.html along with all required resources defined in it
(fonts, styles, etc).
* For standalone plugins, the entry point file is a `pluginname.html` file
located in `gerrit-site/plugins` folder, where `pluginname` is an alphanumeric
plugin name.
Note: Code examples target modern brosers (Chrome, Firefox, Safari, Edge)
Here's a recommended starter `myplugin.html`:
``` html
<dom-module id="my-plugin">
<script>
Gerrit.install(plugin => {
'use strict';
// Your code here.
});
</script>
</dom-module>
```
[[low-level-api-concepts]]
== Low-level DOM API concepts
Basically, the DOM is the API surface. Low-level API provides methods for
decorating, replacing, and styling DOM elements exposed through a set of
endpoints.
PolyGerrit provides a simple way for accessing the DOM via DOM hooks API. A DOM
hook is a custom element that is instantiated for the plugin endpoint. In the
decoration case, a hook is set with a `content` attribute that points to the DOM
element.
1. Get the DOM hook API instance via `plugin.hook(endpointName)`
2. Set up an `onAttached` callback
3. Callback is called when the hook element is created and inserted into DOM
4. Use element.content to get UI element
``` js
Gerrit.install(plugin => {
const domHook = plugin.hook('reply-text');
domHook.onAttached(element => {
if (!element.content) { return; }
// element.content is a reply dialog text area.
});
});
```
[[low-level-decorating]]
=== Decorating DOM Elements
For each endpoint, PolyGerrit provides a list of DOM properties (such as
attributes and events) that are supported in the long-term.
NOTE: TODO: Insert link to the full endpoints API.
``` js
Gerrit.install(plugin => {
const domHook = plugin.hook('reply-text');
domHook.onAttached(element => {
if (!element.content) { return; }
element.content.style.border = '1px red dashed';
});
});
```
[[low-level-replacing]]
=== Replacing DOM Elements
An endpoint's contents can be replaced by passing the replace attribute as an
option.
``` js
Gerrit.install(plugin => {
const domHook = plugin.hook('header-title', {replace: true});
domHook.onAttached(element => {
element.appendChild(document.createElement('my-site-header'));
});
});
```
[[low-level-style]]
=== Styling DOM Elements
A plugin may provide Polymer's
https://www.polymer-project.org/2.0/docs/devguide/style-shadow-dom#style-modules[style
modules] to style individual endpoints using
`plugin.registerStyleModule(endpointName, moduleName)`. A style must be defined
as a standalone `<dom-module>` defined in the same .html file.
Note: TODO: Insert link to the full styling API.
``` html
<dom-module id="my-plugin">
<script>
Gerrit.install(plugin => {
plugin.registerStyleModule('change-metadata', 'some-style-module');
});
</script>
</dom-module>
<dom-module id="some-style-module">
<style>
html {
--change-metadata-label-status: {
display: none;
}
--change-metadata-strategy: {
display: none;
}
}
</style>
</dom-module>
```
[[high-level-api-concepts]]
== High-level DOM API concepts
High leve API is based on low-level DOM API and is essentially a standartized
way for doing common tasks. It's less flexible, but will be a bit more stable.
Common way to access high-leve API is through `plugin` instance passed into
setup callback parameter of `Gerrit.install()`, also sometimes referred as
`self`.
[[low-level-api]]
== Low-level DOM API
Low-level DOM API methods are the base of all UI customization.
=== attributeHelper
`plugin.attributeHelper(element)`
Note: TODO
=== eventHelper
`plugin.eventHelper(element)`
Note: TODO
=== hook
`plugin.hook(endpointName, opt_options)`
Note: TODO
=== registerCustomComponent
`plugin.registerCustomComponent(endpointName, opt_moduleName, opt_options)`
Note: TODO
=== registerStyleModule
`plugin.registerStyleModule(endpointName, moduleName)`
Note: TODO
[[high-level-api]]
== High-level API
Plugin instance provides access to number of more specific APIs and methods
to be used by plugin authors.
=== changeReply
`plugin.changeReply()`
Note: TODO
=== changeView
`plugin.changeView()`
Note: TODO
=== delete
`plugin.delete(url, opt_callback)`
Note: TODO
=== get
`plugin.get(url, opt_callback)`
Note: TODO
=== getPluginName
`plugin.getPluginName()`
Note: TODO
=== getServerInfo
`plugin.getServerInfo()`
Note: TODO
=== on
`plugin.on(eventName, callback)`
Note: TODO
=== popup
`plugin.popup(moduleName)`
Note: TODO
=== post
`plugin.post(url, payload, opt_callback)`
Note: TODO
[plugin-project]
=== project
`plugin.project()`
.Params:
- none
.Returns:
- Instance of link:pg-plugin-project-api.html[GrProjectApi].
=== put
`plugin.put(url, payload, opt_callback)`
Note: TODO
=== theme
`plugin.theme()`
Note: TODO
=== url
`plugin.url(opt_path)`
Note: TODO