@chat21/chat21-ionic 3.0.79-rc.1 → 3.0.79-rc.3

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 (83) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -0
  3. package/env.sample +1 -0
  4. package/package.json +1 -1
  5. package/src/app/app.component.html +7 -1
  6. package/src/app/app.component.scss +16 -1
  7. package/src/app/app.component.ts +182 -11
  8. package/src/app/app.module.ts +3 -1
  9. package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.html +37 -12
  10. package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.scss +55 -50
  11. package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.ts +24 -0
  12. package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.html +0 -18
  13. package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.scss +1 -10
  14. package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.ts +1 -22
  15. package/src/app/chatlib/conversation-detail/message/message-attachment/message-attachment.component.scss +1 -3
  16. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +1 -0
  17. package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.html +1 -2
  18. package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.scss +8 -5
  19. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +6 -5
  20. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +3 -82
  21. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  22. package/src/app/components/navbar/navbar.component.html +103 -0
  23. package/src/app/components/navbar/navbar.component.scss +249 -0
  24. package/src/app/components/{conversation-detail/bubble-my-message/bubble-my-message.component.spec.ts → navbar/navbar.component.spec.ts} +6 -6
  25. package/src/app/components/navbar/navbar.component.ts +189 -0
  26. package/src/app/components/project-item/project-item.component.ts +11 -1
  27. package/src/app/pages/contacts-directory/contacts-directory.page.scss +1 -1
  28. package/src/app/pages/conversation-detail/conversation-detail.module.ts +0 -8
  29. package/src/app/pages/conversation-detail/conversation-detail.page.ts +71 -2
  30. package/src/app/pages/conversations-list/conversations-list.page.scss +1 -0
  31. package/src/app/pages/conversations-list/conversations-list.page.ts +51 -22
  32. package/src/app/pages/create-canned-response/create-canned-response.page.ts +13 -13
  33. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +1 -1
  34. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +42 -0
  35. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +1 -0
  36. package/src/app/services/canned-responses/canned-responses.service.ts +26 -0
  37. package/src/app/services/projects/projects.service.spec.ts +12 -0
  38. package/src/app/services/projects/projects.service.ts +43 -0
  39. package/src/app/services/tiledesk/tiledesk.service.ts +1 -25
  40. package/src/app/shared/shared.module.ts +3 -12
  41. package/src/assets/i18n/ar.json +10 -2
  42. package/src/assets/i18n/az.json +9 -1
  43. package/src/assets/i18n/de.json +10 -2
  44. package/src/assets/i18n/en.json +10 -2
  45. package/src/assets/i18n/es.json +10 -2
  46. package/src/assets/i18n/fr.json +9 -1
  47. package/src/assets/i18n/it.json +9 -1
  48. package/src/assets/i18n/kk.json +10 -2
  49. package/src/assets/i18n/pt.json +10 -2
  50. package/src/assets/i18n/ru.json +9 -1
  51. package/src/assets/i18n/sr.json +277 -269
  52. package/src/assets/i18n/sv.json +10 -2
  53. package/src/assets/i18n/tr.json +10 -2
  54. package/src/assets/i18n/uk.json +10 -2
  55. package/src/assets/i18n/uz.json +9 -1
  56. package/src/assets/sounds/wheep-wheep.mp3 +0 -0
  57. package/src/chat-config-mqtt-localhost.json +1 -0
  58. package/src/chat-config-native-mqtt.json +1 -0
  59. package/src/chat-config-pre.json +2 -1
  60. package/src/chat-config-template.json +1 -0
  61. package/src/chat-config.json +1 -0
  62. package/src/chat21-core/models/conversation.ts +0 -1
  63. package/src/chat21-core/models/projects.ts +27 -0
  64. package/src/chat21-core/utils/constants.ts +1 -1
  65. package/src/chat21-core/utils/convertRequestToConversation.ts +41 -0
  66. package/src/global.scss +1 -13
  67. package/src/index.html +6 -47
  68. package/src/variables.scss +5 -2
  69. package/src/app/components/conversation-detail/bubble-day-message/bubble-day-message.component.html +0 -3
  70. package/src/app/components/conversation-detail/bubble-day-message/bubble-day-message.component.scss +0 -21
  71. package/src/app/components/conversation-detail/bubble-day-message/bubble-day-message.component.spec.ts +0 -24
  72. package/src/app/components/conversation-detail/bubble-day-message/bubble-day-message.component.ts +0 -14
  73. package/src/app/components/conversation-detail/bubble-my-message/bubble-my-message.component.html +0 -54
  74. package/src/app/components/conversation-detail/bubble-my-message/bubble-my-message.component.scss +0 -98
  75. package/src/app/components/conversation-detail/bubble-my-message/bubble-my-message.component.ts +0 -84
  76. package/src/app/components/conversation-detail/bubble-others-message/bubble-others-message.component.html +0 -30
  77. package/src/app/components/conversation-detail/bubble-others-message/bubble-others-message.component.scss +0 -83
  78. package/src/app/components/conversation-detail/bubble-others-message/bubble-others-message.component.spec.ts +0 -24
  79. package/src/app/components/conversation-detail/bubble-others-message/bubble-others-message.component.ts +0 -68
  80. package/src/app/components/conversation-detail/bubble-system-message/bubble-system-message.component.html +0 -3
  81. package/src/app/components/conversation-detail/bubble-system-message/bubble-system-message.component.scss +0 -10
  82. package/src/app/components/conversation-detail/bubble-system-message/bubble-system-message.component.spec.ts +0 -24
  83. package/src/app/components/conversation-detail/bubble-system-message/bubble-system-message.component.ts +0 -14
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # chat21-ionic ver 3.0
2
2
 
