Support for .panel() plugin API

Deprecates `plugin.panel()` in favor of `registerCustomComponent()`.

Adds a "stepping stone" `plugin.deprecated.panel()` with limited
support.

Change-Id: I374f073d5c6ef1232c2fd3512b2f41f191c06d48
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
index 504504e..6147e68 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.html
@@ -484,5 +484,39 @@
             'testplugin-screen-foo', 'some-module'));
       });
     });
+
+    suite('panel', () => {
+      let fakeEl;
+      let emulateAttached;
+
+      setup(()=> {
+        fakeEl = {change: {}, revision: {}};
+        const hookStub = {onAttached: sandbox.stub()};
+        sandbox.stub(plugin, 'hook').returns(hookStub);
+        emulateAttached = () => hookStub.onAttached.callArgWith(0, fakeEl);
+      });
+
+      test('plugin.panel is deprecated', () => {
+        plugin.panel('rubbish');
+        assert.isTrue(console.error.called);
+      });
+
+      [
+        ['CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK', 'change-view-integration'],
+        ['CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK', 'change-metadata-item'],
+      ].forEach(([panelName, endpointName]) => {
+        test(`deprecated.panel works for ${panelName}`, () => {
+          const callback = sandbox.stub();
+          plugin.deprecated.panel(panelName, callback);
+          assert.isTrue(plugin.hook.calledWith(endpointName));
+          emulateAttached();
+          assert.isTrue(callback.called);
+          const args = callback.args[0][0];
+          assert.strictEqual(args.body, fakeEl);
+          assert.strictEqual(args.p.CHANGE_INFO, fakeEl.change);
+          assert.strictEqual(args.p.REVISION_INFO, fakeEl.revision);
+        });
+      });
+    });
   });
 </script>
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
index 2950c05..7402539 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.js
@@ -23,12 +23,17 @@
    */
   const plugins = {};
 
-  const stubbedMethods = ['_loadedGwt', 'settingsScreen', 'panel'];
+  const stubbedMethods = ['_loadedGwt', 'settingsScreen'];
   const GWT_PLUGIN_STUB = {};
   for (const name of stubbedMethods) {
     GWT_PLUGIN_STUB[name] = warnNotSupported.bind(null, name);
   }
 
+  const PANEL_ENDPOINTS_MAPPING = {
+    CHANGE_SCREEN_BELOW_COMMIT_INFO_BLOCK: 'change-view-integration',
+    CHANGE_SCREEN_BELOW_CHANGE_INFO_BLOCK: 'change-metadata-item',
+  };
+
   let _restAPI;
   const getRestAPI = () => {
     if (!_restAPI) {
@@ -110,6 +115,7 @@
     this.deprecated = {
       install: deprecatedAPI.install.bind(this),
       onAction: deprecatedAPI.onAction.bind(this),
+      panel: deprecatedAPI.panel.bind(this),
       popup: deprecatedAPI.popup.bind(this),
       screen: deprecatedAPI.screen.bind(this),
     };
@@ -249,6 +255,11 @@
     return api.open();
   };
 
+  Plugin.prototype.panel = function() {
+    console.error('.panel() is deprecated! ' +
+        'Use registerCustomComponent() instead.');
+  };
+
   Plugin.prototype.screen = function(screenName, opt_moduleName) {
     if (opt_moduleName && typeof opt_moduleName !== 'string') {
       throw new Error('deprecated, use deprecated.screen');
@@ -321,6 +332,23 @@
             });
           });
     },
+
+    panel(extensionpoint, callback) {
+      console.warn('.panel() is deprecated! ' +
+          'Use registerCustomComponent() instead.');
+      const endpoint = PANEL_ENDPOINTS_MAPPING[extensionpoint];
+      if (!endpoint) {
+        console.warn(`.panel ${extensionpoint} not supported!`);
+        return;
+      }
+      this.hook(endpoint).onAttached(el => callback({
+        body: el,
+        p: {
+          CHANGE_INFO: el.change,
+          REVISION_INFO: el.revision,
+        },
+      }));
+    },
   };
 
   const Gerrit = window.Gerrit || {};