Merge branch 'stable-3.0'
* stable-3.0:
PG: autocomplete reviewers
Bazel: Fix standalone build mode
Polygerrit UI
Switch required bazel version to 0.29.1
Change-Id: I3f673674f8c3eef685ab104289c1887295300b6f
diff --git a/.bazelversion b/.bazelversion
index 8862dba..25939d3 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-1.0.0rc2
+0.29.1
diff --git a/BUILD b/BUILD
index a26e3b7..32b4c8d 100644
--- a/BUILD
+++ b/BUILD
@@ -6,6 +6,8 @@
"PLUGIN_TEST_DEPS",
"gerrit_plugin",
)
+load("//tools/bzl:genrule2.bzl", "genrule2")
+load("//tools/bzl:js.bzl", "polygerrit_plugin")
gerrit_plugin(
name = "reviewers",
@@ -15,6 +17,28 @@
"Gerrit-Module: com.googlesource.gerrit.plugins.reviewers.Module",
],
resources = glob(["src/main/resources/**/*"]),
+ resource_jars = [":rv-reviewers-static"],
+)
+
+genrule2(
+ name = "rv-reviewers-static",
+ srcs = [":rv-reviewers"],
+ outs = ["rv-reviewers-static.jar"],
+ cmd = " && ".join([
+ "mkdir $$TMP/static",
+ "cp -r $(locations :rv-reviewers) $$TMP/static",
+ "cd $$TMP",
+ "zip -Drq $$ROOT/$@ -g .",
+ ]),
+)
+
+polygerrit_plugin(
+ name = "rv-reviewers",
+ srcs = glob([
+ "rv-reviewers/*.html",
+ "rv-reviewers/*.js",
+ ]),
+ app = "plugin.html",
)
junit_tests(
diff --git a/WORKSPACE b/WORKSPACE
index 4242552..190fd06 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -7,6 +7,32 @@
#local_path = "/home/<user>/projects/bazlets",
)
+# Polymer dependencies
+load(
+ "@com_googlesource_gerrit_bazlets//:gerrit_polymer.bzl",
+ "gerrit_polymer",
+)
+
+gerrit_polymer()
+
+# Load closure compiler with transitive dependencies
+load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories")
+
+closure_repositories()
+
+# Load Gerrit npm_binary toolchain
+load("@com_googlesource_gerrit_bazlets//tools:js.bzl", "GERRIT", "npm_binary")
+
+npm_binary(
+ name = "polymer-bundler",
+ repository = GERRIT,
+)
+
+npm_binary(
+ name = "crisper",
+ repository = GERRIT,
+)
+
# Release Plugin API
#load(
# "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
diff --git a/plugin.html b/plugin.html
new file mode 100644
index 0000000..29c10cb
--- /dev/null
+++ b/plugin.html
@@ -0,0 +1,27 @@
+<!--
+@license
+Copyright (C) 2019 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="./rv-reviewers/rv-reviewers.html">
+
+<dom-module id="reviewers">
+ <script>
+ if (window.Polymer) {
+ Gerrit.install(plugin => {
+ plugin.registerCustomComponent('repo-command', 'rv-reviewers');
+ });
+ }
+ </script>
+</dom-module>
diff --git a/rv-reviewers/rv-edit-screen.html b/rv-reviewers/rv-edit-screen.html
new file mode 100644
index 0000000..ca32849
--- /dev/null
+++ b/rv-reviewers/rv-edit-screen.html
@@ -0,0 +1,76 @@
+<!--
+@license
+Copyright (C) 2019 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="./rv-filter-section.html">
+
+<dom-module id="rv-edit-screen">
+ <template>
+ <style include="shared-styles"></style>
+ <style include="gr-menu-page-styles"></style>
+ <style include="gr-subpage-styles">
+ .bottomButtons {
+ display: flex;
+ }
+ #closeButton {
+ float: right;
+ }
+ #filterSections {
+ width: 100%;
+ }
+ header {
+ border-bottom: 1px solid var(--border-colo);
+ flex-shrink: 0;
+ font-weight: var(--font-weight-bold)
+ }
+ </style>
+ <div>
+ <header>Reviewers Config</header>
+ <table id="filterSections">
+ <tr>
+ <th>Filter Sections</th>
+ </tr>
+ <tr id="loading" class$="loadingMsg [[_computeLoadingClass(loading)]]">
+ <td>Loading...</td>
+ </tr>
+ <tbody class$="[[_computeLoadingClass(loading)]]">
+ <tr>
+ <template
+ is="dom-repeat"
+ items="[[_filterSections]]"
+ as="section">
+ <rv-filter-section
+ filter="[[section.filter]]"
+ reviewers="[[section.reviewers]]"
+ editing="[[section.editing]]"
+ reviewers-url="[[_getReviewersUrl(repoName)]]"
+ plugin-rest-api="[[pluginRestApi]]"
+ can-modify-config="[[canModifyConfig]]"
+ on-reviewer-changed="_handleReviewerChanged"></rv-filter-section>
+ </template>
+ </tr>
+ </tbody>
+ </table>
+ <div class="bottomButtons">
+ <gr-button id="closeButton" on-tap="_handleCloseTap">Close</gr-button>
+ <gr-button
+ id="addFilterBtn"
+ on-tap="_handleCreateSection"
+ hidden="[[_computeAddFilterBtnHidden(canModifyConfig, _editingFilter)]]">Add New Filter</gr-button>
+ </div>
+ </div>
+ </template>
+ <script src="./rv-edit-screen.js"></script>
+</dom-module>
diff --git a/rv-reviewers/rv-edit-screen.js b/rv-reviewers/rv-edit-screen.js
new file mode 100644
index 0000000..f25f696
--- /dev/null
+++ b/rv-reviewers/rv-edit-screen.js
@@ -0,0 +1,69 @@
+// Copyright (C) 2019 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() {
+ Polymer({
+ is: 'rv-edit-screen',
+
+ properties: {
+ pluginRestApi: Object,
+ repoName: String,
+ loading: Boolean,
+ canModifyConfig: Boolean,
+ _editingFilter: {
+ type: Boolean,
+ value: false,
+ },
+ _filterSections: Array,
+ },
+
+ attached() {
+ this._loadFilterSections();
+ },
+
+ _loadFilterSections() {
+ this.pluginRestApi.get(this._getReviewersUrl(this.repoName))
+ .then(filterSections => {
+ this._filterSections = filterSections;
+ });
+ },
+
+ _computeAddFilterBtnHidden(canModifyConfig, editingFilter) {
+ return !canModifyConfig || editingFilter;
+ },
+
+ _computeLoadingClass(loading) {
+ return loading ? 'loading' : '';
+ },
+
+ _getReviewersUrl(repoName) {
+ return `/projects/${repoName}/reviewers`;
+ },
+
+ _handleCreateSection() {
+ const section = {filter: '', reviewers: [], editing: true};
+ this._editingFilter = true;
+ this.push('_filterSections', section);
+ },
+
+ _handleCloseTap(e) {
+ e.preventDefault();
+ this.fire('close', null, {bubbles: false});
+ },
+
+ _handleReviewerChanged(e) {
+ this._filterSections = e.detail.result;
+ this._editingFilter = false;
+ },
+ });
+})();
diff --git a/rv-reviewers/rv-filter-section.html b/rv-reviewers/rv-filter-section.html
new file mode 100644
index 0000000..104ecbd
--- /dev/null
+++ b/rv-reviewers/rv-filter-section.html
@@ -0,0 +1,97 @@
+<!--
+@license
+Copyright (C) 2019 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="./rv-reviewer.html">
+
+<dom-module id="rv-filter-section">
+ <template>
+ <style include="shared-styles">
+ :host {
+ display: block;
+ margin-bottom: 1em;
+ }
+ fieldset {
+ border: 1px solid var(--border-color);
+ }
+ .name {
+ align-items: center;
+ display: flex;
+ }
+ .header {
+ align-items: center;
+ background: var(--table-header-background-color);
+ border-bottom: 1px dotted var(--border-color);
+ display: flex;
+ justify-content: space-between;
+ min-height: 3em;
+ padding: 0 .7em;
+ }
+ #addReviewer {
+ display: flex;
+ }
+ #editFilterInput {
+ width: 30vw;
+ max-width: 500px;
+ margin-left: 3px;
+ }
+ #mainContainer {
+ display: block;
+ }
+ </style>
+ <style include="gr-form-styles"></style>
+ <fieldset id="section"
+ class$="gr-form-styles">
+ <div id="mainContainer">
+ <div class="header">
+ <div class="name">
+ <h3>Filter:</h3>
+ <input
+ id="editFilterInput"
+ bind-value="{{filter}}"
+ is="iron-input"
+ type="text"
+ disabled="[[_computeFilterInputDisabled(canModifyConfig, _originalFilter)]]">
+ <gr-button
+ id="cancelBtn"
+ on-tap="_handleCancel"
+ hidden$="[[_computeCancelHidden(filter, _originalFilter)]]">Cancel</gr-button>
+ </div><!-- name -->
+ </div><!-- header -->
+ <div class="reviewers">
+ <template
+ is="dom-repeat"
+ items="{{reviewers}}">
+ <rv-reviewer
+ reviewer="{{item}}"
+ can-modify-config="[[canModifyConfig]]"
+ plugin-rest-api="[[pluginRestApi]]"
+ on-reviewer-deleted="_handleReviewerDeleted"
+ on-reviewer-added="_handleReviewerAdded">
+ </rv-reviewer>
+ </template>
+ <div id="addReviewer">
+ <gr-button
+ link
+ id="addBtn"
+ on-tap="_handleAddReviewer"
+ hidden="[[_computeAddBtnHidden(canModifyConfig, _editingReviewer)]]">Add Reviewer</gr-button>
+ </div><!-- addReviewer -->
+ </div><!-- reviewers -->
+ </div>
+ </fieldset>
+ </template>
+ <script src="./rv-filter-section.js"></script>
+</dom-module>
diff --git a/rv-reviewers/rv-filter-section.js b/rv-reviewers/rv-filter-section.js
new file mode 100644
index 0000000..0ca36dc
--- /dev/null
+++ b/rv-reviewers/rv-filter-section.js
@@ -0,0 +1,98 @@
+// Copyright (C) 2019 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() {
+ Polymer({
+ is: 'rv-filter-section',
+
+ properties: {
+ pluginRestApi: Object,
+ reviewers: Array,
+ filter: String,
+ canModifyConfig: Boolean,
+ _originalFilter: String,
+ _editingReviewer: {
+ type: Boolean,
+ value: false,
+ },
+ reviewersUrl: String,
+ },
+
+ attached() {
+ this._updateSection();
+ },
+
+ _updateSection() {
+ this._originalFilter = this.filter;
+ },
+
+ _computeEditing(filter, _originalFilter) {
+ if (_originalFilter === '') {
+ return true;
+ }
+ return filter === '';
+ },
+
+ _computeCancelHidden(filter, _originalFilter) {
+ return !this._computeEditing(filter, _originalFilter);
+ },
+
+ _computeAddBtnHidden(canModifyConfig, editingReviewer) {
+ return !(canModifyConfig && !editingReviewer);
+ },
+
+ _computeFilterInputDisabled(canModifyConfig, originalFilter) {
+ return !canModifyConfig || originalFilter !== '';
+ },
+
+ _handleCancel() {
+ this.remove();
+ },
+
+ _handleReviewerDeleted(e) {
+ if (e.detail.editing) {
+ this.reviewers.pop();
+ this._editingReviewer = false;
+ } else {
+ const index = e.model.index;
+ const deleted = this.reviewers[index];
+ this._putReviewer(deleted, 'DELETE');
+ }
+ },
+
+ _handleReviewerAdded(e) {
+ this._editingReviewer = false;
+ this._putReviewer(e.detail.reviewer, 'ADD').catch(err => {
+ this.fire('show-alert', {message: err});
+ throw err;
+ });
+ },
+
+ _putReviewer(reviewer, action) {
+ return this.pluginRestApi.put(this.reviewersUrl, {
+ action,
+ reviewer,
+ filter: this.filter,
+ }).then(result => {
+ const detail = {result};
+ this.dispatchEvent(
+ new CustomEvent('reviewer-changed', {detail, bubbles: true}));
+ });
+ },
+
+ _handleAddReviewer() {
+ this.push('reviewers', '');
+ this._editingReviewer = true;
+ },
+ });
+})();
diff --git a/rv-reviewers/rv-reviewer.html b/rv-reviewers/rv-reviewer.html
new file mode 100644
index 0000000..339eff7
--- /dev/null
+++ b/rv-reviewers/rv-reviewer.html
@@ -0,0 +1,80 @@
+<!--
+@license
+Copyright (C) 2019 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.
+-->
+<dom-module id="rv-reviewer">
+ <template>
+ <style include="shared-styles">
+ #editReviewerInput {
+ display: block;
+ width: 250px;
+ }
+ .reviewerRow {
+ align-items: center;
+ display: flex;
+ }
+ #reviewerHeader,
+ #editReviewerInput,
+ #deleteCancelBtn,
+ #addBtn,
+ #reviewerField {
+ margin-left: 3px;
+ }
+ #reviewerField {
+ width: 250px;
+ text-indent: 1px;
+ border: 1px solid var(--border-color);
+ }
+ </style>
+ <style include="gr-form-styles"></style>
+ <div class="reviewerRow">
+ <h4 id="reviewerHeader">Reviewer:</h4>
+ <template is="dom-if" if="[[_computeEditing(reviewer, _originalReviewer)]]">
+ <span class="value">
+ <!--
+ TODO:
+ Investigate wether we could reuse gr-account-list.
+ If the REST API returns AccountInfo instead of an account
+ identifier String we should be able to use gr-account-list(size=1)
+ for all reviewers, including those who are non-editable
+ (#reviewerField below) and allign the plugin with how accounts
+ are displayed in core Gerrit's UI.
+ -->
+ <gr-autocomplete
+ id="editReviewerInput"
+ text="{{reviewer}}"
+ value="{{_reviewerSearchId}}"
+ query="[[_queryReviewers]]"
+ placeholder="Name Or Email"
+ disabled="[[_computeReviewerDisabled(reviewer, _originalReviewer)]]">
+ </gr-autocomplete>
+ </span>
+ </template>
+ <template is="dom-if" if="[[!_computeEditing(reviewer, _originalReviewer)]]">
+ <td id="reviewerField">[[reviewer]]</td>
+ </template>
+ <gr-button
+ id="deleteCancelBtn"
+ on-tap="_handleDeleteCancel"
+ hidden$="[[_computeHideDeleteButton(canModifyConfig)]]"
+ >[[_computeDeleteCancel(reviewer, _originalReviewer)]]</gr-button>
+ <gr-button
+ id="addBtn"
+ on-tap="_handleAddReviewer"
+ hidden$="[[_computeHideAddButton(reviewer, _originalReviewer)]]">Add</gr-button>
+ </div> <!-- reviewerRow -->
+ </template>
+ <script src="./rv-reviewer.js"></script>
+</dom-module>
diff --git a/rv-reviewers/rv-reviewer.js b/rv-reviewers/rv-reviewer.js
new file mode 100644
index 0000000..a8da113
--- /dev/null
+++ b/rv-reviewers/rv-reviewer.js
@@ -0,0 +1,119 @@
+// Copyright (C) 2019 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() {
+ Polymer({
+ is: 'rv-reviewer',
+
+ properties: {
+ canModifyConfig: Boolean,
+ pluginRestAPi: Object,
+ reviewer: String,
+ _reviewerSearchId: String,
+ _queryReviewers: {
+ type: Function,
+ value() {
+ return this._getAccountSuggestions.bind(this);
+ },
+ },
+ _originalReviewer: String,
+ _deleted: Boolean,
+ _editing: {
+ type: Boolean,
+ computed: '_computeEditing(reviewer, _originalReviewer)',
+ },
+ },
+
+ attached() {
+ this._originalReviewer = this.reviewer;
+ },
+
+ _computeReviewerDisabled(reviewer, _originalReviewer) {
+ return !this._computeEditing(reviewer, _originalReviewer);
+ },
+
+ _computeEditing(reviewer, _originalReviewer) {
+ if (_originalReviewer === '') {
+ return true;
+ }
+ return reviewer === '';
+ },
+
+ _computeDeleteCancel(reviewer, _originalReviewer) {
+ return this._computeEditing(reviewer, _originalReviewer) ?
+ 'Cancel' : 'Delete';
+ },
+
+ _computeHideAddButton(reviewer, _originalReviewer) {
+ return !(this._computeEditing(reviewer, _originalReviewer)
+ && this._reviewerSearchId);
+ },
+
+ _computeHideDeleteButton(canModifyConfig) {
+ return !canModifyConfig;
+ },
+
+ _getAccountSuggestions(input) {
+ if (input.length === 0) { return Promise.resolve([]); }
+ return this._getSuggestedAccounts(
+ input).then(accounts => {
+ const accountSuggestions = [];
+ let nameAndEmail;
+ let value;
+ if (!accounts) { return []; }
+ for (const key in accounts) {
+ if (!accounts.hasOwnProperty(key)) { continue; }
+ if (accounts[key].email) {
+ nameAndEmail = accounts[key].name +
+ ' <' + accounts[key].email + '>';
+ } else {
+ nameAndEmail = accounts[key].name;
+ }
+ if (accounts[key].username) {
+ value = accounts[key].username;
+ } else if (accounts[key].email) {
+ value = accounts[key].email;
+ } else {
+ value = accounts[key]._account_id;
+ }
+ accountSuggestions.push({
+ name: nameAndEmail,
+ value,
+ });
+ }
+ return accountSuggestions;
+ });
+ },
+
+ _getSuggestedAccounts(input) {
+ const suggestUrl = `/accounts/?suggest&q=${input}`;
+ return this.pluginRestApi.get(suggestUrl);
+ },
+
+ _handleDeleteCancel() {
+ const detail = {editing: this._editing};
+ if (this._editing) {
+ this.remove();
+ }
+ this.dispatchEvent(
+ new CustomEvent('reviewer-deleted', {detail, bubbles: true}));
+ },
+
+ _handleAddReviewer() {
+ const detail = {reviewer: this._reviewerSearchId};
+ this._originalReviewer = this.reviewer;
+ this.dispatchEvent(
+ new CustomEvent('reviewer-added', {detail, bubbles: true}));
+ },
+ });
+})();
diff --git a/rv-reviewers/rv-reviewers.html b/rv-reviewers/rv-reviewers.html
new file mode 100644
index 0000000..dcf890d
--- /dev/null
+++ b/rv-reviewers/rv-reviewers.html
@@ -0,0 +1,40 @@
+<!--
+@license
+Copyright (C) 2019 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="./rv-edit-screen.html">
+
+<dom-module id="rv-reviewers">
+ <template>
+ <style include="shared-styles">
+ #rvScreenOverlay {
+ width: 50em;
+ }
+ </style>
+ <gr-repo-command
+ title="Reviewers Config"
+ on-command-tap="_handleCommandTap">
+ </gr-repo-command>
+ <gr-overlay id="rvScreenOverlay" with-backdrop>
+ <rv-edit-screen
+ plugin-rest-api="[[pluginRestApi]]"
+ repo-name="[[repoName]]"
+ loading="[[_loading]]"
+ can-modify-config="[[_canModifyConfig]]"
+ on-close="_handleRvEditScreenClose"></rv-edit-screen>
+ </gr-overlay>
+ </template>
+ <script src="./rv-reviewers.js"></script>
+</dom-module>
diff --git a/rv-reviewers/rv-reviewers.js b/rv-reviewers/rv-reviewers.js
new file mode 100644
index 0000000..e40e03a
--- /dev/null
+++ b/rv-reviewers/rv-reviewers.js
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 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() {
+ Polymer({
+ is: 'rv-reviewers',
+
+ properties: {
+ pluginRestApi: Object,
+ repoName: String,
+ _canModifyConfig: {
+ type: Boolean,
+ computed: '_computeCanModifyConfig(_isOwner, _hasModifyCapability)',
+ },
+ _loading: {
+ type: Boolean,
+ value: true,
+ },
+ _isOwner: {
+ type: Boolean,
+ value: false,
+ },
+ _hasModifyCapability: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ attached() {
+ this.pluginRestApi = this.plugin.restApi();
+ this._setCanModifyConfig();
+ },
+
+ _handleCommandTap() {
+ this.$.rvScreenOverlay.open();
+ },
+
+ _handleRvEditScreenClose() {
+ this.$.rvScreenOverlay.close();
+ },
+
+ _setCanModifyConfig() {
+ const promises = [];
+ promises.push(this._getRepoAccess(this.repoName).then( access => {
+ if (access && access[this.repoName] && access[this.repoName].is_owner) {
+ this._isOwner = true;
+ }
+ }));
+ promises.push(this._getCapabilities().then(capabilities => {
+ if (capabilities['reviewers-modifyReviewersConfig']) {
+ this._hasModifyCapability = true;
+ }
+ }));
+ Promise.all(promises).then(() => {
+ this._loading = false;
+ });
+ },
+
+ _computeCanModifyConfig(isOwner, hasModifyCapability) {
+ return isOwner || hasModifyCapability;
+ },
+
+ _getRepoAccess(repoName) {
+ return this.pluginRestApi.get(
+ '/access/?project=' + encodeURIComponent(repoName));
+ },
+
+ _getCapabilities() {
+ return this.pluginRestApi.get('/accounts/self/capabilities');
+ },
+ });
+})();
diff --git a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
index 076040b..efc3614 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/reviewers/Module.java
@@ -25,6 +25,8 @@
import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.RestApiModule;
+import com.google.gerrit.extensions.webui.JavaScriptPlugin;
+import com.google.gerrit.extensions.webui.WebUiPlugin;
import com.google.gerrit.server.change.ReviewerSuggestion;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
@@ -78,5 +80,13 @@
}
});
}
+ install(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ DynamicSet.bind(binder(), WebUiPlugin.class)
+ .toInstance(new JavaScriptPlugin("rv-reviewers.html"));
+ }
+ });
}
}
diff --git a/tools/bzl/genrule2.bzl b/tools/bzl/genrule2.bzl
new file mode 100644
index 0000000..61c4e18
--- /dev/null
+++ b/tools/bzl/genrule2.bzl
@@ -0,0 +1,3 @@
+load("@com_googlesource_gerrit_bazlets//tools:genrule2.bzl", _genrule2 = "genrule2")
+
+genrule2 = _genrule2
diff --git a/tools/bzl/js.bzl b/tools/bzl/js.bzl
new file mode 100644
index 0000000..0f9e367
--- /dev/null
+++ b/tools/bzl/js.bzl
@@ -0,0 +1,3 @@
+load("@com_googlesource_gerrit_bazlets//tools:js.bzl", _polygerrit_plugin = "polygerrit_plugin")
+
+polygerrit_plugin = _polygerrit_plugin