diff --git a/docs/configuring.md b/docs/configuring.md index 9c2a32c7..b50a105a 100644 --- a/docs/configuring.md +++ b/docs/configuring.md @@ -77,7 +77,7 @@ Tips: --- | --- | --- | --- **`language`** | `string` | _Optional_ | The 2 (or 4-digit) [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, e.g. `en` or `en-GB`. This must be a language that the app has already been [translated](https://github.com/Lissy93/dashy/tree/master/src/assets/locales) into. If your language is unavailable, Dashy will fallback to English. By default Dashy will attempt to auto-detect your language, although this may not work on some privacy browsers. **`startingView`** | `enum` | _Optional_ | Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI. Can be either `default`, `minimal` or `workspace`. Defaults to `default` -**`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `top`, `parent`, `modal` or `workspace`. Defaults to `newtab` +**`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Defaults to `newtab` **`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping each of your services and display their status as a dot next to each item. This can be overridden by setting `statusCheck` under each item. Defaults to `false` **`statusCheckInterval`** | `boolean` | _Optional_ | The number of seconds between checks. If set to `0` then service will only be checked on initial page load, which is usually the desired functionality. If value is less than `10` you may experience a hit in performance. Defaults to `0` **`webSearch`** | `object` | _Optional_ | Configuration options for the web search feature, set your default search engine, opening method or disable web search. See [`webSearch`](#appconfigwebsearch-optional) @@ -186,7 +186,7 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)** **`description`** | `string` | _Optional_ | Additional info about an item, which is shown in the tooltip on hover, or visible on large tiles **`url`** | `string` | Required | The URL / location of web address for when the item is clicked **`icon`** | `string` | _Optional_ | The icon for a given item. Can be a font-awesome icon, favicon, remote URL or local URL. See [`item.icon`](#sectionicon-and-sectionitemicon) -**`target`** | `string` | _Optional_ | The opening method for when the item is clicked, either `newtab`, `sametab`, `top`, `parent`, `modal` or `workspace`. Where `newtab` will open the link in a new tab, `sametab` will open it in the current tab, and `modal` will open a pop-up modal and `workspace` will open in the Workspace view. Defaults to `newtab` +**`target`** | `string` | _Optional_ | The opening method for when the item is clicked, either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Where `newtab` will open the link in a new tab, `sametab` will open it in the current tab, and `modal` will open a pop-up modal, `workspace` will open in the Workspace view and `clipboard` will copy the URL to system clipboard (but not launch app). Defaults to `newtab` **`hotkey`** | `number` | _Optional_ | Give frequently opened applications a numeric hotkey, between `0 - 9`. You can then just press that key to launch that application. **`tags`** | `string[]` | _Optional_ | A list of tags, which can be used for improved search **`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping the URL associated with the current service, and display its status as a dot next to the item. The value here will override `appConfig.statusCheck` so you can turn off or on checks for a given service. Defaults to `appConfig.statusCheck`, falls back to `false` diff --git a/src/assets/interface-icons/open-clipboard.svg b/src/assets/interface-icons/open-clipboard.svg new file mode 100644 index 00000000..2f3bff6e --- /dev/null +++ b/src/assets/interface-icons/open-clipboard.svg @@ -0,0 +1 @@ +<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="paste" class="svg-inline--fa fa-paste fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M433.941 193.941l-51.882-51.882A48 48 0 0 0 348.118 128H320V80c0-26.51-21.49-48-48-48h-61.414C201.582 13.098 182.294 0 160 0s-41.582 13.098-50.586 32H48C21.49 32 0 53.49 0 80v288c0 26.51 21.49 48 48 48h80v48c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48V227.882a48 48 0 0 0-14.059-33.941zm-84.066-16.184l48.368 48.368a6 6 0 0 1 1.757 4.243V240h-64v-64h9.632a6 6 0 0 1 4.243 1.757zM160 38c9.941 0 18 8.059 18 18s-8.059 18-18 18-18-8.059-18-18 8.059-18 18-18zm-32 138v192H54a6 6 0 0 1-6-6V86a6 6 0 0 1 6-6h55.414c9.004 18.902 28.292 32 50.586 32s41.582-13.098 50.586-32H266a6 6 0 0 1 6 6v42h-96c-26.51 0-48 21.49-48 48zm266 288H182a6 6 0 0 1-6-6V182a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v170a6 6 0 0 1-6 6z"></path></svg> \ No newline at end of file diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 70713065..2e25af9a 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -185,10 +185,12 @@ "newtab": "New Tab", "modal": "Pop-Up Modal", "workspace": "Workspace View", + "clipboard": "Copy to Clipboard", "options-section-title": "Options", "edit-item": "Edit", "move-item": "Copy or Move", - "remove-item": "Remove" + "remove-item": "Remove", + "copied-toast": "URL has been copied to clipboard" }, "section": { "open-section": "Open Section", @@ -281,4 +283,4 @@ "good-service-rest": "Good Service on all other Lines" } } -} +} \ No newline at end of file diff --git a/src/components/LinkItems/Item.vue b/src/components/LinkItems/Item.vue index 414706ef..024de6f2 100644 --- a/src/components/LinkItems/Item.vue +++ b/src/components/LinkItems/Item.vue @@ -141,7 +141,7 @@ export default { hyperLinkHref() { const nothing = '#'; if (this.isEditMode) return nothing; - const noAnchorNeeded = ['modal', 'workspace']; + const noAnchorNeeded = ['modal', 'workspace', 'clipboard']; return noAnchorNeeded.includes(this.accumulatedTarget) ? nothing : this.url; }, }, @@ -174,6 +174,9 @@ export default { this.$emit('triggerModal', this.url); } else if (this.accumulatedTarget === 'workspace') { router.push({ name: 'workspace', query: { url: this.url } }); + } else if (this.accumulatedTarget === 'clipboard') { + navigator.clipboard.writeText(this.url); + this.$toasted.show(this.$t('context-menus.item.copied-toast')); } else { this.$emit('itemClicked'); } @@ -226,6 +229,7 @@ export default { case 'top': return '"\\f102"'; case 'modal': return '"\\f2d0"'; case 'workspace': return '"\\f0b1"'; + case 'clipboard': return '"\\f0ea"'; default: return '"\\f054"'; } }, @@ -279,6 +283,10 @@ export default { case 'workspace': router.push({ name: 'workspace', query: { url } }); break; + case 'clipboard': + navigator.clipboard.writeText(url); + this.$toasted.show(this.$t('context-menus.item.copied-toast')); + break; default: window.open(url, '_blank'); } }, @@ -546,4 +554,7 @@ a.item.is-edit-mode { .disabled-link { pointer-events: none; } +.tooltip.item-description-tooltip { + z-index: 7; +} </style> diff --git a/src/components/LinkItems/ItemContextMenu.vue b/src/components/LinkItems/ItemContextMenu.vue index 1d29a756..6fc9131f 100644 --- a/src/components/LinkItems/ItemContextMenu.vue +++ b/src/components/LinkItems/ItemContextMenu.vue @@ -23,6 +23,10 @@ <WorkspaceOpenIcon /> <span>{{ $t('context-menus.item.workspace') }}</span> </li> + <li @click="launch('clipboard')"> + <ClipboardOpenIcon /> + <span>{{ $t('context-menus.item.clipboard') }}</span> + </li> </ul> <!-- Edit Options --> <ul class="menu-section"> @@ -55,6 +59,7 @@ import SameTabOpenIcon from '@/assets/interface-icons/open-current-tab.svg'; import NewTabOpenIcon from '@/assets/interface-icons/open-new-tab.svg'; import IframeOpenIcon from '@/assets/interface-icons/open-iframe.svg'; import WorkspaceOpenIcon from '@/assets/interface-icons/open-workspace.svg'; +import ClipboardOpenIcon from '@/assets/interface-icons/open-clipboard.svg'; export default { name: 'ContextMenu', @@ -66,6 +71,7 @@ export default { NewTabOpenIcon, IframeOpenIcon, WorkspaceOpenIcon, + ClipboardOpenIcon, }, props: { posX: Number, // The X coordinate for positioning diff --git a/src/components/LinkItems/ItemOpenMethodIcon.vue b/src/components/LinkItems/ItemOpenMethodIcon.vue index b33aa382..4909ccf0 100644 --- a/src/components/LinkItems/ItemOpenMethodIcon.vue +++ b/src/components/LinkItems/ItemOpenMethodIcon.vue @@ -7,6 +7,7 @@ <WorkspaceOpenIcon v-else-if="openingMethod === 'workspace'" /> <ParentOpenIcon v-else-if="openingMethod === 'parent'" /> <TopOpenIcon v-else-if="openingMethod === 'top'" /> + <ClipboardOpenIcon v-else-if="openingMethod === 'clipboard'" /> <UnknownIcon v-else /> </div> <div v-if="hotkey" :class="`hotkey-denominator ${makeClass(position, isSmall, isTransparent)}`"> @@ -25,6 +26,7 @@ import IframeOpenIcon from '@/assets/interface-icons/open-iframe.svg'; import WorkspaceOpenIcon from '@/assets/interface-icons/open-workspace.svg'; import ParentOpenIcon from '@/assets/interface-icons/open-parent.svg'; import TopOpenIcon from '@/assets/interface-icons/open-top.svg'; +import ClipboardOpenIcon from '@/assets/interface-icons/open-clipboard.svg'; import UnknownIcon from '@/assets/interface-icons/unknown-icon.svg'; export default { @@ -52,6 +54,7 @@ export default { WorkspaceOpenIcon, ParentOpenIcon, TopOpenIcon, + ClipboardOpenIcon, UnknownIcon, }, }; diff --git a/src/utils/ConfigSchema.json b/src/utils/ConfigSchema.json index 90c6e49c..f3aaa3e6 100644 --- a/src/utils/ConfigSchema.json +++ b/src/utils/ConfigSchema.json @@ -84,7 +84,8 @@ "parent", "top", "modal", - "workspace" + "workspace", + "clipboard" ], "default": "newtab", "description": "The default opening method for items. Only used if no item.target is specified" @@ -624,7 +625,6 @@ "title": "Show for Groups", "type": "array", "description": "Section will be hidden from all users except those with one or more of these groups", - "items": { "type": "string", "description": "Name of the group that will be able to view this section" @@ -651,7 +651,6 @@ "title": "Hide for Groups", "type": "array", "description": "Section will be hidden from users with any of these groups", - "items": { "type": "string", "description": "name of the group that will not be able to view this section" @@ -712,7 +711,8 @@ "parent", "top", "modal", - "workspace" + "workspace", + "clipboard" ], "default": "newtab", "description": "Where / how the item is opened when it's clicked" @@ -796,4 +796,4 @@ } } } -} +} \ No newline at end of file