From f9a18fa4238d8121a195863127b2736f7c2ff543 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Sat, 17 Jan 2026 12:18:49 -0600 Subject: [PATCH] Fix clipboard copy and org settings navigation - Replace phx:copy event with CopyToClipboard LiveView hook for more reliable clipboard functionality - Add visual feedback (checkmark) when text is copied to clipboard - Apply hook to both agent token and docker compose copy buttons - Add readonly attribute to docker compose textarea - Fix org settings page to stay on settings after save instead of redirecting to dashboard The clipboard copy now works correctly by using a dedicated LiveView hook that directly handles the click event and clipboard API, rather than relying on custom event dispatching which was causing issues. --- assets/js/app.ts | 68 ++++++++++++++++--- .../live/agent_live/index.html.heex | 17 ++--- lib/towerops_web/live/org/settings_live.ex | 3 +- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/assets/js/app.ts b/assets/js/app.ts index f42bd115..2d03e9e0 100644 --- a/assets/js/app.ts +++ b/assets/js/app.ts @@ -284,7 +284,7 @@ if (!csrfToken) { const liveSocket = new LiveSocket("/live", Socket, { longPollFallbackMs: 2500, params: { _csrf_token: csrfToken }, - hooks: { ...colocatedHooks, SensorChart, WebAuthnRegister, WebAuthnLogin }, + hooks: { ...colocatedHooks, SensorChart, WebAuthnRegister, WebAuthnLogin, CopyToClipboard }, }) // Show progress bar on live navigation and form submits @@ -293,7 +293,9 @@ window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) window.addEventListener("phx:page-loading-stop", _info => topbar.hide()) // Handle clipboard copy events -window.addEventListener("phx:copy", (event) => { +window.addEventListener("phx:copy", (event: any) => { + // When using JS.dispatch with 'to:', the event is dispatched to that element + // and event.target will be that element const el = event.target as HTMLElement let text = "" @@ -304,14 +306,64 @@ window.addEventListener("phx:copy", (event) => { text = el.innerText || el.textContent || "" } - navigator.clipboard.writeText(text).then(() => { - // Optional: Show a success message or visual feedback - console.log('Copied to clipboard') - }).catch(err => { - console.error('Failed to copy text: ', err) - }) + if (text) { + navigator.clipboard.writeText(text).then(() => { + console.log('Copied to clipboard:', text.substring(0, 50) + (text.length > 50 ? '...' : '')) + }).catch(err => { + console.error('Failed to copy text:', err) + }) + } else { + console.warn('No text found to copy from element:', el) + } }) +// LiveView hook for copying to clipboard +const CopyToClipboard = { + mounted() { + this.el.addEventListener("click", (e) => { + e.preventDefault() + const targetId = this.el.dataset.target + if (!targetId) { + console.error("No data-target attribute found on copy button") + return + } + + const targetEl = document.querySelector(targetId) as HTMLInputElement | HTMLTextAreaElement | HTMLElement + if (!targetEl) { + console.error(`Target element not found: ${targetId}`) + return + } + + let text = "" + if (targetEl.tagName === "INPUT" || targetEl.tagName === "TEXTAREA") { + text = (targetEl as HTMLInputElement | HTMLTextAreaElement).value + } else { + text = targetEl.innerText || targetEl.textContent || "" + } + + if (text) { + navigator.clipboard.writeText(text).then(() => { + console.log('Copied to clipboard successfully') + // Optional: Show visual feedback + const originalText = this.el.innerHTML + this.el.innerHTML = ' Copied!' + setTimeout(() => { + this.el.innerHTML = originalText + }, 2000) + }).catch(err => { + console.error('Failed to copy:', err) + }) + } else { + console.error('No text found to copy') + } + }) + } +} + +const Hooks = { + CopyToClipboard +} + // connect if there are any LiveViews on the page liveSocket.connect() diff --git a/lib/towerops_web/live/agent_live/index.html.heex b/lib/towerops_web/live/agent_live/index.html.heex index f7745b8e..aac9f731 100644 --- a/lib/towerops_web/live/agent_live/index.html.heex +++ b/lib/towerops_web/live/agent_live/index.html.heex @@ -215,10 +215,9 @@ /> -