Show copy icon for thing and channel uids, fixes #396, fixes #475 (#980)

Signed-off-by: Hubert Nusser <hubsif@gmx.de>
pull/983/head
hubsif 2021-03-27 19:32:15 +01:00 committed by GitHub
parent 093ea4b76d
commit e9e55060db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 99 additions and 151 deletions

View File

@ -31,6 +31,7 @@
"sprintf-js": "^1.1.2",
"template7": "^1.4.2",
"tern": "^0.23.0",
"v-clipboard": "^2.2.3",
"video.js": "^7.10.2",
"vue": "^2.6.12",
"vue-async-computed": "^3.9.0",
@ -2900,21 +2901,13 @@
},
"engines": {
"node": ">= 10.0"
},
"peerDependencies": {
"lodash": "^4.17.11"
}
},
"node_modules/@bundle-stats/utils/node_modules/core-js": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.1.tgz",
"integrity": "sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg==",
"dev": true,
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
"dev": true
},
"node_modules/@cnakazawa/watch": {
"version": "1.0.3",
@ -3150,13 +3143,6 @@
"integrity": "sha512-VS0OynDh5LfPPpnIx9tsMEdn42z+qn8Fwk+mxxs2erZDeOy6JanQ4LP562ZzvyoujmvvlvRXenjgAlGnI7rKLA==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/auto-scroll": {
@ -3165,12 +3151,6 @@
"integrity": "sha512-ro/F9j1g4vwbq3m7Heg4brEHkkCvHBl2dqJTamPnReKH4vCldNCzwM8gsh+om73BS5mMsyiQiuHbkpzhWr7SdQ==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/auto-start": {
@ -3179,22 +3159,12 @@
"integrity": "sha512-Ggm8/Cfbo5DH9cH/oLscq4AfqPC/HAGehU4CfpOmZ+IDno+92KDadNJkUrGGtLJR1ySB8vtZWrbhCpLbmwEEKw==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/core": {
"version": "1.10.8",
"resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.8.tgz",
"integrity": "sha512-x0jUG6s4/la256Sg55DvERIEnZjSwUULL//YPMuEQRkTe+9pZztaZ/Cz5yuxwOmdMEH5HUVTwAL8y25VXPBy8w==",
"peerDependencies": {
"@interactjs/utils": "1.10.8"
}
"integrity": "sha512-x0jUG6s4/la256Sg55DvERIEnZjSwUULL//YPMuEQRkTe+9pZztaZ/Cz5yuxwOmdMEH5HUVTwAL8y25VXPBy8w=="
},
"node_modules/@interactjs/dev-tools": {
"version": "1.10.8",
@ -3202,13 +3172,6 @@
"integrity": "sha512-N6RP7RTjZgrp/RlvT7I2r+d0eY6k/+EdrJJJt7hzjyXbrWkToVGIZ21w2CivHlGyvgqtWZaMeXtMlo6aymuVGA==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/modifiers": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/inertia": {
@ -3218,14 +3181,6 @@
"dependencies": {
"@interactjs/interact": "1.10.8",
"@interactjs/offset": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/modifiers": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/interact": {
@ -3264,13 +3219,6 @@
"dependencies": {
"@interactjs/interact": "1.10.8",
"@interactjs/snappers": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/offset": {
@ -3279,13 +3227,6 @@
"integrity": "sha512-OPC/d9sdyjhkFSD6S62x9Wt98/mIDsk0+ho5s0HG/EAlb76jSKDsRQlWkmI2OkD6Gr1m05ulDnWUzo7li6J66g==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/pointer-events": {
@ -3294,13 +3235,6 @@
"integrity": "sha512-dHOyKorL+K685kNrrzbLH8+rrjqEC8URlyNbAk8UXJLb3lMuCYEJscsi3cHlLP0rt+3t0J3l4KK1/ZSo+tOrYA==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/reflow": {
@ -3309,13 +3243,6 @@
"integrity": "sha512-qrwzRrmz+eTO8QcNnqCWoHCpFRSpdcqijcMoazgfj46jGcFdBle1FtOGCEXXZq50HUtQAtrKlpuJb/QbDMzZ7A==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/core": "1.10.8",
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/snappers": {
@ -3324,12 +3251,6 @@
"integrity": "sha512-wQUDgDfeug6+8pzsLm+UiT6oVsgZFOT426XsRV+Eh2eyoU+CS9Q0YEm/sa6ow5QM5K00wPHqQTgM6AQXA8ytaQ==",
"dependencies": {
"@interactjs/interact": "1.10.8"
},
"optionalDependencies": {
"@interactjs/interact": "1.10.8"
},
"peerDependencies": {
"@interactjs/utils": "1.10.8"
}
},
"node_modules/@interactjs/types": {
@ -3645,21 +3566,13 @@
},
"engines": {
"node": ">= 10.0"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0-rc.1"
}
},
"node_modules/@relative-ci/agent/node_modules/core-js": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.9.1.tgz",
"integrity": "sha512-gSjRvzkxQc1zjM/5paAmL4idJBFzuJoo+jDjF1tStYFMV2ERfD02HhahhCGXUyHxQRG4yFKVSdO6g62eoRMcDg==",
"dev": true,
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
"dev": true
},
"node_modules/@relative-ci/agent/node_modules/cosmiconfig": {
"version": "7.0.0",
@ -3700,9 +3613,6 @@
"dependencies": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/@relative-ci/agent/node_modules/parse-json": {
@ -3718,9 +3628,6 @@
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@relative-ci/agent/node_modules/path-type": {
@ -3786,9 +3693,6 @@
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/@relative-ci/env-ci/node_modules/get-stream": {
@ -3801,9 +3705,6 @@
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@relative-ci/env-ci/node_modules/is-stream": {
@ -3846,9 +3747,6 @@
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@relative-ci/env-ci/node_modules/path-key": {
@ -4124,7 +4022,6 @@
"merge-source-map": "^1.1.0",
"postcss": "^7.0.14",
"postcss-selector-parser": "^6.0.2",
"prettier": "^1.18.2",
"source-map": "~0.6.1",
"vue-template-es2015-compiler": "^1.9.0"
},
@ -8349,6 +8246,9 @@
"lru-cache": "^4.1.5",
"semver": "^5.6.0",
"sigmund": "^1.0.1"
},
"bin": {
"editorconfig": "bin/editorconfig"
}
},
"node_modules/editorconfig/node_modules/commander": {
@ -8585,8 +8485,7 @@
"esprima": "^3.1.3",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
"optionator": "^0.8.1"
},
"bin": {
"escodegen": "bin/escodegen.js",
@ -9197,9 +9096,6 @@
},
"engines": {
"node": ">=8.10.0"
},
"peerDependencies": {
"eslint": ">=5.16.0"
}
},
"node_modules/eslint-plugin-node/node_modules/eslint-plugin-es": {
@ -9213,12 +9109,6 @@
},
"engines": {
"node": ">=8.10.0"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
},
"peerDependencies": {
"eslint": ">=4.19.1"
}
},
"node_modules/eslint-plugin-node/node_modules/eslint-utils": {
@ -9231,9 +9121,6 @@
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/eslint-plugin-node/node_modules/ignore": {
@ -9252,9 +9139,6 @@
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/eslint-plugin-node/node_modules/semver": {
@ -12748,7 +12632,6 @@
"@jest/types": "^24.9.0",
"anymatch": "^2.0.0",
"fb-watchman": "^2.0.0",
"fsevents": "^1.2.7",
"graceful-fs": "^4.1.15",
"invariant": "^2.2.4",
"jest-serializer": "^24.9.0",
@ -17510,9 +17393,6 @@
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/querystring": {
@ -18180,9 +18060,6 @@
"dependencies": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-cwd": {
@ -18540,10 +18417,7 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-1.3.1.tgz",
"integrity": "sha512-oDMjBDqoutgbZIX+4xZxa+DD4gQ/q8C66ukPZbe27msutU21yML9UYsBz+jDKklQh6atdnGlTMHa6YBvjKZwhQ==",
"dev": true,
"peerDependencies": {
"query-string": "^5.1.1 || ^6"
}
"dev": true
},
"node_modules/serve-index": {
"version": "1.9.1",
@ -19114,6 +18988,11 @@
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": {
"node": ">=0.10.0"
}
@ -21380,6 +21259,11 @@
"uuid": "bin/uuid"
}
},
"node_modules/v-clipboard": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/v-clipboard/-/v-clipboard-2.2.3.tgz",
"integrity": "sha512-Wg+ObZoYK6McHb5OOCFWvm0R7xHp0/p0G1ocx/8bO22jvA/yVY05rADbfiztwCokXBNfQuGv/XSd1ozcTFgekw=="
},
"node_modules/v8-compile-cache": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
@ -21745,10 +21629,8 @@
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
"dev": true,
"dependencies": {
"chokidar": "^3.4.1",
"graceful-fs": "^4.1.2",
"neo-async": "^2.5.0",
"watchpack-chokidar2": "^2.0.1"
"neo-async": "^2.5.0"
},
"optionalDependencies": {
"chokidar": "^3.4.1",
@ -22241,7 +22123,6 @@
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
"braces": "^2.3.2",
"fsevents": "^1.2.7",
"glob-parent": "^3.1.0",
"inherits": "^2.0.3",
"is-binary-path": "^1.0.0",
@ -26123,8 +26004,7 @@
"@interactjs/core": {
"version": "1.10.8",
"resolved": "https://registry.npmjs.org/@interactjs/core/-/core-1.10.8.tgz",
"integrity": "sha512-x0jUG6s4/la256Sg55DvERIEnZjSwUULL//YPMuEQRkTe+9pZztaZ/Cz5yuxwOmdMEH5HUVTwAL8y25VXPBy8w==",
"requires": {}
"integrity": "sha512-x0jUG6s4/la256Sg55DvERIEnZjSwUULL//YPMuEQRkTe+9pZztaZ/Cz5yuxwOmdMEH5HUVTwAL8y25VXPBy8w=="
},
"@interactjs/dev-tools": {
"version": "1.10.8",
@ -38919,8 +38799,7 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/serialize-query-params/-/serialize-query-params-1.3.1.tgz",
"integrity": "sha512-oDMjBDqoutgbZIX+4xZxa+DD4gQ/q8C66ukPZbe27msutU21yML9UYsBz+jDKklQh6atdnGlTMHa6YBvjKZwhQ==",
"dev": true,
"requires": {}
"dev": true
},
"serve-index": {
"version": "1.9.1",
@ -41340,6 +41219,11 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
},
"v-clipboard": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/v-clipboard/-/v-clipboard-2.2.3.tgz",
"integrity": "sha512-Wg+ObZoYK6McHb5OOCFWvm0R7xHp0/p0G1ocx/8bO22jvA/yVY05rADbfiztwCokXBNfQuGv/XSd1ozcTFgekw=="
},
"v8-compile-cache": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",

