rivia 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2895 -59
- package/index.d.ts +8 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,7 +32,8 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
32
32
|
id: it.id || `step${i2 + 1}`,
|
|
33
33
|
title: it.heading || `Step ${i2 + 1}`,
|
|
34
34
|
description: it.body || "",
|
|
35
|
-
|
|
35
|
+
event_name: it.event_name || "",
|
|
36
|
+
button_name: it.button_name || "",
|
|
36
37
|
url: it.url || slugify(it.title || `step-${i2 + 1}`),
|
|
37
38
|
color: it.color || null
|
|
38
39
|
})) : [];
|
|
@@ -72,18 +73,20 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
72
73
|
let storedVisited = JSON.parse(
|
|
73
74
|
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
74
75
|
);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
if (!Array.isArray(storedVisited)) storedVisited = [];
|
|
77
|
+
let user_var12 = user_var;
|
|
78
|
+
if (!user_var12) {
|
|
79
|
+
user_var12 = "User_" + Math.random().toString(36).substring(2, 8);
|
|
80
|
+
sessionStorage.setItem(user_var, user_var12);
|
|
79
81
|
}
|
|
80
|
-
const backendUrl = `
|
|
81
|
-
async function
|
|
82
|
+
const backendUrl = `http://localhost:5000/clients/${checklist_id}/${user_var12}`;
|
|
83
|
+
async function getUserProgress22() {
|
|
84
|
+
const backendUrl2 = `http://localhost:5000/clients/${checklist_id}/${user_var12}`;
|
|
82
85
|
try {
|
|
83
|
-
const res = await fetch(
|
|
86
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
84
87
|
if (!res.ok) throw new Error(`GET failed: ${res.status}`);
|
|
85
88
|
const data2 = await res.json();
|
|
86
|
-
let userData = data2[
|
|
89
|
+
let userData = data2[user_var12];
|
|
87
90
|
if (Array.isArray(userData)) {
|
|
88
91
|
storedVisited = userData;
|
|
89
92
|
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
@@ -100,12 +103,11 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
100
103
|
end_date: userData?.end_date || userData?.end_data || ""
|
|
101
104
|
};
|
|
102
105
|
} catch (err) {
|
|
103
|
-
console.warn(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
"onboardingVisited",
|
|
107
|
-
JSON.stringify(storedVisited2)
|
|
106
|
+
console.warn(
|
|
107
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
108
|
+
err
|
|
108
109
|
);
|
|
110
|
+
const storedVisited2 = [];
|
|
109
111
|
return {
|
|
110
112
|
completedPages: [],
|
|
111
113
|
progress: 0,
|
|
@@ -116,9 +118,45 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
storedVisited = sessionStorage.getItem("onboardingVisited");
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
async function getUserProgress22() {
|
|
122
|
+
const backendUrl2 = `http://localhost:5000/clients/${checklist_id}/${user_var12}`;
|
|
123
|
+
try {
|
|
124
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
125
|
+
if (!res.ok) throw new Error(`GET failed: ${res.status}`);
|
|
126
|
+
const data2 = await res.json();
|
|
127
|
+
let userData = data2[user_var12];
|
|
128
|
+
if (Array.isArray(userData)) {
|
|
129
|
+
storedVisited = userData;
|
|
130
|
+
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
131
|
+
storedVisited = userData.completed_items;
|
|
132
|
+
} else {
|
|
133
|
+
storedVisited = [];
|
|
134
|
+
}
|
|
135
|
+
let path;
|
|
136
|
+
return {
|
|
137
|
+
completedPages: storedVisited,
|
|
138
|
+
progress: storedVisited.length,
|
|
139
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
140
|
+
start_date: userData?.start_date || "",
|
|
141
|
+
end_date: userData?.end_date || userData?.end_data || ""
|
|
142
|
+
};
|
|
143
|
+
} catch (err) {
|
|
144
|
+
console.warn(
|
|
145
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
146
|
+
err
|
|
147
|
+
);
|
|
148
|
+
return {
|
|
149
|
+
completedPages: [],
|
|
150
|
+
progress: 0,
|
|
151
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
152
|
+
start_date: "",
|
|
153
|
+
end_date: ""
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (!storedVisited || storedVisited == "[]") {
|
|
158
|
+
getUserProgress22().then((progressData) => {
|
|
159
|
+
if (storedVisited && storedVisited.length >= checklistItems.length) {
|
|
122
160
|
return;
|
|
123
161
|
}
|
|
124
162
|
sessionStorage.setItem(
|
|
@@ -153,7 +191,7 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
153
191
|
);
|
|
154
192
|
storedVisited = [];
|
|
155
193
|
}
|
|
156
|
-
if (storedVisited.length >= checklistItems.length) {
|
|
194
|
+
if (storedVisited && storedVisited.length >= checklistItems.length) {
|
|
157
195
|
if (sessionStorage.getItem("CompletedAll") != "true") return;
|
|
158
196
|
const label = document.createElement("div");
|
|
159
197
|
label.id = "route-label";
|
|
@@ -204,6 +242,9 @@ function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklis
|
|
|
204
242
|
}
|
|
205
243
|
}
|
|
206
244
|
async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id, cssConfig = {}, items = [], storedVisited = [], backendUrl = "", progressData = {}, visitedPages = {}, cleanUrlItems = []) {
|
|
245
|
+
console.log("inside fetchWithTimeout", user_var);
|
|
246
|
+
if (!user_var)
|
|
247
|
+
return;
|
|
207
248
|
let i = 0;
|
|
208
249
|
const stepsHTML = items.map((it) => {
|
|
209
250
|
const border = it.color || cssConfig.borderColor1;
|
|
@@ -220,7 +261,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
220
261
|
|
|
221
262
|
<div class="onboard-circle"
|
|
222
263
|
style="min-width:16px; min-height:16px; width:16px; height:16px; border-radius:50%;
|
|
223
|
-
border:2px solid ${cssConfig.
|
|
264
|
+
border:2px solid ${cssConfig.lowerCheckboxColor}; margin-right:10px; box-sizing:border-box;"></div>
|
|
224
265
|
|
|
225
266
|
<div class="onboard-text"
|
|
226
267
|
style=" font-family:${cssConfig.fontFamily}; font-size:${cssConfig.fontSize};">
|
|
@@ -256,7 +297,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
256
297
|
<p style="margin-top:8px;color: ${cssConfig.subtitleColor};">${subtitle}</p>
|
|
257
298
|
<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px;">
|
|
258
299
|
<div id="progressContainer" style="display: flex; gap: 4px; width: 300%; width: 800px; height: 10px;"></div>
|
|
259
|
-
<span id="progressFraction" style="margin-left: 0px; font-size: 13px; color: ${cssConfig.textColor}; min-width: 20px; text-align: right;">0/0
|
|
300
|
+
<span id="progressFraction" style="margin-left: 0px; font-size: 13px; color: ${cssConfig.textColor}; min-width: 20px; text-align: right;">0/0 </span>
|
|
260
301
|
</div>
|
|
261
302
|
|
|
262
303
|
</div>
|
|
@@ -314,7 +355,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
314
355
|
});
|
|
315
356
|
}
|
|
316
357
|
createSlabs(items.length);
|
|
317
|
-
updateProgress(storedVisited.length);
|
|
358
|
+
if (storedVisited) updateProgress(storedVisited.length);
|
|
318
359
|
Object.assign(label.style, {
|
|
319
360
|
position: "fixed",
|
|
320
361
|
bottom: "80px",
|
|
@@ -360,29 +401,106 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
360
401
|
});
|
|
361
402
|
}
|
|
362
403
|
showBtn.id = "show-tooltip-btn";
|
|
404
|
+
const translateStyle = cssConfig.launcherProgressBar ? 'style="transform: translateY(10px);"' : "";
|
|
405
|
+
const iconHTML = cssConfig.launcherShowIcon ? `<svg width="24" height="24" ${translateStyle} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
406
|
+
<path d="M8 10.167L12.123 6.043C13.248 4.919 13.811 4.356 14.431 3.903C15.7049 2.97403 17.1822 2.36274 18.74 2.12C19.499 2 20.293 2 21.885 2C21.968 2 22 2.038 22 2.115C22 3.705 22 4.501 21.881 5.26C21.638 6.81791 21.0263 8.29523 20.097 9.569C19.644 10.189 19.081 10.752 17.957 11.877L13.833 16" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
407
|
+
<path d="M10.341 8.098C8.638 8.098 6.498 7.738 4.904 8.398C3.737 8.88 2.878 10 2 10.878L5.306 12.296C6.182 12.671 5.646 13.776 5.501 14.502C5.34 15.31 5.349 15.34 5.931 15.922L8.078 18.068C8.66 18.651 8.69 18.66 9.498 18.498C10.223 18.353 11.329 17.818 11.704 18.694L13.121 22C13.999 21.122 15.119 20.263 15.602 19.096C16.262 17.502 15.902 15.362 15.902 13.659" stroke="white" stroke-width="1.5" stroke-linejoin="round"/>
|
|
408
|
+
<path d="M12 20L11 21M4 12L3 13" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
409
|
+
<path d="M15 4.08008C16.2 4.26008 17.46 4.74008 18.161 5.46008C19.058 6.25208 19.68 7.32008 19.92 9.00008" stroke="white" stroke-width="1.5" stroke-linecap="square"/>
|
|
410
|
+
<path d="M17.94 6.05957L16.5 7.49957" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
|
411
|
+
</svg>` : "";
|
|
412
|
+
const progressPaddingLeft = cssConfig.launcherShowIcon ? "28px" : "0px";
|
|
413
|
+
const textTranslateStyle = !cssConfig.launcherProgressBar ? " translateY(50%);" : "";
|
|
363
414
|
showBtn.innerHTML = `
|
|
364
|
-
<
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
415
|
+
<div style="display:flex; align-items:center; gap:12px; width:100%;">
|
|
416
|
+
|
|
417
|
+
<!-- LEFT COLUMN -->
|
|
418
|
+
<div style="flex:1; display:flex; flex-direction:column; box-sizing:border-box; padding-left:${progressPaddingLeft};">
|
|
419
|
+
|
|
420
|
+
<!-- TITLE ROW -->
|
|
421
|
+
<h3 style="
|
|
422
|
+
margin:0;
|
|
423
|
+
position:relative;
|
|
424
|
+
height:24px;
|
|
425
|
+
line-height:1;
|
|
426
|
+
">
|
|
427
|
+
<!-- ICON: fixed original position -->
|
|
428
|
+
<span style="
|
|
429
|
+
position:absolute;
|
|
430
|
+
left:-20px;
|
|
431
|
+
top:50%;
|
|
432
|
+
transform:translateY(-50%);
|
|
433
|
+
display:flex;
|
|
434
|
+
align-items:center;
|
|
435
|
+
">
|
|
436
|
+
${iconHTML}
|
|
437
|
+
</span>
|
|
438
|
+
|
|
439
|
+
<!-- TEXT: centered over progress bar -->
|
|
440
|
+
<span style="
|
|
441
|
+
display:block;
|
|
442
|
+
width:100%;
|
|
443
|
+
padding-left:5%;
|
|
444
|
+
text-align:center;
|
|
445
|
+
transform: ${textTranslateStyle};
|
|
446
|
+
pointer-events:none;
|
|
447
|
+
">
|
|
448
|
+
${cssConfig.launcher_text}
|
|
449
|
+
</span>
|
|
450
|
+
</h3>
|
|
451
|
+
|
|
452
|
+
<!-- PROGRESS BAR -->
|
|
453
|
+
<div style="width:100%; margin-top:6px;">
|
|
454
|
+
<div id="progressContainerBtn" style="
|
|
455
|
+
display:flex;
|
|
456
|
+
gap:4px;
|
|
457
|
+
width:100%;
|
|
458
|
+
padding:5px;
|
|
459
|
+
height:3px;
|
|
460
|
+
box-sizing:border-box;
|
|
461
|
+
"></div>
|
|
462
|
+
</div>
|
|
463
|
+
</div>
|
|
464
|
+
|
|
465
|
+
<!-- RIGHT COLUMN: fraction -->
|
|
466
|
+
<div style="flex-shrink:0; display:flex; align-items:center;">
|
|
467
|
+
<span id="progressFraction" style="
|
|
468
|
+
font-size:13px;
|
|
469
|
+
white-space:nowrap;
|
|
470
|
+
color:${cssConfig.launcherTextColor};
|
|
471
|
+
padding:2px;
|
|
472
|
+
min-width:10px;
|
|
473
|
+
text-align:right;
|
|
474
|
+
">
|
|
475
|
+
0/0
|
|
476
|
+
</span>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
`;
|
|
480
|
+
const isRight = cssConfig.launcherPosition === "right";
|
|
369
481
|
Object.assign(showBtn.style, {
|
|
370
482
|
position: "fixed",
|
|
371
|
-
bottom: "20px",
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
483
|
+
bottom: cssConfig.launcherSpacingBottom || "20px",
|
|
484
|
+
// Horizontal positioning
|
|
485
|
+
left: isRight ? "auto" : cssConfig.launcherSpacingLeft || "20px",
|
|
486
|
+
right: isRight ? cssConfig.launcherSpacingRight || "20px" : "auto",
|
|
487
|
+
width: cssConfig.launcherWidth ? `${cssConfig.launcherWidth}px` : "150px",
|
|
488
|
+
height: cssConfig.launcherHeight ? `${cssConfig.launcherHeight}px` : "78px",
|
|
375
489
|
fontSize: cssConfig.fontSize,
|
|
376
490
|
fontWeight: "bold",
|
|
377
|
-
backgroundColor: cssConfig.
|
|
378
|
-
color: cssConfig.
|
|
491
|
+
backgroundColor: cssConfig.launcherBackgroundColor,
|
|
492
|
+
color: cssConfig.launcherTextColor,
|
|
379
493
|
border: "none",
|
|
380
|
-
borderRadius: "6px",
|
|
494
|
+
borderRadius: cssConfig.showBtnBorderRadius || "6px",
|
|
381
495
|
cursor: "pointer",
|
|
382
496
|
zIndex: 9999,
|
|
383
497
|
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)"
|
|
384
498
|
});
|
|
385
499
|
document.body.appendChild(showBtn);
|
|
500
|
+
if (!cssConfig.launcherProgressBar) {
|
|
501
|
+
document.getElementById("progressContainerBtn").style.display = "none";
|
|
502
|
+
document.getElementById("progressFraction").style.display = "none";
|
|
503
|
+
}
|
|
386
504
|
document.body.appendChild(label);
|
|
387
505
|
createS(items.length);
|
|
388
506
|
const closeBtn = document.createElement("button");
|
|
@@ -409,12 +527,290 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
409
527
|
closeBtn.style.left = `${Math.max(8, rect.left + rect.width / 2 - 170)}px`;
|
|
410
528
|
closeBtn.style.top = `${rect.bottom + 10}px`;
|
|
411
529
|
}
|
|
412
|
-
|
|
413
|
-
|
|
530
|
+
let check = 0;
|
|
531
|
+
console.log("before");
|
|
532
|
+
const EVENT_SRC_URL = "http://localhost:5000/events";
|
|
533
|
+
if (!window._onboardingEventSource) {
|
|
534
|
+
window._onboardingEventSource = new EventSource(EVENT_SRC_URL);
|
|
535
|
+
}
|
|
536
|
+
const eventSource = window._onboardingEventSource;
|
|
537
|
+
const STORAGE_KEY = "onboardingVisited";
|
|
538
|
+
const visitedSet = new Set(
|
|
539
|
+
JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "[]")
|
|
540
|
+
);
|
|
541
|
+
const processedMessages = /* @__PURE__ */ new Set();
|
|
542
|
+
function persistVisited() {
|
|
543
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify([...visitedSet]));
|
|
544
|
+
}
|
|
545
|
+
function handleVisit(cleanUrl, opts = { source: "unknown" }) {
|
|
546
|
+
if (!cleanUrl) return false;
|
|
547
|
+
if (typeof cleanUrl !== "string") return false;
|
|
548
|
+
if (!cleanUrlItems || !cleanUrlItems.includes(cleanUrl)) {
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
if (visitedSet.has(cleanUrl)) {
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
visitedSet.add(cleanUrl);
|
|
555
|
+
storedVisited = [...visitedSet];
|
|
556
|
+
persistVisited();
|
|
557
|
+
try {
|
|
558
|
+
uploadVisitedPagesInBackground([...visitedSet], true);
|
|
559
|
+
} catch (e) {
|
|
560
|
+
console.warn("uploadVisitedPagesInBackground failed", e);
|
|
561
|
+
}
|
|
562
|
+
updateProgress(visitedSet.size);
|
|
563
|
+
updateProgress2(visitedSet.size);
|
|
564
|
+
updateUIFromVisited();
|
|
565
|
+
console.log(`handleVisit: added ${cleanUrl} (source=${opts.source})`);
|
|
566
|
+
if (visitedSet.size >= (checklistItems ? checklistItems.length : Infinity)) {
|
|
567
|
+
sessionStorage.setItem("CompletedAll", "true");
|
|
568
|
+
}
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
571
|
+
eventSource.onopen = () => console.log("SSE connected");
|
|
572
|
+
eventSource.onerror = (err) => console.log("SSE connection error:", err);
|
|
573
|
+
eventSource.onmessage = (event) => {
|
|
574
|
+
if (!event || !event.data) return;
|
|
575
|
+
check = 1;
|
|
576
|
+
let data;
|
|
577
|
+
try {
|
|
578
|
+
data = JSON.parse(event.data);
|
|
579
|
+
} catch (err) {
|
|
580
|
+
console.error("Invalid SSE JSON:", event.data, err);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
if (data.ping) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const msg = data.message;
|
|
587
|
+
if (!msg) return;
|
|
588
|
+
if (processedMessages.has(msg)) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
processedMessages.add(msg);
|
|
592
|
+
const it = items.find((i2) => i2.event_name && i2.event_name === msg);
|
|
593
|
+
if (!it) {
|
|
594
|
+
console.log("SSE message doesn't match any item:", msg);
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
try {
|
|
598
|
+
const stepEl = label ? label.querySelector(`#${it.id}`) : null;
|
|
599
|
+
if (stepEl) {
|
|
600
|
+
const startSelect = stepEl.querySelector(".start-select");
|
|
601
|
+
if (startSelect) startSelect.style.display = "none";
|
|
602
|
+
}
|
|
603
|
+
} catch (err) {
|
|
604
|
+
}
|
|
605
|
+
const path = it.url || "";
|
|
606
|
+
const cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
607
|
+
handleVisit(cleanUrl, { source: "sse" });
|
|
608
|
+
if (storedVisited.length >= checklistItems.length) {
|
|
609
|
+
console.log("All items completed via SSE");
|
|
610
|
+
if (label && label.parentNode) label.remove();
|
|
611
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
612
|
+
const label3 = document.createElement("div");
|
|
613
|
+
label3.id = "route-label";
|
|
614
|
+
label3.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
615
|
+
Object.assign(label3.style, {
|
|
616
|
+
position: "fixed",
|
|
617
|
+
bottom: "20px",
|
|
618
|
+
left: "20px",
|
|
619
|
+
backgroundColor: "#4CAF50",
|
|
620
|
+
color: "white",
|
|
621
|
+
padding: "10px 20px",
|
|
622
|
+
borderRadius: "10px",
|
|
623
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
624
|
+
fontSize: "16px",
|
|
625
|
+
fontWeight: "bold",
|
|
626
|
+
zIndex: 9999,
|
|
627
|
+
opacity: 0,
|
|
628
|
+
transition: "opacity 0.5s ease"
|
|
629
|
+
});
|
|
630
|
+
document.body.appendChild(label3);
|
|
631
|
+
}
|
|
632
|
+
console.log("Received event (SSE):", msg);
|
|
633
|
+
};
|
|
634
|
+
console.log("after");
|
|
635
|
+
function findButtonByText(buttonText) {
|
|
636
|
+
if (!buttonText) return null;
|
|
637
|
+
const needle = buttonText.trim().toLowerCase();
|
|
638
|
+
const buttons = document.querySelectorAll("button");
|
|
639
|
+
for (const button of buttons) {
|
|
640
|
+
if (!button.textContent) continue;
|
|
641
|
+
if (button.textContent.trim().toLowerCase().includes(needle)) {
|
|
642
|
+
return button;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
function attachButtonForItem(it) {
|
|
648
|
+
const btn = findButtonByText(it.button_name);
|
|
649
|
+
if (!btn) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
if (btn._onboardingAttached) return;
|
|
653
|
+
btn._onboardingAttached = true;
|
|
654
|
+
btn.addEventListener("click", (e) => {
|
|
655
|
+
check = 1;
|
|
656
|
+
const path = it.url || "";
|
|
657
|
+
const cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
658
|
+
if (storedVisited.length >= checklistItems.length) {
|
|
659
|
+
(() => {
|
|
660
|
+
if (label2 && label2.parentNode) label2.remove();
|
|
661
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
662
|
+
const label2 = document.createElement("div");
|
|
663
|
+
label2.id = "route-label";
|
|
664
|
+
label2.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
665
|
+
Object.assign(label2.style, {
|
|
666
|
+
position: "fixed",
|
|
667
|
+
bottom: "20px",
|
|
668
|
+
left: "20px",
|
|
669
|
+
backgroundColor: "#4CAF50",
|
|
670
|
+
color: "white",
|
|
671
|
+
padding: "10px 20px",
|
|
672
|
+
borderRadius: "10px",
|
|
673
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
674
|
+
fontSize: "16px",
|
|
675
|
+
fontWeight: "bold",
|
|
676
|
+
zIndex: 9999,
|
|
677
|
+
opacity: 0,
|
|
678
|
+
transition: "opacity 0.5s ease"
|
|
679
|
+
});
|
|
680
|
+
document.body.appendChild(label2);
|
|
681
|
+
})();
|
|
682
|
+
}
|
|
683
|
+
handleVisit(cleanUrl, { source: "click" });
|
|
684
|
+
if (storedVisited.length >= checklistItems.length) {
|
|
685
|
+
(() => {
|
|
686
|
+
if (label && label.parentNode) label.remove();
|
|
687
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
688
|
+
const label3 = document.createElement("div");
|
|
689
|
+
label3.id = "route-label";
|
|
690
|
+
label3.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
691
|
+
Object.assign(label3.style, {
|
|
692
|
+
position: "fixed",
|
|
693
|
+
bottom: "20px",
|
|
694
|
+
left: "20px",
|
|
695
|
+
backgroundColor: "#4CAF50",
|
|
696
|
+
color: "white",
|
|
697
|
+
padding: "10px 20px",
|
|
698
|
+
borderRadius: "10px",
|
|
699
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
700
|
+
fontSize: "16px",
|
|
701
|
+
fontWeight: "bold",
|
|
702
|
+
zIndex: 9999,
|
|
703
|
+
opacity: 0,
|
|
704
|
+
transition: "opacity 0.5s ease"
|
|
705
|
+
});
|
|
706
|
+
document.body.appendChild(label3);
|
|
707
|
+
})();
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
items.forEach(attachButtonForItem);
|
|
712
|
+
const mo = new MutationObserver((mutations) => {
|
|
713
|
+
items.forEach(attachButtonForItem);
|
|
714
|
+
});
|
|
715
|
+
mo.observe(document.body, { childList: true, subtree: true });
|
|
716
|
+
window.addEventListener("storage", (e) => {
|
|
717
|
+
if (e.key === STORAGE_KEY) {
|
|
718
|
+
const arr = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "[]");
|
|
719
|
+
visitedSet.clear();
|
|
720
|
+
arr.forEach((a) => visitedSet.add(a));
|
|
721
|
+
updateUIFromVisited();
|
|
722
|
+
updateProgress(visitedSet.size);
|
|
723
|
+
updateProgress2(visitedSet.size);
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
if (!window._onboardingEventSource) {
|
|
727
|
+
window._onboardingEventSource = new EventSource(EVENT_SRC_URL);
|
|
728
|
+
}
|
|
729
|
+
eventSource.onopen = () => console.log("SSE connected");
|
|
730
|
+
eventSource.onerror = (err) => console.log("SSE connection error:", err);
|
|
731
|
+
eventSource.onmessage = (event) => {
|
|
732
|
+
if (!event || !event.data) return;
|
|
733
|
+
check = 1;
|
|
734
|
+
let data;
|
|
735
|
+
try {
|
|
736
|
+
data = JSON.parse(event.data);
|
|
737
|
+
} catch (err) {
|
|
738
|
+
console.error("Invalid SSE JSON:", event.data, err);
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
if (data.ping) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
const msg = data.message;
|
|
745
|
+
console.log("SSE message received:", msg);
|
|
746
|
+
if (!msg) return;
|
|
747
|
+
if (processedMessages.has(msg)) {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
processedMessages.add(msg);
|
|
751
|
+
const it = items.find((i2) => i2.event_name && i2.event_name === msg);
|
|
752
|
+
if (!it) {
|
|
753
|
+
console.log("SSE message doesn't match any item:", msg);
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
const eventId = data.event_id;
|
|
757
|
+
try {
|
|
758
|
+
fetch("http://localhost:5000/ack-event", {
|
|
759
|
+
method: "POST",
|
|
760
|
+
headers: { "Content-Type": "application/json" },
|
|
761
|
+
body: JSON.stringify({ event_id: eventId })
|
|
762
|
+
});
|
|
763
|
+
console.log("ACK sent for", eventId);
|
|
764
|
+
} catch (err) {
|
|
765
|
+
console.error("Failed to ACK", eventId, err);
|
|
766
|
+
}
|
|
767
|
+
try {
|
|
768
|
+
const stepEl = label ? label.querySelector(`#${it.id}`) : null;
|
|
769
|
+
if (stepEl) {
|
|
770
|
+
const startSelect = stepEl.querySelector(".start-select");
|
|
771
|
+
if (startSelect) startSelect.style.display = "none";
|
|
772
|
+
}
|
|
773
|
+
} catch (err) {
|
|
774
|
+
}
|
|
775
|
+
const path = it.url || "";
|
|
776
|
+
const cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
777
|
+
handleVisit(cleanUrl, { source: "sse" });
|
|
778
|
+
if (storedVisited.length >= checklistItems.length) {
|
|
779
|
+
console.log("All items completed via SSE");
|
|
780
|
+
(() => {
|
|
781
|
+
if (label && label.parentNode) label.remove();
|
|
782
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
783
|
+
const label3 = document.createElement("div");
|
|
784
|
+
label3.id = "route-label";
|
|
785
|
+
label3.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
786
|
+
Object.assign(label3.style, {
|
|
787
|
+
position: "fixed",
|
|
788
|
+
bottom: "20px",
|
|
789
|
+
left: "20px",
|
|
790
|
+
backgroundColor: "#4CAF50",
|
|
791
|
+
color: "white",
|
|
792
|
+
padding: "10px 20px",
|
|
793
|
+
borderRadius: "10px",
|
|
794
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
795
|
+
fontSize: "16px",
|
|
796
|
+
fontWeight: "bold",
|
|
797
|
+
zIndex: 9999,
|
|
798
|
+
opacity: 0,
|
|
799
|
+
transition: "opacity 0.5s ease"
|
|
800
|
+
});
|
|
801
|
+
document.body.appendChild(label3);
|
|
802
|
+
})();
|
|
803
|
+
}
|
|
804
|
+
console.log("Received event (SSE):", msg);
|
|
805
|
+
};
|
|
806
|
+
let user_var2 = user_var;
|
|
414
807
|
function uploadVisitedPagesInBackground(completed2, touched = false) {
|
|
808
|
+
let activeStepId2 = sessionStorage.getItem("activeStepId") || null;
|
|
809
|
+
let user_var22 = user_var;
|
|
810
|
+
const backendUrl22 = `http://localhost:5000/clients/${checklist_id}`;
|
|
415
811
|
try {
|
|
416
812
|
const payload = {
|
|
417
|
-
name:
|
|
813
|
+
name: user_var22,
|
|
418
814
|
completed_items: completed2,
|
|
419
815
|
touched
|
|
420
816
|
};
|
|
@@ -433,7 +829,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
433
829
|
console.error("\u274C Error preparing background upload:", err);
|
|
434
830
|
}
|
|
435
831
|
}
|
|
436
|
-
uploadVisitedPagesInBackground(
|
|
832
|
+
if (check == 0) uploadVisitedPagesInBackground(storedVisited, false);
|
|
437
833
|
let activeStepId = sessionStorage.getItem("activeStepId") || null;
|
|
438
834
|
function updateUIFromVisited() {
|
|
439
835
|
storedVisited = JSON.parse(
|
|
@@ -441,8 +837,45 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
441
837
|
);
|
|
442
838
|
let path;
|
|
443
839
|
storedVisited = sessionStorage.getItem("onboardingVisited");
|
|
444
|
-
if (!storedVisited) {
|
|
445
|
-
|
|
840
|
+
if (!storedVisited || storedVisited == "[]") {
|
|
841
|
+
async function getUserProgress22() {
|
|
842
|
+
const backendUrl2 = `http://localhost:5000/clients/${checklist_id}/${user_var}`;
|
|
843
|
+
try {
|
|
844
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
845
|
+
if (!res.ok) throw new Error(`GET failed: ${res.status}`);
|
|
846
|
+
const data2 = await res.json();
|
|
847
|
+
let userData = data2[user_var1];
|
|
848
|
+
if (Array.isArray(userData)) {
|
|
849
|
+
storedVisited = userData;
|
|
850
|
+
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
851
|
+
storedVisited = userData.completed_items;
|
|
852
|
+
} else {
|
|
853
|
+
storedVisited = [];
|
|
854
|
+
}
|
|
855
|
+
let path2;
|
|
856
|
+
return {
|
|
857
|
+
completedPages: storedVisited,
|
|
858
|
+
progress: storedVisited.length,
|
|
859
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
860
|
+
start_date: userData?.start_date || "",
|
|
861
|
+
end_date: userData?.end_date || userData?.end_data || ""
|
|
862
|
+
};
|
|
863
|
+
} catch (err) {
|
|
864
|
+
console.warn(
|
|
865
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
866
|
+
err
|
|
867
|
+
);
|
|
868
|
+
const storedVisited2 = [];
|
|
869
|
+
return {
|
|
870
|
+
completedPages: [],
|
|
871
|
+
progress: 0,
|
|
872
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
873
|
+
start_date: "",
|
|
874
|
+
end_date: ""
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
getUserProgress22().then((progressData2) => {
|
|
446
879
|
let completed2 = progressData2.completedPages;
|
|
447
880
|
completed2.forEach((path2) => {
|
|
448
881
|
const stepId = visitedPages[path2];
|
|
@@ -454,9 +887,9 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
454
887
|
<div style="background-color: green; border-radius: 50%; width: 30px; height: 18px; display: flex; align-items: center; justify-content: center;">
|
|
455
888
|
<svg width="16" height="16" viewBox="0 0 512 512" fill="white" xmlns="http://www.w3.org/2000/svg">
|
|
456
889
|
<path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206
|
|
457
|
-
0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
|
|
458
|
-
36.204 0L192 312.69 432.095 72.596c9.997-9.997
|
|
459
|
-
26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
|
|
890
|
+
0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
|
|
891
|
+
36.204 0L192 312.69 432.095 72.596c9.997-9.997
|
|
892
|
+
26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
|
|
460
893
|
9.997 26.206 0 36.204l-294.4 294.401c-9.998
|
|
461
894
|
9.997-26.207 9.997-36.204-.001z"/>
|
|
462
895
|
</svg>
|
|
@@ -515,6 +948,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
515
948
|
completed2 = [];
|
|
516
949
|
}
|
|
517
950
|
completed2.forEach((path2) => {
|
|
951
|
+
let activeStepId2 = sessionStorage.getItem("activeStepId") || null;
|
|
518
952
|
const stepId = visitedPages[path2];
|
|
519
953
|
const stepElement = label.querySelector(`#${stepId}`);
|
|
520
954
|
if (!stepElement) return;
|
|
@@ -541,7 +975,7 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
541
975
|
}
|
|
542
976
|
const textContainer = stepElement.querySelector(".onboard-text");
|
|
543
977
|
const startSelect = stepElement.querySelector(".start-select");
|
|
544
|
-
if (stepId ===
|
|
978
|
+
if (stepId === activeStepId2 && startSelect) {
|
|
545
979
|
startSelect.style.display = "block";
|
|
546
980
|
}
|
|
547
981
|
if (textContainer) {
|
|
@@ -576,12 +1010,12 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
576
1010
|
}
|
|
577
1011
|
if (completion == 0) {
|
|
578
1012
|
items.forEach((it) => {
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
1013
|
+
const stepEl = label.querySelector(`#${it.id}`);
|
|
1014
|
+
if (!stepEl) return;
|
|
1015
|
+
const startSelect = stepEl.querySelector(".start-select");
|
|
1016
|
+
startSelect.style.display = "none";
|
|
1017
|
+
stepEl.addEventListener("click", () => {
|
|
1018
|
+
if (it.event_name == "" && it.button_name == "") {
|
|
585
1019
|
items.forEach((inner) => {
|
|
586
1020
|
const el = label.querySelector(`#${inner.id}`);
|
|
587
1021
|
if (el) {
|
|
@@ -595,8 +1029,8 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
595
1029
|
storedVisited = JSON.parse(
|
|
596
1030
|
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
597
1031
|
);
|
|
598
|
-
if (!storedVisited) {
|
|
599
|
-
|
|
1032
|
+
if (!storedVisited || storedVisited == "[]") {
|
|
1033
|
+
getUserProgress2().then((progressData2) => {
|
|
600
1034
|
sessionStorage.setItem(
|
|
601
1035
|
"onboardingVisited",
|
|
602
1036
|
JSON.stringify(progressData2.completedPages)
|
|
@@ -625,9 +1059,9 @@ async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion =
|
|
|
625
1059
|
if (storedVisited.length >= checklistItems.length) {
|
|
626
1060
|
sessionStorage.setItem("CompletedAll", "true");
|
|
627
1061
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
1062
|
+
}
|
|
1063
|
+
window.location.href = it.url;
|
|
1064
|
+
});
|
|
631
1065
|
});
|
|
632
1066
|
} else {
|
|
633
1067
|
if (!sessionStorage.getItem("c")) sessionStorage.setItem("c", 1);
|
|
@@ -733,7 +1167,7 @@ async function OnboardingPopup(checklist_id, user_var) {
|
|
|
733
1167
|
return checklist2;
|
|
734
1168
|
}
|
|
735
1169
|
const res = await fetch(
|
|
736
|
-
`
|
|
1170
|
+
`http://localhost:5000/checklists2/${checklist_id}`,
|
|
737
1171
|
{
|
|
738
1172
|
method: "GET",
|
|
739
1173
|
headers: { "Content-Type": "application/json" }
|
|
@@ -768,12 +1202,2414 @@ async function OnboardingPopup(checklist_id, user_var) {
|
|
|
768
1202
|
);
|
|
769
1203
|
return checklist;
|
|
770
1204
|
} catch (err) {
|
|
771
|
-
console.
|
|
1205
|
+
console.warn("Invalid checklist id ", err.message);
|
|
772
1206
|
throw err;
|
|
773
1207
|
}
|
|
774
1208
|
}
|
|
775
|
-
var
|
|
1209
|
+
var rivia_default = OnboardingPopup;
|
|
1210
|
+
|
|
1211
|
+
// src/utils/rivia-tour.js
|
|
1212
|
+
var RIVIA_TOUR = function() {
|
|
1213
|
+
const STATE = {
|
|
1214
|
+
picking: false,
|
|
1215
|
+
lastSelector: null,
|
|
1216
|
+
tips: [],
|
|
1217
|
+
// {id, selector, title, content, placement}
|
|
1218
|
+
tourIndex: 0,
|
|
1219
|
+
tour_id: null,
|
|
1220
|
+
tours: [],
|
|
1221
|
+
// all tours fetched from backend
|
|
1222
|
+
scrollAdvanceActive: false,
|
|
1223
|
+
// Track if scroll advance is active
|
|
1224
|
+
publish: false,
|
|
1225
|
+
// Track if tour is published
|
|
1226
|
+
is_completed: false,
|
|
1227
|
+
// Track if tour is completed
|
|
1228
|
+
user_var: "Guest_User",
|
|
1229
|
+
url: ""
|
|
1230
|
+
};
|
|
1231
|
+
if (typeof window === "undefined") return;
|
|
1232
|
+
const tourStateStr = window.sessionStorage.getItem("rivia_tour_state");
|
|
1233
|
+
const hasActiveTour = tourStateStr !== null;
|
|
1234
|
+
let user_var12 = "Guest_User";
|
|
1235
|
+
if (hasActiveTour) {
|
|
1236
|
+
console.log("\u{1F7E2} Active tour detected! Restoring state...");
|
|
1237
|
+
setTimeout(() => {
|
|
1238
|
+
restoreTourState();
|
|
1239
|
+
}, 300);
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1242
|
+
function restoreTourState() {
|
|
1243
|
+
if (typeof window === "undefined") return;
|
|
1244
|
+
const tourStateStr2 = window.sessionStorage.getItem("rivia_tour_state");
|
|
1245
|
+
if (!tourStateStr2) return;
|
|
1246
|
+
try {
|
|
1247
|
+
const tourState = JSON.parse(tourStateStr2);
|
|
1248
|
+
console.log("Restoring tour state:", tourState);
|
|
1249
|
+
STATE.tourIndex = tourState.tourIndex;
|
|
1250
|
+
STATE.tour_id = tourState.tourId;
|
|
1251
|
+
STATE.isPreviewMode = tourState.isPreviewMode;
|
|
1252
|
+
STATE.tips = tourState.tips;
|
|
1253
|
+
user_var12 = tourState.user_var1 || "Guest_User";
|
|
1254
|
+
STATE.title = tourState.title || "Untitled Tour";
|
|
1255
|
+
STATE.publish = tourState.publish || false;
|
|
1256
|
+
window.sessionStorage.removeItem("rivia_tour_state");
|
|
1257
|
+
if (STATE.tips?.length > 0) {
|
|
1258
|
+
setTimeout(() => {
|
|
1259
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
1260
|
+
}, 500);
|
|
1261
|
+
}
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
console.error("Error restoring tour state:", error);
|
|
1264
|
+
window.sessionStorage.removeItem("rivia_tour_state");
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
function createTooltip({
|
|
1268
|
+
id,
|
|
1269
|
+
selector,
|
|
1270
|
+
title,
|
|
1271
|
+
content,
|
|
1272
|
+
placement = "auto",
|
|
1273
|
+
nextUrl = "",
|
|
1274
|
+
isPreview = false,
|
|
1275
|
+
basic_showArrow = true,
|
|
1276
|
+
card_header = true,
|
|
1277
|
+
card_footer = true,
|
|
1278
|
+
card_back_button = false,
|
|
1279
|
+
card_next_button = true,
|
|
1280
|
+
card_skip_button = false
|
|
1281
|
+
}) {
|
|
1282
|
+
const anchor = findBySelector(selector);
|
|
1283
|
+
if (!anchor) return null;
|
|
1284
|
+
const tip = document.createElement("div");
|
|
1285
|
+
tip.dataset.riviaTipId = id;
|
|
1286
|
+
const tipStyle = isPreview ? `
|
|
1287
|
+
position: absolute;
|
|
1288
|
+
min-width: 360px;
|
|
1289
|
+
max-width: 420px;
|
|
1290
|
+
min-height: 120px;
|
|
1291
|
+
padding: 18px 20px;
|
|
1292
|
+
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
|
1293
|
+
color: #1a202c;
|
|
1294
|
+
border-radius: 14px;
|
|
1295
|
+
border: 1px solid rgba(37, 99, 235, 0.2);
|
|
1296
|
+
box-shadow: 0 12px 40px rgba(37, 99, 235, 0.15), 0 0 1px rgba(0, 0, 0, 0.1);
|
|
1297
|
+
font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
1298
|
+
z-index: 2147483647;
|
|
1299
|
+
` : `
|
|
1300
|
+
position: absolute;
|
|
1301
|
+
min-width: 360px;
|
|
1302
|
+
max-width: 420px;
|
|
1303
|
+
min-height: 120px;
|
|
1304
|
+
padding: 16px 18px;
|
|
1305
|
+
background: #ffffffff;
|
|
1306
|
+
color: #0d0c0cff;
|
|
1307
|
+
border-radius: 12px;
|
|
1308
|
+
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
|
|
1309
|
+
font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
1310
|
+
z-index: 2147483647;
|
|
1311
|
+
`;
|
|
1312
|
+
tip.style.cssText = tipStyle;
|
|
1313
|
+
const arrow = document.createElement("div");
|
|
1314
|
+
const arrowStyle = isPreview ? `
|
|
1315
|
+
position: absolute;
|
|
1316
|
+
width: 12px;
|
|
1317
|
+
height: 12px;
|
|
1318
|
+
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
|
1319
|
+
border: 1px solid rgba(37, 99, 235, 0.2);
|
|
1320
|
+
transform: rotate(45deg);
|
|
1321
|
+
display: ${basic_showArrow ? "block" : "none"};
|
|
1322
|
+
` : `
|
|
1323
|
+
position: absolute;
|
|
1324
|
+
width: 12px;
|
|
1325
|
+
height: 12px;
|
|
1326
|
+
background: #ffffffff;
|
|
1327
|
+
transform: rotate(45deg);
|
|
1328
|
+
display: ${basic_showArrow ? "block" : "none"};
|
|
1329
|
+
`;
|
|
1330
|
+
arrow.style.cssText = arrowStyle;
|
|
1331
|
+
const h = document.createElement("input");
|
|
1332
|
+
h.value = title || "Tooltip";
|
|
1333
|
+
const titleStyle = isPreview ? "font-weight:700; margin-bottom:10px; font-size:16px; width: 100%; padding: 0; border: none; background: transparent; color: #1a202c; outline: none;" : "font-weight:600; margin-bottom:8px; font-size:15px; width: 100%; padding: 4px; border: 1px solid #e5e7eb; border-radius: 4px;";
|
|
1334
|
+
h.style.cssText = titleStyle;
|
|
1335
|
+
h.placeholder = "Enter title";
|
|
1336
|
+
h.readOnly = isPreview;
|
|
1337
|
+
h.style.display = card_header ? "block" : "none";
|
|
1338
|
+
const p = document.createElement("textarea");
|
|
1339
|
+
p.value = content || "";
|
|
1340
|
+
const contentStyle = isPreview ? "font-size:13px; line-height:1.6; width: 100%; min-height: 60px; padding: 0; border: none; background: transparent; color: #4a5568; resize: none; outline: none; font-family: inherit;" : "font-size:13px; line-height:1.5; width: 100%; min-height: 60px; padding: 8px; border: 1px solid #e5e7eb; border-radius: 4px; resize: vertical;";
|
|
1341
|
+
p.style.cssText = contentStyle;
|
|
1342
|
+
p.placeholder = "Enter description";
|
|
1343
|
+
p.readOnly = isPreview;
|
|
1344
|
+
p.style.display = card_footer ? "block" : "none";
|
|
1345
|
+
h.contentEditable = !isPreview;
|
|
1346
|
+
p.contentEditable = !isPreview;
|
|
1347
|
+
if (!isPreview) {
|
|
1348
|
+
setTimeout(() => h.focus(), 50);
|
|
1349
|
+
}
|
|
1350
|
+
const controls = document.createElement("div");
|
|
1351
|
+
controls.style.cssText = `
|
|
1352
|
+
display: flex;
|
|
1353
|
+
justify-content: flex-start;
|
|
1354
|
+
align-items: center;
|
|
1355
|
+
width: 100%;
|
|
1356
|
+
margin-top: 8px;
|
|
1357
|
+
`;
|
|
1358
|
+
const closeBtn = document.createElement("button");
|
|
1359
|
+
closeBtn.textContent = "Save";
|
|
1360
|
+
closeBtn.style.cssText = `
|
|
1361
|
+
padding: 6px 12px;
|
|
1362
|
+
height: 32px;
|
|
1363
|
+
line-height: 1;
|
|
1364
|
+
border-radius: 6px;
|
|
1365
|
+
border: none;
|
|
1366
|
+
background: #10b981;
|
|
1367
|
+
color: white;
|
|
1368
|
+
font-size: 13px;
|
|
1369
|
+
font-weight: 500;
|
|
1370
|
+
cursor: pointer;
|
|
1371
|
+
transition: background-color 0.2s;
|
|
1372
|
+
display: ${isPreview ? "none" : "block"};
|
|
1373
|
+
`;
|
|
1374
|
+
closeBtn.onclick = () => {
|
|
1375
|
+
const newTitle = h.value || "Tooltip";
|
|
1376
|
+
const newContent = p.value || "";
|
|
1377
|
+
const tipIndex = STATE.tips.findIndex((t) => t.id === id);
|
|
1378
|
+
if (tipIndex !== -1) {
|
|
1379
|
+
STATE.tips[tipIndex].title = newTitle;
|
|
1380
|
+
STATE.tips[tipIndex].content = newContent;
|
|
1381
|
+
if (STATE.tour_id) {
|
|
1382
|
+
putTips();
|
|
1383
|
+
} else {
|
|
1384
|
+
saveTips();
|
|
1385
|
+
}
|
|
1386
|
+
toast("Changes saved!");
|
|
1387
|
+
setTimeout(() => {
|
|
1388
|
+
tip.remove();
|
|
1389
|
+
}, 500);
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
controls.appendChild(closeBtn);
|
|
1393
|
+
const contentWrapper = document.createElement("div");
|
|
1394
|
+
contentWrapper.style.cssText = "margin-bottom: 16px;";
|
|
1395
|
+
if (card_header) {
|
|
1396
|
+
contentWrapper.appendChild(h);
|
|
1397
|
+
contentWrapper.appendChild(document.createElement("br"));
|
|
1398
|
+
}
|
|
1399
|
+
if (card_footer) {
|
|
1400
|
+
contentWrapper.appendChild(p);
|
|
1401
|
+
}
|
|
1402
|
+
tip.appendChild(contentWrapper);
|
|
1403
|
+
tip.appendChild(controls);
|
|
1404
|
+
tip.appendChild(arrow);
|
|
1405
|
+
document.body.appendChild(tip);
|
|
1406
|
+
positionTooltip(anchor, tip, arrow, placement);
|
|
1407
|
+
const reposition = () => positionTooltip(anchor, tip, arrow, placement);
|
|
1408
|
+
const repositionObserver = new ResizeObserver(reposition);
|
|
1409
|
+
repositionObserver.observe(tip);
|
|
1410
|
+
window.addEventListener("scroll", reposition, { passive: true });
|
|
1411
|
+
window.addEventListener("resize", reposition);
|
|
1412
|
+
const obs = new MutationObserver(() => {
|
|
1413
|
+
if (!document.body.contains(tip)) {
|
|
1414
|
+
window.removeEventListener("resize", reposition);
|
|
1415
|
+
window.removeEventListener("scroll", reposition);
|
|
1416
|
+
if (repositionObserver) repositionObserver.disconnect();
|
|
1417
|
+
obs.disconnect();
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
obs.observe(document.body, { childList: true, subtree: true });
|
|
1421
|
+
return tip;
|
|
1422
|
+
}
|
|
1423
|
+
function positionTooltip(anchor, tip, arrow, placement, step) {
|
|
1424
|
+
const a = anchor.getBoundingClientRect();
|
|
1425
|
+
const t = tip.getBoundingClientRect();
|
|
1426
|
+
let place = placement;
|
|
1427
|
+
if (place === "auto") {
|
|
1428
|
+
const spaces = {
|
|
1429
|
+
top: a.top,
|
|
1430
|
+
bottom: window.innerHeight - a.bottom,
|
|
1431
|
+
left: a.left,
|
|
1432
|
+
right: window.innerWidth - a.right
|
|
1433
|
+
};
|
|
1434
|
+
place = Object.entries(spaces).sort((x, y) => y[1] - x[1])[0][0];
|
|
1435
|
+
}
|
|
1436
|
+
let top = 0, left = 0, gap = 8;
|
|
1437
|
+
if (place === "top") {
|
|
1438
|
+
top = a.top - t.height - gap;
|
|
1439
|
+
left = a.left + (a.width - t.width) / 2;
|
|
1440
|
+
Object.assign(arrow.style, {
|
|
1441
|
+
left: t.width / 2 - 5 + "px",
|
|
1442
|
+
top: t.height - 5 + "px"
|
|
1443
|
+
});
|
|
1444
|
+
} else if (place === "bottom") {
|
|
1445
|
+
top = a.bottom + gap;
|
|
1446
|
+
left = a.left + (a.width - t.width) / 2;
|
|
1447
|
+
Object.assign(arrow.style, { left: t.width / 2 - 5 + "px", top: "-5px" });
|
|
1448
|
+
} else if (place === "left") {
|
|
1449
|
+
top = a.top + (a.height - t.height) / 2;
|
|
1450
|
+
left = a.left - t.width - gap;
|
|
1451
|
+
Object.assign(arrow.style, {
|
|
1452
|
+
top: t.height / 2 - 5 + "px",
|
|
1453
|
+
left: t.width - 5 + "px"
|
|
1454
|
+
});
|
|
1455
|
+
} else {
|
|
1456
|
+
top = a.top + (a.height - t.height) / 2;
|
|
1457
|
+
left = a.right + gap;
|
|
1458
|
+
Object.assign(arrow.style, {
|
|
1459
|
+
top: t.height / 2 - 5 + "px",
|
|
1460
|
+
left: "-5px"
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
left = Math.max(8, Math.min(left, window.innerWidth - t.width - 8));
|
|
1464
|
+
top = Math.max(8, Math.min(top, window.innerHeight - t.height - 8));
|
|
1465
|
+
tip.style.left = left + window.scrollX + "px";
|
|
1466
|
+
tip.style.top = top + window.scrollY + "px";
|
|
1467
|
+
}
|
|
1468
|
+
function uploadVisitedPagesInBackground(tourId, user_var, tourIndex) {
|
|
1469
|
+
console.log("Uploading visited pages in background for tour ID:", tourIndex, "and user_var:", user_var12);
|
|
1470
|
+
let user_var2 = user_var12;
|
|
1471
|
+
const backendUrl22 = `http://localhost:5000/tours_clients/${tourId}`;
|
|
1472
|
+
try {
|
|
1473
|
+
const payload = {
|
|
1474
|
+
name: user_var2,
|
|
1475
|
+
tourIndex
|
|
1476
|
+
};
|
|
1477
|
+
fetch(backendUrl22, {
|
|
1478
|
+
method: "POST",
|
|
1479
|
+
headers: { "Content-Type": "application/json" },
|
|
1480
|
+
credentials: "include",
|
|
1481
|
+
body: JSON.stringify(payload),
|
|
1482
|
+
keepalive: true
|
|
1483
|
+
}).then((res) => {
|
|
1484
|
+
if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
|
|
1485
|
+
}).catch((err) => {
|
|
1486
|
+
console.error("\u26A0\uFE0F Background PUT upload failed:", err);
|
|
1487
|
+
});
|
|
1488
|
+
} catch (err) {
|
|
1489
|
+
console.error("\u274C Error preparing background upload:", err);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
async function loadTips(tourId, user_var) {
|
|
1493
|
+
if (!user_var) {
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
if (sessionStorage.getItem("rivia_tour_state"))
|
|
1497
|
+
return;
|
|
1498
|
+
user_var12 = user_var;
|
|
1499
|
+
STATE.tour_id = tourId;
|
|
1500
|
+
console.log("Loading tips for tour ID:", tourId, "and user_var:", user_var12);
|
|
1501
|
+
try {
|
|
1502
|
+
if (!tourId) throw new Error("Tour ID is required");
|
|
1503
|
+
const res = await fetch(`http://localhost:5000/tours2/${tourId}`, {
|
|
1504
|
+
method: "GET",
|
|
1505
|
+
headers: { "Content-Type": "application/json" }
|
|
1506
|
+
});
|
|
1507
|
+
if (!res.ok) throw new Error("Failed to fetch tour: " + res.statusText);
|
|
1508
|
+
const data = await res.json();
|
|
1509
|
+
STATE.tips = data && data.tour && Array.isArray(data.tour.steps) ? data.tour.steps : [];
|
|
1510
|
+
STATE.publish = data.tour.publish;
|
|
1511
|
+
STATE.url = data.tour.url;
|
|
1512
|
+
const stripTrailing = (p) => p.replace(/\/+$/, "");
|
|
1513
|
+
console.log("STATE.url", STATE.url);
|
|
1514
|
+
console.log("window.location.pathname", window.location.href);
|
|
1515
|
+
if (stripTrailing(STATE.url) !== stripTrailing(window.location.href)) {
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
console.log("user_var", user_var);
|
|
1519
|
+
console.log("data.tour?.user_data?.[user_var],", data.tour?.user_data?.[user_var]);
|
|
1520
|
+
if (!data.tour?.user_data?.[user_var]) {
|
|
1521
|
+
uploadVisitedPagesInBackground(tourId, user_var, 0);
|
|
1522
|
+
} else {
|
|
1523
|
+
STATE.tourIndex = data.tour.user_data[user_var].tourIndex || 0;
|
|
1524
|
+
console.log("STATE.tourIndex ", STATE.tourIndex);
|
|
1525
|
+
}
|
|
1526
|
+
STATE.is_completed = data.tour.user_data && data.tour.user_data[user_var] && data.tour.user_data[user_var].is_completed ? data.tour.user_data[user_var].is_completed : false;
|
|
1527
|
+
if (STATE.is_completed) {
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
console.log(`Loaded tips for tour ${tourId}:`, STATE.tips);
|
|
1531
|
+
return STATE.tips;
|
|
1532
|
+
} catch (err) {
|
|
1533
|
+
console.error("Invalid tour id ", err);
|
|
1534
|
+
STATE.tips = [];
|
|
1535
|
+
return STATE.tips;
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
function showStep(i, isPreview = false) {
|
|
1539
|
+
uploadVisitedPagesInBackground(STATE.tour_id, user_var12, i);
|
|
1540
|
+
console.log("Showing step", i, "of", STATE.tips.length);
|
|
1541
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
1542
|
+
const step = STATE.tips[i];
|
|
1543
|
+
if (!step) return;
|
|
1544
|
+
STATE.tourIndex = i;
|
|
1545
|
+
updateUrlStatus();
|
|
1546
|
+
cleanupAllOverlays();
|
|
1547
|
+
if (step.card_type === "welcome") {
|
|
1548
|
+
if (isPreview) {
|
|
1549
|
+
showWelcomeCardPreview(step, i);
|
|
1550
|
+
} else {
|
|
1551
|
+
showWelcomeCardEditModal(i);
|
|
1552
|
+
}
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
if (step.card_type === "modal_dialog") {
|
|
1556
|
+
if (isPreview) {
|
|
1557
|
+
showModalDialogPreview(step, i);
|
|
1558
|
+
} else {
|
|
1559
|
+
showModalDialogEditModal(i);
|
|
1560
|
+
}
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (step.card_type === "feedback") {
|
|
1564
|
+
if (isPreview) {
|
|
1565
|
+
showFeedbackCardPreview(step, i);
|
|
1566
|
+
} else {
|
|
1567
|
+
showFeedbackCardEditModal(i);
|
|
1568
|
+
}
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1571
|
+
if (step.card_type === "video_explainer") {
|
|
1572
|
+
if (isPreview) {
|
|
1573
|
+
console.log("Preview mode: Showing video explainer for step:", step.id);
|
|
1574
|
+
const targetElement = findBySelector(step.selector);
|
|
1575
|
+
if (targetElement) {
|
|
1576
|
+
try {
|
|
1577
|
+
targetElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1578
|
+
} catch (e) {
|
|
1579
|
+
targetElement.scrollIntoView(true);
|
|
1580
|
+
}
|
|
1581
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1582
|
+
targetElement.style.outline = "3px solid #2563eb";
|
|
1583
|
+
targetElement.style.outlineOffset = "2px";
|
|
1584
|
+
targetElement.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1585
|
+
}
|
|
1586
|
+
setTimeout(() => {
|
|
1587
|
+
const highlightedElement = document.querySelector('[data-rivia-highlight="true"]');
|
|
1588
|
+
if (!highlightedElement && targetElement) {
|
|
1589
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1590
|
+
}
|
|
1591
|
+
const videoUI = createVideoUI({ ...step, isPreview: true });
|
|
1592
|
+
if (videoUI) {
|
|
1593
|
+
console.log("Video UI created successfully with built-in navigation buttons");
|
|
1594
|
+
} else {
|
|
1595
|
+
console.warn("Failed to create video UI for preview");
|
|
1596
|
+
}
|
|
1597
|
+
}, 600);
|
|
1598
|
+
} else {
|
|
1599
|
+
console.log("Edit mode: Showing video explainer for step:", step.id);
|
|
1600
|
+
console.log("Step selector:", step.selector);
|
|
1601
|
+
if (step.selector) {
|
|
1602
|
+
const targetElement = findBySelector(step.selector);
|
|
1603
|
+
console.log("Found target element:", targetElement, "for selector:", step.selector);
|
|
1604
|
+
if (targetElement) {
|
|
1605
|
+
console.log("Element found, scrolling into view...");
|
|
1606
|
+
try {
|
|
1607
|
+
targetElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1608
|
+
} catch (e) {
|
|
1609
|
+
console.warn("ScrollIntoView error:", e);
|
|
1610
|
+
targetElement.scrollIntoView(true);
|
|
1611
|
+
}
|
|
1612
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1613
|
+
targetElement.style.outline = "3px solid #2563eb";
|
|
1614
|
+
targetElement.style.outlineOffset = "2px";
|
|
1615
|
+
targetElement.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1616
|
+
console.log("Element highlighted with blue outline");
|
|
1617
|
+
if (step.target_animation && step.target_animation !== "none") {
|
|
1618
|
+
previewAnimation(step.selector, step.target_animation);
|
|
1619
|
+
}
|
|
1620
|
+
if (step.basic_backdrop && step.basic_backdrop !== "none") {
|
|
1621
|
+
previewBackdrop(step.selector, step.basic_backdrop);
|
|
1622
|
+
}
|
|
1623
|
+
} else {
|
|
1624
|
+
console.warn("Target element not found for selector:", step.selector);
|
|
1625
|
+
}
|
|
1626
|
+
} else {
|
|
1627
|
+
console.warn("No selector found in step:", step);
|
|
1628
|
+
}
|
|
1629
|
+
setTimeout(() => {
|
|
1630
|
+
console.log("Creating video UI after scroll delay...");
|
|
1631
|
+
const highlightedElement = document.querySelector('[data-rivia-highlight="true"]');
|
|
1632
|
+
console.log("Highlighted element for video positioning:", highlightedElement);
|
|
1633
|
+
const videoUI = createVideoUI({ ...step, isPreview: false });
|
|
1634
|
+
if (videoUI) {
|
|
1635
|
+
console.log("Video UI created successfully");
|
|
1636
|
+
if (typeof showPointerCardPanel === "function") {
|
|
1637
|
+
console.log("Showing pointer card panel for selector:", step.selector);
|
|
1638
|
+
const stepIndex = STATE.tips.findIndex((t) => t === step);
|
|
1639
|
+
showPointerCardPanel(step.selector, stepIndex);
|
|
1640
|
+
}
|
|
1641
|
+
} else {
|
|
1642
|
+
console.warn("Failed to create video UI");
|
|
1643
|
+
}
|
|
1644
|
+
}, 600);
|
|
1645
|
+
}
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
if (isPreview) {
|
|
1649
|
+
const el = findBySelector(step.selector);
|
|
1650
|
+
if (el) {
|
|
1651
|
+
try {
|
|
1652
|
+
el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1653
|
+
} catch (e) {
|
|
1654
|
+
el.scrollIntoView(true);
|
|
1655
|
+
}
|
|
1656
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
1657
|
+
n.removeAttribute("data-rivia-highlight");
|
|
1658
|
+
n.style.outline = "";
|
|
1659
|
+
n.style.outlineOffset = "";
|
|
1660
|
+
n.style.backgroundColor = "";
|
|
1661
|
+
});
|
|
1662
|
+
el.setAttribute("data-rivia-highlight", "true");
|
|
1663
|
+
el.style.outline = "3px solid #2563eb";
|
|
1664
|
+
el.style.outlineOffset = "2px";
|
|
1665
|
+
el.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1666
|
+
if (step.target_animation && step.target_animation !== "none") {
|
|
1667
|
+
previewAnimation(step.selector, step.target_animation);
|
|
1668
|
+
}
|
|
1669
|
+
if (step.basic_backdrop && step.basic_backdrop !== "none") {
|
|
1670
|
+
previewBackdrop(step.selector, step.basic_backdrop);
|
|
1671
|
+
} else {
|
|
1672
|
+
const backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
1673
|
+
if (backdropOverlay) {
|
|
1674
|
+
backdropOverlay.remove();
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
setTimeout(() => {
|
|
1679
|
+
const tip2 = createTooltip({ ...step, isPreview });
|
|
1680
|
+
if (tip2) {
|
|
1681
|
+
attachNavigationButtons(tip2, i, isPreview);
|
|
1682
|
+
try {
|
|
1683
|
+
tip2.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
1684
|
+
} catch (e) {
|
|
1685
|
+
tip2.scrollIntoView(true);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
}, 600);
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
if (!isPreview && step.selector && !step.card_type) {
|
|
1692
|
+
const el = findBySelector(step.selector);
|
|
1693
|
+
if (el) {
|
|
1694
|
+
try {
|
|
1695
|
+
el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1696
|
+
} catch (e) {
|
|
1697
|
+
el.scrollIntoView(true);
|
|
1698
|
+
}
|
|
1699
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
1700
|
+
n.removeAttribute("data-rivia-highlight");
|
|
1701
|
+
n.style.outline = "";
|
|
1702
|
+
n.style.outlineOffset = "";
|
|
1703
|
+
n.style.backgroundColor = "";
|
|
1704
|
+
});
|
|
1705
|
+
el.setAttribute("data-rivia-highlight", "true");
|
|
1706
|
+
el.style.outline = "3px solid #2563eb";
|
|
1707
|
+
el.style.outlineOffset = "2px";
|
|
1708
|
+
el.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const tip = createTooltip({ ...step, isPreview });
|
|
1712
|
+
console.log("nextUrl for step", step.nextUrl);
|
|
1713
|
+
if (!tip) {
|
|
1714
|
+
const stepUrlInfo = getStepUrlInfo(step);
|
|
1715
|
+
if (stepUrlInfo && !stepUrlInfo.isAvailable) {
|
|
1716
|
+
toast("\u{1F4CD} Step element not found on this URL. The tooltip is designed for: " + stepUrlInfo.targetUrl, true);
|
|
1717
|
+
console.warn("\u{1F4CD} Step element not found. Target URL:", stepUrlInfo.targetUrl, "Current URL:", window.location.href);
|
|
1718
|
+
} else {
|
|
1719
|
+
toast("\u{1F4CD} Tooltip element not found on this page", true);
|
|
1720
|
+
console.warn("\u{1F4CD} Tooltip element not found for selector:", step.selector);
|
|
1721
|
+
}
|
|
1722
|
+
if (step.nextUrl && step.nextUrl.trim()) {
|
|
1723
|
+
const navUrl = addTourParamsToUrl(step.nextUrl, STATE.tour_id);
|
|
1724
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
1725
|
+
tourIndex: STATE.tourIndex,
|
|
1726
|
+
tourId: STATE.tour_id,
|
|
1727
|
+
user_var1: user_var12,
|
|
1728
|
+
isPreviewMode: false,
|
|
1729
|
+
// Use edit mode when navigating from tooltip
|
|
1730
|
+
tips: STATE.tips,
|
|
1731
|
+
title: STATE.title || "Untitled Tour",
|
|
1732
|
+
publish: STATE.publish
|
|
1733
|
+
}));
|
|
1734
|
+
} else {
|
|
1735
|
+
nextStep();
|
|
1736
|
+
}
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
attachNavigationButtons(tip, i, isPreview);
|
|
1740
|
+
setTimeout(() => {
|
|
1741
|
+
try {
|
|
1742
|
+
tip.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
1743
|
+
} catch (e) {
|
|
1744
|
+
tip.scrollIntoView(true);
|
|
1745
|
+
}
|
|
1746
|
+
}, 100);
|
|
1747
|
+
}
|
|
1748
|
+
function createVideoUI(step) {
|
|
1749
|
+
console.log("Creating video UI for step:", step);
|
|
1750
|
+
const anchor = findBySelector(step.selector);
|
|
1751
|
+
console.log("Found anchor:", anchor);
|
|
1752
|
+
if (!anchor) {
|
|
1753
|
+
console.warn("Anchor not found for selector:", step.selector);
|
|
1754
|
+
return null;
|
|
1755
|
+
}
|
|
1756
|
+
const videoContainer = document.createElement("div");
|
|
1757
|
+
videoContainer.dataset.riviaTipId = step.id;
|
|
1758
|
+
const width = step.video_width || 400;
|
|
1759
|
+
const height = step.video_height || 300;
|
|
1760
|
+
videoContainer.style.cssText = `
|
|
1761
|
+
position: absolute;
|
|
1762
|
+
width: ${width}px;
|
|
1763
|
+
height: ${height}px;
|
|
1764
|
+
background: #ffffff;
|
|
1765
|
+
border-radius: 20px;
|
|
1766
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35), 0 0 1px rgba(0, 0, 0, 0.1);
|
|
1767
|
+
overflow: hidden;
|
|
1768
|
+
z-index: 2147483647;
|
|
1769
|
+
display: flex;
|
|
1770
|
+
flex-direction: column;
|
|
1771
|
+
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
1772
|
+
`;
|
|
1773
|
+
const header = document.createElement("div");
|
|
1774
|
+
header.style.cssText = `
|
|
1775
|
+
display: flex;
|
|
1776
|
+
justify-content: space-between;
|
|
1777
|
+
align-items: center;
|
|
1778
|
+
padding: 16px 20px;
|
|
1779
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
1780
|
+
color: white;
|
|
1781
|
+
font-weight: 700;
|
|
1782
|
+
font-size: 15px;
|
|
1783
|
+
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
|
1784
|
+
`;
|
|
1785
|
+
const titleSpan = document.createElement("span");
|
|
1786
|
+
titleSpan.textContent = step.title || "Video Explainer";
|
|
1787
|
+
header.appendChild(titleSpan);
|
|
1788
|
+
if (!step.isPreview) {
|
|
1789
|
+
const settingsBtn = document.createElement("button");
|
|
1790
|
+
settingsBtn.innerHTML = "\u2699\uFE0F";
|
|
1791
|
+
settingsBtn.style.cssText = `
|
|
1792
|
+
background: rgba(255, 255, 255, 0.2);
|
|
1793
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
1794
|
+
border-radius: 6px;
|
|
1795
|
+
width: 32px;
|
|
1796
|
+
height: 32px;
|
|
1797
|
+
cursor: pointer;
|
|
1798
|
+
color: white;
|
|
1799
|
+
font-size: 16px;
|
|
1800
|
+
transition: all 0.2s;
|
|
1801
|
+
`;
|
|
1802
|
+
settingsBtn.onmouseover = () => settingsBtn.style.background = "rgba(255, 255, 255, 0.3)";
|
|
1803
|
+
settingsBtn.onmouseout = () => settingsBtn.style.background = "rgba(255, 255, 255, 0.2)";
|
|
1804
|
+
settingsBtn.onclick = () => {
|
|
1805
|
+
const existingPanel = document.getElementById("rivia-video-settings-panel");
|
|
1806
|
+
if (existingPanel) {
|
|
1807
|
+
existingPanel.remove();
|
|
1808
|
+
} else {
|
|
1809
|
+
showVideoSettings(step, videoContainer, settingsBtn);
|
|
1810
|
+
}
|
|
1811
|
+
};
|
|
1812
|
+
header.appendChild(settingsBtn);
|
|
1813
|
+
}
|
|
1814
|
+
videoContainer.appendChild(header);
|
|
1815
|
+
const playerArea = document.createElement("div");
|
|
1816
|
+
playerArea.style.cssText = `
|
|
1817
|
+
flex: 1;
|
|
1818
|
+
display: flex;
|
|
1819
|
+
align-items: center;
|
|
1820
|
+
justify-content: center;
|
|
1821
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
1822
|
+
position: relative;
|
|
1823
|
+
overflow: hidden;
|
|
1824
|
+
`;
|
|
1825
|
+
if (step.video_url) {
|
|
1826
|
+
const videoId = step.video_url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\n?#]+)/)?.[1];
|
|
1827
|
+
if (videoId) {
|
|
1828
|
+
const thumbnail = document.createElement("img");
|
|
1829
|
+
thumbnail.src = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`;
|
|
1830
|
+
thumbnail.style.cssText = `
|
|
1831
|
+
position: absolute;
|
|
1832
|
+
width: 100%;
|
|
1833
|
+
height: 100%;
|
|
1834
|
+
object-fit: cover;
|
|
1835
|
+
opacity: 0.9;
|
|
1836
|
+
filter: brightness(0.95);
|
|
1837
|
+
`;
|
|
1838
|
+
thumbnail.onerror = () => {
|
|
1839
|
+
thumbnail.src = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
|
|
1840
|
+
};
|
|
1841
|
+
playerArea.appendChild(thumbnail);
|
|
1842
|
+
console.log("Video thumbnail loaded for video ID:", videoId);
|
|
1843
|
+
} else {
|
|
1844
|
+
console.warn("Could not extract video ID from URL:", step.video_url);
|
|
1845
|
+
}
|
|
1846
|
+
} else {
|
|
1847
|
+
console.warn("No video URL provided for step:", step.id);
|
|
1848
|
+
}
|
|
1849
|
+
const playButton = document.createElement("button");
|
|
1850
|
+
playButton.innerHTML = "\u25B6";
|
|
1851
|
+
playButton.style.cssText = `
|
|
1852
|
+
width: 90px;
|
|
1853
|
+
height: 90px;
|
|
1854
|
+
border-radius: 50%;
|
|
1855
|
+
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
|
|
1856
|
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
1857
|
+
color: white;
|
|
1858
|
+
font-size: 36px;
|
|
1859
|
+
cursor: pointer;
|
|
1860
|
+
transition: all 0.3s ease;
|
|
1861
|
+
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.5), inset 0 -2px 5px rgba(0, 0, 0, 0.2);
|
|
1862
|
+
position: relative;
|
|
1863
|
+
z-index: 10;
|
|
1864
|
+
`;
|
|
1865
|
+
playButton.onmouseover = () => {
|
|
1866
|
+
playButton.style.background = "linear-gradient(135deg, #ff5252 0%, #ff1744 100%)";
|
|
1867
|
+
playButton.style.transform = "scale(1.15)";
|
|
1868
|
+
playButton.style.boxShadow = "0 12px 35px rgba(255, 107, 107, 0.7), inset 0 -2px 5px rgba(0, 0, 0, 0.2)";
|
|
1869
|
+
};
|
|
1870
|
+
playButton.onmouseout = () => {
|
|
1871
|
+
playButton.style.background = "linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%)";
|
|
1872
|
+
playButton.style.transform = "scale(1)";
|
|
1873
|
+
playButton.style.boxShadow = "0 8px 25px rgba(255, 107, 107, 0.5), inset 0 -2px 5px rgba(0, 0, 0, 0.2)";
|
|
1874
|
+
};
|
|
1875
|
+
playButton.onclick = () => {
|
|
1876
|
+
if (step.video_url) {
|
|
1877
|
+
const videoId = step.video_url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\n?#]+)/)?.[1];
|
|
1878
|
+
if (videoId) {
|
|
1879
|
+
playerArea.innerHTML = "";
|
|
1880
|
+
const iframe = document.createElement("iframe");
|
|
1881
|
+
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
|
|
1882
|
+
iframe.style.cssText = `
|
|
1883
|
+
width: 100%;
|
|
1884
|
+
height: 100%;
|
|
1885
|
+
border: none;
|
|
1886
|
+
border-radius: 8px;
|
|
1887
|
+
`;
|
|
1888
|
+
iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture";
|
|
1889
|
+
iframe.allowFullscreen = true;
|
|
1890
|
+
playerArea.appendChild(iframe);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
playerArea.appendChild(playButton);
|
|
1895
|
+
videoContainer.appendChild(playerArea);
|
|
1896
|
+
const footer = document.createElement("div");
|
|
1897
|
+
footer.style.cssText = `
|
|
1898
|
+
display: flex;
|
|
1899
|
+
justify-content: space-between;
|
|
1900
|
+
align-items: center;
|
|
1901
|
+
padding: 16px 20px;
|
|
1902
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
1903
|
+
gap: 12px;
|
|
1904
|
+
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
|
1905
|
+
`;
|
|
1906
|
+
const skipBtn = document.createElement("button");
|
|
1907
|
+
skipBtn.textContent = "Skip";
|
|
1908
|
+
skipBtn.style.cssText = `
|
|
1909
|
+
padding: 10px 20px;
|
|
1910
|
+
background: rgba(255, 255, 255, 0.6);
|
|
1911
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
1912
|
+
border-radius: 8px;
|
|
1913
|
+
color: #333;
|
|
1914
|
+
font-weight: 600;
|
|
1915
|
+
cursor: pointer;
|
|
1916
|
+
transition: all 0.2s ease;
|
|
1917
|
+
`;
|
|
1918
|
+
skipBtn.onmouseover = () => {
|
|
1919
|
+
skipBtn.style.background = "rgba(255, 255, 255, 0.9)";
|
|
1920
|
+
skipBtn.style.transform = "translateY(-2px)";
|
|
1921
|
+
skipBtn.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.1)";
|
|
1922
|
+
};
|
|
1923
|
+
skipBtn.onmouseout = () => {
|
|
1924
|
+
skipBtn.style.background = "rgba(255, 255, 255, 0.6)";
|
|
1925
|
+
skipBtn.style.transform = "translateY(0)";
|
|
1926
|
+
skipBtn.style.boxShadow = "none";
|
|
1927
|
+
};
|
|
1928
|
+
skipBtn.onclick = () => {
|
|
1929
|
+
endTour();
|
|
1930
|
+
};
|
|
1931
|
+
footer.appendChild(skipBtn);
|
|
1932
|
+
const nextBtn = document.createElement("button");
|
|
1933
|
+
nextBtn.textContent = "Next";
|
|
1934
|
+
nextBtn.style.cssText = `
|
|
1935
|
+
padding: 10px 24px;
|
|
1936
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
1937
|
+
border: none;
|
|
1938
|
+
border-radius: 8px;
|
|
1939
|
+
color: white;
|
|
1940
|
+
font-weight: 700;
|
|
1941
|
+
cursor: pointer;
|
|
1942
|
+
transition: all 0.2s ease;
|
|
1943
|
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
1944
|
+
`;
|
|
1945
|
+
nextBtn.onmouseover = () => {
|
|
1946
|
+
nextBtn.style.background = "linear-gradient(135deg, #5568d3 0%, #6a3a8f 100%)";
|
|
1947
|
+
nextBtn.style.transform = "translateY(-2px)";
|
|
1948
|
+
nextBtn.style.boxShadow = "0 6px 20px rgba(102, 126, 234, 0.6)";
|
|
1949
|
+
};
|
|
1950
|
+
nextBtn.onmouseout = () => {
|
|
1951
|
+
nextBtn.style.background = "linear-gradient(135deg, #667eea 0%, #764ba2 100%)";
|
|
1952
|
+
nextBtn.style.transform = "translateY(0)";
|
|
1953
|
+
nextBtn.style.boxShadow = "0 4px 15px rgba(102, 126, 234, 0.4)";
|
|
1954
|
+
};
|
|
1955
|
+
nextBtn.onclick = () => {
|
|
1956
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
1957
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
1958
|
+
showStep(STATE.tourIndex, true);
|
|
1959
|
+
} else {
|
|
1960
|
+
endTour();
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
footer.appendChild(nextBtn);
|
|
1964
|
+
videoContainer.appendChild(footer);
|
|
1965
|
+
document.body.appendChild(videoContainer);
|
|
1966
|
+
setTimeout(() => {
|
|
1967
|
+
try {
|
|
1968
|
+
anchor.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1969
|
+
} catch (e) {
|
|
1970
|
+
anchor.scrollIntoView(true);
|
|
1971
|
+
}
|
|
1972
|
+
setTimeout(() => {
|
|
1973
|
+
const a = anchor.getBoundingClientRect();
|
|
1974
|
+
const t = videoContainer.getBoundingClientRect();
|
|
1975
|
+
let top = a.bottom + 8;
|
|
1976
|
+
let left = a.left + (a.width - t.width) / 2;
|
|
1977
|
+
left = Math.max(8, Math.min(left, window.innerWidth - t.width - 8));
|
|
1978
|
+
top = Math.max(8, Math.min(top, window.innerHeight - t.height - 8));
|
|
1979
|
+
videoContainer.style.left = left + window.scrollX + "px";
|
|
1980
|
+
videoContainer.style.top = top + window.scrollY + "px";
|
|
1981
|
+
console.log("Video UI positioned at:", { top, left, width, height });
|
|
1982
|
+
}, 300);
|
|
1983
|
+
}, 0);
|
|
1984
|
+
return videoContainer;
|
|
1985
|
+
}
|
|
1986
|
+
function previewAnimation(selector, animationType) {
|
|
1987
|
+
try {
|
|
1988
|
+
const element = document.querySelector(selector);
|
|
1989
|
+
if (!element) {
|
|
1990
|
+
console.warn("Element not found for selector:", selector);
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
element.classList.remove(
|
|
1994
|
+
"rivia-animate-flash",
|
|
1995
|
+
"rivia-animate-rubber-band",
|
|
1996
|
+
"rivia-animate-shake"
|
|
1997
|
+
);
|
|
1998
|
+
const animationMap = {
|
|
1999
|
+
flash: "rivia-animate-flash",
|
|
2000
|
+
"rubber band": "rivia-animate-rubber-band",
|
|
2001
|
+
shake: "rivia-animate-shake",
|
|
2002
|
+
none: null
|
|
2003
|
+
};
|
|
2004
|
+
const animClass = animationMap[animationType];
|
|
2005
|
+
if (animClass) {
|
|
2006
|
+
element.classList.add(animClass);
|
|
2007
|
+
setTimeout(() => {
|
|
2008
|
+
element.classList.remove(animClass);
|
|
2009
|
+
}, 2e3);
|
|
2010
|
+
}
|
|
2011
|
+
} catch (err) {
|
|
2012
|
+
console.error("Error previewing animation:", err);
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function findBySelector(selector) {
|
|
2016
|
+
try {
|
|
2017
|
+
return document.querySelector(selector);
|
|
2018
|
+
} catch (e) {
|
|
2019
|
+
console.warn("Invalid selector:", selector, e);
|
|
2020
|
+
return null;
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
function highlightElementBySelector(selector) {
|
|
2024
|
+
const el = findBySelector(selector);
|
|
2025
|
+
if (!el) return;
|
|
2026
|
+
try {
|
|
2027
|
+
el.scrollIntoView({
|
|
2028
|
+
behavior: "smooth",
|
|
2029
|
+
block: "center",
|
|
2030
|
+
inline: "nearest"
|
|
2031
|
+
});
|
|
2032
|
+
} catch (e) {
|
|
2033
|
+
el.scrollIntoView(true);
|
|
2034
|
+
}
|
|
2035
|
+
const r = el.getBoundingClientRect();
|
|
2036
|
+
try {
|
|
2037
|
+
document.body.appendChild(overlay);
|
|
2038
|
+
} catch (e) {
|
|
2039
|
+
}
|
|
2040
|
+
Object.assign(highlight.style, {
|
|
2041
|
+
left: r.left + window.scrollX + "px",
|
|
2042
|
+
top: r.top + window.scrollY + "px",
|
|
2043
|
+
width: r.width + "px",
|
|
2044
|
+
height: r.height + "px"
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
function previewBackdrop(selector, backdropType) {
|
|
2048
|
+
try {
|
|
2049
|
+
let backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
2050
|
+
if (backdropOverlay) {
|
|
2051
|
+
backdropOverlay.remove();
|
|
2052
|
+
}
|
|
2053
|
+
if (backdropType === "none") {
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
const targetElement = findBySelector(selector);
|
|
2057
|
+
if (!targetElement) return;
|
|
2058
|
+
const targetRect = targetElement.getBoundingClientRect();
|
|
2059
|
+
const padding = 8;
|
|
2060
|
+
if (backdropType === "boxed") {
|
|
2061
|
+
const boxedOverlay = document.createElement("div");
|
|
2062
|
+
boxedOverlay.id = "rivia-backdrop-overlay";
|
|
2063
|
+
boxedOverlay.style.cssText = `
|
|
2064
|
+
position: fixed;
|
|
2065
|
+
top: 0;
|
|
2066
|
+
left: 0;
|
|
2067
|
+
width: 100%;
|
|
2068
|
+
height: 100%;
|
|
2069
|
+
z-index: 2147483644;
|
|
2070
|
+
pointer-events: none;
|
|
2071
|
+
background: rgba(240, 240, 245, 0.3);
|
|
2072
|
+
backdrop-filter: blur(3px);
|
|
2073
|
+
`;
|
|
2074
|
+
const boxHighlight = document.createElement("div");
|
|
2075
|
+
boxHighlight.style.cssText = `
|
|
2076
|
+
position: fixed;
|
|
2077
|
+
left: ${targetRect.left - padding}px;
|
|
2078
|
+
top: ${targetRect.top - padding}px;
|
|
2079
|
+
width: ${targetRect.width + padding * 2}px;
|
|
2080
|
+
height: ${targetRect.height + padding * 2}px;
|
|
2081
|
+
border: 2px solid #3b82f6;
|
|
2082
|
+
border-radius: 8px;
|
|
2083
|
+
background: rgba(59, 130, 246, 0.08);
|
|
2084
|
+
pointer-events: none;
|
|
2085
|
+
z-index: 2147483645;
|
|
2086
|
+
box-shadow: 0 0 0 9999px rgba(240, 240, 245, 0.3);
|
|
2087
|
+
`;
|
|
2088
|
+
document.body.appendChild(boxedOverlay);
|
|
2089
|
+
document.body.appendChild(boxHighlight);
|
|
2090
|
+
const updateBoxed = () => {
|
|
2091
|
+
const newRect = targetElement.getBoundingClientRect();
|
|
2092
|
+
boxHighlight.style.left = `${newRect.left - padding}px`;
|
|
2093
|
+
boxHighlight.style.top = `${newRect.top - padding}px`;
|
|
2094
|
+
boxHighlight.style.width = `${newRect.width + padding * 2}px`;
|
|
2095
|
+
boxHighlight.style.height = `${newRect.height + padding * 2}px`;
|
|
2096
|
+
};
|
|
2097
|
+
window.addEventListener("scroll", updateBoxed, { passive: true });
|
|
2098
|
+
window.addEventListener("resize", updateBoxed);
|
|
2099
|
+
boxedOverlay.updateBackdrop = updateBoxed;
|
|
2100
|
+
return;
|
|
2101
|
+
}
|
|
2102
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2103
|
+
svg.id = "rivia-backdrop-overlay";
|
|
2104
|
+
svg.style.cssText = `
|
|
2105
|
+
position: fixed;
|
|
2106
|
+
top: 0;
|
|
2107
|
+
left: 0;
|
|
2108
|
+
width: 100%;
|
|
2109
|
+
height: 100%;
|
|
2110
|
+
z-index: 2147483644;
|
|
2111
|
+
pointer-events: none;
|
|
2112
|
+
`;
|
|
2113
|
+
const defs = document.createElementNS(
|
|
2114
|
+
"http://www.w3.org/2000/svg",
|
|
2115
|
+
"defs"
|
|
2116
|
+
);
|
|
2117
|
+
const mask = document.createElementNS(
|
|
2118
|
+
"http://www.w3.org/2000/svg",
|
|
2119
|
+
"mask"
|
|
2120
|
+
);
|
|
2121
|
+
mask.id = "rivia-backdrop-mask";
|
|
2122
|
+
const rect = document.createElementNS(
|
|
2123
|
+
"http://www.w3.org/2000/svg",
|
|
2124
|
+
"rect"
|
|
2125
|
+
);
|
|
2126
|
+
rect.setAttribute("width", "100%");
|
|
2127
|
+
rect.setAttribute("height", "100%");
|
|
2128
|
+
rect.setAttribute("fill", "white");
|
|
2129
|
+
mask.appendChild(rect);
|
|
2130
|
+
const clearRect = document.createElementNS(
|
|
2131
|
+
"http://www.w3.org/2000/svg",
|
|
2132
|
+
"rect"
|
|
2133
|
+
);
|
|
2134
|
+
clearRect.setAttribute("x", Math.max(0, targetRect.left - padding));
|
|
2135
|
+
clearRect.setAttribute("y", Math.max(0, targetRect.top - padding));
|
|
2136
|
+
clearRect.setAttribute("width", targetRect.width + padding * 2);
|
|
2137
|
+
clearRect.setAttribute("height", targetRect.height + padding * 2);
|
|
2138
|
+
clearRect.setAttribute("fill", "black");
|
|
2139
|
+
clearRect.setAttribute("rx", "8");
|
|
2140
|
+
mask.appendChild(clearRect);
|
|
2141
|
+
defs.appendChild(mask);
|
|
2142
|
+
svg.appendChild(defs);
|
|
2143
|
+
const overlayColor = backdropType === "light overlay" ? "rgba(255, 255, 255, 0.6)" : "rgba(0, 0, 0, 0.7)";
|
|
2144
|
+
const maskedRect = document.createElementNS(
|
|
2145
|
+
"http://www.w3.org/2000/svg",
|
|
2146
|
+
"rect"
|
|
2147
|
+
);
|
|
2148
|
+
maskedRect.setAttribute("width", "100%");
|
|
2149
|
+
maskedRect.setAttribute("height", "100%");
|
|
2150
|
+
maskedRect.setAttribute("fill", overlayColor);
|
|
2151
|
+
maskedRect.setAttribute("mask", "url(#rivia-backdrop-mask)");
|
|
2152
|
+
svg.appendChild(maskedRect);
|
|
2153
|
+
document.body.appendChild(svg);
|
|
2154
|
+
const updateBackdrop = () => {
|
|
2155
|
+
const newRect = targetElement.getBoundingClientRect();
|
|
2156
|
+
clearRect.setAttribute("x", Math.max(0, newRect.left - padding));
|
|
2157
|
+
clearRect.setAttribute("y", Math.max(0, newRect.top - padding));
|
|
2158
|
+
clearRect.setAttribute("width", newRect.width + padding * 2);
|
|
2159
|
+
clearRect.setAttribute("height", newRect.height + padding * 2);
|
|
2160
|
+
};
|
|
2161
|
+
window.addEventListener("scroll", updateBackdrop, { passive: true });
|
|
2162
|
+
window.addEventListener("resize", updateBackdrop);
|
|
2163
|
+
svg.updateBackdrop = updateBackdrop;
|
|
2164
|
+
} catch (err) {
|
|
2165
|
+
console.error("Error previewing backdrop:", err);
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
function showWelcomeCardPreview(step, stepIndex) {
|
|
2169
|
+
if (!step) {
|
|
2170
|
+
console.warn("Step not found for preview");
|
|
2171
|
+
return;
|
|
2172
|
+
}
|
|
2173
|
+
console.log("Showing welcome card preview for step:", step);
|
|
2174
|
+
cleanupAllOverlays();
|
|
2175
|
+
document.querySelectorAll('[id*="rivia-welcome-preview"]').forEach((el) => el.remove());
|
|
2176
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
2177
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
2178
|
+
if (backdropStyle !== "none") {
|
|
2179
|
+
const backdropOverlay = document.createElement("div");
|
|
2180
|
+
backdropOverlay.id = "rivia-welcome-preview-backdrop";
|
|
2181
|
+
backdropOverlay.style.cssText = `
|
|
2182
|
+
position: fixed;
|
|
2183
|
+
inset: 0;
|
|
2184
|
+
z-index: 2147483643;
|
|
2185
|
+
pointer-events: none;
|
|
2186
|
+
`;
|
|
2187
|
+
if (backdropStyle === "boxed") {
|
|
2188
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
2189
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
2190
|
+
} else if (backdropStyle === "light overlay") {
|
|
2191
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
2192
|
+
backdropOverlay.style.border = "none";
|
|
2193
|
+
} else if (backdropStyle === "dark overlay") {
|
|
2194
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
2195
|
+
backdropOverlay.style.border = "none";
|
|
2196
|
+
}
|
|
2197
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
2198
|
+
}
|
|
2199
|
+
const overlay2 = document.createElement("div");
|
|
2200
|
+
overlay2.id = "rivia-welcome-preview-overlay";
|
|
2201
|
+
overlay2.style.cssText = `
|
|
2202
|
+
position: fixed;
|
|
2203
|
+
inset: 0;
|
|
2204
|
+
background: rgba(0, 0, 0, 0.5);
|
|
2205
|
+
display: flex;
|
|
2206
|
+
align-items: center;
|
|
2207
|
+
justify-content: center;
|
|
2208
|
+
z-index: 2147483644;
|
|
2209
|
+
`;
|
|
2210
|
+
const modal = document.createElement("div");
|
|
2211
|
+
modal.id = "rivia-welcome-preview-modal";
|
|
2212
|
+
const bgColor = step.welcome_bg_color || "#ffffff";
|
|
2213
|
+
modal.style.cssText = `
|
|
2214
|
+
background: ${bgColor};
|
|
2215
|
+
border-radius: 12px;
|
|
2216
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
2217
|
+
max-width: 700px;
|
|
2218
|
+
width: 90%;
|
|
2219
|
+
max-height: 80vh;
|
|
2220
|
+
overflow-y: auto;
|
|
2221
|
+
padding: 0;
|
|
2222
|
+
`;
|
|
2223
|
+
const headerSection = document.createElement("div");
|
|
2224
|
+
const headerBgColor = step.welcome_header_bg_color || "#667eea";
|
|
2225
|
+
const headerTextColor = step.welcome_header_text_color || "#ffffff";
|
|
2226
|
+
const headerHeight = step.welcome_header_height || 80;
|
|
2227
|
+
headerSection.style.cssText = `
|
|
2228
|
+
background: ${headerBgColor};
|
|
2229
|
+
padding: ${headerHeight / 2}px 30px;
|
|
2230
|
+
color: ${headerTextColor};
|
|
2231
|
+
border-radius: 12px 12px 0 0;
|
|
2232
|
+
text-align: center;
|
|
2233
|
+
min-height: ${headerHeight}px;
|
|
2234
|
+
display: flex;
|
|
2235
|
+
align-items: center;
|
|
2236
|
+
justify-content: center;
|
|
2237
|
+
`;
|
|
2238
|
+
headerSection.id = "rivia-welcome-preview-header";
|
|
2239
|
+
const headerText = document.createElement("h1");
|
|
2240
|
+
headerText.textContent = step.title || "Welcome!";
|
|
2241
|
+
headerText.style.cssText = `
|
|
2242
|
+
margin: 0;
|
|
2243
|
+
font-size: 32px;
|
|
2244
|
+
font-weight: bold;
|
|
2245
|
+
font-family: inherit;
|
|
2246
|
+
color: ${headerTextColor};
|
|
2247
|
+
`;
|
|
2248
|
+
headerSection.appendChild(headerText);
|
|
2249
|
+
modal.appendChild(headerSection);
|
|
2250
|
+
const contentSection = document.createElement("div");
|
|
2251
|
+
const footerPadding = step.welcome_footer_padding || 20;
|
|
2252
|
+
const footerBgColor = step.welcome_footer_bg_color || "#ffffff";
|
|
2253
|
+
const footerTextColor = step.welcome_footer_text_color || "#333333";
|
|
2254
|
+
const footerHeight = step.welcome_footer_height || 60;
|
|
2255
|
+
contentSection.style.cssText = `
|
|
2256
|
+
padding: ${footerPadding}px 30px;
|
|
2257
|
+
text-align: center;
|
|
2258
|
+
background: ${footerBgColor};
|
|
2259
|
+
color: ${footerTextColor};
|
|
2260
|
+
min-height: ${footerHeight}px;
|
|
2261
|
+
display: flex;
|
|
2262
|
+
align-items: center;
|
|
2263
|
+
justify-content: center;
|
|
2264
|
+
`;
|
|
2265
|
+
contentSection.id = "rivia-welcome-preview-content";
|
|
2266
|
+
const descriptionText = document.createElement("p");
|
|
2267
|
+
descriptionText.textContent = step.content || "Welcome message";
|
|
2268
|
+
descriptionText.style.cssText = `
|
|
2269
|
+
margin: 0;
|
|
2270
|
+
font-size: 14px;
|
|
2271
|
+
line-height: 1.6;
|
|
2272
|
+
color: ${footerTextColor};
|
|
2273
|
+
white-space: pre-wrap;
|
|
2274
|
+
word-wrap: break-word;
|
|
2275
|
+
font-family: inherit;
|
|
2276
|
+
`;
|
|
2277
|
+
contentSection.appendChild(descriptionText);
|
|
2278
|
+
modal.appendChild(contentSection);
|
|
2279
|
+
const buttonSection = document.createElement("div");
|
|
2280
|
+
buttonSection.style.cssText = `
|
|
2281
|
+
display: flex;
|
|
2282
|
+
gap: 12px;
|
|
2283
|
+
padding: 20px 30px;
|
|
2284
|
+
border-top: 1px solid #e5e7eb;
|
|
2285
|
+
justify-content: flex-end;
|
|
2286
|
+
`;
|
|
2287
|
+
const skipBtn = document.createElement("button");
|
|
2288
|
+
skipBtn.textContent = step.welcome_skip_label || "Skip";
|
|
2289
|
+
skipBtn.style.cssText = `
|
|
2290
|
+
padding: 8px 16px;
|
|
2291
|
+
border: 1px solid #d1d5db;
|
|
2292
|
+
border-radius: 6px;
|
|
2293
|
+
background: white;
|
|
2294
|
+
color: #6b7280;
|
|
2295
|
+
cursor: pointer;
|
|
2296
|
+
font-size: 14px;
|
|
2297
|
+
font-weight: 500;
|
|
2298
|
+
outline: none;
|
|
2299
|
+
transition: all 0.2s ease;
|
|
2300
|
+
`;
|
|
2301
|
+
skipBtn.onmouseover = () => {
|
|
2302
|
+
skipBtn.style.background = "#f3f4f6";
|
|
2303
|
+
};
|
|
2304
|
+
skipBtn.onmouseout = () => {
|
|
2305
|
+
skipBtn.style.background = "white";
|
|
2306
|
+
};
|
|
2307
|
+
skipBtn.onclick = () => {
|
|
2308
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2309
|
+
overlay2.remove();
|
|
2310
|
+
const backdropOverlay = document.getElementById(
|
|
2311
|
+
"rivia-welcome-preview-backdrop"
|
|
2312
|
+
);
|
|
2313
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2314
|
+
if (advanceAction === "skip button") {
|
|
2315
|
+
endTour();
|
|
2316
|
+
} else {
|
|
2317
|
+
endTour();
|
|
2318
|
+
}
|
|
2319
|
+
};
|
|
2320
|
+
buttonSection.appendChild(skipBtn);
|
|
2321
|
+
const nextBtn = document.createElement("button");
|
|
2322
|
+
nextBtn.textContent = step.welcome_next_label || "Next";
|
|
2323
|
+
nextBtn.style.cssText = `
|
|
2324
|
+
padding: 8px 16px;
|
|
2325
|
+
border: none;
|
|
2326
|
+
border-radius: 6px;
|
|
2327
|
+
background: #2563eb;
|
|
2328
|
+
color: white;
|
|
2329
|
+
cursor: pointer;
|
|
2330
|
+
font-size: 14px;
|
|
2331
|
+
font-weight: 500;
|
|
2332
|
+
outline: none;
|
|
2333
|
+
transition: all 0.2s ease;
|
|
2334
|
+
`;
|
|
2335
|
+
nextBtn.onmouseover = () => {
|
|
2336
|
+
nextBtn.style.background = "#1d4ed8";
|
|
2337
|
+
};
|
|
2338
|
+
nextBtn.onmouseout = () => {
|
|
2339
|
+
nextBtn.style.background = "#2563eb";
|
|
2340
|
+
};
|
|
2341
|
+
nextBtn.onclick = () => {
|
|
2342
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2343
|
+
overlay2.remove();
|
|
2344
|
+
const backdropOverlay = document.getElementById(
|
|
2345
|
+
"rivia-welcome-preview-backdrop"
|
|
2346
|
+
);
|
|
2347
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2348
|
+
if (advanceAction === "next button") {
|
|
2349
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2350
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2351
|
+
showStep(STATE.tourIndex, true);
|
|
2352
|
+
} else {
|
|
2353
|
+
endTour();
|
|
2354
|
+
}
|
|
2355
|
+
} else if (advanceAction === "scroll") {
|
|
2356
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2357
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2358
|
+
const nextStep2 = STATE.tips[STATE.tourIndex];
|
|
2359
|
+
const nextElement = findBySelector(nextStep2.selector);
|
|
2360
|
+
if (nextElement) {
|
|
2361
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
2362
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
2363
|
+
} else {
|
|
2364
|
+
showStep(STATE.tourIndex, true);
|
|
2365
|
+
}
|
|
2366
|
+
} else {
|
|
2367
|
+
endTour();
|
|
2368
|
+
}
|
|
2369
|
+
} else if (advanceAction === "click") {
|
|
2370
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2371
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2372
|
+
showStep(STATE.tourIndex, true);
|
|
2373
|
+
} else {
|
|
2374
|
+
endTour();
|
|
2375
|
+
}
|
|
2376
|
+
} else {
|
|
2377
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2378
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2379
|
+
showStep(STATE.tourIndex, true);
|
|
2380
|
+
} else {
|
|
2381
|
+
endTour();
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
};
|
|
2385
|
+
buttonSection.appendChild(nextBtn);
|
|
2386
|
+
modal.appendChild(buttonSection);
|
|
2387
|
+
overlay2.appendChild(modal);
|
|
2388
|
+
document.body.appendChild(overlay2);
|
|
2389
|
+
overlay2.onclick = (e) => {
|
|
2390
|
+
if (e.target === overlay2) {
|
|
2391
|
+
e.stopPropagation();
|
|
2392
|
+
overlay2.remove();
|
|
2393
|
+
const backdropOverlay = document.getElementById(
|
|
2394
|
+
"rivia-welcome-preview-backdrop"
|
|
2395
|
+
);
|
|
2396
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
modal.onclick = (e) => {
|
|
2400
|
+
e.stopPropagation();
|
|
2401
|
+
};
|
|
2402
|
+
console.log(
|
|
2403
|
+
"Welcome card preview displayed with backdrop:",
|
|
2404
|
+
backdropStyle,
|
|
2405
|
+
"and advance action:",
|
|
2406
|
+
step.basic_advanceAction
|
|
2407
|
+
);
|
|
2408
|
+
}
|
|
2409
|
+
function showModalDialogPreview(step, stepIndex) {
|
|
2410
|
+
const existingCenteredModal = document.getElementById(
|
|
2411
|
+
"rivia-modal-dialog-preview-modal"
|
|
2412
|
+
);
|
|
2413
|
+
if (existingCenteredModal) existingCenteredModal.remove();
|
|
2414
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
2415
|
+
if (backdropStyle !== "none") {
|
|
2416
|
+
const backdropOverlay = document.createElement("div");
|
|
2417
|
+
backdropOverlay.id = "rivia-modal-dialog-preview-backdrop";
|
|
2418
|
+
backdropOverlay.style.cssText = `
|
|
2419
|
+
position: fixed;
|
|
2420
|
+
inset: 0;
|
|
2421
|
+
z-index: 2147483643;
|
|
2422
|
+
pointer-events: none;
|
|
2423
|
+
`;
|
|
2424
|
+
if (backdropStyle === "boxed") {
|
|
2425
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
2426
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
2427
|
+
} else if (backdropStyle === "light overlay") {
|
|
2428
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
2429
|
+
backdropOverlay.style.border = "none";
|
|
2430
|
+
} else if (backdropStyle === "dark overlay") {
|
|
2431
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
2432
|
+
backdropOverlay.style.border = "none";
|
|
2433
|
+
}
|
|
2434
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
2435
|
+
}
|
|
2436
|
+
const centeredContainer = document.createElement("div");
|
|
2437
|
+
centeredContainer.id = "rivia-modal-dialog-preview-modal";
|
|
2438
|
+
centeredContainer.style.cssText = `
|
|
2439
|
+
position: fixed;
|
|
2440
|
+
inset: 0;
|
|
2441
|
+
display: flex;
|
|
2442
|
+
align-items: center;
|
|
2443
|
+
justify-content: center;
|
|
2444
|
+
z-index: 2147483644;
|
|
2445
|
+
pointer-events: none;
|
|
2446
|
+
`;
|
|
2447
|
+
const modal = document.createElement("div");
|
|
2448
|
+
modal.id = "rivia-modal-dialog-preview";
|
|
2449
|
+
const modalWidth = step.modal_width || 500;
|
|
2450
|
+
const modalHeight = step.modal_height || 400;
|
|
2451
|
+
const modalBgColor = step.modal_bg_color || "#ffffff";
|
|
2452
|
+
const modalTextColor = step.modal_text_color || "#333333";
|
|
2453
|
+
const modalFooterBgColor = step.modal_footer_bg_color || "#f3f4f6";
|
|
2454
|
+
const accentColor = step.modal_accent_color || "#10b981";
|
|
2455
|
+
modal.style.cssText = `
|
|
2456
|
+
pointer-events: auto;
|
|
2457
|
+
background: ${modalBgColor};
|
|
2458
|
+
border-radius: 12px;
|
|
2459
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
2460
|
+
width: ${modalWidth}px;
|
|
2461
|
+
max-width: 90vw;
|
|
2462
|
+
height: ${modalHeight}px;
|
|
2463
|
+
max-height: 80vh;
|
|
2464
|
+
overflow-y: auto;
|
|
2465
|
+
padding: 0;
|
|
2466
|
+
display: flex;
|
|
2467
|
+
flex-direction: column;
|
|
2468
|
+
`;
|
|
2469
|
+
const accentLine = document.createElement("div");
|
|
2470
|
+
accentLine.style.cssText = `
|
|
2471
|
+
height: 4px;
|
|
2472
|
+
background: ${accentColor};
|
|
2473
|
+
border-radius: 12px 12px 0 0;
|
|
2474
|
+
`;
|
|
2475
|
+
modal.appendChild(accentLine);
|
|
2476
|
+
const contentSection = document.createElement("div");
|
|
2477
|
+
contentSection.style.cssText = `
|
|
2478
|
+
flex: 1;
|
|
2479
|
+
padding: 30px;
|
|
2480
|
+
color: ${modalTextColor};
|
|
2481
|
+
overflow-y: auto;
|
|
2482
|
+
white-space: pre-wrap;
|
|
2483
|
+
word-wrap: break-word;
|
|
2484
|
+
`;
|
|
2485
|
+
contentSection.textContent = step.content || "Type your content here.";
|
|
2486
|
+
modal.appendChild(contentSection);
|
|
2487
|
+
const footerSection = document.createElement("div");
|
|
2488
|
+
footerSection.style.cssText = `
|
|
2489
|
+
background: ${modalFooterBgColor};
|
|
2490
|
+
padding: 20px 30px;
|
|
2491
|
+
border-top: 1px solid #e5e7eb;
|
|
2492
|
+
border-radius: 0 0 12px 12px;
|
|
2493
|
+
display: flex;
|
|
2494
|
+
justify-content: flex-end;
|
|
2495
|
+
gap: 12px;
|
|
2496
|
+
`;
|
|
2497
|
+
const skipBtn = document.createElement("button");
|
|
2498
|
+
skipBtn.textContent = step.modal_skip_label || "Skip";
|
|
2499
|
+
skipBtn.style.cssText = `
|
|
2500
|
+
background: transparent;
|
|
2501
|
+
color: #9ca3af;
|
|
2502
|
+
border: none;
|
|
2503
|
+
padding: 10px 20px;
|
|
2504
|
+
border-radius: 6px;
|
|
2505
|
+
font-size: 14px;
|
|
2506
|
+
font-weight: 500;
|
|
2507
|
+
cursor: pointer;
|
|
2508
|
+
transition: all 0.2s;
|
|
2509
|
+
`;
|
|
2510
|
+
skipBtn.onmouseover = () => {
|
|
2511
|
+
skipBtn.style.color = "#6b7280";
|
|
2512
|
+
skipBtn.style.background = "#f3f4f6";
|
|
2513
|
+
};
|
|
2514
|
+
skipBtn.onmouseout = () => {
|
|
2515
|
+
skipBtn.style.color = "#9ca3af";
|
|
2516
|
+
skipBtn.style.background = "transparent";
|
|
2517
|
+
};
|
|
2518
|
+
skipBtn.onclick = () => {
|
|
2519
|
+
centeredContainer.remove();
|
|
2520
|
+
const backdropOverlay = document.getElementById(
|
|
2521
|
+
"rivia-modal-dialog-preview-backdrop"
|
|
2522
|
+
);
|
|
2523
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2524
|
+
endTour();
|
|
2525
|
+
};
|
|
2526
|
+
footerSection.appendChild(skipBtn);
|
|
2527
|
+
const nextBtn = document.createElement("button");
|
|
2528
|
+
nextBtn.textContent = step.modal_next_label || "Next";
|
|
2529
|
+
nextBtn.style.cssText = `
|
|
2530
|
+
background: #2563eb;
|
|
2531
|
+
color: white;
|
|
2532
|
+
border: none;
|
|
2533
|
+
padding: 10px 24px;
|
|
2534
|
+
border-radius: 6px;
|
|
2535
|
+
font-size: 14px;
|
|
2536
|
+
font-weight: 600;
|
|
2537
|
+
cursor: pointer;
|
|
2538
|
+
transition: all 0.2s;
|
|
2539
|
+
`;
|
|
2540
|
+
nextBtn.onmouseover = () => nextBtn.style.background = "#1d4ed8";
|
|
2541
|
+
nextBtn.onmouseout = () => nextBtn.style.background = "#2563eb";
|
|
2542
|
+
nextBtn.onclick = () => {
|
|
2543
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2544
|
+
centeredContainer.remove();
|
|
2545
|
+
const backdropOverlay = document.getElementById(
|
|
2546
|
+
"rivia-modal-dialog-preview-backdrop"
|
|
2547
|
+
);
|
|
2548
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2549
|
+
if (advanceAction === "next button") {
|
|
2550
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2551
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2552
|
+
showStep(STATE.tourIndex, true);
|
|
2553
|
+
} else {
|
|
2554
|
+
endTour();
|
|
2555
|
+
}
|
|
2556
|
+
} else if (advanceAction === "scroll") {
|
|
2557
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2558
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2559
|
+
const nextStepData = STATE.tips[STATE.tourIndex];
|
|
2560
|
+
const nextElement = findBySelector(nextStepData.selector);
|
|
2561
|
+
if (nextElement) {
|
|
2562
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
2563
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
2564
|
+
} else {
|
|
2565
|
+
showStep(STATE.tourIndex, true);
|
|
2566
|
+
}
|
|
2567
|
+
} else {
|
|
2568
|
+
endTour();
|
|
2569
|
+
}
|
|
2570
|
+
} else if (advanceAction === "click") {
|
|
2571
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2572
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2573
|
+
showStep(STATE.tourIndex, true);
|
|
2574
|
+
} else {
|
|
2575
|
+
endTour();
|
|
2576
|
+
}
|
|
2577
|
+
} else {
|
|
2578
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2579
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2580
|
+
showStep(STATE.tourIndex, true);
|
|
2581
|
+
} else {
|
|
2582
|
+
endTour();
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
};
|
|
2586
|
+
footerSection.appendChild(nextBtn);
|
|
2587
|
+
modal.appendChild(footerSection);
|
|
2588
|
+
centeredContainer.appendChild(modal);
|
|
2589
|
+
document.body.appendChild(centeredContainer);
|
|
2590
|
+
console.log(
|
|
2591
|
+
"Modal dialog preview displayed with backdrop:",
|
|
2592
|
+
backdropStyle,
|
|
2593
|
+
"and advance action:",
|
|
2594
|
+
step.basic_advanceAction
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
function attachNavigationButtons(tip, i, isPreview) {
|
|
2598
|
+
const nav = document.createElement("div");
|
|
2599
|
+
const navStyle = isPreview ? `
|
|
2600
|
+
display: flex;
|
|
2601
|
+
gap: 8px;
|
|
2602
|
+
margin-top: 12px;
|
|
2603
|
+
justify-content: flex-end;
|
|
2604
|
+
` : `
|
|
2605
|
+
display: flex;
|
|
2606
|
+
gap: 6px;
|
|
2607
|
+
margin-top: 8px;
|
|
2608
|
+
justify-content: flex-end;
|
|
2609
|
+
`;
|
|
2610
|
+
nav.style.cssText = navStyle;
|
|
2611
|
+
const step = STATE.tips[i];
|
|
2612
|
+
const advanceAction = step?.basic_advanceAction || "next button";
|
|
2613
|
+
const card_back_button = step?.card_back_button ?? false;
|
|
2614
|
+
const card_next_button = step?.card_next_button ?? true;
|
|
2615
|
+
const card_skip_button = step?.card_skip_button ?? false;
|
|
2616
|
+
if (i > 0 && card_back_button) {
|
|
2617
|
+
const back = document.createElement("button");
|
|
2618
|
+
back.textContent = "\u2190 Back";
|
|
2619
|
+
const backStyle = isPreview ? `
|
|
2620
|
+
padding: 8px 14px;
|
|
2621
|
+
border-radius: 8px;
|
|
2622
|
+
border: 1px solid rgba(37, 99, 235, 0.3);
|
|
2623
|
+
background: rgba(37, 99, 235, 0.1);
|
|
2624
|
+
color: #2563eb;
|
|
2625
|
+
cursor: pointer;
|
|
2626
|
+
font-size: 13px;
|
|
2627
|
+
font-weight: 500;
|
|
2628
|
+
transition: all 0.2s ease;
|
|
2629
|
+
` : `
|
|
2630
|
+
padding: 6px 10px;
|
|
2631
|
+
border-radius: 8px;
|
|
2632
|
+
border: 1px solid #333;
|
|
2633
|
+
background: #1f1f1f;
|
|
2634
|
+
color: #fff;
|
|
2635
|
+
cursor: pointer;
|
|
2636
|
+
`;
|
|
2637
|
+
back.style.cssText = backStyle;
|
|
2638
|
+
back.onmouseover = () => {
|
|
2639
|
+
if (isPreview) back.style.background = "rgba(37, 99, 235, 0.2)";
|
|
2640
|
+
};
|
|
2641
|
+
back.onmouseout = () => {
|
|
2642
|
+
if (isPreview) back.style.background = "rgba(37, 99, 235, 0.1)";
|
|
2643
|
+
};
|
|
2644
|
+
back.onclick = () => prevStep();
|
|
2645
|
+
nav.appendChild(back);
|
|
2646
|
+
}
|
|
2647
|
+
if (advanceAction === "manual click") {
|
|
2648
|
+
const targetElement = findBySelector(step.selector);
|
|
2649
|
+
if (targetElement) {
|
|
2650
|
+
attachClickListenerToElement(targetElement);
|
|
2651
|
+
}
|
|
2652
|
+
} else if (advanceAction === "scroll") {
|
|
2653
|
+
const scrollMsg = document.createElement("div");
|
|
2654
|
+
scrollMsg.textContent = "\u2B07\uFE0F Scroll to continue";
|
|
2655
|
+
scrollMsg.style.cssText = `
|
|
2656
|
+
padding: 8px 14px;
|
|
2657
|
+
border-radius: 8px;
|
|
2658
|
+
background: rgba(168, 85, 247, 0.1);
|
|
2659
|
+
color: #a855f7;
|
|
2660
|
+
font-size: 13px;
|
|
2661
|
+
font-weight: 500;
|
|
2662
|
+
align-self: center;
|
|
2663
|
+
`;
|
|
2664
|
+
nav.appendChild(scrollMsg);
|
|
2665
|
+
enableScrollAdvance();
|
|
2666
|
+
} else if (card_next_button) {
|
|
2667
|
+
const next = document.createElement("button");
|
|
2668
|
+
next.textContent = i === STATE.tips.length - 1 ? "Finish \u2713" : "Next \u2192";
|
|
2669
|
+
const nextStyle = isPreview ? `
|
|
2670
|
+
padding: 8px 14px;
|
|
2671
|
+
border-radius: 8px;
|
|
2672
|
+
border: 1px solid rgba(37, 99, 235, 0.5);
|
|
2673
|
+
background: linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%);
|
|
2674
|
+
color: white;
|
|
2675
|
+
cursor: pointer;
|
|
2676
|
+
font-size: 13px;
|
|
2677
|
+
font-weight: 600;
|
|
2678
|
+
transition: all 0.2s ease;
|
|
2679
|
+
` : `
|
|
2680
|
+
padding: 6px 10px;
|
|
2681
|
+
border-radius: 8px;
|
|
2682
|
+
border: 1px solid #333;
|
|
2683
|
+
background: #2563eb;
|
|
2684
|
+
color: #fff;
|
|
2685
|
+
cursor: pointer;
|
|
2686
|
+
`;
|
|
2687
|
+
next.style.cssText = nextStyle;
|
|
2688
|
+
next.onmouseover = () => {
|
|
2689
|
+
if (isPreview)
|
|
2690
|
+
next.style.background = "linear-gradient(135deg, rgba(37, 99, 235, 1) 0%, rgba(37, 99, 235, 0.9) 100%)";
|
|
2691
|
+
};
|
|
2692
|
+
next.onmouseout = () => {
|
|
2693
|
+
if (isPreview)
|
|
2694
|
+
next.style.background = "linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%)";
|
|
2695
|
+
};
|
|
2696
|
+
next.onclick = () => i === STATE.tips.length - 1 ? endTour() : nextStep();
|
|
2697
|
+
nav.appendChild(next);
|
|
2698
|
+
}
|
|
2699
|
+
if (card_skip_button) {
|
|
2700
|
+
const skip = document.createElement("button");
|
|
2701
|
+
skip.textContent = "Skip";
|
|
2702
|
+
const skipStyle = isPreview ? `
|
|
2703
|
+
padding: 8px 14px;
|
|
2704
|
+
border-radius: 8px;
|
|
2705
|
+
border: 1px solid rgba(168, 85, 247, 0.3);
|
|
2706
|
+
background: rgba(168, 85, 247, 0.1);
|
|
2707
|
+
color: #a855f7;
|
|
2708
|
+
cursor: pointer;
|
|
2709
|
+
font-size: 13px;
|
|
2710
|
+
font-weight: 500;
|
|
2711
|
+
transition: all 0.2s ease;
|
|
2712
|
+
` : `
|
|
2713
|
+
padding: 6px 10px;
|
|
2714
|
+
border-radius: 8px;
|
|
2715
|
+
border: 1px solid #999;
|
|
2716
|
+
background: #f3f4f6;
|
|
2717
|
+
color: #374151;
|
|
2718
|
+
cursor: pointer;
|
|
2719
|
+
`;
|
|
2720
|
+
skip.style.cssText = skipStyle;
|
|
2721
|
+
skip.onmouseover = () => {
|
|
2722
|
+
if (isPreview) skip.style.background = "rgba(168, 85, 247, 0.2)";
|
|
2723
|
+
};
|
|
2724
|
+
skip.onmouseout = () => {
|
|
2725
|
+
if (isPreview) skip.style.background = "rgba(168, 85, 247, 0.1)";
|
|
2726
|
+
};
|
|
2727
|
+
skip.onclick = () => endTour();
|
|
2728
|
+
nav.appendChild(skip);
|
|
2729
|
+
}
|
|
2730
|
+
tip.appendChild(nav);
|
|
2731
|
+
if (isPreview) {
|
|
2732
|
+
tip.setAttribute("data-rivia-preview-nav", "true");
|
|
2733
|
+
}
|
|
2734
|
+
if (isPreview) {
|
|
2735
|
+
const stepIndicator = document.createElement("div");
|
|
2736
|
+
stepIndicator.style.cssText = `
|
|
2737
|
+
position: absolute;
|
|
2738
|
+
top: 8px;
|
|
2739
|
+
right: 12px;
|
|
2740
|
+
font-size: 11px;
|
|
2741
|
+
color: rgba(37, 99, 235, 0.6);
|
|
2742
|
+
font-weight: 500;
|
|
2743
|
+
`;
|
|
2744
|
+
stepIndicator.textContent = `Step ${i + 1} of ${STATE.tips.length}`;
|
|
2745
|
+
tip.appendChild(stepIndicator);
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
function cleanupAllOverlays() {
|
|
2749
|
+
const welcomeBackdropOverlay = document.getElementById(
|
|
2750
|
+
"rivia-welcome-backdrop-overlay"
|
|
2751
|
+
);
|
|
2752
|
+
if (welcomeBackdropOverlay) {
|
|
2753
|
+
welcomeBackdropOverlay.remove();
|
|
2754
|
+
}
|
|
2755
|
+
const welcomePreviewOverlay = document.getElementById(
|
|
2756
|
+
"rivia-welcome-preview-overlay"
|
|
2757
|
+
);
|
|
2758
|
+
if (welcomePreviewOverlay) {
|
|
2759
|
+
welcomePreviewOverlay.remove();
|
|
2760
|
+
}
|
|
2761
|
+
const backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
2762
|
+
if (backdropOverlay) {
|
|
2763
|
+
if (backdropOverlay.updateBackdrop) {
|
|
2764
|
+
window.removeEventListener("scroll", backdropOverlay.updateBackdrop);
|
|
2765
|
+
window.removeEventListener("resize", backdropOverlay.updateBackdrop);
|
|
2766
|
+
}
|
|
2767
|
+
backdropOverlay.remove();
|
|
2768
|
+
}
|
|
2769
|
+
const spotlightOverlay = document.getElementById("rivia-spotlight-overlay");
|
|
2770
|
+
if (spotlightOverlay) {
|
|
2771
|
+
if (spotlightOverlay.updateSpotlight) {
|
|
2772
|
+
window.removeEventListener("scroll", spotlightOverlay.updateSpotlight);
|
|
2773
|
+
window.removeEventListener("resize", spotlightOverlay.updateSpotlight);
|
|
2774
|
+
}
|
|
2775
|
+
spotlightOverlay.remove();
|
|
2776
|
+
}
|
|
2777
|
+
document.querySelectorAll('[style*="box-shadow: 0 0 0 9999px"]').forEach((el) => {
|
|
2778
|
+
el.remove();
|
|
2779
|
+
});
|
|
2780
|
+
document.querySelectorAll('svg[id*="rivia"]').forEach((svg) => {
|
|
2781
|
+
if (svg.updateSpotlight) {
|
|
2782
|
+
window.removeEventListener("scroll", svg.updateSpotlight);
|
|
2783
|
+
window.removeEventListener("resize", svg.updateSpotlight);
|
|
2784
|
+
}
|
|
2785
|
+
svg.remove();
|
|
2786
|
+
});
|
|
2787
|
+
}
|
|
2788
|
+
function nextStep() {
|
|
2789
|
+
if (STATE.tourIndex < STATE.tips.length - 1) {
|
|
2790
|
+
let getNextStepInfo3 = function(currentIndex2) {
|
|
2791
|
+
if (currentIndex2 >= STATE.tips.length - 1) {
|
|
2792
|
+
return { type: "end", index: currentIndex2 };
|
|
2793
|
+
}
|
|
2794
|
+
const nextStep2 = STATE.tips[currentIndex2 + 1];
|
|
2795
|
+
if (!nextStep2) return { type: "end", index: currentIndex2 };
|
|
2796
|
+
if (nextStep2.targetUrl && nextStep2.targetUrl.trim()) {
|
|
2797
|
+
console.log("WE reached navigation");
|
|
2798
|
+
return { type: "navigate", index: currentIndex2 + 1, url: nextStep2.targetUrl };
|
|
2799
|
+
}
|
|
2800
|
+
if (isStepAvailableOnCurrentPage(nextStep2)) {
|
|
2801
|
+
return { type: "show", index: currentIndex2 + 1 };
|
|
2802
|
+
}
|
|
2803
|
+
return getNextStepInfo3(currentIndex2 + 1);
|
|
2804
|
+
};
|
|
2805
|
+
var getNextStepInfo2 = getNextStepInfo3;
|
|
2806
|
+
const currentIndex = STATE.tourIndex;
|
|
2807
|
+
STATE.tourIndex++;
|
|
2808
|
+
const nextStepData = STATE.tips[STATE.tourIndex];
|
|
2809
|
+
console.log("\u{1F7E2} nextStep called - moving from step", currentIndex, "to", STATE.tourIndex);
|
|
2810
|
+
if (nextStepData.nextUrl && nextStepData.nextUrl.trim()) {
|
|
2811
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
2812
|
+
tourIndex: STATE.tourIndex,
|
|
2813
|
+
tourId: STATE.tour_id,
|
|
2814
|
+
tips: STATE.tips,
|
|
2815
|
+
title: STATE.title || "Untitled Tour",
|
|
2816
|
+
user_var1: user_var12,
|
|
2817
|
+
publish: STATE.publish
|
|
2818
|
+
}));
|
|
2819
|
+
const navUrl = addTourParamsToUrl(nextStepData.nextUrl, STATE.tour_id);
|
|
2820
|
+
console.log("\u{1F7E2} Saving tour state before navigation to:", navUrl);
|
|
2821
|
+
window.location.href = navUrl;
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
const nextStepInfo = getNextStepInfo3(currentIndex);
|
|
2825
|
+
if (nextStepInfo.type === "navigate") {
|
|
2826
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
2827
|
+
tourIndex: nextStepInfo.index,
|
|
2828
|
+
tourId: STATE.tour_id,
|
|
2829
|
+
isPreviewMode: STATE.isPreviewMode,
|
|
2830
|
+
user_var1: user_var12,
|
|
2831
|
+
tips: STATE.tips,
|
|
2832
|
+
title: STATE.title || "Untitled Tour",
|
|
2833
|
+
publish: STATE.publish
|
|
2834
|
+
}));
|
|
2835
|
+
const navUrl = addTourParamsToUrl(nextStepInfo.url, STATE.tour_id);
|
|
2836
|
+
console.log("\u{1F7E2} Navigating to next step URL:", navUrl);
|
|
2837
|
+
window.location.href = navUrl;
|
|
2838
|
+
return;
|
|
2839
|
+
}
|
|
2840
|
+
cleanupAllOverlays();
|
|
2841
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
2842
|
+
} else if (STATE.tourIndex === STATE.tips.length - 1) {
|
|
2843
|
+
endTour();
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
function getNextStepInfo(currentIndex) {
|
|
2847
|
+
if (currentIndex >= STATE.tips.length - 1) {
|
|
2848
|
+
return { type: "end", index: currentIndex };
|
|
2849
|
+
}
|
|
2850
|
+
const nextStep2 = STATE.tips[currentIndex + 1];
|
|
2851
|
+
if (!nextStep2) return { type: "end", index: currentIndex };
|
|
2852
|
+
if (isStepAvailableOnCurrentPage(nextStep2)) {
|
|
2853
|
+
return { type: "show", index: currentIndex + 1 };
|
|
2854
|
+
}
|
|
2855
|
+
if (nextStep2.targetUrl && nextStep2.targetUrl.trim()) {
|
|
2856
|
+
return { type: "navigate", index: currentIndex + 1, url: nextStep2.targetUrl };
|
|
2857
|
+
}
|
|
2858
|
+
return getNextStepInfo(currentIndex + 1);
|
|
2859
|
+
}
|
|
2860
|
+
function isStepAvailableOnCurrentPage(step) {
|
|
2861
|
+
if (!step) return false;
|
|
2862
|
+
if (!step.targetUrl || !step.targetUrl.trim()) return true;
|
|
2863
|
+
return urlMatches(step.targetUrl);
|
|
2864
|
+
}
|
|
2865
|
+
function urlMatches(pattern, currentUrl = window.location.href) {
|
|
2866
|
+
if (!pattern || !pattern.trim()) return true;
|
|
2867
|
+
const cleanPattern = pattern.trim();
|
|
2868
|
+
const cleanUrl = currentUrl.trim();
|
|
2869
|
+
if (cleanPattern === cleanUrl) return true;
|
|
2870
|
+
try {
|
|
2871
|
+
const patternUrl = new URL(cleanPattern);
|
|
2872
|
+
const currentPageUrl = new URL(cleanUrl);
|
|
2873
|
+
if (patternUrl.origin === currentPageUrl.origin) {
|
|
2874
|
+
const patternPath = patternUrl.pathname;
|
|
2875
|
+
const currentPath = currentPageUrl.pathname;
|
|
2876
|
+
if (patternPath === "/" || patternPath === "") {
|
|
2877
|
+
return true;
|
|
2878
|
+
}
|
|
2879
|
+
return currentPath.startsWith(patternPath);
|
|
2880
|
+
}
|
|
2881
|
+
} catch (e) {
|
|
2882
|
+
console.warn("Failed to parse URLs for domain matching:", cleanPattern, cleanUrl, e);
|
|
2883
|
+
}
|
|
2884
|
+
if (cleanPattern.includes("*")) {
|
|
2885
|
+
const regexPattern = cleanPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
2886
|
+
try {
|
|
2887
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
2888
|
+
return regex.test(cleanUrl);
|
|
2889
|
+
} catch (e) {
|
|
2890
|
+
console.warn("Invalid URL pattern:", cleanPattern, e);
|
|
2891
|
+
return false;
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2894
|
+
return cleanUrl.includes(cleanPattern);
|
|
2895
|
+
}
|
|
2896
|
+
function addTourParamsToUrl(url, tourId) {
|
|
2897
|
+
if (!url || !tourId) return url;
|
|
2898
|
+
try {
|
|
2899
|
+
const urlObj = new URL(url);
|
|
2900
|
+
return urlObj.toString();
|
|
2901
|
+
} catch (e) {
|
|
2902
|
+
console.warn("Failed to add tour params to URL:", url, e);
|
|
2903
|
+
return url;
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
function getPreviousStepInfo(currentIndex) {
|
|
2907
|
+
if (currentIndex <= 0) {
|
|
2908
|
+
return { type: "start", index: 0 };
|
|
2909
|
+
}
|
|
2910
|
+
const prevStep2 = STATE.tips[currentIndex - 1];
|
|
2911
|
+
if (!prevStep2) return { type: "start", index: 0 };
|
|
2912
|
+
if (isStepAvailableOnCurrentPage(prevStep2)) {
|
|
2913
|
+
return { type: "show", index: currentIndex - 1 };
|
|
2914
|
+
}
|
|
2915
|
+
if (prevStep2.targetUrl && prevStep2.targetUrl.trim()) {
|
|
2916
|
+
return { type: "navigate", index: currentIndex - 1, url: prevStep2.targetUrl };
|
|
2917
|
+
}
|
|
2918
|
+
return getPreviousStepInfo(currentIndex - 1);
|
|
2919
|
+
}
|
|
2920
|
+
function prevStep() {
|
|
2921
|
+
if (STATE.tourIndex > 0) {
|
|
2922
|
+
const prevInfo = getPreviousStepInfo(STATE.tourIndex);
|
|
2923
|
+
if (prevInfo.type === "start") {
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
if (prevInfo.type === "navigate") {
|
|
2927
|
+
STATE.tourIndex = prevInfo.index;
|
|
2928
|
+
const prevNavUrl = addTourParamsToUrl(prevInfo.url, STATE.tour_id);
|
|
2929
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
2930
|
+
tourIndex: STATE.tourIndex,
|
|
2931
|
+
tourId: STATE.tour_id,
|
|
2932
|
+
user_var1: user_var12,
|
|
2933
|
+
isPreviewMode: STATE.isPreviewMode,
|
|
2934
|
+
tips: STATE.tips,
|
|
2935
|
+
title: STATE.title,
|
|
2936
|
+
publish: STATE.publish
|
|
2937
|
+
}));
|
|
2938
|
+
console.log(" Navigating to previous step URL:", prevNavUrl);
|
|
2939
|
+
window.location.href = prevNavUrl;
|
|
2940
|
+
return;
|
|
2941
|
+
}
|
|
2942
|
+
if (prevInfo.type === "show") {
|
|
2943
|
+
STATE.tourIndex = prevInfo.index;
|
|
2944
|
+
cleanupAllOverlays();
|
|
2945
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
function endTour() {
|
|
2950
|
+
console.log("Ending tour and cleaning up UI elements...");
|
|
2951
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
2952
|
+
STATE.tourIndex = 0;
|
|
2953
|
+
const user_var2 = user_var12;
|
|
2954
|
+
const backendUrl = `http://localhost:5000/tours_clients/${STATE.tour_id}`;
|
|
2955
|
+
const payload = {
|
|
2956
|
+
name: user_var2,
|
|
2957
|
+
is_completed: true
|
|
2958
|
+
};
|
|
2959
|
+
fetch(backendUrl, {
|
|
2960
|
+
method: "POST",
|
|
2961
|
+
// <-- FIXED
|
|
2962
|
+
headers: { "Content-Type": "application/json" },
|
|
2963
|
+
credentials: "include",
|
|
2964
|
+
body: JSON.stringify(payload),
|
|
2965
|
+
keepalive: true
|
|
2966
|
+
// allow sending even during unload
|
|
2967
|
+
}).catch((err) => {
|
|
2968
|
+
console.error("Failed to end tour:", err);
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
function updateUrlStatus() {
|
|
2972
|
+
const urlStatus = document.getElementById("rivia-url-status");
|
|
2973
|
+
if (!urlStatus) return;
|
|
2974
|
+
const currentStep = STATE.tips[STATE.tourIndex];
|
|
2975
|
+
if (!currentStep) {
|
|
2976
|
+
urlStatus.textContent = "\u{1F4CD} Current URL";
|
|
2977
|
+
return;
|
|
2978
|
+
}
|
|
2979
|
+
const stepUrlInfo = getStepUrlInfo(currentStep);
|
|
2980
|
+
if (stepUrlInfo) {
|
|
2981
|
+
if (stepUrlInfo.isAvailable) {
|
|
2982
|
+
urlStatus.textContent = "\u2713 On this page";
|
|
2983
|
+
urlStatus.style.color = "#86efac";
|
|
2984
|
+
} else {
|
|
2985
|
+
const shortUrl = stepUrlInfo.targetUrl.length > 30 ? stepUrlInfo.targetUrl.substring(0, 27) + "..." : stepUrlInfo.targetUrl;
|
|
2986
|
+
urlStatus.textContent = "\u{1F4CD} " + shortUrl;
|
|
2987
|
+
urlStatus.style.color = "#fbbf24";
|
|
2988
|
+
}
|
|
2989
|
+
urlStatus.title = stepUrlInfo.displayText;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
function playTour() {
|
|
2993
|
+
if (STATE.is_completed)
|
|
2994
|
+
return;
|
|
2995
|
+
if (!STATE.tips.length) {
|
|
2996
|
+
console.warn("No tips loaded for this host");
|
|
2997
|
+
return;
|
|
2998
|
+
}
|
|
2999
|
+
STATE.savedTourIndex = STATE.tourIndex;
|
|
3000
|
+
STATE.isPreviewMode = true;
|
|
3001
|
+
updateUrlStatus();
|
|
3002
|
+
console.log("Cleaning up UI elements before preview...");
|
|
3003
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
3004
|
+
document.querySelectorAll('[id*="rivia-welcome-preview"]').forEach((el) => el.remove());
|
|
3005
|
+
document.querySelectorAll('[id*="rivia-welcome-edit"]').forEach((el) => el.remove());
|
|
3006
|
+
document.querySelectorAll('[id*="rivia-modal-dialog"]').forEach((el) => el.remove());
|
|
3007
|
+
const videoSettingsPanel = document.getElementById("rivia-video-settings-panel");
|
|
3008
|
+
if (videoSettingsPanel) {
|
|
3009
|
+
videoSettingsPanel.remove();
|
|
3010
|
+
}
|
|
3011
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
3012
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
3013
|
+
n.removeAttribute("data-rivia-highlight");
|
|
3014
|
+
n.style.outline = "";
|
|
3015
|
+
n.style.outlineOffset = "";
|
|
3016
|
+
n.style.backgroundColor = "";
|
|
3017
|
+
});
|
|
3018
|
+
try {
|
|
3019
|
+
overlay.remove();
|
|
3020
|
+
} catch (e) {
|
|
3021
|
+
}
|
|
3022
|
+
const rightPanel = document.getElementById("rivia-pointer-card-panel");
|
|
3023
|
+
if (rightPanel) {
|
|
3024
|
+
rightPanel.remove();
|
|
3025
|
+
}
|
|
3026
|
+
console.log("UI cleanup complete, starting preview...");
|
|
3027
|
+
const firstStep = STATE.tips[0];
|
|
3028
|
+
if (firstStep && firstStep.targetUrl) {
|
|
3029
|
+
const cleanCurrentUrl = cleanUrlForStorage(window.location.href);
|
|
3030
|
+
if (firstStep.targetUrl !== cleanCurrentUrl) {
|
|
3031
|
+
const navUrl = addTourParamsToUrl(firstStep.targetUrl, STATE.tour_id);
|
|
3032
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
3033
|
+
tourIndex: 0,
|
|
3034
|
+
tourId: STATE.tour_id,
|
|
3035
|
+
isPreviewMode: true,
|
|
3036
|
+
tips: STATE.tips,
|
|
3037
|
+
title: STATE.title || "Untitled Tour",
|
|
3038
|
+
publish: STATE.publish
|
|
3039
|
+
}));
|
|
3040
|
+
console.log("\u{1F7E2} Starting preview - navigating to first step targetUrl:", navUrl);
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
showStep(STATE.tourIndex, true);
|
|
3045
|
+
}
|
|
3046
|
+
function cleanUrlForStorage(url) {
|
|
3047
|
+
if (!url || !url.trim()) return url;
|
|
3048
|
+
try {
|
|
3049
|
+
const urlObj = new URL(url);
|
|
3050
|
+
urlObj.searchParams.delete("rivia_tour");
|
|
3051
|
+
urlObj.searchParams.delete("tour_id");
|
|
3052
|
+
return urlObj.toString();
|
|
3053
|
+
} catch (e) {
|
|
3054
|
+
console.warn("Failed to parse URL:", url, e);
|
|
3055
|
+
return url;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
function showFeedbackCardPreview(step, stepIndex) {
|
|
3059
|
+
if (!step) {
|
|
3060
|
+
console.warn("Step not found for preview");
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
3063
|
+
console.log("Showing feedback card preview for step:", step);
|
|
3064
|
+
cleanupAllOverlays();
|
|
3065
|
+
document.querySelectorAll('[id*="rivia-feedback-preview"]').forEach((el) => el.remove());
|
|
3066
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
3067
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
3068
|
+
if (backdropStyle !== "none") {
|
|
3069
|
+
const backdropOverlay = document.createElement("div");
|
|
3070
|
+
backdropOverlay.id = "rivia-feedback-preview-backdrop";
|
|
3071
|
+
backdropOverlay.style.cssText = `
|
|
3072
|
+
position: fixed;
|
|
3073
|
+
inset: 0;
|
|
3074
|
+
z-index: 2147483643;
|
|
3075
|
+
pointer-events: none;
|
|
3076
|
+
`;
|
|
3077
|
+
if (backdropStyle === "boxed") {
|
|
3078
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
3079
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
3080
|
+
} else if (backdropStyle === "light overlay") {
|
|
3081
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
3082
|
+
backdropOverlay.style.border = "none";
|
|
3083
|
+
} else if (backdropStyle === "dark overlay") {
|
|
3084
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
3085
|
+
backdropOverlay.style.border = "none";
|
|
3086
|
+
}
|
|
3087
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
3088
|
+
}
|
|
3089
|
+
const overlay2 = document.createElement("div");
|
|
3090
|
+
overlay2.id = "rivia-feedback-preview-overlay";
|
|
3091
|
+
overlay2.style.cssText = `
|
|
3092
|
+
position: fixed;
|
|
3093
|
+
inset: 0;
|
|
3094
|
+
background: rgba(0, 0, 0, 0.5);
|
|
3095
|
+
display: flex;
|
|
3096
|
+
align-items: center;
|
|
3097
|
+
justify-content: center;
|
|
3098
|
+
z-index: 2147483644;
|
|
3099
|
+
`;
|
|
3100
|
+
const modal = document.createElement("div");
|
|
3101
|
+
modal.id = "rivia-feedback-preview-modal";
|
|
3102
|
+
const bgColor = step.feedback_bg_color || "#ffffff";
|
|
3103
|
+
modal.style.cssText = `
|
|
3104
|
+
background: ${bgColor};
|
|
3105
|
+
border-radius: 12px;
|
|
3106
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
3107
|
+
max-width: 700px;
|
|
3108
|
+
width: 90%;
|
|
3109
|
+
max-height: 80vh;
|
|
3110
|
+
overflow-y: auto;
|
|
3111
|
+
padding: 0;
|
|
3112
|
+
`;
|
|
3113
|
+
const headerSection = document.createElement("div");
|
|
3114
|
+
const headerBgColor = step.feedback_header_bg_color || "#667eea";
|
|
3115
|
+
const headerTextColor = step.feedback_header_text_color || "#ffffff";
|
|
3116
|
+
const headerHeight = step.feedback_header_height || 80;
|
|
3117
|
+
headerSection.style.cssText = `
|
|
3118
|
+
background: ${headerBgColor};
|
|
3119
|
+
padding: ${headerHeight / 2}px 30px;
|
|
3120
|
+
color: ${headerTextColor};
|
|
3121
|
+
border-radius: 12px 12px 0 0;
|
|
3122
|
+
text-align: center;
|
|
3123
|
+
min-height: ${headerHeight}px;
|
|
3124
|
+
display: flex;
|
|
3125
|
+
align-items: center;
|
|
3126
|
+
justify-content: center;
|
|
3127
|
+
`;
|
|
3128
|
+
headerSection.id = "rivia-feedback-preview-header";
|
|
3129
|
+
const headerText = document.createElement("h1");
|
|
3130
|
+
headerText.textContent = step.title || "How was your experience?";
|
|
3131
|
+
headerText.style.cssText = `
|
|
3132
|
+
margin: 0;
|
|
3133
|
+
font-size: 32px;
|
|
3134
|
+
font-weight: bold;
|
|
3135
|
+
font-family: inherit;
|
|
3136
|
+
color: ${headerTextColor};
|
|
3137
|
+
`;
|
|
3138
|
+
headerSection.appendChild(headerText);
|
|
3139
|
+
modal.appendChild(headerSection);
|
|
3140
|
+
const contentSection = document.createElement("div");
|
|
3141
|
+
const footerPadding = step.feedback_footer_padding || 20;
|
|
3142
|
+
const footerBgColor = step.feedback_footer_bg_color || "#ffffff";
|
|
3143
|
+
const footerTextColor = step.feedback_footer_text_color || "#333333";
|
|
3144
|
+
const footerHeight = step.feedback_footer_height || 60;
|
|
3145
|
+
contentSection.style.cssText = `
|
|
3146
|
+
padding: ${footerPadding}px 30px;
|
|
3147
|
+
text-align: center;
|
|
3148
|
+
background: ${footerBgColor};
|
|
3149
|
+
color: ${footerTextColor};
|
|
3150
|
+
min-height: ${footerHeight}px;
|
|
3151
|
+
display: flex;
|
|
3152
|
+
flex-direction: column;
|
|
3153
|
+
gap: 20px;
|
|
3154
|
+
`;
|
|
3155
|
+
contentSection.id = "rivia-feedback-preview-content";
|
|
3156
|
+
const questionText = document.createElement("p");
|
|
3157
|
+
questionText.textContent = step.content || "Please rate your experience";
|
|
3158
|
+
questionText.style.cssText = `
|
|
3159
|
+
margin: 0;
|
|
3160
|
+
font-size: 14px;
|
|
3161
|
+
line-height: 1.6;
|
|
3162
|
+
color: ${footerTextColor};
|
|
3163
|
+
white-space: pre-wrap;
|
|
3164
|
+
word-wrap: break-word;
|
|
3165
|
+
font-family: inherit;
|
|
3166
|
+
`;
|
|
3167
|
+
contentSection.appendChild(questionText);
|
|
3168
|
+
const emojiContainer = document.createElement("div");
|
|
3169
|
+
emojiContainer.style.cssText = `
|
|
3170
|
+
display: flex;
|
|
3171
|
+
justify-content: center;
|
|
3172
|
+
gap: 12px;
|
|
3173
|
+
flex-wrap: wrap;
|
|
3174
|
+
`;
|
|
3175
|
+
let selectedEmojiIndex = -1;
|
|
3176
|
+
const emojis = step.feedback_emojis || ["\u{1F620}", "\u{1F615}", "\u{1F610}", "\u{1F60A}", "\u{1F604}"];
|
|
3177
|
+
const currentEmoji = step.feedback_emoji || "\u{1F60A}";
|
|
3178
|
+
const displayEmojis = emojis;
|
|
3179
|
+
displayEmojis.forEach((emoji, index) => {
|
|
3180
|
+
const emojiBtn = document.createElement("button");
|
|
3181
|
+
emojiBtn.textContent = emoji;
|
|
3182
|
+
emojiBtn.style.cssText = `
|
|
3183
|
+
font-size: 32px;
|
|
3184
|
+
background: ${emoji === currentEmoji ? "rgba(102, 126, 234, 0.2)" : "transparent"};
|
|
3185
|
+
border: ${emoji === currentEmoji ? "2px solid #667eea" : "2px solid #e5e7eb"};
|
|
3186
|
+
border-radius: 8px;
|
|
3187
|
+
padding: 8px 12px;
|
|
3188
|
+
cursor: pointer;
|
|
3189
|
+
transition: all 0.2s ease;
|
|
3190
|
+
`;
|
|
3191
|
+
emojiBtn.onmouseover = () => {
|
|
3192
|
+
if (emoji !== currentEmoji) {
|
|
3193
|
+
emojiBtn.style.borderColor = "#667eea";
|
|
3194
|
+
emojiBtn.style.background = "rgba(102, 126, 234, 0.1)";
|
|
3195
|
+
}
|
|
3196
|
+
};
|
|
3197
|
+
emojiBtn.onmouseout = () => {
|
|
3198
|
+
if (emoji !== currentEmoji) {
|
|
3199
|
+
emojiBtn.style.borderColor = "#e5e7eb";
|
|
3200
|
+
emojiBtn.style.background = "transparent";
|
|
3201
|
+
}
|
|
3202
|
+
};
|
|
3203
|
+
emojiBtn.onclick = () => {
|
|
3204
|
+
selectedEmojiIndex = index + 1;
|
|
3205
|
+
document.querySelectorAll("[data-feedback-emoji-btn]").forEach((btn) => {
|
|
3206
|
+
const btnEmoji = btn.textContent;
|
|
3207
|
+
if (btnEmoji === emoji) {
|
|
3208
|
+
btn.style.background = "rgba(102, 126, 234, 0.2)";
|
|
3209
|
+
btn.style.borderColor = "#667eea";
|
|
3210
|
+
} else {
|
|
3211
|
+
btn.style.background = "transparent";
|
|
3212
|
+
btn.style.borderColor = "#e5e7eb";
|
|
3213
|
+
}
|
|
3214
|
+
});
|
|
3215
|
+
};
|
|
3216
|
+
emojiBtn.setAttribute("data-feedback-emoji-btn", emoji);
|
|
3217
|
+
emojiBtn.setAttribute("data-emoji-index", index);
|
|
3218
|
+
emojiContainer.appendChild(emojiBtn);
|
|
3219
|
+
});
|
|
3220
|
+
contentSection.appendChild(emojiContainer);
|
|
3221
|
+
modal.appendChild(contentSection);
|
|
3222
|
+
const buttonSection = document.createElement("div");
|
|
3223
|
+
buttonSection.style.cssText = `
|
|
3224
|
+
display: flex;
|
|
3225
|
+
gap: 12px;
|
|
3226
|
+
padding: 20px 30px;
|
|
3227
|
+
border-top: 1px solid #e5e7eb;
|
|
3228
|
+
justify-content: flex-end;
|
|
3229
|
+
`;
|
|
3230
|
+
const skipBtn = document.createElement("button");
|
|
3231
|
+
skipBtn.textContent = step.feedback_skip_label || "Skip";
|
|
3232
|
+
skipBtn.style.cssText = `
|
|
3233
|
+
padding: 8px 16px;
|
|
3234
|
+
border: 1px solid #d1d5db;
|
|
3235
|
+
border-radius: 6px;
|
|
3236
|
+
background: white;
|
|
3237
|
+
color: #6b7280;
|
|
3238
|
+
cursor: pointer;
|
|
3239
|
+
font-size: 14px;
|
|
3240
|
+
font-weight: 500;
|
|
3241
|
+
outline: none;
|
|
3242
|
+
transition: all 0.2s ease;
|
|
3243
|
+
`;
|
|
3244
|
+
skipBtn.onmouseover = () => {
|
|
3245
|
+
skipBtn.style.background = "#f3f4f6";
|
|
3246
|
+
};
|
|
3247
|
+
skipBtn.onmouseout = () => {
|
|
3248
|
+
skipBtn.style.background = "white";
|
|
3249
|
+
};
|
|
3250
|
+
skipBtn.onclick = () => {
|
|
3251
|
+
overlay2.remove();
|
|
3252
|
+
const backdropOverlay = document.getElementById(
|
|
3253
|
+
"rivia-feedback-preview-backdrop"
|
|
3254
|
+
);
|
|
3255
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3256
|
+
endTour();
|
|
3257
|
+
};
|
|
3258
|
+
buttonSection.appendChild(skipBtn);
|
|
3259
|
+
const nextBtn = document.createElement("button");
|
|
3260
|
+
nextBtn.textContent = step.feedback_next_label || "Next";
|
|
3261
|
+
nextBtn.style.cssText = `
|
|
3262
|
+
padding: 8px 16px;
|
|
3263
|
+
border: none;
|
|
3264
|
+
border-radius: 6px;
|
|
3265
|
+
background: #2563eb;
|
|
3266
|
+
color: white;
|
|
3267
|
+
cursor: pointer;
|
|
3268
|
+
font-size: 14px;
|
|
3269
|
+
font-weight: 500;
|
|
3270
|
+
outline: none;
|
|
3271
|
+
transition: all 0.2s ease;
|
|
3272
|
+
`;
|
|
3273
|
+
nextBtn.onmouseover = () => {
|
|
3274
|
+
nextBtn.style.background = "#1d4ed8";
|
|
3275
|
+
};
|
|
3276
|
+
nextBtn.onmouseout = () => {
|
|
3277
|
+
nextBtn.style.background = "#2563eb";
|
|
3278
|
+
};
|
|
3279
|
+
nextBtn.onclick = () => {
|
|
3280
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
3281
|
+
overlay2.remove();
|
|
3282
|
+
const backdropOverlay = document.getElementById(
|
|
3283
|
+
"rivia-feedback-preview-backdrop"
|
|
3284
|
+
);
|
|
3285
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3286
|
+
if (selectedEmojiIndex !== -1) {
|
|
3287
|
+
console.log("Feedback given: emoji index", selectedEmojiIndex);
|
|
3288
|
+
step.feedback_given = selectedEmojiIndex;
|
|
3289
|
+
if (STATE.tour_id) putTips();
|
|
3290
|
+
else saveTips();
|
|
3291
|
+
}
|
|
3292
|
+
if (advanceAction === "next button") {
|
|
3293
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3294
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3295
|
+
showStep(STATE.tourIndex, true);
|
|
3296
|
+
} else {
|
|
3297
|
+
endTour();
|
|
3298
|
+
}
|
|
3299
|
+
} else if (advanceAction === "scroll") {
|
|
3300
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3301
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3302
|
+
const nextStep2 = STATE.tips[STATE.tourIndex];
|
|
3303
|
+
const nextElement = findBySelector(nextStep2.selector);
|
|
3304
|
+
if (nextElement) {
|
|
3305
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
3306
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
3307
|
+
} else {
|
|
3308
|
+
showStep(STATE.tourIndex, true);
|
|
3309
|
+
}
|
|
3310
|
+
} else {
|
|
3311
|
+
endTour();
|
|
3312
|
+
}
|
|
3313
|
+
} else if (advanceAction === "manual click") {
|
|
3314
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3315
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3316
|
+
showStep(STATE.tourIndex, true);
|
|
3317
|
+
} else {
|
|
3318
|
+
endTour();
|
|
3319
|
+
}
|
|
3320
|
+
} else {
|
|
3321
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3322
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3323
|
+
showStep(STATE.tourIndex, true);
|
|
3324
|
+
} else {
|
|
3325
|
+
endTour();
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
};
|
|
3329
|
+
buttonSection.appendChild(nextBtn);
|
|
3330
|
+
modal.appendChild(buttonSection);
|
|
3331
|
+
overlay2.appendChild(modal);
|
|
3332
|
+
document.body.appendChild(overlay2);
|
|
3333
|
+
overlay2.onclick = (e) => {
|
|
3334
|
+
if (e.target === overlay2) {
|
|
3335
|
+
e.stopPropagation();
|
|
3336
|
+
overlay2.remove();
|
|
3337
|
+
const backdropOverlay = document.getElementById(
|
|
3338
|
+
"rivia-feedback-preview-backdrop"
|
|
3339
|
+
);
|
|
3340
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3341
|
+
}
|
|
3342
|
+
};
|
|
3343
|
+
modal.onclick = (e) => {
|
|
3344
|
+
e.stopPropagation();
|
|
3345
|
+
};
|
|
3346
|
+
console.log(
|
|
3347
|
+
"Feedback card preview displayed with backdrop:",
|
|
3348
|
+
backdropStyle,
|
|
3349
|
+
"and advance action:",
|
|
3350
|
+
step.basic_advanceAction
|
|
3351
|
+
);
|
|
3352
|
+
}
|
|
3353
|
+
return { loadTips, playTour, endTour, STATE };
|
|
3354
|
+
}();
|
|
3355
|
+
function tours(tourId, userId) {
|
|
3356
|
+
if (!sessionStorage.getItem("rivia_tour_state")) {
|
|
3357
|
+
RIVIA_TOUR.loadTips(tourId, userId).then(() => {
|
|
3358
|
+
try {
|
|
3359
|
+
RIVIA_TOUR.playTour();
|
|
3360
|
+
} catch (err) {
|
|
3361
|
+
}
|
|
3362
|
+
});
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
var rivia_tour_default = tours;
|
|
3366
|
+
|
|
3367
|
+
// src/utils/banner.js
|
|
3368
|
+
function injectBanner(banner = {}, opts = {}, userId, bannerId) {
|
|
3369
|
+
try {
|
|
3370
|
+
let uploadVisitedPagesInBackground2 = function(bannerId2) {
|
|
3371
|
+
console.log("Uploading visited pages in background for banner ID: and user_var:", userId);
|
|
3372
|
+
let user_var2 = userId;
|
|
3373
|
+
const backendUrl22 = `http://localhost:5000/banners_clients/${bannerId2}`;
|
|
3374
|
+
try {
|
|
3375
|
+
const payload = {
|
|
3376
|
+
name: user_var2,
|
|
3377
|
+
is_completed: true
|
|
3378
|
+
};
|
|
3379
|
+
fetch(backendUrl22, {
|
|
3380
|
+
method: "POST",
|
|
3381
|
+
headers: { "Content-Type": "application/json" },
|
|
3382
|
+
credentials: "include",
|
|
3383
|
+
body: JSON.stringify(payload),
|
|
3384
|
+
keepalive: true
|
|
3385
|
+
}).then((res) => {
|
|
3386
|
+
if (res.status === 404) {
|
|
3387
|
+
throw new Error("Invalid banner id");
|
|
3388
|
+
}
|
|
3389
|
+
throw new Error(`Upload failed: ${res.status}`);
|
|
3390
|
+
}).catch((err) => {
|
|
3391
|
+
console.error("\u26A0\uFE0F Background PUT upload failed:", err);
|
|
3392
|
+
});
|
|
3393
|
+
} catch (err) {
|
|
3394
|
+
console.error("\u274C Error preparing background upload:", err);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
var uploadVisitedPagesInBackground = uploadVisitedPagesInBackground2;
|
|
3398
|
+
const prefix = opts.idPrefix || "rivia";
|
|
3399
|
+
const id = `${prefix}-banner`;
|
|
3400
|
+
const old = document.getElementById(id);
|
|
3401
|
+
if (old) old.remove();
|
|
3402
|
+
const camelToKebab = (s) => s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
3403
|
+
const applyStyles = (el, obj) => {
|
|
3404
|
+
if (!obj) return;
|
|
3405
|
+
for (const k in obj) {
|
|
3406
|
+
el.style.setProperty(camelToKebab(k), obj[k]);
|
|
3407
|
+
}
|
|
3408
|
+
};
|
|
3409
|
+
const container = document.createElement("div");
|
|
3410
|
+
container.id = id;
|
|
3411
|
+
container.style.position = "fixed";
|
|
3412
|
+
container.style.left = "0";
|
|
3413
|
+
container.style.right = "0";
|
|
3414
|
+
container.style.width = "100%";
|
|
3415
|
+
container.style.zIndex = "2147483647";
|
|
3416
|
+
container.style.display = "flex";
|
|
3417
|
+
container.style.fontFamily = "Avenir, sans-serif";
|
|
3418
|
+
container.style.fontSize = "14px";
|
|
3419
|
+
container.style.justifyContent = banner.align === "left" ? "flex-start" : banner.align === "right" ? "flex-end" : "center";
|
|
3420
|
+
if (!banner.position?.includes("inline")) {
|
|
3421
|
+
container.style[banner.position?.includes("bottom") ? "bottom" : "top"] = "0";
|
|
3422
|
+
}
|
|
3423
|
+
const box = document.createElement("div");
|
|
3424
|
+
box.style.display = "flex";
|
|
3425
|
+
box.style.alignItems = "center";
|
|
3426
|
+
box.style.fontFamily = "Avenir, sans-serif";
|
|
3427
|
+
box.style.fontSize = "14px";
|
|
3428
|
+
box.style.justifyContent = "space-between";
|
|
3429
|
+
box.style.padding = "16px 18px";
|
|
3430
|
+
box.style.gap = "12px";
|
|
3431
|
+
box.style.width = `${banner.canvas.width}px`;
|
|
3432
|
+
if (banner.position?.includes("inline")) {
|
|
3433
|
+
box.style.maxWidth = "100%";
|
|
3434
|
+
box.style.width = "100%";
|
|
3435
|
+
box.style.margin = "0";
|
|
3436
|
+
} else {
|
|
3437
|
+
box.style.maxWidth = "1100px";
|
|
3438
|
+
box.style.margin = "0 auto";
|
|
3439
|
+
}
|
|
3440
|
+
box.style.margin = "0 auto";
|
|
3441
|
+
box.style.borderRadius = banner.border?.radius ? `${banner.border.radius}px` : "6px";
|
|
3442
|
+
box.style.border = banner.border ? `${banner.border.width || 1}px solid ${banner.border.color || "#000"}` : "none";
|
|
3443
|
+
if (banner.background) {
|
|
3444
|
+
if (banner.background.type === "gradient") {
|
|
3445
|
+
box.style.background = `linear-gradient(${banner.background.gradient_degree || 0}deg,
|
|
3446
|
+
${banner.background.gradient_color_1 || "#fff"},
|
|
3447
|
+
${banner.background.gradient_color_2 || "#eee"})`;
|
|
3448
|
+
} else {
|
|
3449
|
+
box.style.background = banner.background.color || "#ffffff";
|
|
3450
|
+
}
|
|
3451
|
+
box.style.color = banner.background.text_color || banner.text_color || "#000";
|
|
3452
|
+
}
|
|
3453
|
+
if (banner.canvas) {
|
|
3454
|
+
if (banner.canvas.height) box.style.height = `${banner.canvas.height}px`;
|
|
3455
|
+
if (banner.canvas.width && !banner.position.includes("inline")) box.style.width = `${banner.canvas.width}px`;
|
|
3456
|
+
}
|
|
3457
|
+
const textWrap = document.createElement("div");
|
|
3458
|
+
textWrap.style.display = "flex";
|
|
3459
|
+
textWrap.style.flexDirection = "column";
|
|
3460
|
+
textWrap.style.flex = "1";
|
|
3461
|
+
textWrap.style.gap = "6px";
|
|
3462
|
+
textWrap.style.fontFamily = "Avenir, sans-serif";
|
|
3463
|
+
textWrap.style.fontSize = "14px";
|
|
3464
|
+
if (banner.text) {
|
|
3465
|
+
const textEl = document.createElement("div");
|
|
3466
|
+
textEl.textContent = banner.text;
|
|
3467
|
+
textEl.style.fontFamily = "Avenir, sans-serif";
|
|
3468
|
+
textEl.style.fontSize = "14px";
|
|
3469
|
+
textEl.style.opacity = "0.9";
|
|
3470
|
+
textEl.style.color = banner.background?.text_color || banner.text_color || "#fff";
|
|
3471
|
+
textWrap.appendChild(textEl);
|
|
3472
|
+
}
|
|
3473
|
+
const btnArea = document.createElement("div");
|
|
3474
|
+
btnArea.style.display = "flex";
|
|
3475
|
+
btnArea.style.alignItems = "center";
|
|
3476
|
+
btnArea.style.gap = "10px";
|
|
3477
|
+
const btn = banner.button || {};
|
|
3478
|
+
if (btn.text) {
|
|
3479
|
+
const a = btn.action_url ? document.createElement("a") : document.createElement("button");
|
|
3480
|
+
if (btn.action == "url") {
|
|
3481
|
+
a.href = btn.action_url;
|
|
3482
|
+
a.target = btn.target || "_blank";
|
|
3483
|
+
a.rel = "noopener noreferrer";
|
|
3484
|
+
} else {
|
|
3485
|
+
a.onclick = () => {
|
|
3486
|
+
container.remove();
|
|
3487
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3488
|
+
};
|
|
3489
|
+
}
|
|
3490
|
+
if (btn.border) {
|
|
3491
|
+
a.style.border = btn.border.width ? `${btn.border.width}px solid ${btn.border.color || "#000"}` : "none";
|
|
3492
|
+
a.style.borderRadius = btn.border.radius ? `${btn.border.radius}px` : "6px";
|
|
3493
|
+
}
|
|
3494
|
+
a.textContent = btn.text || "Learn More";
|
|
3495
|
+
a.style.padding = "8px 14px";
|
|
3496
|
+
a.style.fontFamily = "Avenir, sans-serif";
|
|
3497
|
+
a.style.fontSize = "14px";
|
|
3498
|
+
a.style.cursor = "pointer";
|
|
3499
|
+
a.style.background = btn.color || "#ffffffff";
|
|
3500
|
+
a.style.color = btn.text_color || "#0088ffff";
|
|
3501
|
+
btnArea.appendChild(a);
|
|
3502
|
+
}
|
|
3503
|
+
if (banner.align === "left") {
|
|
3504
|
+
box.appendChild(btnArea);
|
|
3505
|
+
box.appendChild(textWrap);
|
|
3506
|
+
if (banner.dismissible !== false) {
|
|
3507
|
+
const closeBtn = document.createElement("button");
|
|
3508
|
+
closeBtn.innerHTML = "\u2715";
|
|
3509
|
+
closeBtn.style.border = "none";
|
|
3510
|
+
closeBtn.style.background = "transparent";
|
|
3511
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
3512
|
+
closeBtn.style.fontSize = "14px";
|
|
3513
|
+
closeBtn.style.cursor = "pointer";
|
|
3514
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
3515
|
+
closeBtn.style.marginLeft = "auto";
|
|
3516
|
+
closeBtn.onclick = () => {
|
|
3517
|
+
container.remove();
|
|
3518
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3519
|
+
};
|
|
3520
|
+
box.appendChild(closeBtn);
|
|
3521
|
+
}
|
|
3522
|
+
} else if (banner.align === "bottom") {
|
|
3523
|
+
textWrap.style.textAlign = "left";
|
|
3524
|
+
box.appendChild(textWrap);
|
|
3525
|
+
if (banner.dismissible !== false) {
|
|
3526
|
+
const closeBtn = document.createElement("button");
|
|
3527
|
+
closeBtn.innerHTML = "\u2715";
|
|
3528
|
+
closeBtn.style.border = "none";
|
|
3529
|
+
closeBtn.style.background = "transparent";
|
|
3530
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
3531
|
+
closeBtn.style.fontSize = "14px";
|
|
3532
|
+
closeBtn.style.cursor = "pointer";
|
|
3533
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
3534
|
+
closeBtn.onclick = () => {
|
|
3535
|
+
container.remove();
|
|
3536
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3537
|
+
};
|
|
3538
|
+
box.appendChild(closeBtn);
|
|
3539
|
+
}
|
|
3540
|
+
btnArea.style.gridColumn = "1 / span 2";
|
|
3541
|
+
btnArea.style.display = "flex";
|
|
3542
|
+
btnArea.style.justifyContent = "center";
|
|
3543
|
+
box.appendChild(btnArea);
|
|
3544
|
+
} else {
|
|
3545
|
+
box.appendChild(textWrap);
|
|
3546
|
+
box.appendChild(btnArea);
|
|
3547
|
+
if (banner.dismissible !== false) {
|
|
3548
|
+
const closeBtn = document.createElement("button");
|
|
3549
|
+
closeBtn.innerHTML = "\u2715";
|
|
3550
|
+
closeBtn.style.border = "none";
|
|
3551
|
+
closeBtn.style.background = "transparent";
|
|
3552
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
3553
|
+
closeBtn.style.fontSize = "14px";
|
|
3554
|
+
closeBtn.style.cursor = "pointer";
|
|
3555
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
3556
|
+
closeBtn.style.marginLeft = "auto";
|
|
3557
|
+
closeBtn.onclick = () => {
|
|
3558
|
+
container.remove();
|
|
3559
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3560
|
+
};
|
|
3561
|
+
box.appendChild(closeBtn);
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
container.appendChild(box);
|
|
3565
|
+
const target = document.body || document.documentElement;
|
|
3566
|
+
if (banner.position?.includes("bottom")) {
|
|
3567
|
+
target.appendChild(container);
|
|
3568
|
+
} else {
|
|
3569
|
+
target.insertBefore(container, target.firstChild);
|
|
3570
|
+
}
|
|
3571
|
+
return {
|
|
3572
|
+
id,
|
|
3573
|
+
element: container,
|
|
3574
|
+
remove: () => container.remove()
|
|
3575
|
+
};
|
|
3576
|
+
} catch (err) {
|
|
3577
|
+
console.error("injectBanner error:", err);
|
|
3578
|
+
}
|
|
3579
|
+
}
|
|
3580
|
+
async function Banner(bannerId, userId) {
|
|
3581
|
+
if (!userId)
|
|
3582
|
+
return;
|
|
3583
|
+
try {
|
|
3584
|
+
const response = await fetch(`http://localhost:5000/banners2/${bannerId}`);
|
|
3585
|
+
if (!response.ok) {
|
|
3586
|
+
throw new Error("Failed to fetch banner");
|
|
3587
|
+
}
|
|
3588
|
+
const data = await response.json();
|
|
3589
|
+
if (data && data.banner && data.banner.user_data && data.banner.user_data[userId] && data.banner.user_data[userId].is_completed) {
|
|
3590
|
+
return;
|
|
3591
|
+
}
|
|
3592
|
+
var bannerFromBackend = null;
|
|
3593
|
+
bannerFromBackend = data.banner;
|
|
3594
|
+
if (!bannerFromBackend.publish)
|
|
3595
|
+
return;
|
|
3596
|
+
injectBanner(bannerFromBackend, {}, userId, bannerId);
|
|
3597
|
+
console.log("Fetched banner:", bannerFromBackend);
|
|
3598
|
+
return bannerFromBackend;
|
|
3599
|
+
} catch (error) {
|
|
3600
|
+
console.error("Error fetching banner:", error);
|
|
3601
|
+
}
|
|
3602
|
+
}
|
|
3603
|
+
var banner_default = Banner;
|
|
3604
|
+
|
|
3605
|
+
// src/utils/index.js
|
|
3606
|
+
if (typeof window !== "undefined") {
|
|
3607
|
+
window.Checklist = rivia_default;
|
|
3608
|
+
window.tours = rivia_tour_default;
|
|
3609
|
+
window.Banner = banner_default;
|
|
3610
|
+
}
|
|
776
3611
|
export {
|
|
777
|
-
|
|
778
|
-
|
|
3612
|
+
banner_default as Banner,
|
|
3613
|
+
rivia_default as OnboardingPopup,
|
|
3614
|
+
rivia_tour_default as tours
|
|
779
3615
|
};
|