@chat21/chat21-web-widget 5.0.60 → 5.0.62

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # chat21-web-widget ver 5.0
2
2
 
3
+ ### 5.0.62 in PROD
4
+ - added: pending messages
5
+ - added: disconnect from messaging handler if no interaction exist within 1 minute
6
+ - bug-fixed: cannot able to send messages due to undefined in conversationHandlerService
7
+
8
+ ### 5.0.61-rc.1
9
+ - added: 'flags' emojii category in conversatio-footer component
10
+ - added: 'share prototype' button inside 'chatbot-panel.html' page to copy link to clipboard
11
+ - added: forceDisconnet var to disconnet messaging client if no interaction is handled within 60s
12
+
3
13
  ### 5.0.60 in PROD
4
14
 
5
15
  ### 5.0.60-rc.2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.0.60",
4
+ "version": "5.0.62",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -103,6 +103,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
103
103
  styleMapConversation: Map<string, string> = new Map();
104
104
  marginBottom: number;
105
105
 
106
+ forceDisconnect: boolean = false;
106
107
  private logger: LoggerService = LoggerInstance.getInstance();
107
108
  constructor(
108
109
  private el: ElementRef,
@@ -407,8 +408,12 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
407
408
  rules.initRules(that.g.windowContext, that.g.tiledeskToken, user, that.generateNewUidConversation(), that.g.botsRules)
408
409
  }
409
410
 
411
+ //if widget is closed subscribe to 'click' event and set a 60sec timer to disconnect if handler isn't fired
412
+ if(!this.g.isOpen){
413
+ that.listenToWidgetClick()
414
+ }
410
415
 
