* stable-2.15: PolyGerrit: Update documentation Support for GWT to PolyGerrit integration plugin migration Update the plugin development documentation. Update PolyGerrit plugin documentation Change-Id: I6b80221d85d3c045f935e8d2accfc23519293c70
		
			
				
	
	
		
			153 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			153 lines
		
	
	
		
			4.9 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.
 | 
						|
 | 
						|
[[migration]]
 | 
						|
== Incremental migration of existing GWT UI plugins
 | 
						|
 | 
						|
link:pg-plugin-dev.html[PolyGerrit plugin API] is based on different concepts and
 | 
						|
provides a different type of API compared to the one available to GWT
 | 
						|
plugins. Depending on the plugin, it might require significant modifications to
 | 
						|
existing UI scripts to fully take advantage of the benefits provided by the PolyGerrit API.
 | 
						|
 | 
						|
To make migration easier, PolyGerrit recommends an incremental migration
 | 
						|
strategy. Starting with a .js file that works for GWT UI, plugin author can
 | 
						|
incrementally migrate deprecated APIs to the new plugin API.
 | 
						|
 | 
						|
The goal for this guide is to provide a migration path from .js-based UI script to
 | 
						|
a html based implementation
 | 
						|
 | 
						|
NOTE: Web UI plugins distributed as a single .js file are not covered in this
 | 
						|
guide.
 | 
						|
 | 
						|
Let's start with a basic plugin that has an UI module. Commonly, file tree
 | 
						|
should look like this:
 | 
						|
 | 
						|
  ├── BUILD
 | 
						|
  ├── LICENSE
 | 
						|
  └── src
 | 
						|
      └── main
 | 
						|
          ├── java
 | 
						|
          │   └── com
 | 
						|
          │       └── foo
 | 
						|
          │           └── SamplePluginModule.java
 | 
						|
          └── resources
 | 
						|
              └── static
 | 
						|
                  └── sampleplugin.js
 | 
						|
 | 
						|
For simplicity's sake, let's assume SamplePluginModule.java has following
 | 
						|
content:
 | 
						|
 | 
						|
``` java
 | 
						|
public class SamplePluginModule extends AbstractModule {
 | 
						|
 | 
						|
  @Override
 | 
						|
  protected void configure() {
 | 
						|
    DynamicSet.bind(binder(), WebUiPlugin.class)
 | 
						|
        .toInstance(new JavaScriptPlugin("sampleplugin.js"));
 | 
						|
  }
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
=== Step 1: Create `sampleplugin.html`
 | 
						|
 | 
						|
As a first step, create `sampleplugin.html` and include the UI script in the
 | 
						|
module file.
 | 
						|
 | 
						|
NOTE: GWT UI ignores html files which it doesn't support.
 | 
						|
 | 
						|
``` java
 | 
						|
  @Override
 | 
						|
  protected void configure() {
 | 
						|
    DynamicSet.bind(binder(), WebUiPlugin.class)
 | 
						|
        .toInstance(new JavaScriptPlugin("sampleplugin.js"));
 | 
						|
    DynamicSet.bind(binder(), WebUiPlugin.class)
 | 
						|
        .toInstance(new JavaScriptPlugin("sampleplugin.html"));
 | 
						|
  }
 | 
						|
```
 | 
						|
 | 
						|
Here's recommended starter code for `sampleplugin.html`:
 | 
						|
 | 
						|
NOTE: By specification, the `id` attribute of `dom-module` *must* contain a dash
 | 
						|
(-).
 | 
						|
 | 
						|
``` html
 | 
						|
<dom-module id="sample-plugin">
 | 
						|
  <script>
 | 
						|
    Gerrit.install(plugin => {
 | 
						|
        // Setup block, is executed before sampleplugin.js
 | 
						|
 | 
						|
        // Install deprecated JS APIs (onAction, popup, etc)
 | 
						|
        plugin.deprecated.install();
 | 
						|
    });
 | 
						|
  </script>
 | 
						|
 | 
						|
  <script src="./sampleplugin.js"></script>
 | 
						|
 | 
						|
  <script>
 | 
						|
    Gerrit.install(plugin => {
 | 
						|
        // Cleanup block, is executed after sampleplugin.js
 | 
						|
    });
 | 
						|
  </script>
 | 
						|
</dom-module>
 | 
						|
```
 | 
						|
 | 
						|
Here's how this works:
 | 
						|
 | 
						|
- PolyGerrit detects migration scenario because UI scripts have same filename
 | 
						|
and different extensions
 | 
						|
 * PolyGerrit will load `sampleplugin.html` and skip `sampleplugin.js`
 | 
						|
 * PolyGerrit will reuse `plugin` (aka `self`) instance for `Gerrit.install()`
 | 
						|
callbacks
 | 
						|
- `sampleplugin.js` is loaded since it's referenced in `sampleplugin.html`
 | 
						|
- setup script tag code is executed before `sampleplugin.js`
 | 
						|
- cleanup script tag code is executed after `sampleplugin.js`
 | 
						|
- `plugin.deprecated.install()` enables deprecated APIs (onAction(), popup(),
 | 
						|
etc) before `sampleplugin.js` is loaded
 | 
						|
 | 
						|
This means the plugin instance is shared between .html-based and .js-based
 | 
						|
code. This allows to gradually and incrementally transfer code to the new API.
 | 
						|
 | 
						|
=== Step 2: Create cut-off marker in `sampleplugin.js`
 | 
						|
 | 
						|
Commonly, window.Polymer is being used to detect in GWT UI script if it's being
 | 
						|
executed inside PolyGerrit. This could be used to separate code that was already
 | 
						|
migrated to new APIs from old not yet migrated code.
 | 
						|
 | 
						|
During incremental migration, some of the UI code will be reimplemented using
 | 
						|
the PolyGerrit plugin API. However, old code still could be required for the plugin
 | 
						|
to work in GWT UI.
 | 
						|
 | 
						|
To handle this case, add the following code at the end of the installation
 | 
						|
callback in `sampleplugin.js`
 | 
						|
 | 
						|
``` js
 | 
						|
Gerrit.install(function(self) {
 | 
						|
 | 
						|
  // Existing code here, not modified.
 | 
						|
 | 
						|
  if (window.Polymer) { return; } // Cut-off marker
 | 
						|
 | 
						|
  // Everything below was migrated to PolyGerrit plugin API.
 | 
						|
  // Code below is still needed for the plugin to work in GWT UI.
 | 
						|
});
 | 
						|
```
 | 
						|
 | 
						|
=== Step 3: Migrate!
 | 
						|
 | 
						|
The code that uses deprecated APIs should be eventually rewritten using
 | 
						|
non-deprecated counterparts. Duplicated pieces could be kept under cut-off
 | 
						|
marker to work in GWT UI.
 | 
						|
 | 
						|
If some data or functions needs to be shared between code in .html and .js, it
 | 
						|
could be stored in the `plugin` (aka `self`) object that's shared between both
 | 
						|
 | 
						|
=== Step 4: Cleanup
 | 
						|
 | 
						|
Once deprecated APIs are migrated, `sampleplugin.js` will only contain
 | 
						|
duplicated code that's required for GWT UI to work. As soon as GWT support is removed from Gerrit
 | 
						|
that file can be simply deleted, along with the script tag loading it.
 | 
						|
 |