@chat21/chat21-ionic 3.4.27-rc8 → 3.4.28

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 (153) hide show
  1. package/CHANGELOG.md +6 -48
  2. package/angular.json +0 -1
  3. package/package.json +1 -1
  4. package/src/app/app.component.ts +13 -68
  5. package/src/app/chatlib/conversation-detail/conversation-content/conversation-content.component.scss +3 -3
  6. package/src/app/chatlib/conversation-detail/conversation-content/conversation-content.component.ts +1 -1
  7. package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.html +1 -1
  8. package/src/app/chatlib/conversation-detail/message/avatar/avatar.component.html +1 -1
  9. package/src/app/chatlib/conversation-detail/message/avatar/avatar.component.ts +4 -4
  10. package/src/app/chatlib/conversation-detail/message/return-receipt/return-receipt.component.scss +3 -3
  11. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +9 -9
  12. package/src/app/components/bubbleMessageInfo-popover/bubbleinfo-popover.component.html +1 -1
  13. package/src/app/components/canned-response/canned-response.component.html +23 -26
  14. package/src/app/components/canned-response/canned-response.component.scss +2 -0
  15. package/src/app/components/canned-response/canned-response.component.ts +1 -3
  16. package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.html +8 -8
  17. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +1 -24
  18. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +0 -30
  19. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +16 -29
  20. package/src/app/components/copilot-popover/copilot-popover.component.html +1 -1
  21. package/src/app/components/navbar/navbar.component.html +3 -3
  22. package/src/app/components/navbar/navbar.component.ts +38 -29
  23. package/src/app/components/project-item/project-item.component.ts +70 -52
  24. package/src/app/components/sidebar/sidebar.component.html +47 -67
  25. package/src/app/components/sidebar/sidebar.component.ts +117 -92
  26. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +4 -4
  27. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +14 -16
  28. package/src/app/modals/create-ticket/create-ticket.page.html +6 -6
  29. package/src/app/modals/create-ticket/create-ticket.page.ts +6 -8
  30. package/src/app/modals/loader-preview/loader-preview.page.ts +1 -1
  31. package/src/app/modals/send-whatsapp-template/send-whatsapp-template.page.scss +1 -1
  32. package/src/app/pages/conversation-detail/conversation-detail.page.html +3 -7
  33. package/src/app/pages/conversation-detail/conversation-detail.page.scss +1 -1
  34. package/src/app/pages/conversation-detail/conversation-detail.page.ts +4 -63
  35. package/src/app/pages/conversations-list/conversations-list.page.ts +8 -8
  36. package/src/app/pages/profile-info/profile-info.page.ts +3 -3
  37. package/src/app/services/brand/brand.service.ts +5 -5
  38. package/src/app/services/global-settings/global-settings.service.ts +2 -5
  39. package/src/app/services/tiledesk/tiledesk.service.ts +16 -0
  40. package/src/app/shared/shared.module.ts +0 -11
  41. package/src/app/utils/project-utils.ts +2 -2
  42. package/src/app/utils/utils-resources.ts +8 -7
  43. package/src/app/utils/utils.ts +1 -18
  44. package/src/assets/i18n/ar.json +1 -11
  45. package/src/assets/i18n/az.json +1 -11
  46. package/src/assets/i18n/de.json +1 -11
  47. package/src/assets/i18n/en.json +1 -11
  48. package/src/assets/i18n/es.json +1 -11
  49. package/src/assets/i18n/fr.json +1 -11
  50. package/src/assets/i18n/it.json +3 -13
  51. package/src/assets/i18n/kk.json +1 -11
  52. package/src/assets/i18n/pt.json +1 -11
  53. package/src/assets/i18n/ru.json +1 -11
  54. package/src/assets/i18n/sr.json +1 -11
  55. package/src/assets/i18n/sv.json +1 -11
  56. package/src/assets/i18n/tr.json +1 -11
  57. package/src/assets/i18n/uk.json +1 -11
  58. package/src/assets/i18n/uz.json +1 -12
  59. package/src/chat-config-template.json +0 -1
  60. package/src/chat-config.json +0 -1
  61. package/src/chat21-core/models/{projectUsers.ts → project_user.ts} +18 -12
  62. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  63. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  64. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +0 -3
  65. package/src/chat21-core/utils/constants.ts +2 -2
  66. package/src/chat21-core/utils/utils.ts +2 -10
  67. package/src/app/services/project_users/project-users.service.spec.ts +0 -16
  68. package/src/app/services/project_users/project-users.service.ts +0 -63
  69. package/src/app/utils/permissions.constants.ts +0 -138
  70. package/src/assets/js/agentDesktop-sdk.js +0 -47
  71. /package/src/assets/{images → img}/channel_icons/chat21.svg +0 -0
  72. /package/src/assets/{images → img}/channel_icons/direct.svg +0 -0
  73. /package/src/assets/{images → img}/channel_icons/email-logo.svg +0 -0
  74. /package/src/assets/{images → img}/channel_icons/form-logo_v2.svg +0 -0
  75. /package/src/assets/{images → img}/channel_icons/group.svg +0 -0
  76. /package/src/assets/{images → img}/channel_icons/messenger-logo.svg +0 -0
  77. /package/src/assets/{images → img}/channel_icons/telegram-logo.svg +0 -0
  78. /package/src/assets/{images → img}/channel_icons/voice.svg +0 -0
  79. /package/src/assets/{images → img}/channel_icons/whatsapp-logo.svg +0 -0
  80. /package/src/assets/{images → img}/default-avatar-x-select.png +0 -0
  81. /package/src/assets/{images → img}/f21ico-done.svg +0 -0
  82. /package/src/assets/{images → img}/f21ico-done_all.svg +0 -0
  83. /package/src/assets/{images → img}/f21ico-schedule.svg +0 -0
  84. /package/src/assets/{images → img}/file-alt-solid.png +0 -0
  85. /package/src/assets/{images → img}/icons/copilot.svg +0 -0
  86. /package/src/assets/{images → img}/json-file.svg +0 -0
  87. /package/src/assets/{images → img}/language_flag/ar.png +0 -0
  88. /package/src/assets/{images → img}/language_flag/az.png +0 -0
  89. /package/src/assets/{images → img}/language_flag/bg.png +0 -0
  90. /package/src/assets/{images → img}/language_flag/ca.png +0 -0
  91. /package/src/assets/{images → img}/language_flag/cs.png +0 -0
  92. /package/src/assets/{images → img}/language_flag/da.png +0 -0
  93. /package/src/assets/{images → img}/language_flag/de.png +0 -0
  94. /package/src/assets/{images → img}/language_flag/el.png +0 -0
  95. /package/src/assets/{images → img}/language_flag/en.png +0 -0
  96. /package/src/assets/{images → img}/language_flag/es.png +0 -0
  97. /package/src/assets/{images → img}/language_flag/fa.png +0 -0
  98. /package/src/assets/{images → img}/language_flag/fi.png +0 -0
  99. /package/src/assets/{images → img}/language_flag/fr.png +0 -0
  100. /package/src/assets/{images → img}/language_flag/he.png +0 -0
  101. /package/src/assets/{images → img}/language_flag/hi.png +0 -0
  102. /package/src/assets/{images → img}/language_flag/hr.png +0 -0
  103. /package/src/assets/{images → img}/language_flag/hu.png +0 -0
  104. /package/src/assets/{images → img}/language_flag/id.png +0 -0
  105. /package/src/assets/{images → img}/language_flag/it.png +0 -0
  106. /package/src/assets/{images → img}/language_flag/ja.png +0 -0
  107. /package/src/assets/{images → img}/language_flag/kk.png +0 -0
  108. /package/src/assets/{images → img}/language_flag/ko.png +0 -0
  109. /package/src/assets/{images → img}/language_flag/ml-IN.png +0 -0
  110. /package/src/assets/{images → img}/language_flag/ne-NP.png +0 -0
  111. /package/src/assets/{images → img}/language_flag/nl.png +0 -0
  112. /package/src/assets/{images → img}/language_flag/no.png +0 -0
  113. /package/src/assets/{images → img}/language_flag/pl.png +0 -0
  114. /package/src/assets/{images → img}/language_flag/pt-BR.png +0 -0
  115. /package/src/assets/{images → img}/language_flag/pt.png +0 -0
  116. /package/src/assets/{images → img}/language_flag/ro.png +0 -0
  117. /package/src/assets/{images → img}/language_flag/ru.png +0 -0
  118. /package/src/assets/{images → img}/language_flag/sk.png +0 -0
  119. /package/src/assets/{images → img}/language_flag/sl.png +0 -0
  120. /package/src/assets/{images → img}/language_flag/sr.png +0 -0
  121. /package/src/assets/{images → img}/language_flag/sv.png +0 -0
  122. /package/src/assets/{images → img}/language_flag/ta.png +0 -0
  123. /package/src/assets/{images → img}/language_flag/th.png +0 -0
  124. /package/src/assets/{images → img}/language_flag/tr.png +0 -0
  125. /package/src/assets/{images → img}/language_flag/uk.png +0 -0
  126. /package/src/assets/{images → img}/language_flag/uz.png +0 -0
  127. /package/src/assets/{images → img}/language_flag/vi.png +0 -0
  128. /package/src/assets/{images → img}/language_flag/zh-CN.png +0 -0
  129. /package/src/assets/{images → img}/language_flag/zh-TW.png +0 -0
  130. /package/src/assets/{logos → img/logos}/chat21-logo.png +0 -0
  131. /package/src/assets/{logos → img/logos}/logo.png +0 -0
  132. /package/src/assets/{logos → img/logos}/tiledesk-logo_new_white.svg +0 -0
  133. /package/src/assets/{logos → img/logos}/tiledesk-solo-logo.png +0 -0
  134. /package/src/assets/{logos → img/logos}/tiledesk_logo.svg +0 -0
  135. /package/src/assets/{logos → img/logos}/tiledesk_logo_no_text.svg +0 -0
  136. /package/src/assets/{logos → img/logos}/tiledesk_logo_white_small.svg +0 -0
  137. /package/src/assets/{images → img}/no_conversation.jpg +0 -0
  138. /package/src/assets/{images → img}/no_image.png +0 -0
  139. /package/src/assets/{images → img}/no_image_user.png +0 -0
  140. /package/src/assets/{images → img}/pin.svg +0 -0
  141. /package/src/assets/{images → img}/pinned.svg +0 -0
  142. /package/src/assets/{images → img}/priority_icons/high.svg +0 -0
  143. /package/src/assets/{images → img}/priority_icons/high_v2.svg +0 -0
  144. /package/src/assets/{images → img}/priority_icons/low.svg +0 -0
  145. /package/src/assets/{images → img}/priority_icons/low_v2.svg +0 -0
  146. /package/src/assets/{images → img}/priority_icons/medium.svg +0 -0
  147. /package/src/assets/{images → img}/priority_icons/medium_v2.svg +0 -0
  148. /package/src/assets/{images → img}/priority_icons/urgent.svg +0 -0
  149. /package/src/assets/{images → img}/priority_icons/urgent_v2.svg +0 -0
  150. /package/src/assets/{images → img}/teammate-status/avaible.svg +0 -0
  151. /package/src/assets/{images → img}/teammate-status/inactive.svg +0 -0
  152. /package/src/assets/{images → img}/teammate-status/unavaible.svg +0 -0
  153. /package/src/assets/{images → img}/whatsapp_background.png +0 -0
