Add copied to clipboard notifications

This commit is contained in:
James Lyne 2021-05-25 14:21:37 +01:00
parent 658aeb3e44
commit 609b265951
9 changed files with 231 additions and 7 deletions

152
package-lock.json generated
View File

@ -121,6 +121,11 @@
} }
} }
}, },
"@kyvg/vue3-notification": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@kyvg/vue3-notification/-/vue3-notification-2.3.0.tgz",
"integrity": "sha512-U2XIofk8bhGnoOyStEeCtWFTvoosC3EtbtpT+ev6JAb0SIky3RqadM/WYFhKmBxEodrB31jQ/ivQYEcBVBPlJQ=="
},
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz",
@ -743,6 +748,12 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.11.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.11.tgz",
"integrity": "sha512-b+zB8A2so8eCE0JsxjL24J7vdGl8rzPQ09hZNhystm+KqSbKcAej1A+Hbva1rCMmTTqA+hFnUSDc5kouEo0JzA==" "integrity": "sha512-b+zB8A2so8eCE0JsxjL24J7vdGl8rzPQ09hZNhystm+KqSbKcAej1A+Hbva1rCMmTTqA+hFnUSDc5kouEo0JzA=="
}, },
"@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
"integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
"dev": true
},
"acorn": { "acorn": {
"version": "7.4.1", "version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
@ -1936,6 +1947,15 @@
"locate-path": "^2.0.0" "locate-path": "^2.0.0"
} }
}, },
"find-yarn-workspace-root": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
"integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
"dev": true,
"requires": {
"micromatch": "^4.0.2"
}
},
"flat-cache": { "flat-cache": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
@ -1969,6 +1989,17 @@
"integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=",
"dev": true "dev": true
}, },
"fs-extra": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
"integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"fs.realpath": { "fs.realpath": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -2367,6 +2398,12 @@
"integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==",
"dev": true "dev": true
}, },
"is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true
},
"is-empty": { "is-empty": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz", "resolved": "https://registry.npmjs.org/is-empty/-/is-empty-1.2.0.tgz",
@ -2480,6 +2517,15 @@
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
"dev": true "dev": true
}, },
"is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
"requires": {
"is-docker": "^2.0.0"
}
},
"is-yarn-global": { "is-yarn-global": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz",
@ -2550,6 +2596,15 @@
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
"dev": true "dev": true
}, },
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"dev": true,
"requires": {
"graceful-fs": "^4.1.6"
}
},
"jstransformer": { "jstransformer": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
@ -2569,6 +2624,15 @@
"json-buffer": "3.0.0" "json-buffer": "3.0.0"
} }
}, },
"klaw-sync": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
"integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.11"
}
},
"latest-version": { "latest-version": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz",
@ -2859,6 +2923,12 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true "dev": true
}, },
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"normalize-package-data": { "normalize-package-data": {
"version": "2.5.0", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@ -2923,6 +2993,16 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"dev": true,
"requires": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
}
},
"optionator": { "optionator": {
"version": "0.9.1", "version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@ -2943,6 +3023,12 @@
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
"dev": true "dev": true
}, },
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-cancelable": { "p-cancelable": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
@ -3018,6 +3104,57 @@
"json-parse-better-errors": "^1.0.1" "json-parse-better-errors": "^1.0.1"
} }
}, },
"patch-package": {
"version": "6.4.7",
"resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.4.7.tgz",
"integrity": "sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ==",
"dev": true,
"requires": {
"@yarnpkg/lockfile": "^1.1.0",
"chalk": "^2.4.2",
"cross-spawn": "^6.0.5",
"find-yarn-workspace-root": "^2.0.0",
"fs-extra": "^7.0.1",
"is-ci": "^2.0.0",
"klaw-sync": "^6.0.0",
"minimist": "^1.2.0",
"open": "^7.4.2",
"rimraf": "^2.6.3",
"semver": "^5.6.0",
"slash": "^2.0.0",
"tmp": "^0.0.33"
},
"dependencies": {
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
}
}
},
"path-exists": { "path-exists": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
@ -3913,6 +4050,15 @@
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
}, },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
}
},
"to-fast-properties": { "to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@ -4255,6 +4401,12 @@
} }
} }
}, },
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"dev": true
},
"untildify": { "untildify": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz",

View File

@ -7,9 +7,11 @@
"preview": "vite preview --port 8082", "preview": "vite preview --port 8082",
"build": "vue-tsc --noEmit && vite build --out-dir dist", "build": "vue-tsc --noEmit && vite build --out-dir dist",
"lint": "eslint src", "lint": "eslint src",
"lint:fix": "eslint src --fix" "lint:fix": "eslint src --fix",
"postinstall": "patch-package"
}, },
"dependencies": { "dependencies": {
"@kyvg/vue3-notification": "^2.3.0",
"@soerenmartius/vue3-clipboard": "^0.1.2", "@soerenmartius/vue3-clipboard": "^0.1.2",
"focus-visible": "^5.2.0", "focus-visible": "^5.2.0",
"normalize-scss": "^7.0.1", "normalize-scss": "^7.0.1",
@ -26,6 +28,7 @@
"@types/leaflet": "^1.7.0", "@types/leaflet": "^1.7.0",
"eslint": "^7.26.0", "eslint": "^7.26.0",
"eslint-plugin-vue": "^7.9.0", "eslint-plugin-vue": "^7.9.0",
"patch-package": "^6.4.7",
"rollup-plugin-analyzer": "^4.0.0", "rollup-plugin-analyzer": "^4.0.0",
"sass": "^1.32.13", "sass": "^1.32.13",
"typescript": "~4.2.4", "typescript": "~4.2.4",

View File

@ -0,0 +1,9 @@
diff --git a/node_modules/@kyvg/vue3-notification/dist/index.d.ts b/node_modules/@kyvg/vue3-notification/dist/index.d.ts
index bbf3c54..6e02345 100644
--- a/node_modules/@kyvg/vue3-notification/dist/index.d.ts
+++ b/node_modules/@kyvg/vue3-notification/dist/index.d.ts
@@ -29,4 +29,3 @@ export declare const notify: {
};
export { }
-}

View File

@ -18,6 +18,7 @@
<Map></Map> <Map></Map>
<Sidebar></Sidebar> <Sidebar></Sidebar>
<ChatBox v-if="chatBoxEnabled" v-show="chatBoxEnabled && chatVisible"></ChatBox> <ChatBox v-if="chatBoxEnabled" v-show="chatBoxEnabled && chatVisible"></ChatBox>
<notifications position="bottom center" speed="250" max="3" ignoreDuplicates="true" />
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@ -2,10 +2,18 @@
<nav id="map-context-menu" v-show="menuVisible" ref="menuElement" :style="style"> <nav id="map-context-menu" v-show="menuVisible" ref="menuElement" :style="style">
<ul class="menu"> <ul class="menu">
<li> <li>
<button type="button" v-clipboard="locationCopy">{{ locationLabel }}</button> <button type="button"
v-clipboard:copy="locationCopy"
v-clipboard:success="copySuccess"
v-clipboard:error="copyError">{{ locationLabel }}
</button>
</li> </li>
<li> <li>
<button type="button" v-clipboard="url">{{ messageCopyLink }}</button> <button type="button"
v-clipboard:copy="url"
v-clipboard:success="copySuccess"
v-clipboard:error="copyError">{{ messageCopyLink }}
</button>
</li> </li>
<li> <li>
<button type="button" @click.prevent="pan">{{ messageCenterHere }}</button> <button type="button" @click.prevent="pan">{{ messageCenterHere }}</button>
@ -112,6 +120,11 @@ export default defineComponent({
if (event.value) { if (event.value) {
props.leaflet.panTo(event.value.latlng); props.leaflet.panTo(event.value.latlng);
} }
},
copySuccess = () => notify('Copied to clipboard'),
copyError = (e: Error) => {
notify({ type: 'error', text:'Unable to copy to clipboard'});
console.error('Error copying to clipboard', e);
}; };
onMounted(() => { onMounted(() => {
@ -161,6 +174,9 @@ export default defineComponent({
messageCopyLink, messageCopyLink,
messageCenterHere, messageCenterHere,
copySuccess,
copyError,
menuVisible, menuVisible,
menuElement, menuElement,
url, url,

View File

@ -20,7 +20,8 @@
import {Control, ControlOptions, DomUtil, Map} from 'leaflet'; import {Control, ControlOptions, DomUtil, Map} from 'leaflet';
import {useStore} from "@/store"; import {useStore} from "@/store";
import '@/assets/icons/link.svg'; import '@/assets/icons/link.svg';
import { toClipboard } from '@soerenmartius/vue3-clipboard' import { toClipboard } from '@soerenmartius/vue3-clipboard';
import {notify} from "@kyvg/vue3-notification";
export class LinkControl extends Control { export class LinkControl extends Control {
// @ts-ignore // @ts-ignore
@ -44,7 +45,13 @@ export class LinkControl extends Control {
linkButton.addEventListener('click', e => { linkButton.addEventListener('click', e => {
e.preventDefault(); e.preventDefault();
toClipboard(window.location.href.split("#")[0] + useStore().getters.url); toClipboard(window.location.href.split("#")[0] + useStore().getters.url).then(() => {
notify('Copied to clipboard');
}).catch((e) => {
notify({ type: 'error', text:'Unable to copy to clipboard'});
console.error('Error copying to clipboard', e);
});
}); });
return linkButton; return linkButton;

View File

@ -25,7 +25,8 @@ import '@/scss/style.scss';
import 'focus-visible'; import 'focus-visible';
import {MutationTypes} from "@/store/mutation-types"; import {MutationTypes} from "@/store/mutation-types";
import {validateConfiguration} from "@/util"; import {validateConfiguration} from "@/util";
import { VueClipboard } from '@soerenmartius/vue3-clipboard' import { VueClipboard } from '@soerenmartius/vue3-clipboard';
import Notifications from '@kyvg/vue3-notification'
const splash = document.getElementById('splash'), const splash = document.getElementById('splash'),
splashSpinner = document.getElementById('splash__spinner'), splashSpinner = document.getElementById('splash__spinner'),
@ -112,7 +113,10 @@ try {
store.commit(MutationTypes.SET_CURRENT_SERVER, config.keys().next().value); store.commit(MutationTypes.SET_CURRENT_SERVER, config.keys().next().value);
} }
const app = createApp(App).use(store).use(VueClipboard); const app = createApp(App)
.use(store)
.use(Notifications)
.use(VueClipboard);
// app.config.performance = true; // app.config.performance = true;
app.mount('#app'); app.mount('#app');

View File

@ -0,0 +1,31 @@
.vue-notification {
margin: 0 0.5rem 1rem;
padding: 1rem 1.5rem;
min-height: 5rem;
font-size: 1.6rem;
font-family: Raleway, sans-serif;
color: var(--text-base);
display: flex;
flex-direction: column;
justify-content: center;
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
background: var(--background-base);
border-left: none;// 5px solid #187fe7;
&.success {
background: #68cd86;
border-left-color: #42a85f;
}
&.warn {
background: #ffb648;
border-left-color: #f48a06;
}
&.error {
background: var(--background-error);
border-left-color: #b82e24;
}
}

View File

@ -18,6 +18,7 @@
*/ */
@import "mixins"; @import "mixins";
@import "placeholders"; @import "placeholders";
@import "notifications";
@import "leaflet/controls"; @import "leaflet/controls";
@import "leaflet/popups"; @import "leaflet/popups";