3
+ ### 3.0.79-rc.3
4
+ - added: segment analytics for SignIn-SignOut-Resolved-MsgAdded-ConvAdded
5
+ - added: navbar component if not mobile
6
+ - added: NAVBAR translations
7
+ - changed: minor improvements on UI
8
+ - changed: ion-split-pane UI if mobile
9
+ - changed: moved hover 'add canned' button from bubble-message to ion-conversation-detail component
10
+ - changed: moved addNewCanned to tiledesk service to canned-responses service
11
+ - bug-fixed: open/close detail icon not aligned correctly on click 'close'
12
+
13
+ ### 3.0.79-rc.2
14
+ - added: new sound if new conversation is triggered in agent's chat
15
+ - changed: header UI of header-conversation-detail and unassigned-conversations components
16
+
3
17
  ### 3.0.79-rc.1
4
18
  - added: LABEL_ONLINE, LABEL_OFFLINE translations
5
19
  - changed: renamed ddp-header with conversations-list-header
package/README.md CHANGED
@@ -101,6 +101,7 @@ Use [Docker Compose Tiledesk installation guide](https://github.com/Tiledesk/til
101
101
  "apiUrl": "https://<YOUR-TILEDESK-API-URL>",
102
102
  "baseImageUrl": "https://<YOUR-BASE-IMAGE-URL>",
103
103
  "dashboardUrl": "https://<YOUR-DASHBOARD-URL>"
104
+ "testsiteBaseUrl": "https:<YOUR-WIDGET-URL>/test_widget_page/index.html"
104
105
  "wsUrl": 'ws://' + window.location.hostname + '/ws/',
105
106
  }
106
107
  };
package/env.sample CHANGED
@@ -1,5 +1,6 @@
1
1
  API_BASEIMAGE_URL=CHANGEIT
2
2
  DASHBOARD_URL=https://YOUR_DASHBOARD_URL
3
+ WIDGET_TEST_LOCATION=https://YOUR_WIDGET_URL/index.html
3
4
  WS_URL=wss://YOUR_TILEDESK_SERVER_URL?token=
4
5
  WS_URL_RELATIVE=********
5
6
  SERVER_BASE_URL=http://localhost:3000/
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-ionic",
3
3
  "author": "Tiledesk SRL",
4
- "version": "3.0.79-rc.1",
4
+ "version": "3.0.79-rc.3",
5
5
  "license": "MIT License",
6
6
  "homepage": "https://tiledesk.com/",
7
7
  "repository": {
@@ -5,6 +5,12 @@
5
5
 
6
6
  <app-network-offline></app-network-offline>
7
7
 
8
+
9
+ <app-navbar *ngIf="!IS_ON_MOBILE_DEVICE"
10
+ [isSoundEnabled]="isSoundEnabled"
11
+ (onSoundChange)="onSoundChange($event)">
12
+ </app-navbar>
13
+
8
14
  <div class="sidebar" [ngClass]="{'hide-sidebar': IS_ONLINE === false || IS_ON_MOBILE_DEVICE === true || SUPPORT_MODE === false}">
9
15
  <app-sidebar></app-sidebar>
10
16
  </div>
@@ -13,7 +19,7 @@
13
19
  <app-sidebar-user-details> </app-sidebar-user-details>
14
20
  </div>
15
21
 
16
- <ion-split-pane when="md" contentId="main">
22
+ <ion-split-pane when="md" contentId="main" [ngClass]="{'mobile': IS_ON_MOBILE_DEVICE}">
17
23
  <!-- 'sidebar-visible': IS_ONLINE === true && SUPPORT_MODE === true, -->
18
24
  <ion-nav #sidebarNav [root]="sidebarPage" [ngClass]="{'sidebar-hidden': IS_ON_MOBILE_DEVICE === true || SUPPORT_MODE === false}"></ion-nav>
19
25
  <!-- our side menu -->
@@ -1,10 +1,21 @@
1
1
  .split-pane-md.split-pane-visible > .split-pane-side {
2
2
  min-width: 360px; //312px;
3
3
  display: block; // Safari bug fix
4
- margin-left: 60px;
4
+ margin-left: var(--sidebar-width);
5
5
  --border: 0px;
6
6
  }
7
7
 
8
+ .split-pane-md:not(.mobile){
9
+ height: calc( 100% - var(--nav-bar-heigth));
10
+ margin-top: var(--nav-bar-heigth);
11
+ }
12
+
13
+ .navbar{
14
+ display: flex;
15
+ position: fixed;
16
+ top: 0px;
17
+ }
18
+
8
19
  .sidebar-visible {
9
20
  margin-left: 60px;
10
21
  }
@@ -21,6 +32,10 @@
21
32
  left: 60px
22
33
  }
