From 1f6844d42b5065008445a462a784b9bdc00c0b50 Mon Sep 17 00:00:00 2001 From: romankko2 Date: Fri, 21 Jun 2024 11:51:37 +0200 Subject: [PATCH 01/13] [quill-editor] smb protocol added for macOS --- app/src/plugins/app/_config/quill.util.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/plugins/app/_config/quill.util.ts b/app/src/plugins/app/_config/quill.util.ts index f05a829..162c7ab 100644 --- a/app/src/plugins/app/_config/quill.util.ts +++ b/app/src/plugins/app/_config/quill.util.ts @@ -3,22 +3,23 @@ import { Quill } from '@vueup/vue-quill' export function registerQuillUrlSanitizer() { const Link = Quill.import('formats/link') + // Extend the protocol whitelist + Link.PROTOCOL_WHITELIST.push('smb', 'fmp', 'radar', 'rdar', 'sms', '\\') + class CustomLinkSanitizer extends Link { static sanitize(url) { const sanitizedUrl = super.sanitize(url) if (!sanitizedUrl || sanitizedUrl === 'about:blank') return sanitizedUrl - const protocolWhhitelist = ['http', 'https', 'mailto', 'tel', 'radar', 'rdar', 'smb', 'sms'] - const hasWhitelistedProtocol = protocolWhhitelist.some(function(protocol) { - return sanitizedUrl.startsWith(protocol) - }) + const protocolWhitelist = Link.PROTOCOL_WHITELIST + const hasWhitelistedProtocol = protocolWhitelist.some(protocol => sanitizedUrl.startsWith(protocol)) if (hasWhitelistedProtocol) return sanitizedUrl return `https://${sanitizedUrl}` - } + } } - Quill.register(CustomLinkSanitizer, true) + Quill.register('formats/link', CustomLinkSanitizer, true) } \ No newline at end of file From f3d3aa916e1289f4081ca3512440bc6c84583032 Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Mon, 24 Jun 2024 19:29:12 +0200 Subject: [PATCH 02/13] [calendar fix] --- .../tm@modal/task/_components/a-timeblock.vue | 26 +++++++++++++++++-- .../plugins/tm@modal/task/z-task-modal.vue | 16 ++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/src/plugins/tm@modal/task/_components/a-timeblock.vue b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue index 9ee7d38..c1cb9eb 100644 --- a/app/src/plugins/tm@modal/task/_components/a-timeblock.vue +++ b/app/src/plugins/tm@modal/task/_components/a-timeblock.vue @@ -3,7 +3,9 @@
- +
+ +
@@ -15,13 +17,15 @@ import useVuelidate from '@vuelidate/core' import { requiredIf } from '@vuelidate/validators' import Datepicker from '@vuepic/vue-datepicker' +import VuetifyFixFocusMixin from '@/plugins/tm@modal/_mixins/vuetify-fix-focus' export default { + mixins: [VuetifyFixFocusMixin], + components: { Datepicker }, - props: { timeblock: { type: Object, @@ -55,6 +59,18 @@ export default { }, methods: { + async openDatepicker(ref) { + this.$refs[ref].openMenu() + this.$nextTick(() => { + this.$refs['datepicker-wrapper'].scrollIntoView({ behavior: 'instant', block: 'center', inline: 'center' }) + this.$nextTick(() => { + const popup = document.querySelector('.dp__menu.dp__menu_index') + const isBottom = popup.querySelector('.dp__arrow_bottom') + const yDifference = isBottom ? 0 - popup.clientHeight - 42 : 35 + popup.style.top = window.innerHeight / 2 + yDifference + 'px' + }) + }) + }, onFocus() { console.log('focus') }, @@ -100,4 +116,10 @@ export default { .error input border: 1px solid red !important + +.datepicker-wrapper + width: 100% + .datepicker-input + width: 100% !important + pointer-events: none e \ No newline at end of file diff --git a/app/src/plugins/tm@modal/task/z-task-modal.vue b/app/src/plugins/tm@modal/task/z-task-modal.vue index d505277..da03cb8 100644 --- a/app/src/plugins/tm@modal/task/z-task-modal.vue +++ b/app/src/plugins/tm@modal/task/z-task-modal.vue @@ -16,7 +16,9 @@
- +
+ +
@@ -69,7 +71,7 @@ + \ No newline at end of file From 1b7315617feb671774009203787d69654952ad0c Mon Sep 17 00:00:00 2001 From: romankko2 Date: Tue, 2 Jul 2024 15:45:10 +0200 Subject: [PATCH 06/13] . --- app/src/plugins/app/_theme/global.sass | 36 ++++++++++++++- .../plugins/tm@_utils/server-links.utils.ts | 18 ++++---- .../_components/read-only/z-description.vue | 35 ++++++++++++--- .../_components/a-task-description.vue | 45 ++++++++++++++----- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/app/src/plugins/app/_theme/global.sass b/app/src/plugins/app/_theme/global.sass index 11f4eb7..417d458 100644 --- a/app/src/plugins/app/_theme/global.sass +++ b/app/src/plugins/app/_theme/global.sass @@ -106,8 +106,42 @@ input[type="time"]::-webkit-calendar-picker-indicator height: 40px !important .server-links + background: rgba(127, 57, 251, 1) + padding: 4px 5px + a - text-decoration: underline + color: #fff + +.copy-btn + position: absolute + right: 0 + width: 10% + height: 100% + text-align: center + bottom: 0 + border-top-right-radius: 9999px + border-bottom-right-radius: 9999px + padding-top: 4px + background: #808080 + color: #fff + + &:hover + cursor: pointer + background: #666666 + +.copying-btn + position: absolute + right: 0 + width: 10% + height: 100% + text-align: center + bottom: 0 + border-top-right-radius: 9999px + border-bottom-right-radius: 9999px + padding-top: 4px + background: rgb(76, 175, 80) + color: #fff + transition: background 0.3s ease, color 0.3s ease @media (max-width: 534px) .mobile-view diff --git a/app/src/plugins/tm@_utils/server-links.utils.ts b/app/src/plugins/tm@_utils/server-links.utils.ts index 2726aee..a6a8be6 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -12,35 +12,35 @@ export function getServerLinks(description) { const text = p.textContent.trim() if (os === 'mac' && text.startsWith('smb://')) { - links.add(`${text}`) + links.add(text) } else if (os === 'win' && text.startsWith('\\\\')) { - links.add(`${text}`) + links.add(`${text.replace(/\//g, '\\')}`) } else if (os === 'mac' && text.startsWith('\\\\')) { const smbLink = 'smb:' + text.replace(/\\/g, '/') - links.add(`${smbLink}`) + links.add(smbLink) } else if (os === 'win' && text.startsWith('smb://')) { const windowsLink = text.replace(/^smb:/, '').replace(/\//g, '\\') - links.add(`${windowsLink}`) + links.add(`${windowsLink}`) } const anchor = p.querySelector('a') if (anchor) { const href = anchor.getAttribute('href') if (os === 'mac' && href.startsWith('smb://')) { - links.add(`${href}`) + links.add(href) } else if (os === 'win' && href.startsWith('\\\\')) { - links.add(`${href}`) + links.add(`${href.replace(/\//g, '\\')}`) } else if (os === 'mac' && href.startsWith('\\\\')) { const smbLink = 'smb:' + href.replace(/\\/g, '/') - links.add(`${smbLink}`) + links.add(smbLink) } else if (os === 'win' && href.startsWith('smb://')) { const windowsLink = href.replace(/^smb:/, '').replace(/\//g, '\\') - links.add(`${windowsLink}`) + links.add(`${windowsLink}`) } } }) - return Array.from(links).join('
') + return Array.from(links) } export function detectOS() { diff --git a/app/src/plugins/tm@modal/_components/read-only/z-description.vue b/app/src/plugins/tm@modal/_components/read-only/z-description.vue index eae2fc0..57738af 100644 --- a/app/src/plugins/tm@modal/_components/read-only/z-description.vue +++ b/app/src/plugins/tm@modal/_components/read-only/z-description.vue @@ -4,11 +4,15 @@
-
+

Odkazy na server

-
- +

Popis mastertasku

@@ -16,7 +20,7 @@ diff --git a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue index a23f31d..28d16f1 100644 --- a/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue +++ b/app/src/plugins/tm@modal/master-task/z-master-task-modal.vue @@ -298,7 +298,7 @@ export default { async save() { if (this.mastertask.id) { this.mastertask.employees = this.mastertask.employees.map(employee => { - const { duration } = this.mastertask.subtasks.find(({ employee_id }) => employee_id == employee.id) + const { duration } = this.mastertask.subtasks.find(({ employee_id }) => employee_id == employee.id) || {} employee.duration = duration return employee }) diff --git a/app/src/plugins/tm@modal/task/_components/_components/a-task-description.vue b/app/src/plugins/tm@modal/task/_components/_components/a-task-description.vue index 2329b9b..2b0beb6 100644 --- a/app/src/plugins/tm@modal/task/_components/_components/a-task-description.vue +++ b/app/src/plugins/tm@modal/task/_components/_components/a-task-description.vue @@ -1,35 +1,17 @@ \ No newline at end of file From c58ca9405a7386a6c73a220c487634f9c1e24b6c Mon Sep 17 00:00:00 2001 From: romankko2 Date: Wed, 3 Jul 2024 10:39:17 +0200 Subject: [PATCH 08/13] . --- app/src/plugins/app/_theme/global.sass | 31 -------------------------- 1 file changed, 31 deletions(-) diff --git a/app/src/plugins/app/_theme/global.sass b/app/src/plugins/app/_theme/global.sass index 417d458..2382e8e 100644 --- a/app/src/plugins/app/_theme/global.sass +++ b/app/src/plugins/app/_theme/global.sass @@ -112,37 +112,6 @@ input[type="time"]::-webkit-calendar-picker-indicator a color: #fff -.copy-btn - position: absolute - right: 0 - width: 10% - height: 100% - text-align: center - bottom: 0 - border-top-right-radius: 9999px - border-bottom-right-radius: 9999px - padding-top: 4px - background: #808080 - color: #fff - - &:hover - cursor: pointer - background: #666666 - -.copying-btn - position: absolute - right: 0 - width: 10% - height: 100% - text-align: center - bottom: 0 - border-top-right-radius: 9999px - border-bottom-right-radius: 9999px - padding-top: 4px - background: rgb(76, 175, 80) - color: #fff - transition: background 0.3s ease, color 0.3s ease - @media (max-width: 534px) .mobile-view flex-direction: column From 935bde4bba69efde59b0ba67854e983443eca1da Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Wed, 3 Jul 2024 13:34:18 +0200 Subject: [PATCH 09/13] [windows copy link fix] --- .../plugins/tm@_utils/server-links.utils.ts | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/app/src/plugins/tm@_utils/server-links.utils.ts b/app/src/plugins/tm@_utils/server-links.utils.ts index c45b814..614c0a0 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -1,7 +1,13 @@ import { useToast } from 'vue-toast-notification'; const toast = useToast(); -window.toast = toast +declare global { + interface Window { + toast: typeof toast; + } +} + +window.toast = toast; export function detectOS() { const platform = window.navigator.platform @@ -18,7 +24,7 @@ export function detectOS() { export function prepareHTMLDescription(description) { if (!description) return description - + const os = detectOS() // make an array from the description of strings from between

and

tags @@ -57,10 +63,24 @@ export function prepareHTMLDescription(description) { function getCopyFunction(text) { return ` - navigator.clipboard.writeText('${text}').then(() => { + if (navigator.clipboard && navigator.clipboard.writeText) { + navigator.clipboard.writeText('${text}').then(() => { + window.toast.success('Link copied to clipboard!') + }).catch(err => { + window.toast.error('Failed to copy link to clipboard!') + }); + } else { + const input = document.createElement('input'); + input.style.position = 'fixed'; + input.style.opacity = 0; + input.style.pointerEvents = 'none'; + input.value = '\\\\${text}'; + document.body.appendChild(input); + input.select(); + input.focus(); + document.execCommand('copy'); + document.body.removeChild(input); window.toast.success('Link copied to clipboard!') - }).catch(err => { - window.toast.error('Failed to copy link to clipboard!') - }); + } ` } \ No newline at end of file From 86d97c01307dfc2b4458ebc22b1397628028b142 Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Wed, 3 Jul 2024 15:43:32 +0200 Subject: [PATCH 10/13] [macos links via href] --- app/src/plugins/tm@_utils/server-links.utils.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/plugins/tm@_utils/server-links.utils.ts b/app/src/plugins/tm@_utils/server-links.utils.ts index 614c0a0..22f972a 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -50,7 +50,9 @@ export function prepareHTMLDescription(description) { if (!link) return word - return `${link}` + if (os === 'mac') return `${link}` + + return `${link}` }) return `

${modifiedWords.join(' ')}

` @@ -63,8 +65,9 @@ export function prepareHTMLDescription(description) { function getCopyFunction(text) { return ` + console.log('${text.replace(/\\/g, '\\\\')}') if (navigator.clipboard && navigator.clipboard.writeText) { - navigator.clipboard.writeText('${text}').then(() => { + navigator.clipboard.writeText('${text.replace(/\\/g, '\\\\')}').then(() => { window.toast.success('Link copied to clipboard!') }).catch(err => { window.toast.error('Failed to copy link to clipboard!') @@ -74,7 +77,7 @@ function getCopyFunction(text) { input.style.position = 'fixed'; input.style.opacity = 0; input.style.pointerEvents = 'none'; - input.value = '\\\\${text}'; + input.value = '${text.replace(/\\/g, '\\\\')}'; document.body.appendChild(input); input.select(); input.focus(); From 25cb9014c4ff55834035aca7d1f2a43de2d68465 Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Tue, 9 Jul 2024 13:35:01 +0200 Subject: [PATCH 11/13] [server links] styling support (lists, bold, italic..) --- .../plugins/tm@_utils/server-links.utils.ts | 43 ++++++------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/app/src/plugins/tm@_utils/server-links.utils.ts b/app/src/plugins/tm@_utils/server-links.utils.ts index 22f972a..f52b3ff 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -27,45 +27,26 @@ export function prepareHTMLDescription(description) { const os = detectOS() - // make an array from the description of strings from between

and

tags - const paragraphs = description.split('

').map(p => p.split('

')[0]) + if (os === 'mac') { + description = description.replace(/\\\\/g, 'smb://') + + // find all smb links and replace them with clickable links, separated by ' ', '<', '>', '"', and '(', ')' characters + description = description.replace(/(smb:\/\/[^\s<>"()]+)/g, '$1') + } else { + description = description.replace(/smb:\/\//g, '\\\\') - const modifiedParagraphs = paragraphs.map(paragraph => { - const words = paragraph.split(' ') - const modifiedWords = words.map(word => { - let link = null - - if (os === 'mac' && word.startsWith('smb://')) { - link = word - } else if (os === 'win' && word.startsWith('\\\\')) { - link = `${word.replace(/\//g, '\\')}` - } else if (os === 'mac' && word.startsWith('\\\\')) { - const smbLink = 'smb:' + word.replace(/\\/g, '/') - link = smbLink - } else if (os === 'win' && word.startsWith('smb://')) { - const windowsLink = word.replace(/^smb:/, '').replace(/\//g, '\\') - link = `${windowsLink}` - } - - if (!link) return word - - if (os === 'mac') return `${link}` - - return `${link}` - }) - - return `

${modifiedWords.join(' ')}

` - }) - - description = modifiedParagraphs.join('') + // find all windows links and replace them with clickable links, separated by ' ', '<', '>', '"', and '(', ')' characters + description = description.replace(/(\\\\[^\s<>"()]+)/g, function(match) { + return '' + match + ''; + }); + } return description; } function getCopyFunction(text) { return ` - console.log('${text.replace(/\\/g, '\\\\')}') if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText('${text.replace(/\\/g, '\\\\')}').then(() => { window.toast.success('Link copied to clipboard!') From 4de8ffec1bbc7ad8d7431ca543ddc2d69f54036a Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Tue, 9 Jul 2024 15:31:02 +0200 Subject: [PATCH 12/13] [description] list indentation --- app/src/plugins/app/_theme/global.sass | 44 ++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/app/src/plugins/app/_theme/global.sass b/app/src/plugins/app/_theme/global.sass index 2382e8e..7ff4fb9 100644 --- a/app/src/plugins/app/_theme/global.sass +++ b/app/src/plugins/app/_theme/global.sass @@ -29,11 +29,6 @@ padding: 5px 20px min-width: 50px -.description-detail - background: rgba(0, 0, 0, 0.04) - color: rgba(0, 0, 0, 0.6) - height: fit-content - .employee-selected-avatar background: #6200EE color: #fff @@ -115,4 +110,41 @@ input[type="time"]::-webkit-calendar-picker-indicator @media (max-width: 534px) .mobile-view flex-direction: column - gap: 20px \ No newline at end of file + gap: 20px + +.description-detail + background: rgba(0, 0, 0, 0.04) + color: rgba(0, 0, 0, 0.6) + height: fit-content + + $indentSize: 15px + + li + margin-left: $indentSize + + &.ql-indent-1 + margin-left: 2 * $indentSize + + &.ql-indent-2 + margin-left: 3 * $indentSize + + &.ql-indent-3 + margin-left: 4 * $indentSize + + &.ql-indent-4 + margin-left: 5 * $indentSize + + &.ql-indent-5 + margin-left: 6 * $indentSize + + &.ql-indent-6 + margin-left: 7 * $indentSize + + &.ql-indent-7 + margin-left: 8 * $indentSize + + &.ql-indent-8 + margin-left: 9 * $indentSize + + &.ql-indent-9 + margin-left: 10 * $indentSize \ No newline at end of file From 3e23b72257835f25bf481bebfb8b4864a1ae2d95 Mon Sep 17 00:00:00 2001 From: JakubPapso <“jakubpapso@gmail.com”> Date: Thu, 11 Jul 2024 11:35:01 +0200 Subject: [PATCH 13/13] [server links] forward / backward slashes --- app/src/plugins/tm@_utils/server-links.utils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/plugins/tm@_utils/server-links.utils.ts b/app/src/plugins/tm@_utils/server-links.utils.ts index f52b3ff..aca5125 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -31,13 +31,16 @@ export function prepareHTMLDescription(description) { description = description.replace(/\\\\/g, 'smb://') // find all smb links and replace them with clickable links, separated by ' ', '<', '>', '"', and '(', ')' characters - description = description.replace(/(smb:\/\/[^\s<>"()]+)/g, '$1') + description = description = description.replace(/(smb:\/\/[^\s<>"()]+)/g, function(match) { + return '' + match.replace(/\\/g, '/') + '' + }) } else { description = description.replace(/smb:\/\//g, '\\\\') // find all windows links and replace them with clickable links, separated by ' ', '<', '>', '"', and '(', ')' characters description = description.replace(/(\\\\[^\s<>"()]+)/g, function(match) { + match = match.replaceAll('/', '\\') return '' + match + ''; }); }