Skip to content

Commit 7b8218e

Browse files
committed
refactor: simplify feedback widget integration by removing redundant loading functions and utilizing new CustomHeadLinks component for CSS/JS inclusion
1 parent 51cdcc7 commit 7b8218e

File tree

4 files changed

+21
-78
lines changed

4 files changed

+21
-78
lines changed

astro.config.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@ export default defineConfig({
77
devToolbar: {
88
enabled: false,
99
},
10-
vite: {
11-
define: {
12-
__FEEDBACK_DOMAIN__: JSON.stringify('https://nimiq-feedback.je-cf9.workers.dev'),
13-
},
14-
},
1510
integrations: [
1611
tutorialkit({
1712
components: {
1813
TopBar: './src/components/CustomTopBar.astro',
14+
HeadTags: './src/components/CustomHeadLinks.astro',
1915
},
2016
}),
2117
vue(),
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<slot name="title" />
2+
<slot name="links" />
3+
<slot name="meta" />
4+
5+
<!-- Nimiq Feedback Widget CSS/JS -->
6+
<link rel="preload" href="https://nimiq-feedback.je-cf9.workers.dev/widget.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
7+
<noscript><link rel="stylesheet" href="https://nimiq-feedback.je-cf9.workers.dev/widget.css"></noscript>
8+
<script src="https://nimiq-feedback.je-cf9.workers.dev/widget.js" defer></script>

src/components/FeedbackModal.vue

Lines changed: 12 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -17,56 +17,9 @@ const isWidgetLoaded = ref(false)
1717
const widgetInstance = ref<WidgetInstance>()
1818
const showFallbackForm = ref(false)
1919
20-
let cssLink: HTMLLinkElement
21-
let script: HTMLScriptElement
22-
23-
const FEEDBACK_DOMAIN = __FEEDBACK_DOMAIN__
24-
2520
const open = ref(false)
2621
27-
// Step 1: Load CSS with preload and fallback
28-
function loadWidgetCss() {
29-
if (document.getElementById('nimiq-feedback-css'))
30-
return
31-
cssLink = document.createElement('link')
32-
cssLink.id = 'nimiq-feedback-css'
33-
cssLink.rel = 'preload'
34-
cssLink.href = `${FEEDBACK_DOMAIN}/widget.css`
35-
cssLink.as = 'style'
36-
cssLink.crossOrigin = 'anonymous'
37-
cssLink.onload = () => {
38-
cssLink.onload = null
39-
cssLink.rel = 'stylesheet'
40-
}
41-
cssLink.onerror = () => {
42-
const fallback = document.createElement('link')
43-
fallback.rel = 'stylesheet'
44-
fallback.href = `${FEEDBACK_DOMAIN}/widget.css`
45-
fallback.crossOrigin = 'anonymous'
46-
document.head.appendChild(fallback)
47-
}
48-
document.head.appendChild(cssLink)
49-
}
50-
51-
// Step 2: Load JS with defer
52-
function loadWidgetScript() {
53-
return new Promise<void>((resolve, reject) => {
54-
if (typeof window.mountFeedbackWidget === 'function')
55-
return resolve()
56-
if (document.getElementById('nimiq-feedback-js'))
57-
return resolve()
58-
script = document.createElement('script')
59-
script.id = 'nimiq-feedback-js'
60-
script.src = `${FEEDBACK_DOMAIN}/widget.js`
61-
script.crossOrigin = 'anonymous'
62-
script.defer = true
63-
script.onload = () => resolve()
64-
script.onerror = () => reject(new Error('Failed to load feedback widget script'))
65-
document.head.appendChild(script)
66-
})
67-
}
68-
69-
// Step 3: Mount the widget after scripts are loaded
22+
// Step: Mount the widget after scripts are loaded
7023
async function mountWidget() {
7124
await nextTick()
7225
if (!widgetContainer.value)
@@ -75,7 +28,7 @@ async function mountWidget() {
7528
widgetInstance.value = window.mountFeedbackWidget('#feedback-widget', {
7629
app: 'nimiq-tutorial',
7730
lang: 'en',
78-
feedbackEndpoint: `${FEEDBACK_DOMAIN}/api/feedback`,
31+
feedbackEndpoint: 'https://nimiq-feedback.je-cf9.workers.dev/api/feedback',
7932
dev: import.meta.env.DEV,
8033
dark: document.documentElement.getAttribute('data-theme') === 'dark',
8134
})
@@ -89,10 +42,12 @@ async function mountWidget() {
8942
widgetInstance.value.communication?.on('form-error', (error) => {
9043
console.error('Feedback submission error:', error)
9144
})
45+
isWidgetLoaded.value = true
9246
}
9347
catch (error) {
9448
console.error('Failed to initialize feedback widget:', error)
9549
showFallbackForm.value = true
50+
isWidgetLoaded.value = false
9651
}
9752
}
9853
@@ -106,29 +61,23 @@ function cleanupWidget() {
10661
}
10762
}
10863
109-
function retryWidgetLoad() {
110-
showFallbackForm.value = false
111-
loadWidgetCss()
112-
loadWidgetScript()
113-
.then(() => isWidgetLoaded.value = true)
114-
.catch(() => {
115-
isWidgetLoaded.value = false
116-
showFallbackForm.value = true
117-
})
64+
function handleRetry() {
65+
open.value = false
66+
nextTick(() => {
67+
open.value = true
68+
})
11869
}
11970
12071
watch(open, async (newValue) => {
12172
if (newValue) {
12273
document.body.style.overflow = 'hidden'
12374
showFallbackForm.value = false
124-
loadWidgetCss()
12575
try {
126-
await loadWidgetScript()
127-
isWidgetLoaded.value = true
76+
await mountWidget()
12877
}
12978
catch {
130-
isWidgetLoaded.value = false
13179
showFallbackForm.value = true
80+
isWidgetLoaded.value = false
13281
}
13382
}
13483
else {
@@ -139,17 +88,8 @@ watch(open, async (newValue) => {
13988
}
14089
}, { immediate: false })
14190
142-
watch([isWidgetLoaded, open], async ([loaded, modalOpen]) => {
143-
if (loaded && modalOpen)
144-
await mountWidget()
145-
})
146-
14791
onUnmounted(() => {
14892
cleanupWidget()
149-
if (typeof cssLink !== 'undefined' && document.head.contains(cssLink))
150-
document.head.removeChild(cssLink)
151-
if (typeof script !== 'undefined' && document.head.contains(script))
152-
document.head.removeChild(script)
15393
})
15494
</script>
15595

@@ -204,7 +144,7 @@ onUnmounted(() => {
204144
</div>
205145
<button
206146
class="rounded-lg bg-blue-600 px-4 py-2 text-white transition-colors hover:bg-blue-700"
207-
@click="retryWidgetLoad"
147+
@click="handleRetry"
208148
>
209149
Try again
210150
</button>

src/types/feedback-widget.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ declare global {
3636
interface Window {
3737
mountFeedbackWidget: MountFeedbackWidgetFn
3838
}
39-
const __FEEDBACK_DOMAIN__: string
4039
}
4140

4241
export type MountFeedbackWidgetFn = (selector: string, props?: WidgetProps) => WidgetInstance

0 commit comments

Comments
 (0)