Add copy to clipboard buttons in gr-downlod-dialog
Adds quick copy to clipboard buttons for all commands in the
gr-download-dialog. Also focuses on the first button if it exists.
Otherwise, focuses on download link as it did previously.
Bug: Issue 5603
Change-Id: Ie0968b0779d5382f33a374a1e22801fba2e5fce2
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.html b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.html
index 7c888da..bcd9053 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.html
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.html
@@ -49,8 +49,6 @@
input {
font-family: var(--monospace-font-family);
font-size: inherit;
- margin-bottom: .5em;
- width: 60em;
}
li[selected] gr-button {
color: #000;
@@ -71,6 +69,19 @@
justify-content: space-between;
padding-top: .75em;
}
+ .command {
+ display: flex;
+ flex-wrap: wrap;
+ margin-bottom: .5em;
+ width: 60em;
+ }
+ .command label {
+ flex: 0 0 100%;
+ }
+ .copyCommand {
+ flex-grow: 1;
+ margin-right: .3em;
+ }
.closeButtonContainer {
display: flex;
flex: 1;
@@ -112,10 +123,14 @@
<div class="command">
<label>[[command.title]]</label>
<input is="iron-input"
+ class="copyCommand"
type="text"
bind-value="[[command.command]]"
on-tap="_handleInputTap"
readonly>
+ <gr-button class="copyToClipboard" on-tap="_copyToClipboard">
+ copy
+ </gr-button>
</div>
</template>
</main>
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
index 72425a4..41f6792 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog.js
@@ -51,7 +51,11 @@
],
focus: function() {
- this.$.download.focus();
+ if (this._schemes.length) {
+ this.$$('.copyToClipboard').focus();
+ } else {
+ this.$.download.focus();
+ }
},
getFocusStops: function() {
@@ -162,5 +166,13 @@
this._selectedScheme = schemes.sort()[0];
}
},
+
+ _copyToClipboard: function(e) {
+ e.target.parentElement.querySelector('.copyCommand').select();
+ document.execCommand('copy');
+ getSelection().removeAllRanges();
+ e.target.textContent = 'done';
+ setTimeout(function() { e.target.textContent = 'copy'; }, 1000);
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
index 7d80c09..ce28d4e 100644
--- a/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
+++ b/polygerrit-ui/app/elements/change/gr-download-dialog/gr-download-dialog_test.html
@@ -97,6 +97,45 @@
};
}
+ function getChangeObjectNoFetch() {
+ return {
+ current_revision: '34685798fe548b6d17d1e8e5edc43a26d055cc72',
+ revisions: {
+ '34685798fe548b6d17d1e8e5edc43a26d055cc72': {
+ _number: 1,
+ fetch: {},
+ }
+ }
+ };
+ }
+
+ suite('gr-download-dialog tests with no fetch options', function() {
+ var element;
+
+ setup(function() {
+ element = fixture('basic');
+ element.change = getChangeObjectNoFetch();
+ element.patchNum = 1;
+ element.config = {
+ schemes: {
+ 'anonymous http': {},
+ http: {},
+ repo: {},
+ ssh: {},
+ },
+ archives: ['tgz', 'tar', 'tbz2', 'txz'],
+ };
+ });
+
+ test('focuses on first download link if no copy links', function() {
+ flushAsynchronousOperations();
+ var focusStub = sinon.stub(element.$.download, 'focus');
+ element.focus();
+ assert.isTrue(focusStub.called);
+ focusStub.restore();
+ });
+ });
+
suite('gr-download-dialog tests', function() {
var element;
@@ -115,14 +154,23 @@
};
});
- test('focuses on first download link', function() {
- var focusStub = sinon.stub(element.$.download, 'focus');
+ test('focuses on first copy link', function() {
+ flushAsynchronousOperations();
+ var focusStub = sinon.stub(element.$$('.copyToClipboard'), 'focus');
element.focus();
flushAsynchronousOperations();
assert.isTrue(focusStub.called);
focusStub.restore();
});
+ test('copy to clipboard', function() {
+ flushAsynchronousOperations();
+ var clipboardSpy = sinon.spy(element, '_copyToClipboard');
+ var copyBtn = element.$$('.copyToClipboard');
+ MockInteractions.tap(copyBtn);
+ assert.isTrue(clipboardSpy.called);
+ });
+
test('element visibility', function() {
assert.isFalse(element.$$('ul').hasAttribute('hidden'));
assert.isFalse(element.$$('main').hasAttribute('hidden'));