@chat21/chat21-ionic 3.4.31 → 3.4.32-rc10

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 (88) hide show
  1. package/CHANGELOG.md +167 -2
  2. package/angular.json +1 -0
  3. package/package.json +1 -1
  4. package/src/app/app.component.html +3 -1
  5. package/src/app/app.component.ts +72 -11
  6. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +14 -2
  7. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +39 -2
  8. package/src/app/chatlib/list-conversations-component/list-conversations.module.ts +14 -0
  9. package/src/app/components/canned-response/canned-response.component.html +26 -23
  10. package/src/app/components/canned-response/canned-response.component.scss +0 -2
  11. package/src/app/components/canned-response/canned-response.component.ts +3 -1
  12. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
  13. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
  14. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +29 -7
  15. package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
  16. package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
  17. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  18. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
  19. package/src/app/components/navbar/navbar.component.html +35 -9
  20. package/src/app/components/navbar/navbar.component.scss +71 -1
  21. package/src/app/components/navbar/navbar.component.ts +100 -42
  22. package/src/app/components/project-item/project-item.component.ts +79 -52
  23. package/src/app/components/sidebar/sidebar.component.html +65 -45
  24. package/src/app/components/sidebar/sidebar.component.ts +110 -117
  25. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +52 -11
  26. package/src/app/components/sidebar-user-details/sidebar-user-details.component.scss +304 -17
  27. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +217 -27
  28. package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
  29. package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
  30. package/src/app/pages/conversation-detail/conversation-detail.page.ts +89 -5
  31. package/src/app/pages/conversations-list/conversations-list.module.ts +3 -5
  32. package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
  33. package/src/app/pages/conversations-list/conversations-list.page.ts +120 -26
  34. package/src/app/pages/unassigned-conversations/unassigned-conversations.module.ts +16 -4
  35. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +43 -17
  36. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +25 -1
  37. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +279 -13
  38. package/src/app/pipe/filter.pipe.spec.ts +8 -0
  39. package/src/app/pipe/filter.pipe.ts +15 -0
  40. package/src/app/pipe/find.pipe.spec.ts +8 -0
  41. package/src/app/pipe/find.pipe.ts +15 -0
  42. package/src/app/services/global-settings/global-settings.service.ts +11 -3
  43. package/src/app/services/nav-proxy.service.ts +0 -1
  44. package/src/app/services/project_users/project-users.service.spec.ts +16 -0
  45. package/src/app/services/project_users/project-users.service.ts +63 -0
  46. package/src/app/services/projects/project.service.ts +2 -1
  47. package/src/app/services/tiledesk/tiledesk.service.ts +24 -0
  48. package/src/app/services/triggerEvents/triggerEvents.ts +40 -0
  49. package/src/app/services/websocket/websocket-js.ts +59 -534
  50. package/src/app/services/websocket/websocket-js_old.ts +578 -0
  51. package/src/app/services/websocket/websocket.service.ts +67 -14
  52. package/src/app/services/websocket/websocket.worker.ts +242 -0
  53. package/src/app/shared/shared.module.ts +26 -10
  54. package/src/app/utils/globals.ts +2 -0
  55. package/src/app/utils/permissions.constants.ts +138 -0
  56. package/src/app/utils/project-utils.ts +2 -2
  57. package/src/app/utils/utils.ts +18 -1
  58. package/src/assets/i18n/ar.json +11 -1
  59. package/src/assets/i18n/az.json +11 -1
  60. package/src/assets/i18n/de.json +11 -1
  61. package/src/assets/i18n/en.json +11 -1
  62. package/src/assets/i18n/es.json +11 -1
  63. package/src/assets/i18n/fr.json +11 -1
  64. package/src/assets/i18n/it.json +13 -3
  65. package/src/assets/i18n/kk.json +11 -1
  66. package/src/assets/i18n/pt.json +11 -1
  67. package/src/assets/i18n/ru.json +11 -1
  68. package/src/assets/i18n/sr.json +11 -1
  69. package/src/assets/i18n/sv.json +11 -1
  70. package/src/assets/i18n/tr.json +11 -1
  71. package/src/assets/i18n/uk.json +11 -1
  72. package/src/assets/i18n/uz.json +12 -1
  73. package/src/assets/js/agentDesktop-sdk.js +55 -0
  74. package/src/assets/js/chat21client.js +36 -0
  75. package/src/assets/js/mqtt-keepalive-worker.js +53 -0
  76. package/src/assets/test.html +5 -2
  77. package/src/chat-config-template.json +1 -0
  78. package/src/chat-config.json +1 -0
  79. package/src/chat21-core/models/projectUsers.ts +19 -0
  80. package/src/chat21-core/models/project_user.ts +2 -1
  81. package/src/chat21-core/models/projects.ts +1 -0
  82. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  83. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  84. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
  85. package/src/chat21-core/utils/constants.ts +6 -0
  86. package/src/chat21-core/utils/convertRequestToConversation.ts +2 -2
  87. package/src/chat21-core/utils/utils.ts +53 -3
  88. package/src/variables.scss +3 -0