@@ -22,13 +22,6 @@
22
22
  {{translationMap?.get('WHATSAPP.LABEL_TEMPLATES')}}
23
23
  </ion-button>
24
24
  </div>
25
- <!-- OPEN TICKET -->
26
- <div *ngIf="ticketSection" class="section-option" id="template" tooltip="{{translationMap?.get('TICKET.OPEN_TICKET')}}" placement="top">
27
- <ion-button fill="clear" [class.active]="section==='ticket'" (click)="onOpenSection('ticket')" [disabled]="channelType === 'direct'">
28
- <ion-icon name="ticket"></ion-icon>
29
- {{translationMap?.get('TICKET.OPEN_TICKET')}}
30
- </ion-button>
31
- </div>
32
25
  </div>
33
26
 
34
27
  <div class="footerContainerAlert">
@@ -57,22 +50,6 @@
57
50
  </ion-col>
58
51
  </ion-row>
59
52
 
60
- <ion-row id="ticket" [style.display]="section==='ticket'? 'flex': 'none'">
61
- <ion-col col-auto>
62
- <div class="placeholder">{{translationMap.get('TICKET.DESCRIPTION')}}</div>
63
- <div class="buttons-container">
64
- <ion-button name="add" size="small" (click)="onClickTicket('open')">
65
- <ion-icon name="add"></ion-icon>
66
- {{translationMap?.get('TICKET.CONFIRM')}}
67
- </ion-button>
68
- <ion-button size="small" color="danger" (click)="onClickTicket('close')">
69
- <ion-icon name="close"></ion-icon>
70
- {{translationMap?.get('TICKET.CLOSE')}}
71
- </ion-button>
72
- </div>
73
- </ion-col>
74
- </ion-row>
75
-
76
53
  <ion-row id="message-text-area" [style.display]="section==='chat' || section ==='templates' || section ==='copilot'? 'flex': 'none'">
