Merge "Remove unused property"
diff --git a/java/com/google/gerrit/server/plugins/AutoRegisterModules.java b/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
index fde61ff..9d93ed2 100644
--- a/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
+++ b/java/com/google/gerrit/server/plugins/AutoRegisterModules.java
@@ -158,7 +158,7 @@
return;
}
- if (is("org.apache.sshd.server.Command", clazz)) {
+ if (is("org.apache.sshd.server.command.Command", clazz)) {
sshGen.export(export, clazz);
} else if (is("javax.servlet.http.HttpServlet", clazz)) {
httpGen.export(export, clazz);
diff --git a/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java b/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
index c032c46..87e1ca9 100644
--- a/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
+++ b/java/com/google/gerrit/server/plugins/PluginGuiceEnvironment.java
@@ -589,7 +589,7 @@
return false;
}
- if (is("org.apache.sshd.server.Command", type)) {
+ if (is("org.apache.sshd.server.command.Command", type)) {
return false;
}
diff --git a/javatests/com/google/gerrit/server/BUILD b/javatests/com/google/gerrit/server/BUILD
index 60d9d69..248c7d1 100644
--- a/javatests/com/google/gerrit/server/BUILD
+++ b/javatests/com/google/gerrit/server/BUILD
@@ -63,6 +63,7 @@
"//java/com/google/gerrit/server/schema",
"//java/com/google/gerrit/server/schema/testing",
"//java/com/google/gerrit/server/util/time",
+ "//java/com/google/gerrit/sshd",
"//java/com/google/gerrit/testing:assertable-executor",
"//java/com/google/gerrit/testing:gerrit-test-util",
"//java/com/google/gerrit/truth",
diff --git a/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java b/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java
new file mode 100644
index 0000000..55c9bc3
--- /dev/null
+++ b/javatests/com/google/gerrit/server/plugins/AutoRegisterModulesTest.java
@@ -0,0 +1,101 @@
+// Copyright (C) 2020 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.
+
+package com.google.gerrit.server.plugins;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Lists;
+import com.google.gerrit.extensions.annotations.Export;
+import com.google.gerrit.extensions.annotations.Listen;
+import com.google.gerrit.sshd.SshCommand;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.jar.Manifest;
+import org.junit.Test;
+
+public class AutoRegisterModulesTest {
+
+ @Test
+ public void shouldRegisterSshCommand() throws InvalidPluginException {
+ ModuleGenerator sshModule = mock(ModuleGenerator.class);
+ PluginGuiceEnvironment env = mock(PluginGuiceEnvironment.class);
+
+ when(env.hasSshModule()).thenReturn(true);
+ when(env.newSshModuleGenerator()).thenReturn(sshModule);
+
+ PluginContentScanner scanner = new TestPluginContextScanner();
+ ClassLoader classLoader = this.getClass().getClassLoader();
+
+ AutoRegisterModules objectUnderTest =
+ new AutoRegisterModules("test_plugin_name", env, scanner, classLoader);
+ objectUnderTest.discover();
+
+ verify(sshModule).setPluginName("test_plugin_name");
+ verify(sshModule).export(any(Export.class), eq(TestSshCommand.class));
+ }
+
+ @Export(value = "test")
+ public static class TestSshCommand extends SshCommand {
+ @Override
+ protected void run() throws UnloggedFailure, Failure, Exception {}
+ }
+
+ private static class TestPluginContextScanner implements PluginContentScanner {
+
+ @Override
+ public Manifest getManifest() throws IOException {
+ return null;
+ }
+
+ @Override
+ public Map<Class<? extends Annotation>, Iterable<ExtensionMetaData>> scan(
+ String pluginName, Iterable<Class<? extends Annotation>> annotations)
+ throws InvalidPluginException {
+ Map<Class<? extends Annotation>, Iterable<ExtensionMetaData>> extensions = new HashMap<>();
+ extensions.put(
+ Export.class,
+ Lists.newArrayList(
+ new ExtensionMetaData(
+ "com.google.gerrit.server.plugins.AutoRegisterModulesTest$TestSshCommand",
+ "com.google.gerrit.extensions.annotations.Export")));
+ extensions.put(Listen.class, Lists.newArrayList());
+ return extensions;
+ }
+
+ @Override
+ public Optional<PluginEntry> getEntry(String resourcePath) throws IOException {
+ return null;
+ }
+
+ @Override
+ public InputStream getInputStream(PluginEntry entry) throws IOException {
+ return null;
+ }
+
+ @Override
+ public Enumeration<PluginEntry> entries() {
+ return null;
+ }
+ }
+}
diff --git a/polygerrit-ui/app/.eslintrc.js b/polygerrit-ui/app/.eslintrc.js
index ab9732a..fc53dbf 100644
--- a/polygerrit-ui/app/.eslintrc.js
+++ b/polygerrit-ui/app/.eslintrc.js
@@ -206,6 +206,7 @@
"stub": "readonly",
"suite": "readonly",
"suiteSetup": "readonly",
+ "suiteTeardown": "readonly",
"teardown": "readonly",
"test": "readonly",
"fixtureFromElement": "readonly",
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 096c665..bab00b0 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -18,7 +18,7 @@
],
),
outs = ["polygerrit_ui.zip"],
- entry_point = "elements/gr-app.html",
+ entry_point = "elements/gr-app.js",
)
filegroup(
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
deleted file mode 100644
index 61d7bac..0000000
--- a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.html
+++ /dev/null
@@ -1,74 +0,0 @@
-<!DOCTYPE html>
-<!--
-@license
-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">
-<meta charset="utf-8">
-<title>base-url-behavior</title>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script>
-
-<script src="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script>
-<script src="/components/wct-browser-legacy/browser.js"></script>
-<script type="module">
-import '../../test/common-test-setup.js';
-/** @type {string} */
-window.CANONICAL_PATH = '/r';
-</script>
-<test-fixture id="basic">
- <template>
- <test-element></test-element>
- </template>
-</test-fixture>
-
-<test-fixture id="within-overlay">
- <template>
- <gr-overlay>
- <test-element></test-element>
- </gr-overlay>
- </template>
-</test-fixture>
-
-<script type="module">
-import '../../test/common-test-setup.js';
-import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
-import {BaseUrlBehavior} from './base-url-behavior.js';
-suite('base-url-behavior tests', () => {
- let element;
- // eslint-disable-next-line no-unused-vars
- let overlay;
-
- suiteSetup(() => {
- // Define a Polymer element that uses this behavior.
- Polymer({
- is: 'test-element',
- behaviors: [
- BaseUrlBehavior,
- ],
- });
- });
-
- setup(() => {
- element = fixture('basic');
- overlay = fixture('within-overlay');
- });
-
- test('getBaseUrl', () => {
- assert.deepEqual(element.getBaseUrl(), '/r');
- });
-});
-</script>
diff --git a/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js
new file mode 100644
index 0000000..44173323
--- /dev/null
+++ b/polygerrit-ui/app/behaviors/base-url-behavior/base-url-behavior_test.js
@@ -0,0 +1,51 @@
+/**
+ * @license
+ * 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.
+ */
+
+import '../../test/common-test-setup-karma.js';
+import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
+import {BaseUrlBehavior} from './base-url-behavior.js';
+
+const basicFixture = fixtureFromElement('test-element');
+
+suite('base-url-behavior tests', () => {
+ let element;
+ let originialCanonicalPath;
+
+ suiteSetup(() => {
+ originialCanonicalPath = window.CANONICAL_PATH;
+ window.CANONICAL_PATH = '/r';
+ // Define a Polymer element that uses this behavior.
+ Polymer({
+ is: 'test-element',
+ behaviors: [
+ BaseUrlBehavior,
+ ],
+ });
+ });
+
+ suiteTeardown(() => {
+ window.CANONICAL_PATH = originialCanonicalPath;
+ });
+
+ setup(() => {
+ element = basicFixture.instantiate();
+ });
+
+ test('getBaseUrl', () => {
+ assert.deepEqual(element.getBaseUrl(), '/r');
+ });
+});
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
index d25ee76..1aa3e4b 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission.js
@@ -314,6 +314,13 @@
return RANGE_NAMES.includes(name.toUpperCase());
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapExclusiveToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrPermission.is, GrPermission);
diff --git a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
index ef4f1da..ed4f64a 100644
--- a/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-permission/gr-permission_html.js
@@ -93,6 +93,7 @@
checked="{{permission.value.exclusive}}"
on-change="_handleValueChange"
disabled$="[[!editing]]"
+ on-tap="_onTapExclusiveToggle"
></paper-toggle-button
>Exclusive
</template>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
index a70aa11..fba5e4e 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config.js
@@ -150,6 +150,13 @@
this.dispatchEvent(new CustomEvent(
this.PLUGIN_CONFIG_CHANGED, {detail, bubbles: true, composed: true}));
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapPluginBoolean(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrRepoPluginConfig.is, GrRepoPluginConfig);
diff --git a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
index 80d77d6..ee633463 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
+++ b/polygerrit-ui/app/elements/admin/gr-repo-plugin-config/gr-repo-plugin-config_html.js
@@ -63,6 +63,7 @@
on-change="_handleBooleanChange"
data-option-key$="[[option._key]]"
disabled$="[[_computeDisabled(option.info.editable)]]"
+ on-tap="_onTapPluginBoolean"
></paper-toggle-button>
</template>
<template is="dom-if" if="[[_isList(option.info.type)]]">
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
index fe0298a..51b4767 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item.js
@@ -110,12 +110,6 @@
});
}
- _handleContentClick(e) {
- e.preventDefault();
- e.stopPropagation();
- GerritNav.navigateToChange(this.change);
- }
-
_computeChangeURL(change) {
return GerritNav.getUrlForChange(change);
}
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
index d2ab2c6..8c65473 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-item/gr-change-list-item_html.js
@@ -44,7 +44,13 @@
text-overflow: ellipsis;
white-space: nowrap;
width: 100%;
- cursor: pointer;
+ }
+ .content a {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ width: 100%;
}
.comments,
.reviewers {
@@ -126,7 +132,7 @@
hidden$="[[isColumnHidden('Subject', visibleChangeTableColumns)]]"
>
<div class="container">
- <div class="content" on-click="_handleContentClick">
+ <div class="content">
<a title$="[[change.subject]]" href$="[[changeURL]]">
[[change.subject]]
</a>
@@ -154,7 +160,7 @@
hidden$="[[isColumnHidden('Owner', visibleChangeTableColumns)]]"
>
<gr-account-link
- show-attention
+ highlight-attention
change="[[change]]"
account="[[change.owner]]"
></gr-account-link>
@@ -186,7 +192,7 @@
<gr-account-link
hide-avatar=""
hide-status=""
- show-attention
+ highlight-attention
change="[[change]]"
account="[[reviewer]]"
></gr-account-link
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
index ca176be..7d84835 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.js
@@ -108,7 +108,11 @@
<section>
<span class="title">Owner</span>
<span class="value">
- <gr-account-link account="[[change.owner]]"></gr-account-link>
+ <gr-account-link
+ account="[[change.owner]]"
+ change="[[change]]"
+ highlight-attention
+ ></gr-account-link>
<template is="dom-if" if="[[_pushCertificateValidation]]">
<gr-tooltip-content
has-tooltip=""
@@ -128,6 +132,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.UPLOADER)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
@@ -136,6 +142,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.AUTHOR)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
@@ -144,6 +152,8 @@
<span class="value">
<gr-account-link
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.COMMITTER)]]"
+ change="[[change]]"
+ highlight-attention
></gr-account-link>
</span>
</section>
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
index ae3a7d2..6e65a19 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental.js
@@ -420,6 +420,13 @@
}
return extremes;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapShowAllActivityToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrMessagesListExperimental.is,
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
index 6d3a064..212de59 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list-experimental_html.js
@@ -74,6 +74,7 @@
checked="{{_showAllActivity}}"
aria-labelledby="showAllEntriesLabel"
role="switch"
+ on-tap="_onTapShowAllActivityToggle"
></paper-toggle-button>
<div id="showAllEntriesLabel">
<span>Show all entries</span>
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
index adf9fd3..1ee9a1e 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list.js
@@ -464,6 +464,13 @@
}
return extremes;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapHideAutomated(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrMessagesList.is, GrMessagesList);
diff --git a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
index 5adfc53..2636a54 100644
--- a/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-messages-list/gr-messages-list_html.js
@@ -81,8 +81,9 @@
checked="{{_hideAutomated}}"
aria-labelledby="onlyCommentsLabel"
role="switch"
- ></paper-toggle-button
- ><span id="onlyCommentsLabel">Only comments</span>
+ on-tap="_onTapHideAutomated"
+ ></paper-toggle-button>
+ <span id="onlyCommentsLabel">Only comments</span>
<span class="transparent separator"></span>
</span>
<gr-button
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
index 93926cf..13a41ed 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.js
@@ -43,7 +43,9 @@
<gr-account-chip
class="reviewer"
account="[[reviewer]]"
+ change="[[change]]"
on-remove="_handleRemove"
+ highlight-attention
voteable-text="[[_computeVoteableText(reviewer, change)]]"
removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]"
>
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
index bd91990..28a8d9a 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list.js
@@ -296,6 +296,13 @@
_isOnParent(side) {
return !!side;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapUnresolvedToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrThreadList.is, GrThreadList);
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
index bb87db8..80983ca 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.js
@@ -61,14 +61,20 @@
<template is="dom-if" if="[[!hideToggleButtons]]">
<div class="header">
<div class="toggleItem">
- <paper-toggle-button id="unresolvedToggle" checked="{{_unresolvedOnly}}"
+ <paper-toggle-button
+ id="unresolvedToggle"
+ checked="{{_unresolvedOnly}}"
+ on-tap="_onTapUnresolvedToggle"
>Only unresolved threads</paper-toggle-button
>
</div>
<div
class$="toggleItem draftToggle [[_computeShowDraftToggle(loggedIn)]]"
>
- <paper-toggle-button id="draftToggle" checked="{{_draftsOnly}}"
+ <paper-toggle-button
+ id="draftToggle"
+ checked="{{_draftsOnly}}"
+ on-tap="_onTapUnresolvedToggle"
>Only threads with drafts</paper-toggle-button
>
</div>
diff --git a/polygerrit-ui/app/elements/gr-app-init.js b/polygerrit-ui/app/elements/gr-app-init.js
index 780e64a..ea10ce8 100644
--- a/polygerrit-ui/app/elements/gr-app-init.js
+++ b/polygerrit-ui/app/elements/gr-app-init.js
@@ -20,7 +20,6 @@
if (!window.Polymer) {
window.Polymer = {
- passiveTouchGestures: true,
lazyRegister: true,
};
}
diff --git a/polygerrit-ui/app/elements/gr-app.html b/polygerrit-ui/app/elements/gr-app.html
deleted file mode 100644
index 1483f7a..0000000
--- a/polygerrit-ui/app/elements/gr-app.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src='./gr-app.js' type='module'></script>
diff --git a/polygerrit-ui/app/elements/gr-app.js b/polygerrit-ui/app/elements/gr-app.js
index 1300955..e0e7fa9 100644
--- a/polygerrit-ui/app/elements/gr-app.js
+++ b/polygerrit-ui/app/elements/gr-app.js
@@ -26,8 +26,9 @@
* on older touch device.
* See https://github.com/Polymer/polymer/issues/5289
*/
-import {setCancelSyntheticClickEvents} from '@polymer/polymer/lib/utils/settings.js';
+import {setPassiveTouchGestures, setCancelSyntheticClickEvents} from '@polymer/polymer/lib/utils/settings.js';
setCancelSyntheticClickEvents(false);
+setPassiveTouchGestures(true);
import 'polymer-resin/standalone/polymer-resin.js';
import {initGlobalVariables} from './gr-app-global-var-init.js';
diff --git a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
index 4822163..93cbcf5 100644
--- a/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
+++ b/polygerrit-ui/app/elements/plugins/gr-dom-hooks/gr-dom-hooks.js
@@ -27,7 +27,12 @@
if (opt_moduleName) {
return endpointName + ' ' + opt_moduleName;
} else {
- return this._plugin.getPluginName() + '-autogenerated-' + endpointName;
+ // lowercase in case plugin's name contains uppercase letters
+ // TODO: this still can not prevent if plugin has invalid char
+ // other than uppercase, but is the first step
+ // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
+ const pluginName = this._plugin.getPluginName() || 'unknown_plugin';
+ return pluginName.toLowerCase() + '-autogenerated-' + endpointName;
}
};
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
index 0e8c68a..3b889c4 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.js
@@ -498,6 +498,13 @@
return false;
}
+
+ /**
+ * Work around a issue on iOS when clicking turns into double tap
+ */
+ _onTapDarkToggle(e) {
+ e.preventDefault();
+ }
}
customElements.define(GrSettingsView.is, GrSettingsView);
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
index e32a551..0e0f86c 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.js
@@ -107,6 +107,7 @@
aria-labelledby="darkThemeToggleLabel"
checked="[[_isDark]]"
on-change="_handleToggleDark"
+ on-tap="_onTapDarkToggle"
></paper-toggle-button>
<div id="darkThemeToggleLabel">Dark theme (alpha)</div>
</div>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
index c74a396..7e40f48 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.js
@@ -48,6 +48,12 @@
static get properties() {
return {
account: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
voteableText: String,
disabled: {
type: Boolean,
@@ -58,7 +64,12 @@
type: Boolean,
value: false,
},
- showAttention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
},
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
index ee19374..7c75488 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.js
@@ -83,7 +83,8 @@
<div class$="container [[_getBackgroundClass(transparentBackground)]]">
<gr-account-link
account="[[account]]"
- show-attention="[[showAttention]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
voteable-text="[[voteableText]]"
>
</gr-account-link>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
index 8c2b7da..844b7f4 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label.js
@@ -44,8 +44,19 @@
* @type {{ name: string, status: string }}
*/
account: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
voteableText: String,
- showAttention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
},
@@ -57,7 +68,10 @@
type: Boolean,
value: false,
},
- _serverConfig: {
+ /**
+ * This is a ServerInfo response object.
+ */
+ _config: {
type: Object,
value: null,
},
@@ -67,8 +81,22 @@
/** @override */
ready() {
super.ready();
- this.$.restAPI.getConfig()
- .then(config => { this._serverConfig = config; });
+ this.$.restAPI.getConfig().then(config => { this._config = config; });
+ }
+
+ get isAttentionSetEnabled() {
+ return !!this._config && !!this._config.change
+ && !!this._config.change.enable_attention_set
+ && !!this.highlightAttention && !!this.change && !!this.account;
+ }
+
+ get hasAttention() {
+ if (!this.isAttentionSetEnabled || !this.change.attention_set) return false;
+ return this.change.attention_set.hasOwnProperty(this.account._account_id);
+ }
+
+ _computeShowAttentionIcon(config, highlightAttention, account, change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
}
_computeName(account, config) {
diff --git a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
index db375c9..12df5fe 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-label/gr-account-label_html.js
@@ -66,19 +66,23 @@
<div class="overlay"></div>
<span>
<gr-hovercard-account
- attention="[[showAttention]]"
account="[[account]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
voteable-text="[[voteableText]]"
>
</gr-hovercard-account>
- <template is="dom-if" if="[[showAttention]]">
+ <template
+ is="dom-if"
+ if="[[_computeShowAttentionIcon(_config, highlightAttention, account, change)]]"
+ >
<iron-icon class="attention" icon="gr-icons:attention"></iron-icon>
</template>
<template is="dom-if" if="[[!hideAvatar]]">
<gr-avatar account="[[account]]" image-size="32"></gr-avatar>
</template>
<span class="text">
- <span class="name">[[_computeName(account, _serverConfig)]]</span>
+ <span class="name">[[_computeName(account, _config)]]</span>
<template is="dom-if" if="[[!hideStatus]]">
<template is="dom-if" if="[[account.status]]">
<iron-icon class="status" icon="gr-icons:calendar"></iron-icon>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
index d7dd88d..3844bea 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link.js
@@ -41,7 +41,18 @@
return {
voteableText: String,
account: Object,
- showAttention: {
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
},
diff --git a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
index ce2dc9e..44afb84 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-account-link/gr-account-link_html.js
@@ -42,10 +42,11 @@
<span>
<a href$="[[_computeOwnerLink(account)]]">
<gr-account-label
- show-attention="[[showAttention]]"
+ account="[[account]]"
+ change="[[change]]"
+ highlight-attention="[[highlightAttention]]"
hide-avatar="[[hideAvatar]]"
hide-status="[[hideStatus]]"
- account="[[account]]"
voteable-text="[[voteableText]]"
>
</gr-account-label>
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
index 49aff7e..ac9bd62 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account.js
@@ -19,7 +19,9 @@
import '../../../styles/shared-styles.js';
import '../gr-avatar/gr-avatar.js';
import '../gr-button/gr-button.js';
+import '../gr-rest-api-interface/gr-rest-api-interface.js';
import {hovercardBehaviorMixin} from '../gr-hovercard/gr-hovercard-behavior.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners.js';
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin.js';
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
@@ -35,15 +37,111 @@
static get properties() {
return {
+ /**
+ * This is an AccountInfo response object.
+ */
account: Object,
+ _selfAccount: Object,
+ /**
+ * Optional ChangeInfo object, typically comes from the change page or
+ * from a row in a list of search results. This is needed for some change
+ * related features like adding the user as a reviewer.
+ */
+ change: Object,
+ /**
+ * Explains which labels the user can vote on and which score they can
+ * give.
+ */
voteableText: String,
- attention: {
+ /**
+ * Should attention set related features be shown in the component? Note
+ * that the information whether the user is in the attention set or not is
+ * part of the ChangeInfo object in the change property.
+ */
+ highlightAttention: {
type: Boolean,
value: false,
- reflectToAttribute: true,
+ },
+ /**
+ * This is a ServerInfo response object.
+ */
+ _config: {
+ type: Object,
+ value: null,
},
};
}
+
+ attached() {
+ super.attached();
+ this.$.restAPI.getConfig().then(config => {
+ this._config = config;
+ });
+ this.$.restAPI.getAccount().then(account => {
+ this._selfAccount = account;
+ });
+ }
+
+ _computeText(account, selfAccount) {
+ if (!account || !selfAccount) return '';
+ return account._account_id === selfAccount._account_id ? 'Your' : 'Their';
+ }
+
+ get isAttentionSetEnabled() {
+ return !!this._config && !!this._config.change
+ && !!this._config.change.enable_attention_set
+ && !!this.highlightAttention && !!this.change && !!this.account;
+ }
+
+ get hasAttention() {
+ if (!this.isAttentionSetEnabled || !this.change.attention_set) return false;
+ return this.change.attention_set.hasOwnProperty(this.account._account_id);
+ }
+
+ _computeShowLabelNeedsAttention(config, highlightAttention, account, change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
+ }
+
+ _computeShowActionAddToAttentionSet(config, highlightAttn, account, change) {
+ return this.isAttentionSetEnabled && !this.hasAttention;
+ }
+
+ _computeShowActionRemoveFromAttentionSet(config, highlightAttention, account,
+ change) {
+ return this.isAttentionSetEnabled && this.hasAttention;
+ }
+
+ _handleClickAddToAttentionSet(e) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Adding user to attention set. Will be reloading ...',
+ dismissOnNavigation: true,
+ },
+ composed: true,
+ bubbles: true,
+ }));
+ this.$.restAPI.addToAttentionSet(this.change._number,
+ this.account._account_id, 'manually added').then(obj => {
+ GerritNav.navigateToChange(this.change);
+ });
+ this.hide();
+ }
+
+ _handleClickRemoveFromAttentionSet(e) {
+ this.dispatchEvent(new CustomEvent('show-alert', {
+ detail: {
+ message: 'Removing user from attention set. Will be reloading ...',
+ dismissOnNavigation: true,
+ },
+ composed: true,
+ bubbles: true,
+ }));
+ this.$.restAPI.removeFromAttentionSet(this.change._number,
+ this.account._account_id, 'manually removed').then(obj => {
+ GerritNav.navigateToChange(this.change);
+ });
+ this.hide();
+ }
}
customElements.define(GrHovercardAccount.is, GrHovercardAccount);
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
index bbf6a96..262b089 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_html.js
@@ -50,17 +50,18 @@
border-top: 1px solid var(--border-color);
padding: var(--spacing-s) var(--spacing-l);
--gr-button: {
- padding: var(--spacing-s) 0;
+ padding: var(--spacing-s) var(--spacing-m);
}
}
- :host(:not([attention])) .attention {
- display: none;
- }
.attention {
background-color: var(--emphasis-color);
}
.attention iron-icon {
+ width: 14px;
+ height: 14px;
vertical-align: top;
+ position: relative;
+ top: 3px;
}
</style>
<div id="container" role="tooltip" tabindex="-1">
@@ -89,10 +90,46 @@
<span class="value">[[voteableText]]</span>
</div>
</template>
- <div class="attention">
- <iron-icon icon="gr-icons:attention"></iron-icon>
- <span>It is this user's turn to take action.</span>
- </div>
+ <template
+ is="dom-if"
+ if="[[_computeShowLabelNeedsAttention(_config, highlightAttention, account, change)]]"
+ >
+ <div class="attention">
+ <iron-icon icon="gr-icons:attention"></iron-icon>
+ <span>
+ [[_computeText(account, _selfAccount)]] turn to take action.
+ </span>
+ </div>
+ </template>
+ <template
+ is="dom-if"
+ if="[[_computeShowActionAddToAttentionSet(_config, highlightAttention, account, change)]]"
+ >
+ <div class="action">
+ <gr-button
+ link=""
+ no-uppercase=""
+ on-click="_handleClickAddToAttentionSet"
+ >
+ Add to attention set
+ </gr-button>
+ </div>
+ </template>
+ <template
+ is="dom-if"
+ if="[[_computeShowActionRemoveFromAttentionSet(_config, highlightAttention, account, change)]]"
+ >
+ <div class="action">
+ <gr-button
+ link=""
+ no-uppercase=""
+ on-click="_handleClickRemoveFromAttentionSet"
+ >
+ Remove from attention set
+ </gr-button>
+ </div>
+ </template>
</template>
</div>
+ <gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
`;
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html
index 884e1b6..a321b43 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account_test.html
@@ -39,6 +39,7 @@
suite('gr-hovercard-account tests', () => {
let element;
+ let sandbox;
const ACCOUNT = {
email: 'kermit@gmail.com',
username: 'kermit',
@@ -47,7 +48,11 @@
};
setup(() => {
+ sandbox = sinon.sandbox.create();
element = fixture('basic');
+ sandbox.stub(element.$.restAPI, 'getAccount').returns(
+ new Promise(resolve => { '2'; })
+ );
element.account = Object.assign({}, ACCOUNT);
element.show({});
flushAsynchronousOperations();
@@ -58,6 +63,14 @@
'Kermit The Frog');
});
+ test('_computeText', () => {
+ let account = {_account_id: '1'};
+ const selfAccount = {_account_id: '1'};
+ assert.equal(element._computeText(account, selfAccount), 'Your');
+ account = {_account_id: '2'};
+ assert.equal(element._computeText(account, selfAccount), 'Their');
+ });
+
test('account status is not shown if the property is not set', () => {
assert.isNull(element.shadowRoot.querySelector('.status'));
});
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
index 1190908..571e49a 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard/gr-hovercard-behavior.js
@@ -186,9 +186,9 @@
* `mouseleave` event on the hovercard's `target` element (as long as the
* user is not hovering over the hovercard).
*
- * @param {Event} e DOM Event (e.g. `mouseleave` event)
+ * @param {Event} opt_e DOM Event (e.g. `mouseleave` event)
*/
- hide(e) {
+ hide(opt_e) {
this._isScheduledToShow = false;
if (!this._isShowing) {
return;
@@ -197,9 +197,11 @@
// If the user is now hovering over the hovercard or the user is returning
// from the hovercard but now hovering over the target (to stop an annoying
// flicker effect), just return.
- if (e.toElement === this ||
- (e.fromElement === this && e.toElement === this._target)) {
- return;
+ if (opt_e) {
+ if (opt_e.toElement === this ||
+ (opt_e.fromElement === this && opt_e.toElement === this._target)) {
+ return;
+ }
}
// Mark that the hovercard is not visible and do not allow focusing
diff --git a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
index de4f12d..963031a 100644
--- a/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
+++ b/polygerrit-ui/app/elements/shared/gr-rest-api-interface/gr-rest-api-interface.js
@@ -2325,6 +2325,26 @@
});
}
+ addToAttentionSet(changeNum, user, reason) {
+ return this._getChangeURLAndSend({
+ changeNum,
+ method: 'POST',
+ endpoint: '/attention',
+ body: {user, reason},
+ reportUrlAsIs: true,
+ });
+ }
+
+ removeFromAttentionSet(changeNum, user, reason) {
+ return this._getChangeURLAndSend({
+ changeNum,
+ method: 'DELETE',
+ endpoint: `/attention/${user}`,
+ anonymizedEndpoint: '/attention/*',
+ body: {reason},
+ });
+ }
+
/**
* @suppress {checkTypes}
* Resulted in error: Promise.prototype.then does not match formal
diff --git a/polygerrit-ui/app/polymer.json b/polygerrit-ui/app/polymer.json
index 411c969..affa7f2 100644
--- a/polygerrit-ui/app/polymer.json
+++ b/polygerrit-ui/app/polymer.json
@@ -1,5 +1,5 @@
{
- "entrypoint": "elements/gr-app.html",
+ "shell": "elements/gr-app.js",
"sources": [
"behaviors/**/*",
"elements/**/*",
diff --git a/polygerrit-ui/app/rules.bzl b/polygerrit-ui/app/rules.bzl
index 5ccf92d..83860d5 100644
--- a/polygerrit-ui/app/rules.bzl
+++ b/polygerrit-ui/app/rules.bzl
@@ -8,10 +8,10 @@
name: rule name
srcs: source files
outs: array with a single item - the output file name
- entry_point: application entry-point
+ entry_point: application js entry-point
"""
- app_name = entry_point.split(".html")[0].split("/").pop() # eg: gr-app
+ app_name = entry_point.split(".js")[0].split("/").pop() # eg: gr-app
native.filegroup(
name = app_name + "-full-src",
@@ -24,7 +24,7 @@
name = app_name + "-bundle-js",
srcs = [app_name + "-full-src"],
config_file = ":rollup.config.js",
- entry_point = "elements/" + app_name + ".js",
+ entry_point = entry_point,
rollup_bin = "//tools/node_tools:rollup-bin",
sourcemap = "hidden",
deps = [
@@ -36,7 +36,6 @@
name = name + "_app_sources",
srcs = [
app_name + "-bundle-js.js",
- entry_point,
],
)
diff --git a/polygerrit-ui/app/test/tests.js b/polygerrit-ui/app/test/tests.js
index 15cf17e..c866a16 100644
--- a/polygerrit-ui/app/test/tests.js
+++ b/polygerrit-ui/app/test/tests.js
@@ -207,7 +207,6 @@
// Behaviors tests.
/* eslint-disable max-len */
const behaviors = [
- 'base-url-behavior/base-url-behavior_test.html',
'docs-url-behavior/docs-url-behavior_test.html',
'dom-util-behavior/dom-util-behavior_test.html',
'keyboard-shortcut-behavior/keyboard-shortcut-behavior_test.html',
diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
index d162714..32ba0bc 100644
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
@@ -139,7 +139,7 @@
// Content between webcomponents-lite and the load of the main app element
// run before polymer-resin is installed so may have security consequences.
// Contact your local security engineer if you have any questions, and
- // CC them on any changes that load content before gr-app.html.
+ // CC them on any changes that load content before gr-app.js.
//
// github.com/Polymer/polymer-resin/blob/master/getting-started.md#integrating
{if $assetsPath and $assetsBundle}