@chat21/chat21-ionic 3.4.30 → 3.4.32-rc1
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 +131 -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 +72 -13
- 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/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +14 -2
- package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +39 -2
- package/src/app/chatlib/list-conversations-component/list-conversations.module.ts +14 -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 +35 -9
- package/src/app/components/navbar/navbar.component.scss +64 -0
- package/src/app/components/navbar/navbar.component.ts +100 -42
- package/src/app/components/project-item/project-item.component.ts +79 -51
- 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 +3 -3
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +15 -22
- package/src/app/directives/html-entities-encode.pipe.ts +20 -5
- 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.module.ts +3 -5
- package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
- package/src/app/pages/conversations-list/conversations-list.page.ts +51 -11
- package/src/app/pages/unassigned-conversations/unassigned-conversations.module.ts +16 -4
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +41 -17
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +10 -1
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +114 -9
- 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/projects/project.service.ts +2 -1
- package/src/app/services/tiledesk/tiledesk.service.ts +21 -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 +59 -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/models/project_user.ts +2 -1
- 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/constants.ts +5 -0
- package/src/chat21-core/utils/convertRequestToConversation.ts +1 -1
- package/src/chat21-core/utils/utils.ts +53 -3
- package/src/variables.scss +3 -0
|
@@ -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
|
*/
|
|
@@ -19,8 +19,7 @@ import { ProfileInfoPageModule } from '../profile-info/profile-info.module';
|
|
|
19
19
|
// import { ConversationDetailPageModule } from '../conversation-detail/conversation-detail.module';
|
|
20
20
|
import { SharedModule } from 'src/app/shared/shared.module';
|
|
21
21
|
import { ScrollbarThemeModule } from '../../utils/scrollbar-theme.directive';
|
|
22
|
-
import {
|
|
23
|
-
import { IonListConversationsComponent } from 'src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component';
|
|
22
|
+
import { ListConversationsModule } from 'src/app/chatlib/list-conversations-component/list-conversations.module';
|
|
24
23
|
import { HeaderConversationsList } from 'src/app/components/conversations-list/header-conversations-list/header-conversations-list.component';
|
|
25
24
|
import { HeaderConversationsListArchived } from 'src/app/components/conversations-list/header-conversations-list-archived/header-conversations-list-archived.component';
|
|
26
25
|
import { HeaderConversationsListUnassigned } from 'src/app/components/conversations-list/header-conversations-list-unassigned/header-conversations-list-unassigned.component';
|
|
@@ -46,14 +45,13 @@ import { MomentModule } from 'ngx-moment';
|
|
|
46
45
|
}
|
|
47
46
|
}),
|
|
48
47
|
SharedModule,
|
|
49
|
-
MomentModule
|
|
48
|
+
MomentModule,
|
|
49
|
+
ListConversationsModule
|
|
50
50
|
],
|
|
51
51
|
// entryComponents: [DdpHeaderComponent],
|
|
52
52
|
declarations: [
|
|
53
53
|
ConversationListPage,
|
|
54
54
|
//******** COMPONENTS - init ********//
|
|
55
|
-
ListConversationsComponent,
|
|
56
|
-
IonListConversationsComponent,
|
|
57
55
|
HeaderConversationsList,
|
|
58
56
|
HeaderConversationsListArchived,
|
|
59
57
|
HeaderConversationsListUnassigned,
|
|
@@ -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,
|
|
@@ -294,17 +302,19 @@ export class ConversationListPage implements OnInit {
|
|
|
294
302
|
// ---------------------------------------------------------
|
|
295
303
|
// Opens the Unassigned Conversations iframe
|
|
296
304
|
// ---------------------------------------------------------
|
|
297
|
-
openUnassignedConversations(IFRAME_URL: string, event) {
|
|
305
|
+
openUnassignedConversations(IFRAME_URL: string, event: { event: string; data: ConversationModel[] }) {
|
|
306
|
+
const unassignedConversations = event?.data ?? [];
|
|
307
|
+
const params = {
|
|
308
|
+
iframe_URL: IFRAME_URL,
|
|
309
|
+
callerBtn: event.event,
|
|
310
|
+
unassignedConversations,
|
|
311
|
+
stylesMap: this.stylesMap,
|
|
312
|
+
translationMapConversation: this.translationMapConversation,
|
|
313
|
+
};
|
|
298
314
|
if (checkPlatformIsMobile()) {
|
|
299
|
-
presentModal(this.modalController, UnassignedConversationsPage,
|
|
300
|
-
iframe_URL: IFRAME_URL,
|
|
301
|
-
callerBtn: event,
|
|
302
|
-
})
|
|
315
|
+
presentModal(this.modalController, UnassignedConversationsPage, params);
|
|
303
316
|
} else {
|
|
304
|
-
this.navService.push(UnassignedConversationsPage,
|
|
305
|
-
iframe_URL: IFRAME_URL,
|
|
306
|
-
callerBtn: event,
|
|
307
|
-
})
|
|
317
|
+
this.navService.push(UnassignedConversationsPage, params);
|
|
308
318
|
}
|
|
309
319
|
}
|
|
310
320
|
|
|
@@ -371,6 +381,11 @@ export class ConversationListPage implements OnInit {
|
|
|
371
381
|
// save conversationHandler in chatManager
|
|
372
382
|
this.chatManager.setConversationsHandler(this.conversationsHandlerService)
|
|
373
383
|
this.showPlaceholder = false
|
|
384
|
+
|
|
385
|
+
// Hide loading spinner if there are no conversations
|
|
386
|
+
if (this.conversations.length === 0) {
|
|
387
|
+
this.loadingIsActive = false
|
|
388
|
+
}
|
|
374
389
|
}
|
|
375
390
|
|
|
376
391
|
// private manageStoredConversations() {
|
|
@@ -471,7 +486,7 @@ export class ConversationListPage implements OnInit {
|
|
|
471
486
|
}
|
|
472
487
|
|
|
473
488
|
listenToCurrentStoredProject() {
|
|
474
|
-
this.events.subscribe('storage:last_project', projectObjct => {
|
|
489
|
+
this.events.subscribe('storage:last_project', async(projectObjct) => {
|
|
475
490
|
if (projectObjct && projectObjct !== 'undefined') {
|
|
476
491
|
this.logger.log('[CONVS-LIST-PAGE] - GET STORED PROJECT ', projectObjct)
|
|
477
492
|
|
|
@@ -496,6 +511,10 @@ export class ConversationListPage implements OnInit {
|
|
|
496
511
|
} else if (this.project.profile.type === 'payment' && this.project.profile.name === 'enterprise') {
|
|
497
512
|
this.profile_name_translated = this.translationMapHeader.get('PaydPlanNameEnterprise');
|
|
498
513
|
}
|
|
514
|
+
|
|
515
|
+
this.projectUser = await this.projectUsersService.getProjectUserByProjectId(this.project._id)
|
|
516
|
+
this.rolesHeader = this.checkCannedResponsesRoles();
|
|
517
|
+
this.logger.log('[CONVS-LIST-PAGE] - GET PROJECT USER ROLES ', this.rolesHeader)
|
|
499
518
|
}
|
|
500
519
|
})
|
|
501
520
|
}
|
|
@@ -631,8 +650,24 @@ export class ConversationListPage implements OnInit {
|
|
|
631
650
|
const public_Key = this.appConfigProvider.getConfig().t2y12PruGU9wUtEGzBJfolMIgK
|
|
632
651
|
this.logger.log('[CONVS-LIST-PAGE] AppConfigService getAppConfig public_Key', public_Key)
|
|
633
652
|
this.isVisibleTKT = getOSCode("TKT", public_Key);
|
|
653
|
+
this.isVisibleCNT = getOSCode("CNT", public_Key);
|
|
634
654
|
}
|
|
635
655
|
|
|
656
|
+
checkCannedResponsesRoles(): { [key: string]: boolean } {
|
|
657
|
+
const permissionKeys = [
|
|
658
|
+
'LEADS_READ',
|
|
659
|
+
] as const;
|
|
660
|
+
|
|
661
|
+
const roles: { [key: string]: boolean } = {};
|
|
662
|
+
for (const key of permissionKeys) {
|
|
663
|
+
const permission = PERMISSIONS[key];
|
|
664
|
+
roles[permission] = hasRole(this.projectUser, permission);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
return roles;
|
|
668
|
+
|
|
669
|
+
}
|
|
670
|
+
|
|
636
671
|
onBackButtonFN(event) {
|
|
637
672
|
this.conversationType = 'active'
|
|
638
673
|
|
|
@@ -883,6 +918,10 @@ export class ConversationListPage implements OnInit {
|
|
|
883
918
|
|
|
884
919
|
this.logger.log('[CONVS-LIST-PAGE] navigateByUrl this.uidConvSelected ', this.uidConvSelected)
|
|
885
920
|
|
|
921
|
+
const queryParams = this.route.snapshot.queryParams;
|
|
922
|
+
const queryString = new URLSearchParams(queryParams).toString();
|
|
923
|
+
|
|
924
|
+
|
|
886
925
|
this.setUidConvSelected(uidConvSelected, converationType)
|
|
887
926
|
if (checkPlatformIsMobile()) {
|
|
888
927
|
this.logger.log('[CONVS-LIST-PAGE] checkPlatformIsMobile(): ', checkPlatformIsMobile())
|
|
@@ -900,6 +939,7 @@ export class ConversationListPage implements OnInit {
|
|
|
900
939
|
if (this.conversationSelected && this.conversationSelected.conversation_with_fullname) {
|
|
901
940
|
pageUrl = 'conversation-detail/' + this.uidConvSelected + '/' + encodeURIComponent(this.conversationSelected.conversation_with_fullname) + '/' + converationType
|
|
902
941
|
}
|
|
942
|
+
pageUrl += queryString ? `?${queryString}` : '';
|
|
903
943
|
this.logger.log('[CONVS-LIST-PAGE] setUidConvSelected navigateByUrl--->: ', pageUrl)
|
|
904
944
|
// replace(/\(/g, '%28').replace(/\)/g, '%29') -> used for the encoder of any round brackets
|
|
905
945
|
this.router.navigateByUrl(pageUrl.replace(/\(/g, '%28').replace(/\)/g, '%29'), {replaceUrl: true})
|
|
@@ -1,22 +1,34 @@
|
|
|
1
1
|
import { NgModule } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { HttpClient } from '@angular/common/http';
|
|
4
5
|
|
|
5
6
|
import { IonicModule } from '@ionic/angular';
|
|
7
|
+
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
|
8
|
+
import { createTranslateLoader } from 'src/chat21-core/utils/utils';
|
|
6
9
|
|
|
7
10
|
import { UnassignedConversationsPageRoutingModule } from './unassigned-conversations-routing.module';
|
|
8
11
|
|
|
9
12
|
import { UnassignedConversationsPage } from './unassigned-conversations.page';
|
|
13
|
+
import { ListConversationsModule } from 'src/app/chatlib/list-conversations-component/list-conversations.module';
|
|
14
|
+
import { MomentModule } from 'ngx-moment';
|
|
10
15
|
|
|
11
16
|
@NgModule({
|
|
12
17
|
imports: [
|
|
13
18
|
CommonModule,
|
|
14
19
|
FormsModule,
|
|
15
20
|
IonicModule,
|
|
16
|
-
UnassignedConversationsPageRoutingModule
|
|
21
|
+
UnassignedConversationsPageRoutingModule,
|
|
22
|
+
MomentModule,
|
|
23
|
+
ListConversationsModule,
|
|
24
|
+
TranslateModule.forChild({
|
|
25
|
+
loader: {
|
|
26
|
+
provide: TranslateLoader,
|
|
27
|
+
useFactory: createTranslateLoader,
|
|
28
|
+
deps: [HttpClient],
|
|
29
|
+
},
|
|
30
|
+
}),
|
|
17
31
|
],
|
|
18
|
-
declarations: [
|
|
19
|
-
UnassignedConversationsPage,
|
|
20
|
-
]
|
|
32
|
+
declarations: [UnassignedConversationsPage]
|
|
21
33
|
})
|
|
22
34
|
export class UnassignedConversationsPageModule {}
|
|
@@ -1,27 +1,51 @@
|
|
|
1
|
-
<ion-
|
|
2
|
-
<ion-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
</ion-
|
|
1
|
+
<ion-toolbar [class.mobile]="isMobile">
|
|
2
|
+
<ion-title *ngIf="callerBtn !== 'pinbtn'" style="font-size: 16px;">
|
|
3
|
+
{{translationMap?.get('UnassignedConversations') }}
|
|
4
|
+
</ion-title>
|
|
5
|
+
<ion-title *ngIf="callerBtn === 'pinbtn'" style="font-size: 16px;">
|
|
6
|
+
{{translationMap?.get('PIN_A_PROJECT') }}
|
|
7
|
+
</ion-title>
|
|
8
|
+
|
|
9
|
+
<ion-buttons slot="end">
|
|
10
|
+
<ion-button ion-button fill="clear" (click)="onClose()">
|
|
11
|
+
<ion-icon slot="icon-only" name="close"></ion-icon>
|
|
12
|
+
</ion-button>
|
|
13
|
+
</ion-buttons>
|
|
14
|
+
|
|
15
|
+
</ion-toolbar>
|
|
16
16
|
|
|
17
17
|
<ion-content overflow-scroll="true" id="iframe-ion-content"
|
|
18
18
|
[ngClass]="{'ion-content-black-background' : isProjectsForPanel === true}">
|
|
19
|
-
|
|
20
|
-
<div class="loader-spinner-wpr">
|
|
19
|
+
<div *ngIf="callerBtn === 'pinbtn'" class="loader-spinner-wpr">
|
|
21
20
|
<div id="loader" class="loader">
|
|
22
21
|
<svg class="circular" viewBox="25 25 50 50">
|
|
23
22
|
<circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10" />
|
|
24
23
|
</svg>
|
|
25
24
|
</div>
|
|
26
25
|
</div>
|
|
26
|
+
|
|
27
|
+
<div *ngIf="callerBtn !== 'pinbtn'" class="list-avatar-page">
|
|
28
|
+
<ion-list>
|
|
29
|
+
<ng-container *ngIf="unassignedConversationsList.length > 0; else noConvs">
|
|
30
|
+
<ion-list-conversations
|
|
31
|
+
[listConversations]="unassignedConversationsList"
|
|
32
|
+
[stylesMap]="stylesMap"
|
|
33
|
+
[translationMap]="translationMapConversation"
|
|
34
|
+
[uidConvSelected]="uidConvSelected"
|
|
35
|
+
(onConversationSelected)="onConversationSelected($event)"
|
|
36
|
+
(onCloseConversation)="onCloseConversation($event)"
|
|
37
|
+
(onJoinConversation)="onJoinConversation($event)"
|
|
38
|
+
(onImageLoaded)="onImageLoaded($event)"
|
|
39
|
+
(onConversationLoaded)="onConversationLoaded($event)">
|
|
40
|
+
</ion-list-conversations>
|
|
41
|
+
</ng-container>
|
|
42
|
+
<ng-template #noConvs>
|
|
43
|
+
<ion-item id="no-convs" class="ion-text-center" lines="none">
|
|
44
|
+
<ion-label class="ion-text-wrap" color="medium">
|
|
45
|
+
{{ 'LABEL_MSG_PUSH_START_CHAT' | translate }}
|
|
46
|
+
</ion-label>
|
|
47
|
+
</ion-item>
|
|
48
|
+
</ng-template>
|
|
49
|
+
</ion-list>
|
|
50
|
+
</div>
|
|
27
51
|
</ion-content>
|
|
@@ -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(--
|
|
24
|
+
--background: var(--bacis-white);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -224,3 +225,11 @@ 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
|
+
}
|