411
- } else if (state && state === AUTH_STATE_OFFLINE) {
416
+ } else if (state && state === AUTH_STATE_OFFLINE && !this.forceDisconnect) {
412
417
  /** non sono loggato */
413
418
  that.logger.info('[APP-COMP] OFFLINE - NO CURRENT USER AUTENTICATE: ');
414
419
  that.g.setParameter('isLogged', false);
@@ -427,7 +432,8 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
427
432
 
428
433
  const subUserLogOut = this.messagingAuthService.BSSignOut.subscribe((state) => {
429
434
  // that.ngZone.run(() => {
430
- if (state === true) { //state = true -> user has logged out
435
+ console.log('[FORCE] messagingAuthService BSSignOut', state, this.forceDisconnect)
436
+ if (state === true && !this.forceDisconnect) { //state = true -> user has logged out
431
437
  /** ho effettuato il logout: nascondo il widget */
432
438
  that.logger.debug('[APP-COMP] sono nel caso logout -1');
433
439
  // that.g.wdLog(['obsLoggedUser', obsLoggedUser);
@@ -1580,6 +1586,12 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
1580
1586
  this.g.setParameter('recipientId', recipientId);
1581
1587
  this.logger.debug('[APP-COMP] openCloseWidget', recipientId, this.g.isOpen, this.g.startFromHome);
1582
1588
  if (this.g.isOpen === false) {
1589
+ if(this.forceDisconnect){
1590
+ console.log('[FORCE] onOpenCloseWidget --> reconnect', this.forceDisconnect)
1591
+ this.messagingAuthService.createCustomToken(this.g.tiledeskToken)
1592
+ this.forceDisconnect = false;
1593
+ }
1594
+
1583
1595
  if (!recipientId) {
1584
1596
  if(this.g.singleConversation){
1585
1597
  this.isOpenHome = false;
@@ -1715,6 +1727,12 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
1715
1727
  public onSelectedConversation($event: ConversationModel) {
1716
1728
  if ($event) {
1717
1729
  if (this.g.isOpen === false) {
1730
+
1731
+ if(this.forceDisconnect){
1732
+ console.log('[FORCE] onSelectedConversation --> reconnect', this.forceDisconnect)
1733
+ this.messagingAuthService.createCustomToken(this.g.tiledeskToken)
1734
+ this.forceDisconnect = false;
1735
+ }
1718
1736
  //this.f21_open();
1719
1737
  this._f21_open()
1720
1738
  }
@@ -2075,6 +2093,20 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
2075
2093
  }
2076
2094
  }
2077
2095
 
2096
+
2097
+ private listenToWidgetClick(){
2098
+ let clickTimeout = setTimeout(() => {
2099
+ console.log('[FORCE] --> NO INTERACTION: disconnection... <--- ')
2100
+ //disconnect
2101
+ this.forceDisconnect = true
2102
+ this.messagingAuthService.logout()
2103
+ }, 60*1000);
2104
+ window.addEventListener("click", function(){
2105
+ console.log('[FORCE] <<INTERACTION>> within 1 minute')
2106
+ clearTimeout(clickTimeout)
2107
+ })
2108
+ }
2109
+
2078
2110
  // ========= begin:: DESTROY ALL SUBSCRIPTIONS ============//
2079
2111
  /** elimino tutte le sottoscrizioni */
2080
2112
  ngOnDestroy() {
@@ -68,7 +68,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
68
68
  showPreview: false,
69
69
  darkMode: false,
70
70
  enableSearch: false,
71
- include: [ 'recent', 'people', 'nature', 'activity']
71
+ include: [ 'recent', 'people', 'nature', 'activity', 'flags']
72
72
  }
73
73
 
74
74
  convertColorToRGBA = convertColorToRGBA;
@@ -342,6 +342,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
342
342
  channelType: channelType
343
343
  })
344
344
 
345
+ this.conversationHandlerService = this.chatManager.getConversationHandlerByConversationId(this.conversationWith);
345
346
  const messageSent = this.conversationHandlerService.sendMessage(
346
347
  msg,
347
348
  type,
@@ -239,9 +239,9 @@
239
239
  box-shadow: none;
240
240
  vertical-align: top;
241
241
 
242
- // button.c21-button-primary{
243
- // margin: 5px 0px;
244
- // }
242
+ button.c21-button-primary{
243
+ margin: 20px 0px;
244
+ }
245
245
  }
246
246
 
247
247
  .c21-footer{
@@ -979,12 +979,12 @@ class Chat21Client {
979
979
  // clean: true,
980
980
  reconnectPeriod: 1000,
981
981
  // connectTimeout: 30 * 1000,
982
- will: {
983
- topic: this.presence_topic,
984
- payload: '{"disconnected":true}',
985
- qos: 1,
986
- retain: true
987
- },
982
+ // will: {
983
+ // topic: this.presence_topic,
984
+ // payload: '{"disconnected":true}',
985
+ // qos: 1,
986
+ // retain: true
987
+ // },
988
988
  clientId: this.client_id,
989
989
  username: 'JWT',
990
990
  password: jwt,
@@ -992,7 +992,6 @@ class Chat21Client {
992
992
  }
993
993
  if (this.log) {console.log("starting mqtt connection with LWT on:", this.presence_topic, this.endpoint)}
994
994
  // client = mqtt.connect('mqtt://127.0.0.1:15675/ws',options)
995
- console.log("starting mqtt connection with LWT on:", this.presence_topic, this.endpoint)
996
995
  this.client = mqtt.connect(this.endpoint,options)
997
996
 
998
997
  this.client.on('connect', // TODO if token is wrong it must reply with an error!
@@ -158,6 +158,31 @@
158
158
  text-align: center;
159
159
  }
160
160
 
161
+ header#header{
162
+ z-index: 2;
163
+ position: absolute;
164
+ cursor: pointer;
165
+ }
166
+
167
+ .share-btn{
168
+ transition: color 0.15s ease 0s, opacity 0.15s ease 0s, box-shadow 0.15s ease 0s, background-color 0.15s ease 0s;
169
+ height: 41px;
170
+ box-sizing: border-box;
171
+ color: rgb(19, 33, 68);
172
+ font-weight: 600;
173
+ line-height: 22px;
174
+ background-size: 1px 41px;
175
+ padding: 10px 19px;
176
+ border-radius: 10px;
177
+ border: 1px solid rgb(255, 255, 255);
178
+ background-color: rgb(231, 240, 242);
179
+ box-shadow: rgb(204, 211, 228) 0px 0px 0px 1px;
180
+ }
181
+
182
+ .share-btn:hover{
183
+ opacity: 0.8;
184
+ }
185
+
161
186
  footer#footer {
162
187
  background-color: white;
163
188
  text-align: center;
@@ -190,7 +215,53 @@
190
215
  height: 24px;
191
216
  /* margin-left: 20px; */
192
217
  }
193
-
218
+
219
+ /* The snackbar - position it at the bottom and in the middle of the screen */
220
+ #snackbar {
221
+ visibility: hidden; /* Hidden by default. Visible on click */
222
+ min-width: 250px; /* Set a default minimum width */
223
+ margin-left: -125px; /* Divide value of min-width by 2 */
224
+ background-color: #504a4a; /* Black background color */
225
+ color: #fff; /* White text color */
226
+ text-align: center; /* Centered text */
227
+ border-radius: 10px; /* Rounded borders */
228
+ padding: 16px; /* Padding */
229
+ position: fixed; /* Sit on top of the screen */
230
+ z-index: 1; /* Add a z-index if needed */
231
+ left: 50%; /* Center the snackbar */
232
+ bottom: 30px; /* 30px from the bottom */
233
+ font-size: medium;
234
+ }
235
+
236
+ /* Show the snackbar when clicking on a button (class added with JavaScript) */
237
+ #snackbar.show {
238
+ visibility: visible; /* Show the snackbar */
239
+ /* Add animation: Take 0.5 seconds to fade in and out the snackbar.
240
+ However, delay the fade out process for 2.5 seconds */
241
+ -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
242
+ animation: fadein 0.5s, fadeout 0.5s 2.5s;
243
+ }
244
+
245
+ /* Animations to fade the snackbar in and out */
246
+ @-webkit-keyframes fadein {
247
+ from {bottom: 0; opacity: 0;}
248
+ to {bottom: 30px; opacity: 1;}
249
+ }
250
+
251
+ @keyframes fadein {
252
+ from {bottom: 0; opacity: 0;}
253
+ to {bottom: 30px; opacity: 1;}
254
+ }
255
+
256
+ @-webkit-keyframes fadeout {
257
+ from {bottom: 30px; opacity: 1;}
258
+ to {bottom: 0; opacity: 0;}
259
+ }
260
+
261
+ @keyframes fadeout {
262
+ from {bottom: 30px; opacity: 1;}
263
+ to {bottom: 0; opacity: 0;}
264
+ }
194
265
 
195
266
  </style>
196
267
 
@@ -367,15 +438,28 @@
367
438
  }
368
439
  return(false);
369
440
  }
441
+
442
+
443
+
370
444
  </script>
371
445
 
372
446
  </head>
373
447
 
374
448
  <body class="website white" >
449
+
450
+
375
451
  <div id="preloader">
376
452
  <div class="logo"></div>
377
453
  </div>
378
454
 
455
+ <header id="header">
456
+ <ul class="nav navbar-nav navbar-left">
457
+ <li class="sign-up"><button class="share-btn" onclick="copyLink()">SHARE THIS PROTOTYPE</button></li>
458
+ </ul>
459
+ </header>
460
+ <!-- The actual snackbar -->
461
+ <div id="snackbar">Copied to clipboard...</div>
462
+
379
463
  <div id="wrapper" class="mockup">
380
464
  </div>
381
465
 
@@ -389,24 +473,38 @@
389
473
  </footer>
390
474
 
391
475
 
392
- <!-- <script>
476
+ <script>
393
477
  // non-blocking CSS delivery
394
- var loadDeferredStyles = function() {
395
- var addStylesNode = document.getElementById("deferred-styles");
396
- console.log('addStylesNode ', addStylesNode)
397
- var replacement = document.createElement("div");
398
- replacement.innerHTML = addStylesNode.textContent;
399
- document.body.appendChild(replacement);
400
- addStylesNode.parentElement.removeChild(addStylesNode);
401
- };
402
- var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
403
- window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
404
- if (raf) {
405
- raf(function() { window.setTimeout(loadDeferredStyles, 0); });
406
- } else {
407
- window.addEventListener('load', loadDeferredStyles);
478
+ // var loadDeferredStyles = function() {
479
+ // var addStylesNode = document.getElementById("deferred-styles");
480
+ // console.log('addStylesNode ', addStylesNode)
481
+ // var replacement = document.createElement("div");
482
+ // replacement.innerHTML = addStylesNode.textContent;
483
+ // document.body.appendChild(replacement);
484
+ // addStylesNode.parentElement.removeChild(addStylesNode);
485
+ // };
486
+ // var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
487
+ // window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
488
+ // if (raf) {
489
+ // raf(function() { window.setTimeout(loadDeferredStyles, 0); });
490
+ // } else {
491
+ // window.addEventListener('load', loadDeferredStyles);
492
+ // }
493
+ function copyLink(){
494
+ let url = window.location.href
495
+ navigator.clipboard.writeText(url)
496
+
497
+ // Get the snackbar DIV
498
+ var toast = document.getElementById("snackbar");
499
+
500
+ // Add the "show" class to DIV
501
+ toast.className = "show";
502
+
503
+ // After 3 seconds, remove the show class from DIV
504
+ setTimeout(function(){ toast.className = toast.className.replace("show", ""); }, 3000);
505
+
408
506
  }
409
- </script> -->
507
+ </script>
410
508
 
411
509
  <!-- Google Analytics -->
412
510
 
@@ -184,7 +184,6 @@ export class ChatManager {
184
184
  getConversationHandlerByConversationId(conversationId): any {
185
185
  let handler = null;
186
186
  this.handlers.forEach(conv => {
187
- this.logger.log('[CHAT MANAGER]forEach ***', conversationId, this.handlers, conv);
188
187
  if (conv.conversationWith === conversationId) {
189
188
  handler = conv;
190
189
  return;
@@ -127,13 +127,19 @@ export class MQTTConversationHandler extends ConversationHandlerService {
127
127
  this.conversationWith, (message, topic) => {
128
128
  this.logger.log('[MQTTConversationHandlerSERVICE] message added:', message, 'on topic:', topic, this.messages);
129
129
  // this.addedMessage(msg);
130
- const msg: MessageModel = message;
131
- msg.uid = message.message_id;
130
+ const msg: MessageModel = message;
132
131
 
133
- //escape command message is already is in list checking by parendUid
134
- if(this.messages.filter(message => message.attributes['parentUid'] === msg.uid).length > 0){
135
- return;
132
+ //allow to replace message in unknown status (pending status: '0')
133
+ if(message.attributes && message.attributes.tempUID){
134
+ msg.uid = message.attributes.tempUID;
135
+ }else{
136
+ msg.uid = message.message_id
136
137
  }
138
+
139
+ //escape command message is already is in list checking by parendUid
140
+ // if(this.messages.filter(message => message.attributes['parentUid'] === msg.uid).length > 0){
141
+ // return;
142
+ // }
137
143
 
138
144
  if (msg.attributes && msg.attributes.commands) {
139
145
  this.logger.debug('[MQTTConversationHandlerSERVICE] splitted message::::', msg)
@@ -191,6 +197,7 @@ export class MQTTConversationHandler extends ConversationHandlerService {
191
197
  const recipientFullname = conversationWithFullname;
192
198
  const recipientId = conversationWith;
193
199
  attributes.lang = language;
200
+ attributes.tempUID = uuidv4(); //allow to show message in a pending status
194
201
  this.chat21Service.chatClient.sendMessage(
195
202
  msg,
196
203
  typeMsg,
@@ -210,6 +217,25 @@ export class MQTTConversationHandler extends ConversationHandlerService {
210
217
  }
211
218
  }
212
219
  );
220
+
221
+ const message = new MessageModel(
222
+ attributes.tempUID, //allow to show message in a pending status
223
+ language,
224
+ conversationWith,
225
+ recipientFullname,
226
+ sender,
227
+ senderFullname,
228
+ 0,
229
+ metadataMsg,
230
+ msg,
231
+ Date.now(),
232
+ typeMsg,
233
+ attributes,
234
+ channelType,
235
+ false
236
+ );
237
+ this.addedMessage(message) //allow to show message in a pending status: add pending message in array of messages
238
+
213
239
  return new MessageModel(
214
240
  '',
215
241
  language,
@@ -410,7 +436,7 @@ export class MQTTConversationHandler extends ConversationHandlerService {
410
436
  */
411
437
  private updateMessageStatusReceived(msg) {
412
438
  this.logger.log('[MQTTConversationHandlerSERVICE] updateMessageStatusReceived', msg);
413
- if (msg['status'] < MSG_STATUS_RECEIVED) {
439
+ if (msg['status'] < MSG_STATUS_RECEIVED && msg['status'] > 0) {
414
440
  this.logger.log('[MQTTConversationHandlerSERVICE] status ', msg['status'], ' < (RECEIVED:200)', MSG_STATUS_RECEIVED);
415
441
  let uid = msg.uid
416
442
  msg.attributes.commands? uid = msg.attributes.parentUid: null
@@ -72,9 +72,9 @@ export class MQTTPresenceService extends PresenceService {
72
72
 
73
73
  public imHere(): void {
74
74
  this.logger.debug('[MQTT-PRESENCE] imHere', this.tenant);
75
- setTimeout(() => {
76
- this.chat21Service.chatClient.ImHere()
77
- }, 2000);
75
+ // setTimeout(() => {
76
+ // this.chat21Service.chatClient.ImHere()
77
+ // }, 2000);
78
78
  }
79
79
 
80
80
  /**