77
54
 
78
55
  <ion-col col-auto style="display: flex;">
@@ -80,7 +57,7 @@
80
57
  <div class="buttons-left">
81
58
 
82
59
  <!-- CANNED RESPONSES -->
83
- <ng-container *ngIf="areVisibleCAR && supportMode && cannedSection">
60
+ <ng-container *ngIf="areVisibleCAR && supportMode">
84
61
  <div class="canned-responses-btn-wpr" tooltip="{{translationMap?.get('CANNED_RESPONSES')}}" placement="top">
85
62
  <ion-button ion-button fill="clear" class="canned-responses-btn" (click)="openCannedResponses()"
86
63
  [disabled]="!conversationWith?.startsWith(CHANNEL_TYPE.SUPPORT_GROUP) || disableTextarea">
@@ -183,36 +183,6 @@
183
183
  }
184
184
  }
185
185
 
186
- #ticket{
187
- text-align: center;
188
- font-size: 12px;
189
-
190
- .buttons-container{
191
- display: flex;
192
- justify-content: center;
193
- gap: 10px;
194
-
195
- ion-button{
196
- font-size: 12px;
197
- --padding-top: 4px;
198
- --padding-bottom: 4px;
199
- --padding-start: 6px;
200
- --padding-end: 6px;
201
- --ripple-color: transparent;
202
- text-transform: unset;
203
- height: auto;
204
-
205
- ion-icon{
206
- margin-right: 4px;
207
- }
208
-
209
- &[name="add"]{
210
- --background: var(--basic-blue);
211
- }
212
- }
213
- }
214
- }
215
-
216
186
  #fileInput {
