aumera-on-screen-widget 0.0.15 → 0.0.17
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/df-btn.js +208 -35
- package/package.json +1 -1
package/df-btn.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(async function() {
|
|
1
|
+
(async function () {
|
|
2
2
|
const wrapper = document.querySelector("#df-btn");
|
|
3
3
|
|
|
4
4
|
// Helper function to get GraphQL endpoint based on environment
|
|
@@ -26,12 +26,27 @@
|
|
|
26
26
|
return supportedLangs.includes(lang) ? lang : "de";
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
// Helper function to resize Cloudinary images for optimized file size
|
|
30
|
+
function cloudinaryResize(url, width = 32, height = 32) {
|
|
31
|
+
const transform = `w_${width},h_${height},c_fill,f_auto,q_auto`;
|
|
32
|
+
|
|
33
|
+
// Insert transformation right after `/upload/`
|
|
34
|
+
return url.replace('/upload/', `/upload/${transform}/`);
|
|
35
|
+
}
|
|
36
|
+
|
|
29
37
|
// Async function to fetch chatbot settings from GraphQL
|
|
30
38
|
async function fetchChatbotSettings(orgId, env, language) {
|
|
31
39
|
try {
|
|
32
40
|
const graphqlUrl = getGraphQLUrl(env);
|
|
33
41
|
console.log("[OSW Widget] Fetching settings from:", graphqlUrl);
|
|
34
|
-
console.log(
|
|
42
|
+
console.log(
|
|
43
|
+
"[OSW Widget] Request params - orgId:",
|
|
44
|
+
orgId,
|
|
45
|
+
"env:",
|
|
46
|
+
env,
|
|
47
|
+
"language:",
|
|
48
|
+
language
|
|
49
|
+
);
|
|
35
50
|
|
|
36
51
|
const query = `
|
|
37
52
|
query osw {
|
|
@@ -58,16 +73,26 @@
|
|
|
58
73
|
method: "POST",
|
|
59
74
|
headers: {
|
|
60
75
|
"Content-Type": "application/json",
|
|
61
|
-
"Accept-Language": language
|
|
76
|
+
"Accept-Language": language,
|
|
62
77
|
},
|
|
63
|
-
body: JSON.stringify({ query })
|
|
78
|
+
body: JSON.stringify({ query }),
|
|
64
79
|
});
|
|
65
80
|
|
|
66
|
-
console.log(
|
|
81
|
+
console.log(
|
|
82
|
+
"[OSW Widget] Response status:",
|
|
83
|
+
response.status,
|
|
84
|
+
response.statusText
|
|
85
|
+
);
|
|
67
86
|
|
|
68
87
|
if (!response.ok) {
|
|
69
|
-
console.error(
|
|
70
|
-
|
|
88
|
+
console.error(
|
|
89
|
+
"[OSW Widget] Failed to fetch - Status:",
|
|
90
|
+
response.status,
|
|
91
|
+
response.statusText
|
|
92
|
+
);
|
|
93
|
+
const errorText = await response
|
|
94
|
+
.text()
|
|
95
|
+
.catch(() => "Unable to read error response");
|
|
71
96
|
console.error("[OSW Widget] Error response:", errorText);
|
|
72
97
|
return null;
|
|
73
98
|
}
|
|
@@ -76,11 +101,16 @@
|
|
|
76
101
|
console.log("[OSW Widget] GraphQL response:", result);
|
|
77
102
|
|
|
78
103
|
if (result.data?.oswChatbotSettingsPublic?.success) {
|
|
79
|
-
console.log(
|
|
104
|
+
console.log(
|
|
105
|
+
"[OSW Widget] Settings retrieved successfully:",
|
|
106
|
+
result.data.oswChatbotSettingsPublic.settings
|
|
107
|
+
);
|
|
80
108
|
return result.data.oswChatbotSettingsPublic.settings;
|
|
81
109
|
}
|
|
82
110
|
|
|
83
|
-
console.warn(
|
|
111
|
+
console.warn(
|
|
112
|
+
"[OSW Widget] GraphQL query succeeded but success=false or missing data"
|
|
113
|
+
);
|
|
84
114
|
return null;
|
|
85
115
|
} catch (error) {
|
|
86
116
|
console.error("[OSW Widget] Exception while fetching settings:", error);
|
|
@@ -101,7 +131,7 @@
|
|
|
101
131
|
fontColor: "#3c4043",
|
|
102
132
|
fontColorDark: "#FFFFFF",
|
|
103
133
|
position: "right",
|
|
104
|
-
animation: "
|
|
134
|
+
animation: "none",
|
|
105
135
|
shakeDuration: 3000,
|
|
106
136
|
shakeInterval: 1000,
|
|
107
137
|
shakeAmplitude: 10,
|
|
@@ -119,18 +149,30 @@
|
|
|
119
149
|
openText: wrapper.getAttribute("openText") || defaultConfig.openText,
|
|
120
150
|
closeText: wrapper.getAttribute("closeText") || defaultConfig.closeText,
|
|
121
151
|
background: wrapper.getAttribute("background") || defaultConfig.background,
|
|
122
|
-
backgroundDark:
|
|
152
|
+
backgroundDark:
|
|
153
|
+
wrapper.getAttribute("backgroundDark") || defaultConfig.backgroundDark,
|
|
123
154
|
fontColor: wrapper.getAttribute("fontColor") || defaultConfig.fontColor,
|
|
124
|
-
fontColorDark:
|
|
155
|
+
fontColorDark:
|
|
156
|
+
wrapper.getAttribute("fontColorDark") || defaultConfig.fontColorDark,
|
|
125
157
|
logo: wrapper.getAttribute("logo"),
|
|
126
158
|
logoDark: wrapper.getAttribute("logoDark"),
|
|
127
159
|
position: wrapper.getAttribute("position") || defaultConfig.position,
|
|
128
160
|
animation: wrapper.getAttribute("animation") || defaultConfig.animation,
|
|
129
|
-
shakeDuration:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
shakeDuration:
|
|
162
|
+
parseInt(wrapper.getAttribute("shakeDuration")) ||
|
|
163
|
+
defaultConfig.shakeDuration,
|
|
164
|
+
shakeInterval:
|
|
165
|
+
parseInt(wrapper.getAttribute("shakeInterval")) ||
|
|
166
|
+
defaultConfig.shakeInterval,
|
|
167
|
+
shakeAmplitude:
|
|
168
|
+
parseInt(wrapper.getAttribute("shakeAmplitude")) ||
|
|
169
|
+
defaultConfig.shakeAmplitude,
|
|
170
|
+
shakeFrequency:
|
|
171
|
+
parseInt(wrapper.getAttribute("shakeFrequency")) ||
|
|
172
|
+
defaultConfig.shakeFrequency,
|
|
173
|
+
showNotification:
|
|
174
|
+
wrapper.getAttribute("showNotification") === "true" ||
|
|
175
|
+
defaultConfig.showNotification,
|
|
134
176
|
};
|
|
135
177
|
|
|
136
178
|
const origin = config.src.substring(0, config.src.lastIndexOf("/"));
|
|
@@ -142,15 +184,25 @@
|
|
|
142
184
|
|
|
143
185
|
// Fetch settings from GraphQL and merge with config
|
|
144
186
|
if (!config.orgId) {
|
|
145
|
-
console.error(
|
|
146
|
-
|
|
187
|
+
console.error(
|
|
188
|
+
"[OSW Widget] No organization ID provided! Widget will not be displayed."
|
|
189
|
+
);
|
|
190
|
+
console.error(
|
|
191
|
+
"[OSW Widget] Add orgId attribute to the script tag: <script id='df-btn' orgId='YOUR_ORG_ID' ...>"
|
|
192
|
+
);
|
|
147
193
|
return; // Exit if no orgId
|
|
148
194
|
}
|
|
149
195
|
|
|
150
|
-
const settings = await fetchChatbotSettings(
|
|
196
|
+
const settings = await fetchChatbotSettings(
|
|
197
|
+
config.orgId,
|
|
198
|
+
config.env,
|
|
199
|
+
detectedLang
|
|
200
|
+
);
|
|
151
201
|
|
|
152
202
|
if (!settings) {
|
|
153
|
-
console.warn(
|
|
203
|
+
console.warn(
|
|
204
|
+
"[OSW Widget] Failed to fetch chatbot settings. Using fallback configuration."
|
|
205
|
+
);
|
|
154
206
|
console.warn("[OSW Widget] Check:");
|
|
155
207
|
console.warn("[OSW Widget] 1. Network tab for CORS errors");
|
|
156
208
|
console.warn("[OSW Widget] 2. Organization ID is correct");
|
|
@@ -165,17 +217,22 @@
|
|
|
165
217
|
config.openText = settings.oswLabel || config.openText;
|
|
166
218
|
config.position = settings.position || config.position;
|
|
167
219
|
config.background = settings.oswColourBackgroundLight || config.background;
|
|
168
|
-
config.backgroundDark =
|
|
220
|
+
config.backgroundDark =
|
|
221
|
+
settings.oswColourBackgroundDark || config.backgroundDark;
|
|
169
222
|
config.fontColor = settings.oswColourFontLight || config.fontColor;
|
|
170
223
|
config.fontColorDark = settings.oswColourFontDark || config.fontColorDark;
|
|
171
|
-
config.showNotification =
|
|
224
|
+
config.showNotification =
|
|
225
|
+
settings.showNotification ?? config.showNotification;
|
|
172
226
|
config.hintMessage = settings.oswHintMessage || "Click to check messages";
|
|
173
227
|
|
|
174
228
|
// Use chatbotMask as logo if available
|
|
175
229
|
if (settings.chatbotMask) {
|
|
176
|
-
config.logo = settings.chatbotMask;
|
|
177
|
-
config.logoDark = settings.chatbotMask;
|
|
178
|
-
console.log(
|
|
230
|
+
config.logo = cloudinaryResize(settings.chatbotMask, 64, 64);
|
|
231
|
+
config.logoDark = cloudinaryResize(settings.chatbotMask, 64, 64);
|
|
232
|
+
console.log(
|
|
233
|
+
"[OSW Widget] Using chatbotMask as logo:",
|
|
234
|
+
settings.chatbotMask
|
|
235
|
+
);
|
|
179
236
|
}
|
|
180
237
|
}
|
|
181
238
|
|
|
@@ -185,7 +242,7 @@
|
|
|
185
242
|
openText: config.openText,
|
|
186
243
|
position: config.position,
|
|
187
244
|
showNotification: config.showNotification,
|
|
188
|
-
logo: config.logo ? "Custom logo" : "Default logo"
|
|
245
|
+
logo: config.logo ? "Custom logo" : "Default logo",
|
|
189
246
|
});
|
|
190
247
|
const style = document.createElement("style");
|
|
191
248
|
style.innerHTML = `
|
|
@@ -215,8 +272,8 @@
|
|
|
215
272
|
position: absolute;
|
|
216
273
|
top: -45px;
|
|
217
274
|
${config.position === "left" ? "left: 0;" : "right: 0;"}
|
|
218
|
-
background: #
|
|
219
|
-
color:
|
|
275
|
+
background: ${config.background || "#FEFFFF"};
|
|
276
|
+
color: ${config.fontColor || "#3c4043"};
|
|
220
277
|
padding: 8px 16px;
|
|
221
278
|
border-radius: 8px;
|
|
222
279
|
font-size: 13px;
|
|
@@ -225,7 +282,10 @@
|
|
|
225
282
|
transition: all 0.3s ease;
|
|
226
283
|
white-space: nowrap;
|
|
227
284
|
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
|
|
228
|
-
pointer-events:
|
|
285
|
+
pointer-events: auto;
|
|
286
|
+
display: flex;
|
|
287
|
+
align-items: center;
|
|
288
|
+
gap: 8px;
|
|
229
289
|
}
|
|
230
290
|
|
|
231
291
|
.df-notification:after {
|
|
@@ -237,7 +297,7 @@
|
|
|
237
297
|
height: 0;
|
|
238
298
|
border-left: 6px solid transparent;
|
|
239
299
|
border-right: 6px solid transparent;
|
|
240
|
-
border-top: 6px solid #
|
|
300
|
+
border-top: 6px solid ${config.background || "#FEFFFF"};
|
|
241
301
|
}
|
|
242
302
|
|
|
243
303
|
.df-notification.show {
|
|
@@ -245,6 +305,26 @@
|
|
|
245
305
|
transform: translateY(0);
|
|
246
306
|
}
|
|
247
307
|
|
|
308
|
+
.df-notification-close {
|
|
309
|
+
cursor: pointer;
|
|
310
|
+
width: 16px;
|
|
311
|
+
height: 16px;
|
|
312
|
+
display: flex;
|
|
313
|
+
align-items: center;
|
|
314
|
+
justify-content: center;
|
|
315
|
+
flex-shrink: 0;
|
|
316
|
+
opacity: 0.7;
|
|
317
|
+
transition: opacity 0.2s ease;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.df-notification-close:hover {
|
|
321
|
+
opacity: 1;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.df-notification-text {
|
|
325
|
+
flex: 1;
|
|
326
|
+
}
|
|
327
|
+
|
|
248
328
|
.df-btn-text {
|
|
249
329
|
min-width: 56px;
|
|
250
330
|
color: ${config.fontColor || "#3c4043"};
|
|
@@ -268,7 +348,9 @@
|
|
|
268
348
|
background-position: center;
|
|
269
349
|
background-repeat: no-repeat;
|
|
270
350
|
background-size: cover;
|
|
271
|
-
background-image: url('${
|
|
351
|
+
background-image: url('${
|
|
352
|
+
config.logo || origin + "/assets/chat-agent.jpg"
|
|
353
|
+
}');
|
|
272
354
|
border-radius: 50%;
|
|
273
355
|
width: 32px;
|
|
274
356
|
height: 32px;
|
|
@@ -415,12 +497,25 @@
|
|
|
415
497
|
}
|
|
416
498
|
|
|
417
499
|
.df-btn-text:before {
|
|
418
|
-
background-image: url('${
|
|
500
|
+
background-image: url('${
|
|
501
|
+
config.logoDark ||
|
|
502
|
+
config.logo ||
|
|
503
|
+
origin + "/assets/chat-agent.jpg"
|
|
504
|
+
}')
|
|
419
505
|
}
|
|
420
506
|
|
|
421
507
|
.df-btn:not(.df-closed) > .df-btn-text:before {
|
|
422
508
|
background-image: url('${origin}/assets/close_dark.svg')
|
|
423
509
|
}
|
|
510
|
+
|
|
511
|
+
.df-notification {
|
|
512
|
+
background: ${config.backgroundDark || "#171717"};
|
|
513
|
+
color: ${config.fontColorDark || "#FFFFFF"};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.df-notification:after {
|
|
517
|
+
border-top: 6px solid ${config.backgroundDark || "#171717"};
|
|
518
|
+
}
|
|
424
519
|
}
|
|
425
520
|
|
|
426
521
|
@keyframes shake {
|
|
@@ -462,7 +557,16 @@
|
|
|
462
557
|
<button class="df-btn df-closed" onclick="dfToggle()">
|
|
463
558
|
${
|
|
464
559
|
config.showNotification
|
|
465
|
-
? `<div class="df-notification"
|
|
560
|
+
? `<div class="df-notification">
|
|
561
|
+
<span class="df-notification-text">${
|
|
562
|
+
config.hintMessage || "Click to check messages"
|
|
563
|
+
}</span>
|
|
564
|
+
<div class="df-notification-close" onclick="dismissNotification(event)">
|
|
565
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
|
|
566
|
+
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
|
|
567
|
+
</svg>
|
|
568
|
+
</div>
|
|
569
|
+
</div>`
|
|
466
570
|
: ""
|
|
467
571
|
}
|
|
468
572
|
<div class="df-btn-header">
|
|
@@ -475,13 +579,60 @@
|
|
|
475
579
|
`;
|
|
476
580
|
|
|
477
581
|
// Insert button into DOM (works in async context unlike document.write)
|
|
478
|
-
document.body.insertAdjacentHTML(
|
|
582
|
+
document.body.insertAdjacentHTML("beforeend", buttonHTML);
|
|
479
583
|
|
|
480
584
|
let dfToggled = false;
|
|
481
585
|
let inactivityTimer = null;
|
|
482
586
|
let shakeInterval = null;
|
|
483
587
|
|
|
588
|
+
// Check if notification was dismissed
|
|
589
|
+
const NOTIFICATION_DISMISSED_KEY = `osw-notification-dismissed-${config.orgId}`;
|
|
590
|
+
|
|
591
|
+
function isNotificationDismissed() {
|
|
592
|
+
try {
|
|
593
|
+
return localStorage.getItem(NOTIFICATION_DISMISSED_KEY) === "true";
|
|
594
|
+
} catch (e) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function dismissNotification(event) {
|
|
600
|
+
event.stopPropagation();
|
|
601
|
+
event.preventDefault();
|
|
602
|
+
|
|
603
|
+
const notification = document.querySelector(".df-notification");
|
|
604
|
+
if (notification) {
|
|
605
|
+
notification.classList.remove("show");
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Stop any ongoing shake animation
|
|
609
|
+
const button = document.querySelector(".df-btn");
|
|
610
|
+
if (button) {
|
|
611
|
+
button.classList.remove("shake");
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// Clear timers
|
|
615
|
+
clearInactivityAndShake();
|
|
616
|
+
|
|
617
|
+
// Store dismissed state
|
|
618
|
+
try {
|
|
619
|
+
localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
|
|
620
|
+
} catch (e) {
|
|
621
|
+
console.warn(
|
|
622
|
+
"[OSW Widget] Could not save notification dismissed state:",
|
|
623
|
+
e
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
window.dismissNotification = dismissNotification;
|
|
629
|
+
|
|
484
630
|
const startInactivityTimer = () => {
|
|
631
|
+
// Don't start timer if notification was dismissed
|
|
632
|
+
if (isNotificationDismissed()) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
485
636
|
// Only start inactivity timer if button is closed
|
|
486
637
|
if (!dfToggled) {
|
|
487
638
|
inactivityTimer = setTimeout(() => {
|
|
@@ -663,6 +814,28 @@
|
|
|
663
814
|
btn.addEventListener("click", () => {
|
|
664
815
|
// Only toggle if chat is closed (popover mode)
|
|
665
816
|
if (btn.classList.contains("df-closed")) {
|
|
817
|
+
// Dismiss notification when opening chat
|
|
818
|
+
const notification = document.querySelector(".df-notification");
|
|
819
|
+
if (notification && notification.classList.contains("show")) {
|
|
820
|
+
notification.classList.remove("show");
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// Stop any ongoing shake animation
|
|
824
|
+
btn.classList.remove("shake");
|
|
825
|
+
|
|
826
|
+
// Clear timers
|
|
827
|
+
clearInactivityAndShake();
|
|
828
|
+
|
|
829
|
+
// Store dismissed state
|
|
830
|
+
try {
|
|
831
|
+
localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
|
|
832
|
+
} catch (e) {
|
|
833
|
+
console.warn(
|
|
834
|
+
"[OSW Widget] Could not save notification dismissed state:",
|
|
835
|
+
e
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
|
|
666
839
|
const isMobile = window.innerWidth <= 768;
|
|
667
840
|
|
|
668
841
|
if (isMobile) {
|