Expose reply dialog and label score value to plugins.
Provides sample plugin that sets Code-Review+1 on entering LGTM into reply dialog. Adds a getLabelValue(labelName) to plugin.changeReply(). Adds support for plugin dom hooks in general, and for reply dialog text area as a first instance. Adds plugin.changeReply().addReplyTextChangedCallback() which uses dom plugin hook. Feature: Issue 6280 Change-Id: I2b8d52c0d8000ea5d217268f6e6d7ef4137b2213
This commit is contained in:
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
|
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
|
||||||
<link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
|
<link rel="import" href="../../../behaviors/gr-patch-set-behavior/gr-patch-set-behavior.html">
|
||||||
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
|
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
|
||||||
<link rel="import" href="../../../behaviors/rest-client-behavior/rest-client-behavior.html">
|
<link rel="import" href="../../../behaviors/rest-client-behavior/rest-client-behavior.html">
|
||||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
|
||||||
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
|
<link rel="import" href="../../../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
|
||||||
|
<link rel="import" href="../../plugins/gr-endpoint-decorator/gr-endpoint-decorator.html">
|
||||||
<link rel="import" href="../../shared/gr-account-chip/gr-account-chip.html">
|
<link rel="import" href="../../shared/gr-account-chip/gr-account-chip.html">
|
||||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||||
<link rel="import" href="../../shared/gr-formatted-text/gr-formatted-text.html">
|
<link rel="import" href="../../shared/gr-formatted-text/gr-formatted-text.html">
|
||||||
@@ -95,6 +96,9 @@ limitations under the License.
|
|||||||
min-height: 6em;
|
min-height: 6em;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.textareaContainer > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
iron-autogrow-textarea {
|
iron-autogrow-textarea {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: var(--monospace-font-family);
|
font-family: var(--monospace-font-family);
|
||||||
@@ -202,17 +206,19 @@ limitations under the License.
|
|||||||
</gr-overlay>
|
</gr-overlay>
|
||||||
</section>
|
</section>
|
||||||
<section class="textareaContainer">
|
<section class="textareaContainer">
|
||||||
<iron-autogrow-textarea
|
<gr-endpoint-decorator name="reply-text">
|
||||||
id="textarea"
|
<iron-autogrow-textarea
|
||||||
class="message"
|
id="textarea"
|
||||||
autocomplete="on"
|
class="message"
|
||||||
placeholder=[[_messagePlaceholder]]
|
autocomplete="on"
|
||||||
disabled="{{disabled}}"
|
placeholder=[[_messagePlaceholder]]
|
||||||
rows="4"
|
disabled="{{disabled}}"
|
||||||
max-rows="15"
|
rows="4"
|
||||||
bind-value="{{draft}}"
|
max-rows="15"
|
||||||
on-bind-value-changed="_handleHeightChanged">
|
bind-value="{{draft}}"
|
||||||
</iron-autogrow-textarea>
|
on-bind-value-changed="_handleHeightChanged">
|
||||||
|
</iron-autogrow-textarea>
|
||||||
|
</gr-endpoint-decorator>
|
||||||
</section>
|
</section>
|
||||||
<section class="previewContainer">
|
<section class="previewContainer">
|
||||||
<label>
|
<label>
|
||||||
|
@@ -198,14 +198,24 @@
|
|||||||
|
|
||||||
setLabelValue(label, value) {
|
setLabelValue(label, value) {
|
||||||
const selectorEl =
|
const selectorEl =
|
||||||
this.$.labelScores.$$('iron-selector[data-label="' + label + '"]');
|
this.$.labelScores.$$(`iron-selector[data-label="${label}"]`);
|
||||||
// The selector may not be present if it’s not at the latest patch set.
|
// The selector may not be present if it’s not at the latest patch set.
|
||||||
if (!selectorEl) { return; }
|
if (!selectorEl) { return; }
|
||||||
const item = selectorEl.$$('gr-button[data-value="' + value + '"]');
|
const item = selectorEl.$$(`gr-button[data-value="${value}"]`);
|
||||||
if (!item) { return; }
|
if (!item) { return; }
|
||||||
selectorEl.selectIndex(selectorEl.indexOf(item));
|
selectorEl.selectIndex(selectorEl.indexOf(item));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getLabelValue(label) {
|
||||||
|
const selectorEl =
|
||||||
|
this.$.labelScores.$$(`iron-selector[data-label="${label}"]`);
|
||||||
|
// The selector may not be present if it’s not at the latest patch set.
|
||||||
|
if (!selectorEl) { return null; }
|
||||||
|
const item = selectorEl.querySelector('gr-button.iron-selected');
|
||||||
|
if (!item) { return null; }
|
||||||
|
return item.getAttribute('data-value');
|
||||||
|
},
|
||||||
|
|
||||||
_handleEscKey(e) {
|
_handleEscKey(e) {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
},
|
},
|
||||||
|
@@ -211,6 +211,26 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getlabelValue returns value', done => {
|
||||||
|
flush(() => {
|
||||||
|
MockInteractions.tap(element.$$('gr-label-scores').$$(
|
||||||
|
'iron-selector[data-label="Verified"] > ' +
|
||||||
|
'gr-button[data-value="-1"]'));
|
||||||
|
assert.equal('-1', element.getLabelValue('Verified'));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getlabelValue when no score is selected', done => {
|
||||||
|
flush(() => {
|
||||||
|
MockInteractions.tap(element.$$('gr-label-scores').$$(
|
||||||
|
'iron-selector[data-label="Code-Review"] > ' +
|
||||||
|
'gr-button[data-value="-1"]'));
|
||||||
|
assert.isNull(element.getLabelValue('Verified'));
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('setlabelValue', () => {
|
test('setlabelValue', () => {
|
||||||
element._account = {_account_id: 1};
|
element._account = {_account_id: 1};
|
||||||
flushAsynchronousOperations();
|
flushAsynchronousOperations();
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
<link rel="import" href="../../shared/gr-js-api-interface/gr-js-api-interface.html">
|
||||||
|
|
||||||
|
<dom-module id="gr-endpoint-decorator">
|
||||||
|
<template>
|
||||||
|
<content></content>
|
||||||
|
</template>
|
||||||
|
<script src="gr-endpoint-decorator.js"></script>
|
||||||
|
</dom-module>
|
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (C) 2017 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
Polymer({
|
||||||
|
is: 'gr-endpoint-decorator',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
|
||||||
|
_import(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.importHref(url, resolve, reject);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_initPluginDomHook(name, plugin) {
|
||||||
|
const el = document.createElement(name);
|
||||||
|
el.plugin = plugin;
|
||||||
|
el.content = this.getContentChildren()[0];
|
||||||
|
return Polymer.dom(this.root).appendChild(el);
|
||||||
|
},
|
||||||
|
|
||||||
|
ready() {
|
||||||
|
Gerrit.awaitPluginsLoaded().then(() => Promise.all(
|
||||||
|
Gerrit._getPluginsForEndpoint(this.name).map(
|
||||||
|
pluginUrl => this._import(pluginUrl)))
|
||||||
|
).then(() => {
|
||||||
|
const modulesData = Gerrit._getEndpointDetails(this.name);
|
||||||
|
for (const {moduleName, plugin} of modulesData) {
|
||||||
|
this._initPluginDomHook(moduleName, plugin);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})();
|
@@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<title>gr-endpoint-decorator</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||||
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||||
|
<link rel="import" href="gr-endpoint-decorator.html">
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<gr-endpoint-decorator name="foo"></gr-endpoint-decorator>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
suite('gr-endpoint-decorator', () => {
|
||||||
|
let sandbox;
|
||||||
|
let element;
|
||||||
|
let plugin;
|
||||||
|
|
||||||
|
setup(done => {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
// NB: Order is important.
|
||||||
|
Gerrit.install(p => {
|
||||||
|
plugin = p;
|
||||||
|
plugin.registerCustomComponent('foo', 'some-module');
|
||||||
|
}, '0.1', 'http://some/plugin/url.html');
|
||||||
|
|
||||||
|
sandbox.stub(Gerrit, 'awaitPluginsLoaded').returns(Promise.resolve());
|
||||||
|
|
||||||
|
element = fixture('basic');
|
||||||
|
sandbox.stub(element, '_initPluginDomHook');
|
||||||
|
sandbox.stub(element, 'importHref', (url, resolve) => { resolve(); });
|
||||||
|
|
||||||
|
flush(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('imports plugin-provided module', () => {
|
||||||
|
assert.isTrue(
|
||||||
|
element.importHref.calledWith(new URL('http://some/plugin/url.html')));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('inits plugin-provided dom hook', () => {
|
||||||
|
assert.isTrue(
|
||||||
|
element._initPluginDomHook.calledWith('some-module', plugin));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@@ -34,24 +34,13 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
ready() {
|
ready() {
|
||||||
Gerrit.awaitPluginsLoaded().then(() => {
|
Gerrit.awaitPluginsLoaded().then(() => Promise.all(
|
||||||
const sharedStyles = Gerrit._styleModules[this.name];
|
Gerrit._getPluginsForEndpoint(this.name).map(
|
||||||
if (sharedStyles) {
|
pluginUrl => this._import(pluginUrl)))
|
||||||
const pluginUrls = [];
|
).then(() => {
|
||||||
const moduleNames = [];
|
const moduleNames = Gerrit._getModulesForEndoint(this.name);
|
||||||
sharedStyles.reduce((result, item) => {
|
for (const name of moduleNames) {
|
||||||
if (!result.pluginUrls.includes(item.pluginUrl)) {
|
this._applyStyle(name);
|
||||||
result.pluginUrls.push(item.pluginUrl);
|
|
||||||
}
|
|
||||||
result.moduleNames.push(item.moduleName);
|
|
||||||
return result;
|
|
||||||
}, {pluginUrls, moduleNames});
|
|
||||||
Promise.all(pluginUrls.map(this._import.bind(this)))
|
|
||||||
.then(() => {
|
|
||||||
for (const name of moduleNames) {
|
|
||||||
this._applyStyle(name);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@@ -31,18 +31,26 @@ limitations under the License.
|
|||||||
</test-fixture>
|
</test-fixture>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
suite('gr-change-metadata integration tests', () => {
|
suite('gr-external-style integration tests', () => {
|
||||||
let sandbox;
|
let sandbox;
|
||||||
let element;
|
let element;
|
||||||
|
|
||||||
setup(done => {
|
setup(done => {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
// NB: Order is important.
|
||||||
|
let plugin;
|
||||||
|
Gerrit.install(p => {
|
||||||
|
plugin = p;
|
||||||
|
plugin.registerStyleModule('foo', 'some-module');
|
||||||
|
}, '0.1', 'http://some/plugin/url.html');
|
||||||
|
|
||||||
sandbox.stub(Gerrit, 'awaitPluginsLoaded').returns(Promise.resolve());
|
sandbox.stub(Gerrit, 'awaitPluginsLoaded').returns(Promise.resolve());
|
||||||
Gerrit._styleModules = {foo: [{pluginUrl: 'bar', moduleName: 'baz'}]};
|
|
||||||
|
|
||||||
element = fixture('basic');
|
element = fixture('basic');
|
||||||
sandbox.stub(element, '_applyStyle');
|
sandbox.stub(element, '_applyStyle');
|
||||||
sandbox.stub(element, 'importHref', (url, resolve) => { resolve(); });
|
sandbox.stub(element, 'importHref', (url, resolve) => { resolve(); });
|
||||||
|
|
||||||
flush(done);
|
flush(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,11 +59,12 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('imports plugin-provided module', () => {
|
test('imports plugin-provided module', () => {
|
||||||
assert.isTrue(element.importHref.calledWith('bar'));
|
assert.isTrue(element.importHref.calledWith(
|
||||||
|
new URL('http://some/plugin/url.html')));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('applies plugin-provided styles', () => {
|
test('applies plugin-provided styles', () => {
|
||||||
assert.isTrue(element._applyStyle.calledWith('baz'));
|
assert.isTrue(element._applyStyle.calledWith('some-module'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -14,17 +14,44 @@
|
|||||||
(function(window) {
|
(function(window) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
function GrChangeReplyInterface(el) {
|
/**
|
||||||
this._el = el;
|
* Don't add new API methods to GrChangeReplyInterfaceOld.
|
||||||
|
* All new API should be added to GrChangeReplyInterface.
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
class GrChangeReplyInterfaceOld {
|
||||||
|
constructor(el) {
|
||||||
|
this._el = el;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabelValue(label) {
|
||||||
|
return this._el.getLabelValue(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLabelValue(label, value) {
|
||||||
|
this._el.setLabelValue(label, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(opt_includeComments) {
|
||||||
|
return this._el.send(opt_includeComments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GrChangeReplyInterface.prototype.setLabelValue = function(label, value) {
|
class GrChangeReplyInterface extends GrChangeReplyInterfaceOld {
|
||||||
this._el.setLabelValue(label, value);
|
constructor(plugin, el) {
|
||||||
};
|
super(el);
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
GrChangeReplyInterface.prototype.send = function(opt_includeComments) {
|
addReplyTextChangedCallback(handler) {
|
||||||
return this._el.send(opt_includeComments);
|
this.plugin.getDomHook('reply-text').then(el => {
|
||||||
};
|
if (!el.content) { return; }
|
||||||
|
el.content.addEventListener('value-changed', e => {
|
||||||
|
handler(e.detail.value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.GrChangeReplyInterface = GrChangeReplyInterface;
|
window.GrChangeReplyInterface = GrChangeReplyInterface;
|
||||||
})(window);
|
})(window);
|
||||||
|
@@ -23,9 +23,9 @@ limitations under the License.
|
|||||||
|
|
||||||
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||||
<!--
|
<!--
|
||||||
This must refer to the element this interface is wrapping around. Otherwise
|
This must refer to the element this interface is wrapping around. Otherwise
|
||||||
breaking changes to gr-reply-dialog won’t be noticed.
|
breaking changes to gr-reply-dialog won’t be noticed.
|
||||||
-->
|
-->
|
||||||
<link rel="import" href="../../change/gr-reply-dialog/gr-reply-dialog.html">
|
<link rel="import" href="../../change/gr-reply-dialog/gr-reply-dialog.html">
|
||||||
|
|
||||||
<script>void(0);</script>
|
<script>void(0);</script>
|
||||||
@@ -61,13 +61,17 @@ limitations under the License.
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('calls', () => {
|
test('calls', () => {
|
||||||
const setLabelValueStub = sinon.stub(element, 'setLabelValue');
|
sandbox.stub(element, 'getLabelValue').returns('+123');
|
||||||
changeReply.setLabelValue('My-Label', '+1337');
|
assert.equal(changeReply.getLabelValue('My-Label'), '+123');
|
||||||
assert(setLabelValueStub.calledWithExactly('My-Label', '+1337'));
|
|
||||||
|
|
||||||
const sendStub = sinon.stub(element, 'send');
|
sandbox.stub(element, 'setLabelValue');
|
||||||
|
changeReply.setLabelValue('My-Label', '+1337');
|
||||||
|
assert.isTrue(
|
||||||
|
element.setLabelValue.calledWithExactly('My-Label', '+1337'));
|
||||||
|
|
||||||
|
sandbox.stub(element, 'send');
|
||||||
changeReply.send(false);
|
changeReply.send(false);
|
||||||
assert(sendStub.calledWithExactly(false));
|
assert.isTrue(element.send.calledWithExactly(false));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -34,6 +34,11 @@
|
|||||||
|
|
||||||
const API_VERSION = '0.1';
|
const API_VERSION = '0.1';
|
||||||
|
|
||||||
|
const EndpointType = {
|
||||||
|
STYLE: 'style',
|
||||||
|
DOM_DECORATION: 'dom',
|
||||||
|
};
|
||||||
|
|
||||||
// GWT JSNI uses $wnd to refer to window.
|
// GWT JSNI uses $wnd to refer to window.
|
||||||
// http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
|
// http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
|
||||||
window.$wnd = window;
|
window.$wnd = window;
|
||||||
@@ -52,6 +57,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._name = this._url.pathname.split('/')[2];
|
this._name = this._url.pathname.split('/')[2];
|
||||||
|
this._generatedHookNames = [];
|
||||||
|
this._hooks = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin._sharedAPIElement = document.createElement('gr-js-api-interface');
|
Plugin._sharedAPIElement = document.createElement('gr-js-api-interface');
|
||||||
@@ -62,14 +69,27 @@
|
|||||||
return this._name;
|
return this._name;
|
||||||
};
|
};
|
||||||
|
|
||||||
Plugin.prototype.registerStyleModule = function(stylingEndpointName,
|
Plugin.prototype.registerStyleModule = function(endpointName, moduleName) {
|
||||||
moduleName) {
|
this._registerEndpointModule(
|
||||||
if (!Gerrit._styleModules[stylingEndpointName]) {
|
endpointName, EndpointType.STYLE, moduleName);
|
||||||
Gerrit._styleModules[stylingEndpointName] = [];
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.registerCustomComponent =
|
||||||
|
function(endpointName, moduleName) {
|
||||||
|
this._registerEndpointModule(
|
||||||
|
endpointName, EndpointType.DOM_DECORATION, moduleName);
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype._registerEndpointModule = function(endpoint, type, module) {
|
||||||
|
const endpoints = Gerrit._endpoints;
|
||||||
|
if (!endpoints[endpoint]) {
|
||||||
|
endpoints[endpoint] = [];
|
||||||
}
|
}
|
||||||
Gerrit._styleModules[stylingEndpointName].push({
|
endpoints[endpoint].push({
|
||||||
|
moduleName: module,
|
||||||
|
plugin: this,
|
||||||
pluginUrl: this._url,
|
pluginUrl: this._url,
|
||||||
moduleName,
|
type,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,8 +125,37 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
Plugin.prototype.changeReply = function() {
|
Plugin.prototype.changeReply = function() {
|
||||||
return new GrChangeReplyInterface(Plugin._sharedAPIElement.getElement(
|
return new GrChangeReplyInterface(this,
|
||||||
Plugin._sharedAPIElement.Element.REPLY_DIALOG));
|
Plugin._sharedAPIElement.getElement(
|
||||||
|
Plugin._sharedAPIElement.Element.REPLY_DIALOG));
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype._getGeneratedHookName = function(endpointName) {
|
||||||
|
if (!this._generatedHookNames[endpointName]) {
|
||||||
|
this._generatedHookNames[endpointName] = this.getPluginName() +
|
||||||
|
'-autogenerated-' + endpointName;
|
||||||
|
}
|
||||||
|
return this._generatedHookNames[endpointName];
|
||||||
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.getDomHook = function(endpointName) {
|
||||||
|
const hookName = this._getGeneratedHookName(endpointName);
|
||||||
|
if (!this._hooks[hookName]) {
|
||||||
|
this._hooks[hookName] = new Promise((resolve, reject) => {
|
||||||
|
Polymer({
|
||||||
|
is: hookName,
|
||||||
|
properties: {
|
||||||
|
plugin: Object,
|
||||||
|
content: Object,
|
||||||
|
},
|
||||||
|
attached() {
|
||||||
|
resolve(this);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.registerCustomComponent(endpointName, hookName);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this._hooks[hookName];
|
||||||
};
|
};
|
||||||
|
|
||||||
const Gerrit = window.Gerrit || {};
|
const Gerrit = window.Gerrit || {};
|
||||||
@@ -114,8 +163,8 @@
|
|||||||
// Number of plugins to initialize, -1 means 'not yet known'.
|
// Number of plugins to initialize, -1 means 'not yet known'.
|
||||||
Gerrit._pluginsPending = -1;
|
Gerrit._pluginsPending = -1;
|
||||||
|
|
||||||
// Hash of style modules to be applied, insertion point to shared style name.
|
// Hash of custom components to be instantiated for extension endpoints.
|
||||||
Gerrit._styleModules = {};
|
Gerrit._endpoints = {};
|
||||||
|
|
||||||
Gerrit.getPluginName = function() {
|
Gerrit.getPluginName = function() {
|
||||||
console.warn('Gerrit.getPluginName is not supported in PolyGerrit.',
|
console.warn('Gerrit.getPluginName is not supported in PolyGerrit.',
|
||||||
@@ -204,5 +253,67 @@
|
|||||||
return Gerrit._pluginsPending === 0;
|
return Gerrit._pluginsPending === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get detailed information about modules registered with an extension
|
||||||
|
* endpoint.
|
||||||
|
* @param {string} name Endpoint name.
|
||||||
|
* @param {?{
|
||||||
|
* type: (string|undefined),
|
||||||
|
* moduleName: (string|undefined)
|
||||||
|
* }} opt_options
|
||||||
|
* @return {{
|
||||||
|
* moduleName: string,
|
||||||
|
* plugin: Plugin,
|
||||||
|
* pluginUrl: String,
|
||||||
|
* type: EndpointType,
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
Gerrit._getEndpointDetails = function(name, opt_options) {
|
||||||
|
const type = opt_options && opt_options.type;
|
||||||
|
const moduleName = opt_options && opt_options.moduleName;
|
||||||
|
if (!Gerrit._endpoints[name]) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Gerrit._endpoints[name]
|
||||||
|
.filter(item => (!type || item.type === type) &&
|
||||||
|
(!moduleName || moduleName == item.moduleName));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get detailed module names for instantiating at the endpoint
|
||||||
|
* @param {string} name Endpoint name.
|
||||||
|
* @param {?{
|
||||||
|
* type: (string|undefined),
|
||||||
|
* moduleName: (string|undefined)
|
||||||
|
* }} opt_options
|
||||||
|
* @return {!Array<string>}
|
||||||
|
*/
|
||||||
|
Gerrit._getModulesForEndoint = function(name, opt_options) {
|
||||||
|
const modulesData = Gerrit._getEndpointDetails(name, opt_options);
|
||||||
|
if (!modulesData.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return modulesData.map(m => m.moduleName);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get .html plugin URLs with element and module definitions.
|
||||||
|
* @param {string} name Endpoint name.
|
||||||
|
* @param {?{
|
||||||
|
* type: (string|undefined),
|
||||||
|
* moduleName: (string|undefined)
|
||||||
|
* }} opt_options
|
||||||
|
* @return {!Array<!URL>}
|
||||||
|
*/
|
||||||
|
Gerrit._getPluginsForEndpoint = function(name, opt_options) {
|
||||||
|
const modulesData =
|
||||||
|
Gerrit._getEndpointDetails(name, opt_options).filter(
|
||||||
|
data => data.pluginUrl.pathname.indexOf('.html') !== -1);
|
||||||
|
if (!modulesData.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Array.from(new Set(modulesData.map(m => m.pluginUrl)));
|
||||||
|
};
|
||||||
|
|
||||||
window.Gerrit = Gerrit;
|
window.Gerrit = Gerrit;
|
||||||
})(window);
|
})(window);
|
||||||
|
16
polygerrit-ui/app/samples/lgtm-plugin.html
Normal file
16
polygerrit-ui/app/samples/lgtm-plugin.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<dom-module id="lgtm-plugin">
|
||||||
|
<script>
|
||||||
|
Gerrit.install(plugin => {
|
||||||
|
const replyApi = plugin.changeReply();
|
||||||
|
replyApi.addReplyTextChangedCallback(text => {
|
||||||
|
const label = 'Code-Review';
|
||||||
|
const labelValue = replyApi.getLabelValue(label);
|
||||||
|
if (labelValue &&
|
||||||
|
labelValue === ' 0' &&
|
||||||
|
text.indexOf('LGTM') === 0) {
|
||||||
|
replyApi.setLabelValue(label, '+1');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</dom-module>
|
Reference in New Issue
Block a user