diff --git a/app/src/plugins/app/_theme/global.sass b/app/src/plugins/app/_theme/global.sass index 11f4eb7..2382e8e 100644 --- a/app/src/plugins/app/_theme/global.sass +++ b/app/src/plugins/app/_theme/global.sass @@ -106,8 +106,11 @@ 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 @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..22f972a 100644 --- a/app/src/plugins/tm@_utils/server-links.utils.ts +++ b/app/src/plugins/tm@_utils/server-links.utils.ts @@ -1,48 +1,14 @@ -export function getServerLinks(description) { - const os = detectOS() +import { useToast } from 'vue-toast-notification'; +const toast = useToast(); - // Create a temporary DOM element to manipulate the HTML content - const tempDiv = document.createElement('div') - tempDiv.innerHTML = description - - const links = new Set() - const paragraphs = tempDiv.querySelectorAll('p') - - paragraphs.forEach(p => { - const text = p.textContent.trim() - - if (os === 'mac' && text.startsWith('smb://')) { - links.add(`${text}`) - } else if (os === 'win' && text.startsWith('\\\\')) { - links.add(`${text}`) - } else if (os === 'mac' && text.startsWith('\\\\')) { - const smbLink = 'smb:' + text.replace(/\\/g, '/') - links.add(`${smbLink}`) - } else if (os === 'win' && text.startsWith('smb://')) { - const windowsLink = text.replace(/^smb:/, '').replace(/\//g, '\\') - links.add(`${windowsLink}`) - } - - const anchor = p.querySelector('a') - if (anchor) { - const href = anchor.getAttribute('href') - if (os === 'mac' && href.startsWith('smb://')) { - links.add(`${href}`) - } else if (os === 'win' && href.startsWith('\\\\')) { - links.add(`${href}`) - } else if (os === 'mac' && href.startsWith('\\\\')) { - const smbLink = 'smb:' + href.replace(/\\/g, '/') - links.add(`${smbLink}`) - } else if (os === 'win' && href.startsWith('smb://')) { - const windowsLink = href.replace(/^smb:/, '').replace(/\//g, '\\') - links.add(`${windowsLink}`) - } - } - }) - - return Array.from(links).join('
') +declare global { + interface Window { + toast: typeof toast; + } } +window.toast = toast; + export function detectOS() { const platform = window.navigator.platform const macosPlatforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'] @@ -54,4 +20,70 @@ export function detectOS() { return 'win' } return 'win' +} + +export function prepareHTMLDescription(description) { + if (!description) return 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]) + + 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('') + + 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!') + }).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.replace(/\\/g, '\\\\')}'; + document.body.appendChild(input); + input.select(); + input.focus(); + document.execCommand('copy'); + document.body.removeChild(input); + window.toast.success('Link copied to clipboard!') + } + ` } \ No newline at end of file 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..e15160b 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 @@ -1,22 +1,17 @@ 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 922ed94..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,27 +1,17 @@ \ No newline at end of file