View File

@ -83,6 +83,7 @@
"sprintf-js": "^1.1.2",
"template7": "^1.4.2",
"tern": "^0.23.0",
"v-clipboard": "^2.2.3",
"video.js": "^7.10.2",
"vue": "^2.6.12",
"vue-async-computed": "^3.9.0",

View File

@ -30,12 +30,25 @@
<div v-if="multipleLinksMode" slot="root-end">
<slot :channelType="c.channelType" :channelId="c.channel.id" :channel="c.channel" :extensible="c.extensible" />
</div>
<clipboard-icon class="channel-clipboard-icon" :value="c.channel.uid" tooltip="Copy UID" color="gray" />
</f7-list-item>
</f7-list>
</template>
<style lang="stylus">
.channel-clipboard-icon
position absolute !important
right 60px
top 8px
</style>
<script>
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
export default {
components: {
ClipboardIcon
},
props: [
'extensible',
'group',

View File

@ -8,7 +8,15 @@
<f7-list-input label="Unique ID" v-if="createMode" type="text" placeholder="Required" :value="thing.ID"
@input="changeUID" info="Note: cannot be changed after the creation"
required validate pattern="[A-Za-z0-9_\-]+" error-message="Required. A-Z,a-z,0-9,_,- only" />
<f7-list-input label="Identifier" type="text" placeholder="Name" :value="thing.UID" disabled />
<f7-list-item>
<div slot="inner" class="item-label">
Identifier
</div>
<div slot="inner" class="item-input-wrap">
{{ thing.UID ? thing.UID : 'Name' }}
<clipboard-icon v-if="thing.UID" slot="inner-end" :value="thing.UID" tooltip="Copy UID" />
</div>
</f7-list-item>
<f7-list-input label="Label" type="text" :disabled="!ready || readOnly" placeholder="e.g. My Thing" :value="thing.label"
@input="thing.label = $event.target.value; $emit('updated')" required validate />
<f7-list-input label="Location" type="text" :disabled="!ready || readOnly" placeholder="e.g. Kitchen" :value="thing.location"
@ -36,11 +44,13 @@
<script>
import ThingPicker from '@/components/config/controls/thing-picker.vue'
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
export default {
props: ['thing', 'thingType', 'createMode', 'ready', 'readOnly'],
components: {
ThingPicker
ThingPicker,
ClipboardIcon
},
methods: {
computedThingUid () {

View File

@ -0,0 +1,29 @@
<template>
<f7-icon class="clipboard-icon" v-bind="$attrs" f7="square_on_square" :size="size ? size : 12" v-clipboard="value" v-clipboard:success="success" />
</template>
<style lang="stylus">
.clipboard-icon
cursor: copy
</style>
<script>
import Vue from 'vue'
import Clipboard from 'v-clipboard'
Vue.use(Clipboard)
export default {
props: ['value', 'size'],
methods: {
success ({ value, event }) {
event.stopPropagation()
this.$f7.toast.create({
text: 'Copied to clipboard',
destroyOnClose: true,
closeTimeout: 2000
}).open()
}
}
}
</script>

View File

@ -14,8 +14,12 @@
<f7-list media-list>
<f7-list-item media-item class="channel-item"
:title="channel.label"
:footer="channel.description"
:subtitle="channel.uid" />
:footer="channel.description">
<div slot="subtitle">
{{ channel.uid }}
<clipboard-icon :value="channel.uid" tooltip="Copy UID" />
</div>
</f7-list-item>
</f7-list>
</f7-col>
<f7-col v-if="channelType != null">
@ -38,10 +42,12 @@
<script>
import ConfigSheet from '@/components/config/config-sheet.vue'
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
export default {
components: {
ConfigSheet
ConfigSheet,
ClipboardIcon
},
props: ['thing', 'thingType', 'channel', 'channelType', 'channelId'],
data () {

View File

@ -87,8 +87,11 @@
@click.ctrl="(e) => ctrlClick(e, thing)"
@click.exact="(e) => click(e, thing)"
link=""
:title="thing.label || thing.UID"
:footer="thing.UID">
:title="thing.label || thing.UID">
<div slot="footer">
{{ thing.UID }}
<clipboard-icon :value="thing.UID" tooltip="Copy UID" />
</div>
<f7-badge slot="after" :color="thingStatusBadgeColor(thing.statusInfo)" :tooltip="thing.statusInfo.description">
{{ thingStatusBadgeText(thing.statusInfo) }}
</f7-badge>
@ -121,11 +124,13 @@
<script>
import thingStatus from '@/components/thing/thing-status-mixin'
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
export default {
mixins: [thingStatus],
components: {
'empty-state-placeholder': () => import('@/components/empty-state-placeholder.vue')
'empty-state-placeholder': () => import('@/components/empty-state-placeholder.vue'),
ClipboardIcon
},
data () {
return {