From 05f2ca53b876b7fbb69e3ada0dc21f2d0a309644 Mon Sep 17 00:00:00 2001 From: Eliot Berriot <contact@eliotberriot.com> Date: Tue, 11 Jun 2019 13:41:56 +0200 Subject: [PATCH] Fix #814: Added copy-to-clipboard button with Subsonic password input --- changes/changelog.d/814.enhancement | 1 + .../src/components/auth/SubsonicTokenForm.vue | 11 ++++++-- front/src/components/forms/PasswordInput.vue | 28 +++++++++++++++++-- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 changes/changelog.d/814.enhancement diff --git a/changes/changelog.d/814.enhancement b/changes/changelog.d/814.enhancement new file mode 100644 index 0000000000..c93b1983c9 --- /dev/null +++ b/changes/changelog.d/814.enhancement @@ -0,0 +1 @@ +Added copy-to-clipboard button with Subsonic password input (#814) diff --git a/front/src/components/auth/SubsonicTokenForm.vue b/front/src/components/auth/SubsonicTokenForm.vue index 0184074e29..fdd9f5e107 100644 --- a/front/src/components/auth/SubsonicTokenForm.vue +++ b/front/src/components/auth/SubsonicTokenForm.vue @@ -24,7 +24,12 @@ </div> <template v-if="subsonicEnabled"> <div v-if="token" class="field"> - <password-input v-model="token" /> + <password-input + ref="passwordInput" + v-model="token" + :key="token" + :copy-button="true" + :default-show="showToken"/> </div> <dangerous-button v-if="token" @@ -69,7 +74,8 @@ export default { errors: [], success: false, isLoading: false, - successMessage: '' + successMessage: '', + showToken: false } }, created () { @@ -98,6 +104,7 @@ export default { let self = this let url = `users/users/${this.$store.state.auth.username}/subsonic-token/` return axios.post(url, {}).then(response => { + self.showToken = true self.token = response.data['subsonic_api_token'] self.isLoading = false self.success = true diff --git a/front/src/components/forms/PasswordInput.vue b/front/src/components/forms/PasswordInput.vue index d57e3017f3..702be4f66a 100644 --- a/front/src/components/forms/PasswordInput.vue +++ b/front/src/components/forms/PasswordInput.vue @@ -10,20 +10,37 @@ <span @click="showPassword = !showPassword" :title="labels.title" class="ui icon button"> <i class="eye icon"></i> </span> + <button v-if="copyButton" @click.prevent="copy" class="ui icon button" :title="labels.copy"> + <i class="copy icon"></i> + </button> </div> </template> <script> + +function copyStringToClipboard (str) { + // cf https://techoverflow.net/2018/03/30/copying-strings-to-the-clipboard-using-pure-javascript/ + let el = document.createElement('textarea'); + el.value = str; + el.setAttribute('readonly', ''); + el.style = {position: 'absolute', left: '-9999px'}; + document.body.appendChild(el); + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); +} + export default { - props: ['value', 'index'], + props: ['value', 'index', 'defaultShow', 'copyButton'], data () { return { - showPassword: false + showPassword: this.defaultShow || false, } }, computed: { labels () { return { - title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password') + title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password'), + copy: this.$pgettext('*/*/Button.Label/Short, Verb', 'Copy') } }, passwordInputType () { @@ -32,6 +49,11 @@ export default { } return 'password' } + }, + methods: { + copy () { + copyStringToClipboard(this.value) + } } } </script> -- GitLab