aumera-on-screen-widget 0.0.15 → 0.0.16

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.
Files changed (2) hide show
  1. package/df-btn.js +198 -33
  2. 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
@@ -31,7 +31,14 @@
31
31
  try {
32
32
  const graphqlUrl = getGraphQLUrl(env);
33
33
  console.log("[OSW Widget] Fetching settings from:", graphqlUrl);
34
- console.log("[OSW Widget] Request params - orgId:", orgId, "env:", env, "language:", language);
34
+ console.log(
35
+ "[OSW Widget] Request params - orgId:",
36
+ orgId,
37
+ "env:",
38
+ env,
39
+ "language:",
40
+ language
41
+ );
35
42
 
36
43
  const query = `
37
44
  query osw {
@@ -58,16 +65,26 @@
58
65
  method: "POST",
59
66
  headers: {
60
67
  "Content-Type": "application/json",
61
- "Accept-Language": language
68
+ "Accept-Language": language,
62
69
  },
63
- body: JSON.stringify({ query })
70
+ body: JSON.stringify({ query }),
64
71
  });
65
72
 
66
- console.log("[OSW Widget] Response status:", response.status, response.statusText);
73
+ console.log(
74
+ "[OSW Widget] Response status:",
75
+ response.status,
76
+ response.statusText
77
+ );
67
78
 
68
79
  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");
80
+ console.error(
81
+ "[OSW Widget] Failed to fetch - Status:",
82
+ response.status,
83
+ response.statusText
84
+ );
85
+ const errorText = await response
86
+ .text()
87
+ .catch(() => "Unable to read error response");
71
88
  console.error("[OSW Widget] Error response:", errorText);
72
89
  return null;
73
90
  }
@@ -76,11 +93,16 @@
76
93
  console.log("[OSW Widget] GraphQL response:", result);
77
94
 
78
95
  if (result.data?.oswChatbotSettingsPublic?.success) {
79
- console.log("[OSW Widget] Settings retrieved successfully:", result.data.oswChatbotSettingsPublic.settings);
96
+ console.log(
97
+ "[OSW Widget] Settings retrieved successfully:",
98
+ result.data.oswChatbotSettingsPublic.settings
99
+ );
80
100
  return result.data.oswChatbotSettingsPublic.settings;
81
101
  }
82
102
 
83
- console.warn("[OSW Widget] GraphQL query succeeded but success=false or missing data");
103
+ console.warn(
104
+ "[OSW Widget] GraphQL query succeeded but success=false or missing data"
105
+ );
84
106
  return null;
85
107
  } catch (error) {
86
108
  console.error("[OSW Widget] Exception while fetching settings:", error);
@@ -101,7 +123,7 @@
101
123
  fontColor: "#3c4043",
102
124
  fontColorDark: "#FFFFFF",
103
125
  position: "right",
104
- animation: "message",
126
+ animation: "none",
105
127
  shakeDuration: 3000,
106
128
  shakeInterval: 1000,
107
129
  shakeAmplitude: 10,
@@ -119,18 +141,30 @@
119
141
  openText: wrapper.getAttribute("openText") || defaultConfig.openText,
120
142
  closeText: wrapper.getAttribute("closeText") || defaultConfig.closeText,
121
143
  background: wrapper.getAttribute("background") || defaultConfig.background,
122
- backgroundDark: wrapper.getAttribute("backgroundDark") || defaultConfig.backgroundDark,
144
+ backgroundDark:
145
+ wrapper.getAttribute("backgroundDark") || defaultConfig.backgroundDark,
123
146
  fontColor: wrapper.getAttribute("fontColor") || defaultConfig.fontColor,
124
- fontColorDark: wrapper.getAttribute("fontColorDark") || defaultConfig.fontColorDark,
147
+ fontColorDark:
148
+ wrapper.getAttribute("fontColorDark") || defaultConfig.fontColorDark,
125
149
  logo: wrapper.getAttribute("logo"),
126
150
  logoDark: wrapper.getAttribute("logoDark"),
127
151
  position: wrapper.getAttribute("position") || defaultConfig.position,
128
152
  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,
153
+ shakeDuration:
154
+ parseInt(wrapper.getAttribute("shakeDuration")) ||
155
+ defaultConfig.shakeDuration,
156
+ shakeInterval:
157
+ parseInt(wrapper.getAttribute("shakeInterval")) ||
158
+ defaultConfig.shakeInterval,
159
+ shakeAmplitude:
160
+ parseInt(wrapper.getAttribute("shakeAmplitude")) ||
161
+ defaultConfig.shakeAmplitude,
162
+ shakeFrequency:
163
+ parseInt(wrapper.getAttribute("shakeFrequency")) ||
164
+ defaultConfig.shakeFrequency,
165
+ showNotification:
166
+ wrapper.getAttribute("showNotification") === "true" ||
167
+ defaultConfig.showNotification,
134
168
  };
135
169
 
136
170
  const origin = config.src.substring(0, config.src.lastIndexOf("/"));
@@ -142,15 +176,25 @@
142
176
 
143
177
  // Fetch settings from GraphQL and merge with config
144
178
  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' ...>");
179
+ console.error(
180
+ "[OSW Widget] No organization ID provided! Widget will not be displayed."
181
+ );
182
+ console.error(
183
+ "[OSW Widget] Add orgId attribute to the script tag: <script id='df-btn' orgId='YOUR_ORG_ID' ...>"
184
+ );
147
185
  return; // Exit if no orgId
148
186
  }
149
187
 
150
- const settings = await fetchChatbotSettings(config.orgId, config.env, detectedLang);
188
+ const settings = await fetchChatbotSettings(
189
+ config.orgId,
190
+ config.env,
191
+ detectedLang
192
+ );
151
193
 
152
194
  if (!settings) {
153
- console.warn("[OSW Widget] Failed to fetch chatbot settings. Using fallback configuration.");
195
+ console.warn(
196
+ "[OSW Widget] Failed to fetch chatbot settings. Using fallback configuration."
197
+ );
154
198
  console.warn("[OSW Widget] Check:");
155
199
  console.warn("[OSW Widget] 1. Network tab for CORS errors");
156
200
  console.warn("[OSW Widget] 2. Organization ID is correct");
@@ -165,17 +209,22 @@
165
209
  config.openText = settings.oswLabel || config.openText;
166
210
  config.position = settings.position || config.position;
167
211
  config.background = settings.oswColourBackgroundLight || config.background;
168
- config.backgroundDark = settings.oswColourBackgroundDark || config.backgroundDark;
212
+ config.backgroundDark =
213
+ settings.oswColourBackgroundDark || config.backgroundDark;
169
214
  config.fontColor = settings.oswColourFontLight || config.fontColor;
170
215
  config.fontColorDark = settings.oswColourFontDark || config.fontColorDark;
171
- config.showNotification = settings.showNotification ?? config.showNotification;
216
+ config.showNotification =
217
+ settings.showNotification ?? config.showNotification;
172
218
  config.hintMessage = settings.oswHintMessage || "Click to check messages";
173
219
 
174
220
  // Use chatbotMask as logo if available
175
221
  if (settings.chatbotMask) {
176
222
  config.logo = settings.chatbotMask;
177
223
  config.logoDark = settings.chatbotMask;
178
- console.log("[OSW Widget] Using chatbotMask as logo:", settings.chatbotMask);
224
+ console.log(
225
+ "[OSW Widget] Using chatbotMask as logo:",
226
+ settings.chatbotMask
227
+ );
179
228
  }
180
229
  }
181
230
 
@@ -185,7 +234,7 @@
185
234
  openText: config.openText,
186
235
  position: config.position,
187
236
  showNotification: config.showNotification,
188
- logo: config.logo ? "Custom logo" : "Default logo"
237
+ logo: config.logo ? "Custom logo" : "Default logo",
189
238
  });
190
239
  const style = document.createElement("style");
191
240
  style.innerHTML = `
@@ -215,8 +264,8 @@
215
264
  position: absolute;
216
265
  top: -45px;
217
266
  ${config.position === "left" ? "left: 0;" : "right: 0;"}
218
- background: #202124;
219
- color: white;
267
+ background: ${config.background || "#FEFFFF"};
268
+ color: ${config.fontColor || "#3c4043"};
220
269
  padding: 8px 16px;
221
270
  border-radius: 8px;
222
271
  font-size: 13px;
@@ -225,7 +274,10 @@
225
274
  transition: all 0.3s ease;
226
275
  white-space: nowrap;
227
276
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
228
- pointer-events: none;
277
+ pointer-events: auto;
278
+ display: flex;
279
+ align-items: center;
280
+ gap: 8px;
229
281
  }
