From c3f65d27c8fe7021ae807dec5cb82ae191697b69 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Sat, 13 Apr 2019 12:56:11 +0000 Subject: [webapp/groups] add copy to clipboard button --- webapp/src/components/DataTable.vue | 123 ++++++++++++- webapp/src/components/GroupModuleClientList.vue | 2 +- webapp/src/components/GroupModuleGroupList.vue | 2 +- webapp/src/components/GroupModuleGroupView.vue | 218 ++++++++++++------------ 4 files changed, 231 insertions(+), 114 deletions(-) (limited to 'webapp') diff --git a/webapp/src/components/DataTable.vue b/webapp/src/components/DataTable.vue index a537af3..69656ed 100644 --- a/webapp/src/components/DataTable.vue +++ b/webapp/src/components/DataTable.vue @@ -8,7 +8,12 @@ "regex": "Regex", "caseSensitive": "Case sensitive", "onlyShowSelected": "Selected entries only", - "selected": "selected" + "selected": "selected", + "copyDone": "Copied to Clipboard", + "nothingToCopy": "Nothing to Copy", + "copyHeading": "Copy to Clipboard", + "copy": "Copy", + "close": "Close" }, "de": { "all": "Alle", @@ -18,7 +23,12 @@ "regex": "Regex", "caseSensitive": "Groß-/Kleinschreibung beachten", "onlyShowSelected": "Nur ausgewählte Einträg", - "selected": "ausgewählt" + "selected": "ausgewählt", + "copyDone": "In die Zwischenablage kopiert", + "nothingToCopy": "Nichts zu kopieren", + "copyHeading": "In die Zwischenablage kopieren", + "copy": "Kopieren", + "close": "Schließen" } } @@ -32,7 +42,7 @@ @filter="filteredRows = $event" :selected="value" :items="sortedRows" - :data-keys="headers.filter(h => h.text !== undefined)" + :data-keys="headersWithText" nested-data :regex="regex" :case-sensitive="caseSensitive" @@ -133,6 +143,9 @@ arrow_upward +
+ file_copy +
@@ -158,6 +171,42 @@
{{ $t('noResult') }}
+ + + +
{{ $t('copyHeading') }}
+ + + CSV + JSON + +
+ + + + + + + + {{ $t('close') }} + {{ $t('copy') }} + +
+
@@ -208,6 +257,10 @@ export default { noSort: { type: Boolean, default: false + }, + exportButton: { + type: Boolean, + default: false } }, data () { @@ -221,7 +274,9 @@ export default { onlyShowSelected: false, lastSelectIndex: null, shiftKey: false, - filteredRows: [] + filteredRows: [], + copyDialog: false, + copyFormat: 0 } }, computed: { @@ -254,6 +309,9 @@ export default { selectedIconMap () { if (this.singleSelect) return { 'true': 'radio_button_checked', 'false': 'radio_button_unchecked' } return { 'true': 'check_box', 'false': 'check_box_outline_blank' } + }, + headersWithText () { + return this.headers.filter(h => h.text !== undefined) } }, watch: { @@ -394,6 +452,43 @@ export default { }) if (this.onlyShowSelected && this.$refs.search) this.$refs.search.filterRows() if (this.filteredRows) this.calcSelectState() + }, + copyToClipboard () { + let result = '' + const keys = this.headersWithText.filter(h => h.includeInCopy).map(x => x.key) + if (this.copyFormat === 0) { + const topIndex = keys.length - 1 + this.filteredRows.forEach(row => { + let rowString = '' + for (let i in keys) { + let value = row.data[keys[i]] + if (value) rowString += value + if (i < topIndex) rowString += ',' + } + if (rowString) result += rowString + '\n' + }) + } else if (this.copyFormat === 1) { + const rows = this.filteredRows.map(row => { + let filterdRow = {} + for (let i in keys) { + let k = keys[i] + filterdRow[k] = row.data[k] + } + return filterdRow + }) + result = JSON.stringify(rows, null, 4) + } + if (!result) { + this.$snackbar({ text: this.$t('nothingToCopy'), color: 'error', timeout: 1200 }) + return + } + const copyHelper = this.$refs.copyHelper + copyHelper.style.display = 'block' + copyHelper.value = result + copyHelper.select() + document.execCommand('copy') + copyHelper.style.display = 'none' + this.$snackbar({ text: this.$t('copyDone'), color: 'primary', timeout: 1200 }) } } } @@ -405,6 +500,25 @@ export default { white-space: nowrap; } +.copy-button { + position: absolute; + top: 0; + bottom: 0; + right: 8px; + margin: 0 !important; + display: flex; + align-items: center; +} + +.copy-header-checkbox { + margin: 0; + padding: 0; +} + +.copy-format-toggle .v-btn--active { + color: white; +} + .toggle-button { margin: 0; padding: 0; @@ -466,6 +580,7 @@ export default { } .table-head { + position: relative; height: 56px; display: flex; font-size: 12px; diff --git a/webapp/src/components/GroupModuleClientList.vue b/webapp/src/components/GroupModuleClientList.vue index e3ab36a..9630e55 100644 --- a/webapp/src/components/GroupModuleClientList.vue +++ b/webapp/src/components/GroupModuleClientList.vue @@ -30,7 +30,7 @@