aumera-on-screen-widget 0.0.14 → 0.0.15
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 +203 -56
- package/package.json +1 -1
package/df-btn.js
CHANGED
|
@@ -1,30 +1,192 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
1
|
+
(async function() {
|
|
2
|
+
const wrapper = document.querySelector("#df-btn");
|
|
3
|
+
|
|
4
|
+
// Helper function to get GraphQL endpoint based on environment
|
|
5
|
+
function getGraphQLUrl(env) {
|
|
6
|
+
return env === "dev"
|
|
7
|
+
? "https://admin.dev.aumera.ai/g/"
|
|
8
|
+
: "https://admin.aumera.ai/g/";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Helper function to get language from page
|
|
12
|
+
function getLanguage() {
|
|
13
|
+
// Check HTML lang attribute first
|
|
14
|
+
let lang = document.documentElement.lang || "";
|
|
15
|
+
|
|
16
|
+
// Fallback to browser language
|
|
17
|
+
if (!lang) {
|
|
18
|
+
lang = navigator.language || navigator.languages?.[0] || "en";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Extract language code (e.g., "en" from "en-US")
|
|
22
|
+
lang = lang.split("-")[0].toLowerCase();
|
|
23
|
+
|
|
24
|
+
// Validate against supported languages
|
|
25
|
+
const supportedLangs = ["en", "de", "it", "fr", "es"];
|
|
26
|
+
return supportedLangs.includes(lang) ? lang : "de";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Async function to fetch chatbot settings from GraphQL
|
|
30
|
+
async function fetchChatbotSettings(orgId, env, language) {
|
|
31
|
+
try {
|
|
32
|
+
const graphqlUrl = getGraphQLUrl(env);
|
|
33
|
+
console.log("[OSW Widget] Fetching settings from:", graphqlUrl);
|
|
34
|
+
console.log("[OSW Widget] Request params - orgId:", orgId, "env:", env, "language:", language);
|
|
35
|
+
|
|
36
|
+
const query = `
|
|
37
|
+
query osw {
|
|
38
|
+
oswChatbotSettingsPublic(organizationId: ${orgId}) {
|
|
39
|
+
message
|
|
40
|
+
success
|
|
41
|
+
settings {
|
|
42
|
+
animation
|
|
43
|
+
chatbotMask
|
|
44
|
+
oswColourBackgroundDark
|
|
45
|
+
oswColourBackgroundLight
|
|
46
|
+
oswColourFontDark
|
|
47
|
+
oswColourFontLight
|
|
48
|
+
oswHintMessage
|
|
49
|
+
oswLabel
|
|
50
|
+
position
|
|
51
|
+
showNotification
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const response = await fetch(graphqlUrl, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: {
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
"Accept-Language": language
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({ query })
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log("[OSW Widget] Response status:", response.status, response.statusText);
|
|
67
|
+
|
|
68
|
+
if (!response.ok) {
|
|
69
|
+
console.error("[OSW Widget] Failed to fetch - Status:", response.status, response.statusText);
|
|
70
|
+
const errorText = await response.text().catch(() => "Unable to read error response");
|
|
71
|
+
console.error("[OSW Widget] Error response:", errorText);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const result = await response.json();
|
|
76
|
+
console.log("[OSW Widget] GraphQL response:", result);
|
|
77
|
+
|
|
78
|
+
if (result.data?.oswChatbotSettingsPublic?.success) {
|
|
79
|
+
console.log("[OSW Widget] Settings retrieved successfully:", result.data.oswChatbotSettingsPublic.settings);
|
|
80
|
+
return result.data.oswChatbotSettingsPublic.settings;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
console.warn("[OSW Widget] GraphQL query succeeded but success=false or missing data");
|
|
84
|
+
return null;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("[OSW Widget] Exception while fetching settings:", error);
|
|
87
|
+
console.error("[OSW Widget] Error details:", error.message, error.stack);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Default configuration with fallback values
|
|
93
|
+
const defaultConfig = {
|
|
94
|
+
env: "prod",
|
|
95
|
+
width: "414px",
|
|
96
|
+
height: "75vh",
|
|
97
|
+
openText: "Chat",
|
|
98
|
+
closeText: "Close",
|
|
99
|
+
background: "#FEFFFF",
|
|
100
|
+
backgroundDark: "#171717",
|
|
101
|
+
fontColor: "#3c4043",
|
|
102
|
+
fontColorDark: "#FFFFFF",
|
|
103
|
+
position: "right",
|
|
104
|
+
animation: "message",
|
|
105
|
+
shakeDuration: 3000,
|
|
106
|
+
shakeInterval: 1000,
|
|
107
|
+
shakeAmplitude: 10,
|
|
108
|
+
shakeFrequency: 1,
|
|
109
|
+
showNotification: false,
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
// Initial config from HTML attributes with fallback to defaults
|
|
113
|
+
const config = {
|
|
114
|
+
src: wrapper.getAttribute("src"),
|
|
115
|
+
orgId: wrapper.getAttribute("orgId"),
|
|
116
|
+
env: wrapper.getAttribute("env") || defaultConfig.env,
|
|
117
|
+
width: wrapper.getAttribute("width") || defaultConfig.width,
|
|
118
|
+
height: wrapper.getAttribute("height") || defaultConfig.height,
|
|
119
|
+
openText: wrapper.getAttribute("openText") || defaultConfig.openText,
|
|
120
|
+
closeText: wrapper.getAttribute("closeText") || defaultConfig.closeText,
|
|
121
|
+
background: wrapper.getAttribute("background") || defaultConfig.background,
|
|
122
|
+
backgroundDark: wrapper.getAttribute("backgroundDark") || defaultConfig.backgroundDark,
|
|
123
|
+
fontColor: wrapper.getAttribute("fontColor") || defaultConfig.fontColor,
|
|
124
|
+
fontColorDark: wrapper.getAttribute("fontColorDark") || defaultConfig.fontColorDark,
|
|
125
|
+
logo: wrapper.getAttribute("logo"),
|
|
126
|
+
logoDark: wrapper.getAttribute("logoDark"),
|
|
127
|
+
position: wrapper.getAttribute("position") || defaultConfig.position,
|
|
128
|
+
animation: wrapper.getAttribute("animation") || defaultConfig.animation,
|
|
129
|
+
shakeDuration: parseInt(wrapper.getAttribute("shakeDuration")) || defaultConfig.shakeDuration,
|
|
130
|
+
shakeInterval: parseInt(wrapper.getAttribute("shakeInterval")) || defaultConfig.shakeInterval,
|
|
131
|
+
shakeAmplitude: parseInt(wrapper.getAttribute("shakeAmplitude")) || defaultConfig.shakeAmplitude,
|
|
132
|
+
shakeFrequency: parseInt(wrapper.getAttribute("shakeFrequency")) || defaultConfig.shakeFrequency,
|
|
133
|
+
showNotification: wrapper.getAttribute("showNotification") === "true" || defaultConfig.showNotification,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const origin = config.src.substring(0, config.src.lastIndexOf("/"));
|
|
137
|
+
|
|
138
|
+
// Get detected language
|
|
139
|
+
const detectedLang = getLanguage();
|
|
140
|
+
console.log("[OSW Widget] Detected language:", detectedLang);
|
|
141
|
+
console.log("[OSW Widget] Initial config from HTML:", config);
|
|
142
|
+
|
|
143
|
+
// Fetch settings from GraphQL and merge with config
|
|
144
|
+
if (!config.orgId) {
|
|
145
|
+
console.error("[OSW Widget] No organization ID provided! Widget will not be displayed.");
|
|
146
|
+
console.error("[OSW Widget] Add orgId attribute to the script tag: <script id='df-btn' orgId='YOUR_ORG_ID' ...>");
|
|
147
|
+
return; // Exit if no orgId
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const settings = await fetchChatbotSettings(config.orgId, config.env, detectedLang);
|
|
151
|
+
|
|
152
|
+
if (!settings) {
|
|
153
|
+
console.warn("[OSW Widget] Failed to fetch chatbot settings. Using fallback configuration.");
|
|
154
|
+
console.warn("[OSW Widget] Check:");
|
|
155
|
+
console.warn("[OSW Widget] 1. Network tab for CORS errors");
|
|
156
|
+
console.warn("[OSW Widget] 2. Organization ID is correct");
|
|
157
|
+
console.warn("[OSW Widget] 3. API endpoint is accessible");
|
|
158
|
+
// Continue with default config instead of exiting
|
|
159
|
+
config.hintMessage = "Click to check messages";
|
|
160
|
+
} else {
|
|
161
|
+
console.log("[OSW Widget] Merging GraphQL settings with config...");
|
|
162
|
+
|
|
163
|
+
// Merge GraphQL settings with config (GraphQL takes precedence, but null values fall back to HTML attributes)
|
|
164
|
+
config.animation = settings.animation || config.animation;
|
|
165
|
+
config.openText = settings.oswLabel || config.openText;
|
|
166
|
+
config.position = settings.position || config.position;
|
|
167
|
+
config.background = settings.oswColourBackgroundLight || config.background;
|
|
168
|
+
config.backgroundDark = settings.oswColourBackgroundDark || config.backgroundDark;
|
|
169
|
+
config.fontColor = settings.oswColourFontLight || config.fontColor;
|
|
170
|
+
config.fontColorDark = settings.oswColourFontDark || config.fontColorDark;
|
|
171
|
+
config.showNotification = settings.showNotification ?? config.showNotification;
|
|
172
|
+
config.hintMessage = settings.oswHintMessage || "Click to check messages";
|
|
173
|
+
|
|
174
|
+
// Use chatbotMask as logo if available
|
|
175
|
+
if (settings.chatbotMask) {
|
|
176
|
+
config.logo = settings.chatbotMask;
|
|
177
|
+
config.logoDark = settings.chatbotMask;
|
|
178
|
+
console.log("[OSW Widget] Using chatbotMask as logo:", settings.chatbotMask);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
console.log("[OSW Widget] Final merged config:", config);
|
|
183
|
+
console.log("[OSW Widget] Widget will render with:", {
|
|
184
|
+
animation: config.animation,
|
|
185
|
+
openText: config.openText,
|
|
186
|
+
position: config.position,
|
|
187
|
+
showNotification: config.showNotification,
|
|
188
|
+
logo: config.logo ? "Custom logo" : "Default logo"
|
|
189
|
+
});
|
|
28
190
|
const style = document.createElement("style");
|
|
29
191
|
style.innerHTML = `
|
|
30
192
|
.df-btn {
|
|
@@ -85,7 +247,7 @@ if (!config.orgId) {
|
|
|
85
247
|
|
|
86
248
|
.df-btn-text {
|
|
87
249
|
min-width: 56px;
|
|
88
|
-
color: #3c4043;
|
|
250
|
+
color: ${config.fontColor || "#3c4043"};
|
|
89
251
|
display: inline-flex;
|
|
90
252
|
align-items: center;
|
|
91
253
|
font-weight: 500;
|
|
@@ -106,7 +268,7 @@ if (!config.orgId) {
|
|
|
106
268
|
background-position: center;
|
|
107
269
|
background-repeat: no-repeat;
|
|
108
270
|
background-size: cover;
|
|
109
|
-
background-image: url('${origin + "/assets/chat-agent.jpg"}');
|
|
271
|
+
background-image: url('${config.logo || origin + "/assets/chat-agent.jpg"}');
|
|
110
272
|
border-radius: 50%;
|
|
111
273
|
width: 32px;
|
|
112
274
|
height: 32px;
|
|
@@ -249,11 +411,11 @@ if (!config.orgId) {
|
|
|
249
411
|
}
|
|
250
412
|
|
|
251
413
|
.df-btn-text {
|
|
252
|
-
color:
|
|
414
|
+
color: ${config.fontColorDark || "#FFFFFF"}
|
|
253
415
|
}
|
|
254
416
|
|
|
255
417
|
.df-btn-text:before {
|
|
256
|
-
background-image: url('${origin + "/assets/chat-agent.jpg"}')
|
|
418
|
+
background-image: url('${config.logoDark || config.logo || origin + "/assets/chat-agent.jpg"}')
|
|
257
419
|
}
|
|
258
420
|
|
|
259
421
|
.df-btn:not(.df-closed) > .df-btn-text:before {
|
|
@@ -280,27 +442,6 @@ if (!config.orgId) {
|
|
|
280
442
|
|
|
281
443
|
document.head.appendChild(style);
|
|
282
444
|
|
|
283
|
-
// Language detection function
|
|
284
|
-
function getLanguage() {
|
|
285
|
-
// Check HTML lang attribute first
|
|
286
|
-
let lang = document.documentElement.lang || "";
|
|
287
|
-
|
|
288
|
-
// Fallback to browser language
|
|
289
|
-
if (!lang) {
|
|
290
|
-
lang = navigator.language || navigator.languages?.[0] || "en";
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// Extract language code (e.g., "en" from "en-US")
|
|
294
|
-
lang = lang.split("-")[0].toLowerCase();
|
|
295
|
-
|
|
296
|
-
// Validate against supported languages
|
|
297
|
-
const supportedLangs = ["en", "de", "it", "fr", "es"];
|
|
298
|
-
return supportedLangs.includes(lang) ? lang : "de";
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Get the detected language
|
|
302
|
-
const detectedLang = getLanguage();
|
|
303
|
-
|
|
304
445
|
// Function to get chat URL based on environment
|
|
305
446
|
function getChatUrl() {
|
|
306
447
|
const env = config.env;
|
|
@@ -316,11 +457,12 @@ if (!config.orgId) {
|
|
|
316
457
|
}
|
|
317
458
|
}
|
|
318
459
|
|
|
319
|
-
|
|
460
|
+
// Create button HTML
|
|
461
|
+
const buttonHTML = `
|
|
320
462
|
<button class="df-btn df-closed" onclick="dfToggle()">
|
|
321
463
|
${
|
|
322
464
|
config.showNotification
|
|
323
|
-
?
|
|
465
|
+
? `<div class="df-notification">${config.hintMessage || "Click to check messages"}</div>`
|
|
324
466
|
: ""
|
|
325
467
|
}
|
|
326
468
|
<div class="df-btn-header">
|
|
@@ -330,7 +472,10 @@ if (!config.orgId) {
|
|
|
330
472
|
config.orgId
|
|
331
473
|
}" allow="microphone *"></iframe>
|
|
332
474
|
</button>
|
|
333
|
-
|
|
475
|
+
`;
|
|
476
|
+
|
|
477
|
+
// Insert button into DOM (works in async context unlike document.write)
|
|
478
|
+
document.body.insertAdjacentHTML('beforeend', buttonHTML);
|
|
334
479
|
|
|
335
480
|
let dfToggled = false;
|
|
336
481
|
let inactivityTimer = null;
|
|
@@ -587,4 +732,6 @@ if (!config.orgId) {
|
|
|
587
732
|
if (!isMobile) {
|
|
588
733
|
startInactivityTimer();
|
|
589
734
|
}
|
|
590
|
-
|
|
735
|
+
|
|
736
|
+
console.log("[OSW Widget] ✓ Widget initialized successfully!");
|
|
737
|
+
})();
|