230
282
 
231
283
  .df-notification:after {
@@ -237,7 +289,7 @@
237
289
  height: 0;
238
290
  border-left: 6px solid transparent;
239
291
  border-right: 6px solid transparent;
240
- border-top: 6px solid #202124;
292
+ border-top: 6px solid ${config.background || "#FEFFFF"};
241
293
  }
242
294
 
243
295
  .df-notification.show {
@@ -245,6 +297,26 @@
245
297
  transform: translateY(0);
246
298
  }
247
299
 
300
+ .df-notification-close {
301
+ cursor: pointer;
302
+ width: 16px;
303
+ height: 16px;
304
+ display: flex;
305
+ align-items: center;
306
+ justify-content: center;
307
+ flex-shrink: 0;
308
+ opacity: 0.7;
309
+ transition: opacity 0.2s ease;
310
+ }
311
+
312
+ .df-notification-close:hover {
313
+ opacity: 1;
314
+ }
315
+
316
+ .df-notification-text {
317
+ flex: 1;
318
+ }
319
+
248
320
  .df-btn-text {
249
321
  min-width: 56px;
250
322
  color: ${config.fontColor || "#3c4043"};
@@ -268,7 +340,9 @@
268
340
  background-position: center;
269
341
  background-repeat: no-repeat;
270
342
  background-size: cover;
271
- background-image: url('${config.logo || origin + "/assets/chat-agent.jpg"}');
343
+ background-image: url('${
344
+ config.logo || origin + "/assets/chat-agent.jpg"
345
+ }');
272
346
  border-radius: 50%;
273
347
  width: 32px;
274
348
  height: 32px;
@@ -415,12 +489,25 @@
415
489
  }