217
187
  position: absolute;
218
188
  opacity: 0;
@@ -26,7 +26,6 @@ import { CopilotService } from 'src/app/services/copilot/copilot.service';
26
26
  import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
27
27
  import { ProjectService } from 'src/app/services/projects/project.service';
28
28
  import { Project } from 'src/chat21-core/models/projects';
29
- import { ProjectUser } from 'src/chat21-core/models/projectUsers';
30
29
 
31
30
 
32
31
  @Component({
@@ -50,7 +49,6 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
50
49
  @ViewChild('fileInput', { static: false }) fileInput: any;
51
50
 
52
51
  @Input() loggedUser: UserModel;
53
- @Input() projectUser: ProjectUser;
54
52
  @Input() conversationWith: string;
55
53
  @Input() channelType: string;
56
54
  @Input() channel: string;
@@ -63,20 +61,16 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
63
61
  @Input() emailSection: boolean;
64
62
  @Input() offlineMsgEmail: boolean;
65
63
  @Input() whatsappTemplatesSection: boolean;
66
- @Input() ticketSection: boolean
67
64
  @Input() isOpenInfoConversation: boolean;
68
- @Input() cannedSection: boolean;
69
65
  @Input() stylesMap: Map<string, string>;
70
66
  @Input() translationMap: Map<string, string>;
71
67
  @Input() dropEvent: any;
72
68
  @Input() disableTextarea: boolean;
73
- @Input() roles: Array<string>;
74
69
  @Output() eventChangeTextArea = new EventEmitter<{msg: string, offsetHeight: number}>();
75
70
  @Output() eventSendMessage = new EventEmitter<{msg: string, type: string, metadata?: Object, attributes?: Object}>();
76
71
  @Output() onClickOpenCannedResponses = new EventEmitter<boolean>();
77
72
  @Output() onPresentModalScrollToBottom = new EventEmitter<boolean>();
78
73
  @Output() onOpenFooterSection = new EventEmitter<string>();
79
- @Output() onOpenTicket = new EventEmitter<boolean>();
80
74
 
81
75
  public project: Project;
82
76
  public conversationEnabled = false;
@@ -294,17 +288,6 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
294
288
  this.prensentTemplateModal();
295
289
  }
296
290
 
297
- onClickTicket(option: "open" | "close"){
298
- this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] - onClickTicket', option);
299
- switch(option){
300
- case "open":
301
- this.onOpenTicket.emit();
302
- case "close":
303
- this.section = 'chat'
304
- }
305
-
306
- }
307
-
308
291
 
