@chat21/chat21-ionic 3.4.29 → 3.4.30-rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +120 -2
- package/angular.json +1 -0
- package/package.json +1 -1
- package/src/app/app.component.html +3 -1
- package/src/app/app.component.ts +71 -12
- package/src/app/chatlib/conversation-detail/message/image/image.component.html +1 -0
- package/src/app/chatlib/conversation-detail/message/image/image.component.ts +19 -0
- package/src/app/components/canned-response/canned-response.component.html +26 -23
- package/src/app/components/canned-response/canned-response.component.scss +0 -2
- package/src/app/components/canned-response/canned-response.component.ts +3 -1
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +39 -9
- package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
- package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
- package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
- package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
- package/src/app/components/navbar/navbar.component.html +3 -3
- package/src/app/components/navbar/navbar.component.ts +29 -38
- package/src/app/components/project-item/project-item.component.ts +11 -11
- package/src/app/components/sidebar/sidebar.component.html +65 -45
- package/src/app/components/sidebar/sidebar.component.ts +110 -117
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +2 -2
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +10 -7
- package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
- package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
- package/src/app/pages/conversation-detail/conversation-detail.page.ts +95 -7
- package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
- package/src/app/pages/conversations-list/conversations-list.page.ts +40 -2
- package/src/app/services/global-settings/global-settings.service.ts +11 -3
- package/src/app/services/nav-proxy.service.ts +0 -1
- package/src/app/services/project_users/project-users.service.spec.ts +16 -0
- package/src/app/services/project_users/project-users.service.ts +63 -0
- package/src/app/services/tiledesk/tiledesk.service.ts +0 -16
- package/src/app/services/triggerEvents/triggerEvents.ts +28 -0
- package/src/app/services/websocket/websocket-js.ts +59 -534
- package/src/app/services/websocket/websocket-js_old.ts +578 -0
- package/src/app/services/websocket/websocket.service.ts +9 -10
- package/src/app/services/websocket/websocket.worker.ts +242 -0
- package/src/app/shared/shared.module.ts +11 -2
- package/src/app/utils/globals.ts +2 -0
- package/src/app/utils/permissions.constants.ts +138 -0
- package/src/app/utils/project-utils.ts +2 -2
- package/src/app/utils/utils.ts +18 -1
- package/src/assets/i18n/ar.json +11 -1
- package/src/assets/i18n/az.json +11 -1
- package/src/assets/i18n/de.json +11 -1
- package/src/assets/i18n/en.json +11 -1
- package/src/assets/i18n/es.json +11 -1
- package/src/assets/i18n/fr.json +11 -1
- package/src/assets/i18n/it.json +13 -3
- package/src/assets/i18n/kk.json +11 -1
- package/src/assets/i18n/pt.json +11 -1
- package/src/assets/i18n/ru.json +11 -1
- package/src/assets/i18n/sr.json +11 -1
- package/src/assets/i18n/sv.json +11 -1
- package/src/assets/i18n/tr.json +11 -1
- package/src/assets/i18n/uk.json +11 -1
- package/src/assets/i18n/uz.json +12 -1
- package/src/assets/img/no_data_found.png +0 -0
- package/src/assets/js/agentDesktop-sdk.js +55 -0
- package/src/assets/js/chat21client.js +36 -0
- package/src/assets/js/mqtt-keepalive-worker.js +53 -0
- package/src/assets/test.html +5 -2
- package/src/chat-config-template.json +1 -0
- package/src/chat-config.json +1 -0
- package/src/chat21-core/models/projectUsers.ts +19 -0
- package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
- package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
- package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
- package/src/chat21-core/utils/utils.ts +16 -2
|
@@ -83,7 +83,12 @@ import { WebsocketService } from 'src/app/services/websocket/websocket.service';
|
|
|
83
83
|
import { Project } from 'src/chat21-core/models/projects';
|
|
84
84
|
import { Globals } from 'src/app/utils/globals';
|
|
85
85
|
import { ProjectService } from 'src/app/services/projects/project.service';
|
|
86
|
-
import {
|
|
86
|
+
import { UploadService } from 'src/chat21-core/providers/abstract/upload.service';
|
|
87
|
+
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
88
|
+
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
89
|
+
import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
90
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
91
|
+
import { TriggerEvents } from 'src/app/services/triggerEvents/triggerEvents';
|
|
87
92
|
|
|
88
93
|
@Component({
|
|
89
94
|
selector: 'app-conversation-detail',
|
|
@@ -108,6 +113,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
108
113
|
private subscriptions: Array<any>
|
|
109
114
|
public tenant: string;
|
|
110
115
|
public loggedUser: UserModel
|
|
116
|
+
public projectUser: ProjectUser;
|
|
111
117
|
public conversationWith: string
|
|
112
118
|
public conversationWithFullname: string
|
|
113
119
|
public messages: Array<MessageModel> = []
|
|
@@ -137,6 +143,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
137
143
|
public tagsCannedFilter: Array<any> = [];
|
|
138
144
|
public SHOW_CANNED_RESPONSES: boolean = false
|
|
139
145
|
public canShowCanned: boolean = true
|
|
146
|
+
public rolesCanned: { [key: string]: boolean }
|
|
140
147
|
|
|
141
148
|
public SHOW_COPILOT_SUGGESTIONS: boolean = false;
|
|
142
149
|
|
|
@@ -171,6 +178,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
171
178
|
copilotQuestion: string = '';
|
|
172
179
|
/**COPILOT : end */
|
|
173
180
|
|
|
181
|
+
/** TICKET: start */
|
|
182
|
+
isTicketEnabled: boolean = false;
|
|
183
|
+
/** TICKET: end */
|
|
184
|
+
|
|
174
185
|
isMine = isMine
|
|
175
186
|
isInfo = isInfo
|
|
176
187
|
isFirstMessage = isFirstMessage
|
|
@@ -236,22 +247,25 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
236
247
|
public conversationHandlerBuilderService: ConversationHandlerBuilderService,
|
|
237
248
|
public cannedResponsesService: CannedResponsesService,
|
|
238
249
|
public imageRepoService: ImageRepoService,
|
|
250
|
+
public uploadService: UploadService,
|
|
239
251
|
public presenceService: PresenceService,
|
|
240
252
|
public toastController: ToastController,
|
|
241
253
|
public tiledeskService: TiledeskService,
|
|
242
254
|
public projectService: ProjectService,
|
|
255
|
+
public projectUsersService: ProjectUsersService,
|
|
243
256
|
private networkService: NetworkService,
|
|
244
257
|
private events: EventsService,
|
|
245
258
|
private webSocketService: WebsocketService,
|
|
246
259
|
public projectPlanUtils: ProjectPlanUtils,
|
|
260
|
+
public triggerEvents: TriggerEvents,
|
|
247
261
|
private g: Globals,
|
|
248
262
|
) {
|
|
249
263
|
// Change list on date change
|
|
250
264
|
this.route.paramMap.subscribe((params) => {
|
|
251
265
|
this.logger.log('[CONVS-DETAIL] - constructor -> params: ', params)
|
|
252
266
|
this.conversationWith = params.get('IDConv')
|
|
253
|
-
this.conversationWithFullname = params.get('FullNameConv')
|
|
254
|
-
this.conv_type = params.get('Convtype')
|
|
267
|
+
this.conversationWithFullname = decodeURIComponent(params.get('FullNameConv'))
|
|
268
|
+
this.conv_type = decodeURIComponent(params.get('Convtype'))
|
|
255
269
|
|
|
256
270
|
this.events.publish('supportconvid:haschanged', this.conversationWith)
|
|
257
271
|
})
|
|
@@ -418,6 +432,8 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
418
432
|
ionViewDidEnter() {
|
|
419
433
|
this.logger.log('[CONVS-DETAIL] > ionViewDidEnter')
|
|
420
434
|
// this.info_content_child_enabled = true;
|
|
435
|
+
// Scroll to bottom to show the last message without animation
|
|
436
|
+
this.scrollToLastMessage()
|
|
421
437
|
}
|
|
422
438
|
|
|
423
439
|
// Unsubscibe when new page transition end
|
|
@@ -477,8 +493,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
477
493
|
this.messages = [] // list messages of conversation
|
|
478
494
|
this.isFileSelected = false // indicates if a file has been selected (image to upload)
|
|
479
495
|
this.isEmailEnabled = (this.appConfigProvider.getConfig().emailSection === 'true' || this.appConfigProvider.getConfig().emailSection === true) ? true : false;
|
|
496
|
+
this.isTicketEnabled = (this.appConfigProvider.getConfig().ticketSection === 'true' || this.appConfigProvider.getConfig().ticketSection === true) ? true : false;
|
|
480
497
|
this.isWhatsappTemplatesEnabled = (this.appConfigProvider.getConfig().whatsappTemplatesSection === 'true' || this.appConfigProvider.getConfig().whatsappTemplatesSection === true) ? true : false;
|
|
481
|
-
|
|
498
|
+
this.fileUploadAccept = this.appConfigProvider.getConfig().fileUploadAccept
|
|
499
|
+
|
|
482
500
|
this.cannedResponsesService.initialize(appconfig.apiUrl)
|
|
483
501
|
|
|
484
502
|
if (checkPlatformIsMobile()) {
|
|
@@ -507,10 +525,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
507
525
|
// this.initConversationsHandler(); // nk
|
|
508
526
|
if (this.conversationWith) {
|
|
509
527
|
this.disableTextarea = false
|
|
528
|
+
this.startConversation();
|
|
510
529
|
this._getProjectIdByConversationWith(this.conversationWith)
|
|
511
530
|
this.initConversationHandler()
|
|
512
531
|
this.initGroupsHandler();
|
|
513
|
-
this.startConversation();
|
|
514
532
|
this.initSubscriptions();
|
|
515
533
|
this.getLeadDetail();
|
|
516
534
|
this.initializeTyping();
|
|
@@ -521,6 +539,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
521
539
|
}
|
|
522
540
|
|
|
523
541
|
_getProjectIdByConversationWith(conversationWith: string) {
|
|
542
|
+
console.log('[CONVS-DETAIL] - _getProjectIdByConversationWith conversationWith', conversationWith, this.channelType)
|
|
524
543
|
if (this.channelType !== TYPE_DIRECT && !this.conversationWith.startsWith('group-')) {
|
|
525
544
|
this.tiledeskService.getProjectIdByConvRecipient(conversationWith).subscribe((res) => {
|
|
526
545
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT RES + projectId', res, res.id_project)
|
|
@@ -534,7 +553,6 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
534
553
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT * COMPLETE *',)
|
|
535
554
|
})
|
|
536
555
|
}else {
|
|
537
|
-
this.canShowCanned = false;
|
|
538
556
|
this.offlineMsgEmail = false;
|
|
539
557
|
}
|
|
540
558
|
|
|
@@ -545,10 +563,13 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
545
563
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT RES', project)
|
|
546
564
|
if (project) {
|
|
547
565
|
const projectId = project.id_project
|
|
548
|
-
this.
|
|
566
|
+
this.projectUser = await this.projectUsersService.getProjectUserByProjectId(project._id)
|
|
549
567
|
this.offlineMsgEmail = this.checkOfflineMsgEmailIsEnabled(project)
|
|
550
568
|
this.isCopilotEnabled = this.projectPlanUtils.checkProjectProfileFeature(project, 'copilot');
|
|
551
569
|
this.fileUploadAccept = this.checkAcceptedUploadFile(project)
|
|
570
|
+
this.rolesCanned = this.checkCannedResponsesRoles()
|
|
571
|
+
this.canShowCanned = this.checkCannedResponses(project)
|
|
572
|
+
this.logger.log('[CONVS-DETAIL] this.rolesCanned ', this.canShowCanned)
|
|
552
573
|
}
|
|
553
574
|
}, (error) => {
|
|
554
575
|
this.logger.error('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT - ERROR ', error)
|
|
@@ -586,6 +607,40 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
586
607
|
return this.appConfigProvider.getConfig().fileUploadAccept
|
|
587
608
|
}
|
|
588
609
|
|
|
610
|
+
checkCannedResponses(project: Project): boolean {
|
|
611
|
+
let expires = this.projectPlanUtils.checkPlanIsExpired(project)
|
|
612
|
+
this.logger.log('[CONVS-DETAIL] checkCannedResponses expires ', expires)
|
|
613
|
+
if(expires){
|
|
614
|
+
return false
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
let hasRoleToShowCanned = this.rolesCanned[PERMISSIONS.CANNED_RESPONSES_READ]
|
|
618
|
+
this.logger.log('[CONVS-DETAIL] checkCannedResponses hasRoleToShowCanned ', hasRoleToShowCanned)
|
|
619
|
+
if(!hasRoleToShowCanned){
|
|
620
|
+
return false
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return true
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
checkCannedResponsesRoles(): { [key: string]: boolean } {
|
|
627
|
+
const permissionKeys = [
|
|
628
|
+
'CANNED_RESPONSES_CREATE',
|
|
629
|
+
'CANNED_RESPONSES_READ',
|
|
630
|
+
'CANNED_RESPONSES_UPDATE',
|
|
631
|
+
'CANNED_RESPONSES_DELETE',
|
|
632
|
+
] as const;
|
|
633
|
+
|
|
634
|
+
const roles: { [key: string]: boolean } = {};
|
|
635
|
+
for (const key of permissionKeys) {
|
|
636
|
+
const permission = PERMISSIONS[key];
|
|
637
|
+
roles[permission] = hasRole(this.projectUser, permission);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return roles;
|
|
641
|
+
|
|
642
|
+
}
|
|
643
|
+
|
|
589
644
|
// getProjectIdSelectedConversation(conversationWith: string): string{
|
|
590
645
|
// const conversationWith_segments = conversationWith.split('-')
|
|
591
646
|
// // Removes the last element of the array if is = to the separator
|
|
@@ -669,6 +724,11 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
669
724
|
"WHATSAPP.ERROR_WHATSAPP_NOT_INSTALLED",
|
|
670
725
|
"WHATSAPP.ERROR_WHATSAPP_GENERIC_ERROR",
|
|
671
726
|
|
|
727
|
+
"TICKET.OPEN_TICKET",
|
|
728
|
+
"TICKET.DESCRIPTION",
|
|
729
|
+
"TICKET.CONFIRM",
|
|
730
|
+
"TICKET.CLOSE",
|
|
731
|
+
|
|
672
732
|
"COPILOT.ASK_AI",
|
|
673
733
|
"COPILOT.NO_SUGGESTIONS_PRESENT",
|
|
674
734
|
|
|
@@ -1884,6 +1944,11 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1884
1944
|
}
|
|
1885
1945
|
|
|
1886
1946
|
|
|
1947
|
+
onOpenTicket(event) {
|
|
1948
|
+
this.logger.debug('[CONVS-DETAIL] openTicketOnExternalService - conversationWith ', this.conversationWith)
|
|
1949
|
+
const detailOBJ = { event: 'onOpenTicketExternally', request_id: this.conversationWith, conversation: this.conversation }
|
|
1950
|
+
this.triggerEvents.triggerOnOpenTicketExternally(detailOBJ)
|
|
1951
|
+
}
|
|
1887
1952
|
// -------------- START SCROLL/RESIZE -------------- //
|
|
1888
1953
|
/** */
|
|
1889
1954
|
resizeTextArea() {
|
|
@@ -1927,6 +1992,29 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1927
1992
|
}
|
|
1928
1993
|
}
|
|
1929
1994
|
|
|
1995
|
+
/**
|
|
1996
|
+
* Scroll to last message without animation using requestAnimationFrame
|
|
1997
|
+
* This is a best practice alternative to setTimeout
|
|
1998
|
+
*/
|
|
1999
|
+
private scrollToLastMessage() {
|
|
2000
|
+
this.showIonContent = true
|
|
2001
|
+
if (this.ionContentChatArea) {
|
|
2002
|
+
// Use requestAnimationFrame for better performance
|
|
2003
|
+
requestAnimationFrame(() => {
|
|
2004
|
+
requestAnimationFrame(() => {
|
|
2005
|
+
// Double RAF ensures DOM is fully rendered
|
|
2006
|
+
this.ionContentChatArea.scrollToBottom(0).then(() => {
|
|
2007
|
+
this.logger.log('[CONVS-DETAIL] scroll posizionato all\'ultimo messaggio')
|
|
2008
|
+
}).catch((error) => {
|
|
2009
|
+
this.logger.error('[CONVS-DETAIL] errore durante lo scroll:', error)
|
|
2010
|
+
})
|
|
2011
|
+
})
|
|
2012
|
+
})
|
|
2013
|
+
} else {
|
|
2014
|
+
this.logger.warn('[CONVS-DETAIL] ionContentChatArea non disponibile')
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
|
|
1930
2018
|
/**
|
|
1931
2019
|
* detectBottom
|
|
1932
2020
|
*/
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
[sound_btn]="sound_btn"
|
|
8
8
|
[isMobile]="isMobile"
|
|
9
9
|
[isVisibleTKT]="isVisibleTKT"
|
|
10
|
+
[isVisibleCNT]="isVisibleCNT"
|
|
11
|
+
[roles]="rolesHeader"
|
|
10
12
|
(onSoundChange)="onSoundChange($event)"
|
|
11
13
|
(openContactsDirectory)=openContactsDirectory($event)
|
|
12
14
|
(openProfileInfo)=openProfileInfo($event)>
|
|
@@ -53,7 +53,10 @@ import { Globals } from 'src/app/utils/globals';
|
|
|
53
53
|
import { TriggerEvents } from 'src/app/services/triggerEvents/triggerEvents';
|
|
54
54
|
import { MessageModel } from 'src/chat21-core/models/message';
|
|
55
55
|
import { Project } from 'src/chat21-core/models/projects';
|
|
56
|
-
import { getOSCode } from 'src/app/utils/utils';
|
|
56
|
+
import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
57
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
58
|
+
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
59
|
+
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
57
60
|
|
|
58
61
|
@Component({
|
|
59
62
|
selector: 'app-conversations-list',
|
|
@@ -82,6 +85,7 @@ export class ConversationListPage implements OnInit {
|
|
|
82
85
|
public archived_btn: boolean
|
|
83
86
|
public sound_btn: string
|
|
84
87
|
public isVisibleTKT: boolean = true;
|
|
88
|
+
public isVisibleCNT: boolean = true;;
|
|
85
89
|
public convertMessage = convertMessage
|
|
86
90
|
private isShowMenuPage = false
|
|
87
91
|
private logger: LoggerService = LoggerInstance.getInstance()
|
|
@@ -104,6 +108,9 @@ export class ConversationListPage implements OnInit {
|
|
|
104
108
|
public isMobile: boolean = false;
|
|
105
109
|
public isInitialized: boolean = false;
|
|
106
110
|
|
|
111
|
+
public projectUser: ProjectUser;
|
|
112
|
+
public rolesHeader: { [key: string]: boolean }
|
|
113
|
+
|
|
107
114
|
// PROJECT AVAILABILITY INFO: start
|
|
108
115
|
project: Project
|
|
109
116
|
profile_name_translated: string;
|
|
@@ -130,6 +137,7 @@ export class ConversationListPage implements OnInit {
|
|
|
130
137
|
private translateService: CustomTranslateService,
|
|
131
138
|
public tiledeskService: TiledeskService,
|
|
132
139
|
public tiledeskAuthService: TiledeskAuthService,
|
|
140
|
+
public projectUsersService: ProjectUsersService,
|
|
133
141
|
public appConfigProvider: AppConfigProvider,
|
|
134
142
|
public platform: Platform,
|
|
135
143
|
public wsService: WebsocketService,
|
|
@@ -371,6 +379,11 @@ export class ConversationListPage implements OnInit {
|
|
|
371
379
|
// save conversationHandler in chatManager
|
|
372
380
|
this.chatManager.setConversationsHandler(this.conversationsHandlerService)
|
|
373
381
|
this.showPlaceholder = false
|
|
382
|
+
|
|
383
|
+
// Hide loading spinner if there are no conversations
|
|
384
|
+
if (this.conversations.length === 0) {
|
|
385
|
+
this.loadingIsActive = false
|
|
386
|
+
}
|
|
374
387
|
}
|
|
375
388
|
|
|
376
389
|
// private manageStoredConversations() {
|
|
@@ -471,7 +484,7 @@ export class ConversationListPage implements OnInit {
|
|
|
471
484
|
}
|
|
472
485
|
|
|
473
486
|
listenToCurrentStoredProject() {
|
|
474
|
-
this.events.subscribe('storage:last_project', projectObjct => {
|
|
487
|
+
this.events.subscribe('storage:last_project', async(projectObjct) => {
|
|
475
488
|
if (projectObjct && projectObjct !== 'undefined') {
|
|
476
489
|
this.logger.log('[CONVS-LIST-PAGE] - GET STORED PROJECT ', projectObjct)
|
|
477
490
|
|
|
@@ -496,6 +509,10 @@ export class ConversationListPage implements OnInit {
|
|
|
496
509
|
} else if (this.project.profile.type === 'payment' && this.project.profile.name === 'enterprise') {
|
|
497
510
|
this.profile_name_translated = this.translationMapHeader.get('PaydPlanNameEnterprise');
|
|
498
511
|
}
|
|
512
|
+
|
|
513
|
+
this.projectUser = await this.projectUsersService.getProjectUserByProjectId(this.project._id)
|
|
514
|
+
this.rolesHeader = this.checkCannedResponsesRoles();
|
|
515
|
+
this.logger.log('[CONVS-LIST-PAGE] - GET PROJECT USER ROLES ', this.rolesHeader)
|
|
499
516
|
}
|
|
500
517
|
})
|
|
501
518
|
}
|
|
@@ -631,8 +648,24 @@ export class ConversationListPage implements OnInit {
|
|
|
631
648
|
const public_Key = this.appConfigProvider.getConfig().t2y12PruGU9wUtEGzBJfolMIgK
|
|
632
649
|
this.logger.log('[CONVS-LIST-PAGE] AppConfigService getAppConfig public_Key', public_Key)
|
|
633
650
|
this.isVisibleTKT = getOSCode("TKT", public_Key);
|
|
651
|
+
this.isVisibleCNT = getOSCode("CNT", public_Key);
|
|
634
652
|
}
|
|
635
653
|
|
|
654
|
+
checkCannedResponsesRoles(): { [key: string]: boolean } {
|
|
655
|
+
const permissionKeys = [
|
|
656
|
+
'LEADS_READ',
|
|
657
|
+
] as const;
|
|
658
|
+
|
|
659
|
+
const roles: { [key: string]: boolean } = {};
|
|
660
|
+
for (const key of permissionKeys) {
|
|
661
|
+
const permission = PERMISSIONS[key];
|
|
662
|
+
roles[permission] = hasRole(this.projectUser, permission);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return roles;
|
|
666
|
+
|
|
667
|
+
}
|
|
668
|
+
|
|
636
669
|
onBackButtonFN(event) {
|
|
637
670
|
this.conversationType = 'active'
|
|
638
671
|
|
|
@@ -883,6 +916,10 @@ export class ConversationListPage implements OnInit {
|
|
|
883
916
|
|
|
884
917
|
this.logger.log('[CONVS-LIST-PAGE] navigateByUrl this.uidConvSelected ', this.uidConvSelected)
|
|
885
918
|
|
|
919
|
+
const queryParams = this.route.snapshot.queryParams;
|
|
920
|
+
const queryString = new URLSearchParams(queryParams).toString();
|
|
921
|
+
|
|
922
|
+
|
|
886
923
|
this.setUidConvSelected(uidConvSelected, converationType)
|
|
887
924
|
if (checkPlatformIsMobile()) {
|
|
888
925
|
this.logger.log('[CONVS-LIST-PAGE] checkPlatformIsMobile(): ', checkPlatformIsMobile())
|
|
@@ -900,6 +937,7 @@ export class ConversationListPage implements OnInit {
|
|
|
900
937
|
if (this.conversationSelected && this.conversationSelected.conversation_with_fullname) {
|
|
901
938
|
pageUrl = 'conversation-detail/' + this.uidConvSelected + '/' + encodeURIComponent(this.conversationSelected.conversation_with_fullname) + '/' + converationType
|
|
902
939
|
}
|
|
940
|
+
pageUrl += queryString ? `?${queryString}` : '';
|
|
903
941
|
this.logger.log('[CONVS-LIST-PAGE] setUidConvSelected navigateByUrl--->: ', pageUrl)
|
|
904
942
|
// replace(/\(/g, '%28').replace(/\)/g, '%29') -> used for the encoder of any round brackets
|
|
905
943
|
this.router.navigateByUrl(pageUrl.replace(/\(/g, '%28').replace(/\)/g, '%29'), {replaceUrl: true})
|
|
@@ -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
|
-
|
|
92
|
-
|
|
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
|
+
}
|
|
@@ -93,22 +93,6 @@ export class TiledeskService {
|
|
|
93
93
|
}))
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
public getProjectUsersByProjectId(project_id: string) {
|
|
97
|
-
const url = this.SERVER_BASE_URL + project_id + '/project_users/';
|
|
98
|
-
this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER URL', url);
|
|
99
|
-
|
|
100
|
-
const httpOptions = {
|
|
101
|
-
headers: new HttpHeaders({
|
|
102
|
-
'Content-Type': 'application/json',
|
|
103
|
-
Authorization: this.tiledeskToken
|
|
104
|
-
})
|
|
105
|
-
};
|
|
106
|
-
return this.http.get(url, httpOptions).pipe(map((res: any) => {
|
|
107
|
-
this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER RES ', res);
|
|
108
|
-
return res
|
|
109
|
-
}))
|
|
110
|
-
}
|
|
111
|
-
|
|
112
96
|
public getAllLeadsActiveWithLimit(project_id: string, limit: number) {
|
|
113
97
|
const url = this.SERVER_BASE_URL + project_id + '/leads?limit=' + limit + '&with_fullname=true';
|
|
114
98
|
this.logger.log('[TILEDESK-SERVICE] - GET ALL ACTIVE LEADS (LIMIT 10000) - URL', url);
|
|
@@ -102,5 +102,33 @@ export class TriggerEvents {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
public triggerOnUpdateNewConversationBadge(detailObj: {}) {
|
|
106
|
+
this.logger.debug(' ---------------- triggerOnUpdateNewConversationBadge ---------------- ', detailObj);
|
|
107
|
+
try {
|
|
108
|
+
const onBeforeInit = new CustomEvent('onUpdateNewConversationBadge', { detail: detailObj });
|
|
109
|
+
const windowContext = this.windowContext;
|
|
110
|
+
if (windowContext){
|
|
111
|
+
// windowContext.document.dispatchEvent(onNewConversation);
|
|
112
|
+
windowContext.postMessage({type: "onUpdateNewConversationBadge", detail: detailObj }, '*')
|
|
113
|
+
}
|
|
114
|
+
} catch (e) {
|
|
115
|
+
this.logger.error('[TRIGGER-HANDLER] > Error:' + e);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public triggerOnOpenTicketExternally(detailObj: {}) {
|
|
120
|
+
this.logger.debug(' ---------------- triggerOnOpenTicketExternally ---------------- ', detailObj);
|
|
121
|
+
try {
|
|
122
|
+
const onBeforeInit = new CustomEvent('onOpenTicketExternally', { detail: detailObj });
|
|
123
|
+
const windowContext = this.windowContext;
|
|
124
|
+
if (windowContext){
|
|
125
|
+
// windowContext.document.dispatchEvent(onNewConversation);
|
|
126
|
+
windowContext.postMessage({type: "onOpenTicketExternally", detail: detailObj }, '*')
|
|
127
|
+
}
|
|
128
|
+
} catch (e) {
|
|
129
|
+
this.logger.error('[TRIGGER-HANDLER] > Error:' + e);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
105
133
|
|
|
106
134
|
}
|