23
34
 
35
+ // ion-nav {
36
+ // background-color: var(--list-bkg-color);
37
+ // }
38
+
24
39
  // @media (min-width: 768px) {
25
40
  // .split-pane-md.split-pane-visible > .split-pane-side {
26
41
  // min-width: 312px;
@@ -1,8 +1,9 @@
1
- import { tranlatedLanguage, URL_SOUND_LIST_CONVERSATION } from './../chat21-core/utils/constants';
1
+ import { TYPE_DIRECT, TYPE_SUPPORT_GROUP } from 'src/chat21-core/utils/constants';
2
+ import { tranlatedLanguage, URL_SOUND_CONVERSATION_ADDED, URL_SOUND_LIST_CONVERSATION } from './../chat21-core/utils/constants';
2
3
  import { ArchivedConversationsHandlerService } from 'src/chat21-core/providers/abstract/archivedconversations-handler.service';
3
4
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
4
5
 
5
- import { Component, ViewChild, NgZone, OnInit, HostListener, ElementRef, Renderer2, AfterViewInit, } from '@angular/core';
6
+ import { Component, ViewChild, NgZone, OnInit, HostListener, ElementRef, Renderer2, AfterViewInit, isDevMode} from '@angular/core';
6
7
  import { Config, Platform, IonRouterOutlet, IonSplitPane, NavController, MenuController, AlertController, IonNav, ToastController } from '@ionic/angular';
7
8
  import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
8
9
  import { Subscription, VirtualTimeScheduler } from 'rxjs';