416
490
 
417
491
  .df-btn-text:before {
418
- background-image: url('${config.logoDark || config.logo || origin + "/assets/chat-agent.jpg"}')
492
+ background-image: url('${
493
+ config.logoDark ||
494
+ config.logo ||
495
+ origin + "/assets/chat-agent.jpg"
496
+ }')
419
497
  }
420
498
 
421
499
  .df-btn:not(.df-closed) > .df-btn-text:before {
422
500
  background-image: url('${origin}/assets/close_dark.svg')
423
501
  }
502
+
503
+ .df-notification {
504
+ background: ${config.backgroundDark || "#171717"};
505
+ color: ${config.fontColorDark || "#FFFFFF"};
506
+ }
507
+
508
+ .df-notification:after {
509
+ border-top: 6px solid ${config.backgroundDark || "#171717"};
510
+ }
424
511
  }
425
512
 
426
513
  @keyframes shake {
@@ -462,7 +549,16 @@
462
549
  <button class="df-btn df-closed" onclick="dfToggle()">
463
550
  ${
464
551
  config.showNotification
465
- ? `<div class="df-notification">${config.hintMessage || "Click to check messages"}</div>`
552
+ ? `<div class="df-notification">
553
+ <span class="df-notification-text">${
554
+ config.hintMessage || "Click to check messages"
555
+ }</span>
556
+ <div class="df-notification-close" onclick="dismissNotification(event)">
557
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor">
558
+ <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"/>
559
+ </svg>
560
+ </div>
561
+ </div>`
466
562
  : ""
467
563
  }
468
564
  <div class="df-btn-header">
@@ -475,13 +571,60 @@
475
571
  `;
476
572
 
477
573
  // Insert button into DOM (works in async context unlike document.write)
478
- document.body.insertAdjacentHTML('beforeend', buttonHTML);
574
+ document.body.insertAdjacentHTML("beforeend", buttonHTML);
479
575
 
480
576
  let dfToggled = false;
481
577
  let inactivityTimer = null;
482
578
  let shakeInterval = null;
483
579
 
580
+ // Check if notification was dismissed
581
+ const NOTIFICATION_DISMISSED_KEY = `osw-notification-dismissed-${config.orgId}`;
582
+
583
+ function isNotificationDismissed() {
584
+ try {
585
+ return localStorage.getItem(NOTIFICATION_DISMISSED_KEY) === "true";
586
+ } catch (e) {
587
+ return false;
588
+ }
589
+ }
590
+
591
+ function dismissNotification(event) {
592
+ event.stopPropagation();
593
+ event.preventDefault();
594
+
595
+ const notification = document.querySelector(".df-notification");
596
+ if (notification) {
597
+ notification.classList.remove("show");
598
+ }
599
+
600
+ // Stop any ongoing shake animation
601
+ const button = document.querySelector(".df-btn");
602
+ if (button) {
603
+ button.classList.remove("shake");
604
+ }
605
+
606
+ // Clear timers
607
+ clearInactivityAndShake();
608
+
609
+ // Store dismissed state
610
+ try {
611
+ localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
612
+ } catch (e) {
613
+ console.warn(
614
+ "[OSW Widget] Could not save notification dismissed state:",
615
+ e
616
+ );
617
+ }
618
+ }
619
+
620
+ window.dismissNotification = dismissNotification;
621
+
484
622
  const startInactivityTimer = () => {
623
+ // Don't start timer if notification was dismissed
624
+ if (isNotificationDismissed()) {
625
+ return;
626
+ }
627
+
485
628
  // Only start inactivity timer if button is closed
486
629
  if (!dfToggled) {
487
630
  inactivityTimer = setTimeout(() => {
@@ -663,6 +806,28 @@
663
806
  btn.addEventListener("click", () => {
664
807
  // Only toggle if chat is closed (popover mode)
665
808
  if (btn.classList.contains("df-closed")) {
809
+ // Dismiss notification when opening chat
810
+ const notification = document.querySelector(".df-notification");
811
+ if (notification && notification.classList.contains("show")) {
812
+ notification.classList.remove("show");
813
+ }
814
+
815
+ // Stop any ongoing shake animation
816
+ btn.classList.remove("shake");
817
+
818
+ // Clear timers
819
+ clearInactivityAndShake();
820
+
821
+ // Store dismissed state
822
+ try {
823
+ localStorage.setItem(NOTIFICATION_DISMISSED_KEY, "true");
824
+ } catch (e) {
825
+ console.warn(
826
+ "[OSW Widget] Could not save notification dismissed state:",
827
+ e
828
+ );
829
+ }
830
+
666
831
  const isMobile = window.innerWidth <= 768;
667
832
 
668
833
  if (isMobile) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aumera-on-screen-widget",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "A lightweight, customizable chat widget for websites",
5
5
  "main": "df-btn.js",
6
6
  "scripts": {