Merge "Fix gr-edit-controls"
diff --git a/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java b/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
index 3dc5be0..179a3d0 100644
--- a/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
+++ b/java/com/google/gerrit/server/rules/PrologRuleEvaluator.java
@@ -158,6 +158,8 @@
return ruleError("Error looking up change " + cd.getId(), e);
}
+ logger.atFine().log("input approvals: %s", cd.approvals());
+
List<Term> results;
try {
results =
@@ -178,7 +180,9 @@
getSubmitRuleName(), cd.getId(), projectState.getName()));
}
- return resultsToSubmitRecord(getSubmitRule(), results);
+ SubmitRecord submitRecord = resultsToSubmitRecord(getSubmitRule(), results);
+ logger.atFine().log("submit record: %s", submitRecord);
+ return submitRecord;
}
private String getSubmitRuleName() {
@@ -320,6 +324,7 @@
logger.atSevere().withCause(e).log(err);
return createRuleError(DEFAULT_MSG);
}
+ logger.atFine().log("rule error: %s", err);
return createRuleError(err);
}
diff --git a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
index ca68926..07f9a4a 100644
--- a/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-metadata/gr-change-metadata_html.ts
@@ -184,7 +184,7 @@
<gr-account-chip
account="[[change.owner]]"
change="[[change]]"
- highlight-attention
+ highlightAttention
></gr-account-chip>
<template is="dom-if" if="[[_pushCertificateValidation]]">
<gr-tooltip-content
@@ -213,7 +213,7 @@
<gr-account-chip
account="[[_getNonOwnerRole(change, _CHANGE_ROLE.UPLOADER)]]"
change="[[change]]"
- highlight-attention
+ highlightAttention
></gr-account-chip>
</span>
</section>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index 0c55f67..53bdb91 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -677,7 +677,6 @@
);
this.addEventListener('open-fix-preview', e => this._onOpenFixPreview(e));
this.addEventListener('close-fix-preview', e => this._onCloseFixPreview(e));
- window.addEventListener('scroll', this.handleScroll);
document.addEventListener('visibilitychange', this.handleVisibilityChange);
this.addEventListener(EventType.SHOW_PRIMARY_TAB, e =>
@@ -694,7 +693,6 @@
/** @override */
disconnectedCallback() {
this.disconnected$.next();
- window.removeEventListener('scroll', this.handleScroll);
document.removeEventListener(
'visibilitychange',
this.handleVisibilityChange
@@ -1140,14 +1138,6 @@
this._openReplyDialog(target);
}
- readonly handleScroll = () => {
- this.scrollTask = debounce(
- this.scrollTask,
- () => (this.viewState.scrollTop = document.body.scrollTop),
- 150
- );
- };
-
_setShownFiles(e: CustomEvent<{length: number}>) {
this._shownFileCount = e.detail.length;
}
@@ -1284,11 +1274,7 @@
this._sendShowChangeEvent();
setTimeout(() => {
- if (this.viewState.scrollTop) {
- document.documentElement.scrollTop = document.body.scrollTop = this.viewState.scrollTop;
- } else {
- this._maybeScrollToMessage(window.location.hash);
- }
+ this._maybeScrollToMessage(window.location.hash);
this._initialLoadComplete = true;
});
}
@@ -1408,7 +1394,6 @@
_resetFileListViewState() {
this.set('viewState.selectedFileIndex', 0);
- this.set('viewState.scrollTop', 0);
if (
!!this.viewState.changeNum &&
this.viewState.changeNum !== this._changeNum
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
index 5b940a8..c6975e6 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_html.ts
@@ -344,7 +344,7 @@
<span class="headerSubject">[[_change.subject]]</span>
<gr-copy-clipboard
class="changeCopyClipboard"
- hide-input=""
+ hideInput=""
text="[[_computeCopyTextForTitle(_change)]]"
>
</gr-copy-clipboard>
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
index e882920..867b3a7 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
@@ -128,8 +128,6 @@
TestKeyboardShortcutBinder.pop();
});
- const TEST_SCROLL_TOP_PX = 100;
-
const ROBOT_COMMENTS_LIMIT = 10;
// TODO: should have a mock service to generate VALID fake data
@@ -1805,42 +1803,6 @@
assert.isTrue(awaitPluginsLoadedStub.called);
});
- suite('scroll related tests', () => {
- test('document scrolling calls function to set scroll height', done => {
- const originalHeight = document.body.scrollHeight;
- const scrollStub = sinon.stub(element, 'handleScroll').callsFake(() => {
- assert.isTrue(scrollStub.called);
- document.body.style.height = `${originalHeight}px`;
- scrollStub.restore();
- done();
- });
- document.body.style.height = '10000px';
- element.handleScroll();
- });
-
- test('scrollTop is set correctly', async () => {
- element.viewState = {scrollTop: TEST_SCROLL_TOP_PX};
-
- sinon.stub(element, 'loadData').callsFake(() => {
- // When element is reloaded, ensure that the history
- // state has the scrollTop set earlier. This will then
- // be reset.
- assert.isTrue(element.viewState.scrollTop === TEST_SCROLL_TOP_PX);
- return Promise.resolve([]);
- });
-
- // simulate reloading component, which is done when route
- // changes to match a regex of change view type.
- element.params = {...createAppElementChangeViewParams()};
- await flush();
- });
-
- test('scrollTop is reset when new change is loaded', () => {
- element._resetFileListViewState();
- assert.equal(element.viewState.scrollTop, 0);
- });
- });
-
suite('reply dialog tests', () => {
setup(() => {
sinon.stub(element.$.replyDialog, '_draftChanged');
diff --git a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_html.ts b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_html.ts
index 65ca8b5..02fa090 100644
--- a/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-commit-info/gr-commit-info_html.ts
@@ -31,9 +31,9 @@
>[[_computeShortHash(change, commitInfo, serverConfig)]]</a
>
<gr-copy-clipboard
- has-tooltip=""
- button-title="Copy full SHA to clipboard"
- hide-input=""
+ hasTooltip=""
+ buttonTitle="Copy full SHA to clipboard"
+ hideInput=""
text="[[commitInfo.commit]]"
>
</gr-copy-clipboard>
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
index 3b2cacf..4d04744 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_html.ts
@@ -410,7 +410,7 @@
</span>
<gr-file-status-chip file="[[file]]"></gr-file-status-chip>
<gr-copy-clipboard
- hide-input=""
+ hideInput=""
text="[[file.__path]]"
></gr-copy-clipboard>
</a>
@@ -418,7 +418,7 @@
<div class="oldPath" title$="[[file.old_path]]">
[[file.old_path]]
<gr-copy-clipboard
- hide-input=""
+ hideInput=""
text="[[file.old_path]]"
></gr-copy-clipboard>
</div>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
index 25d8517..ca8bf87 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
@@ -66,7 +66,7 @@
account="[[reviewer]]"
change="[[change]]"
on-remove="_handleRemove"
- highlight-attention
+ highlightAttention
voteable-text="[[_computeVoteableText(reviewer, change)]]"
removable="[[_computeCanRemoveReviewer(reviewer, mutable)]]"
>
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.ts
index 354d360..d3f23ad 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_test.ts
@@ -67,7 +67,7 @@
await dialogShown;
});
- test('only show remove for removable reviewers', () => {
+ test('only show remove for removable reviewers', async () => {
element.mutable = true;
element.change = {
...createChange(),
@@ -112,7 +112,7 @@
},
],
};
- flush();
+ await flush();
const chips = element.root!.querySelectorAll('gr-account-chip');
assert.equal(chips.length, 4);
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index c9f0506..ebd143c 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -295,7 +295,6 @@
showDownloadDialog: false,
diffMode: null,
numFilesShown: null,
- scrollTop: 0,
},
changeListView: {
query: null,
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
index ab24168..f4641c2 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_html.ts
@@ -70,9 +70,9 @@
</td>
<td>
<gr-copy-clipboard
- has-tooltip=""
- button-title="Copy GPG public key to clipboard"
- hide-input=""
+ hasTooltip=""
+ buttonTitle="Copy GPG public key to clipboard"
+ hideInput=""
text="[[key.key]]"
>
</gr-copy-clipboard>
diff --git a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_html.ts b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_html.ts
index 549fc93..811b85c 100644
--- a/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-http-password/gr-http-password_html.ts
@@ -78,9 +78,9 @@
<span class="title">New Password:</span>
<span class="value">[[_generatedPassword]]</span>
<gr-copy-clipboard
- has-tooltip=""
- button-title="Copy password to clipboard"
- hide-input=""
+ hasTooltip=""
+ buttonTitle="Copy password to clipboard"
+ hideInput=""
text="[[_generatedPassword]]"
>
</gr-copy-clipboard>
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_html.ts b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_html.ts
index 0bee1d3..e853b58 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_html.ts
@@ -76,9 +76,9 @@
</td>
<td>
<gr-copy-clipboard
- has-tooltip=""
- button-title="Copy SSH public key to clipboard"
- hide-input=""
+ hasTooltip=""
+ buttonTitle="Copy SSH public key to clipboard"
+ hideInput=""
text="[[key.ssh_public_key]]"
>
</gr-copy-clipboard>
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
index dab778b..5436128 100644
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
+++ b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip.ts
@@ -17,19 +17,14 @@
import '../gr-account-link/gr-account-link';
import '../gr-button/gr-button';
import '../gr-icons/gr-icons';
-import '../../../styles/shared-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-account-chip_html';
-import {customElement, property} from '@polymer/decorators';
import {AccountInfo, ChangeInfo} from '../../../types/common';
import {appContext} from '../../../services/app-context';
+import {GrLitElement} from '../../lit/gr-lit-element';
+import {css, customElement, html, property} from 'lit-element';
+import {classMap} from 'lit-html/directives/class-map';
@customElement('gr-account-chip')
-export class GrAccountChip extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
+export class GrAccountChip extends GrLitElement {
/**
* Fired to indicate a key was pressed while this chip was focused.
*
@@ -64,10 +59,10 @@
@property({type: String})
voteableText?: string;
- @property({type: Boolean, reflectToAttribute: true})
+ @property({type: Boolean, reflect: true})
disabled = false;
- @property({type: Boolean, reflectToAttribute: true})
+ @property({type: Boolean, reflect: true})
removable = false;
/**
@@ -78,7 +73,7 @@
@property({type: Boolean})
highlightAttention = false;
- @property({type: Boolean, reflectToAttribute: true})
+ @property({type: Boolean, reflect: true})
showAvatar?: boolean;
@property({type: Boolean})
@@ -86,18 +81,126 @@
private readonly restApiService = appContext.restApiService;
- /** @override */
- ready() {
- super.ready();
+ static get styles() {
+ return [
+ css`
+ :host {
+ display: block;
+ overflow: hidden;
+ }
+ .container {
+ align-items: center;
+ background-color: var(--background-color-primary);
+ /** round */
+ border-radius: var(--account-chip-border-radius, 20px);
+ border: 1px solid var(--border-color);
+ display: inline-flex;
+ padding: 0 1px;
+ }
+ :host:focus {
+ border-color: transparent;
+ box-shadow: none;
+ outline: none;
+ }
+ :host:focus .container,
+ :host:focus gr-button {
+ background: #ccc;
+ }
+ .transparentBackground,
+ gr-button.transparentBackground {
+ background-color: transparent;
+ }
+ :host([disabled]) {
+ opacity: 0.6;
+ pointer-events: none;
+ }
+ iron-icon {
+ height: 1.2rem;
+ width: 1.2rem;
+ }
+ .container gr-account-link::part(gr-account-link-text) {
+ color: var(--deemphasized-text-color);
+ }
+ `,
+ ];
+ }
+
+ render() {
+ // To pass CSS mixins for @apply to Polymer components, they need to appear
+ // in <style> inside the template.
+ const customStyle = html`
+ <style>
+ .container {
+ --account-label-padding-horizontal: 6px;
+ }
+ gr-button.remove {
+ --gr-remove-button-style: {
+ border-top-width: 0;
+ border-right-width: 0;
+ border-bottom-width: 0;
+ border-left-width: 0;
+ color: var(--deemphasized-text-color);
+ font-weight: var(--font-weight-normal);
+ height: 0.6em;
+ line-height: 10px;
+ /* This cancels most of the --account-label-padding-horizontal. */
+ margin-left: -4px;
+ padding: 0 2px 0 0;
+ text-decoration: none;
+ }
+ }
+
+ gr-button.remove:hover,
+ gr-button.remove:focus {
+ --gr-button: {
+ @apply --gr-remove-button-style;
+ }
+ }
+ gr-button.remove {
+ --gr-button: {
+ @apply --gr-remove-button-style;
+ }
+ }
+ </style>
+ `;
+ return html`${customStyle}
+ <div
+ class="${classMap({
+ container: true,
+ transparentBackground: this.transparentBackground,
+ })}"
+ >
+ <gr-account-link
+ .account="${this.account}"
+ .change="${this.change}"
+ ?force-attention=${this.forceAttention}
+ ?highlight-attention=${this.highlightAttention}
+ .voteable-text=${this.voteableText}
+ >
+ </gr-account-link>
+ <gr-button
+ id="remove"
+ link=""
+ ?hidden=${!this.removable}
+ aria-label="Remove"
+ class="${classMap({
+ remove: true,
+ transparentBackground: this.transparentBackground,
+ })}"
+ @click=${this._handleRemoveTap}
+ >
+ <iron-icon icon="gr-icons:close"></iron-icon>
+ </gr-button>
+ </div>`;
+ }
+
+ constructor() {
+ super();
this._getHasAvatars().then(hasAvatars => {
this.showAvatar = hasAvatars;
});
}
- _getBackgroundClass(transparent: boolean) {
- return transparent ? 'transparentBackground' : '';
- }
-
_handleRemoveTap(e: MouseEvent) {
e.preventDefault();
this.dispatchEvent(
diff --git a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.ts b/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.ts
deleted file mode 100644
index 52a5985..0000000
--- a/polygerrit-ui/app/elements/shared/gr-account-chip/gr-account-chip_html.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * @license
- * 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.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style>
- :host {
- display: block;
- overflow: hidden;
- }
- .container {
- align-items: center;
- background-color: var(--background-color-primary);
- /** round */
- border-radius: var(--account-chip-border-radius, 20px);
- border: 1px solid var(--border-color);
- display: inline-flex;
- padding: 0 1px;
-
- --account-label-padding-horizontal: 6px;
- }
- .container gr-account-link::part(gr-account-link-text) {
- color: var(--deemphasized-text-color);
- }
- :host([show-avatar]) .container {
- }
- :host([removable]) .container {
- }
- gr-button.remove {
- --gr-remove-button-style: {
- border-top-width: 0;
- border-right-width: 0;
- border-bottom-width: 0;
- border-left-width: 0;
- color: var(--deemphasized-text-color);
- font-weight: var(--font-weight-normal);
- height: 0.6em;
- line-height: 10px;
- /* This cancels most of the --account-label-padding-horizontal. */
- margin-left: -4px;
- padding: 0 2px 0 0;
- text-decoration: none;
- }
- }
-
- gr-button.remove:hover,
- gr-button.remove:focus {
- --gr-button: {
- @apply --gr-remove-button-style;
- }
- }
- gr-button.remove {
- --gr-button: {
- @apply --gr-remove-button-style;
- }
- }
- :host:focus {
- border-color: transparent;
- box-shadow: none;
- outline: none;
- }
- :host:focus .container,
- :host:focus gr-button {
- background: #ccc;
- }
- .transparentBackground,
- gr-button.transparentBackground {
- background-color: transparent;
- }
- :host([disabled]) {
- opacity: 0.6;
- pointer-events: none;
- }
- iron-icon {
- height: 1.2rem;
- width: 1.2rem;
- }
- </style>
- <div class$="container [[_getBackgroundClass(transparentBackground)]]">
- <gr-account-link
- account="[[account]]"
- change="[[change]]"
- force-attention="[[forceAttention]]"
- highlight-attention="[[highlightAttention]]"
- voteable-text="[[voteableText]]"
- >
- </gr-account-link>
- <gr-button
- id="remove"
- link=""
- hidden$="[[!removable]]"
- hidden=""
- aria-label="Remove"
- class$="remove [[_getBackgroundClass(transparentBackground)]]"
- on-click="_handleRemoveTap"
- >
- <iron-icon icon="gr-icons:close"></iron-icon>
- </gr-button>
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
index 2fe6fed..4a2bcee 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard.ts
@@ -15,16 +15,14 @@
* limitations under the License.
*/
import '@polymer/iron-input/iron-input';
-import '../../../styles/shared-styles';
import '../gr-button/gr-button';
import '../gr-icons/gr-icons';
-import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-copy-clipboard_html';
-import {GrButton} from '../gr-button/gr-button';
-import {customElement, property} from '@polymer/decorators';
import {IronIconElement} from '@polymer/iron-icon';
-import {assertIsDefined} from '../../../utils/common-util';
+import {assertIsDefined, queryAndAssert} from '../../../utils/common-util';
+import {classMap} from 'lit-html/directives/class-map';
+import {css, customElement, html, property} from 'lit-element';
+import {GrLitElement} from '../../lit/gr-lit-element';
+import {GrButton} from '../gr-button/gr-button';
const COPY_TIMEOUT_MS = 1000;
@@ -33,17 +31,8 @@
'gr-copy-clipboard': GrCopyClipboard;
}
}
-
-export interface GrCopyClipboard {
- $: {button: GrButton; icon: IronIconElement; input: HTMLInputElement};
-}
-
@customElement('gr-copy-clipboard')
-export class GrCopyClipboard extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
+export class GrCopyClipboard extends GrLitElement {
@property({type: String})
text: string | undefined;
@@ -56,29 +45,121 @@
@property({type: Boolean})
hideInput = false;
- focusOnCopy() {
- this.$.button.focus();
+ static get styles() {
+ return [
+ css`
+ .text {
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ }
+ .copyText {
+ flex-grow: 1;
+ margin-right: var(--spacing-s);
+ }
+ .hideInput {
+ display: none;
+ }
+ input#input {
+ font-family: var(--monospace-font-family);
+ font-size: var(--font-size-mono);
+ line-height: var(--line-height-mono);
+ width: 100%;
+ }
+ /*
+ * Typically icons are 20px, which is the normal line-height.
+ * The copy icon is too prominent at 20px, so we choose 16px
+ * here, but add 2x2px padding below, so the entire
+ * component should still fit nicely into a normal inline
+ * layout flow.
+ */
+ #icon {
+ height: 16px;
+ width: 16px;
+ }
+ iron-icon {
+ color: var(--deemphasized-text-color);
+ vertical-align: top;
+ }
+ `,
+ ];
}
- _computeInputClass(hideInput: boolean) {
- return hideInput ? 'hideInput' : '';
+ render() {
+ // To pass CSS mixins for @apply to Polymer components, they need to appear
+ // in <style> inside the template.
+ const customStyle = html`
+ <style>
+ iron-icon {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ }
+ gr-button {
+ --gr-button: {
+ padding: 2px;
+ }
+ }
+ </style>
+ `;
+ return html`${customStyle}
+ <div class="text">
+ <iron-input
+ class="copyText"
+ type="text"
+ @click="${this._handleInputClick}"
+ readonly=""
+ bind-value=${this.text}
+ >
+ <input
+ id="input"
+ is="iron-input"
+ class="${classMap({hideInput: this.hideInput})}"
+ type="text"
+ @click="${this._handleInputClick}"
+ readonly=""
+ .value=${this.text}
+ part="text-container-style"
+ />
+ </iron-input>
+ <gr-button
+ id="copy-clipboard-button"
+ link=""
+ ?has-tooltip=${this.hasTooltip}
+ class="copyToClipboard"
+ title="${this.buttonTitle}"
+ @click="${this._copyToClipboard}"
+ aria-label="Click to copy to clipboard"
+ >
+ <iron-icon id="icon" icon="gr-icons:content-copy"></iron-icon>
+ </gr-button>
+ </div> `;
+ }
+
+ focusOnCopy() {
+ queryAndAssert<GrButton>(this, '#copy-clipboard-button').focus();
}
_handleInputClick(e: MouseEvent) {
e.preventDefault();
- ((dom(e) as EventApi).rootTarget as HTMLInputElement).select();
+ const rootTarget = e.composedPath()[0];
+ (rootTarget as HTMLInputElement).select();
}
_copyToClipboard(e: MouseEvent) {
e.preventDefault();
e.stopPropagation();
+ this.text = queryAndAssert<HTMLInputElement>(this, '#input').value;
assertIsDefined(this.text, 'text');
- this.$.icon.icon = 'gr-icons:check';
+ this.iconEl.icon = 'gr-icons:check';
navigator.clipboard.writeText(this.text);
setTimeout(
- () => (this.$.icon.icon = 'gr-icons:content-copy'),
+ () => (this.iconEl.icon = 'gr-icons:content-copy'),
COPY_TIMEOUT_MS
);
}
+
+ private get iconEl(): IronIconElement {
+ return queryAndAssert<IronIconElement>(this, '#icon');
+ }
}
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_html.ts b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_html.ts
deleted file mode 100644
index 3ccc46f..0000000
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_html.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * @license
- * 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.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style>
- .text {
- align-items: center;
- display: flex;
- flex-wrap: wrap;
- }
- .copyText {
- flex-grow: 1;
- margin-right: var(--spacing-s);
- }
- .hideInput {
- display: none;
- }
- input#input {
- font-family: var(--monospace-font-family);
- font-size: var(--font-size-mono);
- line-height: var(--line-height-mono);
- @apply --text-container-style;
- width: 100%;
- }
- /*
- * Typically icons are 20px, which is the normal line-height.
- * The copy icon is too prominent at 20px, so we choose 16px
- * here, but add 2x2px padding below, so the entire
- * component should still fit nicely into a normal inline
- * layout flow.
- */
- #icon {
- height: 16px;
- width: 16px;
- }
- iron-icon {
- color: var(--deemphasized-text-color);
- vertical-align: top;
- --iron-icon-height: 20px;
- --iron-icon-width: 20px;
- }
- gr-button {
- --gr-button: {
- padding: 2px;
- }
- }
- </style>
- <div class="text">
- <iron-input
- class="copyText"
- type="text"
- bind-value="[[text]]"
- on-click="_handleInputClick"
- readonly=""
- >
- <input
- id="input"
- is="iron-input"
- class$="[[_computeInputClass(hideInput)]]"
- type="text"
- bind-value="[[text]]"
- on-click="_handleInputClick"
- readonly=""
- />
- </iron-input>
- <gr-button
- id="button"
- link=""
- has-tooltip="[[hasTooltip]]"
- class="copyToClipboard"
- title="[[buttonTitle]]"
- on-click="_copyToClipboard"
- aria-label="Click to copy to clipboard"
- >
- <iron-icon id="icon" icon="gr-icons:content-copy"></iron-icon>
- </gr-button>
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
index 55b2483..45847d7 100644
--- a/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
+++ b/polygerrit-ui/app/elements/shared/gr-copy-clipboard/gr-copy-clipboard_test.js
@@ -17,7 +17,7 @@
import '../../../test/common-test-setup-karma.js';
import './gr-copy-clipboard.js';
-import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
+import {queryAndAssert} from '../../../test/test-utils.js';
const basicFixture = fixtureFromElement('gr-copy-clipboard');
@@ -32,18 +32,18 @@
});
test('copy to clipboard', () => {
- const clipboardSpy = sinon.spy(element, '_copyToClipboard');
+ const clipboardSpy = sinon.spy(navigator.clipboard, 'writeText');
const copyBtn = element.shadowRoot
.querySelector('.copyToClipboard');
- MockInteractions.tap(copyBtn);
+ MockInteractions.click(copyBtn);
assert.isTrue(clipboardSpy.called);
});
test('focusOnCopy', () => {
element.focusOnCopy();
- assert.deepEqual(dom(element.root).activeElement,
- element.shadowRoot
- .querySelector('.copyToClipboard'));
+ const activeElement = element.shadowRoot.activeElement;
+ const button = element.shadowRoot.querySelector('.copyToClipboard');
+ assert.deepEqual(activeElement, button);
});
test('_handleInputClick', () => {
@@ -58,16 +58,17 @@
assert.equal(inputElement.selectionEnd, element.text.length - 1);
});
- test('hideInput', () => {
+ test('hideInput', async () => {
// iron-input as parent should never be hidden as copy won't work
// on nested hidden elements
const ironInputElement = element.shadowRoot.querySelector('iron-input');
assert.notEqual(getComputedStyle(ironInputElement).display, 'none');
- assert.notEqual(getComputedStyle(element.$.input).display, 'none');
+ const input = queryAndAssert(element, 'input');
+ assert.notEqual(getComputedStyle(input).display, 'none');
element.hideInput = true;
- flush();
- assert.equal(getComputedStyle(element.$.input).display, 'none');
+ await flush();
+ assert.equal(getComputedStyle(input).display, 'none');
});
test('stop events propagation', () => {
diff --git a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
index c163924..18a46a0 100644
--- a/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-dropdown-list/gr-dropdown-list_html.ts
@@ -127,7 +127,7 @@
<span id="triggerText">[[text]]</span>
<gr-copy-clipboard
hidden="[[!showCopyForTriggerText]]"
- hide-input=""
+ hideInput=""
text="[[text]]"
></gr-copy-clipboard>
</gr-button>
diff --git a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_html.ts b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_html.ts
index 6c7f0d8..e43460d 100644
--- a/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_html.ts
+++ b/polygerrit-ui/app/elements/shared/gr-shell-command/gr-shell-command_html.ts
@@ -45,17 +45,15 @@
/* Should roughly match the height of .commandContainer without padding. */
line-height: 26px;
}
- .commandContainer gr-copy-clipboard {
- --text-container-style: {
- border: none;
- }
+ .commandContainer gr-copy-clipboard::part(text-container-style) {
+ border: none;
}
</style>
<label>[[label]]</label>
<div class="commandContainer">
<gr-copy-clipboard
text="[[command]]"
- has-tooltip
+ hasTooltip
button-title="[[tooltip]]"
></gr-copy-clipboard>
</div>
diff --git a/polygerrit-ui/app/types/types.ts b/polygerrit-ui/app/types/types.ts
index fd41cc9..2d4d412 100644
--- a/polygerrit-ui/app/types/types.ts
+++ b/polygerrit-ui/app/types/types.ts
@@ -189,7 +189,6 @@
showDownloadDialog: boolean;
diffMode: DiffViewMode | null;
numFilesShown: number | null;
- scrollTop?: number;
diffViewMode?: boolean;
}