@@ -1,5 +1,6 @@
1
1
  ion-toolbar {
2
2
  height: var(--header-height);
3
+ --background: transparent;
3
4
  &:not(.mobile){
4
5
  --background: var(--list-bkg-color);
5
6
  border: none;
@@ -20,7 +21,7 @@ ion-content {
20
21
  // Forcing `--overflow: hidden` breaks scrolling (Chrome >= 144 is stricter here).
21
22
  --overflow: auto;
22
23
  &:not(.mobile){
23
- --background: var(--list-bkg-color);
24
+ --background: var(--bacis-white);
24
25
  }
25
26
  }
26
27
 
@@ -224,3 +225,26 @@ ion-content::part(scroll) {
224
225
  .hide-stretchspinner {
225
226
  display: none;
226
227
  }
228
+
229
+ // -------------------------------------------------
230
+ // List avatar page - full viewport height
231
+ // -------------------------------------------------
232
+ .list-avatar-page {
233
+ min-height: calc(100vh - var(--header-height, 56px));
234
+ height: 100%;
235
+ }
236
+
237
+ // -------------------------------------------------
238
+ // Empty state - label centrata nell'altezza disponibile
239
+ // -------------------------------------------------
240
+ .no-convs-container {
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ min-height: calc(100vh - var(--header-height, 56px));
245
+ width: 100%;
246
+
247
+ ion-item {
248
+ --background: transparent;
249
+ }
250
+ }
@@ -1,5 +1,6 @@
1
- import { Component, Input, OnInit, SecurityContext } from '@angular/core';
2
- import { ModalController } from '@ionic/angular';
1
+ import { Component, Input, OnChanges, OnInit, SecurityContext, SimpleChanges } from '@angular/core';
2
+ import { AlertController, ModalController } from '@ionic/angular';
3
+ import { Router } from '@angular/router';
3
4
  import { NavProxyService } from 'src/app/services/nav-proxy.service';
4
5
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
5
6
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
@@ -7,22 +8,38 @@ import { DomSanitizer } from '@angular/platform-browser'
7
8
  import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
8
9
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
9
10
  import { EventsService } from 'src/app/services/events-service';
10
-
11
+ import { ConversationModel } from 'src/chat21-core/models/conversation';
12
+ import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
13
+ import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
14
+ import { getProjectIdSelectedConversation, isGroup } from 'src/chat21-core/utils/utils';
15
+ import { ImageRepoService } from 'src/chat21-core/providers/abstract/image-repo.service';
16
+ import { Project } from 'src/chat21-core/models/projects';
17
+ import { ProjectService } from 'src/app/services/projects/project.service';
18
+ import { PROJECTS_STORAGE_KEY } from 'src/chat21-core/utils/constants';
11
19
 
12
20
  @Component({
13
21
  selector: 'app-unassigned-conversations',
14
22
  templateUrl: './unassigned-conversations.page.html',
15
23
  styleUrls: ['./unassigned-conversations.page.scss'],
16
24
  })
17
- export class UnassignedConversationsPage implements OnInit {
25
+ export class UnassignedConversationsPage implements OnInit, OnChanges {
18
26
 
19
27
  @Input() iframe_URL: any;
20
28
  @Input() callerBtn: string;
21
29
  @Input() isMobile: boolean;
30
+ /** Lista conversazioni unassigned passata da project-item (calcolata da wsRequestsList) */
31
+ @Input() unassignedConversations: ConversationModel[] = [];
32
+ @Input() stylesMap: Map<string, string>;
33
+ @Input() translationMapConversation: Map<string, string>;
34
+
35
+ /** Array salvato localmente per uso nella page */
36
+ unassignedConversationsList: ConversationModel[] = [];
37
+ uidConvSelected: string;
22
38
  // @Input() prjctsxpanel_url: any;
23
39
  // @Input() unassigned_convs_url: any;
24
40
 
25
41
  iframe_url_sanitized: any;
42
+ private loggedUserUid: string;
26
43
  private logger: LoggerService = LoggerInstance.getInstance();
27
44
  // has_loaded: boolean;
28
45
  ion_content: any;
@@ -34,28 +51,133 @@ export class UnassignedConversationsPage implements OnInit {
34
51
  constructor(
35
52
  private modalController: ModalController,
36
53
  private navService: NavProxyService,
54
+ private alertController: AlertController,
55
+ private router: Router,
37
56
  private sanitizer: DomSanitizer,
38
57
  private translateService: CustomTranslateService,
39
- private events : EventsService
40
- ) { }
58
+ private events: EventsService,
59
+ private tiledeskAuthService: TiledeskAuthService,
60
+ private tiledeskService: TiledeskService,
61
+ private projectService: ProjectService,
62
+ public imageRepoService: ImageRepoService,
63
+ public appStorageService: AppStorageService,
64
+ ) {
65
+ if (this.tiledeskAuthService.getCurrentUser()) {
66
+ this.loggedUserUid = this.tiledeskAuthService.getCurrentUser().uid;
67
+ }
68
+ }
41
69
 
42
70
  ngOnInit() {
43
71
  const keys = [
44
72
  'UnassignedConversations',
45
73
  'NewConversations',
46
- 'PIN_A_PROJECT'
74
+ 'PIN_A_PROJECT',
75
+ 'LABEL_MSG_PUSH_START_CHAT'
47
76
  ];
48
77
  this.translationMap = this.translateService.translateLanguage(keys);
49
- this.buildIFRAME();
78
+
79
+ this.unassignedConversationsList = this.unassignedConversations ?? [];
80
+ if (!this.stylesMap) {
81
+ this.stylesMap = new Map([['themeColor', '#165CEE']]);
82
+ }
83
+ if (!this.translationMapConversation) {
84
+ this.translationMapConversation = this.translateService.translateLanguage(['CLOSED', 'Resolve']);
85
+ }
86
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] unassignedConversationsList', this.unassignedConversationsList);
87
+ this.processConversationsForDisplay();
88
+ this.loadAndStoreProjects();
89
+ // this.buildIFRAME();
50
90
  this.listenToPostMsg();
51
91
  this.hideHotjarFeedbackBtn();
52
92
  this.events.subscribe('style', (data)=>this.loadStyle(data))
53
93
  }
54
94
 
95
+ ngOnChanges(changes: SimpleChanges) {
96
+ if (changes['unassignedConversations'] && changes['unassignedConversations'].currentValue) {
97
+ this.unassignedConversationsList = this.unassignedConversations ?? [];
98
+ this.processConversationsForDisplay();
99
+ }
100
+ }
101
+
55
102
  ngOnDestroy(){
56
103
  this.logger.log('[UNASSIGNED-CONVS-PAGE] - onDestroy called', this.iframe_URL);
57
104
  }
58
105
 
106
+ /** Chiama onImageLoaded e onConversationLoaded per ogni conversazione in lista */
107
+ private processConversationsForDisplay() {
108
+ if (!this.unassignedConversationsList?.length) return;
109
+ this.unassignedConversationsList.forEach((conv) => {
110
+ this.onImageLoaded(conv);
111
+ this.onConversationLoaded(conv);
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Recupera tutti i progetti con getProjects e li salva in AppStorage.
117
+ * Se la chiave esiste già nello storage, salta la chiamata remota e usa i dati in cache.
118
+ * Al termine richiama processConversationsForDisplay per aggiornare i project_name.
119
+ */
120
+ private loadAndStoreProjects() {
121
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
122
+ if (stored) {
123
+ this.processConversationsForDisplay();
124
+ return;
125
+ }
126
+ const token = this.tiledeskAuthService.getTiledeskToken();
127
+ if (!token) return;
128
+ this.projectService.getProjects().subscribe(
129
+ (projects: Project[]) => {
130
+ if (!projects?.length) return;
131
+ let projectsMap: Record<string, Project> = {};
132
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
133
+ if (stored) {
134
+ try {
135
+ projectsMap = JSON.parse(stored) || {};
136
+ } catch (e) {
137
+ this.logger.warn('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - failed to parse stored projects', e);
138
+ }
139
+ }
140
+ let hasChanges = false;
141
+ projects.forEach((project) => {
142
+ const projectId = project.id_project?._id || project.id_project?.id || project._id;
143
+ if (!projectId) return;
144
+ if (!projectsMap[projectId]) {
145
+ projectsMap[projectId] = project.id_project || project;
146
+ hasChanges = true;
147
+ }
148
+ });
149
+ if (hasChanges) {
150
+ this.appStorageService.setItem(PROJECTS_STORAGE_KEY, JSON.stringify(projectsMap));
151
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - saved', Object.keys(projectsMap).length, 'projects');
152
+ }
153
+ this.processConversationsForDisplay();
154
+ },
155
+ (err) => {
156
+ this.logger.error('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - error', err);
157
+ this.processConversationsForDisplay();
158
+ }
159
+ );
160
+ }
161
+
162
+ /** Recupera il progetto dalla chiave di storage (all_projects); se non trovato restituisce null */
163
+ private getProjectFromStorage(conversation: ConversationModel): Project | null {
164
+ let projectId: string | undefined;
165
+ if (conversation.attributes?.['projectId']) {
166
+ projectId = conversation.attributes['projectId'];
167
+ } else if (conversation.attributes) {
168
+ projectId = getProjectIdSelectedConversation(conversation.uid);
169
+ }
170
+ if (!projectId) return null;
171
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
172
+ if (!stored) return null;
173
+ try {
174
+ const projectsMap: Record<string, Project> = JSON.parse(stored);
175
+ return projectsMap[projectId] || null;
176
+ } catch {
177
+ return null;
178
+ }
179
+ }
180
+
59
181
  hideHotjarFeedbackBtn() {
60
182
  const hotjarFeedbackBtn = <HTMLElement>document.querySelector("#_hj_feedback_container > div > button")
61
183
  if (hotjarFeedbackBtn) {
@@ -117,6 +239,45 @@ export class UnassignedConversationsPage implements OnInit {
117
239
 
118
240
  }
119
241
 
242
+ async presentAlertConfirmJoinRequest(request: ConversationModel) {
243
+ var iframeWin = <HTMLIFrameElement>document.getElementById("unassigned-convs-iframe")
244
+
245
+ const isIFrame = (input: HTMLElement | null): input is HTMLIFrameElement =>
246
+ input !== null && input.tagName === 'IFRAME';
247
+
248
+ const keys = ['YouAreAboutToJoinThisChat', 'Cancel', 'AreYouSure'];
249
+ const translationMap = this.translateService.translateLanguage(keys);
250
+
251
+ const alert = await this.alertController.create({
252
+ cssClass: 'my-custom-class',
253
+ header: translationMap.get('AreYouSure'),
254
+ message: translationMap.get('YouAreAboutToJoinThisChat'),
255
+ buttons: [
256
+ {
257
+ text: translationMap.get('Cancel'),
258
+ role: 'cancel',
259
+ cssClass: 'secondary',
260
+ handler: (blah) => {
261
+ }
262
+ }, {
263
+ text: 'Ok',
264
+ handler: () => {
265
+ this.tiledeskService.addParticipant(request.uid, this.loggedUserUid, request.attributes.projectId).subscribe((res: any) => {
266
+ this.logger.log('[APP-COMP] addParticipant - RES ', res);
267
+ this.onClose(request);
268
+ }, (error) => {
269
+ this.logger.error('[APP-COMP] addParticipant - ERROR ', error);
270
+ }, () => {
271
+ this.logger.log('[APP-COMP] addParticipant - COMPLETE ');
272
+ });
273
+ }
274
+ }
275
+ ]
276
+ });
277
+
278
+ await alert.present();
279
+ }
280
+
120
281
  onLoad(iframe){
121
282
  let styleData = localStorage.getItem('custom_style')
122
283
  if(styleData && styleData !== 'undefined'){
@@ -185,18 +346,123 @@ export class UnassignedConversationsPage implements OnInit {
185
346
  }
186
347
 
187
348
 
188
- async onClose() {
349
+ onConversationSelected(conversation: ConversationModel) {
350
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] onConversationSelected', conversation);
351
+ this.uidConvSelected = conversation?.uid;
352
+ const fullName = conversation?.conversation_with_fullname || '';
353
+ const pageUrl = 'conversation-detail/' + conversation.uid + '/' + encodeURIComponent(fullName) + '/unassigned';
354
+ this.modalController.dismiss({ conversation }).then(() => {
355
+ this.router.navigateByUrl(pageUrl.replace(/\(/g, '%28').replace(/\)/g, '%29'));
356
+ }).catch(() => {
357
+ this.navService.pop();
358
+ this.router.navigateByUrl(pageUrl.replace(/\(/g, '%28').replace(/\)/g, '%29'));
359
+ });
360
+ }
361
+
362
+ onCloseConversation(conversation: ConversationModel) {
363
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] onCloseConversation', conversation);
364
+ this.tiledeskService.closeSupportGroup(conversation.attributes.projectId, conversation.uid).subscribe((res: any) => {
365
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] archiveRequest - RES ', res);
366
+ this.onClose();
367
+ }, (error) => {
368
+ this.logger.error('[UNASSIGNED-CONVS-PAGE] archiveRequest - ERROR ', error);
369
+ }, () => {
370
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] archiveRequest - COMPLETE ');
371
+ });
372
+ }
373
+
374
+ onJoinConversation(conversation: ConversationModel) {
375
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] onJoinConversation', conversation);
376
+ this.presentAlertConfirmJoinRequest(conversation)
377
+ }
378
+
379
+ onImageLoaded(conversation: any) {
380
+ // this.logger.log('[CONVS-LIST-PAGE] onImageLoaded', conversation)
381
+ let conversation_with_fullname = conversation.sender_fullname
382
+ let conversation_with = conversation.sender
383
+ if (conversation.sender === this.loggedUserUid) {
384
+ conversation_with = conversation.recipient
385
+ conversation_with_fullname = conversation.recipient_fullname
386
+ } else if (isGroup(conversation)) {
387
+ // conversation_with_fullname = conv.sender_fullname;
388
+ // conv.last_message_text = conv.last_message_text;
389
+ conversation_with = conversation.recipient
390
+ conversation_with_fullname = conversation.recipient_fullname
391
+ }
392
+ if (!conversation_with.startsWith('support-group')) {
393
+ conversation.image = this.imageRepoService.getImagePhotoUrl(conversation_with)
394
+ }
395
+ }
396
+
397
+ onConversationLoaded(conversation: ConversationModel) {
398
+ this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded ', conversation)
399
+ // this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded is new? ', conversation.is_new)
400
+ // if (conversation.is_new === false) {
401
+ // this.ionContentConvList.scrollToTop(0);
402
+ // }
403
+
404
+ const keys = ['YOU', 'SENT_AN_IMAGE', 'SENT_AN_ATTACHMENT']
405
+ const translationMap = this.translateService.translateLanguage(keys)
406
+ // Fixes the bug: if a snippet of code is pasted and sent it is not displayed correctly in the convesations list
407
+
408
+ var regex = /<br\s*[\/]?>/gi
409
+ if (conversation ) { //&& conversation.last_message_text
410
+ conversation.last_message_text = conversation.last_message_text.replace(regex, '',)
411
+
412
+ //FIX-BUG: 'YOU: YOU: YOU: text' on last-message-text in conversation-list
413
+ if (conversation.sender === this.loggedUserUid && !conversation.last_message_text.includes(': ')) {
414
+ // this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded', conversation)
415
+
416
+ if (conversation.type !== 'image' && conversation.type !== 'file') {
417
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + conversation.last_message_text
418
+ } else if (conversation.type === 'image') {
419
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT AN IMAGE');
420
+ // this.logger.log("[CONVS-LIST-PAGE] translationMap.get('YOU')")
421
+ const SENT_AN_IMAGE = (conversation['last_message_text'] = translationMap.get('SENT_AN_IMAGE'))
422
+
423
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + SENT_AN_IMAGE
424
+ } else if (conversation.type === 'file') {
425
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT FILE')
426
+ const SENT_AN_ATTACHMENT = (conversation['last_message_text'] = translationMap.get('SENT_AN_ATTACHMENT'))
427
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + SENT_AN_ATTACHMENT
428
+ }
429
+ } else {
430
+ if (conversation.type === 'image') {
431
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT AN IMAGE');
432
+ // this.logger.log("[CONVS-LIST-PAGE] translationMap.get('YOU')")
433
+ const SENT_AN_IMAGE = (conversation['last_message_text'] = translationMap.get('SENT_AN_IMAGE'))
434
+
435
+ conversation.last_message_text = SENT_AN_IMAGE
436
+ } else if (conversation.type === 'file') {
437
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT FILE')
438
+ const SENT_AN_ATTACHMENT = (conversation['last_message_text'] = translationMap.get('SENT_AN_ATTACHMENT'))
439
+ conversation.last_message_text = SENT_AN_ATTACHMENT
440
+ }
441
+ }
442
+ }
443
+
444
+ const project = this.getProjectFromStorage(conversation);
445
+ if (project) {
446
+ if (!conversation.attributes) conversation.attributes = {};
447
+ conversation.attributes.projectId = project._id;
448
+ conversation.attributes.project_name = project.name;
449
+ }
450
+ }
451
+
452
+ async onClose(conversation?: ConversationModel) {
189
453
  this.logger.log('[UNASSIGNED-CONVS-PAGE] - onClose MODAL')
190
- this.logger.log('[UNASSIGNED-CONVS-PAGE] - onClose MODAL isModalOpened ', await this.modalController.getTop())
191
454
  const isModalOpened = await this.modalController.getTop();
192
455
  this.logger.log('[UNASSIGNED-CONVS-PAGE] - onClose MODAL isModalOpened ', isModalOpened)
193
456
  if (isModalOpened) {
194
- this.modalController.dismiss({
195
- confirmed: true
196
- });
457
+ await this.modalController.dismiss({ confirmed: true });
197
458
  } else {
198
459
  this.navService.pop();
199
460
  }
461
+ if (conversation) {
462
+ const fullName = conversation.conversation_with_fullname || '';
463
+ const pageUrl = 'conversation-detail/' + conversation.uid + '/' + encodeURIComponent(fullName) + '/active';
464
+ this.router.navigateByUrl(pageUrl.replace(/\(/g, '%28').replace(/\)/g, '%29'));
465
+ }
200
466
  }
201
467
 
202
468
  }
@@ -0,0 +1,8 @@
1
+ import { FilterPipe } from './filter.pipe';
2
+
3
+ describe('FilterPipe', () => {
4
+ it('create an instance', () => {
5
+ const pipe = new FilterPipe();
6
+ expect(pipe).toBeTruthy();
7
+ });
8
+ });
@@ -0,0 +1,15 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+
3
+ @Pipe({
4
+ name: 'filter'
5
+ })
6
+ export class FilterPipe implements PipeTransform {
7
+
8
+ transform(items: any[], filter: Object): any {
9
+ if (!items || !filter) {
10
+ return items;
11
+ }
12
+ return items.filter(item => item[filter['key']] === filter['value']);
13
+ }
14
+
15
+ }
@@ -0,0 +1,8 @@
1
+ import { FindPipe } from './find.pipe';
2
+
3
+ describe('FindPipe', () => {
4
+ it('create an instance', () => {
5
+ const pipe = new FindPipe();
6
+ expect(pipe).toBeTruthy();
7
+ });
8
+ });
@@ -0,0 +1,15 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+
3
+ @Pipe({
4
+ name: 'find'
5
+ })
6
+ export class FindPipe implements PipeTransform {
7
+
8
+ transform(items: any[], filter: Object): any {
9
+ if (!items || !filter) {
10
+ return items;
11
+ }
12
+ return items.find(item => item[filter['key']] === filter['value']);
13
+ }
14
+
15
+ }
@@ -88,14 +88,14 @@ export class GlobalSettingsService {
88
88
  this.logger.debug('[GLOBAL-SET] setVariableFromStorage :::::::: SET VARIABLE ---------->', Object.keys(globals));
89
89
  for (const key of Object.keys(globals)) {
90
90
  const val = this.appStorageService.getItem(key);
91
- // this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals KEY ---------->', key);
92
- // this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals VAL ---------->', val);
91
+ this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals KEY ---------->', key);
92
+ this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals VAL ---------->', val);
93
93
  if (val && val !== null) {
94
94
  // globals.setParameter(key, val);
95
95
  globals[key] = stringToBoolean(val);
96
96
  }
97
97
  // this.logger.debug('[GLOBAL-SET] setVariableFromStorage SET globals == ---------->', globals);
98
- }
98
+ }
99
99
  }
100
100
 
101
101
  /**
@@ -113,6 +113,7 @@ export class GlobalSettingsService {
113
113
  TEMP = getParameterByName(windowContext, 'tiledesk_supportMode');
114
114
  if (TEMP) {
115
115
  globals.supportMode = stringToBoolean(TEMP);
116
+ this.appStorageService.setItem('supportMode', String(globals.supportMode))
116
117
  }
117
118
 
118
119
  TEMP = getParameterByName(windowContext, 'tiledesk_lang');
@@ -138,6 +139,13 @@ export class GlobalSettingsService {
138
139
  TEMP = getParameterByName(windowContext, 'tiledesk_projectID');
139
140
  if (TEMP) {
140
141
  globals.projectID = TEMP;
142
+ this.appStorageService.setItem('projectID', TEMP)
143
+ }
144
+
145
+ TEMP = getParameterByName(windowContext, 'tiledesk_logOut');
146
+ if (TEMP) {
147
+ globals.logOut = stringToBoolean(TEMP);
148
+ this.appStorageService.setItem('logOut', TEMP)
141
149
  }
142
150
 
143
151
  }
@@ -4,7 +4,6 @@ import { Router, NavigationExtras } from '@angular/router';
4
4
 
5
5
  // utils
6
6
  import { checkPlatformIsMobile } from '../../chat21-core/utils/utils';
7
- // import { ConversationDetailPage } from '../pages/conversation-detail/conversation-detail.page';
8
7
 
9
8
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
10
9
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { ProjectUsersService } from './project-users.service';
4
+
5
+ describe('ProjectUsersService', () => {
6
+ let service: ProjectUsersService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(ProjectUsersService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });
@@ -0,0 +1,63 @@
1
+ import { HttpClient, HttpHeaders } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { Observable } from 'rxjs';
4
+ import { map } from 'rxjs/operators';
5
+ import { ProjectUser } from 'src/chat21-core/models/projectUsers';
6
+ import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
7
+ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
8
+ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
9
+
10
+ @Injectable({
11
+ providedIn: 'root'
12
+ })
13
+ export class ProjectUsersService {
14
+
15
+ private SERVER_BASE_URL: string;
16
+ private tiledeskToken: string;
17
+
18
+ private logger: LoggerService = LoggerInstance.getInstance();
19
+ constructor(
20
+ public http: HttpClient,
21
+ public appStorageService: AppStorageService
22
+ ) {}
23
+
24
+ initialize(serverBaseUrl: string) {
25
+ this.logger.log('[TILEDESK-PROJECT_USERS-SERV] - initialize serverBaseUrl', serverBaseUrl);
26
+ this.SERVER_BASE_URL = serverBaseUrl;
27
+ this.tiledeskToken = this.appStorageService.getItem('tiledeskToken')
28
+ }
29
+
30
+ public getProjectUsersByProjectId(project_id: string): Observable<ProjectUser[]> {
31
+ const url = this.SERVER_BASE_URL + project_id + '/project_users/';
32
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER URL', url);
33
+
34
+ const httpOptions = {
35
+ headers: new HttpHeaders({
36
+ 'Content-Type': 'application/json',
37
+ Authorization: this.tiledeskToken
38
+ })
39
+ };
40
+ return this.http.get(url, httpOptions).pipe(map((res: any) => {
41
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER RES ', res);
42
+ return res
43
+ }))
44
+ }
45
+
46
+ public getProjectUserByProjectId(project_id: string): Promise<ProjectUser> {
47
+ const url = this.SERVER_BASE_URL + project_id + '/project_users/me';
48
+ this.logger.log('[TILEDESK-SERVICE]- GET PROJECT-USER BY USER-ID - URL', url);
49
+
50
+ const httpOptions = {
51
+ headers: new HttpHeaders({
52
+ 'Content-Type': 'application/json',
53
+ Authorization: this.tiledeskToken
54
+ })
55
+ };
56
+
57
+ return this.http.get(url, httpOptions).pipe(map((res: any) => {
58
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER RES ', res);
59
+ return res[0]
60
+ })).toPromise();
61
+ }
62
+
63
+ }
@@ -7,6 +7,7 @@ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance'
7
7
  import { AppConfigProvider } from '../app-config';
8
8
  import { Observable } from 'rxjs';
9
9
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
10
+ import { ProjectUser } from 'src/chat21-core/models/project_user';
10
11
 
11
12
  @Injectable({
12
13
  providedIn: 'root'
@@ -35,7 +36,7 @@ export class ProjectService {
35
36
  this.tiledeskToken = this.appStorageService.getItem('tiledeskToken')
36
37
  }
37
38
 
38
- public getProjects(): Observable<Project[]> {
39
+ public getProjects(): Observable<ProjectUser[]> {
39
40
  const url = this.SERVER_BASE_URL + "projects/";
40
41
  this.logger.log('[PROJECTS-SERVICE] getProjects - URL ', url);
41
42
 
@@ -7,6 +7,8 @@ import { map } from 'rxjs/operators';
7
7
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
8
8
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
9
9
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
10
+ import { Project } from 'src/chat21-core/models/projects';
11
+ import { Observable } from 'rxjs';
10
12
 
11
13
 
12
14
  @Injectable({
@@ -93,6 +95,7 @@ export class TiledeskService {
93
95
  }))
94
96
  }
95
97
 
98
+
96
99
  public getProjectUsersByProjectId(project_id: string) {
97
100
  const url = this.SERVER_BASE_URL + project_id + '/project_users/';
98
101
  this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER URL', url);
@@ -260,5 +263,26 @@ export class TiledeskService {
260
263
  return res
261
264
  }))
262
265
  }
266
+
267
+ // -----------------------------------------------------------------------------------------
268
+ // @ Add participant to request
269
+ // -----------------------------------------------------------------------------------------
270
+ public addParticipant(requestid: string, userid: string, project_id: string) {
271
+ const url = this.SERVER_BASE_URL + project_id + '/requests/' + requestid + '/participants';
272
+ this.logger.log('[TILEDESK-SERVICE] addParticipant - URL ', url)
273
+ const httpOptions = {
274
+ headers: new HttpHeaders({
275
+ 'Content-Type': 'application/json',
276
+ 'Authorization': this.tiledeskToken
277
+ })
278
+ };
279
+
280
+ const body = { 'member': userid };
281
+
282
+ return this.http.post(url, JSON.stringify(body), httpOptions).pipe(map((res: any) => {
283
+ this.logger.log('[TILEDESK-SERVICE] addParticipant - RES ', res);
284
+ return res
285
+ }))
286
+ }
263
287
 
264
288
  }