309
292
  /**
310
293
  *
@@ -548,6 +531,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
548
531
  e.preventDefault(); // Prevent press enter from creating new line
549
532
  // console.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea * event: ", e);
550
533
 
534
+ if(this.showAlertEmoji || this.showAlertUrl){
535
+ return;
536
+ }
537
+
551
538
  this.countClicks++;
552
539
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - countClicks: ', this.countClicks);
553
540
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - event: ', e);
@@ -580,10 +567,8 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
580
567
  if (!text.includes("/")) {
581
568
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 1 message: ', message);
582
569
  this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 1 message: ", message);
583
-
570
+ this.messageString = '';
584
571
  this.sendMessage(text);
585
- // this.messageString = '';
586
-
587
572
  this.countClicks = 0
588
573
  } else if (text.includes("/") && pos === 0 && this.countClicks > 1 && this.tagsCannedFilter.length > 0) {
589
574
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 2: ', this.tagsCannedFilter.length);
@@ -595,10 +580,9 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
595
580
  this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
596
581
  this.logger.log("[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
597
582
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 2 message: ', message);
598
-
599
- this.sendMessage(text);
600
- // this.messageString = '';
583
+ this.messageString = '';
601
584
 
585
+ this.sendMessage(text);
602
586
  this.countClicks = 0
603
587
  } else if (text.includes("/") && pos > 0 && this.countClicks > 1 && this.tagsCannedFilter.length > 0 && text.substr(-1) !== '/') {
604
588
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 3: ', this.tagsCannedFilter.length);
@@ -610,19 +594,17 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
610
594
  this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
611
595
  this.logger.log("[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown in msg-texarea SEND MESSAGE 2 this.countClicks: ", this.countClicks);
612
596
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 2 message: ', message);
613
-
614
- this.sendMessage(text);
615
- // this.messageString = '';
597
+ this.messageString = '';
616
598
 
599
+ this.sendMessage(text);
617
600
  this.countClicks = 0
618
601
  } else if (text.includes("/") && this.tagsCannedFilter.length === 0) {
619
602
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - tagsCannedFilter.length 3: ', this.tagsCannedFilter.length);
620
603
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] onKeydown - SEND MESSAGE 3 message: ', message);
621
604
  this.logger.log("[CONVS-DETAIL] replaceTagInMessage onKeydown in msg-texarea SEND MESSAGE 3 message: ", message);
622
-
623
- this.sendMessage(text);
624
- // this.messageString = '';
605
+ this.messageString = '';
625
606
 
607
+ this.sendMessage(text);
626
608
  this.countClicks = 0
627
609
 
628
610
  }
@@ -652,6 +634,11 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
652
634
  return
653
635
  }
654
636
 
637
+ let check = this.checkForEmojii(text)
638
+ if(!check){
639
+ return;
640
+ }
641
+
655
642
  this.messageString = '';
656
643
  // text = text.replace(/(\r\n|\n|\r)/gm, '');
657
644
 
@@ -18,7 +18,7 @@
18
18
  </ion-content>
19
19
  <ion-footer class="ion-no-border">
20
20
  <ion-button fill="clear" (click)="onClickCopilot()">
21
- <ion-icon src="assets/images/icons/copilot.svg"></ion-icon>
21
+ <ion-icon src="assets/img/icons/copilot.svg"></ion-icon>
22
22
  {{translationsMap.get('COPILOT.ASK_AI') }}
23
23
  </ion-button>
24
24
  </ion-footer>
@@ -5,7 +5,7 @@
5
5
  </div>
6
6
  <div class="navbar-right">
7
7
  <!-- test site -->
8
- <ng-container *ngIf="project && roles?.[PERMISSIONS.SIMULATE_CONV]">
8
+ <ng-container *ngIf="project">
9
9
  <button class="btn simulate-visitor-btn" (click)="testWidgetPage()">
10
10
  <i class="material-icons">play_arrow</i>
11
11
  <!-- {{translationsMap?.get('NAVBAR.SIMULATE_VISITOR')}} -->
@@ -23,7 +23,7 @@
23
23
  </ng-container>
24
24
 
25
25
  <!-- ------ PROJECTS DROPDOWN ------ -->
26
- <ng-container *ngIf="project && roles?.[PERMISSIONS.CHANGE_PROJECT]">
26
+ <ng-container *ngIf="project">
27
27
  <li>
28
28
  <button class="btn dropdown-toggle project-dropdown" (click)="openDropdownProjects = !openDropdownProjects">
29
29
  <span class="project-dropdown" style="text-transform: none"> {{ project?.id_project?.name }} </span>
@@ -49,7 +49,7 @@
49
49
  </li>
50
50
 
51
51
  <!-- ADD PROJECT -->
52
- <li id="navbar_create_prjct" *ngIf="isVisibleMT" (click)="onClickDropdownOption('addProject')" class="add-project">
52
+ <li id="navbar_create_prjct" *ngIf="MT === true" (click)="onClickDropdownOption('addProject')" class="add-project">
53
53
  <a>
54
54
  <i class="material-icons">add_circle_outline </i>
55
55
  {{translationsMap?.get('NAVBAR.ADD_PROJECT')}}
@@ -7,10 +7,6 @@ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service
7
7
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
8
8
  import { Project } from 'src/chat21-core/models/projects';
9
9
  import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
10
- import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
11
- import { ProjectUser } from 'src/chat21-core/models/projectUsers';
12
- import { PERMISSIONS } from 'src/app/utils/permissions.constants';
13
- import { getOSCode, hasRole } from 'src/app/utils/utils';
14
10
 
15
11
  @Component({
16
12
  selector: 'app-navbar',
@@ -34,14 +30,10 @@ export class NavbarComponent implements OnInit {
34
30
  public openDropdownProjects: boolean = false
35
31
  private public_Key: string;
36
32
  public isVisible: boolean;
37
- public isVisibleMT: boolean;
33
+ public MT: boolean;
38
34
 
39
- public projectUser: ProjectUser;
40
- public roles: { [key: string]: boolean }
41
- PERMISSIONS = PERMISSIONS;
42
35
  constructor(
43
36
  private projectService: ProjectService,
44
- public projectUsersService: ProjectUsersService,
45
37
  private tiledeskAuthService: TiledeskAuthService,
46
38
  private appConfigProvider: AppConfigProvider,
47
39
  private translateService: CustomTranslateService,
@@ -104,14 +96,11 @@ export class NavbarComponent implements OnInit {
104
96
  }
105
97
 
106
98
  getStoredProjectAndUserRole() {
107
- this.events.subscribe('storage:last_project',async (project) =>{
99
+ this.events.subscribe('storage:last_project',project =>{
108
100
  this.logger.log('[NAVBAR] stored_project ', project)
109
101
  if (project && project !== 'undefined') {
110
102
  this.project = project;
111
103
  this.USER_ROLE = project.role;
112
- this.projectUser = await this.projectUsersService.getProjectUserByProjectId(project.id_project.id)
113
- this.roles = this.checkRoles()
114
- console.log('[SIDEBAR] roles ', this.roles)
115
104
  }
116
105
  })
117
106
  }
@@ -119,24 +108,44 @@ export class NavbarComponent implements OnInit {
119
108
  getOSCODE() {
120
109
  this.public_Key = this.appConfigProvider.getConfig().t2y12PruGU9wUtEGzBJfolMIgK;
121
110
  this.logger.log('[NAVBAR] AppConfigService getAppConfig public_Key', this.public_Key)
122
-
123
- this.isVisibleMT = getOSCode("MTT", this.public_Key);
124
-
125
- }
126
-
127
- checkRoles(): { [key: string]: boolean } {
128
- const permissionKeys = [
129
- 'CHANGE_PROJECT',
130
- 'SIMULATE_CONV',
131
- ] as const;
111
+ this.logger.log('[NAVBAR] public_Key', this.public_Key)
112
+
113
+ let keys = this.public_Key.split("-");
114
+ // this.logger.log('PUBLIC-KEY (Navbar) - public_Key keys', keys)
115
+
116
+ keys.forEach(key => {
117
+ // this.logger.log('NavbarComponent public_Key key', key)
118
+ if (key.includes("PAY")) {
119
+ // this.logger.log('PUBLIC-KEY (Navbar) - key', key);
120
+ let pay = key.split(":");
121
+ // this.logger.log('PUBLIC-KEY (Navbar) - pay key&value', pay);
122
+ if (pay[1] === "F") {
123
+ this.isVisible = false;
124
+ // this.logger.log('PUBLIC-KEY (Navbar) - pay isVisible', this.isVisible);
125
+ } else {
126
+ this.isVisible = true;
127
+ // this.logger.log('PUBLIC-KEY (Navbar) - pay isVisible', this.isVisible);
128
+ }
129
+ }
130
+
131
+ if (key.includes("MTT")) {
132
+ // this.logger.log('PUBLIC-KEY (Navbar) - key', key);
133
+ let mt = key.split(":");
134
+ // this.logger.log('PUBLIC-KEY (Navbar) - mt key&value', mt);
135
+ if (mt[1] === "F") {
136
+ this.MT = false;
137
+ // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
138
+ } else {
139
+ this.MT = true;
140
+ // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
141
+ }
142
+ }
143
+ });
132
144
 
133
- const roles: { [key: string]: boolean } = {};
134
- for (const key of permissionKeys) {
135
- const permission = PERMISSIONS[key];
136
- roles[permission] = hasRole(this.projectUser, permission);
145
+ if (!this.public_Key.includes("MTT")) {
146
+ this.MT = false;
147
+ // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
137
148
  }
138
-
139
- return roles;
140
149
 
141
150
  }
142
151
 
@@ -15,6 +15,8 @@ import { AppConfigProvider } from 'src/app/services/app-config';
15
15
  import { ConvertRequestToConversation } from 'src/chat21-core/utils/convertRequestToConversation';
16
16
  import { compareValues } from 'src/chat21-core/utils/utils';
17
17
  import { ProjectService } from 'src/app/services/projects/project.service';
18
+ import { ProjectUser } from 'src/chat21-core/models/project_user';
19
+ import { Project } from 'src/chat21-core/models/projects';
18
20
 
19
21
  @Component({
20
22
  selector: 'app-project-item',
@@ -85,17 +87,17 @@ export class ProjectItemComponent implements OnInit {
85
87
 
86
88
  connetWebsocket(tiledeskToken) {
87
89
 
88
- // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] tiledeskToken ', tiledeskToken)
89
- // const appconfig = this.appConfigProvider.getConfig();
90
- // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', appconfig.wsUrl)
91
- // const WS_URL = appconfig.wsUrl + '?token=' + tiledeskToken
92
- // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', WS_URL)
93
- // this.webSocketJs.init(
94
- // WS_URL,
95
- // undefined,
96
- // undefined,
97
- // undefined
98
- // );
90
+ this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] tiledeskToken ', tiledeskToken)
91
+ const appconfig = this.appConfigProvider.getConfig();
92
+ this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', appconfig.wsUrl)
93
+ const WS_URL = appconfig.wsUrl + '?token=' + tiledeskToken
94
+ this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', WS_URL)
95
+ this.webSocketJs.init(
96
+ WS_URL,
97
+ undefined,
98
+ undefined,
99
+ undefined
100
+ );
99
101
 
100
102
  this.getLastProjectStoredAndSubscToWSAvailabilityAndConversations();
101
103
  }
@@ -164,63 +166,68 @@ export class ProjectItemComponent implements OnInit {
164
166
  }
165
167
  }
166
168
 
167
- getLastProjectStoredAndSubscToWSAvailabilityAndConversations() {
168
- let stored_project = ''
169
+ getStoredProject(): ProjectUser | null {
169
170
  try {
170
- stored_project = localStorage.getItem('last_project')
171
- this.logger.log('PROJECT-ITEM - THERE IS A STORED PROJECT ', stored_project)
171
+ const raw = localStorage.getItem('last_project');
172
+
173
+ if (!raw) {
174
+ return null;
175
+ }
176
+
177
+ const parsed = JSON.parse(raw);
178
+
179
+ if (this.isValidStoredProject(parsed)) {
180
+ return parsed;
181
+ }
182
+
183
+ // modello sbagliato → pulizia
184
+ this.logger.warn('[PROJECT-ITEM] Invalid stored project schema, clearing storage');
185
+ localStorage.removeItem('last_project');
186
+ return null;
187
+
172
188
  } catch (err) {
173
- this.logger.error('Get local storage LAST PROJECT ', err)
189
+ this.logger.error('[PROJECT-ITEM] Error parsing stored project', err);
190
+ localStorage.removeItem('last_project');
191
+ return null;
174
192
  }
193
+ }
194
+
195
+ getLastProjectStoredAndSubscToWSAvailabilityAndConversations() {
175
196
 
197
+ let stored_project = this.getStoredProject();
176
198
 
177
- if (!stored_project || stored_project === 'undefined') {
178
- this.logger.log('PROJECT-ITEM - THERE IS NOT STORED LAST PROJECT OR IS UNDEFINED ', stored_project)
199
+ if (!stored_project) {
200
+ this.logger.log('[PROJECT-ITEM] No valid stored project, fetching remote');
179
201
  this.projectService.getProjects().subscribe(projects => {
180
- this.logger.log('[PROJECT-ITEM - GET PROJECTS - RES', projects);
181
-
182
- this.logger.log('[INFO-CONTENT-COMP] - GET PROJECTS - RES this.project', this.project);
183
-
184
- if(this.projectID){
185
- const project = projects.find(prjct => prjct.id_project._id === this.projectID)
186
- if(project){
187
- this.project = project
188
- this.logger.log('[PROJECT-ITEM] - GET PROJECTS - project found with this.projectID', this.project);
189
- localStorage.setItem('last_project', JSON.stringify(this.project))
190
- this.doProjectSubscriptions(this.project)
191
- return
192
- }else{
193
- this.logger.log('[PROJECT-ITEM] - GET PROJECTS - project NOT found with this.projectID', this.projectID);
194
- }
202
+ let project: Project | undefined;
203
+
204
+ if (this.projectID) {
205
+ project = projects.find( p => p.id_project?._id === this.projectID );
195
206
  }
196
207
 
197
- if (projects[0]) {
198
- localStorage.setItem('last_project', JSON.stringify(projects[0]))
199
- this.project = projects[0];
200
- this.doProjectSubscriptions(this.project)
208
+ if (!project) {
209
+ project = projects[0];
201
210
  }
202
211
 
203
- }, (error) => {
204
- this.logger.error('[PROJECT-ITEM] - GET PROJECTS - ERROR ', error);
212
+ if (!project) {
213
+ this.logger.warn('[PROJECT-ITEM] No projects returned from API');
214
+ return;
215
+ }
205
216
 
206
- }, () => {
207
- this.logger.log('[INFO-CONTENT-COMP] - GET PROJECTS * COMPLETE *');
217
+ this.project = project;
218
+ localStorage.setItem('last_project', JSON.stringify(project));
219
+ this.doProjectSubscriptions(project);
208
220
 
221
+ }, error => {
222
+ this.logger.error('[PROJECT-ITEM] GET PROJECTS ERROR', error);
209
223
  });
210
- }
211
-
212
224
 
213
- if (stored_project && stored_project !== 'undefined') {
214
- this.logger.log('PROJECT-ITEM - THERE IS STORED LAST PROJECT ', stored_project)
215
- if (stored_project) {
216
- this.project = JSON.parse(stored_project)
217
- }
218
- this.doProjectSubscriptions(this.project)
219
- this.logger.log('[PROJECT-ITEM] - LAST PROJECT PARSED ', this.project)
225
+ return;
220
226
  }
221
227
 
222
-
223
-
228
+ // ✅ stored project valido
229
+ this.project = stored_project;
230
+ this.doProjectSubscriptions(stored_project);
224
231
 
225
232
  }
226
233
 
@@ -345,6 +352,17 @@ export class ProjectItemComponent implements OnInit {
345
352
  }
346
353
  }
347
354
 
355
+ isValidStoredProject(obj: any): obj is ProjectUser {
356
+ return (
357
+ obj &&
358
+ typeof obj === 'object' &&
359
+ obj.id_project &&
360
+ typeof obj.id_project === 'object' &&
361
+ typeof obj.id_project._id === 'string' &&
362
+ typeof obj._id === 'string' &&
363
+ typeof obj.role === 'string'
364
+ );
365
+ }
348
366
 
349
367
 
350
368