@@ -86,11 +87,13 @@ export class AppComponent implements OnInit {
86
87
  public authModal: any;
87
88
 
88
89
  private audio: any;
90
+ private audio_NewConv: any;
89
91
  private setIntervalTime: any;
90
92
  private setTimeoutSound: any;
91
93
  private isTabVisible: boolean = true;
92
- private isSoundEnabled: boolean;
94
+ public isSoundEnabled: boolean;
93
95
  private hasPlayed: boolean;
96
+ private hasPlayedConversation: boolean;
94
97
  private tabTitle: string;
95
98
  private setTimeoutConversationsEvent: any;
96
99
  private logger: LoggerService = LoggerInstance.getInstance();
@@ -316,7 +319,6 @@ export class AppComponent implements OnInit {
316
319
  // this.initializeApp('oninit');
317
320
  const token = getParameterByName('jwt')
318
321
  // this.logger.log('[APP-COMP] ngOnInit AUTOLOGIN token get with getParameterByName -->', token);
319
-
320
322
  if (token) {
321
323
  // this.isOnline = false;
322
324
  // this.logger.log('[APP-COMP] ngOnInit AUTOLOGIN token get with this.isOnline ', this.isOnline)
@@ -831,6 +833,10 @@ export class AppComponent implements OnInit {
831
833
  this.audio.src = chatBaseUrl + URL_SOUND_LIST_CONVERSATION;
832
834
  this.audio.load();
833
835
 
836
+ this.audio_NewConv = new Audio();
837
+ this.audio_NewConv.src = chatBaseUrl + URL_SOUND_CONVERSATION_ADDED;
838
+ this.audio_NewConv.load();
839
+
834
840
  const sound_status = localStorage.getItem('dshbrd----sound')
835
841
  if(sound_status && sound_status !== 'undefined'){
836
842
  this.isSoundEnabled = sound_status === 'enabled'? true: false
@@ -840,7 +846,14 @@ export class AppComponent implements OnInit {
840
846
 
841
847
  }
842
848
 
843
- private manageTabNotification(badgeNotificationCount?: number) {
849
+ onSoundChange(event){
850
+ if(event && event !== undefined){
851
+ localStorage.setItem('dshbrd----sound', event)
852
+ this.isSoundEnabled = event === 'enabled'? true: false
853
+ }
854
+ }
855
+
856
+ private manageTabNotification(sound_type: string, badgeNotificationCount?: number) {
844
857
  if (!this.isTabVisible) {
845
858
  // TAB IS HIDDEN --> manage title and SOUND
846
859
  let badgeNewConverstionNumber = badgeNotificationCount? badgeNotificationCount : this.conversationsHandlerService.countIsNew()
@@ -864,7 +877,9 @@ export class AppComponent implements OnInit {
864
877
  this.isSoundEnabled = sound_status === 'enabled'? true: false
865
878
  }
866
879
  this.logger.debug('[APP-COMP] manageTabNotification can saund?', this.isInitialized, this.isSoundEnabled)
867
- if(this.isInitialized && this.isSoundEnabled) this.soundMessage()
880
+ if(this.isInitialized && this.isSoundEnabled) {
881
+ sound_type === 'conv_added'? this.soundConversationAdded(): this.soundMessage();
882
+ }
868
883
  }
869
884
 
870
885
  soundMessage() {
@@ -880,7 +895,7 @@ export class AppComponent implements OnInit {
880
895
  // }, 4000);
881
896
 
882
897
  //play sound every 4s from the fist time you receive a conversation added/changed
883
- if(!this.hasPlayed){
898
+ if(!this.hasPlayed && !this.hasPlayedConversation){
884
899
  that.audio.play().then(() => {
885
900
  that.hasPlayed = true
886
901
  that.logger.debug('[APP-COMP] ****** soundMessage played *****');
@@ -892,6 +907,22 @@ export class AppComponent implements OnInit {
892
907
  });
893
908
  }
894
909
  }
910
+
911
+ soundConversationAdded(){
912
+ const that = this;
913
+ console.log('soundConversationAdded ENABLEDDDD-->', this.hasPlayed)
914
+ if(!this.hasPlayedConversation ){
915
+ that.audio_NewConv.play().then(() => {
916
+ that.hasPlayedConversation = true
917
+ that.logger.debug('[APP-COMP] ****** soundConversationAdded played *****');
918
+ setTimeout(() => {
919
+ that.hasPlayedConversation = false
920
+ }, 4000);
921
+ }).catch((error: any) => {
922
+ that.logger.error('[APP-COMP] ***soundConversationAdded error*', error);
923
+ });
924
+ }
925
+ }
895
926
  /**---------------- SOUND FUNCTIONS --> END <--- +*/
896
927
  /***************************************************+*/
897
928
 
@@ -943,7 +974,7 @@ export class AppComponent implements OnInit {
943
974
  this.conversationsHandlerService.conversationAdded.subscribe((conversation: ConversationModel) => {
944
975
  // this.logger.log('[APP-COMP] ***** subscribeConversationAdded *****', conversation);
945
976
  if (conversation && conversation.is_new === true) {
946
- this.manageTabNotification()
977
+ this.manageTabNotification('conv_added')
947
978
  }
948
979
  if(conversation) this.updateConversationsOnStorage()
949
980
  });
@@ -961,7 +992,7 @@ export class AppComponent implements OnInit {
961
992
  this.logger.log('[APP-COMP] ***** subscribeConversationChangedDetailed currentUser: ', currentUser);
962
993
  if (changes.value && changes.value.sender !== currentUser.uid) {
963
994
  if(changes.value.is_new === changes.previousValue.is_new){
964
- this.manageTabNotification();
995
+ this.manageTabNotification('new_message');
965
996
  }
966
997
  }
967
998
  }
@@ -969,7 +1000,10 @@ export class AppComponent implements OnInit {
969
1000
 
970
1001
  this.conversationsHandlerService.conversationRemoved.subscribe((conversation: ConversationModel) => {
971
1002
  this.logger.log('[APP-COMP] ***** conversationRemoved *****', conversation);
972
- if(conversation) this.updateConversationsOnStorage();
1003
+ if(conversation) {
1004
+ this.updateConversationsOnStorage();
1005
+ isDevMode()? null: this.segmentResolved(conversation)
1006
+ }
973
1007
  });
974
1008
  }
975
1009
 
@@ -1014,6 +1048,7 @@ export class AppComponent implements OnInit {
1014
1048
 
1015
1049
  this.initConversationsHandler(currentUser.uid);
1016
1050
  this.initArchivedConversationsHandler(currentUser.uid);
1051
+ isDevMode()? null: this.segmentSignIn(currentUser)
1017
1052
  }
1018
1053
  this.checkPlatform();
1019
1054
  try {
@@ -1035,6 +1070,8 @@ export class AppComponent implements OnInit {
1035
1070
  if (this.SUPPORT_MODE === true) {
1036
1071
  this.webSocketClose()
1037
1072
  }
1073
+ const currentUser = this.tiledeskAuthService.getCurrentUser();
1074
+ isDevMode()? null: this.segmentSignedOut(currentUser)
1038
1075
  // this.isOnline = false;
1039
1076
  // this.conversationsHandlerService.conversations = [];
1040
1077
  this.chatManager.setTiledeskToken(null);
@@ -1054,7 +1091,7 @@ export class AppComponent implements OnInit {
1054
1091
 
1055
1092
  // this.unsubscribe$.next();
1056
1093
  // this.unsubscribe$.complete();
1057
-
1094
+
1058
1095
  }
1059
1096
 
1060
1097
  goToDashboardLogin(){
@@ -1261,6 +1298,119 @@ export class AppComponent implements OnInit {
1261
1298
  }
1262
1299
  }
1263
1300
 
1301
+ segmentSignIn(user: UserModel){
1302
+ try {
1303
+ window['analytics'].page("Chat Auth Page, Signin", {});
1304
+ } catch (err) {
1305
+ this.logger.error('Event:Signed In [page] error', err);
1306
+ }
1307
+
1308
+ try {
1309
+ window['analytics'].identify(user.uid, {
1310
+ name: user.firstname + ' ' + user.lastname,
1311
+ email: user.email,
1312
+ logins: 5,
1313
+
1314
+ });
1315
+ } catch (err) {
1316
+ this.logger.error('Event:Signed In [identify] error', err);
1317
+ }
1318
+ // Segments
1319
+ try {
1320
+ window['analytics'].track('Signed In', {
1321
+ "username": user.firstname + ' ' + user.lastname,
1322
+ "userId": user.uid
1323
+ });
1324
+ } catch (err) {
1325
+ this.logger.error('Event:Signed In [track] error', err);
1326
+ }
1327
+ }
1328
+
1329
+
1330
+ segmentSignedOut(user: UserModel){
1331
+ try {
1332
+ window['analytics'].page("Chat Auth Page, Signed Out", {});
1333
+ } catch (err) {
1334
+ this.logger.error('Event:Signed Out [page] error', err);
1335
+ }
1336
+
1337
+ try {
1338
+ window['analytics'].identify(user.uid, {
1339
+ name: user.firstname + ' ' + user.lastname,
1340
+ email: user.email,
1341
+ logins: 5,
1342
+
1343
+ });
1344
+ } catch (err) {
1345
+ this.logger.error('Event:Signed Out [identify] error', err);
1346
+ }
1347
+
1348
+ try {
1349
+ window['analytics'].track('Signed Out', {
1350
+ "username": user.firstname + ' ' + user.lastname,
1351
+ "userId": user.uid
1352
+ });
1353
+ } catch (err) {
1354
+ this.logger.error('Event:Signed Out [track] error', err);
1355
+ }
1356
+
1357
+ try {
1358
+ // setTimeout(() => {
1359
+ window['analytics'].reset()
1360
+ // }, 0);
1361
+ } catch (err) {
1362
+ this.logger.error('Event:reset error', err);
1363
+ }
1364
+ }
1365
+
1366
+ segmentResolved(conversation: ConversationModel){
1367
+ let user = this.tiledeskAuthService.getCurrentUser();
1368
+ try {
1369
+ window['analytics'].page("Chat List Conversations Page, Chat Resolved", {});
1370
+ } catch (err) {
1371
+ this.logger.error('Event:Chat Resolved [page] error', err);
1372
+ }
1373
+
1374
+ try {
1375
+ window['analytics'].identify(user.uid, {
1376
+ name: user.firstname + ' ' + user.lastname,
1377
+ email: user.email,
1378
+ logins: 5,
1379
+
1380
+ });
1381
+ } catch (err) {
1382
+ this.logger.error('Event:Chat Resolved [identify] error', err);
1383
+ }
1384
+
1385
+ try {
1386
+ window['analytics'].track('Chat Resolved', {
1387
+ "username": user.firstname + ' ' + user.lastname,
1388
+ "userId": user.uid,
1389
+ "conversation_id": conversation.uid,
1390
+ "channel_type": conversation.channel_type,
1391
+ "conversation_with":(conversation.channel_type !== TYPE_DIRECT)? null: conversation.conversation_with,
1392
+ "conversation_with_fullname": (conversation.channel_type !== TYPE_DIRECT)? null: conversation.conversation_with_fullname,
1393
+ "department_name":(conversation.channel_type !== TYPE_DIRECT)? conversation.attributes.departmentName: null,
1394
+ "department_id":(conversation.channel_type !== TYPE_DIRECT)? conversation.attributes.departmentId: null,
1395
+ },
1396
+ { "context": {
1397
+ "groupId": (conversation.channel_type !== TYPE_DIRECT)? conversation.attributes.projectId: null
1398
+ }
1399
+ });
1400
+ } catch (err) {
1401
+ this.logger.error('Event:Chat Resolved [track] error', err);
1402
+ }
1403
+
1404
+ try {
1405
+ window['analytics'].group(conversation.attributes.projectId, {
1406
+ name: (conversation.attributes.project_name)? conversation.attributes.project_name : null,
1407
+ // plan: projectProfileName,
1408
+ });
1409
+ } catch (err) {
1410
+ this.logger.error('Event:Chat Resolved [group] error', err);
1411
+ }
1412
+ }
1413
+
1264
1414
 
1265
1415
  @HostListener('document:visibilitychange', [])
1266
1416
  visibilitychange() {
@@ -1325,5 +1475,26 @@ export class AppComponent implements OnInit {
1325
1475
  this.isSoundEnabled = event.newValue === 'enabled'? true: false
1326
1476
  }
1327
1477
  }
1478
+
1479
+
1480
+ // @HostListener('mouseenter', ['$event'])
1481
+ // onMouseEnter(event: any) {
1482
+ // console.log('HostListener onMouseEnter-->', event)
1483
+ // }
1484
+
1485
+ // @HostListener('mouseleave', ['$event'])
1486
+ // onMouseLeave(event: any) {
1487
+ // console.log('HostListener onMouseLeave-->', event)
1488
+ // }
1489
+
1490
+ // @HostListener('focus', ['$event'])
1491
+ // onFocus(event: any) {
1492
+ // console.log('HostListener onFocus-->', event)
1493
+ // }
1494
+
1495
+ // @HostListener('blur', ['$event'])
1496
+ // onBlur(event: any) {
1497
+ // console.log('HostListener onBlur-->', event)
1498
+ // }
1328
1499
  }
1329
1500
 
@@ -1,3 +1,4 @@
1
+ import { ConvertRequestToConversation } from './../chat21-core/utils/convertRequestToConversation';
1
2
  import { LogLevel, PUSH_ENGINE_FIREBASE, PUSH_ENGINE_MQTT } from './../chat21-core/utils/constants';
2
3
  import { CustomLogger } from 'src/chat21-core/providers/logger/customLogger';
3
4
  import { NgModule, ErrorHandler, APP_INITIALIZER } from '@angular/core';
@@ -369,7 +370,8 @@ const appInitializerFn = (appConfig: AppConfigProvider, logger: NGXLogger) => {
369
370
  EventsService,
370
371
  Chooser,
371
372
  Chat21Service,
372
- WebSocketJs
373
+ WebSocketJs,
374
+ ConvertRequestToConversation
373
375
  ]
374
376
  })
375
377
  export class AppModule { }
@@ -88,6 +88,17 @@
88
88
  <!-- message SENDER:: -->
89
89
  <div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_MINE, message)" class="msg_container base_sent">
90
90
 
91
+ <div class="message-date-hover"> {{message.timestamp | date:'HH:mm' }} </div>
92
+
93
+ <ng-container *ngIf="areVisibleCAR && supportMode">
94
+ <ion-button shape="round" size="small" class="btn-add-msg canned" ion-button fill="clear"
95
+ (click)="presentCreateCannedResponseModal(message)" [tooltip]="addAsCannedResponseTooltipText"
96
+ [options]="tooltipOptions" placement="bottom">
97
+ <ion-icon slot="icon-only" name="flash-outline" style="font-size: 1em;"> </ion-icon>
98
+ <span class="add-canned-response-add-icon">+</span>
99
+ </ion-button>
100
+ </ng-container>
101
+
91
102
  <!--backgroundColor non viene ancora usato -->
92
103
  <chat-bubble-message class="messages msg_sent" id="message_msg_sent" style="position: relative;"
93
104
  [ngClass]="{'has-metadata': (isImage(message) || isFrame(message)), 'privateMsg': (message?.attributes && message?.attributes?.subtype === 'private')}"
@@ -98,9 +109,6 @@
98
109
  [fontColor]="stylesMap.get('bubbleSentTextColor')"
99
110
  [fontSize]="stylesMap.get('fontSize')"
100
111
  [fontFamily]="stylesMap.get('fontFamily')"
101
- [addAsCannedResponseTooltipText]="addAsCannedResponseTooltipText"
102
- [areVisibleCAR]="areVisibleCAR"
103
- [supportMode]="supportMode"
104
112
  (onBeforeMessageRender)="onBeforeMessageRenderFN($event)"
105
113
  (onAfterMessageRender)="onAfterMessageRenderFN($event)"
106
114
  (onElementRendered)="onElementRenderedFN($event)">
@@ -115,11 +123,14 @@
115
123
 
116
124
  </div>
117
125
 
118
- <!-- message RECIPIENT:: -->
119
- <div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_OTHERS, message) && isChannelTypeGroup(channelType) && !isSameSender(message?.sender, i)"
120
- class="message_sender_fullname">
121
- {{message.sender_fullname}}
126
+ <!-- message RECIPIENT + TIME :: -->
127
+ <div class="msg_container base_receive" *ngIf="messageType(MESSAGE_TYPE_OTHERS, message) && isChannelTypeGroup(channelType) && !isSameSender(message?.sender, i)">
128
+ <div role="messaggio" class="message_sender_fullname">
129
+ {{message.sender_fullname}}
130
+ </div>
131
+ <div class="message-date"> {{message.timestamp | date:'HH:mm' }} </div>
122
132
  </div>
133
+ <!-- message RECIPIENT :: -->
123
134
  <div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_OTHERS, message)" class="msg_container base_receive">
124
135
 
125
136
  <!-- <chat-avatar-image class="slide-in-left"
@@ -129,8 +140,7 @@
129
140
  </chat-avatar-image> -->
130
141
 
131
142
  <!--backgroundColor non viene ancora usato -->
132
-
133
- <chat-bubble-message class="messages msg_receive" id="message_msg_receive" style="position: relative;"
143
+ <chat-bubble-message class="messages msg_receive" id="message_msg_receive"
134
144
  [ngClass]="{'has-metadata': (isImage(message) || isFrame(message)), 'privateMsg': (message?.attributes && message?.attributes?.subtype === 'private')}"
135
145
  [class.emoticon]="isEmojii(message?.text)"
136
146
  [ngStyle]="{'background': stylesMap?.get('bubbleReceivedBackground'), 'color': stylesMap.get('bubbleReceivedTextColor')}"
@@ -138,13 +148,28 @@
138
148
  [fontColor]="stylesMap?.get('bubbleReceivedTextColor')"
139
149
  [fontSize]="stylesMap?.get('fontSize')"
140
150
  [fontFamily]="stylesMap?.get('fontFamily')"
141
- [addAsCannedResponseTooltipText]="addAsCannedResponseTooltipText"
142
- [areVisibleCAR]="areVisibleCAR"
143
- [supportMode]="supportMode"
144
151
  (onBeforeMessageRender)="onBeforeMessageRenderFN($event)"
145
152
  (onAfterMessageRender)="onAfterMessageRenderFN($event)"
146
153
  (onElementRendered)="onElementRenderedFN($event)">
147
154
  </chat-bubble-message>
155
+
156
+ <ng-container *ngIf="areVisibleCAR && supportMode">
157
+ <ion-button shape="round" size="small" class="btn-add-msg canned" ion-button fill="clear"
158
+ (click)="presentCreateCannedResponseModal(message)" [tooltip]="addAsCannedResponseTooltipText"
159
+ [options]="tooltipOptions" placement="bottom">
160
+ <ion-icon slot="icon-only" name="flash-outline" style="font-size: 1em;"> </ion-icon>
161
+ <span class="add-canned-response-add-icon">+</span>
162
+ </ion-button>
163
+ </ng-container>
164
+ <!-- <ng-container *ngIf="supportMode">
165
+ <ion-button shape="round" size="small" class="btn-add-msg emoji" ion-button fill="clear"
166
+ (click)="presentEmojiiModal()" tooltip="{{addAsCannedResponseTooltipText}}"
167
+ [options]="tooltipOptions" placement="bottom">
168
+ <ion-icon slot="icon-only" name="happy-outline" style="font-size: 1em;"> </ion-icon>
169
+ </ion-button>
170
+ </ng-container> -->
171
+
172
+ <div class="message-date-hover" *ngIf="(isChannelTypeGroup(channelType) && isSameSender(message?.sender, i)) || !isChannelTypeGroup(channelType)"> {{message.timestamp | date:'HH:mm' }} </div>
148
173
  </div>
149
174
 
150
175
  <!-- message type:: button && -->
@@ -48,12 +48,15 @@
48
48
 
49
49
  &.close{
50
50
  right: 0px;
51
+ &:not(.mobile){
52
+ top: calc(60px + var(--padding-conversation-detail));
53
+ }
51
54
  }
52
55
 
53
56
  &.mobile{
54
57
  right: 0px;
55
58
  }
56
- &:not(.mobile){
59
+ &:not(.mobile):not(.close){
57
60
  right: calc(300px + var(--padding-conversation-detail));
58
61
  top: calc(60px + var(--padding-conversation-detail));
59
62
  }
@@ -110,7 +113,7 @@ ion-item {
110
113
 
111
114
  .message_sender_fullname {
112
115
  font-size: 0.9em;
113
- margin: 0 0 1px 20px;
116
+ margin: 0px 10px 0px 10px;
114
117
  // color: var(--gray);
115
118
  font-weight: 500;
116
119
  color: #080f1a;
@@ -153,12 +156,16 @@ ion-item {
153
156
  align-items: flex-end;
154
157
  justify-content: flex-end;
155
158
  // padding: 2px 0px 4px 40px;
156
- padding: 2px 0px 14px 40px; // edited to display the date at the bottom of the "message bubble"
159
+ padding: 0px 0px 6px 40px;
160
+
161
+ &:hover .message-date-hover, &:hover .btn-add-msg{
162
+ display: block;
163
+ }
164
+
157
165
  .msg_sent {
158
166
  background-color: var(--bubble-blue);
159
167
  color: var(--col-msg-sent);
160
- margin-right: 4px;
161
- margin-left: 4px;
168
+ margin: 0px 0px 0px 0px;
162
169
  max-width: calc(100% - 70px);
163
170
  min-width: 14px;
164
171
  border-top-right-radius: 8px;
@@ -183,8 +190,17 @@ ion-item {
183
190
 
184
191
  /** recive message **/
185
192
  .base_receive {
186
- // padding: 0px 0px 6px 0px;
187
- padding: 0px 0px 15px 10px; // edited to display the date at the bottom of the "message bubble"
193
+ padding: 0px 20px 6px 0px;
194
+ .message-date{
195
+ color: #647491;
196
+ font-size: 12px;
197
+ align-self: center;
198
+ }
199
+
200
+
201
+ &:hover .message-date-hover, &:hover .btn-add-msg{
202
+ display: block;
203
+ }
188
204
  /* avatar */
189
205
  .content-avatar {
190
206
  position: relative;
@@ -218,7 +234,7 @@ ion-item {
218
234
  // max-width: 260px;
219
235
  max-width: calc(100% - 70px);
220
236
  min-width: 14px;
221
- margin: 0 20px 4px 10px;
237
+ margin: 0 0px 0px 10px;
222
238
  height: fit-content;
223
239
  width: auto;
224
240
  border-top-left-radius: 8px;
@@ -241,8 +257,37 @@ ion-item {
241
257
 
242
258
  }
243
259
 
244
- .time {
245
- margin-bottom: 20px;
260
+ .message-date-hover{
261
+ color: #647491;
262
+ font-size: 12px;
263
+ align-self: center;
264
+
265
+ display: none;
266
+
267
+ }
268
+
269
+ .btn-add-msg {
270
+ border-radius: 50%;
271
+ --padding-end: 7px;
272
+ --padding-start: 7px;
273
+ box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.13);
274
+ display: none;
275
+ align-self: center;
276
+ margin: 0px 5px;
277
+
278
+ ion-icon{
279
+ font-size: 1.2em;
280
+ color: var(--basic-blue)
281
+ }
282
+
283
+ .add-canned-response-add-icon{
284
+ color: var(--basic-blue);
285
+ cursor: pointer;
286
+ position: relative;
287
+ top: 6px;
288
+ left: -6px;
289
+ font-size: 9px;
290
+ }
246
291
  }
247
292
 
248
293
  /* LOADING */
@@ -317,28 +362,6 @@ ion-item {
317
362
  // left: -26px;
318
363
  }
319
364
 
320
- :host .base_receive .msg_receive ::ng-deep div > div > div > ion-button.canned {
321
- display: none;
322
- position: absolute;
323
- top: -3px;
324
- right: -31px;
325
- }
326
-
327
- :host .base_receive .msg_receive ::ng-deep div > div > div >ion-button.emoji {
328
- display: none;
329
- position: absolute;
330
- top: -3px;
331
- right: -51px;
332
- }
333
-
334
- // :host .base_receive .msg_receive:hover ::ng-deep div > div > ion-button {
335
- :host .base_receive:hover .msg_receive ::ng-deep div > div > div > ion-button {
336
- display: block;
337
- // position: absolute;
338
- // top: -11px;
339
- // left: 91px;
340
- }
341
-
342
365
  // ---------------------------------------------------------
343
366
  // Long date divider
344
367
  // ---------------------------------------------------------
@@ -367,24 +390,6 @@ ion-item {
367
390
  color: #64748b;
368
391
  }
369
392
 
370
- // ---------------------------------------------------------
371
- // message date
372
- // ---------------------------------------------------------
373
- :host .base_sent .msg_sent ::ng-deep div > div > div > .message-date {
374
- position: absolute;
375
- bottom: -11px;
376
- color: #64748b;
377
- font-size: 10px;
378
- right: 0px;
379
- }
380
-
381
- :host .base_receive .msg_receive ::ng-deep div > div > .message-date {
382
- position: absolute;
383
- bottom: -11px;
384
- color: #64748b;
385
- font-size: 10px;
386
- left: 0px;
387
- }
388
393
  // ---------------------------------------------------------
389
394
  // emoticon
390
395
  // ---------------------------------------------------------