rivia 0.0.90 → 0.0.91
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.cjs.js +4816 -0
- package/dist/index.cjs.js.map +7 -0
- package/dist/{index.js → index.esm.js} +1 -0
- package/dist/index.esm.js.map +7 -0
- package/dist/index.iife.js +878 -0
- package/dist/index.iife.js.map +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,4816 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/utils/index.js
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Banner: () => banner_default,
|
|
24
|
+
Checklist: () => rivia_default,
|
|
25
|
+
ProductManagement: () => pm_default,
|
|
26
|
+
Tours: () => rivia_tour_default,
|
|
27
|
+
triggerEvent: () => triggerEvent
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/utils/rivia.js
|
|
32
|
+
function slugify(text) {
|
|
33
|
+
return "/" + String(text || "").trim().toLowerCase().replace(/[^a-z0-9\-_\s]/g, "").replace(/\s+/g, "-");
|
|
34
|
+
}
|
|
35
|
+
function Onboarding(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, customCSS = "", user_var, checklist_id) {
|
|
36
|
+
if (sessionStorage.getItem(`dismissedChecklist${checklist_id}`) == "true")
|
|
37
|
+
return;
|
|
38
|
+
let usrn = targetingData?.targeting_data?.usernames ?? "Not Set";
|
|
39
|
+
let inc = targetingData?.targeting_data?.inclusion ?? "Not Set";
|
|
40
|
+
const mymap = /* @__PURE__ */ new Map();
|
|
41
|
+
for (let i2 = 0; i2 < usrn.length; i2++) {
|
|
42
|
+
mymap.set(usrn[i2], true);
|
|
43
|
+
}
|
|
44
|
+
let flag = false;
|
|
45
|
+
let data = {};
|
|
46
|
+
for (let i2 = 0; i2 < sessionStorage.length; i2++) {
|
|
47
|
+
const key = sessionStorage.key(i2);
|
|
48
|
+
data[key] = sessionStorage.getItem(key);
|
|
49
|
+
let j, t = 0;
|
|
50
|
+
if (mymap.get(data[key]) == true && inc == 2) {
|
|
51
|
+
flag = true;
|
|
52
|
+
t = 1;
|
|
53
|
+
break;
|
|
54
|
+
} else if (mymap.get(data[key]) == true && inc == 1) {
|
|
55
|
+
flag = false;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (inc == 0) {
|
|
60
|
+
flag = true;
|
|
61
|
+
}
|
|
62
|
+
let completedPages = [];
|
|
63
|
+
const items = Array.isArray(checklistItems) && checklistItems.length ? checklistItems.map((it, i2) => ({
|
|
64
|
+
id: it.id || `step${i2 + 1}`,
|
|
65
|
+
title: it.heading || `Step ${i2 + 1}`,
|
|
66
|
+
description: it.body || "",
|
|
67
|
+
event_name: it.event_name || "",
|
|
68
|
+
button_name: it.button_name || "",
|
|
69
|
+
url: it.url || slugify(it.title || `step-${i2 + 1}`),
|
|
70
|
+
color: it.color || null
|
|
71
|
+
})) : [];
|
|
72
|
+
const cleanUrlItems = items.map(
|
|
73
|
+
(item) => item.url.startsWith("/") ? item.url.slice(1) : item.url
|
|
74
|
+
);
|
|
75
|
+
const defaultTheme = {
|
|
76
|
+
backgroundColor: "#ffffff",
|
|
77
|
+
lowerBackgroundColor: "#ffffff",
|
|
78
|
+
closeBackgroundColor: "#d9534f",
|
|
79
|
+
textColor: "#000000",
|
|
80
|
+
progressBg: "#a0afa2",
|
|
81
|
+
progressFill: "#01a016",
|
|
82
|
+
subtitleColor: "#666666",
|
|
83
|
+
fontFamily: "Arial, sans-serif",
|
|
84
|
+
fontSize: "14px",
|
|
85
|
+
title: "AI Caller",
|
|
86
|
+
subtitle: "Describe the purpose of this checklist...",
|
|
87
|
+
uncheckedBorderColor: "#d1d5db",
|
|
88
|
+
headingColor: "#111827",
|
|
89
|
+
bodyColor: "#6b7280",
|
|
90
|
+
showCloseButton: true,
|
|
91
|
+
lowerBodyColor: "#6b7280",
|
|
92
|
+
lowerHeadingColor: "#111827"
|
|
93
|
+
};
|
|
94
|
+
const cssConfig = Object.assign({}, defaultTheme, cssText || {});
|
|
95
|
+
if (!items.length) return;
|
|
96
|
+
["route-label", "show-tooltip-btn", "tooltip-close-btn"].forEach((id) => {
|
|
97
|
+
const el = document.getElementById(id);
|
|
98
|
+
if (el) el.remove();
|
|
99
|
+
});
|
|
100
|
+
const visitedPages = {};
|
|
101
|
+
items.forEach((it) => {
|
|
102
|
+
const cleanUrl = it.url.startsWith("/") ? it.url.slice(1) : it.url;
|
|
103
|
+
visitedPages[cleanUrl] = it.id;
|
|
104
|
+
if (it.event_name && it.event_name != "click") {
|
|
105
|
+
visitedPages[it.event_name] = it.id;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
let storedVisited2 = JSON.parse(
|
|
109
|
+
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
110
|
+
);
|
|
111
|
+
if (!Array.isArray(storedVisited2)) storedVisited2 = [];
|
|
112
|
+
let user_var1 = user_var;
|
|
113
|
+
if (!user_var1) {
|
|
114
|
+
user_var1 = "User_" + Math.random().toString(36).substring(2, 8);
|
|
115
|
+
sessionStorage.setItem(user_var, user_var1);
|
|
116
|
+
}
|
|
117
|
+
const backendUrl = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var1}`;
|
|
118
|
+
async function getUserProgress22() {
|
|
119
|
+
const backendUrl2 = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var1}`;
|
|
120
|
+
try {
|
|
121
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
122
|
+
if (!res.ok) console.warn(`GET failed: ${res.status}`);
|
|
123
|
+
const data2 = await res.json();
|
|
124
|
+
let userData = data2[user_var1];
|
|
125
|
+
if (Array.isArray(userData)) {
|
|
126
|
+
storedVisited2 = userData;
|
|
127
|
+
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
128
|
+
storedVisited2 = userData.completed_items;
|
|
129
|
+
} else {
|
|
130
|
+
storedVisited2 = [];
|
|
131
|
+
}
|
|
132
|
+
let path;
|
|
133
|
+
return {
|
|
134
|
+
completedPages: storedVisited2,
|
|
135
|
+
progress: storedVisited2.length,
|
|
136
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
137
|
+
start_date: userData?.start_date || "",
|
|
138
|
+
end_date: userData?.end_date || userData?.end_data || ""
|
|
139
|
+
};
|
|
140
|
+
} catch (err) {
|
|
141
|
+
console.warn(
|
|
142
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
143
|
+
err
|
|
144
|
+
);
|
|
145
|
+
const storedVisited22 = [];
|
|
146
|
+
return {
|
|
147
|
+
completedPages: [],
|
|
148
|
+
progress: 0,
|
|
149
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
150
|
+
start_date: "",
|
|
151
|
+
end_date: ""
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
storedVisited2 = sessionStorage.getItem("onboardingVisited");
|
|
156
|
+
async function getUserProgress22() {
|
|
157
|
+
const backendUrl2 = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var1}`;
|
|
158
|
+
try {
|
|
159
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
160
|
+
if (!res.ok) console.warn(`GET failed: ${res.status}`);
|
|
161
|
+
const data2 = await res.json();
|
|
162
|
+
let userData = data2[user_var1];
|
|
163
|
+
if (Array.isArray(userData)) {
|
|
164
|
+
storedVisited2 = userData;
|
|
165
|
+
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
166
|
+
storedVisited2 = userData.completed_items;
|
|
167
|
+
} else {
|
|
168
|
+
storedVisited2 = [];
|
|
169
|
+
}
|
|
170
|
+
let path;
|
|
171
|
+
return {
|
|
172
|
+
completedPages: storedVisited2,
|
|
173
|
+
progress: storedVisited2.length,
|
|
174
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
175
|
+
start_date: userData?.start_date || "",
|
|
176
|
+
end_date: userData?.end_date || userData?.end_data || ""
|
|
177
|
+
};
|
|
178
|
+
} catch (err) {
|
|
179
|
+
let uploadVisitedPagesInBackground2 = function(completed2, touched = false) {
|
|
180
|
+
let activeStepId2 = sessionStorage.getItem("activeStepId") || null;
|
|
181
|
+
let user_var22 = user_var;
|
|
182
|
+
const backendUrl22 = `https://demoapi.rivia.ai/clients/${checklist_id}`;
|
|
183
|
+
try {
|
|
184
|
+
const payload = {
|
|
185
|
+
name: user_var22,
|
|
186
|
+
completed_items: completed2,
|
|
187
|
+
touched
|
|
188
|
+
};
|
|
189
|
+
fetch(backendUrl22, {
|
|
190
|
+
method: "POST",
|
|
191
|
+
headers: { "Content-Type": "application/json" },
|
|
192
|
+
credentials: "include",
|
|
193
|
+
body: JSON.stringify(payload),
|
|
194
|
+
keepalive: true
|
|
195
|
+
}).then((res) => {
|
|
196
|
+
if (!res.ok) console.warn(`Upload failed: ${res.status}`);
|
|
197
|
+
}).catch((err2) => {
|
|
198
|
+
console.warn("\u26A0\uFE0F Background PUT upload failed:", err2);
|
|
199
|
+
});
|
|
200
|
+
} catch (err2) {
|
|
201
|
+
console.warn("\u274C Error preparing background upload:", err2);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
var uploadVisitedPagesInBackground = uploadVisitedPagesInBackground2;
|
|
205
|
+
console.warn(
|
|
206
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
207
|
+
err
|
|
208
|
+
);
|
|
209
|
+
uploadVisitedPagesInBackground2([], false);
|
|
210
|
+
return {
|
|
211
|
+
completedPages: [],
|
|
212
|
+
progress: 0,
|
|
213
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
214
|
+
start_date: "",
|
|
215
|
+
end_date: ""
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (!storedVisited2 || storedVisited2 == "[]") {
|
|
220
|
+
getUserProgress22().then((progressData) => {
|
|
221
|
+
if (storedVisited2 && storedVisited2.length >= checklistItems.length) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
sessionStorage.setItem(
|
|
225
|
+
"onboardingVisited",
|
|
226
|
+
JSON.stringify(progressData.completedPages)
|
|
227
|
+
);
|
|
228
|
+
fetchWithTimeout(
|
|
229
|
+
topTitle,
|
|
230
|
+
subtitle,
|
|
231
|
+
completion,
|
|
232
|
+
checklistItems,
|
|
233
|
+
cssText,
|
|
234
|
+
targetingData,
|
|
235
|
+
user_var,
|
|
236
|
+
checklist_id,
|
|
237
|
+
cssConfig,
|
|
238
|
+
items,
|
|
239
|
+
storedVisited2,
|
|
240
|
+
backendUrl,
|
|
241
|
+
progressData,
|
|
242
|
+
visitedPages,
|
|
243
|
+
cleanUrlItems,
|
|
244
|
+
customCSS
|
|
245
|
+
);
|
|
246
|
+
});
|
|
247
|
+
} else {
|
|
248
|
+
try {
|
|
249
|
+
storedVisited2 = storedVisited2 ? JSON.parse(storedVisited2) : [];
|
|
250
|
+
} catch (e) {
|
|
251
|
+
console.warn(
|
|
252
|
+
"Invalid onboardingVisited data, resetting cache:",
|
|
253
|
+
storedVisited2
|
|
254
|
+
);
|
|
255
|
+
storedVisited2 = [];
|
|
256
|
+
}
|
|
257
|
+
if (storedVisited2 && storedVisited2.length >= checklistItems.length) {
|
|
258
|
+
if (sessionStorage.getItem("CompletedAll") != "true") return;
|
|
259
|
+
const label = document.createElement("div");
|
|
260
|
+
label.id = "route-label";
|
|
261
|
+
label.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
262
|
+
Object.assign(label.style, {
|
|
263
|
+
position: "fixed",
|
|
264
|
+
bottom: "20px",
|
|
265
|
+
left: "20px",
|
|
266
|
+
backgroundColor: "#4CAF50",
|
|
267
|
+
color: "white",
|
|
268
|
+
padding: "10px 20px",
|
|
269
|
+
borderRadius: "10px",
|
|
270
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
271
|
+
fontSize: "16px",
|
|
272
|
+
fontWeight: "bold",
|
|
273
|
+
zIndex: 9999,
|
|
274
|
+
opacity: 0,
|
|
275
|
+
transition: "opacity 0.5s ease"
|
|
276
|
+
});
|
|
277
|
+
document.body.appendChild(label);
|
|
278
|
+
requestAnimationFrame(() => {
|
|
279
|
+
label.style.opacity = 1;
|
|
280
|
+
});
|
|
281
|
+
setTimeout(() => {
|
|
282
|
+
label.style.opacity = 0;
|
|
283
|
+
setTimeout(() => label.remove(), 500);
|
|
284
|
+
}, 3e3);
|
|
285
|
+
sessionStorage.setItem("CompletedAll", "false ");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
fetchWithTimeout(
|
|
289
|
+
topTitle,
|
|
290
|
+
subtitle,
|
|
291
|
+
completion,
|
|
292
|
+
checklistItems,
|
|
293
|
+
cssText,
|
|
294
|
+
targetingData,
|
|
295
|
+
user_var,
|
|
296
|
+
checklist_id,
|
|
297
|
+
cssConfig,
|
|
298
|
+
items,
|
|
299
|
+
storedVisited2,
|
|
300
|
+
backendUrl,
|
|
301
|
+
[],
|
|
302
|
+
visitedPages,
|
|
303
|
+
cleanUrlItems,
|
|
304
|
+
customCSS
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
async function fetchWithTimeout(topTitle = "Get Started", subtitle, completion = 0, checklistItems = [], cssText = [], targetingData = {}, user_var, checklist_id, cssConfig = {}, items = [], storedVisited2 = [], backendUrl = "", progressData = {}, visitedPages = {}, cleanUrlItems = [], custom_css = "") {
|
|
309
|
+
console.log("inside fetchWithTimeout", user_var);
|
|
310
|
+
if (!user_var)
|
|
311
|
+
return;
|
|
312
|
+
let i = 0;
|
|
313
|
+
const stepsHTML = items.map((it) => {
|
|
314
|
+
return `
|
|
315
|
+
<div id="${it.id}" class="onboard-step">
|
|
316
|
+
<div class="start-select"></div>
|
|
317
|
+
|
|
318
|
+
<div class="onboard-circle"></div>
|
|
319
|
+
|
|
320
|
+
<div class="onboard-text">
|
|
321
|
+
<strong class="onboard-title">${it.title}</strong><br />
|
|
322
|
+
<small class="onboard-desc">${it.description || ""}</small>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
${i++ < items.length - 1 ? '<hr class="onboard-divider" />' : ""}
|
|
326
|
+
`;
|
|
327
|
+
}).join("");
|
|
328
|
+
const labelHTML = `
|
|
329
|
+
<div id="checklistRoot" class="checklist-root">
|
|
330
|
+
<button id="checklistCloseBtn" class="checklist-close">×</button>
|
|
331
|
+
|
|
332
|
+
<div class="checklist-header">
|
|
333
|
+
<h3 class="checklist-title">${topTitle}</h3>
|
|
334
|
+
<p class="checklist-subtitle">${subtitle}</p>
|
|
335
|
+
|
|
336
|
+
<div class="checklist-progress">
|
|
337
|
+
<div id="progressContainer" style="display: flex; gap: 4px; width: 300px; height: 10px;"></div>
|
|
338
|
+
<span id="progressFraction" style="margin-left: 0px; font-size: 13px; color: ${cssConfig.textColor}; min-width: 20px; text-align: right;">0/0 </span>
|
|
339
|
+
|
|
340
|
+
</div>
|
|
341
|
+
|
|
342
|
+
</div>
|
|
343
|
+
|
|
344
|
+
<div class="checklist-body">
|
|
345
|
+
${stepsHTML}
|
|
346
|
+
<div style="text-align: right; margin-top: 10px; cursor: pointer; color: black; font-size: 12px;" id="dismissChecklist">Dismiss this checklist</div>
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
349
|
+
`;
|
|
350
|
+
function injectChecklistBaseCSS() {
|
|
351
|
+
if (document.getElementById("rivia-checklist-css")) return;
|
|
352
|
+
const style2 = document.createElement("style");
|
|
353
|
+
style2.id = "rivia-checklist-css";
|
|
354
|
+
style2.textContent = custom_css || `/* Root */
|
|
355
|
+
.checklist-root {
|
|
356
|
+
max-width: 500px;
|
|
357
|
+
margin: auto;
|
|
358
|
+
position: relative;
|
|
359
|
+
font-family: var(--font-family);
|
|
360
|
+
font-size: var(--font-size);
|
|
361
|
+
color: var(--text-color);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.checklist-title {
|
|
365
|
+
max-width: 500px;
|
|
366
|
+
margin: auto;
|
|
367
|
+
position: relative;
|
|
368
|
+
font-family: var(--font-family);
|
|
369
|
+
font-size: var(--font-size);
|
|
370
|
+
color: var(--text-color);
|
|
371
|
+
}
|
|
372
|
+
/* Close button */
|
|
373
|
+
.checklist-close {
|
|
374
|
+
position: absolute;
|
|
375
|
+
top: 8px;
|
|
376
|
+
right: 12px;
|
|
377
|
+
background: transparent;
|
|
378
|
+
border: none;
|
|
379
|
+
font-size: 28px;
|
|
380
|
+
cursor: pointer;
|
|
381
|
+
color: var(--text-color);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/* Header */
|
|
385
|
+
.checklist-header {
|
|
386
|
+
background: var(--header-bg);
|
|
387
|
+
padding: 16px;
|
|
388
|
+
border-radius: 8px 8px 0 0;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.checklist-subtitle {
|
|
392
|
+
margin-top: 8px;
|
|
393
|
+
color: var(--subtitle-color);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/* Progress */
|
|
397
|
+
.checklist-progress {
|
|
398
|
+
display: flex;
|
|
399
|
+
align-items: center;
|
|
400
|
+
justify-content: space-between;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.progress-fraction {
|
|
404
|
+
font-size: 13px;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/* Body */
|
|
408
|
+
.checklist-body {
|
|
409
|
+
height:380px;
|
|
410
|
+
width:400px;
|
|
411
|
+
padding: 16px;
|
|
412
|
+
background: var(--lower-bg);
|
|
413
|
+
max-height: 420px;
|
|
414
|
+
overflow: auto;
|
|
415
|
+
border-radius: 0 0 8px 8px;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* Steps */
|
|
419
|
+
.onboard-step {
|
|
420
|
+
position: relative;
|
|
421
|
+
display: flex;
|
|
422
|
+
align-items: flex-start;
|
|
423
|
+
cursor: pointer;
|
|
424
|
+
padding: 8px;
|
|
425
|
+
border-radius: 6px;
|
|
426
|
+
background: var(--step-bg);
|
|
427
|
+
margin-bottom: 2px;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.start-select {
|
|
431
|
+
position: absolute;
|
|
432
|
+
top: 0;
|
|
433
|
+
left: -18px;
|
|
434
|
+
width: 10px;
|
|
435
|
+
height: 120%;
|
|
436
|
+
background: rgba(247,143,7,0.9);
|
|
437
|
+
border-radius: 4px 0 0 4px;
|
|
438
|
+
display: none;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.onboard-circle {
|
|
442
|
+
width: 16px;
|
|
443
|
+
height: 16px;
|
|
444
|
+
min-width: 16px;
|
|
445
|
+
min-height: 16px;
|
|
446
|
+
border-radius: 50%;
|
|
447
|
+
border: 2px solid var(--checkbox-color, #f78f07);
|
|
448
|
+
background: transparent;
|
|
449
|
+
margin-right: 10px;
|
|
450
|
+
box-sizing: border-box;
|
|
451
|
+
display: block;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.onboard-title {
|
|
455
|
+
color: var(--heading-color);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.onboard-desc {
|
|
459
|
+
color: var(--body-color);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.onboard-divider {
|
|
463
|
+
border: none;
|
|
464
|
+
border-top: 1px solid #9d9d9d;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.rivia-launcher {
|
|
468
|
+
position: fixed;
|
|
469
|
+
display: block;
|
|
470
|
+
z-index: 9999;
|
|
471
|
+
cursor: pointer;
|
|
472
|
+
border: none;
|
|
473
|
+
box-shadow: 0 2px 8px rgba(19, 20, 19, 0.2);
|
|
474
|
+
background: var(--launcher-bg);
|
|
475
|
+
color: var(--launcher-text);
|
|
476
|
+
font-weight: bold;
|
|
477
|
+
border-radius: 20px;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.rivia-launcher .launcher-root {
|
|
481
|
+
display: flex;
|
|
482
|
+
align-items: center;
|
|
483
|
+
width: 100%;
|
|
484
|
+
height: 100%;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.rivia-launcher .launcher-left {
|
|
488
|
+
flex: 1;
|
|
489
|
+
display: flex;
|
|
490
|
+
flex-direction: column;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.rivia-launcher .launcher-title {
|
|
494
|
+
transform: translateY(-20%);
|
|
495
|
+
position: relative;
|
|
496
|
+
margin: 0;
|
|
497
|
+
line-height: 1;
|
|
498
|
+
text-align: center;
|
|
499
|
+
padding-left: 28px;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.rivia-launcher .launcher-icon {
|
|
503
|
+
position: absolute;
|
|
504
|
+
left: 10px;
|
|
505
|
+
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.rivia-launcher .launcher-text { font-size:var(--font-size);
|
|
509
|
+
display: block;
|
|
510
|
+
width: 100%;
|
|
511
|
+
padding-left: 5%;
|
|
512
|
+
text-align: center;
|
|
513
|
+
pointer-events: none;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.rivia-launcher .launcher-progress-wrap {
|
|
517
|
+
margin-top: 4px;
|
|
518
|
+
padding-left: 32px;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/* Text adjustment when progress bar is hidden */
|
|
522
|
+
.rivia-launcher.no-progress .launcher-text {
|
|
523
|
+
transform: translateY(50%);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.rivia-launcher .launcher-progress {
|
|
527
|
+
display: flex;
|
|
528
|
+
gap: 4px;
|
|
529
|
+
width: 100%;
|
|
530
|
+
padding: 5px;
|
|
531
|
+
height: 6px;
|
|
532
|
+
box-sizing: border-box;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
.rivia-launcher .launcher-right {
|
|
536
|
+
flex-shrink: 0;
|
|
537
|
+
padding-right: 8px;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.rivia-launcher .launcher-fraction {
|
|
541
|
+
font-size: 13px;
|
|
542
|
+
white-space: nowrap;
|
|
543
|
+
}`;
|
|
544
|
+
document.head.appendChild(style2);
|
|
545
|
+
console.log("inside injectChecklistBaseCSS");
|
|
546
|
+
}
|
|
547
|
+
let label = document.getElementById("route-label");
|
|
548
|
+
if (!label) {
|
|
549
|
+
label = document.createElement("div");
|
|
550
|
+
label.id = "route-label";
|
|
551
|
+
label.innerHTML = labelHTML;
|
|
552
|
+
}
|
|
553
|
+
const closeElement = label.querySelector(`#checklistCloseBtn`);
|
|
554
|
+
closeElement.addEventListener("click", (e) => {
|
|
555
|
+
e.stopPropagation();
|
|
556
|
+
label.style.opacity = "0";
|
|
557
|
+
label.style.pointerEvents = "none";
|
|
558
|
+
sessionStorage.setItem("onboardingVisible", "false");
|
|
559
|
+
closeBtn.style.display = "none";
|
|
560
|
+
showBtn.style.display = "block";
|
|
561
|
+
});
|
|
562
|
+
const dismissElement = label.querySelector(`#dismissChecklist`);
|
|
563
|
+
dismissElement.addEventListener("click", (e) => {
|
|
564
|
+
label.style.display = "none";
|
|
565
|
+
e.stopPropagation();
|
|
566
|
+
const confirmDiv = document.createElement("div");
|
|
567
|
+
confirmDiv.innerHTML = `
|
|
568
|
+
<div style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 10000; display: flex; align-items: flex-end; justify-content: flex-start;">
|
|
569
|
+
<div style="background: white;width: 250px; border-radius: 10px; text-align: center; margin: 20px;">
|
|
570
|
+
<p style="padding: 15px;">Are you sure you want to dismiss this checklist?</p>
|
|
571
|
+
<hr class="confirmHR1293" id="confirmHR947" style="
|
|
572
|
+
all: unset !important;
|
|
573
|
+
display: block !important;
|
|
574
|
+
box-sizing: border-box !important;
|
|
575
|
+
border-top: 2px solid #f33f27 !important;
|
|
576
|
+
margin: 0 10px !important;
|
|
577
|
+
height: 0 !important;">
|
|
578
|
+
<button id="confirmYes" style="margin: 10px; padding: 4px 8px;color: #f33f27ff; border: none; cursor: pointer;">Yes</button>
|
|
579
|
+
<span style="border-left: 2px solid #f33f27ff;color:#eda600ff; height: 52px; margin: 0 10px; display: inline-block; vertical-align: top;"></span>
|
|
580
|
+
<button id="confirmNo" style="margin: 10px; padding: 4px 8px; color: #f33f27ff; border: none; cursor: pointer;">No</button>
|
|
581
|
+
</div>
|
|
582
|
+
</div>
|
|
583
|
+
`;
|
|
584
|
+
document.body.appendChild(confirmDiv);
|
|
585
|
+
const yesBtn = confirmDiv.querySelector("#confirmYes");
|
|
586
|
+
const noBtn = confirmDiv.querySelector("#confirmNo");
|
|
587
|
+
yesBtn.addEventListener("click", () => {
|
|
588
|
+
label.style.display = "none";
|
|
589
|
+
label.style.pointerEvents = "none";
|
|
590
|
+
closeBtn.style.display = "none";
|
|
591
|
+
showBtn.style.display = "none";
|
|
592
|
+
sessionStorage.setItem(`dismissedChecklist${checklist_id}`, "true");
|
|
593
|
+
document.body.removeChild(confirmDiv);
|
|
594
|
+
});
|
|
595
|
+
noBtn.addEventListener("click", () => {
|
|
596
|
+
document.body.removeChild(confirmDiv);
|
|
597
|
+
showBtn.style.display = "block";
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
function createSlabs(n) {
|
|
601
|
+
const container = label.querySelector("#progressContainer");
|
|
602
|
+
if (!container) return;
|
|
603
|
+
container.innerHTML = "";
|
|
604
|
+
for (let i2 = 0; i2 < n; i2++) {
|
|
605
|
+
const slab = document.createElement("div");
|
|
606
|
+
slab.className = "slab";
|
|
607
|
+
container.appendChild(slab);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
const style = document.createElement("style");
|
|
611
|
+
style.textContent = `
|
|
612
|
+
.slab {
|
|
613
|
+
flex: 1 0 0%; /* \u{1F512} important */
|
|
614
|
+
min-width: 5px;
|
|
615
|
+
height: 8px;
|
|
616
|
+
background-color: #ccc;
|
|
617
|
+
border-radius: 4px;
|
|
618
|
+
transition: background-color 0.3s ease;
|
|
619
|
+
}
|
|
620
|
+
.slab.active {
|
|
621
|
+
background-color: #4caf50;
|
|
622
|
+
}
|
|
623
|
+
#progressContainerBtn .slab {
|
|
624
|
+
height: 5px;
|
|
625
|
+
}
|
|
626
|
+
`;
|
|
627
|
+
label.appendChild(style);
|
|
628
|
+
function updateProgress(completed) {
|
|
629
|
+
const slabs = label.querySelectorAll(".slab");
|
|
630
|
+
slabs.forEach((slab, index) => {
|
|
631
|
+
slab.classList.toggle("active", index < completed);
|
|
632
|
+
});
|
|
633
|
+
const fraction = label.querySelector("#progressFraction");
|
|
634
|
+
if (fraction) {
|
|
635
|
+
fraction.textContent = `${completed}/${slabs.length}`;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
createSlabs(items.length);
|
|
639
|
+
if (storedVisited2) updateProgress(storedVisited2.length);
|
|
640
|
+
Object.assign(label.style, {
|
|
641
|
+
position: "fixed",
|
|
642
|
+
bottom: "80px",
|
|
643
|
+
left: "20px",
|
|
644
|
+
backgroundColor: cssConfig.backgroundColor,
|
|
645
|
+
color: cssConfig.textColor,
|
|
646
|
+
padding: "0px",
|
|
647
|
+
borderRadius: "10px",
|
|
648
|
+
zIndex: 9999,
|
|
649
|
+
fontSize: cssConfig.fontSize,
|
|
650
|
+
fontFamily: cssConfig.fontFamily,
|
|
651
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.2)",
|
|
652
|
+
width: "400px",
|
|
653
|
+
maxWidth: "400px",
|
|
654
|
+
maxHeight: "500px",
|
|
655
|
+
lineHeight: "1.5",
|
|
656
|
+
transition: "opacity 0.5s ease-in-out, transform 0.2s",
|
|
657
|
+
opacity: "0",
|
|
658
|
+
cursor: "pointer",
|
|
659
|
+
textAlign: "left",
|
|
660
|
+
display: "none",
|
|
661
|
+
pointerEvents: "none"
|
|
662
|
+
});
|
|
663
|
+
let showBtn = document.getElementById("show-tooltip-btn");
|
|
664
|
+
if (!showBtn) {
|
|
665
|
+
showBtn = document.createElement("button");
|
|
666
|
+
showBtn.id = "show-tooltip-btn";
|
|
667
|
+
}
|
|
668
|
+
function createS(n) {
|
|
669
|
+
const container2 = showBtn.querySelector("#progressContainerBtn");
|
|
670
|
+
if (!container2) return;
|
|
671
|
+
container2.innerHTML = "";
|
|
672
|
+
for (let i2 = 0; i2 < n; i2++) {
|
|
673
|
+
const slab2 = document.createElement("div");
|
|
674
|
+
slab2.classList.add("slab");
|
|
675
|
+
container2.appendChild(slab2);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
function updateProgress2(completed) {
|
|
679
|
+
const slab2 = showBtn.querySelectorAll("#progressContainerBtn .slab");
|
|
680
|
+
slab2.forEach((slab, index) => {
|
|
681
|
+
if (index < completed) {
|
|
682
|
+
slab.classList.add("active");
|
|
683
|
+
} else {
|
|
684
|
+
slab.classList.remove("active");
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
showBtn.id = "show-tooltip-btn";
|
|
689
|
+
showBtn.className = "rivia-launcher";
|
|
690
|
+
const translateStyle = cssConfig.launcherProgressBar ? 'style="transform: translateY(10px);"' : "";
|
|
691
|
+
const isRight = cssConfig.launcherPosition === "right";
|
|
692
|
+
const iconHTML = cssConfig.launcherShowIcon ? `<svg class="launcher-icon" width="24" height="24" ${translateStyle} viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
693
|
+
<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"/>
|
|
694
|
+
<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"/>
|
|
695
|
+
<path d="M12 20L11 21M4 12L3 13" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
696
|
+
<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"/>
|
|
697
|
+
<path d="M17.94 6.05957L16.5 7.49957" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
|
698
|
+
</svg>` : "";
|
|
699
|
+
const textTranslateStyle = !cssConfig.launcherProgressBar ? " translateY(50%);" : "";
|
|
700
|
+
if (!cssConfig.launcherProgressBar) {
|
|
701
|
+
showBtn.classList.add("no-progress");
|
|
702
|
+
}
|
|
703
|
+
showBtn.innerHTML = `
|
|
704
|
+
<div class="launcher-root">
|
|
705
|
+
<div class="launcher-left">
|
|
706
|
+
|
|
707
|
+
<h3 class="launcher-title">
|
|
708
|
+
${iconHTML}
|
|
709
|
+
<span class="launcher-text">${cssConfig.launcher_text}</span>
|
|
710
|
+
</h3>
|
|
711
|
+
|
|
712
|
+
<div class="launcher-progress-wrap">
|
|
713
|
+
<div id="progressContainerBtn" class="launcher-progress"></div>
|
|
714
|
+
</div>
|
|
715
|
+
|
|
716
|
+
</div>
|
|
717
|
+
|
|
718
|
+
<div class="launcher-right">
|
|
719
|
+
<span id="progressFraction" class="launcher-fraction">0/0</span>
|
|
720
|
+
</div>
|
|
721
|
+
</div>
|
|
722
|
+
`;
|
|
723
|
+
function injectLauncherCSS() {
|
|
724
|
+
if (document.getElementById("rivia-launcher-css")) return;
|
|
725
|
+
const style2 = document.createElement("style");
|
|
726
|
+
style2.id = "rivia-launcher-css";
|
|
727
|
+
style2.textContent = `
|
|
728
|
+
/* Root */ .checklist-root { max-width: 500px; margin: auto; position: relative; font-family: var(--font-family); font-size: var(--font-size); color: var(--text-color); } /* Close button */ .checklist-close { position: absolute; top: 8px; right: 12px; background: transparent; border: none; font-size: 28px; cursor: pointer; color: var(--text-color); } /* Header */ .checklist-header { background: var(--header-bg); padding: 16px; border-radius: 8px 8px 0 0; } .checklist-subtitle { margin-top: 8px; color: var(--subtitle-color); } /* Progress */ .checklist-progress { display: flex; align-items: center; justify-content: space-between; } .progress-fraction { font-size: 13px; } /* Body */ .checklist-body { padding: 16px; background: var(--lower-bg); max-height: 340px; overflow: auto; border-radius: 0 0 8px 8px; } /* Steps */ .onboard-step { position: relative; display: flex; align-items: flex-start; cursor: pointer; padding: 8px; border-radius: 6px; background: var(--step-bg); margin-bottom: 16px; } .start-select { position: absolute; top: 0; left: -18px; width: 10px; height: 120%; background: rgba(247,143,7,0.9); border-radius: 4px 0 0 4px; display: none; } .onboard-circle { width: 16px; height: 16px; min-width: 16px; min-height: 16px; border-radius: 50%; border: 2px solid var(--checkbox-color, #f78f07); /* hardcoded for test */ background: transparent; margin-right: 10px; box-sizing: border-box; display: block; } .onboard-title { color: var(--heading-color); } .onboard-desc { color: var(--body-color); } .onboard-divider { border: none; border-top: 1px solid #9d9d9d; } .rivia-launcher { position: fixed; display: block; z-index: 9999; cursor: pointer; border: none; box-shadow: 0 2px 8px rgba(19, 20, 19, 0.2); background: var(--launcher-bg); color: var(--launcher-text); font-weight: bold; } .rivia-launcher .launcher-root { display: flex; align-items: center; width: 100%; height: 100%; } .rivia-launcher .launcher-left { flex: 1; display: flex; flex-direction: column; } .rivia-launcher .launcher-title { position: relative; margin: 0; line-height: 1; text-align: center; padding-left: 28px; } .rivia-launcher .launcher-icon { position: absolute; left: 10px; transform: translateY(50%); }
|
|
729
|
+
.rivia-launcher .launcher-text {font-size:var(--font-size); display: block; width: 100%; padding-left: 5%; text-align: center; pointer-events: none; }
|
|
730
|
+
.rivia-launcher .launcher-progress-wrap { margin-top: 4px; padding-left: 32px; } /* Text adjustment when progress bar is hidden */ .rivia-launcher.no-progress .launcher-text { transform: translateY(50%);font-size:var(--font-size); } .rivia-launcher .launcher-progress { display:flex; gap:4px; width:100%; padding:5px; height:3px; box-sizing:border-box; } .rivia-launcher .launcher-right { flex-shrink: 0; padding-right: 8px; } .rivia-launcher .launcher-fraction { font-size: 13px; white-space: nowrap; } /* Customer CSS */ .rivia-launcher { border-radius: 20px; } .rivia-launcher .launcher-progress { height: 6px; }
|
|
731
|
+
`;
|
|
732
|
+
document.head.appendChild(style2);
|
|
733
|
+
}
|
|
734
|
+
function applyChecklistTheme(root, cssConfig2) {
|
|
735
|
+
root.style.setProperty("--font-family", cssConfig2.fontFamily);
|
|
736
|
+
root.style.setProperty("--font-size", cssConfig2.fontSize);
|
|
737
|
+
root.style.setProperty("--text-color", cssConfig2.textColor);
|
|
738
|
+
root.style.setProperty("--subtitle-color", cssConfig2.subtitleColor);
|
|
739
|
+
root.style.setProperty("--header-bg", cssConfig2.backgroundColor);
|
|
740
|
+
root.style.setProperty("--lower-bg", cssConfig2.lowerBackgroundColor);
|
|
741
|
+
root.style.setProperty("--step-bg", cssConfig2.lowerBackgroundColor);
|
|
742
|
+
root.style.setProperty("--checkbox-color", cssConfig2.lowerCheckboxColor);
|
|
743
|
+
root.style.setProperty("--heading-color", cssConfig2.lowerHeadingColor);
|
|
744
|
+
root.style.setProperty("--body-color", cssConfig2.lowerBodyColor);
|
|
745
|
+
}
|
|
746
|
+
injectChecklistBaseCSS();
|
|
747
|
+
Object.assign(showBtn.style, {
|
|
748
|
+
bottom: cssConfig.launcherSpacingBottom || "20px",
|
|
749
|
+
left: isRight ? "auto" : cssConfig.launcherSpacingLeft || "20px",
|
|
750
|
+
right: isRight ? cssConfig.launcherSpacingRight || "20px" : "auto",
|
|
751
|
+
width: cssConfig.launcherWidth ? `${cssConfig.launcherWidth}px` : "150px",
|
|
752
|
+
height: cssConfig.launcherHeight ? `${cssConfig.launcherHeight}px` : "78px",
|
|
753
|
+
borderRadius: `${cssConfig.launcherBorderRadius || 6}px`
|
|
754
|
+
/* CSS variables */
|
|
755
|
+
});
|
|
756
|
+
showBtn.style.setProperty("--launcher-bg", cssConfig.launcherBackgroundColor || "#f78f07");
|
|
757
|
+
showBtn.style.setProperty("--launcher-text", cssConfig.launcherTextColor || "#ffffff");
|
|
758
|
+
showBtn.style.setProperty("--font-size", cssConfig.fontSize || "14px");
|
|
759
|
+
applyChecklistTheme(label, cssConfig);
|
|
760
|
+
injectChecklistBaseCSS();
|
|
761
|
+
if (!document.contains(showBtn))
|
|
762
|
+
document.body.appendChild(showBtn);
|
|
763
|
+
console.log("after applyChecklistTheme");
|
|
764
|
+
if (!document.contains(label))
|
|
765
|
+
document.body.appendChild(label);
|
|
766
|
+
if (!cssConfig.launcherProgressBar) {
|
|
767
|
+
const progressContainerBtn = document.getElementById("progressContainerBtn");
|
|
768
|
+
if (progressContainerBtn) {
|
|
769
|
+
progressContainerBtn.style.display = "none";
|
|
770
|
+
}
|
|
771
|
+
const progressFraction = document.getElementById("progressFraction");
|
|
772
|
+
if (progressFraction) {
|
|
773
|
+
progressFraction.style.display = "none";
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
createS(items.length);
|
|
777
|
+
window.updateUIFromVisited = updateUIFromVisited;
|
|
778
|
+
window.updateProgress = updateProgress;
|
|
779
|
+
window.updateProgress2 = updateProgress2;
|
|
780
|
+
window.storedVisited = storedVisited2;
|
|
781
|
+
window.uploadVisitedPagesInBackground = uploadVisitedPagesInBackground;
|
|
782
|
+
window.items = items;
|
|
783
|
+
window.label = label;
|
|
784
|
+
window.showBtn = showBtn;
|
|
785
|
+
const closeBtn = document.createElement("button");
|
|
786
|
+
closeBtn.id = "tooltip-close-btn";
|
|
787
|
+
closeBtn.innerHTML = "\u2715";
|
|
788
|
+
Object.assign(closeBtn.style, {
|
|
789
|
+
position: "fixed",
|
|
790
|
+
width: "40px",
|
|
791
|
+
height: "40px",
|
|
792
|
+
border: "none",
|
|
793
|
+
backgroundColor: cssConfig.closeBackgroundColor,
|
|
794
|
+
color: cssConfig.textColor,
|
|
795
|
+
borderRadius: "4px",
|
|
796
|
+
cursor: "pointer",
|
|
797
|
+
fontSize: "25px",
|
|
798
|
+
fontWeight: "bold",
|
|
799
|
+
display: "none",
|
|
800
|
+
alignItems: "center",
|
|
801
|
+
justifyContent: "center",
|
|
802
|
+
zIndex: 1e4
|
|
803
|
+
});
|
|
804
|
+
function positionCloseBtn() {
|
|
805
|
+
const rect = label.getBoundingClientRect();
|
|
806
|
+
closeBtn.style.left = `${Math.max(8, rect.left + rect.width / 2 - 170)}px`;
|
|
807
|
+
closeBtn.style.top = `${rect.bottom + 10}px`;
|
|
808
|
+
}
|
|
809
|
+
let check = 0;
|
|
810
|
+
console.log("before");
|
|
811
|
+
const STORAGE_KEY = "onboardingVisited";
|
|
812
|
+
const visitedSet = new Set(
|
|
813
|
+
JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "[]")
|
|
814
|
+
);
|
|
815
|
+
const processedMessages = /* @__PURE__ */ new Set();
|
|
816
|
+
function persistVisited() {
|
|
817
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify([...visitedSet]));
|
|
818
|
+
}
|
|
819
|
+
function handleVisit(cleanUrl, opts = { source: "unknown" }) {
|
|
820
|
+
if (!cleanUrl) return false;
|
|
821
|
+
if (typeof cleanUrl !== "string") return false;
|
|
822
|
+
if (!cleanUrlItems || !cleanUrlItems.includes(cleanUrl)) {
|
|
823
|
+
return false;
|
|
824
|
+
}
|
|
825
|
+
if (visitedSet.has(cleanUrl)) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
visitedSet.add(cleanUrl);
|
|
829
|
+
storedVisited2 = [...visitedSet];
|
|
830
|
+
persistVisited();
|
|
831
|
+
try {
|
|
832
|
+
uploadVisitedPagesInBackground([...visitedSet], true);
|
|
833
|
+
} catch (e) {
|
|
834
|
+
console.warn("uploadVisitedPagesInBackground failed", e);
|
|
835
|
+
}
|
|
836
|
+
updateProgress(visitedSet.size);
|
|
837
|
+
updateProgress2(visitedSet.size);
|
|
838
|
+
updateUIFromVisited();
|
|
839
|
+
console.log(`handleVisit: added ${cleanUrl} (source=${opts.source})`);
|
|
840
|
+
if (visitedSet.size >= (checklistItems ? checklistItems.length : Infinity)) {
|
|
841
|
+
sessionStorage.setItem("CompletedAll", "true");
|
|
842
|
+
}
|
|
843
|
+
return true;
|
|
844
|
+
}
|
|
845
|
+
function findButtonByText(buttonText) {
|
|
846
|
+
if (!buttonText) return null;
|
|
847
|
+
const needle = buttonText.trim().toLowerCase();
|
|
848
|
+
const buttons = document.querySelectorAll("button");
|
|
849
|
+
for (const button of buttons) {
|
|
850
|
+
if (!button.textContent) continue;
|
|
851
|
+
if (button.textContent.trim().toLowerCase().includes(needle)) {
|
|
852
|
+
return button;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return null;
|
|
856
|
+
}
|
|
857
|
+
function attachButtonForItem(it) {
|
|
858
|
+
const btn = findButtonByText(it.button_name);
|
|
859
|
+
if (!btn) {
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
if (btn._onboardingAttached) return;
|
|
863
|
+
btn._onboardingAttached = true;
|
|
864
|
+
btn.addEventListener("click", (e) => {
|
|
865
|
+
check = 1;
|
|
866
|
+
const path = it.url || "";
|
|
867
|
+
const cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
868
|
+
if (storedVisited2.length >= checklistItems.length) {
|
|
869
|
+
(() => {
|
|
870
|
+
if (label2 && label2.parentNode) label2.remove();
|
|
871
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
872
|
+
const label2 = document.createElement("div");
|
|
873
|
+
label2.id = "route-label";
|
|
874
|
+
label2.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
875
|
+
Object.assign(label2.style, {
|
|
876
|
+
position: "fixed",
|
|
877
|
+
bottom: "20px",
|
|
878
|
+
left: "20px",
|
|
879
|
+
backgroundColor: "#4CAF50",
|
|
880
|
+
color: "white",
|
|
881
|
+
padding: "10px 20px",
|
|
882
|
+
borderRadius: "10px",
|
|
883
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
884
|
+
fontSize: "16px",
|
|
885
|
+
fontWeight: "bold",
|
|
886
|
+
zIndex: 9999,
|
|
887
|
+
opacity: 0,
|
|
888
|
+
transition: "opacity 0.5s ease"
|
|
889
|
+
});
|
|
890
|
+
document.body.appendChild(label2);
|
|
891
|
+
})();
|
|
892
|
+
}
|
|
893
|
+
handleVisit(cleanUrl, { source: "click" });
|
|
894
|
+
if (storedVisited2.length >= checklistItems.length) {
|
|
895
|
+
(() => {
|
|
896
|
+
if (label && label.parentNode) label.remove();
|
|
897
|
+
if (showBtn && showBtn.parentNode) showBtn.remove();
|
|
898
|
+
const label3 = document.createElement("div");
|
|
899
|
+
label3.id = "route-label";
|
|
900
|
+
label3.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
901
|
+
Object.assign(label3.style, {
|
|
902
|
+
position: "fixed",
|
|
903
|
+
bottom: "20px",
|
|
904
|
+
left: "20px",
|
|
905
|
+
backgroundColor: "#4CAF50",
|
|
906
|
+
color: "white",
|
|
907
|
+
padding: "10px 20px",
|
|
908
|
+
borderRadius: "10px",
|
|
909
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
910
|
+
fontSize: "16px",
|
|
911
|
+
fontWeight: "bold",
|
|
912
|
+
zIndex: 9999,
|
|
913
|
+
opacity: 0,
|
|
914
|
+
transition: "opacity 0.5s ease"
|
|
915
|
+
});
|
|
916
|
+
document.body.appendChild(label3);
|
|
917
|
+
})();
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
items.forEach(attachButtonForItem);
|
|
922
|
+
const mo = new MutationObserver((mutations) => {
|
|
923
|
+
items.forEach(attachButtonForItem);
|
|
924
|
+
});
|
|
925
|
+
mo.observe(document.body, { childList: true, subtree: true });
|
|
926
|
+
window.addEventListener("storage", (e) => {
|
|
927
|
+
if (e.key === STORAGE_KEY) {
|
|
928
|
+
const arr = JSON.parse(sessionStorage.getItem(STORAGE_KEY) || "[]");
|
|
929
|
+
visitedSet.clear();
|
|
930
|
+
arr.forEach((a) => visitedSet.add(a));
|
|
931
|
+
updateUIFromVisited();
|
|
932
|
+
updateProgress(visitedSet.size);
|
|
933
|
+
updateProgress2(visitedSet.size);
|
|
934
|
+
}
|
|
935
|
+
});
|
|
936
|
+
let user_var2 = user_var;
|
|
937
|
+
function uploadVisitedPagesInBackground(completed2, touched = false) {
|
|
938
|
+
let activeStepId2 = sessionStorage.getItem("activeStepId") || null;
|
|
939
|
+
let user_var22 = user_var;
|
|
940
|
+
const backendUrl22 = `https://demoapi.rivia.ai/clients/${checklist_id}`;
|
|
941
|
+
try {
|
|
942
|
+
const payload = {
|
|
943
|
+
name: user_var22,
|
|
944
|
+
completed_items: completed2,
|
|
945
|
+
touched
|
|
946
|
+
};
|
|
947
|
+
fetch(backendUrl22, {
|
|
948
|
+
method: "POST",
|
|
949
|
+
headers: { "Content-Type": "application/json" },
|
|
950
|
+
credentials: "include",
|
|
951
|
+
body: JSON.stringify(payload),
|
|
952
|
+
keepalive: true
|
|
953
|
+
}).then((res) => {
|
|
954
|
+
if (!res.ok) console.warn(`Upload failed: ${res.status}`);
|
|
955
|
+
}).catch((err) => {
|
|
956
|
+
console.warn("\u26A0\uFE0F Background PUT upload failed:", err);
|
|
957
|
+
});
|
|
958
|
+
} catch (err) {
|
|
959
|
+
console.warn("\u274C Error preparing background upload:", err);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
let activeStepId = sessionStorage.getItem("activeStepId") || null;
|
|
963
|
+
function updateUIFromVisited() {
|
|
964
|
+
storedVisited2 = JSON.parse(
|
|
965
|
+
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
966
|
+
);
|
|
967
|
+
let path;
|
|
968
|
+
storedVisited2 = sessionStorage.getItem("onboardingVisited");
|
|
969
|
+
if (!storedVisited2 || storedVisited2 == "[]") {
|
|
970
|
+
async function getUserProgress22() {
|
|
971
|
+
const backendUrl2 = `https://demoapi.rivia.ai/clients/${checklist_id}/${user_var}`;
|
|
972
|
+
try {
|
|
973
|
+
const res = await fetch(backendUrl2, { credentials: "include" });
|
|
974
|
+
if (!res.ok) console.warn(`GET failed: ${res.status}`);
|
|
975
|
+
const data2 = await res.json();
|
|
976
|
+
let userData = data2[user_var];
|
|
977
|
+
if (Array.isArray(userData)) {
|
|
978
|
+
storedVisited2 = userData;
|
|
979
|
+
} else if (typeof userData === "object" && userData !== null && Array.isArray(userData.completed_items)) {
|
|
980
|
+
storedVisited2 = userData.completed_items;
|
|
981
|
+
} else {
|
|
982
|
+
storedVisited2 = [];
|
|
983
|
+
}
|
|
984
|
+
let path2;
|
|
985
|
+
return {
|
|
986
|
+
completedPages: storedVisited2,
|
|
987
|
+
progress: storedVisited2.length,
|
|
988
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
989
|
+
start_date: userData?.start_date || "",
|
|
990
|
+
end_date: userData?.end_date || userData?.end_data || ""
|
|
991
|
+
};
|
|
992
|
+
} catch (err) {
|
|
993
|
+
console.warn(
|
|
994
|
+
"\u26A0\uFE0F Invalid checklist Id",
|
|
995
|
+
err
|
|
996
|
+
);
|
|
997
|
+
uploadVisitedPagesInBackground([], false);
|
|
998
|
+
const storedVisited22 = [];
|
|
999
|
+
return {
|
|
1000
|
+
completedPages: [],
|
|
1001
|
+
progress: 0,
|
|
1002
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1003
|
+
start_date: "",
|
|
1004
|
+
end_date: ""
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
getUserProgress22().then((progressData2) => {
|
|
1009
|
+
let completed2 = progressData2.completedPages;
|
|
1010
|
+
completed2.forEach((path2) => {
|
|
1011
|
+
const stepId = visitedPages[path2];
|
|
1012
|
+
const stepElement = label.querySelector(`#${stepId}`);
|
|
1013
|
+
if (!stepElement) return;
|
|
1014
|
+
const circle = stepElement.querySelector(".onboard-circle");
|
|
1015
|
+
if (circle) {
|
|
1016
|
+
circle.innerHTML = `
|
|
1017
|
+
<div style="background-color: green; border-radius: 50%; width: 30px; height: 18px; display: flex; align-items: center; justify-content: center;">
|
|
1018
|
+
<svg width="16" height="16" viewBox="0 0 512 512" fill="white" xmlns="http://www.w3.org/2000/svg">
|
|
1019
|
+
<path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206
|
|
1020
|
+
0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
|
|
1021
|
+
36.204 0L192 312.69 432.095 72.596c9.997-9.997
|
|
1022
|
+
26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
|
|
1023
|
+
9.997 26.206 0 36.204l-294.4 294.401c-9.998
|
|
1024
|
+
9.997-26.207 9.997-36.204-.001z"/>
|
|
1025
|
+
</svg>
|
|
1026
|
+
</div>
|
|
1027
|
+
`;
|
|
1028
|
+
circle.style.border = "none";
|
|
1029
|
+
circle.style.backgroundColor = "transparent";
|
|
1030
|
+
circle.style.display = "flex";
|
|
1031
|
+
circle.style.alignItems = "center";
|
|
1032
|
+
circle.style.justifyContent = "center";
|
|
1033
|
+
circle.style.padding = "1px";
|
|
1034
|
+
}
|
|
1035
|
+
const textContainer = stepElement.querySelector(".onboard-text");
|
|
1036
|
+
const startSelect = stepElement.querySelector(".start-select");
|
|
1037
|
+
if (stepId === activeStepId && startSelect) {
|
|
1038
|
+
startSelect.style.display = "block";
|
|
1039
|
+
}
|
|
1040
|
+
if (textContainer) {
|
|
1041
|
+
textContainer.style.textDecoration = "line-through";
|
|
1042
|
+
textContainer.style.opacity = "0.6";
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
const progress2 = Math.min(
|
|
1046
|
+
100,
|
|
1047
|
+
Math.round(completed2.length / items.length * 100)
|
|
1048
|
+
);
|
|
1049
|
+
const percentText2 = `${progress2}%`;
|
|
1050
|
+
const labelPercent2 = label.querySelector("#progressFraction");
|
|
1051
|
+
const btnPercent2 = showBtn.querySelector("#progressFraction");
|
|
1052
|
+
if (labelPercent2) labelPercent2.textContent = percentText2;
|
|
1053
|
+
if (btnPercent2) btnPercent2.textContent = percentText2;
|
|
1054
|
+
const progressFraction2 = label.querySelector("#progressFraction");
|
|
1055
|
+
if (progressFraction2) {
|
|
1056
|
+
progressFraction2.textContent = `${completed2.length}/${items.length}`;
|
|
1057
|
+
}
|
|
1058
|
+
const btnFraction2 = showBtn.querySelector("#progressFraction");
|
|
1059
|
+
if (btnFraction2) {
|
|
1060
|
+
btnFraction2.textContent = `${completed2.length}/${items.length}`;
|
|
1061
|
+
}
|
|
1062
|
+
storedVisited2 = completed2;
|
|
1063
|
+
updateProgress(completed2.length);
|
|
1064
|
+
updateProgress2(completed2.length);
|
|
1065
|
+
});
|
|
1066
|
+
} else {
|
|
1067
|
+
let completed2 = storedVisited2;
|
|
1068
|
+
if (completed2) {
|
|
1069
|
+
try {
|
|
1070
|
+
completed2 = JSON.parse(completed2);
|
|
1071
|
+
} catch (e) {
|
|
1072
|
+
console.warn("Failed to parse onboardingVisited:", e);
|
|
1073
|
+
completed2 = [];
|
|
1074
|
+
}
|
|
1075
|
+
} else {
|
|
1076
|
+
completed2 = [];
|
|
1077
|
+
}
|
|
1078
|
+
completed2.forEach((path2) => {
|
|
1079
|
+
let activeStepId2 = sessionStorage.getItem("activeStepId") || null;
|
|
1080
|
+
const stepId = visitedPages[path2];
|
|
1081
|
+
const stepElement = label.querySelector(`#${stepId}`);
|
|
1082
|
+
if (!stepElement) return;
|
|
1083
|
+
const circle = stepElement.querySelector(".onboard-circle");
|
|
1084
|
+
if (circle) {
|
|
1085
|
+
circle.innerHTML = `
|
|
1086
|
+
<div style="background-color: green; border-radius: 50%; width: 30px; height: 18px; display: flex; align-items: center; justify-content: center;">
|
|
1087
|
+
<svg width="16" height="16" viewBox="0 0 512 512" fill="white" xmlns="http://www.w3.org/2000/svg">
|
|
1088
|
+
<path d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206
|
|
1089
|
+
0-36.204l36.203-36.204c9.997-9.998 26.207-9.998
|
|
1090
|
+
36.204 0L192 312.69 432.095 72.596c9.997-9.997
|
|
1091
|
+
26.207-9.997 36.204 0l36.203 36.204c9.997 9.997
|
|
1092
|
+
9.997 26.206 0 36.204l-294.4 294.401c-9.998
|
|
1093
|
+
9.997-26.207 9.997-36.204-.001z"/>
|
|
1094
|
+
</svg>
|
|
1095
|
+
</div>
|
|
1096
|
+
`;
|
|
1097
|
+
circle.style.border = "none";
|
|
1098
|
+
circle.style.backgroundColor = "transparent";
|
|
1099
|
+
circle.style.display = "flex";
|
|
1100
|
+
circle.style.alignItems = "center";
|
|
1101
|
+
circle.style.justifyContent = "center";
|
|
1102
|
+
circle.style.padding = "1px";
|
|
1103
|
+
}
|
|
1104
|
+
const textContainer = stepElement.querySelector(".onboard-text");
|
|
1105
|
+
const startSelect = stepElement.querySelector(".start-select");
|
|
1106
|
+
if (stepId === activeStepId2 && startSelect) {
|
|
1107
|
+
startSelect.style.display = "block";
|
|
1108
|
+
}
|
|
1109
|
+
if (textContainer) {
|
|
1110
|
+
textContainer.style.textDecoration = "line-through";
|
|
1111
|
+
textContainer.style.opacity = "0.6";
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
const progress2 = Math.min(
|
|
1115
|
+
100,
|
|
1116
|
+
Math.round(completed2.length / items.length * 100)
|
|
1117
|
+
);
|
|
1118
|
+
const percentText2 = `${progress2}%`;
|
|
1119
|
+
const labelPercent2 = label.querySelector("#progressFraction");
|
|
1120
|
+
const btnPercent2 = showBtn.querySelector("#progressFraction");
|
|
1121
|
+
if (labelPercent2) labelPercent2.textContent = percentText2;
|
|
1122
|
+
if (btnPercent2) btnPercent2.textContent = percentText2;
|
|
1123
|
+
const progressFraction2 = label.querySelector("#progressFraction");
|
|
1124
|
+
if (progressFraction2) {
|
|
1125
|
+
progressFraction2.textContent = `${completed2.length}/${items.length}`;
|
|
1126
|
+
}
|
|
1127
|
+
const btnFraction2 = showBtn.querySelector("#progressFraction");
|
|
1128
|
+
if (btnFraction2) {
|
|
1129
|
+
btnFraction2.textContent = `${completed2.length}/${items.length} `;
|
|
1130
|
+
}
|
|
1131
|
+
storedVisited2 = completed2;
|
|
1132
|
+
updateProgress(completed2.length);
|
|
1133
|
+
updateProgress2(completed2.length);
|
|
1134
|
+
}
|
|
1135
|
+
let completed = storedVisited2;
|
|
1136
|
+
}
|
|
1137
|
+
if (completion == 0) {
|
|
1138
|
+
items.forEach((it) => {
|
|
1139
|
+
const stepEl = label.querySelector(`#${it.id}`);
|
|
1140
|
+
if (!stepEl) return;
|
|
1141
|
+
const startSelect = stepEl.querySelector(".start-select");
|
|
1142
|
+
startSelect.style.display = "none";
|
|
1143
|
+
stepEl.addEventListener("click", () => {
|
|
1144
|
+
if (it.event_name == "click" && it.button_name == "") {
|
|
1145
|
+
items.forEach((inner) => {
|
|
1146
|
+
const el = label.querySelector(`#${inner.id}`);
|
|
1147
|
+
if (el) {
|
|
1148
|
+
const sel = el.querySelector(".start-select");
|
|
1149
|
+
if (sel) sel.style.display = "none";
|
|
1150
|
+
}
|
|
1151
|
+
});
|
|
1152
|
+
startSelect.style.display = "block";
|
|
1153
|
+
activeStepId = it.id;
|
|
1154
|
+
sessionStorage.setItem("activeStepId", activeStepId);
|
|
1155
|
+
storedVisited2 = JSON.parse(
|
|
1156
|
+
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
1157
|
+
);
|
|
1158
|
+
if (!storedVisited2 || storedVisited2 == "[]") {
|
|
1159
|
+
getUserProgress2().then((progressData2) => {
|
|
1160
|
+
sessionStorage.setItem(
|
|
1161
|
+
"onboardingVisited",
|
|
1162
|
+
JSON.stringify(progressData2.completedPages)
|
|
1163
|
+
);
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
storedVisited2 = JSON.parse(
|
|
1167
|
+
sessionStorage.getItem("onboardingVisited") || "[]"
|
|
1168
|
+
);
|
|
1169
|
+
let path = it.url;
|
|
1170
|
+
let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
1171
|
+
if (!storedVisited2.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
|
|
1172
|
+
storedVisited2.push(cleanUrl);
|
|
1173
|
+
sessionStorage.setItem(
|
|
1174
|
+
"onboardingVisited",
|
|
1175
|
+
JSON.stringify(storedVisited2)
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
if (storedVisited2.length >= checklistItems.length) {
|
|
1179
|
+
sessionStorage.setItem("CompletedAll", "true");
|
|
1180
|
+
}
|
|
1181
|
+
uploadVisitedPagesInBackground(storedVisited2, true);
|
|
1182
|
+
updateProgress(storedVisited2.length);
|
|
1183
|
+
updateProgress2(storedVisited2.length);
|
|
1184
|
+
updateUIFromVisited();
|
|
1185
|
+
if (storedVisited2.length >= checklistItems.length) {
|
|
1186
|
+
sessionStorage.setItem("CompletedAll", "true");
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
window.location.href = it.url;
|
|
1190
|
+
});
|
|
1191
|
+
});
|
|
1192
|
+
} else {
|
|
1193
|
+
if (!sessionStorage.getItem("c")) sessionStorage.setItem("c", 1);
|
|
1194
|
+
let c = parseInt(sessionStorage.getItem("c") || "1");
|
|
1195
|
+
items.forEach((it, index) => {
|
|
1196
|
+
const stepEl = label.querySelector(`#${it.id}`);
|
|
1197
|
+
if (!stepEl) return;
|
|
1198
|
+
const startSelect = stepEl.querySelector(".start-select");
|
|
1199
|
+
startSelect.style.display = "none";
|
|
1200
|
+
stepEl.addEventListener("click", () => {
|
|
1201
|
+
if (index < c) {
|
|
1202
|
+
alert("You have already completed this step!");
|
|
1203
|
+
c--;
|
|
1204
|
+
}
|
|
1205
|
+
if (index != c) {
|
|
1206
|
+
alert("Please complete the previous steps first!");
|
|
1207
|
+
return;
|
|
1208
|
+
}
|
|
1209
|
+
sessionStorage.setItem("c", c + 1);
|
|
1210
|
+
items.forEach((inner) => {
|
|
1211
|
+
const el = label.querySelector(`#${inner.id}`);
|
|
1212
|
+
if (el) {
|
|
1213
|
+
const sel = el.querySelector(".start-select");
|
|
1214
|
+
if (sel) sel.style.display = "none";
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
startSelect.style.display = "block";
|
|
1218
|
+
activeStepId = it.id;
|
|
1219
|
+
sessionStorage.setItem("activeStepId", activeStepId);
|
|
1220
|
+
let path = it.url;
|
|
1221
|
+
let cleanUrl = path.startsWith("/") ? path.slice(1) : path;
|
|
1222
|
+
if (!storedVisited2.includes(cleanUrl) && cleanUrlItems.includes(cleanUrl)) {
|
|
1223
|
+
storedVisited2.push(cleanUrl);
|
|
1224
|
+
sessionStorage.setItem(
|
|
1225
|
+
"onboardingVisited",
|
|
1226
|
+
JSON.stringify(storedVisited2)
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1229
|
+
uploadVisitedPagesInBackground(storedVisited2, true);
|
|
1230
|
+
updateProgress(storedVisited2.length);
|
|
1231
|
+
updateProgress2(storedVisited2.length);
|
|
1232
|
+
updateUIFromVisited();
|
|
1233
|
+
if (storedVisited2.length >= checklistItems.length) {
|
|
1234
|
+
sessionStorage.setItem("CompletedAll", "true");
|
|
1235
|
+
}
|
|
1236
|
+
window.location.href = it.url;
|
|
1237
|
+
});
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
showBtn.addEventListener("click", (e) => {
|
|
1241
|
+
e.stopPropagation();
|
|
1242
|
+
label.style.display = "block";
|
|
1243
|
+
label.style.pointerEvents = "auto";
|
|
1244
|
+
closeBtn.style.display = "flex";
|
|
1245
|
+
showBtn.style.display = "none";
|
|
1246
|
+
sessionStorage.setItem("onboardingVisible", "true");
|
|
1247
|
+
positionCloseBtn();
|
|
1248
|
+
requestAnimationFrame(() => {
|
|
1249
|
+
label.style.opacity = "1";
|
|
1250
|
+
});
|
|
1251
|
+
});
|
|
1252
|
+
closeBtn.addEventListener("click", (ev) => {
|
|
1253
|
+
ev.stopPropagation();
|
|
1254
|
+
label.style.opacity = "0";
|
|
1255
|
+
label.style.pointerEvents = "none";
|
|
1256
|
+
closeBtn.style.display = "none";
|
|
1257
|
+
showBtn.style.display = "block";
|
|
1258
|
+
});
|
|
1259
|
+
label.addEventListener(
|
|
1260
|
+
"mouseenter",
|
|
1261
|
+
() => label.style.transform = "scale(1.02)"
|
|
1262
|
+
);
|
|
1263
|
+
label.addEventListener(
|
|
1264
|
+
"mouseleave",
|
|
1265
|
+
() => label.style.transform = "scale(1)"
|
|
1266
|
+
);
|
|
1267
|
+
label.addEventListener("click", () => {
|
|
1268
|
+
const getStarted = document.querySelector("button#get-started");
|
|
1269
|
+
if (getStarted) getStarted.click();
|
|
1270
|
+
});
|
|
1271
|
+
if (sessionStorage.getItem("onboardingVisible") === "true") {
|
|
1272
|
+
label.style.display = "block";
|
|
1273
|
+
label.style.pointerEvents = "auto";
|
|
1274
|
+
closeBtn.style.display = "flex";
|
|
1275
|
+
showBtn.style.display = "none";
|
|
1276
|
+
sessionStorage.setItem("onboardingVisible", "true");
|
|
1277
|
+
positionCloseBtn();
|
|
1278
|
+
} else {
|
|
1279
|
+
showBtn.style.display = "block";
|
|
1280
|
+
label.style.display = "none";
|
|
1281
|
+
}
|
|
1282
|
+
label.style.opacity = "1";
|
|
1283
|
+
updateUIFromVisited();
|
|
1284
|
+
window.addEventListener("resize", () => {
|
|
1285
|
+
if (label.style.display !== "none") positionCloseBtn();
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
function evaluateRule(rule, context) {
|
|
1289
|
+
const leftValue = context[rule.name];
|
|
1290
|
+
const operator = rule.operator;
|
|
1291
|
+
const rightValue = rule.values;
|
|
1292
|
+
console.log("leftValue", leftValue);
|
|
1293
|
+
console.log("operator", operator);
|
|
1294
|
+
console.log("rightValue", rightValue);
|
|
1295
|
+
if (leftValue === void 0) return false;
|
|
1296
|
+
switch (operator) {
|
|
1297
|
+
case "in":
|
|
1298
|
+
return Array.isArray(rightValue) && rightValue.includes(leftValue);
|
|
1299
|
+
case "not_in":
|
|
1300
|
+
return Array.isArray(rightValue) && !rightValue.includes(leftValue);
|
|
1301
|
+
case "equals":
|
|
1302
|
+
return leftValue === rightValue;
|
|
1303
|
+
case "not_equals":
|
|
1304
|
+
return leftValue != rightValue;
|
|
1305
|
+
case "greater_than":
|
|
1306
|
+
if (rule.name == "sign_up_at")
|
|
1307
|
+
return new Date(leftValue).getTime() > new Date(rightValue).getTime();
|
|
1308
|
+
else
|
|
1309
|
+
return leftValue > rightValue;
|
|
1310
|
+
case "less_than":
|
|
1311
|
+
if (rule.name == "sign_up_at")
|
|
1312
|
+
return new Date(leftValue).getTime() < new Date(rightValue).getTime();
|
|
1313
|
+
else
|
|
1314
|
+
return leftValue < rightValue;
|
|
1315
|
+
case "greater_or_equals":
|
|
1316
|
+
if (rule.name == "sign_up_at")
|
|
1317
|
+
return new Date(leftValue).getTime() >= new Date(rightValue).getTime();
|
|
1318
|
+
else
|
|
1319
|
+
return leftValue >= rightValue;
|
|
1320
|
+
case "less_or_equals":
|
|
1321
|
+
if (rule.name == "sign_up_at")
|
|
1322
|
+
return new Date(leftValue).getTime() <= new Date(rightValue).getTime();
|
|
1323
|
+
else
|
|
1324
|
+
return leftValue <= rightValue;
|
|
1325
|
+
case "is_empty":
|
|
1326
|
+
if (leftValue == "")
|
|
1327
|
+
return true;
|
|
1328
|
+
else
|
|
1329
|
+
return false;
|
|
1330
|
+
case "is_not_empty":
|
|
1331
|
+
if (leftValue != "")
|
|
1332
|
+
return true;
|
|
1333
|
+
else
|
|
1334
|
+
return false;
|
|
1335
|
+
default:
|
|
1336
|
+
return false;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
function evaluateRules(rules, context) {
|
|
1340
|
+
if (!Array.isArray(rules) || rules.length === 0) return true;
|
|
1341
|
+
let finalResult = evaluateRule(rules[0], context);
|
|
1342
|
+
for (let i = 1; i < rules.length; i++) {
|
|
1343
|
+
console.log(finalResult);
|
|
1344
|
+
const previousRule = rules[i - 1];
|
|
1345
|
+
const currentResult = evaluateRule(rules[i], context);
|
|
1346
|
+
switch (previousRule.next) {
|
|
1347
|
+
case "and":
|
|
1348
|
+
finalResult = finalResult && currentResult;
|
|
1349
|
+
break;
|
|
1350
|
+
case "or":
|
|
1351
|
+
finalResult = finalResult || currentResult;
|
|
1352
|
+
break;
|
|
1353
|
+
default:
|
|
1354
|
+
finalResult = currentResult;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return finalResult;
|
|
1358
|
+
}
|
|
1359
|
+
async function Checklist(workspace_id, obj) {
|
|
1360
|
+
window.addEventListener("locationchange", async () => {
|
|
1361
|
+
window.workspace_id = workspace_id;
|
|
1362
|
+
window.userid = obj.userid;
|
|
1363
|
+
let user_var = obj.userid;
|
|
1364
|
+
window.sign_up_at = obj.sign_up_at;
|
|
1365
|
+
window.role = obj.role;
|
|
1366
|
+
window.email = obj.email;
|
|
1367
|
+
console.log("");
|
|
1368
|
+
try {
|
|
1369
|
+
let doesRouteMatch2 = function(routes) {
|
|
1370
|
+
if (!Array.isArray(routes)) return true;
|
|
1371
|
+
const currentPath2 = window.location.pathname.toLowerCase();
|
|
1372
|
+
console.log("Current Path:", currentPath2);
|
|
1373
|
+
return routes.some((route) => {
|
|
1374
|
+
if (!route) return false;
|
|
1375
|
+
let pattern;
|
|
1376
|
+
const normalizedRoute = route.toLowerCase().replace(/\/$/, "");
|
|
1377
|
+
if (normalizedRoute.includes("[dynamic]")) {
|
|
1378
|
+
const base = normalizedRoute.split("[dynamic]")[0].replace(/\/$/, "");
|
|
1379
|
+
console.log("Base:", base);
|
|
1380
|
+
pattern = new RegExp(`^${escapeRegex2(base)}(/.*)?$`);
|
|
1381
|
+
} else {
|
|
1382
|
+
pattern = new RegExp(`^${escapeRegex2(normalizedRoute)}$`);
|
|
1383
|
+
}
|
|
1384
|
+
return pattern.test(currentPath2);
|
|
1385
|
+
});
|
|
1386
|
+
}, escapeRegex2 = function(str) {
|
|
1387
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1388
|
+
}, buildContext2 = function(obj2) {
|
|
1389
|
+
return {
|
|
1390
|
+
userid: obj2.userid,
|
|
1391
|
+
role: obj2.role,
|
|
1392
|
+
sign_up_at: obj2.sign_up_at,
|
|
1393
|
+
email: obj2.email,
|
|
1394
|
+
first_name: obj2.first_name,
|
|
1395
|
+
last_name: obj2.last_name
|
|
1396
|
+
};
|
|
1397
|
+
};
|
|
1398
|
+
var doesRouteMatch = doesRouteMatch2, escapeRegex = escapeRegex2, buildContext = buildContext2;
|
|
1399
|
+
const res = await fetch(
|
|
1400
|
+
`https://demoapi.rivia.ai/checklist_by_workspace2/${workspace_id}`,
|
|
1401
|
+
{
|
|
1402
|
+
method: "GET",
|
|
1403
|
+
headers: { "Content-Type": "application/json" }
|
|
1404
|
+
}
|
|
1405
|
+
);
|
|
1406
|
+
if (!res.ok) {
|
|
1407
|
+
console.warn("\u274C Failed to fetch checklist");
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const data = await res.json();
|
|
1411
|
+
const checklists = data.checklist || [];
|
|
1412
|
+
if (!Array.isArray(checklists) || checklists.length === 0) return;
|
|
1413
|
+
const currentPath = window.location.pathname;
|
|
1414
|
+
const matchedChecklist = checklists.find((chk) => {
|
|
1415
|
+
const routes = chk?.targeting_data?.routes;
|
|
1416
|
+
if (!chk?.publish)
|
|
1417
|
+
return false;
|
|
1418
|
+
if (!chk?.targeting_data?.display)
|
|
1419
|
+
return !doesRouteMatch2(routes, currentPath);
|
|
1420
|
+
else
|
|
1421
|
+
return doesRouteMatch2(routes, currentPath);
|
|
1422
|
+
});
|
|
1423
|
+
if (!matchedChecklist) {
|
|
1424
|
+
if (window.showBtn && window.showBtn.parentNode) {
|
|
1425
|
+
window.showBtn.remove();
|
|
1426
|
+
}
|
|
1427
|
+
if (window.label && window.label.parentNode) {
|
|
1428
|
+
window.label.remove();
|
|
1429
|
+
}
|
|
1430
|
+
console.log("No checklist applicable for this route");
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
console.log("userid", obj.userid);
|
|
1434
|
+
console.log("matched ch", matchedChecklist);
|
|
1435
|
+
const rules = matchedChecklist?.targeting_data?.custom_rules || [];
|
|
1436
|
+
console.log("rules", rules);
|
|
1437
|
+
const context = buildContext2(obj);
|
|
1438
|
+
const shouldShow = evaluateRules(rules, context);
|
|
1439
|
+
if (!shouldShow) {
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
const {
|
|
1443
|
+
checklist_id,
|
|
1444
|
+
title = "Untitled Checklist",
|
|
1445
|
+
subtitle = "Describe the purpose of this checklist...",
|
|
1446
|
+
items = [],
|
|
1447
|
+
completion = 0,
|
|
1448
|
+
branding_data: cssConfig = {},
|
|
1449
|
+
targeting_data: targetingData = {},
|
|
1450
|
+
customCSS = ""
|
|
1451
|
+
} = matchedChecklist;
|
|
1452
|
+
const fullData = {
|
|
1453
|
+
checklist: matchedChecklist,
|
|
1454
|
+
cssConfig,
|
|
1455
|
+
targetingData,
|
|
1456
|
+
customCSS
|
|
1457
|
+
};
|
|
1458
|
+
sessionStorage.removeItem("onboardingVisited");
|
|
1459
|
+
Onboarding(
|
|
1460
|
+
title,
|
|
1461
|
+
subtitle,
|
|
1462
|
+
completion,
|
|
1463
|
+
items,
|
|
1464
|
+
cssConfig,
|
|
1465
|
+
targetingData,
|
|
1466
|
+
customCSS,
|
|
1467
|
+
user_var,
|
|
1468
|
+
checklist_id
|
|
1469
|
+
);
|
|
1470
|
+
return matchedChecklist;
|
|
1471
|
+
} catch (err) {
|
|
1472
|
+
console.warn("Checklist error:", err.message);
|
|
1473
|
+
throw err;
|
|
1474
|
+
}
|
|
1475
|
+
});
|
|
1476
|
+
(function() {
|
|
1477
|
+
const pushState = history.pushState;
|
|
1478
|
+
const replaceState = history.replaceState;
|
|
1479
|
+
history.pushState = function() {
|
|
1480
|
+
pushState.apply(history, arguments);
|
|
1481
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
1482
|
+
};
|
|
1483
|
+
history.replaceState = function() {
|
|
1484
|
+
replaceState.apply(history, arguments);
|
|
1485
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
1486
|
+
};
|
|
1487
|
+
window.addEventListener("popstate", () => {
|
|
1488
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
1489
|
+
});
|
|
1490
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
1491
|
+
})();
|
|
1492
|
+
}
|
|
1493
|
+
var rivia_default = Checklist;
|
|
1494
|
+
|
|
1495
|
+
// src/utils/rivia-tour.js
|
|
1496
|
+
var RIVIA_TOUR = function() {
|
|
1497
|
+
const STATE = {
|
|
1498
|
+
picking: false,
|
|
1499
|
+
lastSelector: null,
|
|
1500
|
+
tips: [],
|
|
1501
|
+
// {id, selector, title, content, placement}
|
|
1502
|
+
tourIndex: 0,
|
|
1503
|
+
tour_id: null,
|
|
1504
|
+
tours: [],
|
|
1505
|
+
// all tours fetched from backend
|
|
1506
|
+
scrollAdvanceActive: false,
|
|
1507
|
+
// Track if scroll advance is active
|
|
1508
|
+
publish: false,
|
|
1509
|
+
// Track if tour is published
|
|
1510
|
+
is_completed: false,
|
|
1511
|
+
// Track if tour is completed
|
|
1512
|
+
user_var: "Guest_User",
|
|
1513
|
+
url: ""
|
|
1514
|
+
};
|
|
1515
|
+
if (typeof window === "undefined") return;
|
|
1516
|
+
const tourStateStr = window.sessionStorage.getItem("rivia_tour_state");
|
|
1517
|
+
const hasActiveTour = tourStateStr !== null;
|
|
1518
|
+
let user_var1 = "Guest_User";
|
|
1519
|
+
if (hasActiveTour) {
|
|
1520
|
+
console.log("\u{1F7E2} Active tour detected! Restoring state...");
|
|
1521
|
+
setTimeout(() => {
|
|
1522
|
+
restoreTourState();
|
|
1523
|
+
}, 300);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
function restoreTourState() {
|
|
1527
|
+
if (typeof window === "undefined") return;
|
|
1528
|
+
const tourStateStr2 = window.sessionStorage.getItem("rivia_tour_state");
|
|
1529
|
+
if (!tourStateStr2 || STATE.tour_id) {
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
;
|
|
1533
|
+
try {
|
|
1534
|
+
const tourState = JSON.parse(tourStateStr2);
|
|
1535
|
+
console.log("Restoring tour state:", tourState);
|
|
1536
|
+
STATE.tourIndex = tourState.tourIndex;
|
|
1537
|
+
STATE.tour_id = tourState.tourId;
|
|
1538
|
+
STATE.isPreviewMode = tourState.isPreviewMode;
|
|
1539
|
+
STATE.tips = tourState.tips;
|
|
1540
|
+
user_var1 = tourState.user_var1 || "Guest_User";
|
|
1541
|
+
STATE.title = tourState.title || "Untitled Tour";
|
|
1542
|
+
STATE.publish = tourState.publish || false;
|
|
1543
|
+
window.sessionStorage.removeItem("rivia_tour_state");
|
|
1544
|
+
if (STATE.tips?.length > 0) {
|
|
1545
|
+
setTimeout(() => {
|
|
1546
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
1547
|
+
}, 500);
|
|
1548
|
+
}
|
|
1549
|
+
} catch (error) {
|
|
1550
|
+
console.warn("Error restoring tour state:", error);
|
|
1551
|
+
window.sessionStorage.removeItem("rivia_tour_state");
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
async function createTooltip({
|
|
1555
|
+
id,
|
|
1556
|
+
selector,
|
|
1557
|
+
title,
|
|
1558
|
+
content,
|
|
1559
|
+
placement = "auto",
|
|
1560
|
+
nextUrl = "",
|
|
1561
|
+
isPreview = false,
|
|
1562
|
+
basic_showArrow = true,
|
|
1563
|
+
card_header = true,
|
|
1564
|
+
card_footer = true,
|
|
1565
|
+
card_back_button = false,
|
|
1566
|
+
card_next_button = true,
|
|
1567
|
+
card_skip_button = false
|
|
1568
|
+
}) {
|
|
1569
|
+
const anchor = await findBySelector(selector);
|
|
1570
|
+
if (!anchor) return null;
|
|
1571
|
+
const tip = document.createElement("div");
|
|
1572
|
+
tip.dataset.riviaTipId = id;
|
|
1573
|
+
const tipStyle = isPreview ? `
|
|
1574
|
+
position: absolute;
|
|
1575
|
+
min-width: 360px;
|
|
1576
|
+
max-width: 420px;
|
|
1577
|
+
min-height: 120px;
|
|
1578
|
+
padding: 18px 20px;
|
|
1579
|
+
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
|
1580
|
+
color: #1a202c;
|
|
1581
|
+
border-radius: 14px;
|
|
1582
|
+
border: 1px solid rgba(37, 99, 235, 0.2);
|
|
1583
|
+
box-shadow: 0 12px 40px rgba(37, 99, 235, 0.15), 0 0 1px rgba(0, 0, 0, 0.1);
|
|
1584
|
+
font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
1585
|
+
z-index: 2147483647;
|
|
1586
|
+
` : `
|
|
1587
|
+
position: absolute;
|
|
1588
|
+
min-width: 360px;
|
|
1589
|
+
max-width: 420px;
|
|
1590
|
+
min-height: 120px;
|
|
1591
|
+
padding: 16px 18px;
|
|
1592
|
+
background: #ffffffff;
|
|
1593
|
+
color: #0d0c0cff;
|
|
1594
|
+
border-radius: 12px;
|
|
1595
|
+
box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
|
|
1596
|
+
font: 14px/1.45 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
1597
|
+
z-index: 2147483647;
|
|
1598
|
+
`;
|
|
1599
|
+
tip.style.cssText = tipStyle;
|
|
1600
|
+
const arrow = document.createElement("div");
|
|
1601
|
+
const arrowStyle = isPreview ? `
|
|
1602
|
+
position: absolute;
|
|
1603
|
+
width: 12px;
|
|
1604
|
+
height: 12px;
|
|
1605
|
+
background: linear-gradient(135deg, #ffffff 0%, #f8f9fa 100%);
|
|
1606
|
+
border: 1px solid rgba(37, 99, 235, 0.2);
|
|
1607
|
+
transform: rotate(45deg);
|
|
1608
|
+
display: ${basic_showArrow ? "block" : "none"};
|
|
1609
|
+
` : `
|
|
1610
|
+
position: absolute;
|
|
1611
|
+
width: 12px;
|
|
1612
|
+
height: 12px;
|
|
1613
|
+
background: #ffffffff;
|
|
1614
|
+
transform: rotate(45deg);
|
|
1615
|
+
display: ${basic_showArrow ? "block" : "none"};
|
|
1616
|
+
`;
|
|
1617
|
+
arrow.style.cssText = arrowStyle;
|
|
1618
|
+
const h = document.createElement("input");
|
|
1619
|
+
h.value = title || "Tooltip";
|
|
1620
|
+
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;";
|
|
1621
|
+
h.style.cssText = titleStyle;
|
|
1622
|
+
h.placeholder = "Enter title";
|
|
1623
|
+
h.readOnly = isPreview;
|
|
1624
|
+
h.style.display = card_header ? "block" : "none";
|
|
1625
|
+
const p = document.createElement("textarea");
|
|
1626
|
+
p.value = content || "";
|
|
1627
|
+
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;";
|
|
1628
|
+
p.style.cssText = contentStyle;
|
|
1629
|
+
p.placeholder = "Enter description";
|
|
1630
|
+
p.readOnly = isPreview;
|
|
1631
|
+
p.style.display = card_footer ? "block" : "none";
|
|
1632
|
+
h.contentEditable = !isPreview;
|
|
1633
|
+
p.contentEditable = !isPreview;
|
|
1634
|
+
if (!isPreview) {
|
|
1635
|
+
setTimeout(() => h.focus(), 50);
|
|
1636
|
+
}
|
|
1637
|
+
const controls = document.createElement("div");
|
|
1638
|
+
controls.style.cssText = `
|
|
1639
|
+
display: flex;
|
|
1640
|
+
justify-content: flex-start;
|
|
1641
|
+
align-items: center;
|
|
1642
|
+
width: 100%;
|
|
1643
|
+
margin-top: 8px;
|
|
1644
|
+
`;
|
|
1645
|
+
const closeBtn = document.createElement("button");
|
|
1646
|
+
closeBtn.textContent = "Save";
|
|
1647
|
+
closeBtn.style.cssText = `
|
|
1648
|
+
padding: 6px 12px;
|
|
1649
|
+
height: 32px;
|
|
1650
|
+
line-height: 1;
|
|
1651
|
+
border-radius: 6px;
|
|
1652
|
+
border: none;
|
|
1653
|
+
background: #10b981;
|
|
1654
|
+
color: white;
|
|
1655
|
+
font-size: 13px;
|
|
1656
|
+
font-weight: 500;
|
|
1657
|
+
cursor: pointer;
|
|
1658
|
+
transition: background-color 0.2s;
|
|
1659
|
+
display: ${isPreview ? "none" : "block"};
|
|
1660
|
+
`;
|
|
1661
|
+
closeBtn.onclick = () => {
|
|
1662
|
+
const newTitle = h.value || "Tooltip";
|
|
1663
|
+
const newContent = p.value || "";
|
|
1664
|
+
const tipIndex = STATE.tips.findIndex((t) => t.id === id);
|
|
1665
|
+
if (tipIndex !== -1) {
|
|
1666
|
+
STATE.tips[tipIndex].title = newTitle;
|
|
1667
|
+
STATE.tips[tipIndex].content = newContent;
|
|
1668
|
+
if (STATE.tour_id) {
|
|
1669
|
+
putTips();
|
|
1670
|
+
} else {
|
|
1671
|
+
saveTips();
|
|
1672
|
+
}
|
|
1673
|
+
toast("Changes saved!");
|
|
1674
|
+
setTimeout(() => {
|
|
1675
|
+
tip.remove();
|
|
1676
|
+
}, 500);
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
controls.appendChild(closeBtn);
|
|
1680
|
+
const contentWrapper = document.createElement("div");
|
|
1681
|
+
contentWrapper.style.cssText = "margin-bottom: 16px;";
|
|
1682
|
+
if (card_header) {
|
|
1683
|
+
contentWrapper.appendChild(h);
|
|
1684
|
+
contentWrapper.appendChild(document.createElement("br"));
|
|
1685
|
+
}
|
|
1686
|
+
if (card_footer) {
|
|
1687
|
+
contentWrapper.appendChild(p);
|
|
1688
|
+
}
|
|
1689
|
+
tip.appendChild(contentWrapper);
|
|
1690
|
+
tip.appendChild(controls);
|
|
1691
|
+
tip.appendChild(arrow);
|
|
1692
|
+
document.body.appendChild(tip);
|
|
1693
|
+
positionTooltip(anchor, tip, arrow, placement);
|
|
1694
|
+
const reposition = () => positionTooltip(anchor, tip, arrow, placement);
|
|
1695
|
+
const repositionObserver = new ResizeObserver(reposition);
|
|
1696
|
+
repositionObserver.observe(tip);
|
|
1697
|
+
window.addEventListener("scroll", reposition, { passive: true });
|
|
1698
|
+
window.addEventListener("resize", reposition);
|
|
1699
|
+
const obs = new MutationObserver(() => {
|
|
1700
|
+
if (!document.body.contains(tip)) {
|
|
1701
|
+
window.removeEventListener("resize", reposition);
|
|
1702
|
+
window.removeEventListener("scroll", reposition);
|
|
1703
|
+
if (repositionObserver) repositionObserver.disconnect();
|
|
1704
|
+
obs.disconnect();
|
|
1705
|
+
}
|
|
1706
|
+
});
|
|
1707
|
+
obs.observe(document.body, { childList: true, subtree: true });
|
|
1708
|
+
return tip;
|
|
1709
|
+
}
|
|
1710
|
+
function positionTooltip(anchor, tip, arrow, placement, step) {
|
|
1711
|
+
const a = anchor.getBoundingClientRect();
|
|
1712
|
+
const t = tip.getBoundingClientRect();
|
|
1713
|
+
let place = placement;
|
|
1714
|
+
if (place === "auto") {
|
|
1715
|
+
const spaces = {
|
|
1716
|
+
top: a.top,
|
|
1717
|
+
bottom: window.innerHeight - a.bottom,
|
|
1718
|
+
left: a.left,
|
|
1719
|
+
right: window.innerWidth - a.right
|
|
1720
|
+
};
|
|
1721
|
+
place = Object.entries(spaces).sort((x, y) => y[1] - x[1])[0][0];
|
|
1722
|
+
}
|
|
1723
|
+
let top = 0, left = 0, gap = 8;
|
|
1724
|
+
if (place === "top") {
|
|
1725
|
+
top = a.top - t.height - gap;
|
|
1726
|
+
left = a.left + (a.width - t.width) / 2;
|
|
1727
|
+
Object.assign(arrow.style, {
|
|
1728
|
+
left: t.width / 2 - 5 + "px",
|
|
1729
|
+
top: t.height - 5 + "px"
|
|
1730
|
+
});
|
|
1731
|
+
} else if (place === "bottom") {
|
|
1732
|
+
top = a.bottom + gap;
|
|
1733
|
+
left = a.left + (a.width - t.width) / 2;
|
|
1734
|
+
Object.assign(arrow.style, { left: t.width / 2 - 5 + "px", top: "-5px" });
|
|
1735
|
+
} else if (place === "left") {
|
|
1736
|
+
top = a.top + (a.height - t.height) / 2;
|
|
1737
|
+
left = a.left - t.width - gap;
|
|
1738
|
+
Object.assign(arrow.style, {
|
|
1739
|
+
top: t.height / 2 - 5 + "px",
|
|
1740
|
+
left: t.width - 5 + "px"
|
|
1741
|
+
});
|
|
1742
|
+
} else {
|
|
1743
|
+
top = a.top + (a.height - t.height) / 2;
|
|
1744
|
+
left = a.right + gap;
|
|
1745
|
+
Object.assign(arrow.style, {
|
|
1746
|
+
top: t.height / 2 - 5 + "px",
|
|
1747
|
+
left: "-5px"
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
left = Math.max(8, Math.min(left, window.innerWidth - t.width - 8));
|
|
1751
|
+
top = Math.max(8, Math.min(top, window.innerHeight - t.height - 8));
|
|
1752
|
+
tip.style.left = left + window.scrollX + "px";
|
|
1753
|
+
tip.style.top = top + window.scrollY + "px";
|
|
1754
|
+
}
|
|
1755
|
+
function uploadVisitedPagesInBackground(tourId, user_var, tourIndex) {
|
|
1756
|
+
console.log("Uploading visited pages in background for tour ID:", tourIndex, "and user_var:", user_var1);
|
|
1757
|
+
let user_var2 = user_var1;
|
|
1758
|
+
const backendUrl22 = `https://demoapi.rivia.ai/tours_clients/${tourId}`;
|
|
1759
|
+
try {
|
|
1760
|
+
const payload = {
|
|
1761
|
+
name: user_var2,
|
|
1762
|
+
tourIndex
|
|
1763
|
+
};
|
|
1764
|
+
fetch(backendUrl22, {
|
|
1765
|
+
method: "POST",
|
|
1766
|
+
headers: { "Content-Type": "application/json" },
|
|
1767
|
+
credentials: "include",
|
|
1768
|
+
body: JSON.stringify(payload),
|
|
1769
|
+
keepalive: true
|
|
1770
|
+
}).then((res) => {
|
|
1771
|
+
if (res.status === 404) {
|
|
1772
|
+
console.warn("Invalid tour id");
|
|
1773
|
+
}
|
|
1774
|
+
}).catch((err) => {
|
|
1775
|
+
});
|
|
1776
|
+
} catch (err) {
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
async function loadTips(tourId, user_var) {
|
|
1780
|
+
if (!user_var) {
|
|
1781
|
+
return;
|
|
1782
|
+
}
|
|
1783
|
+
user_var1 = user_var;
|
|
1784
|
+
STATE.tour_id = tourId;
|
|
1785
|
+
if (sessionStorage.getItem("rivia_tour_state"))
|
|
1786
|
+
return;
|
|
1787
|
+
console.log("Loading tips for tour ID:", tourId, "and user_var:", user_var1);
|
|
1788
|
+
try {
|
|
1789
|
+
if (!tourId) console.warn("Tour ID is required");
|
|
1790
|
+
const res = await fetch(`https://demoapi.rivia.ai/tours2/${tourId}`, {
|
|
1791
|
+
method: "GET",
|
|
1792
|
+
headers: { "Content-Type": "application/json" }
|
|
1793
|
+
});
|
|
1794
|
+
if (!res.ok) {
|
|
1795
|
+
if (res.status === 404) {
|
|
1796
|
+
console.warn("Invalid tour id");
|
|
1797
|
+
}
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
const data = await res.json();
|
|
1801
|
+
STATE.tips = data && data.tour && Array.isArray(data.tour.steps) ? data.tour.steps : [];
|
|
1802
|
+
STATE.publish = data.tour.publish;
|
|
1803
|
+
STATE.url = data.tour.url;
|
|
1804
|
+
const stripTrailing = (p) => p.replace(/\/+$/, "");
|
|
1805
|
+
console.log("STATE.url", STATE.url);
|
|
1806
|
+
console.log("window.location.pathname", window.location.href);
|
|
1807
|
+
console.log("user_var", user_var);
|
|
1808
|
+
console.log("data.tour?.user_data?.[user_var],", data.tour?.user_data?.[user_var]);
|
|
1809
|
+
if (!data.tour?.user_data?.[user_var]) {
|
|
1810
|
+
uploadVisitedPagesInBackground(tourId, user_var, 0);
|
|
1811
|
+
} else {
|
|
1812
|
+
STATE.tourIndex = data.tour.user_data[user_var].tourIndex || 0;
|
|
1813
|
+
console.log("STATE.tourIndex ", STATE.tourIndex);
|
|
1814
|
+
}
|
|
1815
|
+
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;
|
|
1816
|
+
if (STATE.is_completed) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
console.log(`Loaded tips for tour ${tourId}:`, STATE.tips);
|
|
1820
|
+
return STATE.tips;
|
|
1821
|
+
} catch (err) {
|
|
1822
|
+
console.warn("Invalid tour id ", err);
|
|
1823
|
+
STATE.tips = [];
|
|
1824
|
+
return STATE.tips;
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
function getStepUrlInfo(step) {
|
|
1828
|
+
if (!step) return null;
|
|
1829
|
+
const targetUrl = step.targetUrl || "All pages";
|
|
1830
|
+
const isAvailable = isStepAvailableOnCurrentPage(step);
|
|
1831
|
+
return {
|
|
1832
|
+
targetUrl,
|
|
1833
|
+
isAvailable,
|
|
1834
|
+
displayText: isAvailable ? "\u2713 On this page" : `\u{1F4CD} Go to: ${targetUrl}`
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
async function showStep(i, isPreview = true) {
|
|
1838
|
+
uploadVisitedPagesInBackground(STATE.tour_id, user_var1, i);
|
|
1839
|
+
console.log("Showing step", i, "of", STATE.tips.length);
|
|
1840
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
1841
|
+
const step = STATE.tips[i];
|
|
1842
|
+
if (!step) return;
|
|
1843
|
+
STATE.tourIndex = i;
|
|
1844
|
+
updateUrlStatus();
|
|
1845
|
+
cleanupAllOverlays();
|
|
1846
|
+
if (step.card_type === "welcome") {
|
|
1847
|
+
if (isPreview) {
|
|
1848
|
+
await showWelcomeCardPreview(step, i);
|
|
1849
|
+
} else {
|
|
1850
|
+
showWelcomeCardEditModal(i);
|
|
1851
|
+
}
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
if (step.card_type === "modal_dialog") {
|
|
1855
|
+
if (isPreview) {
|
|
1856
|
+
await showModalDialogPreview(step, i);
|
|
1857
|
+
} else {
|
|
1858
|
+
showModalDialogEditModal(i);
|
|
1859
|
+
}
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
if (step.card_type === "feedback") {
|
|
1863
|
+
if (isPreview) {
|
|
1864
|
+
await showFeedbackCardPreview(step, i);
|
|
1865
|
+
} else {
|
|
1866
|
+
showFeedbackCardEditModal(i);
|
|
1867
|
+
}
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
if (step.card_type === "video_explainer") {
|
|
1871
|
+
if (isPreview) {
|
|
1872
|
+
console.log("Preview mode: Showing video explainer for step:", step.id);
|
|
1873
|
+
const targetElement = await findBySelector(step.selector);
|
|
1874
|
+
if (targetElement) {
|
|
1875
|
+
try {
|
|
1876
|
+
targetElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1877
|
+
} catch (e) {
|
|
1878
|
+
targetElement.scrollIntoView(true);
|
|
1879
|
+
}
|
|
1880
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1881
|
+
targetElement.style.outline = "3px solid #2563eb";
|
|
1882
|
+
targetElement.style.outlineOffset = "2px";
|
|
1883
|
+
targetElement.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1884
|
+
}
|
|
1885
|
+
setTimeout(async () => {
|
|
1886
|
+
const highlightedElement = document.querySelector('[data-rivia-highlight="true"]');
|
|
1887
|
+
if (!highlightedElement && targetElement) {
|
|
1888
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1889
|
+
}
|
|
1890
|
+
const videoUI = await createVideoUI({ ...step, isPreview: true });
|
|
1891
|
+
if (videoUI) {
|
|
1892
|
+
console.log("Video UI created successfully with built-in navigation buttons");
|
|
1893
|
+
} else {
|
|
1894
|
+
console.warn("Failed to create video UI for preview");
|
|
1895
|
+
}
|
|
1896
|
+
}, 600);
|
|
1897
|
+
} else {
|
|
1898
|
+
console.log("Edit mode: Showing video explainer for step:", step.id);
|
|
1899
|
+
console.log("Step selector:", step.selector);
|
|
1900
|
+
if (step.selector) {
|
|
1901
|
+
const targetElement = await findBySelector(step.selector);
|
|
1902
|
+
console.log("Found target element:", targetElement, "for selector:", step.selector);
|
|
1903
|
+
if (targetElement) {
|
|
1904
|
+
console.log("Element found, scrolling into view...");
|
|
1905
|
+
try {
|
|
1906
|
+
targetElement.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1907
|
+
} catch (e) {
|
|
1908
|
+
console.warn("ScrollIntoView error:", e);
|
|
1909
|
+
targetElement.scrollIntoView(true);
|
|
1910
|
+
}
|
|
1911
|
+
targetElement.setAttribute("data-rivia-highlight", "true");
|
|
1912
|
+
targetElement.style.outline = "3px solid #2563eb";
|
|
1913
|
+
targetElement.style.outlineOffset = "2px";
|
|
1914
|
+
targetElement.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1915
|
+
console.log("Element highlighted with blue outline");
|
|
1916
|
+
if (step.target_animation && step.target_animation !== "none") {
|
|
1917
|
+
previewAnimation(step.selector, step.target_animation);
|
|
1918
|
+
}
|
|
1919
|
+
if (step.basic_backdrop && step.basic_backdrop !== "none") {
|
|
1920
|
+
previewBackdrop(step.selector, step.basic_backdrop);
|
|
1921
|
+
}
|
|
1922
|
+
} else {
|
|
1923
|
+
console.warn("Target element not found for selector:", step.selector);
|
|
1924
|
+
}
|
|
1925
|
+
} else {
|
|
1926
|
+
console.warn("No selector found in step:", step);
|
|
1927
|
+
}
|
|
1928
|
+
setTimeout(async () => {
|
|
1929
|
+
console.log("Creating video UI after scroll delay...");
|
|
1930
|
+
const highlightedElement = document.querySelector('[data-rivia-highlight="true"]');
|
|
1931
|
+
console.log("Highlighted element for video positioning:", highlightedElement);
|
|
1932
|
+
const videoUI = await createVideoUI({ ...step, isPreview: false });
|
|
1933
|
+
if (videoUI) {
|
|
1934
|
+
console.log("Video UI created successfully");
|
|
1935
|
+
if (typeof showPointerCardPanel === "function") {
|
|
1936
|
+
console.log("Showing pointer card panel for selector:", step.selector);
|
|
1937
|
+
const stepIndex = STATE.tips.findIndex((t) => t === step);
|
|
1938
|
+
showPointerCardPanel(step.selector, stepIndex);
|
|
1939
|
+
}
|
|
1940
|
+
} else {
|
|
1941
|
+
console.warn("Failed to create video UI");
|
|
1942
|
+
}
|
|
1943
|
+
}, 600);
|
|
1944
|
+
}
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
if (isPreview) {
|
|
1948
|
+
const el = await findBySelector(step.selector);
|
|
1949
|
+
if (el) {
|
|
1950
|
+
try {
|
|
1951
|
+
el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1952
|
+
} catch (e) {
|
|
1953
|
+
el.scrollIntoView(true);
|
|
1954
|
+
}
|
|
1955
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
1956
|
+
n.removeAttribute("data-rivia-highlight");
|
|
1957
|
+
n.style.outline = "";
|
|
1958
|
+
n.style.outlineOffset = "";
|
|
1959
|
+
n.style.backgroundColor = "";
|
|
1960
|
+
});
|
|
1961
|
+
el.setAttribute("data-rivia-highlight", "true");
|
|
1962
|
+
el.style.outline = "3px solid #2563eb";
|
|
1963
|
+
el.style.outlineOffset = "2px";
|
|
1964
|
+
el.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
1965
|
+
if (step.target_animation && step.target_animation !== "none") {
|
|
1966
|
+
previewAnimation(step.selector, step.target_animation);
|
|
1967
|
+
}
|
|
1968
|
+
if (step.basic_backdrop && step.basic_backdrop !== "none") {
|
|
1969
|
+
previewBackdrop(step.selector, step.basic_backdrop);
|
|
1970
|
+
} else {
|
|
1971
|
+
const backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
1972
|
+
if (backdropOverlay) {
|
|
1973
|
+
backdropOverlay.remove();
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
setTimeout(async () => {
|
|
1978
|
+
const tip2 = await createTooltip({ ...step, isPreview });
|
|
1979
|
+
if (tip2) {
|
|
1980
|
+
await attachNavigationButtons(tip2, i, isPreview);
|
|
1981
|
+
try {
|
|
1982
|
+
tip2.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
1983
|
+
} catch (e) {
|
|
1984
|
+
tip2.scrollIntoView(true);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
}, 600);
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
if (!isPreview && step.selector && !step.card_type) {
|
|
1991
|
+
const el = await findBySelector(step.selector);
|
|
1992
|
+
if (el) {
|
|
1993
|
+
try {
|
|
1994
|
+
el.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
1995
|
+
} catch (e) {
|
|
1996
|
+
el.scrollIntoView(true);
|
|
1997
|
+
}
|
|
1998
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
1999
|
+
n.removeAttribute("data-rivia-highlight");
|
|
2000
|
+
n.style.outline = "";
|
|
2001
|
+
n.style.outlineOffset = "";
|
|
2002
|
+
n.style.backgroundColor = "";
|
|
2003
|
+
});
|
|
2004
|
+
el.setAttribute("data-rivia-highlight", "true");
|
|
2005
|
+
el.style.outline = "3px solid #2563eb";
|
|
2006
|
+
el.style.outlineOffset = "2px";
|
|
2007
|
+
el.style.backgroundColor = "rgba(37, 99, 235, 0.1)";
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
const tip = await createTooltip({ ...step, isPreview });
|
|
2011
|
+
console.log("nextUrl for step", step.nextUrl);
|
|
2012
|
+
if (!tip) {
|
|
2013
|
+
const stepUrlInfo = getStepUrlInfo(step);
|
|
2014
|
+
if (stepUrlInfo && !stepUrlInfo.isAvailable) {
|
|
2015
|
+
toast("\u{1F4CD} Step element not found on this URL. The tooltip is designed for: " + stepUrlInfo.targetUrl, true);
|
|
2016
|
+
console.warn("\u{1F4CD} Step element not found. Target URL:", stepUrlInfo.targetUrl, "Current URL:", window.location.href);
|
|
2017
|
+
} else {
|
|
2018
|
+
toast("\u{1F4CD} Tooltip element not found on this page", true);
|
|
2019
|
+
console.warn("\u{1F4CD} Tooltip element not found for selector:", step.selector);
|
|
2020
|
+
}
|
|
2021
|
+
if (step.nextUrl && step.nextUrl.trim()) {
|
|
2022
|
+
const navUrl = addTourParamsToUrl(step.nextUrl, STATE.tour_id);
|
|
2023
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
2024
|
+
tourIndex: STATE.tourIndex,
|
|
2025
|
+
tourId: STATE.tour_id,
|
|
2026
|
+
user_var1,
|
|
2027
|
+
isPreviewMode: true,
|
|
2028
|
+
// Use edit mode when navigating from tooltip
|
|
2029
|
+
tips: STATE.tips,
|
|
2030
|
+
title: STATE.title || "Untitled Tour",
|
|
2031
|
+
publish: STATE.publish
|
|
2032
|
+
}));
|
|
2033
|
+
} else {
|
|
2034
|
+
nextStep();
|
|
2035
|
+
}
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
await attachNavigationButtons(tip, i, isPreview);
|
|
2039
|
+
setTimeout(() => {
|
|
2040
|
+
try {
|
|
2041
|
+
tip.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
|
|
2042
|
+
} catch (e) {
|
|
2043
|
+
tip.scrollIntoView(true);
|
|
2044
|
+
}
|
|
2045
|
+
}, 100);
|
|
2046
|
+
}
|
|
2047
|
+
async function createVideoUI(step) {
|
|
2048
|
+
console.log("Creating video UI for step:", step);
|
|
2049
|
+
const anchor = await findBySelector(step.selector);
|
|
2050
|
+
console.log("Found anchor:", anchor);
|
|
2051
|
+
if (!anchor) {
|
|
2052
|
+
console.warn("Anchor not found for selector:", step.selector);
|
|
2053
|
+
return null;
|
|
2054
|
+
}
|
|
2055
|
+
const videoContainer = document.createElement("div");
|
|
2056
|
+
videoContainer.dataset.riviaTipId = step.id;
|
|
2057
|
+
const width = step.video_width || 400;
|
|
2058
|
+
const height = step.video_height || 300;
|
|
2059
|
+
videoContainer.style.cssText = `
|
|
2060
|
+
position: absolute;
|
|
2061
|
+
width: ${width}px;
|
|
2062
|
+
height: ${height}px;
|
|
2063
|
+
background: #ffffff;
|
|
2064
|
+
border-radius: 20px;
|
|
2065
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35), 0 0 1px rgba(0, 0, 0, 0.1);
|
|
2066
|
+
overflow: hidden;
|
|
2067
|
+
z-index: 2147483647;
|
|
2068
|
+
display: flex;
|
|
2069
|
+
flex-direction: column;
|
|
2070
|
+
border: 1px solid rgba(255, 255, 255, 0.8);
|
|
2071
|
+
`;
|
|
2072
|
+
const header = document.createElement("div");
|
|
2073
|
+
header.style.cssText = `
|
|
2074
|
+
display: flex;
|
|
2075
|
+
justify-content: space-between;
|
|
2076
|
+
align-items: center;
|
|
2077
|
+
padding: 16px 20px;
|
|
2078
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
2079
|
+
color: white;
|
|
2080
|
+
font-weight: 700;
|
|
2081
|
+
font-size: 15px;
|
|
2082
|
+
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
|
2083
|
+
`;
|
|
2084
|
+
const titleSpan = document.createElement("span");
|
|
2085
|
+
titleSpan.textContent = step.title || "Video Explainer";
|
|
2086
|
+
header.appendChild(titleSpan);
|
|
2087
|
+
if (!step.isPreview) {
|
|
2088
|
+
const settingsBtn = document.createElement("button");
|
|
2089
|
+
settingsBtn.innerHTML = "\u2699\uFE0F";
|
|
2090
|
+
settingsBtn.style.cssText = `
|
|
2091
|
+
background: rgba(255, 255, 255, 0.2);
|
|
2092
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
2093
|
+
border-radius: 6px;
|
|
2094
|
+
width: 32px;
|
|
2095
|
+
height: 32px;
|
|
2096
|
+
cursor: pointer;
|
|
2097
|
+
color: white;
|
|
2098
|
+
font-size: 16px;
|
|
2099
|
+
transition: all 0.2s;
|
|
2100
|
+
`;
|
|
2101
|
+
settingsBtn.onmouseover = () => settingsBtn.style.background = "rgba(255, 255, 255, 0.3)";
|
|
2102
|
+
settingsBtn.onmouseout = () => settingsBtn.style.background = "rgba(255, 255, 255, 0.2)";
|
|
2103
|
+
settingsBtn.onclick = () => {
|
|
2104
|
+
const existingPanel = document.getElementById("rivia-video-settings-panel");
|
|
2105
|
+
if (existingPanel) {
|
|
2106
|
+
existingPanel.remove();
|
|
2107
|
+
} else {
|
|
2108
|
+
showVideoSettings(step, videoContainer, settingsBtn);
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
header.appendChild(settingsBtn);
|
|
2112
|
+
}
|
|
2113
|
+
videoContainer.appendChild(header);
|
|
2114
|
+
const playerArea = document.createElement("div");
|
|
2115
|
+
playerArea.style.cssText = `
|
|
2116
|
+
flex: 1;
|
|
2117
|
+
display: flex;
|
|
2118
|
+
align-items: center;
|
|
2119
|
+
justify-content: center;
|
|
2120
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
2121
|
+
position: relative;
|
|
2122
|
+
overflow: hidden;
|
|
2123
|
+
`;
|
|
2124
|
+
if (step.video_url) {
|
|
2125
|
+
const videoId = step.video_url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\n?#]+)/)?.[1];
|
|
2126
|
+
if (videoId) {
|
|
2127
|
+
const thumbnail = document.createElement("img");
|
|
2128
|
+
thumbnail.src = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`;
|
|
2129
|
+
thumbnail.style.cssText = `
|
|
2130
|
+
position: absolute;
|
|
2131
|
+
width: 100%;
|
|
2132
|
+
height: 100%;
|
|
2133
|
+
object-fit: cover;
|
|
2134
|
+
opacity: 0.9;
|
|
2135
|
+
filter: brightness(0.95);
|
|
2136
|
+
`;
|
|
2137
|
+
thumbnail.onerror = () => {
|
|
2138
|
+
thumbnail.src = `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
|
|
2139
|
+
};
|
|
2140
|
+
playerArea.appendChild(thumbnail);
|
|
2141
|
+
console.log("Video thumbnail loaded for video ID:", videoId);
|
|
2142
|
+
} else {
|
|
2143
|
+
console.warn("Could not extract video ID from URL:", step.video_url);
|
|
2144
|
+
}
|
|
2145
|
+
} else {
|
|
2146
|
+
console.warn("No video URL provided for step:", step.id);
|
|
2147
|
+
}
|
|
2148
|
+
const playButton = document.createElement("button");
|
|
2149
|
+
playButton.innerHTML = "\u25B6";
|
|
2150
|
+
playButton.style.cssText = `
|
|
2151
|
+
width: 90px;
|
|
2152
|
+
height: 90px;
|
|
2153
|
+
border-radius: 50%;
|
|
2154
|
+
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
|
|
2155
|
+
border: 4px solid rgba(255, 255, 255, 0.3);
|
|
2156
|
+
color: white;
|
|
2157
|
+
font-size: 36px;
|
|
2158
|
+
cursor: pointer;
|
|
2159
|
+
transition: all 0.3s ease;
|
|
2160
|
+
box-shadow: 0 8px 25px rgba(255, 107, 107, 0.5), inset 0 -2px 5px rgba(0, 0, 0, 0.2);
|
|
2161
|
+
position: relative;
|
|
2162
|
+
z-index: 10;
|
|
2163
|
+
`;
|
|
2164
|
+
playButton.onmouseover = () => {
|
|
2165
|
+
playButton.style.background = "linear-gradient(135deg, #ff5252 0%, #ff1744 100%)";
|
|
2166
|
+
playButton.style.transform = "scale(1.15)";
|
|
2167
|
+
playButton.style.boxShadow = "0 12px 35px rgba(255, 107, 107, 0.7), inset 0 -2px 5px rgba(0, 0, 0, 0.2)";
|
|
2168
|
+
};
|
|
2169
|
+
playButton.onmouseout = () => {
|
|
2170
|
+
playButton.style.background = "linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%)";
|
|
2171
|
+
playButton.style.transform = "scale(1)";
|
|
2172
|
+
playButton.style.boxShadow = "0 8px 25px rgba(255, 107, 107, 0.5), inset 0 -2px 5px rgba(0, 0, 0, 0.2)";
|
|
2173
|
+
};
|
|
2174
|
+
playButton.onclick = () => {
|
|
2175
|
+
if (step.video_url) {
|
|
2176
|
+
const videoId = step.video_url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\n?#]+)/)?.[1];
|
|
2177
|
+
if (videoId) {
|
|
2178
|
+
playerArea.innerHTML = "";
|
|
2179
|
+
const iframe = document.createElement("iframe");
|
|
2180
|
+
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
|
|
2181
|
+
iframe.style.cssText = `
|
|
2182
|
+
width: 100%;
|
|
2183
|
+
height: 100%;
|
|
2184
|
+
border: none;
|
|
2185
|
+
border-radius: 8px;
|
|
2186
|
+
`;
|
|
2187
|
+
iframe.allow = "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture";
|
|
2188
|
+
iframe.allowFullscreen = true;
|
|
2189
|
+
playerArea.appendChild(iframe);
|
|
2190
|
+
}
|
|
2191
|
+
}
|
|
2192
|
+
};
|
|
2193
|
+
playerArea.appendChild(playButton);
|
|
2194
|
+
videoContainer.appendChild(playerArea);
|
|
2195
|
+
const footer = document.createElement("div");
|
|
2196
|
+
footer.style.cssText = `
|
|
2197
|
+
display: flex;
|
|
2198
|
+
justify-content: space-between;
|
|
2199
|
+
align-items: center;
|
|
2200
|
+
padding: 16px 20px;
|
|
2201
|
+
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
2202
|
+
gap: 12px;
|
|
2203
|
+
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
|
2204
|
+
`;
|
|
2205
|
+
const skipBtn = document.createElement("button");
|
|
2206
|
+
skipBtn.textContent = "Skip";
|
|
2207
|
+
skipBtn.style.cssText = `
|
|
2208
|
+
padding: 10px 20px;
|
|
2209
|
+
background: rgba(255, 255, 255, 0.6);
|
|
2210
|
+
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
2211
|
+
border-radius: 8px;
|
|
2212
|
+
color: #333;
|
|
2213
|
+
font-weight: 600;
|
|
2214
|
+
cursor: pointer;
|
|
2215
|
+
transition: all 0.2s ease;
|
|
2216
|
+
`;
|
|
2217
|
+
skipBtn.onmouseover = () => {
|
|
2218
|
+
skipBtn.style.background = "rgba(255, 255, 255, 0.9)";
|
|
2219
|
+
skipBtn.style.transform = "translateY(-2px)";
|
|
2220
|
+
skipBtn.style.boxShadow = "0 4px 12px rgba(0, 0, 0, 0.1)";
|
|
2221
|
+
};
|
|
2222
|
+
skipBtn.onmouseout = () => {
|
|
2223
|
+
skipBtn.style.background = "rgba(255, 255, 255, 0.6)";
|
|
2224
|
+
skipBtn.style.transform = "translateY(0)";
|
|
2225
|
+
skipBtn.style.boxShadow = "none";
|
|
2226
|
+
};
|
|
2227
|
+
skipBtn.onclick = () => {
|
|
2228
|
+
endTour();
|
|
2229
|
+
};
|
|
2230
|
+
footer.appendChild(skipBtn);
|
|
2231
|
+
const nextBtn = document.createElement("button");
|
|
2232
|
+
nextBtn.textContent = "Next";
|
|
2233
|
+
nextBtn.style.cssText = `
|
|
2234
|
+
padding: 10px 24px;
|
|
2235
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
2236
|
+
border: none;
|
|
2237
|
+
border-radius: 8px;
|
|
2238
|
+
color: white;
|
|
2239
|
+
font-weight: 700;
|
|
2240
|
+
cursor: pointer;
|
|
2241
|
+
transition: all 0.2s ease;
|
|
2242
|
+
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
2243
|
+
`;
|
|
2244
|
+
nextBtn.onmouseover = () => {
|
|
2245
|
+
nextBtn.style.background = "linear-gradient(135deg, #5568d3 0%, #6a3a8f 100%)";
|
|
2246
|
+
nextBtn.style.transform = "translateY(-2px)";
|
|
2247
|
+
nextBtn.style.boxShadow = "0 6px 20px rgba(102, 126, 234, 0.6)";
|
|
2248
|
+
};
|
|
2249
|
+
nextBtn.onmouseout = () => {
|
|
2250
|
+
nextBtn.style.background = "linear-gradient(135deg, #667eea 0%, #764ba2 100%)";
|
|
2251
|
+
nextBtn.style.transform = "translateY(0)";
|
|
2252
|
+
nextBtn.style.boxShadow = "0 4px 15px rgba(102, 126, 234, 0.4)";
|
|
2253
|
+
};
|
|
2254
|
+
nextBtn.onclick = async () => {
|
|
2255
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2256
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2257
|
+
showStep(STATE.tourIndex, true);
|
|
2258
|
+
} else {
|
|
2259
|
+
endTour();
|
|
2260
|
+
}
|
|
2261
|
+
};
|
|
2262
|
+
footer.appendChild(nextBtn);
|
|
2263
|
+
videoContainer.appendChild(footer);
|
|
2264
|
+
document.body.appendChild(videoContainer);
|
|
2265
|
+
setTimeout(async () => {
|
|
2266
|
+
try {
|
|
2267
|
+
anchor.scrollIntoView({ behavior: "smooth", block: "center", inline: "nearest" });
|
|
2268
|
+
} catch (e) {
|
|
2269
|
+
anchor.scrollIntoView(true);
|
|
2270
|
+
}
|
|
2271
|
+
setTimeout(async () => {
|
|
2272
|
+
const a = anchor.getBoundingClientRect();
|
|
2273
|
+
const t = videoContainer.getBoundingClientRect();
|
|
2274
|
+
let top = a.bottom + 8;
|
|
2275
|
+
let left = a.left + (a.width - t.width) / 2;
|
|
2276
|
+
left = Math.max(8, Math.min(left, window.innerWidth - t.width - 8));
|
|
2277
|
+
top = Math.max(8, Math.min(top, window.innerHeight - t.height - 8));
|
|
2278
|
+
videoContainer.style.left = left + window.scrollX + "px";
|
|
2279
|
+
videoContainer.style.top = top + window.scrollY + "px";
|
|
2280
|
+
console.log("Video UI positioned at:", { top, left, width, height });
|
|
2281
|
+
}, 300);
|
|
2282
|
+
}, 0);
|
|
2283
|
+
return videoContainer;
|
|
2284
|
+
}
|
|
2285
|
+
async function previewAnimation(selector, animationType) {
|
|
2286
|
+
try {
|
|
2287
|
+
const element = document.querySelector(selector);
|
|
2288
|
+
if (!element) {
|
|
2289
|
+
console.warn("Element not found for selector:", selector);
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
element.classList.remove(
|
|
2293
|
+
"rivia-animate-flash",
|
|
2294
|
+
"rivia-animate-rubber-band",
|
|
2295
|
+
"rivia-animate-shake"
|
|
2296
|
+
);
|
|
2297
|
+
const animationMap = {
|
|
2298
|
+
flash: "rivia-animate-flash",
|
|
2299
|
+
"rubber band": "rivia-animate-rubber-band",
|
|
2300
|
+
shake: "rivia-animate-shake",
|
|
2301
|
+
none: null
|
|
2302
|
+
};
|
|
2303
|
+
const animClass = animationMap[animationType];
|
|
2304
|
+
if (animClass) {
|
|
2305
|
+
element.classList.add(animClass);
|
|
2306
|
+
setTimeout(async () => {
|
|
2307
|
+
element.classList.remove(animClass);
|
|
2308
|
+
}, 2e3);
|
|
2309
|
+
}
|
|
2310
|
+
} catch (err) {
|
|
2311
|
+
console.warn("Error previewing animation:", err);
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
async function findBySelector(selector) {
|
|
2315
|
+
if (!selector) return null;
|
|
2316
|
+
const retryInterval = 1e3;
|
|
2317
|
+
while (true) {
|
|
2318
|
+
try {
|
|
2319
|
+
const element = document.querySelector(selector);
|
|
2320
|
+
if (element) {
|
|
2321
|
+
console.log("\u2713 Element found with selector:", selector);
|
|
2322
|
+
return element;
|
|
2323
|
+
} else {
|
|
2324
|
+
console.warn("\u26A0\uFE0F Selector did not match any element, retrying:", selector);
|
|
2325
|
+
const idMatch = selector.match(/#([\w-]+)/);
|
|
2326
|
+
if (idMatch) {
|
|
2327
|
+
const idElement = document.getElementById(idMatch[1]);
|
|
2328
|
+
if (idElement) {
|
|
2329
|
+
console.log("\u2713 Found element by ID fallback:", idMatch[1]);
|
|
2330
|
+
return idElement;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
const classMatch = selector.match(/\.([-\w]+)/);
|
|
2334
|
+
if (classMatch) {
|
|
2335
|
+
const classElement = document.querySelector("." + classMatch[1]);
|
|
2336
|
+
if (classElement) {
|
|
2337
|
+
console.log("\u2713 Found element by class fallback:", classMatch[1]);
|
|
2338
|
+
return classElement;
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
await new Promise((resolve) => setTimeout(resolve, retryInterval));
|
|
2342
|
+
}
|
|
2343
|
+
} catch (e) {
|
|
2344
|
+
console.warn("\u26A0\uFE0F Invalid selector, retrying:", selector, e);
|
|
2345
|
+
const idMatch = selector.match(/#([\w-]+)/);
|
|
2346
|
+
if (idMatch) {
|
|
2347
|
+
const idElement = document.getElementById(idMatch[1]);
|
|
2348
|
+
if (idElement) {
|
|
2349
|
+
console.log("\u2713 Found element by ID after selector error:", idMatch[1]);
|
|
2350
|
+
return idElement;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
await new Promise((resolve) => setTimeout(resolve, retryInterval));
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
async function highlightElementBySelector(selector) {
|
|
2358
|
+
const el = await findBySelector(selector);
|
|
2359
|
+
if (!el) return;
|
|
2360
|
+
try {
|
|
2361
|
+
el.scrollIntoView({
|
|
2362
|
+
behavior: "smooth",
|
|
2363
|
+
block: "center",
|
|
2364
|
+
inline: "nearest"
|
|
2365
|
+
});
|
|
2366
|
+
} catch (e) {
|
|
2367
|
+
el.scrollIntoView(true);
|
|
2368
|
+
}
|
|
2369
|
+
const r = el.getBoundingClientRect();
|
|
2370
|
+
try {
|
|
2371
|
+
document.body.appendChild(overlay);
|
|
2372
|
+
} catch (e) {
|
|
2373
|
+
}
|
|
2374
|
+
Object.assign(highlight.style, {
|
|
2375
|
+
left: r.left + window.scrollX + "px",
|
|
2376
|
+
top: r.top + window.scrollY + "px",
|
|
2377
|
+
width: r.width + "px",
|
|
2378
|
+
height: r.height + "px"
|
|
2379
|
+
});
|
|
2380
|
+
}
|
|
2381
|
+
async function previewBackdrop(selector, backdropType) {
|
|
2382
|
+
try {
|
|
2383
|
+
let backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
2384
|
+
if (backdropOverlay) {
|
|
2385
|
+
backdropOverlay.remove();
|
|
2386
|
+
}
|
|
2387
|
+
if (backdropType === "none") {
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
const targetElement = await findBySelector(selector);
|
|
2391
|
+
if (!targetElement) return;
|
|
2392
|
+
const targetRect = targetElement.getBoundingClientRect();
|
|
2393
|
+
const padding = 8;
|
|
2394
|
+
if (backdropType === "boxed") {
|
|
2395
|
+
const boxedOverlay = document.createElement("div");
|
|
2396
|
+
boxedOverlay.id = "rivia-backdrop-overlay";
|
|
2397
|
+
boxedOverlay.style.cssText = `
|
|
2398
|
+
position: fixed;
|
|
2399
|
+
top: 0;
|
|
2400
|
+
left: 0;
|
|
2401
|
+
width: 100%;
|
|
2402
|
+
height: 100%;
|
|
2403
|
+
z-index: 2147483644;
|
|
2404
|
+
pointer-events: none;
|
|
2405
|
+
background: rgba(240, 240, 245, 0.3);
|
|
2406
|
+
backdrop-filter: blur(3px);
|
|
2407
|
+
`;
|
|
2408
|
+
const boxHighlight = document.createElement("div");
|
|
2409
|
+
boxHighlight.style.cssText = `
|
|
2410
|
+
position: fixed;
|
|
2411
|
+
left: ${targetRect.left - padding}px;
|
|
2412
|
+
top: ${targetRect.top - padding}px;
|
|
2413
|
+
width: ${targetRect.width + padding * 2}px;
|
|
2414
|
+
height: ${targetRect.height + padding * 2}px;
|
|
2415
|
+
border: 2px solid #3b82f6;
|
|
2416
|
+
border-radius: 8px;
|
|
2417
|
+
background: rgba(59, 130, 246, 0.08);
|
|
2418
|
+
pointer-events: none;
|
|
2419
|
+
z-index: 2147483645;
|
|
2420
|
+
box-shadow: 0 0 0 9999px rgba(240, 240, 245, 0.3);
|
|
2421
|
+
`;
|
|
2422
|
+
document.body.appendChild(boxedOverlay);
|
|
2423
|
+
document.body.appendChild(boxHighlight);
|
|
2424
|
+
const updateBoxed = () => {
|
|
2425
|
+
const newRect = targetElement.getBoundingClientRect();
|
|
2426
|
+
boxHighlight.style.left = `${newRect.left - padding}px`;
|
|
2427
|
+
boxHighlight.style.top = `${newRect.top - padding}px`;
|
|
2428
|
+
boxHighlight.style.width = `${newRect.width + padding * 2}px`;
|
|
2429
|
+
boxHighlight.style.height = `${newRect.height + padding * 2}px`;
|
|
2430
|
+
};
|
|
2431
|
+
window.addEventListener("scroll", updateBoxed, { passive: true });
|
|
2432
|
+
window.addEventListener("resize", updateBoxed);
|
|
2433
|
+
boxedOverlay.updateBackdrop = updateBoxed;
|
|
2434
|
+
return;
|
|
2435
|
+
}
|
|
2436
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
2437
|
+
svg.id = "rivia-backdrop-overlay";
|
|
2438
|
+
svg.style.cssText = `
|
|
2439
|
+
position: fixed;
|
|
2440
|
+
top: 0;
|
|
2441
|
+
left: 0;
|
|
2442
|
+
width: 100%;
|
|
2443
|
+
height: 100%;
|
|
2444
|
+
z-index: 2147483644;
|
|
2445
|
+
pointer-events: none;
|
|
2446
|
+
`;
|
|
2447
|
+
const defs = document.createElementNS(
|
|
2448
|
+
"http://www.w3.org/2000/svg",
|
|
2449
|
+
"defs"
|
|
2450
|
+
);
|
|
2451
|
+
const mask = document.createElementNS(
|
|
2452
|
+
"http://www.w3.org/2000/svg",
|
|
2453
|
+
"mask"
|
|
2454
|
+
);
|
|
2455
|
+
mask.id = "rivia-backdrop-mask";
|
|
2456
|
+
const rect = document.createElementNS(
|
|
2457
|
+
"http://www.w3.org/2000/svg",
|
|
2458
|
+
"rect"
|
|
2459
|
+
);
|
|
2460
|
+
rect.setAttribute("width", "100%");
|
|
2461
|
+
rect.setAttribute("height", "100%");
|
|
2462
|
+
rect.setAttribute("fill", "white");
|
|
2463
|
+
mask.appendChild(rect);
|
|
2464
|
+
const clearRect = document.createElementNS(
|
|
2465
|
+
"http://www.w3.org/2000/svg",
|
|
2466
|
+
"rect"
|
|
2467
|
+
);
|
|
2468
|
+
clearRect.setAttribute("x", Math.max(0, targetRect.left - padding));
|
|
2469
|
+
clearRect.setAttribute("y", Math.max(0, targetRect.top - padding));
|
|
2470
|
+
clearRect.setAttribute("width", targetRect.width + padding * 2);
|
|
2471
|
+
clearRect.setAttribute("height", targetRect.height + padding * 2);
|
|
2472
|
+
clearRect.setAttribute("fill", "black");
|
|
2473
|
+
clearRect.setAttribute("rx", "8");
|
|
2474
|
+
mask.appendChild(clearRect);
|
|
2475
|
+
defs.appendChild(mask);
|
|
2476
|
+
svg.appendChild(defs);
|
|
2477
|
+
const overlayColor = backdropType === "light overlay" ? "rgba(255, 255, 255, 0.6)" : "rgba(0, 0, 0, 0.7)";
|
|
2478
|
+
const maskedRect = document.createElementNS(
|
|
2479
|
+
"http://www.w3.org/2000/svg",
|
|
2480
|
+
"rect"
|
|
2481
|
+
);
|
|
2482
|
+
maskedRect.setAttribute("width", "100%");
|
|
2483
|
+
maskedRect.setAttribute("height", "100%");
|
|
2484
|
+
maskedRect.setAttribute("fill", overlayColor);
|
|
2485
|
+
maskedRect.setAttribute("mask", "url(#rivia-backdrop-mask)");
|
|
2486
|
+
svg.appendChild(maskedRect);
|
|
2487
|
+
document.body.appendChild(svg);
|
|
2488
|
+
const updateBackdrop = () => {
|
|
2489
|
+
const newRect = targetElement.getBoundingClientRect();
|
|
2490
|
+
clearRect.setAttribute("x", Math.max(0, newRect.left - padding));
|
|
2491
|
+
clearRect.setAttribute("y", Math.max(0, newRect.top - padding));
|
|
2492
|
+
clearRect.setAttribute("width", newRect.width + padding * 2);
|
|
2493
|
+
clearRect.setAttribute("height", newRect.height + padding * 2);
|
|
2494
|
+
};
|
|
2495
|
+
window.addEventListener("scroll", updateBackdrop, { passive: true });
|
|
2496
|
+
window.addEventListener("resize", updateBackdrop);
|
|
2497
|
+
svg.updateBackdrop = updateBackdrop;
|
|
2498
|
+
} catch (err) {
|
|
2499
|
+
console.warn("Error previewing backdrop:", err);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
async function showWelcomeCardPreview(step, stepIndex) {
|
|
2503
|
+
if (!step) {
|
|
2504
|
+
console.warn("Step not found for preview");
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
console.log("Showing welcome card preview for step:", step);
|
|
2508
|
+
cleanupAllOverlays();
|
|
2509
|
+
document.querySelectorAll('[id*="rivia-welcome-preview"]').forEach((el) => el.remove());
|
|
2510
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
2511
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
2512
|
+
if (backdropStyle !== "none") {
|
|
2513
|
+
const backdropOverlay = document.createElement("div");
|
|
2514
|
+
backdropOverlay.id = "rivia-welcome-preview-backdrop";
|
|
2515
|
+
backdropOverlay.style.cssText = `
|
|
2516
|
+
position: fixed;
|
|
2517
|
+
inset: 0;
|
|
2518
|
+
z-index: 2147483643;
|
|
2519
|
+
pointer-events: none;
|
|
2520
|
+
`;
|
|
2521
|
+
if (backdropStyle === "boxed") {
|
|
2522
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
2523
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
2524
|
+
} else if (backdropStyle === "light overlay") {
|
|
2525
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
2526
|
+
backdropOverlay.style.border = "none";
|
|
2527
|
+
} else if (backdropStyle === "dark overlay") {
|
|
2528
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
2529
|
+
backdropOverlay.style.border = "none";
|
|
2530
|
+
}
|
|
2531
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
2532
|
+
}
|
|
2533
|
+
const overlay2 = document.createElement("div");
|
|
2534
|
+
overlay2.id = "rivia-welcome-preview-overlay";
|
|
2535
|
+
overlay2.style.cssText = `
|
|
2536
|
+
position: fixed;
|
|
2537
|
+
inset: 0;
|
|
2538
|
+
background: rgba(0, 0, 0, 0.5);
|
|
2539
|
+
display: flex;
|
|
2540
|
+
align-items: center;
|
|
2541
|
+
justify-content: center;
|
|
2542
|
+
z-index: 2147483644;
|
|
2543
|
+
`;
|
|
2544
|
+
const modal = document.createElement("div");
|
|
2545
|
+
modal.id = "rivia-welcome-preview-modal";
|
|
2546
|
+
const bgColor = step.welcome_bg_color || "#ffffff";
|
|
2547
|
+
modal.style.cssText = `
|
|
2548
|
+
background: ${bgColor};
|
|
2549
|
+
border-radius: 12px;
|
|
2550
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
2551
|
+
max-width: 700px;
|
|
2552
|
+
width: 90%;
|
|
2553
|
+
max-height: 80vh;
|
|
2554
|
+
overflow-y: auto;
|
|
2555
|
+
padding: 0;
|
|
2556
|
+
`;
|
|
2557
|
+
const headerSection = document.createElement("div");
|
|
2558
|
+
const headerBgColor = step.welcome_header_bg_color || "#667eea";
|
|
2559
|
+
const headerTextColor = step.welcome_header_text_color || "#ffffff";
|
|
2560
|
+
const headerHeight = step.welcome_header_height || 80;
|
|
2561
|
+
headerSection.style.cssText = `
|
|
2562
|
+
background: ${headerBgColor};
|
|
2563
|
+
padding: ${headerHeight / 2}px 30px;
|
|
2564
|
+
color: ${headerTextColor};
|
|
2565
|
+
border-radius: 12px 12px 0 0;
|
|
2566
|
+
text-align: center;
|
|
2567
|
+
min-height: ${headerHeight}px;
|
|
2568
|
+
display: flex;
|
|
2569
|
+
align-items: center;
|
|
2570
|
+
justify-content: center;
|
|
2571
|
+
`;
|
|
2572
|
+
headerSection.id = "rivia-welcome-preview-header";
|
|
2573
|
+
const headerText = document.createElement("h1");
|
|
2574
|
+
headerText.textContent = step.title || "Welcome!";
|
|
2575
|
+
headerText.style.cssText = `
|
|
2576
|
+
margin: 0;
|
|
2577
|
+
font-size: 32px;
|
|
2578
|
+
font-weight: bold;
|
|
2579
|
+
font-family: inherit;
|
|
2580
|
+
color: ${headerTextColor};
|
|
2581
|
+
`;
|
|
2582
|
+
headerSection.appendChild(headerText);
|
|
2583
|
+
modal.appendChild(headerSection);
|
|
2584
|
+
const contentSection = document.createElement("div");
|
|
2585
|
+
const footerPadding = step.welcome_footer_padding || 20;
|
|
2586
|
+
const footerBgColor = step.welcome_footer_bg_color || "#ffffff";
|
|
2587
|
+
const footerTextColor = step.welcome_footer_text_color || "#333333";
|
|
2588
|
+
const footerHeight = step.welcome_footer_height || 60;
|
|
2589
|
+
contentSection.style.cssText = `
|
|
2590
|
+
padding: ${footerPadding}px 30px;
|
|
2591
|
+
text-align: center;
|
|
2592
|
+
background: ${footerBgColor};
|
|
2593
|
+
color: ${footerTextColor};
|
|
2594
|
+
min-height: ${footerHeight}px;
|
|
2595
|
+
display: flex;
|
|
2596
|
+
align-items: center;
|
|
2597
|
+
justify-content: center;
|
|
2598
|
+
`;
|
|
2599
|
+
contentSection.id = "rivia-welcome-preview-content";
|
|
2600
|
+
const descriptionText = document.createElement("p");
|
|
2601
|
+
descriptionText.textContent = step.content || "Welcome message";
|
|
2602
|
+
descriptionText.style.cssText = `
|
|
2603
|
+
margin: 0;
|
|
2604
|
+
font-size: 14px;
|
|
2605
|
+
line-height: 1.6;
|
|
2606
|
+
color: ${footerTextColor};
|
|
2607
|
+
white-space: pre-wrap;
|
|
2608
|
+
word-wrap: break-word;
|
|
2609
|
+
font-family: inherit;
|
|
2610
|
+
`;
|
|
2611
|
+
contentSection.appendChild(descriptionText);
|
|
2612
|
+
modal.appendChild(contentSection);
|
|
2613
|
+
const buttonSection = document.createElement("div");
|
|
2614
|
+
buttonSection.style.cssText = `
|
|
2615
|
+
display: flex;
|
|
2616
|
+
gap: 12px;
|
|
2617
|
+
padding: 20px 30px;
|
|
2618
|
+
border-top: 1px solid #e5e7eb;
|
|
2619
|
+
justify-content: flex-end;
|
|
2620
|
+
`;
|
|
2621
|
+
const skipBtn = document.createElement("button");
|
|
2622
|
+
skipBtn.textContent = step.welcome_skip_label || "Skip";
|
|
2623
|
+
skipBtn.style.cssText = `
|
|
2624
|
+
padding: 8px 16px;
|
|
2625
|
+
border: 1px solid #d1d5db;
|
|
2626
|
+
border-radius: 6px;
|
|
2627
|
+
background: white;
|
|
2628
|
+
color: #6b7280;
|
|
2629
|
+
cursor: pointer;
|
|
2630
|
+
font-size: 14px;
|
|
2631
|
+
font-weight: 500;
|
|
2632
|
+
outline: none;
|
|
2633
|
+
transition: all 0.2s ease;
|
|
2634
|
+
`;
|
|
2635
|
+
skipBtn.onmouseover = () => {
|
|
2636
|
+
skipBtn.style.background = "#f3f4f6";
|
|
2637
|
+
};
|
|
2638
|
+
skipBtn.onmouseout = () => {
|
|
2639
|
+
skipBtn.style.background = "white";
|
|
2640
|
+
};
|
|
2641
|
+
skipBtn.onclick = () => {
|
|
2642
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2643
|
+
overlay2.remove();
|
|
2644
|
+
const backdropOverlay = document.getElementById(
|
|
2645
|
+
"rivia-welcome-preview-backdrop"
|
|
2646
|
+
);
|
|
2647
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2648
|
+
if (advanceAction === "skip button") {
|
|
2649
|
+
endTour();
|
|
2650
|
+
} else {
|
|
2651
|
+
endTour();
|
|
2652
|
+
}
|
|
2653
|
+
};
|
|
2654
|
+
buttonSection.appendChild(skipBtn);
|
|
2655
|
+
const nextBtn = document.createElement("button");
|
|
2656
|
+
nextBtn.textContent = step.welcome_next_label || "Next";
|
|
2657
|
+
nextBtn.style.cssText = `
|
|
2658
|
+
padding: 8px 16px;
|
|
2659
|
+
border: none;
|
|
2660
|
+
border-radius: 6px;
|
|
2661
|
+
background: #2563eb;
|
|
2662
|
+
color: white;
|
|
2663
|
+
cursor: pointer;
|
|
2664
|
+
font-size: 14px;
|
|
2665
|
+
font-weight: 500;
|
|
2666
|
+
outline: none;
|
|
2667
|
+
transition: all 0.2s ease;
|
|
2668
|
+
`;
|
|
2669
|
+
nextBtn.onmouseover = () => {
|
|
2670
|
+
nextBtn.style.background = "#1d4ed8";
|
|
2671
|
+
};
|
|
2672
|
+
nextBtn.onmouseout = () => {
|
|
2673
|
+
nextBtn.style.background = "#2563eb";
|
|
2674
|
+
};
|
|
2675
|
+
nextBtn.onclick = async () => {
|
|
2676
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2677
|
+
overlay2.remove();
|
|
2678
|
+
const backdropOverlay = document.getElementById(
|
|
2679
|
+
"rivia-welcome-preview-backdrop"
|
|
2680
|
+
);
|
|
2681
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2682
|
+
if (advanceAction === "next button") {
|
|
2683
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2684
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2685
|
+
showStep(STATE.tourIndex, true);
|
|
2686
|
+
} else {
|
|
2687
|
+
endTour();
|
|
2688
|
+
}
|
|
2689
|
+
} else if (advanceAction === "scroll") {
|
|
2690
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2691
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2692
|
+
const nextStep2 = STATE.tips[STATE.tourIndex];
|
|
2693
|
+
const nextElement = await findBySelector(nextStep2.selector);
|
|
2694
|
+
if (nextElement) {
|
|
2695
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
2696
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
2697
|
+
} else {
|
|
2698
|
+
showStep(STATE.tourIndex, true);
|
|
2699
|
+
}
|
|
2700
|
+
} else {
|
|
2701
|
+
endTour();
|
|
2702
|
+
}
|
|
2703
|
+
} else if (advanceAction === "click") {
|
|
2704
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2705
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2706
|
+
showStep(STATE.tourIndex, true);
|
|
2707
|
+
} else {
|
|
2708
|
+
endTour();
|
|
2709
|
+
}
|
|
2710
|
+
} else {
|
|
2711
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2712
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2713
|
+
showStep(STATE.tourIndex, true);
|
|
2714
|
+
} else {
|
|
2715
|
+
endTour();
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
};
|
|
2719
|
+
buttonSection.appendChild(nextBtn);
|
|
2720
|
+
modal.appendChild(buttonSection);
|
|
2721
|
+
overlay2.appendChild(modal);
|
|
2722
|
+
document.body.appendChild(overlay2);
|
|
2723
|
+
overlay2.onclick = (e) => {
|
|
2724
|
+
if (e.target === overlay2) {
|
|
2725
|
+
e.stopPropagation();
|
|
2726
|
+
overlay2.remove();
|
|
2727
|
+
const backdropOverlay = document.getElementById(
|
|
2728
|
+
"rivia-welcome-preview-backdrop"
|
|
2729
|
+
);
|
|
2730
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2731
|
+
}
|
|
2732
|
+
};
|
|
2733
|
+
modal.onclick = (e) => {
|
|
2734
|
+
e.stopPropagation();
|
|
2735
|
+
};
|
|
2736
|
+
console.log(
|
|
2737
|
+
"Welcome card preview displayed with backdrop:",
|
|
2738
|
+
backdropStyle,
|
|
2739
|
+
"and advance action:",
|
|
2740
|
+
step.basic_advanceAction
|
|
2741
|
+
);
|
|
2742
|
+
}
|
|
2743
|
+
async function showModalDialogPreview(step, stepIndex) {
|
|
2744
|
+
const existingCenteredModal = document.getElementById(
|
|
2745
|
+
"rivia-modal-dialog-preview-modal"
|
|
2746
|
+
);
|
|
2747
|
+
if (existingCenteredModal) existingCenteredModal.remove();
|
|
2748
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
2749
|
+
if (backdropStyle !== "none") {
|
|
2750
|
+
const backdropOverlay = document.createElement("div");
|
|
2751
|
+
backdropOverlay.id = "rivia-modal-dialog-preview-backdrop";
|
|
2752
|
+
backdropOverlay.style.cssText = `
|
|
2753
|
+
position: fixed;
|
|
2754
|
+
inset: 0;
|
|
2755
|
+
z-index: 2147483643;
|
|
2756
|
+
pointer-events: none;
|
|
2757
|
+
`;
|
|
2758
|
+
if (backdropStyle === "boxed") {
|
|
2759
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
2760
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
2761
|
+
} else if (backdropStyle === "light overlay") {
|
|
2762
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
2763
|
+
backdropOverlay.style.border = "none";
|
|
2764
|
+
} else if (backdropStyle === "dark overlay") {
|
|
2765
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
2766
|
+
backdropOverlay.style.border = "none";
|
|
2767
|
+
}
|
|
2768
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
2769
|
+
}
|
|
2770
|
+
const centeredContainer = document.createElement("div");
|
|
2771
|
+
centeredContainer.id = "rivia-modal-dialog-preview-modal";
|
|
2772
|
+
centeredContainer.style.cssText = `
|
|
2773
|
+
position: fixed;
|
|
2774
|
+
inset: 0;
|
|
2775
|
+
display: flex;
|
|
2776
|
+
align-items: center;
|
|
2777
|
+
justify-content: center;
|
|
2778
|
+
z-index: 2147483644;
|
|
2779
|
+
pointer-events: none;
|
|
2780
|
+
`;
|
|
2781
|
+
const modal = document.createElement("div");
|
|
2782
|
+
modal.id = "rivia-modal-dialog-preview";
|
|
2783
|
+
const modalWidth = step.modal_width || 500;
|
|
2784
|
+
const modalHeight = step.modal_height || 400;
|
|
2785
|
+
const modalBgColor = step.modal_bg_color || "#ffffff";
|
|
2786
|
+
const modalTextColor = step.modal_text_color || "#333333";
|
|
2787
|
+
const modalFooterBgColor = step.modal_footer_bg_color || "#f3f4f6";
|
|
2788
|
+
const accentColor = step.modal_accent_color || "#10b981";
|
|
2789
|
+
modal.style.cssText = `
|
|
2790
|
+
pointer-events: auto;
|
|
2791
|
+
background: ${modalBgColor};
|
|
2792
|
+
border-radius: 12px;
|
|
2793
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
2794
|
+
width: ${modalWidth}px;
|
|
2795
|
+
max-width: 90vw;
|
|
2796
|
+
height: ${modalHeight}px;
|
|
2797
|
+
max-height: 80vh;
|
|
2798
|
+
overflow-y: auto;
|
|
2799
|
+
padding: 0;
|
|
2800
|
+
display: flex;
|
|
2801
|
+
flex-direction: column;
|
|
2802
|
+
`;
|
|
2803
|
+
const accentLine = document.createElement("div");
|
|
2804
|
+
accentLine.style.cssText = `
|
|
2805
|
+
height: 4px;
|
|
2806
|
+
background: ${accentColor};
|
|
2807
|
+
border-radius: 12px 12px 0 0;
|
|
2808
|
+
`;
|
|
2809
|
+
modal.appendChild(accentLine);
|
|
2810
|
+
const contentSection = document.createElement("div");
|
|
2811
|
+
contentSection.style.cssText = `
|
|
2812
|
+
flex: 1;
|
|
2813
|
+
padding: 30px;
|
|
2814
|
+
color: ${modalTextColor};
|
|
2815
|
+
overflow-y: auto;
|
|
2816
|
+
white-space: pre-wrap;
|
|
2817
|
+
word-wrap: break-word;
|
|
2818
|
+
`;
|
|
2819
|
+
contentSection.textContent = step.content || "Type your content here.";
|
|
2820
|
+
modal.appendChild(contentSection);
|
|
2821
|
+
const footerSection = document.createElement("div");
|
|
2822
|
+
footerSection.style.cssText = `
|
|
2823
|
+
background: ${modalFooterBgColor};
|
|
2824
|
+
padding: 20px 30px;
|
|
2825
|
+
border-top: 1px solid #e5e7eb;
|
|
2826
|
+
border-radius: 0 0 12px 12px;
|
|
2827
|
+
display: flex;
|
|
2828
|
+
justify-content: flex-end;
|
|
2829
|
+
gap: 12px;
|
|
2830
|
+
`;
|
|
2831
|
+
const skipBtn = document.createElement("button");
|
|
2832
|
+
skipBtn.textContent = step.modal_skip_label || "Skip";
|
|
2833
|
+
skipBtn.style.cssText = `
|
|
2834
|
+
background: transparent;
|
|
2835
|
+
color: #9ca3af;
|
|
2836
|
+
border: none;
|
|
2837
|
+
padding: 10px 20px;
|
|
2838
|
+
border-radius: 6px;
|
|
2839
|
+
font-size: 14px;
|
|
2840
|
+
font-weight: 500;
|
|
2841
|
+
cursor: pointer;
|
|
2842
|
+
transition: all 0.2s;
|
|
2843
|
+
`;
|
|
2844
|
+
skipBtn.onmouseover = () => {
|
|
2845
|
+
skipBtn.style.color = "#6b7280";
|
|
2846
|
+
skipBtn.style.background = "#f3f4f6";
|
|
2847
|
+
};
|
|
2848
|
+
skipBtn.onmouseout = () => {
|
|
2849
|
+
skipBtn.style.color = "#9ca3af";
|
|
2850
|
+
skipBtn.style.background = "transparent";
|
|
2851
|
+
};
|
|
2852
|
+
skipBtn.onclick = () => {
|
|
2853
|
+
centeredContainer.remove();
|
|
2854
|
+
const backdropOverlay = document.getElementById(
|
|
2855
|
+
"rivia-modal-dialog-preview-backdrop"
|
|
2856
|
+
);
|
|
2857
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2858
|
+
endTour();
|
|
2859
|
+
};
|
|
2860
|
+
footerSection.appendChild(skipBtn);
|
|
2861
|
+
const nextBtn = document.createElement("button");
|
|
2862
|
+
nextBtn.textContent = step.modal_next_label || "Next";
|
|
2863
|
+
nextBtn.style.cssText = `
|
|
2864
|
+
background: #2563eb;
|
|
2865
|
+
color: white;
|
|
2866
|
+
border: none;
|
|
2867
|
+
padding: 10px 24px;
|
|
2868
|
+
border-radius: 6px;
|
|
2869
|
+
font-size: 14px;
|
|
2870
|
+
font-weight: 600;
|
|
2871
|
+
cursor: pointer;
|
|
2872
|
+
transition: all 0.2s;
|
|
2873
|
+
`;
|
|
2874
|
+
nextBtn.onmouseover = () => nextBtn.style.background = "#1d4ed8";
|
|
2875
|
+
nextBtn.onmouseout = () => nextBtn.style.background = "#2563eb";
|
|
2876
|
+
nextBtn.onclick = async () => {
|
|
2877
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
2878
|
+
centeredContainer.remove();
|
|
2879
|
+
const backdropOverlay = document.getElementById(
|
|
2880
|
+
"rivia-modal-dialog-preview-backdrop"
|
|
2881
|
+
);
|
|
2882
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
2883
|
+
if (advanceAction === "next button") {
|
|
2884
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2885
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2886
|
+
showStep(STATE.tourIndex, true);
|
|
2887
|
+
} else {
|
|
2888
|
+
endTour();
|
|
2889
|
+
}
|
|
2890
|
+
} else if (advanceAction === "scroll") {
|
|
2891
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2892
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2893
|
+
const nextStepData = STATE.tips[STATE.tourIndex];
|
|
2894
|
+
const nextElement = await findBySelector(nextStepData.selector);
|
|
2895
|
+
if (nextElement) {
|
|
2896
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
2897
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
2898
|
+
} else {
|
|
2899
|
+
showStep(STATE.tourIndex, true);
|
|
2900
|
+
}
|
|
2901
|
+
} else {
|
|
2902
|
+
endTour();
|
|
2903
|
+
}
|
|
2904
|
+
} else if (advanceAction === "click") {
|
|
2905
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2906
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2907
|
+
showStep(STATE.tourIndex, true);
|
|
2908
|
+
} else {
|
|
2909
|
+
endTour();
|
|
2910
|
+
}
|
|
2911
|
+
} else {
|
|
2912
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
2913
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
2914
|
+
showStep(STATE.tourIndex, true);
|
|
2915
|
+
} else {
|
|
2916
|
+
endTour();
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
};
|
|
2920
|
+
footerSection.appendChild(nextBtn);
|
|
2921
|
+
modal.appendChild(footerSection);
|
|
2922
|
+
centeredContainer.appendChild(modal);
|
|
2923
|
+
document.body.appendChild(centeredContainer);
|
|
2924
|
+
console.log(
|
|
2925
|
+
"Modal dialog preview displayed with backdrop:",
|
|
2926
|
+
backdropStyle,
|
|
2927
|
+
"and advance action:",
|
|
2928
|
+
step.basic_advanceAction
|
|
2929
|
+
);
|
|
2930
|
+
}
|
|
2931
|
+
async function attachNavigationButtons(tip, i, isPreview) {
|
|
2932
|
+
const nav = document.createElement("div");
|
|
2933
|
+
const navStyle = isPreview ? `
|
|
2934
|
+
display: flex;
|
|
2935
|
+
gap: 8px;
|
|
2936
|
+
margin-top: 12px;
|
|
2937
|
+
justify-content: flex-end;
|
|
2938
|
+
` : `
|
|
2939
|
+
display: flex;
|
|
2940
|
+
gap: 6px;
|
|
2941
|
+
margin-top: 8px;
|
|
2942
|
+
justify-content: flex-end;
|
|
2943
|
+
`;
|
|
2944
|
+
nav.style.cssText = navStyle;
|
|
2945
|
+
const step = STATE.tips[i];
|
|
2946
|
+
const advanceAction = step?.basic_advanceAction || "next button";
|
|
2947
|
+
const card_back_button = step?.card_back_button ?? false;
|
|
2948
|
+
const card_next_button = step?.card_next_button ?? true;
|
|
2949
|
+
const card_skip_button = step?.card_skip_button ?? false;
|
|
2950
|
+
if (i > 0 && card_back_button) {
|
|
2951
|
+
const back = document.createElement("button");
|
|
2952
|
+
back.textContent = "\u2190 Back";
|
|
2953
|
+
const backStyle = isPreview ? `
|
|
2954
|
+
padding: 8px 14px;
|
|
2955
|
+
border-radius: 8px;
|
|
2956
|
+
border: 1px solid rgba(37, 99, 235, 0.3);
|
|
2957
|
+
background: rgba(37, 99, 235, 0.1);
|
|
2958
|
+
color: #2563eb;
|
|
2959
|
+
cursor: pointer;
|
|
2960
|
+
font-size: 13px;
|
|
2961
|
+
font-weight: 500;
|
|
2962
|
+
transition: all 0.2s ease;
|
|
2963
|
+
` : `
|
|
2964
|
+
padding: 6px 10px;
|
|
2965
|
+
border-radius: 8px;
|
|
2966
|
+
border: 1px solid #333;
|
|
2967
|
+
background: #1f1f1f;
|
|
2968
|
+
color: #fff;
|
|
2969
|
+
cursor: pointer;
|
|
2970
|
+
`;
|
|
2971
|
+
back.style.cssText = backStyle;
|
|
2972
|
+
back.onmouseover = () => {
|
|
2973
|
+
if (isPreview) back.style.background = "rgba(37, 99, 235, 0.2)";
|
|
2974
|
+
};
|
|
2975
|
+
back.onmouseout = () => {
|
|
2976
|
+
if (isPreview) back.style.background = "rgba(37, 99, 235, 0.1)";
|
|
2977
|
+
};
|
|
2978
|
+
back.onclick = () => prevStep();
|
|
2979
|
+
nav.appendChild(back);
|
|
2980
|
+
}
|
|
2981
|
+
if (advanceAction === "manual click") {
|
|
2982
|
+
const targetElement = await findBySelector(step.selector);
|
|
2983
|
+
if (targetElement) {
|
|
2984
|
+
attachClickListenerToElement(targetElement);
|
|
2985
|
+
}
|
|
2986
|
+
} else if (advanceAction === "scroll") {
|
|
2987
|
+
const scrollMsg = document.createElement("div");
|
|
2988
|
+
scrollMsg.textContent = "\u2B07\uFE0F Scroll to continue";
|
|
2989
|
+
scrollMsg.style.cssText = `
|
|
2990
|
+
padding: 8px 14px;
|
|
2991
|
+
border-radius: 8px;
|
|
2992
|
+
background: rgba(168, 85, 247, 0.1);
|
|
2993
|
+
color: #a855f7;
|
|
2994
|
+
font-size: 13px;
|
|
2995
|
+
font-weight: 500;
|
|
2996
|
+
align-self: center;
|
|
2997
|
+
`;
|
|
2998
|
+
nav.appendChild(scrollMsg);
|
|
2999
|
+
enableScrollAdvance();
|
|
3000
|
+
} else if (card_next_button) {
|
|
3001
|
+
const next = document.createElement("button");
|
|
3002
|
+
next.textContent = i === STATE.tips.length - 1 ? "Finish \u2713" : "Next \u2192";
|
|
3003
|
+
const nextStyle = isPreview ? `
|
|
3004
|
+
padding: 8px 14px;
|
|
3005
|
+
border-radius: 8px;
|
|
3006
|
+
border: 1px solid rgba(37, 99, 235, 0.5);
|
|
3007
|
+
background: linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%);
|
|
3008
|
+
color: white;
|
|
3009
|
+
cursor: pointer;
|
|
3010
|
+
font-size: 13px;
|
|
3011
|
+
font-weight: 600;
|
|
3012
|
+
transition: all 0.2s ease;
|
|
3013
|
+
` : `
|
|
3014
|
+
padding: 6px 10px;
|
|
3015
|
+
border-radius: 8px;
|
|
3016
|
+
border: 1px solid #333;
|
|
3017
|
+
background: #2563eb;
|
|
3018
|
+
color: #fff;
|
|
3019
|
+
cursor: pointer;
|
|
3020
|
+
`;
|
|
3021
|
+
next.style.cssText = nextStyle;
|
|
3022
|
+
next.onmouseover = () => {
|
|
3023
|
+
if (isPreview)
|
|
3024
|
+
next.style.background = "linear-gradient(135deg, rgba(37, 99, 235, 1) 0%, rgba(37, 99, 235, 0.9) 100%)";
|
|
3025
|
+
};
|
|
3026
|
+
next.onmouseout = () => {
|
|
3027
|
+
if (isPreview)
|
|
3028
|
+
next.style.background = "linear-gradient(135deg, rgba(37, 99, 235, 0.9) 0%, rgba(37, 99, 235, 0.8) 100%)";
|
|
3029
|
+
};
|
|
3030
|
+
next.onclick = () => i === STATE.tips.length - 1 ? endTour() : nextStep();
|
|
3031
|
+
nav.appendChild(next);
|
|
3032
|
+
}
|
|
3033
|
+
if (card_skip_button) {
|
|
3034
|
+
const skip = document.createElement("button");
|
|
3035
|
+
skip.textContent = "Skip";
|
|
3036
|
+
const skipStyle = isPreview ? `
|
|
3037
|
+
padding: 8px 14px;
|
|
3038
|
+
border-radius: 8px;
|
|
3039
|
+
border: 1px solid rgba(168, 85, 247, 0.3);
|
|
3040
|
+
background: rgba(168, 85, 247, 0.1);
|
|
3041
|
+
color: #a855f7;
|
|
3042
|
+
cursor: pointer;
|
|
3043
|
+
font-size: 13px;
|
|
3044
|
+
font-weight: 500;
|
|
3045
|
+
transition: all 0.2s ease;
|
|
3046
|
+
` : `
|
|
3047
|
+
padding: 6px 10px;
|
|
3048
|
+
border-radius: 8px;
|
|
3049
|
+
border: 1px solid #999;
|
|
3050
|
+
background: #f3f4f6;
|
|
3051
|
+
color: #374151;
|
|
3052
|
+
cursor: pointer;
|
|
3053
|
+
`;
|
|
3054
|
+
skip.style.cssText = skipStyle;
|
|
3055
|
+
skip.onmouseover = () => {
|
|
3056
|
+
if (isPreview) skip.style.background = "rgba(168, 85, 247, 0.2)";
|
|
3057
|
+
};
|
|
3058
|
+
skip.onmouseout = () => {
|
|
3059
|
+
if (isPreview) skip.style.background = "rgba(168, 85, 247, 0.1)";
|
|
3060
|
+
};
|
|
3061
|
+
skip.onclick = () => endTour();
|
|
3062
|
+
nav.appendChild(skip);
|
|
3063
|
+
}
|
|
3064
|
+
tip.appendChild(nav);
|
|
3065
|
+
if (isPreview) {
|
|
3066
|
+
tip.setAttribute("data-rivia-preview-nav", "true");
|
|
3067
|
+
}
|
|
3068
|
+
if (isPreview) {
|
|
3069
|
+
const stepIndicator = document.createElement("div");
|
|
3070
|
+
stepIndicator.style.cssText = `
|
|
3071
|
+
position: absolute;
|
|
3072
|
+
top: 8px;
|
|
3073
|
+
right: 12px;
|
|
3074
|
+
font-size: 11px;
|
|
3075
|
+
color: rgba(37, 99, 235, 0.6);
|
|
3076
|
+
font-weight: 500;
|
|
3077
|
+
`;
|
|
3078
|
+
stepIndicator.textContent = `Step ${i + 1} of ${STATE.tips.length}`;
|
|
3079
|
+
tip.appendChild(stepIndicator);
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
async function cleanupAllOverlays() {
|
|
3083
|
+
const welcomeBackdropOverlay = document.getElementById(
|
|
3084
|
+
"rivia-welcome-backdrop-overlay"
|
|
3085
|
+
);
|
|
3086
|
+
if (welcomeBackdropOverlay) {
|
|
3087
|
+
welcomeBackdropOverlay.remove();
|
|
3088
|
+
}
|
|
3089
|
+
const welcomePreviewOverlay = document.getElementById(
|
|
3090
|
+
"rivia-welcome-preview-overlay"
|
|
3091
|
+
);
|
|
3092
|
+
if (welcomePreviewOverlay) {
|
|
3093
|
+
welcomePreviewOverlay.remove();
|
|
3094
|
+
}
|
|
3095
|
+
const backdropOverlay = document.getElementById("rivia-backdrop-overlay");
|
|
3096
|
+
if (backdropOverlay) {
|
|
3097
|
+
if (backdropOverlay.updateBackdrop) {
|
|
3098
|
+
window.removeEventListener("scroll", backdropOverlay.updateBackdrop);
|
|
3099
|
+
window.removeEventListener("resize", backdropOverlay.updateBackdrop);
|
|
3100
|
+
}
|
|
3101
|
+
backdropOverlay.remove();
|
|
3102
|
+
}
|
|
3103
|
+
const spotlightOverlay = document.getElementById("rivia-spotlight-overlay");
|
|
3104
|
+
if (spotlightOverlay) {
|
|
3105
|
+
if (spotlightOverlay.updateSpotlight) {
|
|
3106
|
+
window.removeEventListener("scroll", spotlightOverlay.updateSpotlight);
|
|
3107
|
+
window.removeEventListener("resize", spotlightOverlay.updateSpotlight);
|
|
3108
|
+
}
|
|
3109
|
+
spotlightOverlay.remove();
|
|
3110
|
+
}
|
|
3111
|
+
document.querySelectorAll('[style*="box-shadow: 0 0 0 9999px"]').forEach((el) => {
|
|
3112
|
+
el.remove();
|
|
3113
|
+
});
|
|
3114
|
+
document.querySelectorAll('svg[id*="rivia"]').forEach((svg) => {
|
|
3115
|
+
if (svg.updateSpotlight) {
|
|
3116
|
+
window.removeEventListener("scroll", svg.updateSpotlight);
|
|
3117
|
+
window.removeEventListener("resize", svg.updateSpotlight);
|
|
3118
|
+
}
|
|
3119
|
+
svg.remove();
|
|
3120
|
+
});
|
|
3121
|
+
}
|
|
3122
|
+
function nextStep() {
|
|
3123
|
+
if (STATE.tourIndex < STATE.tips.length - 1) {
|
|
3124
|
+
let getNextStepInfo3 = function(currentIndex2) {
|
|
3125
|
+
if (currentIndex2 >= STATE.tips.length - 1) {
|
|
3126
|
+
return { type: "end", index: currentIndex2 };
|
|
3127
|
+
}
|
|
3128
|
+
const nextStep2 = STATE.tips[currentIndex2 + 1];
|
|
3129
|
+
if (!nextStep2) return { type: "end", index: currentIndex2 };
|
|
3130
|
+
if (nextStep2.targetUrl && nextStep2.targetUrl.trim()) {
|
|
3131
|
+
console.log("WE reached navigation");
|
|
3132
|
+
return { type: "navigate", index: currentIndex2 + 1, url: nextStep2.targetUrl };
|
|
3133
|
+
}
|
|
3134
|
+
if (isStepAvailableOnCurrentPage(nextStep2)) {
|
|
3135
|
+
return { type: "show", index: currentIndex2 + 1 };
|
|
3136
|
+
}
|
|
3137
|
+
return getNextStepInfo3(currentIndex2 + 1);
|
|
3138
|
+
};
|
|
3139
|
+
var getNextStepInfo2 = getNextStepInfo3;
|
|
3140
|
+
const currentIndex = STATE.tourIndex;
|
|
3141
|
+
STATE.tourIndex++;
|
|
3142
|
+
const nextStepData = STATE.tips[STATE.tourIndex];
|
|
3143
|
+
console.log("\u{1F7E2} nextStep called - moving from step", currentIndex, "to", STATE.tourIndex);
|
|
3144
|
+
if (nextStepData.nextUrl && nextStepData.nextUrl.trim()) {
|
|
3145
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
3146
|
+
tourIndex: STATE.tourIndex,
|
|
3147
|
+
tourId: STATE.tour_id,
|
|
3148
|
+
tips: STATE.tips,
|
|
3149
|
+
title: STATE.title || "Untitled Tour",
|
|
3150
|
+
user_var1,
|
|
3151
|
+
publish: STATE.publish
|
|
3152
|
+
}));
|
|
3153
|
+
const navUrl = addTourParamsToUrl(nextStepData.nextUrl, STATE.tour_id);
|
|
3154
|
+
console.log("\u{1F7E2} Saving tour state before navigation to:", nextStepData.nextUrl);
|
|
3155
|
+
window.location.href = nextStepData.nextUrl;
|
|
3156
|
+
return;
|
|
3157
|
+
}
|
|
3158
|
+
const nextStepInfo = getNextStepInfo3(currentIndex);
|
|
3159
|
+
if (nextStepInfo.type === "navigate") {
|
|
3160
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
3161
|
+
tourIndex: nextStepInfo.index,
|
|
3162
|
+
tourId: STATE.tour_id,
|
|
3163
|
+
isPreviewMode: STATE.isPreviewMode,
|
|
3164
|
+
user_var1,
|
|
3165
|
+
tips: STATE.tips,
|
|
3166
|
+
title: STATE.title || "Untitled Tour",
|
|
3167
|
+
publish: STATE.publish
|
|
3168
|
+
}));
|
|
3169
|
+
const navUrl = addTourParamsToUrl(nextStepInfo.url, STATE.tour_id);
|
|
3170
|
+
console.log("\u{1F7E2} Navigating to next step URL:", navUrl);
|
|
3171
|
+
window.location.href = navUrl;
|
|
3172
|
+
return;
|
|
3173
|
+
}
|
|
3174
|
+
cleanupAllOverlays();
|
|
3175
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
3176
|
+
} else if (STATE.tourIndex === STATE.tips.length - 1) {
|
|
3177
|
+
endTour();
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
async function getNextStepInfo(currentIndex) {
|
|
3181
|
+
if (currentIndex >= STATE.tips.length - 1) {
|
|
3182
|
+
return { type: "end", index: currentIndex };
|
|
3183
|
+
}
|
|
3184
|
+
const nextStep2 = STATE.tips[currentIndex + 1];
|
|
3185
|
+
if (!nextStep2) return { type: "end", index: currentIndex };
|
|
3186
|
+
if (nextStep2.targetUrl && nextStep2.targetUrl.trim()) {
|
|
3187
|
+
return { type: "navigate", index: currentIndex + 1, url: nextStep2.targetUrl };
|
|
3188
|
+
}
|
|
3189
|
+
if (isStepAvailableOnCurrentPage(nextStep2)) {
|
|
3190
|
+
return { type: "show", index: currentIndex + 1 };
|
|
3191
|
+
}
|
|
3192
|
+
return getNextStepInfo(currentIndex + 1);
|
|
3193
|
+
}
|
|
3194
|
+
function isStepAvailableOnCurrentPage(step) {
|
|
3195
|
+
if (!step) return false;
|
|
3196
|
+
if (!step.targetUrl || !step.targetUrl.trim()) return true;
|
|
3197
|
+
return urlMatches(step.targetUrl);
|
|
3198
|
+
}
|
|
3199
|
+
function urlMatches(pattern, currentUrl = window.location.href) {
|
|
3200
|
+
if (!pattern || !pattern.trim()) return true;
|
|
3201
|
+
const cleanPattern = pattern.trim();
|
|
3202
|
+
const cleanUrl = currentUrl.trim();
|
|
3203
|
+
if (cleanPattern === cleanUrl) return true;
|
|
3204
|
+
try {
|
|
3205
|
+
const patternUrl = new URL(cleanPattern);
|
|
3206
|
+
const currentPageUrl = new URL(cleanUrl);
|
|
3207
|
+
if (patternUrl.origin === currentPageUrl.origin) {
|
|
3208
|
+
const patternPath = patternUrl.pathname;
|
|
3209
|
+
const currentPath = currentPageUrl.pathname;
|
|
3210
|
+
if (patternPath === "/" || patternPath === "") {
|
|
3211
|
+
return true;
|
|
3212
|
+
}
|
|
3213
|
+
return currentPath.startsWith(patternPath);
|
|
3214
|
+
}
|
|
3215
|
+
} catch (e) {
|
|
3216
|
+
console.warn("Failed to parse URLs for domain matching:", cleanPattern, cleanUrl, e);
|
|
3217
|
+
}
|
|
3218
|
+
if (cleanPattern.includes("*")) {
|
|
3219
|
+
const regexPattern = cleanPattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
3220
|
+
try {
|
|
3221
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
3222
|
+
return regex.test(cleanUrl);
|
|
3223
|
+
} catch (e) {
|
|
3224
|
+
console.warn("Invalid URL pattern:", cleanPattern, e);
|
|
3225
|
+
return false;
|
|
3226
|
+
}
|
|
3227
|
+
}
|
|
3228
|
+
return cleanUrl.includes(cleanPattern);
|
|
3229
|
+
}
|
|
3230
|
+
function addTourParamsToUrl(url, tourId) {
|
|
3231
|
+
if (!url || !tourId) return url;
|
|
3232
|
+
try {
|
|
3233
|
+
const urlObj = new URL(url);
|
|
3234
|
+
return urlObj.toString();
|
|
3235
|
+
} catch (e) {
|
|
3236
|
+
console.warn("Failed to add tour params to URL:", url, e);
|
|
3237
|
+
return url;
|
|
3238
|
+
}
|
|
3239
|
+
}
|
|
3240
|
+
function getPreviousStepInfo(currentIndex) {
|
|
3241
|
+
if (currentIndex <= 0) {
|
|
3242
|
+
return { type: "start", index: 0 };
|
|
3243
|
+
}
|
|
3244
|
+
const prevStep2 = STATE.tips[currentIndex - 1];
|
|
3245
|
+
if (!prevStep2) return { type: "start", index: 0 };
|
|
3246
|
+
if (isStepAvailableOnCurrentPage(prevStep2)) {
|
|
3247
|
+
return { type: "show", index: currentIndex - 1 };
|
|
3248
|
+
}
|
|
3249
|
+
if (prevStep2.targetUrl && prevStep2.targetUrl.trim()) {
|
|
3250
|
+
return { type: "navigate", index: currentIndex - 1, url: prevStep2.targetUrl };
|
|
3251
|
+
}
|
|
3252
|
+
return getPreviousStepInfo(currentIndex - 1);
|
|
3253
|
+
}
|
|
3254
|
+
function prevStep() {
|
|
3255
|
+
if (STATE.tourIndex > 0) {
|
|
3256
|
+
const prevInfo = getPreviousStepInfo(STATE.tourIndex);
|
|
3257
|
+
if (prevInfo.type === "start") {
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
if (prevInfo.type === "navigate") {
|
|
3261
|
+
STATE.tourIndex = prevInfo.index;
|
|
3262
|
+
const prevNavUrl = addTourParamsToUrl(prevInfo.url, STATE.tour_id);
|
|
3263
|
+
sessionStorage.setItem("rivia_tour_state", JSON.stringify({
|
|
3264
|
+
tourIndex: STATE.tourIndex,
|
|
3265
|
+
tourId: STATE.tour_id,
|
|
3266
|
+
user_var1,
|
|
3267
|
+
isPreviewMode: STATE.isPreviewMode,
|
|
3268
|
+
tips: STATE.tips,
|
|
3269
|
+
title: STATE.title,
|
|
3270
|
+
publish: STATE.publish
|
|
3271
|
+
}));
|
|
3272
|
+
console.log(" Navigating to previous step URL:", prevNavUrl);
|
|
3273
|
+
window.location.href = prevNavUrl;
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3276
|
+
if (prevInfo.type === "show") {
|
|
3277
|
+
STATE.tourIndex = prevInfo.index;
|
|
3278
|
+
cleanupAllOverlays();
|
|
3279
|
+
showStep(STATE.tourIndex, STATE.isPreviewMode);
|
|
3280
|
+
}
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
function endTour() {
|
|
3284
|
+
console.log("Ending tour and cleaning up UI elements...");
|
|
3285
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
3286
|
+
STATE.tourIndex = 0;
|
|
3287
|
+
const user_var2 = user_var1;
|
|
3288
|
+
const backendUrl = `https://demoapi.rivia.ai/tours_clients/${STATE.tour_id}`;
|
|
3289
|
+
const payload = {
|
|
3290
|
+
name: user_var2,
|
|
3291
|
+
is_completed: true
|
|
3292
|
+
};
|
|
3293
|
+
fetch(backendUrl, {
|
|
3294
|
+
method: "POST",
|
|
3295
|
+
// <-- FIXED
|
|
3296
|
+
headers: { "Content-Type": "application/json" },
|
|
3297
|
+
credentials: "include",
|
|
3298
|
+
body: JSON.stringify(payload),
|
|
3299
|
+
keepalive: true
|
|
3300
|
+
// allow sending even during unload
|
|
3301
|
+
}).catch((err) => {
|
|
3302
|
+
console.warn("Failed to end tour:", err);
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
3305
|
+
async function updateUrlStatus() {
|
|
3306
|
+
const urlStatus = document.getElementById("rivia-url-status");
|
|
3307
|
+
if (!urlStatus) return;
|
|
3308
|
+
const currentStep = STATE.tips[STATE.tourIndex];
|
|
3309
|
+
if (!currentStep) {
|
|
3310
|
+
urlStatus.textContent = "\u{1F4CD} Current URL";
|
|
3311
|
+
return;
|
|
3312
|
+
}
|
|
3313
|
+
const stepUrlInfo = getStepUrlInfo(currentStep);
|
|
3314
|
+
if (stepUrlInfo) {
|
|
3315
|
+
if (stepUrlInfo.isAvailable) {
|
|
3316
|
+
urlStatus.textContent = "\u2713 On this page";
|
|
3317
|
+
urlStatus.style.color = "#86efac";
|
|
3318
|
+
} else {
|
|
3319
|
+
const shortUrl = stepUrlInfo.targetUrl.length > 30 ? stepUrlInfo.targetUrl.substring(0, 27) + "..." : stepUrlInfo.targetUrl;
|
|
3320
|
+
urlStatus.textContent = "\u{1F4CD} " + shortUrl;
|
|
3321
|
+
urlStatus.style.color = "#fbbf24";
|
|
3322
|
+
}
|
|
3323
|
+
urlStatus.title = stepUrlInfo.displayText;
|
|
3324
|
+
}
|
|
3325
|
+
}
|
|
3326
|
+
function playTour() {
|
|
3327
|
+
if (STATE.is_completed)
|
|
3328
|
+
return;
|
|
3329
|
+
if (!STATE.tips.length) {
|
|
3330
|
+
console.warn("No tips loaded for this host");
|
|
3331
|
+
return;
|
|
3332
|
+
}
|
|
3333
|
+
STATE.savedTourIndex = STATE.tourIndex;
|
|
3334
|
+
STATE.isPreviewMode = true;
|
|
3335
|
+
console.log("\u{1F7E2} Starting tour preview mode...", STATE.tourIndex);
|
|
3336
|
+
updateUrlStatus();
|
|
3337
|
+
console.log("Cleaning up UI elements before preview...");
|
|
3338
|
+
document.querySelectorAll("[data-rivia-tip-id]").forEach((n) => n.remove());
|
|
3339
|
+
document.querySelectorAll('[id*="rivia-welcome-preview"]').forEach((el) => el.remove());
|
|
3340
|
+
document.querySelectorAll('[id*="rivia-welcome-edit"]').forEach((el) => el.remove());
|
|
3341
|
+
document.querySelectorAll('[id*="rivia-modal-dialog"]').forEach((el) => el.remove());
|
|
3342
|
+
const videoSettingsPanel = document.getElementById("rivia-video-settings-panel");
|
|
3343
|
+
if (videoSettingsPanel) {
|
|
3344
|
+
videoSettingsPanel.remove();
|
|
3345
|
+
}
|
|
3346
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
3347
|
+
document.querySelectorAll("[data-rivia-highlight]").forEach((n) => {
|
|
3348
|
+
n.removeAttribute("data-rivia-highlight");
|
|
3349
|
+
n.style.outline = "";
|
|
3350
|
+
n.style.outlineOffset = "";
|
|
3351
|
+
n.style.backgroundColor = "";
|
|
3352
|
+
});
|
|
3353
|
+
try {
|
|
3354
|
+
overlay.remove();
|
|
3355
|
+
} catch (e) {
|
|
3356
|
+
}
|
|
3357
|
+
const rightPanel = document.getElementById("rivia-pointer-card-panel");
|
|
3358
|
+
if (rightPanel) {
|
|
3359
|
+
rightPanel.remove();
|
|
3360
|
+
}
|
|
3361
|
+
console.log("UI cleanup complete, starting preview...");
|
|
3362
|
+
showStep(STATE.tourIndex, true);
|
|
3363
|
+
}
|
|
3364
|
+
function cleanUrlForStorage(url) {
|
|
3365
|
+
if (!url || !url.trim()) return url;
|
|
3366
|
+
try {
|
|
3367
|
+
const urlObj = new URL(url);
|
|
3368
|
+
urlObj.searchParams.delete("rivia_tour");
|
|
3369
|
+
urlObj.searchParams.delete("tour_id");
|
|
3370
|
+
return urlObj.toString();
|
|
3371
|
+
} catch (e) {
|
|
3372
|
+
console.warn("Failed to parse URL:", url, e);
|
|
3373
|
+
return url;
|
|
3374
|
+
}
|
|
3375
|
+
}
|
|
3376
|
+
async function showFeedbackCardPreview(step, stepIndex) {
|
|
3377
|
+
if (!step) {
|
|
3378
|
+
console.warn("Step not found for preview");
|
|
3379
|
+
return;
|
|
3380
|
+
}
|
|
3381
|
+
console.log("Showing feedback card preview for step:", step);
|
|
3382
|
+
cleanupAllOverlays();
|
|
3383
|
+
document.querySelectorAll('[id*="rivia-feedback-preview"]').forEach((el) => el.remove());
|
|
3384
|
+
document.querySelectorAll('[id*="rivia-backdrop"]').forEach((el) => el.remove());
|
|
3385
|
+
const backdropStyle = step.basic_backdrop || "none";
|
|
3386
|
+
if (backdropStyle !== "none") {
|
|
3387
|
+
const backdropOverlay = document.createElement("div");
|
|
3388
|
+
backdropOverlay.id = "rivia-feedback-preview-backdrop";
|
|
3389
|
+
backdropOverlay.style.cssText = `
|
|
3390
|
+
position: fixed;
|
|
3391
|
+
inset: 0;
|
|
3392
|
+
z-index: 2147483643;
|
|
3393
|
+
pointer-events: none;
|
|
3394
|
+
`;
|
|
3395
|
+
if (backdropStyle === "boxed") {
|
|
3396
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.1)";
|
|
3397
|
+
backdropOverlay.style.border = "2px solid rgba(0, 0, 0, 0.2)";
|
|
3398
|
+
} else if (backdropStyle === "light overlay") {
|
|
3399
|
+
backdropOverlay.style.background = "rgba(255, 255, 255, 0.7)";
|
|
3400
|
+
backdropOverlay.style.border = "none";
|
|
3401
|
+
} else if (backdropStyle === "dark overlay") {
|
|
3402
|
+
backdropOverlay.style.background = "rgba(0, 0, 0, 0.7)";
|
|
3403
|
+
backdropOverlay.style.border = "none";
|
|
3404
|
+
}
|
|
3405
|
+
document.body.insertBefore(backdropOverlay, document.body.firstChild);
|
|
3406
|
+
}
|
|
3407
|
+
const overlay2 = document.createElement("div");
|
|
3408
|
+
overlay2.id = "rivia-feedback-preview-overlay";
|
|
3409
|
+
overlay2.style.cssText = `
|
|
3410
|
+
position: fixed;
|
|
3411
|
+
inset: 0;
|
|
3412
|
+
background: rgba(0, 0, 0, 0.5);
|
|
3413
|
+
display: flex;
|
|
3414
|
+
align-items: center;
|
|
3415
|
+
justify-content: center;
|
|
3416
|
+
z-index: 2147483644;
|
|
3417
|
+
`;
|
|
3418
|
+
const modal = document.createElement("div");
|
|
3419
|
+
modal.id = "rivia-feedback-preview-modal";
|
|
3420
|
+
const bgColor = step.feedback_bg_color || "#ffffff";
|
|
3421
|
+
modal.style.cssText = `
|
|
3422
|
+
background: ${bgColor};
|
|
3423
|
+
border-radius: 12px;
|
|
3424
|
+
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
3425
|
+
max-width: 700px;
|
|
3426
|
+
width: 90%;
|
|
3427
|
+
max-height: 80vh;
|
|
3428
|
+
overflow-y: auto;
|
|
3429
|
+
padding: 0;
|
|
3430
|
+
`;
|
|
3431
|
+
const headerSection = document.createElement("div");
|
|
3432
|
+
const headerBgColor = step.feedback_header_bg_color || "#667eea";
|
|
3433
|
+
const headerTextColor = step.feedback_header_text_color || "#ffffff";
|
|
3434
|
+
const headerHeight = step.feedback_header_height || 80;
|
|
3435
|
+
headerSection.style.cssText = `
|
|
3436
|
+
background: ${headerBgColor};
|
|
3437
|
+
padding: ${headerHeight / 2}px 30px;
|
|
3438
|
+
color: ${headerTextColor};
|
|
3439
|
+
border-radius: 12px 12px 0 0;
|
|
3440
|
+
text-align: center;
|
|
3441
|
+
min-height: ${headerHeight}px;
|
|
3442
|
+
display: flex;
|
|
3443
|
+
align-items: center;
|
|
3444
|
+
justify-content: center;
|
|
3445
|
+
`;
|
|
3446
|
+
headerSection.id = "rivia-feedback-preview-header";
|
|
3447
|
+
const headerText = document.createElement("h1");
|
|
3448
|
+
headerText.textContent = step.title || "How was your experience?";
|
|
3449
|
+
headerText.style.cssText = `
|
|
3450
|
+
margin: 0;
|
|
3451
|
+
font-size: 32px;
|
|
3452
|
+
font-weight: bold;
|
|
3453
|
+
font-family: inherit;
|
|
3454
|
+
color: ${headerTextColor};
|
|
3455
|
+
`;
|
|
3456
|
+
headerSection.appendChild(headerText);
|
|
3457
|
+
modal.appendChild(headerSection);
|
|
3458
|
+
const contentSection = document.createElement("div");
|
|
3459
|
+
const footerPadding = step.feedback_footer_padding || 20;
|
|
3460
|
+
const footerBgColor = step.feedback_footer_bg_color || "#ffffff";
|
|
3461
|
+
const footerTextColor = step.feedback_footer_text_color || "#333333";
|
|
3462
|
+
const footerHeight = step.feedback_footer_height || 60;
|
|
3463
|
+
contentSection.style.cssText = `
|
|
3464
|
+
padding: ${footerPadding}px 30px;
|
|
3465
|
+
text-align: center;
|
|
3466
|
+
background: ${footerBgColor};
|
|
3467
|
+
color: ${footerTextColor};
|
|
3468
|
+
min-height: ${footerHeight}px;
|
|
3469
|
+
display: flex;
|
|
3470
|
+
flex-direction: column;
|
|
3471
|
+
gap: 20px;
|
|
3472
|
+
`;
|
|
3473
|
+
contentSection.id = "rivia-feedback-preview-content";
|
|
3474
|
+
const questionText = document.createElement("p");
|
|
3475
|
+
questionText.textContent = step.content || "Please rate your experience";
|
|
3476
|
+
questionText.style.cssText = `
|
|
3477
|
+
margin: 0;
|
|
3478
|
+
font-size: 14px;
|
|
3479
|
+
line-height: 1.6;
|
|
3480
|
+
color: ${footerTextColor};
|
|
3481
|
+
white-space: pre-wrap;
|
|
3482
|
+
word-wrap: break-word;
|
|
3483
|
+
font-family: inherit;
|
|
3484
|
+
`;
|
|
3485
|
+
contentSection.appendChild(questionText);
|
|
3486
|
+
const emojiContainer = document.createElement("div");
|
|
3487
|
+
emojiContainer.style.cssText = `
|
|
3488
|
+
display: flex;
|
|
3489
|
+
justify-content: center;
|
|
3490
|
+
gap: 12px;
|
|
3491
|
+
flex-wrap: wrap;
|
|
3492
|
+
`;
|
|
3493
|
+
let selectedEmojiIndex = -1;
|
|
3494
|
+
const emojis = step.feedback_emojis || ["\u{1F620}", "\u{1F615}", "\u{1F610}", "\u{1F60A}", "\u{1F604}"];
|
|
3495
|
+
const currentEmoji = step.feedback_emoji || "\u{1F60A}";
|
|
3496
|
+
const displayEmojis = emojis;
|
|
3497
|
+
displayEmojis.forEach((emoji, index) => {
|
|
3498
|
+
const emojiBtn = document.createElement("button");
|
|
3499
|
+
emojiBtn.textContent = emoji;
|
|
3500
|
+
emojiBtn.style.cssText = `
|
|
3501
|
+
font-size: 32px;
|
|
3502
|
+
background: ${emoji === currentEmoji ? "rgba(102, 126, 234, 0.2)" : "transparent"};
|
|
3503
|
+
border: ${emoji === currentEmoji ? "2px solid #667eea" : "2px solid #e5e7eb"};
|
|
3504
|
+
border-radius: 8px;
|
|
3505
|
+
padding: 8px 12px;
|
|
3506
|
+
cursor: pointer;
|
|
3507
|
+
transition: all 0.2s ease;
|
|
3508
|
+
`;
|
|
3509
|
+
emojiBtn.onmouseover = () => {
|
|
3510
|
+
if (emoji !== currentEmoji) {
|
|
3511
|
+
emojiBtn.style.borderColor = "#667eea";
|
|
3512
|
+
emojiBtn.style.background = "rgba(102, 126, 234, 0.1)";
|
|
3513
|
+
}
|
|
3514
|
+
};
|
|
3515
|
+
emojiBtn.onmouseout = () => {
|
|
3516
|
+
if (emoji !== currentEmoji) {
|
|
3517
|
+
emojiBtn.style.borderColor = "#e5e7eb";
|
|
3518
|
+
emojiBtn.style.background = "transparent";
|
|
3519
|
+
}
|
|
3520
|
+
};
|
|
3521
|
+
emojiBtn.onclick = () => {
|
|
3522
|
+
selectedEmojiIndex = index + 1;
|
|
3523
|
+
document.querySelectorAll("[data-feedback-emoji-btn]").forEach((btn) => {
|
|
3524
|
+
const btnEmoji = btn.textContent;
|
|
3525
|
+
if (btnEmoji === emoji) {
|
|
3526
|
+
btn.style.background = "rgba(102, 126, 234, 0.2)";
|
|
3527
|
+
btn.style.borderColor = "#667eea";
|
|
3528
|
+
} else {
|
|
3529
|
+
btn.style.background = "transparent";
|
|
3530
|
+
btn.style.borderColor = "#e5e7eb";
|
|
3531
|
+
}
|
|
3532
|
+
});
|
|
3533
|
+
};
|
|
3534
|
+
emojiBtn.setAttribute("data-feedback-emoji-btn", emoji);
|
|
3535
|
+
emojiBtn.setAttribute("data-emoji-index", index);
|
|
3536
|
+
emojiContainer.appendChild(emojiBtn);
|
|
3537
|
+
});
|
|
3538
|
+
contentSection.appendChild(emojiContainer);
|
|
3539
|
+
modal.appendChild(contentSection);
|
|
3540
|
+
const buttonSection = document.createElement("div");
|
|
3541
|
+
buttonSection.style.cssText = `
|
|
3542
|
+
display: flex;
|
|
3543
|
+
gap: 12px;
|
|
3544
|
+
padding: 20px 30px;
|
|
3545
|
+
border-top: 1px solid #e5e7eb;
|
|
3546
|
+
justify-content: flex-end;
|
|
3547
|
+
`;
|
|
3548
|
+
const skipBtn = document.createElement("button");
|
|
3549
|
+
skipBtn.textContent = step.feedback_skip_label || "Skip";
|
|
3550
|
+
skipBtn.style.cssText = `
|
|
3551
|
+
padding: 8px 16px;
|
|
3552
|
+
border: 1px solid #d1d5db;
|
|
3553
|
+
border-radius: 6px;
|
|
3554
|
+
background: white;
|
|
3555
|
+
color: #6b7280;
|
|
3556
|
+
cursor: pointer;
|
|
3557
|
+
font-size: 14px;
|
|
3558
|
+
font-weight: 500;
|
|
3559
|
+
outline: none;
|
|
3560
|
+
transition: all 0.2s ease;
|
|
3561
|
+
`;
|
|
3562
|
+
skipBtn.onmouseover = () => {
|
|
3563
|
+
skipBtn.style.background = "#f3f4f6";
|
|
3564
|
+
};
|
|
3565
|
+
skipBtn.onmouseout = () => {
|
|
3566
|
+
skipBtn.style.background = "white";
|
|
3567
|
+
};
|
|
3568
|
+
skipBtn.onclick = () => {
|
|
3569
|
+
overlay2.remove();
|
|
3570
|
+
const backdropOverlay = document.getElementById(
|
|
3571
|
+
"rivia-feedback-preview-backdrop"
|
|
3572
|
+
);
|
|
3573
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3574
|
+
endTour();
|
|
3575
|
+
};
|
|
3576
|
+
buttonSection.appendChild(skipBtn);
|
|
3577
|
+
const nextBtn = document.createElement("button");
|
|
3578
|
+
nextBtn.textContent = step.feedback_next_label || "Next";
|
|
3579
|
+
nextBtn.style.cssText = `
|
|
3580
|
+
padding: 8px 16px;
|
|
3581
|
+
border: none;
|
|
3582
|
+
border-radius: 6px;
|
|
3583
|
+
background: #2563eb;
|
|
3584
|
+
color: white;
|
|
3585
|
+
cursor: pointer;
|
|
3586
|
+
font-size: 14px;
|
|
3587
|
+
font-weight: 500;
|
|
3588
|
+
outline: none;
|
|
3589
|
+
transition: all 0.2s ease;
|
|
3590
|
+
`;
|
|
3591
|
+
nextBtn.onmouseover = () => {
|
|
3592
|
+
nextBtn.style.background = "#1d4ed8";
|
|
3593
|
+
};
|
|
3594
|
+
nextBtn.onmouseout = () => {
|
|
3595
|
+
nextBtn.style.background = "#2563eb";
|
|
3596
|
+
};
|
|
3597
|
+
nextBtn.onclick = async () => {
|
|
3598
|
+
const advanceAction = step.basic_advanceAction || "next button";
|
|
3599
|
+
overlay2.remove();
|
|
3600
|
+
const backdropOverlay = document.getElementById(
|
|
3601
|
+
"rivia-feedback-preview-backdrop"
|
|
3602
|
+
);
|
|
3603
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3604
|
+
if (selectedEmojiIndex !== -1) {
|
|
3605
|
+
console.log("Feedback given: emoji index", selectedEmojiIndex);
|
|
3606
|
+
step.feedback_given = selectedEmojiIndex;
|
|
3607
|
+
if (STATE.tour_id) putTips();
|
|
3608
|
+
else saveTips();
|
|
3609
|
+
}
|
|
3610
|
+
if (advanceAction === "next button") {
|
|
3611
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3612
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3613
|
+
showStep(STATE.tourIndex, true);
|
|
3614
|
+
} else {
|
|
3615
|
+
endTour();
|
|
3616
|
+
}
|
|
3617
|
+
} else if (advanceAction === "scroll") {
|
|
3618
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3619
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3620
|
+
const nextStep2 = STATE.tips[STATE.tourIndex];
|
|
3621
|
+
const nextElement = await findBySelector(nextStep2.selector);
|
|
3622
|
+
if (nextElement) {
|
|
3623
|
+
nextElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
3624
|
+
setTimeout(() => showStep(STATE.tourIndex, true), 600);
|
|
3625
|
+
} else {
|
|
3626
|
+
showStep(STATE.tourIndex, true);
|
|
3627
|
+
}
|
|
3628
|
+
} else {
|
|
3629
|
+
endTour();
|
|
3630
|
+
}
|
|
3631
|
+
} else if (advanceAction === "manual click") {
|
|
3632
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3633
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3634
|
+
showStep(STATE.tourIndex, true);
|
|
3635
|
+
} else {
|
|
3636
|
+
endTour();
|
|
3637
|
+
}
|
|
3638
|
+
} else {
|
|
3639
|
+
STATE.tourIndex = Math.min(STATE.tourIndex + 1, STATE.tips.length - 1);
|
|
3640
|
+
if (STATE.tourIndex < STATE.tips.length) {
|
|
3641
|
+
showStep(STATE.tourIndex, true);
|
|
3642
|
+
} else {
|
|
3643
|
+
endTour();
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
};
|
|
3647
|
+
buttonSection.appendChild(nextBtn);
|
|
3648
|
+
modal.appendChild(buttonSection);
|
|
3649
|
+
overlay2.appendChild(modal);
|
|
3650
|
+
document.body.appendChild(overlay2);
|
|
3651
|
+
overlay2.onclick = (e) => {
|
|
3652
|
+
if (e.target === overlay2) {
|
|
3653
|
+
e.stopPropagation();
|
|
3654
|
+
overlay2.remove();
|
|
3655
|
+
const backdropOverlay = document.getElementById(
|
|
3656
|
+
"rivia-feedback-preview-backdrop"
|
|
3657
|
+
);
|
|
3658
|
+
if (backdropOverlay) backdropOverlay.remove();
|
|
3659
|
+
}
|
|
3660
|
+
};
|
|
3661
|
+
modal.onclick = (e) => {
|
|
3662
|
+
e.stopPropagation();
|
|
3663
|
+
};
|
|
3664
|
+
console.log(
|
|
3665
|
+
"Feedback card preview displayed with backdrop:",
|
|
3666
|
+
backdropStyle,
|
|
3667
|
+
"and advance action:",
|
|
3668
|
+
step.basic_advanceAction
|
|
3669
|
+
);
|
|
3670
|
+
}
|
|
3671
|
+
return { loadTips, playTour, endTour, STATE };
|
|
3672
|
+
}();
|
|
3673
|
+
function evaluateRule2(rule, context) {
|
|
3674
|
+
const leftValue = context[rule.name];
|
|
3675
|
+
const operator = rule.operator;
|
|
3676
|
+
const rightValue = rule.values;
|
|
3677
|
+
console.log("leftValue", leftValue);
|
|
3678
|
+
console.log("operator", operator);
|
|
3679
|
+
console.log("rightValue", rightValue);
|
|
3680
|
+
if (leftValue === void 0) return false;
|
|
3681
|
+
switch (operator) {
|
|
3682
|
+
case "in":
|
|
3683
|
+
return Array.isArray(rightValue) && rightValue.includes(leftValue);
|
|
3684
|
+
case "not_in":
|
|
3685
|
+
return Array.isArray(rightValue) && !rightValue.includes(leftValue);
|
|
3686
|
+
case "equals":
|
|
3687
|
+
return leftValue === rightValue;
|
|
3688
|
+
case "not_equals":
|
|
3689
|
+
return leftValue != rightValue;
|
|
3690
|
+
case "greater_than":
|
|
3691
|
+
if (rule.name == "sign_up_at")
|
|
3692
|
+
return new Date(leftValue).getTime() > new Date(rightValue).getTime();
|
|
3693
|
+
else
|
|
3694
|
+
return leftValue > rightValue;
|
|
3695
|
+
case "less_than":
|
|
3696
|
+
if (rule.name == "sign_up_at")
|
|
3697
|
+
return new Date(leftValue).getTime() < new Date(rightValue).getTime();
|
|
3698
|
+
else
|
|
3699
|
+
return leftValue < rightValue;
|
|
3700
|
+
case "greater_or_equals":
|
|
3701
|
+
if (rule.name == "sign_up_at")
|
|
3702
|
+
return new Date(leftValue).getTime() >= new Date(rightValue).getTime();
|
|
3703
|
+
else
|
|
3704
|
+
return leftValue >= rightValue;
|
|
3705
|
+
case "less_or_equals":
|
|
3706
|
+
if (rule.name == "sign_up_at")
|
|
3707
|
+
return new Date(leftValue).getTime() <= new Date(rightValue).getTime();
|
|
3708
|
+
else
|
|
3709
|
+
return leftValue <= rightValue;
|
|
3710
|
+
case "is_empty":
|
|
3711
|
+
if (leftValue == "")
|
|
3712
|
+
return true;
|
|
3713
|
+
else
|
|
3714
|
+
return false;
|
|
3715
|
+
case "is_not_empty":
|
|
3716
|
+
if (leftValue != "")
|
|
3717
|
+
return true;
|
|
3718
|
+
else
|
|
3719
|
+
return false;
|
|
3720
|
+
default:
|
|
3721
|
+
return false;
|
|
3722
|
+
}
|
|
3723
|
+
}
|
|
3724
|
+
function evaluateRules2(rules, context) {
|
|
3725
|
+
if (!Array.isArray(rules) || rules.length === 0) return true;
|
|
3726
|
+
let finalResult = evaluateRule2(rules[0], context);
|
|
3727
|
+
for (let i = 1; i < rules.length; i++) {
|
|
3728
|
+
console.log(finalResult);
|
|
3729
|
+
const previousRule = rules[i - 1];
|
|
3730
|
+
const currentResult = evaluateRule2(rules[i], context);
|
|
3731
|
+
switch (previousRule.next) {
|
|
3732
|
+
case "and":
|
|
3733
|
+
finalResult = finalResult && currentResult;
|
|
3734
|
+
break;
|
|
3735
|
+
case "or":
|
|
3736
|
+
finalResult = finalResult || currentResult;
|
|
3737
|
+
break;
|
|
3738
|
+
default:
|
|
3739
|
+
finalResult = currentResult;
|
|
3740
|
+
}
|
|
3741
|
+
}
|
|
3742
|
+
return finalResult;
|
|
3743
|
+
}
|
|
3744
|
+
async function Tours(workspace_id, obj) {
|
|
3745
|
+
if (!sessionStorage.getItem("rivia_tour_state")) {
|
|
3746
|
+
window.userId = obj.userid;
|
|
3747
|
+
let userId = obj.userid;
|
|
3748
|
+
window.sign_up_at = obj.sign_up_at;
|
|
3749
|
+
window.role = obj.role;
|
|
3750
|
+
window.email = obj.email;
|
|
3751
|
+
try {
|
|
3752
|
+
let doesRouteMatch2 = function(route) {
|
|
3753
|
+
if (!route) return false;
|
|
3754
|
+
const currentPath2 = window.location.href.toLowerCase().replace(/\/$/, "");
|
|
3755
|
+
const normalizedRoute = route.toLowerCase().replace(/\/$/, "");
|
|
3756
|
+
let pattern;
|
|
3757
|
+
if (normalizedRoute.includes("[dynamic]")) {
|
|
3758
|
+
const base = normalizedRoute.split("[dynamic]")[0].replace(/\/$/, "");
|
|
3759
|
+
pattern = new RegExp(`^${escapeRegex2(base)}(/.*)?$`);
|
|
3760
|
+
} else {
|
|
3761
|
+
pattern = new RegExp(`^${escapeRegex2(normalizedRoute)}$`);
|
|
3762
|
+
}
|
|
3763
|
+
console.log("Matching current path:", currentPath2, "against pattern:", pattern);
|
|
3764
|
+
return pattern.test(currentPath2);
|
|
3765
|
+
}, escapeRegex2 = function(str) {
|
|
3766
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3767
|
+
}, buildContext2 = function(obj2) {
|
|
3768
|
+
return {
|
|
3769
|
+
userid: obj2.userid,
|
|
3770
|
+
role: obj2.role,
|
|
3771
|
+
sign_up_at: obj2.sign_up_at,
|
|
3772
|
+
email: obj2.email,
|
|
3773
|
+
first_name: obj2.first_name,
|
|
3774
|
+
last_name: obj2.last_name
|
|
3775
|
+
};
|
|
3776
|
+
};
|
|
3777
|
+
var doesRouteMatch = doesRouteMatch2, escapeRegex = escapeRegex2, buildContext = buildContext2;
|
|
3778
|
+
const res = await fetch(
|
|
3779
|
+
`https://demoapi.rivia.ai/tour_by_workspace2/${workspace_id}`,
|
|
3780
|
+
{
|
|
3781
|
+
method: "GET",
|
|
3782
|
+
headers: { "Content-Type": "application/json" }
|
|
3783
|
+
}
|
|
3784
|
+
);
|
|
3785
|
+
if (!res.ok) {
|
|
3786
|
+
console.warn("\u274C Failed to fetch tour");
|
|
3787
|
+
return;
|
|
3788
|
+
}
|
|
3789
|
+
const data = await res.json();
|
|
3790
|
+
const tours = data.tour || [];
|
|
3791
|
+
if (!Array.isArray(tours) || tours.length === 0) return;
|
|
3792
|
+
const currentPath = window.location.href;
|
|
3793
|
+
const matchedTour = tours.find((chk) => {
|
|
3794
|
+
const routes = chk?.url;
|
|
3795
|
+
console.log("Checking tour:", window.location.href, "with routes:", routes);
|
|
3796
|
+
if (!chk?.publish && !chk?.published)
|
|
3797
|
+
return false;
|
|
3798
|
+
return doesRouteMatch2(routes, currentPath);
|
|
3799
|
+
});
|
|
3800
|
+
if (!matchedTour) {
|
|
3801
|
+
console.log("No tour applicable for this route");
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
console.log("userid", obj.userid);
|
|
3805
|
+
console.log("matched ch", matchedTour);
|
|
3806
|
+
const rules = matchedTour?.targeting_data?.custom_rules || [];
|
|
3807
|
+
console.log("rules", rules);
|
|
3808
|
+
const context = buildContext2(obj);
|
|
3809
|
+
const shouldShow = evaluateRules2(rules, context);
|
|
3810
|
+
if (!shouldShow) {
|
|
3811
|
+
console.log("User does not meet targeting rules for this tour");
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
const {
|
|
3815
|
+
tour_id,
|
|
3816
|
+
title = "Untitled Tour",
|
|
3817
|
+
subtitle = "Describe the purpose of this tour...",
|
|
3818
|
+
items = [],
|
|
3819
|
+
completion = 0,
|
|
3820
|
+
branding_data: cssConfig = {},
|
|
3821
|
+
targeting_data: targetingData = {},
|
|
3822
|
+
customCSS = ""
|
|
3823
|
+
} = matchedTour;
|
|
3824
|
+
const fullData = {
|
|
3825
|
+
tour: matchedTour,
|
|
3826
|
+
cssConfig,
|
|
3827
|
+
targetingData,
|
|
3828
|
+
customCSS
|
|
3829
|
+
};
|
|
3830
|
+
RIVIA_TOUR.loadTips(tour_id, userId).then(() => {
|
|
3831
|
+
try {
|
|
3832
|
+
RIVIA_TOUR.playTour();
|
|
3833
|
+
} catch (err) {
|
|
3834
|
+
}
|
|
3835
|
+
});
|
|
3836
|
+
} catch (err) {
|
|
3837
|
+
console.warn("Tour error:", err.message);
|
|
3838
|
+
throw err;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
var rivia_tour_default = Tours;
|
|
3843
|
+
|
|
3844
|
+
// src/utils/banner.js
|
|
3845
|
+
function injectBanner(banner = {}, opts = {}, userId, bannerId) {
|
|
3846
|
+
try {
|
|
3847
|
+
let uploadVisitedPagesInBackground2 = function(bannerId2) {
|
|
3848
|
+
console.log("Uploading visited pages in background for banner ID: and user_var:", userId);
|
|
3849
|
+
let user_var2 = userId;
|
|
3850
|
+
const backendUrl22 = `https://demoapi.rivia.ai/banners_clients/${bannerId2}`;
|
|
3851
|
+
try {
|
|
3852
|
+
const payload = {
|
|
3853
|
+
name: user_var2,
|
|
3854
|
+
is_completed: true
|
|
3855
|
+
};
|
|
3856
|
+
fetch(backendUrl22, {
|
|
3857
|
+
method: "POST",
|
|
3858
|
+
headers: { "Content-Type": "application/json" },
|
|
3859
|
+
credentials: "include",
|
|
3860
|
+
body: JSON.stringify(payload),
|
|
3861
|
+
keepalive: true
|
|
3862
|
+
}).then((res) => {
|
|
3863
|
+
if (res.status === 404) {
|
|
3864
|
+
throw new Error("Invalid banner id");
|
|
3865
|
+
}
|
|
3866
|
+
throw new Error(`Upload failed: ${res.status}`);
|
|
3867
|
+
}).catch((err) => {
|
|
3868
|
+
console.error("\u26A0\uFE0F Background PUT upload failed:", err);
|
|
3869
|
+
});
|
|
3870
|
+
} catch (err) {
|
|
3871
|
+
console.error("\u274C Error preparing background upload:", err);
|
|
3872
|
+
}
|
|
3873
|
+
};
|
|
3874
|
+
var uploadVisitedPagesInBackground = uploadVisitedPagesInBackground2;
|
|
3875
|
+
const prefix = opts.idPrefix || "rivia";
|
|
3876
|
+
const id = `${prefix}-banner`;
|
|
3877
|
+
const old = document.getElementById(id);
|
|
3878
|
+
if (old) old.remove();
|
|
3879
|
+
const camelToKebab = (s) => s.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
3880
|
+
const applyStyles = (el, obj) => {
|
|
3881
|
+
if (!obj) return;
|
|
3882
|
+
for (const k in obj) {
|
|
3883
|
+
el.style.setProperty(camelToKebab(k), obj[k]);
|
|
3884
|
+
}
|
|
3885
|
+
};
|
|
3886
|
+
const container = document.createElement("div");
|
|
3887
|
+
container.id = id;
|
|
3888
|
+
container.style.position = "fixed";
|
|
3889
|
+
container.style.left = "0";
|
|
3890
|
+
container.style.right = "0";
|
|
3891
|
+
container.style.width = "100%";
|
|
3892
|
+
container.style.zIndex = "2147483647";
|
|
3893
|
+
container.style.display = "flex";
|
|
3894
|
+
container.style.fontFamily = "Avenir, sans-serif";
|
|
3895
|
+
container.style.fontSize = "14px";
|
|
3896
|
+
container.style.justifyContent = banner.align === "left" ? "flex-start" : banner.align === "right" ? "flex-end" : "center";
|
|
3897
|
+
if (!banner.position?.includes("inline")) {
|
|
3898
|
+
container.style[banner.position?.includes("bottom") ? "bottom" : "top"] = "0";
|
|
3899
|
+
}
|
|
3900
|
+
const box = document.createElement("div");
|
|
3901
|
+
box.style.display = "flex";
|
|
3902
|
+
box.style.alignItems = "center";
|
|
3903
|
+
box.style.fontFamily = "Avenir, sans-serif";
|
|
3904
|
+
box.style.fontSize = "14px";
|
|
3905
|
+
box.style.justifyContent = "space-between";
|
|
3906
|
+
box.style.padding = "16px 18px";
|
|
3907
|
+
box.style.gap = "12px";
|
|
3908
|
+
box.style.width = `${banner.canvas.width}px`;
|
|
3909
|
+
if (banner.position?.includes("inline")) {
|
|
3910
|
+
box.style.maxWidth = "100%";
|
|
3911
|
+
box.style.width = "100%";
|
|
3912
|
+
box.style.margin = "0";
|
|
3913
|
+
} else {
|
|
3914
|
+
box.style.maxWidth = "1100px";
|
|
3915
|
+
box.style.margin = "0 auto";
|
|
3916
|
+
}
|
|
3917
|
+
box.style.margin = "0 auto";
|
|
3918
|
+
box.style.borderRadius = banner.border?.radius ? `${banner.border.radius}px` : "6px";
|
|
3919
|
+
box.style.border = banner.border ? `${banner.border.width || 1}px solid ${banner.border.color || "#000"}` : "none";
|
|
3920
|
+
if (banner.background) {
|
|
3921
|
+
if (banner.background.type === "gradient") {
|
|
3922
|
+
box.style.background = `linear-gradient(${banner.background.gradient_degree || 0}deg,
|
|
3923
|
+
${banner.background.gradient_color_1 || "#fff"},
|
|
3924
|
+
${banner.background.gradient_color_2 || "#eee"})`;
|
|
3925
|
+
} else {
|
|
3926
|
+
box.style.background = banner.background.color || "#ffffff";
|
|
3927
|
+
}
|
|
3928
|
+
box.style.color = banner.background.text_color || banner.text_color || "#000";
|
|
3929
|
+
}
|
|
3930
|
+
if (banner.canvas) {
|
|
3931
|
+
if (banner.canvas.height) box.style.height = `${banner.canvas.height}px`;
|
|
3932
|
+
if (banner.canvas.width && !banner.position.includes("inline")) box.style.width = `${banner.canvas.width}px`;
|
|
3933
|
+
}
|
|
3934
|
+
const textWrap = document.createElement("div");
|
|
3935
|
+
textWrap.style.display = "flex";
|
|
3936
|
+
textWrap.style.flexDirection = "column";
|
|
3937
|
+
textWrap.style.flex = "1";
|
|
3938
|
+
textWrap.style.gap = "6px";
|
|
3939
|
+
textWrap.style.fontFamily = "Avenir, sans-serif";
|
|
3940
|
+
textWrap.style.fontSize = "14px";
|
|
3941
|
+
if (banner.text) {
|
|
3942
|
+
const textEl = document.createElement("div");
|
|
3943
|
+
textEl.textContent = banner.text;
|
|
3944
|
+
textEl.style.fontFamily = "Avenir, sans-serif";
|
|
3945
|
+
textEl.style.fontSize = "14px";
|
|
3946
|
+
textEl.style.opacity = "0.9";
|
|
3947
|
+
textEl.style.color = banner.background?.text_color || banner.text_color || "#fff";
|
|
3948
|
+
textWrap.appendChild(textEl);
|
|
3949
|
+
}
|
|
3950
|
+
window.container = container;
|
|
3951
|
+
const btnArea = document.createElement("div");
|
|
3952
|
+
btnArea.style.display = "flex";
|
|
3953
|
+
btnArea.style.alignItems = "center";
|
|
3954
|
+
btnArea.style.gap = "10px";
|
|
3955
|
+
const btn = banner.button || {};
|
|
3956
|
+
if (btn.text) {
|
|
3957
|
+
const a = btn.action_url ? document.createElement("a") : document.createElement("button");
|
|
3958
|
+
if (btn.action == "url") {
|
|
3959
|
+
a.href = btn.action_url;
|
|
3960
|
+
a.target = btn.target || "_blank";
|
|
3961
|
+
a.rel = "noopener noreferrer";
|
|
3962
|
+
} else {
|
|
3963
|
+
a.onclick = () => {
|
|
3964
|
+
container.remove();
|
|
3965
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3966
|
+
};
|
|
3967
|
+
}
|
|
3968
|
+
if (btn.border) {
|
|
3969
|
+
a.style.border = btn.border.width ? `${btn.border.width}px solid ${btn.border.color || "#000"}` : "none";
|
|
3970
|
+
a.style.borderRadius = btn.border.radius ? `${btn.border.radius}px` : "6px";
|
|
3971
|
+
}
|
|
3972
|
+
a.textContent = btn.text || "Learn More";
|
|
3973
|
+
a.style.padding = "8px 14px";
|
|
3974
|
+
a.style.fontFamily = "Avenir, sans-serif";
|
|
3975
|
+
a.style.fontSize = "14px";
|
|
3976
|
+
a.style.cursor = "pointer";
|
|
3977
|
+
a.style.background = btn.color || "#ffffffff";
|
|
3978
|
+
a.style.color = btn.text_color || "#0088ffff";
|
|
3979
|
+
btnArea.appendChild(a);
|
|
3980
|
+
}
|
|
3981
|
+
if (banner.align === "left") {
|
|
3982
|
+
box.appendChild(btnArea);
|
|
3983
|
+
box.appendChild(textWrap);
|
|
3984
|
+
if (banner.dismissible !== false) {
|
|
3985
|
+
const closeBtn = document.createElement("button");
|
|
3986
|
+
closeBtn.innerHTML = "\u2715";
|
|
3987
|
+
closeBtn.style.border = "none";
|
|
3988
|
+
closeBtn.style.background = "transparent";
|
|
3989
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
3990
|
+
closeBtn.style.fontSize = "14px";
|
|
3991
|
+
closeBtn.style.cursor = "pointer";
|
|
3992
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
3993
|
+
closeBtn.style.marginLeft = "auto";
|
|
3994
|
+
closeBtn.onclick = () => {
|
|
3995
|
+
container.remove();
|
|
3996
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
3997
|
+
};
|
|
3998
|
+
box.appendChild(closeBtn);
|
|
3999
|
+
}
|
|
4000
|
+
} else if (banner.align === "bottom") {
|
|
4001
|
+
textWrap.style.textAlign = "left";
|
|
4002
|
+
box.appendChild(textWrap);
|
|
4003
|
+
if (banner.dismissible !== false) {
|
|
4004
|
+
const closeBtn = document.createElement("button");
|
|
4005
|
+
closeBtn.innerHTML = "\u2715";
|
|
4006
|
+
closeBtn.style.border = "none";
|
|
4007
|
+
closeBtn.style.background = "transparent";
|
|
4008
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
4009
|
+
closeBtn.style.fontSize = "14px";
|
|
4010
|
+
closeBtn.style.cursor = "pointer";
|
|
4011
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
4012
|
+
closeBtn.onclick = () => {
|
|
4013
|
+
container.remove();
|
|
4014
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
4015
|
+
};
|
|
4016
|
+
box.appendChild(closeBtn);
|
|
4017
|
+
}
|
|
4018
|
+
btnArea.style.gridColumn = "1 / span 2";
|
|
4019
|
+
btnArea.style.display = "flex";
|
|
4020
|
+
btnArea.style.justifyContent = "center";
|
|
4021
|
+
box.appendChild(btnArea);
|
|
4022
|
+
} else {
|
|
4023
|
+
box.appendChild(textWrap);
|
|
4024
|
+
box.appendChild(btnArea);
|
|
4025
|
+
if (banner.dismissible !== false) {
|
|
4026
|
+
const closeBtn = document.createElement("button");
|
|
4027
|
+
closeBtn.innerHTML = "\u2715";
|
|
4028
|
+
closeBtn.style.border = "none";
|
|
4029
|
+
closeBtn.style.background = "transparent";
|
|
4030
|
+
closeBtn.style.fontFamily = "Avenir, sans-serif";
|
|
4031
|
+
closeBtn.style.fontSize = "14px";
|
|
4032
|
+
closeBtn.style.cursor = "pointer";
|
|
4033
|
+
closeBtn.style.color = banner.background.text_color || "#fff";
|
|
4034
|
+
closeBtn.style.marginLeft = "auto";
|
|
4035
|
+
closeBtn.onclick = () => {
|
|
4036
|
+
container.remove();
|
|
4037
|
+
uploadVisitedPagesInBackground2(bannerId);
|
|
4038
|
+
};
|
|
4039
|
+
box.appendChild(closeBtn);
|
|
4040
|
+
}
|
|
4041
|
+
}
|
|
4042
|
+
container.appendChild(box);
|
|
4043
|
+
const target = document.body || document.documentElement;
|
|
4044
|
+
if (banner.position?.includes("bottom")) {
|
|
4045
|
+
target.appendChild(container);
|
|
4046
|
+
} else {
|
|
4047
|
+
target.insertBefore(container, target.firstChild);
|
|
4048
|
+
}
|
|
4049
|
+
return {
|
|
4050
|
+
id,
|
|
4051
|
+
element: container,
|
|
4052
|
+
remove: () => container.remove()
|
|
4053
|
+
};
|
|
4054
|
+
} catch (err) {
|
|
4055
|
+
console.error("injectBanner error:", err);
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
function evaluateRule3(rule, context) {
|
|
4059
|
+
const leftValue = context[rule.name];
|
|
4060
|
+
const operator = rule.operator;
|
|
4061
|
+
const rightValue = rule.values;
|
|
4062
|
+
console.log("leftValue", leftValue);
|
|
4063
|
+
console.log("operator", operator);
|
|
4064
|
+
console.log("rightValue", rightValue);
|
|
4065
|
+
if (leftValue === void 0) return false;
|
|
4066
|
+
switch (operator) {
|
|
4067
|
+
case "in":
|
|
4068
|
+
return Array.isArray(rightValue) && rightValue.includes(leftValue);
|
|
4069
|
+
case "not_in":
|
|
4070
|
+
return Array.isArray(rightValue) && !rightValue.includes(leftValue);
|
|
4071
|
+
case "equals":
|
|
4072
|
+
return leftValue === rightValue;
|
|
4073
|
+
case "not_equals":
|
|
4074
|
+
return leftValue != rightValue;
|
|
4075
|
+
case "greater_than":
|
|
4076
|
+
if (rule.name == "sign_up_at")
|
|
4077
|
+
return new Date(leftValue).getTime() > new Date(rightValue).getTime();
|
|
4078
|
+
else
|
|
4079
|
+
return leftValue > rightValue;
|
|
4080
|
+
case "less_than":
|
|
4081
|
+
if (rule.name == "sign_up_at")
|
|
4082
|
+
return new Date(leftValue).getTime() < new Date(rightValue).getTime();
|
|
4083
|
+
else
|
|
4084
|
+
return leftValue < rightValue;
|
|
4085
|
+
case "greater_or_equals":
|
|
4086
|
+
if (rule.name == "sign_up_at")
|
|
4087
|
+
return new Date(leftValue).getTime() >= new Date(rightValue).getTime();
|
|
4088
|
+
else
|
|
4089
|
+
return leftValue >= rightValue;
|
|
4090
|
+
case "less_or_equals":
|
|
4091
|
+
if (rule.name == "sign_up_at")
|
|
4092
|
+
return new Date(leftValue).getTime() <= new Date(rightValue).getTime();
|
|
4093
|
+
else
|
|
4094
|
+
return leftValue <= rightValue;
|
|
4095
|
+
case "is_empty":
|
|
4096
|
+
if (leftValue == "")
|
|
4097
|
+
return true;
|
|
4098
|
+
else
|
|
4099
|
+
return false;
|
|
4100
|
+
case "is_not_empty":
|
|
4101
|
+
if (leftValue != "")
|
|
4102
|
+
return true;
|
|
4103
|
+
else
|
|
4104
|
+
return false;
|
|
4105
|
+
default:
|
|
4106
|
+
return false;
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
function evaluateRules3(rules, context) {
|
|
4110
|
+
if (!Array.isArray(rules) || rules.length === 0) return true;
|
|
4111
|
+
let finalResult = evaluateRule3(rules[0], context);
|
|
4112
|
+
for (let i = 1; i < rules.length; i++) {
|
|
4113
|
+
console.log(finalResult);
|
|
4114
|
+
const previousRule = rules[i - 1];
|
|
4115
|
+
const currentResult = evaluateRule3(rules[i], context);
|
|
4116
|
+
switch (previousRule.next) {
|
|
4117
|
+
case "and":
|
|
4118
|
+
finalResult = finalResult && currentResult;
|
|
4119
|
+
break;
|
|
4120
|
+
case "or":
|
|
4121
|
+
finalResult = finalResult || currentResult;
|
|
4122
|
+
break;
|
|
4123
|
+
default:
|
|
4124
|
+
finalResult = currentResult;
|
|
4125
|
+
}
|
|
4126
|
+
}
|
|
4127
|
+
return finalResult;
|
|
4128
|
+
}
|
|
4129
|
+
async function Banner(workspace_id, obj) {
|
|
4130
|
+
window.addEventListener("locationchange", async () => {
|
|
4131
|
+
window.workspace_id = workspace_id;
|
|
4132
|
+
window.userid = obj.userid;
|
|
4133
|
+
let user_var = obj.userid;
|
|
4134
|
+
window.sign_up_at = obj.sign_up_at;
|
|
4135
|
+
window.role = obj.role;
|
|
4136
|
+
window.email = obj.email;
|
|
4137
|
+
console.log("");
|
|
4138
|
+
try {
|
|
4139
|
+
let doesRouteMatch2 = function(routes) {
|
|
4140
|
+
if (!Array.isArray(routes)) return true;
|
|
4141
|
+
const currentPath2 = window.location.pathname.toLowerCase();
|
|
4142
|
+
console.log("Current Path:", currentPath2);
|
|
4143
|
+
return routes.some((route) => {
|
|
4144
|
+
if (!route) return false;
|
|
4145
|
+
let pattern;
|
|
4146
|
+
const normalizedRoute = route.toLowerCase().replace(/\/$/, "");
|
|
4147
|
+
if (normalizedRoute.includes("[dynamic]")) {
|
|
4148
|
+
const base = normalizedRoute.split("[dynamic]")[0].replace(/\/$/, "");
|
|
4149
|
+
console.log("Base:", base);
|
|
4150
|
+
pattern = new RegExp(`^${escapeRegex2(base)}(/.*)?$`);
|
|
4151
|
+
} else {
|
|
4152
|
+
pattern = new RegExp(`^${escapeRegex2(normalizedRoute)}$`);
|
|
4153
|
+
}
|
|
4154
|
+
return pattern.test(currentPath2);
|
|
4155
|
+
});
|
|
4156
|
+
}, escapeRegex2 = function(str) {
|
|
4157
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
4158
|
+
}, buildContext2 = function(obj2) {
|
|
4159
|
+
return {
|
|
4160
|
+
userid: obj2.userid,
|
|
4161
|
+
role: obj2.role,
|
|
4162
|
+
sign_up_at: obj2.sign_up_at,
|
|
4163
|
+
email: obj2.email,
|
|
4164
|
+
first_name: obj2.first_name,
|
|
4165
|
+
last_name: obj2.last_name
|
|
4166
|
+
};
|
|
4167
|
+
};
|
|
4168
|
+
var doesRouteMatch = doesRouteMatch2, escapeRegex = escapeRegex2, buildContext = buildContext2;
|
|
4169
|
+
const res = await fetch(
|
|
4170
|
+
`https://demoapi.rivia.ai/banner_by_workspace2/${workspace_id}`,
|
|
4171
|
+
{
|
|
4172
|
+
method: "GET",
|
|
4173
|
+
headers: { "Content-Type": "application/json" }
|
|
4174
|
+
}
|
|
4175
|
+
);
|
|
4176
|
+
if (!res.ok) {
|
|
4177
|
+
console.warn("\u274C Failed to fetch banner");
|
|
4178
|
+
return;
|
|
4179
|
+
}
|
|
4180
|
+
const data = await res.json();
|
|
4181
|
+
const banners = data.banner || [];
|
|
4182
|
+
if (!Array.isArray(banners) || banners.length === 0) return;
|
|
4183
|
+
const currentPath = window.location.pathname;
|
|
4184
|
+
const matchedbanner = banners.find((chk) => {
|
|
4185
|
+
const routes = chk?.targeting_data?.routes;
|
|
4186
|
+
if (!chk?.publish)
|
|
4187
|
+
return false;
|
|
4188
|
+
if (!chk?.targeting_data?.display)
|
|
4189
|
+
return !doesRouteMatch2(routes, currentPath);
|
|
4190
|
+
else
|
|
4191
|
+
return doesRouteMatch2(routes, currentPath);
|
|
4192
|
+
});
|
|
4193
|
+
if (!matchedbanner) {
|
|
4194
|
+
if (window.container && window.container.parentNode) {
|
|
4195
|
+
window.container.remove();
|
|
4196
|
+
}
|
|
4197
|
+
console.log("No banner applicable for this route");
|
|
4198
|
+
return;
|
|
4199
|
+
}
|
|
4200
|
+
console.log("userid", obj.userid);
|
|
4201
|
+
console.log("matched ch", matchedbanner);
|
|
4202
|
+
const rules = matchedbanner?.targeting_data?.custom_rules || [];
|
|
4203
|
+
console.log("rules", rules);
|
|
4204
|
+
const context = buildContext2(obj);
|
|
4205
|
+
const shouldShow = evaluateRules3(rules, context);
|
|
4206
|
+
if (!shouldShow) {
|
|
4207
|
+
console.log("Banner rules not satisfied, not showing banner");
|
|
4208
|
+
return;
|
|
4209
|
+
}
|
|
4210
|
+
const {
|
|
4211
|
+
banner_id,
|
|
4212
|
+
title = "Untitled banner",
|
|
4213
|
+
subtitle = "Describe the purpose of this banner...",
|
|
4214
|
+
items = [],
|
|
4215
|
+
completion = 0,
|
|
4216
|
+
branding_data: cssConfig = {},
|
|
4217
|
+
targeting_data: targetingData = {},
|
|
4218
|
+
customCSS = ""
|
|
4219
|
+
} = matchedbanner;
|
|
4220
|
+
console.log("Banner rules satisfied, showing banner", banner_id);
|
|
4221
|
+
const fullData = {
|
|
4222
|
+
banner: matchedbanner,
|
|
4223
|
+
cssConfig,
|
|
4224
|
+
targetingData,
|
|
4225
|
+
customCSS
|
|
4226
|
+
};
|
|
4227
|
+
sessionStorage.removeItem("onboardingVisited");
|
|
4228
|
+
injectBanner(matchedbanner, {}, obj.userid, banner_id);
|
|
4229
|
+
return matchedbanner;
|
|
4230
|
+
} catch (err) {
|
|
4231
|
+
console.warn("banner error:", err.message);
|
|
4232
|
+
throw err;
|
|
4233
|
+
}
|
|
4234
|
+
});
|
|
4235
|
+
(function() {
|
|
4236
|
+
const pushState = history.pushState;
|
|
4237
|
+
const replaceState = history.replaceState;
|
|
4238
|
+
history.pushState = function() {
|
|
4239
|
+
pushState.apply(history, arguments);
|
|
4240
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
4241
|
+
};
|
|
4242
|
+
history.replaceState = function() {
|
|
4243
|
+
replaceState.apply(history, arguments);
|
|
4244
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
4245
|
+
};
|
|
4246
|
+
window.addEventListener("popstate", () => {
|
|
4247
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
4248
|
+
});
|
|
4249
|
+
window.dispatchEvent(new Event("locationchange"));
|
|
4250
|
+
})();
|
|
4251
|
+
}
|
|
4252
|
+
var banner_default = Banner;
|
|
4253
|
+
|
|
4254
|
+
// src/utils/trigger-event.js
|
|
4255
|
+
var triggerEvent = async (message) => {
|
|
4256
|
+
try {
|
|
4257
|
+
let checklist_id = window.checklist_id;
|
|
4258
|
+
let user_name = window.user_var;
|
|
4259
|
+
for (let item of window.items) {
|
|
4260
|
+
console.log("Comparing:", item.event_name, "with", message);
|
|
4261
|
+
if (item.event_name === message) {
|
|
4262
|
+
let clean_item = item.url.startsWith("/") ? item.url.slice(1) : item.url;
|
|
4263
|
+
if (!window.storedVisited.includes(item.event_name)) {
|
|
4264
|
+
window.storedVisited.push(item.event_name);
|
|
4265
|
+
}
|
|
4266
|
+
sessionStorage.setItem("onboardingVisited", JSON.stringify(window.storedVisited));
|
|
4267
|
+
window.updateProgress(window.storedVisited);
|
|
4268
|
+
window.updateProgress2(window.storedVisited);
|
|
4269
|
+
window.updateUIFromVisited();
|
|
4270
|
+
window.uploadVisitedPagesInBackground(window.storedVisited);
|
|
4271
|
+
if (storedVisited.length === window.items.length) {
|
|
4272
|
+
if (window.showBtn && window.showBtn.parentNode) {
|
|
4273
|
+
window.showBtn.remove();
|
|
4274
|
+
}
|
|
4275
|
+
if (window.label && window.label.parentNode) {
|
|
4276
|
+
window.label.remove();
|
|
4277
|
+
}
|
|
4278
|
+
(() => {
|
|
4279
|
+
const ll2 = document.createElement("div");
|
|
4280
|
+
ll2.id = "route-labe";
|
|
4281
|
+
ll2.innerText = "\u{1F389} Congrats! You've completed all items!";
|
|
4282
|
+
Object.assign(ll2.style, {
|
|
4283
|
+
position: "fixed",
|
|
4284
|
+
bottom: "20px",
|
|
4285
|
+
left: "20px",
|
|
4286
|
+
backgroundColor: "#4CAF50",
|
|
4287
|
+
color: "white",
|
|
4288
|
+
padding: "10px 20px",
|
|
4289
|
+
borderRadius: "10px",
|
|
4290
|
+
boxShadow: "0 4px 6px rgba(0,0,0,0.2)",
|
|
4291
|
+
fontSize: "16px",
|
|
4292
|
+
fontWeight: "bold",
|
|
4293
|
+
zIndex: 9999,
|
|
4294
|
+
opacity: 0,
|
|
4295
|
+
transition: "opacity 0.5s ease"
|
|
4296
|
+
});
|
|
4297
|
+
document.body.appendChild(ll2);
|
|
4298
|
+
console.log("ll2");
|
|
4299
|
+
requestAnimationFrame(() => {
|
|
4300
|
+
ll2.style.opacity = 1;
|
|
4301
|
+
});
|
|
4302
|
+
setTimeout(() => {
|
|
4303
|
+
ll2.style.opacity = 0;
|
|
4304
|
+
setTimeout(() => ll2.remove(), 500);
|
|
4305
|
+
}, 3e3);
|
|
4306
|
+
})();
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
} catch (error) {
|
|
4311
|
+
console.error("\u274C Error triggering event:", error);
|
|
4312
|
+
throw error;
|
|
4313
|
+
}
|
|
4314
|
+
};
|
|
4315
|
+
|
|
4316
|
+
// src/utils/pm.js
|
|
4317
|
+
var ProductManagement = /* @__PURE__ */ function() {
|
|
4318
|
+
const defaults = {
|
|
4319
|
+
apiUrl: "/api/changelog",
|
|
4320
|
+
// backend endpoint to fetch changelog JSON (base URL)
|
|
4321
|
+
appID: null,
|
|
4322
|
+
authToken: null,
|
|
4323
|
+
// optional Authorization header
|
|
4324
|
+
buttonSelector: "[data-pm-changelog]",
|
|
4325
|
+
position: "bottom",
|
|
4326
|
+
// or 'top'
|
|
4327
|
+
align: "right",
|
|
4328
|
+
// or 'left' or 'center'
|
|
4329
|
+
theme: "light",
|
|
4330
|
+
// light | dark | auto
|
|
4331
|
+
initialData: null,
|
|
4332
|
+
// optional pre-fetched object to avoid network call
|
|
4333
|
+
fetchOptions: {},
|
|
4334
|
+
// additional fetch options
|
|
4335
|
+
workspace: null,
|
|
4336
|
+
// optional workspace identifier to send to backend for multi-tenant support
|
|
4337
|
+
pmUserId: null,
|
|
4338
|
+
// optional user identifier to send to backend for personalization
|
|
4339
|
+
name: "abc",
|
|
4340
|
+
user_avatar: null,
|
|
4341
|
+
url: "https://img.freepik.com/free-photo/closeup-scarlet-macaw-from-side-view-scarlet-macaw-closeup-head_488145-3540.jpg?semt=ais_hybrid&w=740&q=80",
|
|
4342
|
+
email: "priyanshu@yopmail.com",
|
|
4343
|
+
// hardcoded preview id while debugging
|
|
4344
|
+
changelogPreviewId: "outplay"
|
|
4345
|
+
};
|
|
4346
|
+
const state = {
|
|
4347
|
+
initialized: false,
|
|
4348
|
+
config: {},
|
|
4349
|
+
widgetEl: null,
|
|
4350
|
+
backdropEl: null,
|
|
4351
|
+
pmUserId: null,
|
|
4352
|
+
changelogEntries: [],
|
|
4353
|
+
// ✅ store API data
|
|
4354
|
+
titleFontSize: null,
|
|
4355
|
+
// for dynamic spacing when preview styles are applied
|
|
4356
|
+
workspaceId: null
|
|
4357
|
+
// to track current workspace for dynamic updates
|
|
4358
|
+
};
|
|
4359
|
+
function mergeConfig(cfg) {
|
|
4360
|
+
state.config = Object.assign({}, defaults, cfg || {});
|
|
4361
|
+
}
|
|
4362
|
+
async function fetchCSS(previewId, widget, header, body) {
|
|
4363
|
+
if (!previewId) return;
|
|
4364
|
+
try {
|
|
4365
|
+
console.log("Fetching preview styles for id:", previewId);
|
|
4366
|
+
const res = await fetch(`https://demoapi.rivia.ai/change_logs_preview_by_workspace_name/${previewId}`);
|
|
4367
|
+
if (!res.ok) throw new Error("Failed to fetch preview styles");
|
|
4368
|
+
const response = await res.json();
|
|
4369
|
+
const data = response?.message?.[0];
|
|
4370
|
+
console.log("Applying preview styles:", data);
|
|
4371
|
+
if (data.width) {
|
|
4372
|
+
widget.style.width = data.width;
|
|
4373
|
+
widget.style.maxWidth = data.width;
|
|
4374
|
+
}
|
|
4375
|
+
if (data.backgroundColor)
|
|
4376
|
+
widget.style.backgroundColor = data.backgroundColor;
|
|
4377
|
+
if (data.borderRadius)
|
|
4378
|
+
widget.style.borderRadius = data.borderRadius;
|
|
4379
|
+
if (data.fontFamily)
|
|
4380
|
+
widget.style.fontFamily = data.fontFamily;
|
|
4381
|
+
if (data.padding)
|
|
4382
|
+
body.style.padding = data.padding;
|
|
4383
|
+
if (data.bodyFontSize)
|
|
4384
|
+
body.style.fontSize = data.bodyFontSize;
|
|
4385
|
+
if (data.bodyColor)
|
|
4386
|
+
body.style.color = data.bodyColor;
|
|
4387
|
+
if (data.titleFontSize) {
|
|
4388
|
+
header.style.fontSize = data.titleFontSize;
|
|
4389
|
+
state.titleFontSize = data.titleFontSize;
|
|
4390
|
+
}
|
|
4391
|
+
if (data.titleColor)
|
|
4392
|
+
header.style.color = data.titleColor;
|
|
4393
|
+
} catch (err) {
|
|
4394
|
+
console.error("Preview CSS load failed:", err);
|
|
4395
|
+
}
|
|
4396
|
+
}
|
|
4397
|
+
function ensureStyles() {
|
|
4398
|
+
if (document.getElementById("pm-lite-styles")) return;
|
|
4399
|
+
const css = `
|
|
4400
|
+
.pm-lite-backdrop{position:fixed;inset:0;background:rgba(255, 255, 255, 0);display:none;z-index:9998}
|
|
4401
|
+
.pm-lite-widget{position:fixed;z-index:9999;max-width:420px;width:clamp(280px,30vw,420px);box-shadow:0 10px 40px rgba(0,0,0,0.2);border-radius:12px;overflow:hidden;font-family:Inter,system-ui,Segoe UI,Roboto,Arial,sans-serif}
|
|
4402
|
+
.pm-lite-widget.light{background:#fff;color:#111}
|
|
4403
|
+
.pm-lite-widget.dark{background:#111;color:#eee}
|
|
4404
|
+
.pm-lite-header{
|
|
4405
|
+
|
|
4406
|
+
padding:6px;
|
|
4407
|
+
padding-top:15px; /* default is 12px, can be overridden by preview styles */
|
|
4408
|
+
font-weight:600;
|
|
4409
|
+
position:relative;
|
|
4410
|
+
|
|
4411
|
+
display:flex;
|
|
4412
|
+
align-items:center;
|
|
4413
|
+
justify-content:center;
|
|
4414
|
+
}
|
|
4415
|
+
.pm-lite-rivia-btn{
|
|
4416
|
+
display:block;
|
|
4417
|
+
margin-left:auto;
|
|
4418
|
+
color:#2563eb; /* blue */
|
|
4419
|
+
font-style:italic;
|
|
4420
|
+
font-size:13px;
|
|
4421
|
+
background:transparent;
|
|
4422
|
+
border:none;
|
|
4423
|
+
cursor:pointer;
|
|
4424
|
+
font-family: Inter, system-ui, Segoe UI, Roboto, Arial, sans-serif;
|
|
4425
|
+
padding:3px 15px;
|
|
4426
|
+
|
|
4427
|
+
}
|
|
4428
|
+
.pm-lite-rivia-label{
|
|
4429
|
+
display:block;
|
|
4430
|
+
margin-right:auto;
|
|
4431
|
+
color:rgba(0,0,0,0.6);
|
|
4432
|
+
font-style:italic;
|
|
4433
|
+
font-size:12px;
|
|
4434
|
+
font-family: Inter, system-ui, Segoe UI, Roboto, Arial, sans-serif;
|
|
4435
|
+
padding-left:18px;
|
|
4436
|
+
}
|
|
4437
|
+
.pm-lite-badge{font-size:12px;margin-left:8px;color:rgba(0,0,0,0.6)}
|
|
4438
|
+
.pm-lite-body{max-height:60vh;overflow:auto;
|
|
4439
|
+
|
|
4440
|
+
overflow: visible; /* remove scroll */
|
|
4441
|
+
height: auto; /* dynamic height */
|
|
4442
|
+
max-height: none; }
|
|
4443
|
+
.pm-lite-item{
|
|
4444
|
+
box-sizing:border-box;
|
|
4445
|
+
margin-bottom:6px;
|
|
4446
|
+
padding:6px 7px;
|
|
4447
|
+
border:1px solid rgba(0,0,0,0.08);
|
|
4448
|
+
border-radius:8px;
|
|
4449
|
+
background:#ffffff;
|
|
4450
|
+
/* isolate from external CSS */
|
|
4451
|
+
font-family:inherit;
|
|
4452
|
+
line-height:1.4;
|
|
4453
|
+
}
|
|
4454
|
+
.pm-lite-item.unread{background:linear-gradient(90deg,rgba(255,245,235,0.6),transparent)}
|
|
4455
|
+
.pm-lite-close{position:absolute;right:8px;top:8px;border:none;background:transparent;font-size:16px;cursor:pointer}
|
|
4456
|
+
.pm-lite-tags{font-size:12px;opacity:0.8;}
|
|
4457
|
+
.pm-lite-link{display:inline-block;margin-top:6px;font-size:13px}
|
|
4458
|
+
.pm-lite-tags{
|
|
4459
|
+
display:inline-block;
|
|
4460
|
+
background-color:rgb(220, 252, 231);
|
|
4461
|
+
color:rgb(22, 101, 52);
|
|
4462
|
+
border-radius:999px;
|
|
4463
|
+
padding:2px 8px;
|
|
4464
|
+
font-size:12px;
|
|
4465
|
+
font-weight:bold;
|
|
4466
|
+
font:Verdana, sans-serif;
|
|
4467
|
+
}
|
|
4468
|
+
`;
|
|
4469
|
+
const style = document.createElement("style");
|
|
4470
|
+
style.id = "pm-lite-styles";
|
|
4471
|
+
style.appendChild(document.createTextNode(css));
|
|
4472
|
+
document.head.appendChild(style);
|
|
4473
|
+
}
|
|
4474
|
+
async function createWidgetShell() {
|
|
4475
|
+
if (state.widgetEl) return;
|
|
4476
|
+
ensureStyles();
|
|
4477
|
+
const backdrop = document.createElement("div");
|
|
4478
|
+
backdrop.className = "pm-lite-backdrop";
|
|
4479
|
+
backdrop.addEventListener("click", closeWidget);
|
|
4480
|
+
const widget = document.createElement("div");
|
|
4481
|
+
widget.className = "pm-lite-widget " + (state.config.theme === "dark" ? "dark" : "light");
|
|
4482
|
+
widget.setAttribute("role", "dialog");
|
|
4483
|
+
const header = document.createElement("div");
|
|
4484
|
+
header.className = "pm-lite-header";
|
|
4485
|
+
header.innerText = "Latest Updates";
|
|
4486
|
+
header.paddingTop = "10px";
|
|
4487
|
+
const badge = document.createElement("span");
|
|
4488
|
+
badge.className = "pm-lite-badge";
|
|
4489
|
+
badge.style.display = "none";
|
|
4490
|
+
header.appendChild(badge);
|
|
4491
|
+
const closeBtn = document.createElement("button");
|
|
4492
|
+
closeBtn.className = "pm-lite-close";
|
|
4493
|
+
closeBtn.innerHTML = "\u2715";
|
|
4494
|
+
closeBtn.addEventListener("click", closeWidget);
|
|
4495
|
+
const body = document.createElement("div");
|
|
4496
|
+
body.className = "pm-lite-body";
|
|
4497
|
+
body.innerHTML = '<div class="pm-lite-loading">Loading\u2026</div>';
|
|
4498
|
+
const footerRow = document.createElement("div");
|
|
4499
|
+
footerRow.style.display = "flex";
|
|
4500
|
+
footerRow.style.alignItems = "center";
|
|
4501
|
+
footerRow.style.justifyContent = "space-between";
|
|
4502
|
+
footerRow.style.marginTop = "5px";
|
|
4503
|
+
footerRow.style.marginBottom = "5px";
|
|
4504
|
+
const riviaLabel = document.createElement("span");
|
|
4505
|
+
riviaLabel.className = "pm-lite-rivia-label";
|
|
4506
|
+
riviaLabel.innerText = "Powered by Rivia";
|
|
4507
|
+
riviaLabel.style.fontSize = "12px";
|
|
4508
|
+
riviaLabel.style.opacity = "0.7";
|
|
4509
|
+
const riviaBtn = document.createElement("button");
|
|
4510
|
+
riviaBtn.className = "pm-lite-rivia-btn";
|
|
4511
|
+
riviaBtn.innerText = "See all changes";
|
|
4512
|
+
footerRow.appendChild(riviaLabel);
|
|
4513
|
+
footerRow.appendChild(riviaBtn);
|
|
4514
|
+
riviaBtn.addEventListener("click", () => {
|
|
4515
|
+
const baseUrl = `http://${state.config.workspace}.rivia.ai:8080/users/changelog?userId=${state.pmUserId || ""}`;
|
|
4516
|
+
const url = new URL(baseUrl);
|
|
4517
|
+
window.open(url.toString(), "_blank");
|
|
4518
|
+
});
|
|
4519
|
+
widget.appendChild(header);
|
|
4520
|
+
const divider = document.createElement("div");
|
|
4521
|
+
divider.style.borderTop = "1px solid rgba(0,0,0,0.08)";
|
|
4522
|
+
widget.appendChild(body);
|
|
4523
|
+
widget.appendChild(divider);
|
|
4524
|
+
widget.appendChild(footerRow);
|
|
4525
|
+
document.body.appendChild(backdrop);
|
|
4526
|
+
document.body.appendChild(widget);
|
|
4527
|
+
state.backdropEl = backdrop;
|
|
4528
|
+
state.widgetEl = widget;
|
|
4529
|
+
state.widgetBody = body;
|
|
4530
|
+
state.widgetHeader = header;
|
|
4531
|
+
state.widgetBadge = badge;
|
|
4532
|
+
console.log("Widget shell created, now fetching preview CSS if available...", state.config.workspace);
|
|
4533
|
+
await fetchCSS(state.config.workspace, widget, header, body);
|
|
4534
|
+
positionWidget();
|
|
4535
|
+
window.addEventListener("resize", positionWidget);
|
|
4536
|
+
}
|
|
4537
|
+
function positionWidget() {
|
|
4538
|
+
if (!state.widgetEl) return;
|
|
4539
|
+
const { position, align } = state.config;
|
|
4540
|
+
const offset = 20;
|
|
4541
|
+
state.widgetEl.style.bottom = "";
|
|
4542
|
+
state.widgetEl.style.top = "";
|
|
4543
|
+
state.widgetEl.style.left = "";
|
|
4544
|
+
state.widgetEl.style.right = "";
|
|
4545
|
+
state.widgetEl.style.transform = "";
|
|
4546
|
+
if (position === "bottom") {
|
|
4547
|
+
state.widgetEl.style.bottom = offset + "px";
|
|
4548
|
+
} else {
|
|
4549
|
+
state.widgetEl.style.top = offset + "px";
|
|
4550
|
+
}
|
|
4551
|
+
if (align === "left") {
|
|
4552
|
+
state.widgetEl.style.left = offset + "px";
|
|
4553
|
+
} else if (align === "center") {
|
|
4554
|
+
state.widgetEl.style.left = "50%";
|
|
4555
|
+
state.widgetEl.style.transform = "translateX(-50%)";
|
|
4556
|
+
} else {
|
|
4557
|
+
state.widgetEl.style.right = offset + "px";
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
async function fetchChangelog(id) {
|
|
4561
|
+
if (state.config.initialData) {
|
|
4562
|
+
return state.config.initialData;
|
|
4563
|
+
}
|
|
4564
|
+
let urlStr = `https://demoapi.rivia.ai/change_logs_by_workspace_name`;
|
|
4565
|
+
if (!urlStr) throw new Error("apiUrl is not configured");
|
|
4566
|
+
if (id) {
|
|
4567
|
+
if (urlStr.includes("{id}")) urlStr = urlStr.replace("{id}", encodeURIComponent(id));
|
|
4568
|
+
else if (urlStr.includes(":id")) urlStr = urlStr.replace(":id", encodeURIComponent(id));
|
|
4569
|
+
else urlStr = urlStr.replace(/\/$/, "") + "/" + encodeURIComponent(id);
|
|
4570
|
+
}
|
|
4571
|
+
try {
|
|
4572
|
+
const url = new URL(urlStr, window.location.origin);
|
|
4573
|
+
const headers = Object.assign({}, state.config.fetchOptions.headers || {});
|
|
4574
|
+
const opts = Object.assign({ method: "GET", headers }, state.config.fetchOptions);
|
|
4575
|
+
const res = await fetch(url.toString(), opts);
|
|
4576
|
+
if (!res.ok) {
|
|
4577
|
+
throw new Error("Failed to fetch changelog: " + res.status + " " + res.statusText);
|
|
4578
|
+
}
|
|
4579
|
+
const payload = await res.json();
|
|
4580
|
+
state.changelogEntries = payload.message || [];
|
|
4581
|
+
return state.changelogEntries;
|
|
4582
|
+
} catch (err) {
|
|
4583
|
+
throw err;
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
function renderChangelog(data) {
|
|
4587
|
+
if (!state.widgetBody) return;
|
|
4588
|
+
if (state.widgetHeader.childNodes[0]) {
|
|
4589
|
+
state.widgetHeader.childNodes[0].nodeValue = "Latest Updates";
|
|
4590
|
+
}
|
|
4591
|
+
if (!data || !data.length) {
|
|
4592
|
+
state.widgetBody.innerHTML = '<div class="pm-lite-empty">No updates yet.</div>';
|
|
4593
|
+
return;
|
|
4594
|
+
}
|
|
4595
|
+
const frag = document.createDocumentFragment();
|
|
4596
|
+
let i = 0;
|
|
4597
|
+
data.forEach((it) => {
|
|
4598
|
+
i++;
|
|
4599
|
+
if (i > 3) return;
|
|
4600
|
+
const div = document.createElement("div");
|
|
4601
|
+
div.className = "pm-lite-item";
|
|
4602
|
+
const date = it.created_at ? new Date(it.created_at).toLocaleDateString() : "";
|
|
4603
|
+
if (it.label) {
|
|
4604
|
+
const tag = document.createElement("span");
|
|
4605
|
+
tag.className = "pm-lite-tags";
|
|
4606
|
+
tag.innerText = it.label;
|
|
4607
|
+
tag.style.display = "inline-block";
|
|
4608
|
+
tag.style.borderRadius = "999px";
|
|
4609
|
+
tag.style.fontSize = "11px";
|
|
4610
|
+
tag.style.fontWeight = "bold";
|
|
4611
|
+
tag.style.fontFamily = "Verdana, sans-serif";
|
|
4612
|
+
tag.style.backgroundColor = "rgb(220, 252, 231)";
|
|
4613
|
+
tag.style.color = "rgb(22, 101, 52)";
|
|
4614
|
+
tag.style.border = "1px solid rgb(187, 247, 208)";
|
|
4615
|
+
div.appendChild(tag);
|
|
4616
|
+
}
|
|
4617
|
+
const header = document.createElement("div");
|
|
4618
|
+
header.className = "pm-lite-item-header";
|
|
4619
|
+
header.style.fontWeight = "600";
|
|
4620
|
+
header.innerText = `${it.title || "Untitled"} `;
|
|
4621
|
+
header.style.display = "-webkit-box";
|
|
4622
|
+
header.style.webkitLineClamp = "1";
|
|
4623
|
+
header.style.webkitBoxOrient = "vertical";
|
|
4624
|
+
header.style.overflow = "hidden";
|
|
4625
|
+
header.style.textOverflow = "ellipsis";
|
|
4626
|
+
header.style.fontSize = state.titleFontSize;
|
|
4627
|
+
const content = document.createElement("div");
|
|
4628
|
+
content.innerHTML = it.text || "";
|
|
4629
|
+
content.style.display = "-webkit-box";
|
|
4630
|
+
content.style.webkitLineClamp = "3";
|
|
4631
|
+
content.style.webkitBoxOrient = "vertical";
|
|
4632
|
+
content.style.overflow = "hidden";
|
|
4633
|
+
content.style.textOverflow = "ellipsis";
|
|
4634
|
+
content.querySelectorAll("b, strong").forEach((el) => {
|
|
4635
|
+
el.style.fontWeight = "normal";
|
|
4636
|
+
});
|
|
4637
|
+
div.appendChild(header);
|
|
4638
|
+
div.appendChild(content);
|
|
4639
|
+
frag.appendChild(div);
|
|
4640
|
+
});
|
|
4641
|
+
state.widgetBody.innerHTML = "";
|
|
4642
|
+
state.widgetBody.appendChild(frag);
|
|
4643
|
+
}
|
|
4644
|
+
function escapeHtml(str) {
|
|
4645
|
+
if (!str) return "";
|
|
4646
|
+
return String(str).replace(/[&<>\"']/g, function(s) {
|
|
4647
|
+
return { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[s];
|
|
4648
|
+
});
|
|
4649
|
+
}
|
|
4650
|
+
function showWidget() {
|
|
4651
|
+
if (!state.widgetEl) createWidgetShell();
|
|
4652
|
+
state.backdropEl.style.display = "block";
|
|
4653
|
+
state.widgetEl.style.visibility = "hidden";
|
|
4654
|
+
state.widgetEl.style.display = "block";
|
|
4655
|
+
}
|
|
4656
|
+
function closeWidget() {
|
|
4657
|
+
if (!state.widgetEl) return;
|
|
4658
|
+
state.backdropEl.style.display = "none";
|
|
4659
|
+
state.widgetEl.style.display = "none";
|
|
4660
|
+
}
|
|
4661
|
+
function computePlacement(triggerRect, widgetRect, cfg) {
|
|
4662
|
+
const offset = cfg && cfg.attachOffset || 8;
|
|
4663
|
+
const vw = window.innerWidth;
|
|
4664
|
+
const vh = window.innerHeight;
|
|
4665
|
+
let top = triggerRect.bottom + offset;
|
|
4666
|
+
let left;
|
|
4667
|
+
const align = cfg && cfg.align ? cfg.align : state.config.align || "right";
|
|
4668
|
+
if (align === "left") {
|
|
4669
|
+
left = triggerRect.left;
|
|
4670
|
+
} else if (align === "center") {
|
|
4671
|
+
left = triggerRect.left + triggerRect.width / 2 - widgetRect.width / 2;
|
|
4672
|
+
} else {
|
|
4673
|
+
left = triggerRect.right - widgetRect.width;
|
|
4674
|
+
}
|
|
4675
|
+
if (top + widgetRect.height > vh) {
|
|
4676
|
+
top = triggerRect.top - widgetRect.height - offset;
|
|
4677
|
+
}
|
|
4678
|
+
if (top < 6) top = 6;
|
|
4679
|
+
const margin = 6;
|
|
4680
|
+
if (left + widgetRect.width > vw - margin) left = vw - widgetRect.width - margin;
|
|
4681
|
+
if (left < margin) left = margin;
|
|
4682
|
+
return { top, left };
|
|
4683
|
+
}
|
|
4684
|
+
async function openWidgetFor(id) {
|
|
4685
|
+
try {
|
|
4686
|
+
showWidget();
|
|
4687
|
+
state.widgetBody.innerHTML = '<div class="pm-lite-loading">Loading\u2026</div>';
|
|
4688
|
+
const data = await fetchChangelog(id);
|
|
4689
|
+
renderChangelog(data);
|
|
4690
|
+
const active = document.activeElement;
|
|
4691
|
+
const selector = state.config.buttonSelector || "[data-pm-changelog]";
|
|
4692
|
+
const isTrigger = active && active instanceof Element && active.matches && active.matches(selector);
|
|
4693
|
+
if (isTrigger) {
|
|
4694
|
+
state.widgetEl.style.visibility = "hidden";
|
|
4695
|
+
state.widgetEl.style.display = "block";
|
|
4696
|
+
await new Promise((r) => requestAnimationFrame(r));
|
|
4697
|
+
const widgetRect = state.widgetEl.getBoundingClientRect();
|
|
4698
|
+
const triggerRect = active.getBoundingClientRect();
|
|
4699
|
+
const { top, left } = computePlacement(triggerRect, widgetRect, state.config);
|
|
4700
|
+
state.widgetEl.style.position = "fixed";
|
|
4701
|
+
state.widgetEl.style.top = Math.round(top) + "px";
|
|
4702
|
+
state.widgetEl.style.left = Math.round(left) + "px";
|
|
4703
|
+
state.widgetEl.style.right = "auto";
|
|
4704
|
+
state.widgetEl.style.bottom = "auto";
|
|
4705
|
+
state.widgetEl.style.transform = "none";
|
|
4706
|
+
state.widgetEl.style.visibility = "visible";
|
|
4707
|
+
} else {
|
|
4708
|
+
positionWidget();
|
|
4709
|
+
}
|
|
4710
|
+
} catch (err) {
|
|
4711
|
+
state.widgetBody.innerHTML = `<div class="pm-lite-error">Error loading changelog: ${escapeHtml(err.message)}</div>`;
|
|
4712
|
+
console.error(err);
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
function bindClicks() {
|
|
4716
|
+
document.addEventListener("click", function onDocClick(e) {
|
|
4717
|
+
const el = e.target.closest(state.config.buttonSelector);
|
|
4718
|
+
if (!el) return;
|
|
4719
|
+
e.preventDefault();
|
|
4720
|
+
const id = el.getAttribute("data-pm-changelog");
|
|
4721
|
+
openWidgetFor(state.config.workspace || id);
|
|
4722
|
+
});
|
|
4723
|
+
}
|
|
4724
|
+
async function syncUserFromConfig() {
|
|
4725
|
+
const cfg = state.config;
|
|
4726
|
+
if (!cfg.workspace || !cfg.email) {
|
|
4727
|
+
console.warn("ProductManagement: workspace/email missing, skipping user sync");
|
|
4728
|
+
return;
|
|
4729
|
+
}
|
|
4730
|
+
const payload = {
|
|
4731
|
+
workspace: cfg.workspace,
|
|
4732
|
+
pmUserId: cfg.pmUserId,
|
|
4733
|
+
name: cfg.name,
|
|
4734
|
+
email: cfg.email,
|
|
4735
|
+
user_avatar: cfg.user_avatar,
|
|
4736
|
+
url: cfg.url
|
|
4737
|
+
};
|
|
4738
|
+
try {
|
|
4739
|
+
const res = await fetch(`https://demoapi.rivia.ai/pm_users`, {
|
|
4740
|
+
method: "POST",
|
|
4741
|
+
headers: {
|
|
4742
|
+
"Content-Type": "application/json"
|
|
4743
|
+
},
|
|
4744
|
+
body: JSON.stringify(payload)
|
|
4745
|
+
});
|
|
4746
|
+
if (!res.ok) {
|
|
4747
|
+
throw new Error(`Failed to sync user (${res.status})`);
|
|
4748
|
+
}
|
|
4749
|
+
const data = await res.json();
|
|
4750
|
+
if (data?.pm_user?.pm_user_id) {
|
|
4751
|
+
state.pmUserId = data.pm_user.pm_user_id;
|
|
4752
|
+
} else {
|
|
4753
|
+
state.pmUserId = cfg.pm_user_id;
|
|
4754
|
+
}
|
|
4755
|
+
} catch (err) {
|
|
4756
|
+
console.error("ProductManagement user sync failed:", err);
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
function init(cfg) {
|
|
4760
|
+
if (state.initialized) {
|
|
4761
|
+
console.warn("ProductManagement already initialized \u2014 ignoring subsequent init call.");
|
|
4762
|
+
return;
|
|
4763
|
+
}
|
|
4764
|
+
mergeConfig(cfg);
|
|
4765
|
+
syncUserFromConfig();
|
|
4766
|
+
bindClicks();
|
|
4767
|
+
state.initialized = true;
|
|
4768
|
+
}
|
|
4769
|
+
function setConfig(cfg) {
|
|
4770
|
+
mergeConfig(Object.assign({}, state.config, cfg));
|
|
4771
|
+
if (state.widgetEl) {
|
|
4772
|
+
state.widgetEl.className = "pm-lite-widget " + (state.config.theme === "dark" ? "dark" : "light");
|
|
4773
|
+
positionWidget();
|
|
4774
|
+
}
|
|
4775
|
+
}
|
|
4776
|
+
function attachButton(selector) {
|
|
4777
|
+
state.config.buttonSelector = selector;
|
|
4778
|
+
}
|
|
4779
|
+
function destroy() {
|
|
4780
|
+
if (state.widgetEl) state.widgetEl.remove();
|
|
4781
|
+
if (state.backdropEl) state.backdropEl.remove();
|
|
4782
|
+
const style = document.getElementById("pm-lite-styles");
|
|
4783
|
+
if (style) style.remove();
|
|
4784
|
+
state.widgetEl = null;
|
|
4785
|
+
state.backdropEl = null;
|
|
4786
|
+
state.initialized = false;
|
|
4787
|
+
}
|
|
4788
|
+
return {
|
|
4789
|
+
init,
|
|
4790
|
+
open: openWidgetFor,
|
|
4791
|
+
close: closeWidget,
|
|
4792
|
+
setConfig,
|
|
4793
|
+
attachButton,
|
|
4794
|
+
destroy
|
|
4795
|
+
};
|
|
4796
|
+
}();
|
|
4797
|
+
if (typeof window !== "undefined") window.ProductManagement = ProductManagement;
|
|
4798
|
+
var pm_default = ProductManagement;
|
|
4799
|
+
|
|
4800
|
+
// src/utils/index.js
|
|
4801
|
+
if (typeof window !== "undefined") {
|
|
4802
|
+
window.Checklist = rivia_default;
|
|
4803
|
+
window.Tours = rivia_tour_default;
|
|
4804
|
+
window.Banner = banner_default;
|
|
4805
|
+
window.triggerEvent = triggerEvent;
|
|
4806
|
+
window.ProductManagement = pm_default;
|
|
4807
|
+
}
|
|
4808
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
4809
|
+
0 && (module.exports = {
|
|
4810
|
+
Banner,
|
|
4811
|
+
Checklist,
|
|
4812
|
+
ProductManagement,
|
|
4813
|
+
Tours,
|
|
4814
|
+
triggerEvent
|
|
4815
|
+
});
|
|
4816
|
+
//# sourceMappingURL=index.cjs.js.map
|