@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 +10 -0
- package/package.json +1 -1
- package/src/app/app.component.ts +34 -2
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +2 -1
- package/src/app/component/home-conversations/home-conversations.component.scss +3 -3
- package/src/assets/js/chat21client.js +6 -7
- package/src/assets/twp/chatbot-panel.html +115 -17
- package/src/chat21-core/providers/chat-manager.ts +0 -1
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +32 -6
- package/src/chat21-core/providers/mqtt/mqtt-presence.service.ts +3 -3
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
package/src/app/app.component.ts
CHANGED
|
@@ -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
|
-
|
|
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() {
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -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,
|
|
@@ -979,12 +979,12 @@ class Chat21Client {
|
|
|
979
979
|
// clean: true,
|
|
980
980
|
reconnectPeriod: 1000,
|
|
981
981
|
// connectTimeout: 30 * 1000,
|
|
982
|
-
will: {
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
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
|
-
|
|
476
|
+
<script>
|
|
393
477
|
// non-blocking CSS delivery
|
|
394
|
-
var loadDeferredStyles = function() {
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
};
|
|
402
|
-
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
|
|
403
|
-
|
|
404
|
-
if (raf) {
|
|
405
|
-
|
|
406
|
-
} else {
|
|
407
|
-
|
|
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
|
-
//
|
|
134
|
-
if(
|
|
135
|
-
|
|
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
|
-
|
|
77
|
-
}, 2000);
|
|
75
|
+
// setTimeout(() => {
|
|
76
|
+
// this.chat21Service.chatClient.ImHere()
|
|
77
|
+
// }, 2000);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/**
|