@chat21/chat21-ionic 3.4.27 → 3.4.28-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 +110 -4
- 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 -10
- 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 +29 -7
- 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 +70 -52
- 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 +89 -5
- 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/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 +25 -0
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
- package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
- package/src/chat21-core/utils/utils.ts +16 -2
|
@@ -15,7 +15,10 @@ import { tranlatedLanguage } from '../../../chat21-core/utils/constants';
|
|
|
15
15
|
// utils
|
|
16
16
|
import { avatarPlaceholder, getColorBck } from 'src/chat21-core/utils/utils-user';
|
|
17
17
|
import { BRAND_BASE_INFO, LOGOS_ITEMS } from 'src/app/utils/utils-resources';
|
|
18
|
-
import { getOSCode } from 'src/app/utils/utils';
|
|
18
|
+
import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
19
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
20
|
+
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
21
|
+
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
19
22
|
|
|
20
23
|
@Component({
|
|
21
24
|
selector: 'app-sidebar',
|
|
@@ -31,7 +34,7 @@ export class SidebarComponent implements OnInit {
|
|
|
31
34
|
IS_AVAILABLE: boolean = false;
|
|
32
35
|
IS_INACTIVE: boolean = true;
|
|
33
36
|
IS_BUSY: boolean;
|
|
34
|
-
isVisibleAPP: boolean;
|
|
37
|
+
// isVisibleAPP: boolean;
|
|
35
38
|
isVisibleANA: boolean;
|
|
36
39
|
isVisibleACT: boolean;
|
|
37
40
|
isVisibleMON: boolean;
|
|
@@ -41,9 +44,10 @@ export class SidebarComponent implements OnInit {
|
|
|
41
44
|
project_id: string;
|
|
42
45
|
DASHBOARD_URL: string;
|
|
43
46
|
// HAS_CLICKED_OPEN_USER_DETAIL: boolean = false
|
|
44
|
-
public
|
|
47
|
+
public translationsMap: Map<string, string>;
|
|
45
48
|
public_Key: any;
|
|
46
49
|
conversations_lbl: string;
|
|
50
|
+
whatsappbroadcast_lbl: string;
|
|
47
51
|
contacts_lbl: string;
|
|
48
52
|
apps_lbl: string;
|
|
49
53
|
analytics_lbl: string;
|
|
@@ -53,19 +57,14 @@ export class SidebarComponent implements OnInit {
|
|
|
53
57
|
countClickOnOpenUserDetailSidebar: number = 0
|
|
54
58
|
USER_PHOTO_PROFILE_EXIST: boolean;
|
|
55
59
|
currentUser: any;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
dashboard_app_url: string;
|
|
62
|
-
dashboard_analytics_url: string;
|
|
63
|
-
dashboard_activities_url: string;
|
|
64
|
-
dashboard_history_url: string;
|
|
65
|
-
dashboard_settings_url: string;
|
|
66
|
-
tiledesk_url: string;
|
|
60
|
+
URLS: { [key: string]: string} = {};
|
|
61
|
+
|
|
62
|
+
public projectUser: ProjectUser;
|
|
63
|
+
public roles: { [key: string]: boolean }
|
|
64
|
+
|
|
67
65
|
LOGOS_ITEMS = LOGOS_ITEMS;
|
|
68
66
|
BRAND_BASE_INFO = BRAND_BASE_INFO;
|
|
67
|
+
PERMISSIONS = PERMISSIONS;
|
|
69
68
|
constructor(
|
|
70
69
|
public imageRepoService: ImageRepoService,
|
|
71
70
|
public appStorageService: AppStorageService,
|
|
@@ -75,12 +74,13 @@ export class SidebarComponent implements OnInit {
|
|
|
75
74
|
public wsService: WebsocketService,
|
|
76
75
|
public appConfigProvider: AppConfigProvider,
|
|
77
76
|
private translate: TranslateService,
|
|
77
|
+
public projectUsersService: ProjectUsersService,
|
|
78
78
|
public events: EventsService,
|
|
79
79
|
|
|
80
80
|
) { }
|
|
81
81
|
|
|
82
82
|
ngOnInit() {
|
|
83
|
-
this.
|
|
83
|
+
this.URLS.TILEDESK = BRAND_BASE_INFO['COMPANY_SITE_URL'] as string
|
|
84
84
|
|
|
85
85
|
this.DASHBOARD_URL = this.appConfig.getConfig().dashboardUrl + '#/project/';
|
|
86
86
|
this.getStoredProjectAndUserRole()
|
|
@@ -92,36 +92,57 @@ export class SidebarComponent implements OnInit {
|
|
|
92
92
|
|
|
93
93
|
|
|
94
94
|
getStoredProjectAndUserRole() {
|
|
95
|
-
this.events.subscribe('storage:last_project',project =>{
|
|
95
|
+
this.events.subscribe('storage:last_project',async (project) =>{
|
|
96
96
|
this.logger.log('[SIDEBAR] stored_project ', project)
|
|
97
97
|
if (project && project !== 'undefined') {
|
|
98
98
|
this.project_id = project.id_project.id
|
|
99
99
|
this.USER_ROLE = project.role;
|
|
100
100
|
this.buildURLs(this.USER_ROLE)
|
|
101
|
+
this.projectUser = await this.projectUsersService.getProjectUserByProjectId(project.id_project.id)
|
|
102
|
+
this.roles = this.checkRoles()
|
|
103
|
+
this.logger.log('[SIDEBAR] roles ', this.roles)
|
|
101
104
|
}
|
|
102
105
|
})
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
buildURLs(USER_ROLE) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
this.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
const base = this.DASHBOARD_URL + this.project_id;
|
|
110
|
+
|
|
111
|
+
this.URLS = {
|
|
112
|
+
HOME: `${base}/home`,
|
|
113
|
+
KNOWLEDGEBASE: `${base}/knowledge-bases`,
|
|
114
|
+
BOTS: `${base}/bots`,
|
|
115
|
+
MONITOR: `${base}/wsrequests`,
|
|
116
|
+
WHATSAPP: `${base}/automations`,
|
|
117
|
+
CONTACTS: `${base}/contacts`,
|
|
118
|
+
APPSTORE: `${base}/app-store`,
|
|
119
|
+
ANALYTICS: `${base}/analytics`,
|
|
120
|
+
ACTIVITIES: `${base}/activities`,
|
|
121
|
+
HISTORY: `${base}/history`,
|
|
122
|
+
SETTINGS: USER_ROLE !== 'agent' ? `${base}/widget-set-up` : `${base}/cannedresponses`,
|
|
123
|
+
TILEDESK: 'https://www.tiledesk.com'
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
this.setQueryParamsForAll({ tiledesk_logOut: BRAND_BASE_INFO['LOGOUT_ENABLED'] });
|
|
122
127
|
|
|
123
128
|
}
|
|
124
129
|
|
|
130
|
+
// Funzione helper per aggiungere query params a tutte le URL
|
|
131
|
+
setQueryParamsForAll(queryParams: any) {
|
|
132
|
+
if (!queryParams) return;
|
|
133
|
+
|
|
134
|
+
const queryString = new URLSearchParams(queryParams).toString();
|
|
135
|
+
|
|
136
|
+
// Cicla tutte le chiavi di URLS
|
|
137
|
+
Object.keys(this.URLS).forEach(key => {
|
|
138
|
+
if (this.URLS[key]) {
|
|
139
|
+
// Controlla se già ci sono query params
|
|
140
|
+
const separator = this.URLS[key].includes('?') ? '&' : '?';
|
|
141
|
+
this.URLS[key] = `${this.URLS[key]}${queryString ? separator + queryString : ''}`;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
125
146
|
subcribeToAuthStateChanged() {
|
|
126
147
|
this.messagingAuthService.BSAuthStateChanged.subscribe((state) => {
|
|
127
148
|
this.logger.log('[SIDEBAR] BSAuthStateChanged ', state)
|
|
@@ -240,6 +261,7 @@ export class SidebarComponent implements OnInit {
|
|
|
240
261
|
this.logger.error('[SIDEBAR] - ngOnInit - currentUser not found in storage ')
|
|
241
262
|
}
|
|
242
263
|
this.translateLabels()
|
|
264
|
+
this.translations()
|
|
243
265
|
}
|
|
244
266
|
|
|
245
267
|
|
|
@@ -256,6 +278,7 @@ export class SidebarComponent implements OnInit {
|
|
|
256
278
|
|
|
257
279
|
this.translate.get(keys).subscribe((text: string) => {
|
|
258
280
|
this.conversations_lbl = text['Conversations'];
|
|
281
|
+
this.whatsappbroadcast_lbl = text['WhatsAppBroadcasts']
|
|
259
282
|
this.contacts_lbl = text['LABEL_CONTACTS']
|
|
260
283
|
this.apps_lbl = text['Apps']
|
|
261
284
|
this.analytics_lbl = text['Analytics']
|
|
@@ -271,13 +294,55 @@ export class SidebarComponent implements OnInit {
|
|
|
271
294
|
|
|
272
295
|
this.isVisibleANA = getOSCode("ANA", this.public_Key);
|
|
273
296
|
this.isVisibleACT = getOSCode("ACT", this.public_Key);
|
|
274
|
-
this.isVisibleAPP = getOSCode("APP", this.public_Key);
|
|
275
297
|
this.isVisibleMON = getOSCode("MON", this.public_Key);
|
|
276
298
|
this.isVisibleCNT = getOSCode("CNT", this.public_Key);
|
|
277
299
|
this.isVisibleKNB = getOSCode("KNB", this.public_Key);
|
|
278
|
-
|
|
300
|
+
|
|
279
301
|
}
|
|
280
302
|
|
|
303
|
+
|
|
304
|
+
checkRoles(): { [key: string]: boolean } {
|
|
305
|
+
const permissionKeys = [
|
|
306
|
+
'HOME_READ',
|
|
307
|
+
'KB_READ',
|
|
308
|
+
'FLOWS_READ',
|
|
309
|
+
'INBOX_READ',
|
|
310
|
+
'AUTOMATIONSLOG_READ',
|
|
311
|
+
'LEADS_READ',
|
|
312
|
+
'ANALYTICS_READ',
|
|
313
|
+
'ACTIVITIES_READ',
|
|
314
|
+
'HISTORY_READ',
|
|
315
|
+
'PROJECTSETTINGS_GENERAL_READ',
|
|
316
|
+
'PROJECTSETTINGS_DEVELOPER_READ',
|
|
317
|
+
'PROJECTSETTINGS_SMARTASSIGNMENT_READ',
|
|
318
|
+
'PROJECTSETTINGS_NOTIFICATION_READ',
|
|
319
|
+
'PROJECTSETTINGS_SECURITY_READ',
|
|
320
|
+
'PROJECTSETTINGS_BANNED_READ',
|
|
321
|
+
'PROJECTSETTINGS_ADVANCED_READ'
|
|
322
|
+
] as const;
|
|
323
|
+
|
|
324
|
+
const roles: { [key: string]: boolean } = {};
|
|
325
|
+
for (const key of permissionKeys) {
|
|
326
|
+
const permission = PERMISSIONS[key];
|
|
327
|
+
roles[permission] = hasRole(this.projectUser, permission);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
let settingRoleKEys = [
|
|
332
|
+
'PROJECTSETTINGS_GENERAL_READ',
|
|
333
|
+
'PROJECTSETTINGS_DEVELOPER_READ',
|
|
334
|
+
'PROJECTSETTINGS_SMARTASSIGNMENT_READ',
|
|
335
|
+
'PROJECTSETTINGS_NOTIFICATION_READ',
|
|
336
|
+
'PROJECTSETTINGS_SECURITY_READ',
|
|
337
|
+
'PROJECTSETTINGS_BANNED_READ',
|
|
338
|
+
'PROJECTSETTINGS_ADVANCED_READ'
|
|
339
|
+
] as const;
|
|
340
|
+
roles[PERMISSIONS.SETTINGS_READ] = settingRoleKEys.some(settingKey => roles[PERMISSIONS[settingKey]]);
|
|
341
|
+
|
|
342
|
+
return roles;
|
|
343
|
+
|
|
344
|
+
}
|
|
345
|
+
|
|
281
346
|
listenTocurrentProjectUserUserAvailability$() {
|
|
282
347
|
this.wsService.currentProjectUserAvailability$.subscribe((data) => {
|
|
283
348
|
this.logger.log('[SIDEBAR] - $UBSC TO WS USER AVAILABILITY & BUSY STATUS RES ', data);
|
|
@@ -327,92 +392,20 @@ export class SidebarComponent implements OnInit {
|
|
|
327
392
|
}
|
|
328
393
|
}
|
|
329
394
|
|
|
330
|
-
goToHome() {
|
|
331
|
-
let url = this.DASHBOARD_URL + this.project_id + '/home'
|
|
332
|
-
this.dashboard_home_url = url;
|
|
333
|
-
const myWindow = window.open(url, '_self');
|
|
334
|
-
myWindow.focus();
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
goToBots() {
|
|
338
|
-
let url = this.DASHBOARD_URL + this.project_id + '/bots/my-chatbots/all'
|
|
339
|
-
const myWindow = window.open(url, '_self');
|
|
340
|
-
myWindow.focus();
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
goToConversations() {
|
|
344
|
-
let url = this.DASHBOARD_URL + this.project_id + '/wsrequests'
|
|
345
|
-
const myWindow = window.open(url, '_self');
|
|
346
|
-
myWindow.focus();
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
goToContacts() {
|
|
350
|
-
let url = this.DASHBOARD_URL + this.project_id + '/contacts'
|
|
351
|
-
const myWindow = window.open(url, '_self');
|
|
352
|
-
myWindow.focus();
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
goToAppStore() {
|
|
356
|
-
let url = this.DASHBOARD_URL + this.project_id + '/app-store'
|
|
357
|
-
const myWindow = window.open(url, '_self');
|
|
358
|
-
myWindow.focus();
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
goToAnalytics() {
|
|
362
|
-
let url = this.DASHBOARD_URL + this.project_id + '/analytics'
|
|
363
|
-
const myWindow = window.open(url, '_self');
|
|
364
|
-
myWindow.focus();
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
goToActivities() {
|
|
368
|
-
let url = this.DASHBOARD_URL + this.project_id + '/activities'
|
|
369
|
-
const myWindow = window.open(url, '_self');
|
|
370
|
-
myWindow.focus();
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
goToHistory() {
|
|
374
|
-
let url = this.DASHBOARD_URL + this.project_id + '/history'
|
|
375
|
-
const myWindow = window.open(url, '_self');
|
|
376
|
-
myWindow.focus();
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
goToWidgetSetUpOrToCannedResponses() {
|
|
380
|
-
if (this.USER_ROLE !== 'agent') {
|
|
381
|
-
this.goToWidgetSetUp()
|
|
382
|
-
} else if (this.USER_ROLE === 'agent') {
|
|
383
|
-
this.goToSettings_CannedResponses()
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
goToWidgetSetUp() {
|
|
388
|
-
let url = this.DASHBOARD_URL + this.project_id + '/widget-set-up'
|
|
389
|
-
const myWindow = window.open(url, '_self');
|
|
390
|
-
myWindow.focus();
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
goToSettings_CannedResponses() {
|
|
394
|
-
let url = this.DASHBOARD_URL + this.project_id + '/cannedresponses'
|
|
395
|
-
const myWindow = window.open(url, '_self');
|
|
396
|
-
myWindow.focus();
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
395
|
public translations() {
|
|
402
396
|
const keys = [
|
|
403
|
-
'
|
|
404
|
-
'
|
|
405
|
-
'
|
|
406
|
-
'
|
|
407
|
-
'
|
|
408
|
-
'
|
|
409
|
-
'
|
|
410
|
-
'
|
|
411
|
-
'
|
|
412
|
-
|
|
413
|
-
"CHANGE_TO_YOUR_STATUS_TO_UNAVAILABLE"
|
|
397
|
+
'Monitor',
|
|
398
|
+
'Flows',
|
|
399
|
+
'Knowledgebases',
|
|
400
|
+
'WhatsAppBroadcasts',
|
|
401
|
+
'LABEL_CONTACTS',
|
|
402
|
+
'Apps',
|
|
403
|
+
'Analytics',
|
|
404
|
+
'Activities',
|
|
405
|
+
'History',
|
|
406
|
+
'Settings'
|
|
414
407
|
];
|
|
415
|
-
this.
|
|
408
|
+
this.translationsMap = this.translateService.translateLanguage(keys);
|
|
416
409
|
}
|
|
417
410
|
|
|
418
411
|
|
|
@@ -81,11 +81,11 @@
|
|
|
81
81
|
[searchable]="false">
|
|
82
82
|
<ng-template ng-label-tmp let-item="item">
|
|
83
83
|
<img style="width: 15px;height: 15px;position: relative; top: 1px;" height="15" width="15" [src]="item?.avatar" />
|
|
84
|
-
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label}} </span>
|
|
84
|
+
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label | translate}} </span>
|
|
85
85
|
</ng-template>
|
|
86
86
|
<ng-template ng-option-tmp let-item="item" let-index="index">
|
|
87
87
|
<img style="width: 15px;height: 15px;position: relative; top: 1px;" height="15" width="15" [src]="item?.avatar" />
|
|
88
|
-
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label}} </span>
|
|
88
|
+
<span id="sidebaravatar_{{item.name}}" style="text-transform: capitalize; margin-left:8px"> {{item.label | translate}} </span>
|
|
89
89
|
</ng-template>
|
|
90
90
|
</ng-select>
|
|
91
91
|
</section>
|
|
@@ -25,6 +25,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
25
25
|
// HAS_CLICKED_OPEN_USER_DETAIL: boolean = false;
|
|
26
26
|
// @Output() onCloseUserDetailsSidebar = new EventEmitter();
|
|
27
27
|
|
|
28
|
+
@Input() logOut: boolean;
|
|
28
29
|
|
|
29
30
|
public browserLang: string;
|
|
30
31
|
private logger: LoggerService = LoggerInstance.getInstance()
|
|
@@ -242,9 +243,9 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
242
243
|
.set('SubscriptionPaymentProblem', text['SubscriptionPaymentProblem'])
|
|
243
244
|
.set('ThePlanHasExpired', text['ThePlanHasExpired'])
|
|
244
245
|
|
|
245
|
-
this.teammateStatus.forEach(element => {
|
|
246
|
-
|
|
247
|
-
});
|
|
246
|
+
// this.teammateStatus.forEach(element => {
|
|
247
|
+
// element.label = this.translationsMap.get(element.label)
|
|
248
|
+
// });
|
|
248
249
|
|
|
249
250
|
});
|
|
250
251
|
}
|
|
@@ -261,7 +262,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
261
262
|
listenToCurrentStoredProject() {
|
|
262
263
|
this.events.subscribe('storage:last_project', projectObjct => {
|
|
263
264
|
if (projectObjct && projectObjct !== 'undefined') {
|
|
264
|
-
|
|
265
|
+
this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED PROJECT ', projectObjct)
|
|
265
266
|
|
|
266
267
|
//TODO: recuperare info da root e non da id_project
|
|
267
268
|
this.project = {
|
|
@@ -284,6 +285,8 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
284
285
|
} else if (this.project.profile.type === 'payment' && this.project.profile.name === 'enterprise') {
|
|
285
286
|
this.getEnterprisePlanTranslation();
|
|
286
287
|
}
|
|
288
|
+
|
|
289
|
+
this.wsService.subscriptionToWsCurrentProjectUserAvailability(this.project._id, projectObjct._id);
|
|
287
290
|
}
|
|
288
291
|
})
|
|
289
292
|
|
|
@@ -329,14 +332,14 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
329
332
|
// this.logger.log('teammateStatus ', this.teammateStatus)
|
|
330
333
|
this.selectedStatus = this.teammateStatus[2].id;
|
|
331
334
|
this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[2].name);
|
|
332
|
-
this.teammateStatus = this.teammateStatus.slice(0)
|
|
335
|
+
// this.teammateStatus = this.teammateStatus.slice(0)
|
|
333
336
|
} else if (projectUser['user_available'] === false && (projectUser['profileStatus'] === '' || !projectUser['profileStatus'])) {
|
|
334
337
|
this.selectedStatus = this.teammateStatus[1].id;
|
|
335
338
|
this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[1].name);
|
|
336
|
-
this.teammateStatus = this.teammateStatus.slice(0)
|
|
339
|
+
// this.teammateStatus = this.teammateStatus.slice(0)
|
|
337
340
|
} else if (projectUser['user_available'] === true && (projectUser['profileStatus'] === '' || !projectUser['profileStatus'])) {
|
|
338
341
|
this.selectedStatus = this.teammateStatus[0].id
|
|
339
|
-
this.teammateStatus = this.teammateStatus.slice(0)
|
|
342
|
+
// this.teammateStatus = this.teammateStatus.slice(0)
|
|
340
343
|
this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[0].name);
|
|
341
344
|
}
|
|
342
345
|
this.IS_BUSY = projectUser['isBusy']
|
|
@@ -9,6 +9,7 @@ import * as uuid from 'uuid';
|
|
|
9
9
|
import { EventsService } from 'src/app/services/events-service'
|
|
10
10
|
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
11
11
|
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
12
|
+
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service'
|
|
12
13
|
|
|
13
14
|
@Component({
|
|
14
15
|
selector: 'app-create-ticket',
|
|
@@ -64,6 +65,7 @@ export class CreateTicketPage implements OnInit {
|
|
|
64
65
|
logger: LoggerService = LoggerInstance.getInstance();
|
|
65
66
|
constructor(
|
|
66
67
|
public modalController: ModalController,
|
|
68
|
+
public projectUsersService: ProjectUsersService,
|
|
67
69
|
public tiledeskService: TiledeskService,
|
|
68
70
|
public appConfigProvider: AppConfigProvider,
|
|
69
71
|
public events: EventsService
|
|
@@ -104,7 +106,7 @@ export class CreateTicketPage implements OnInit {
|
|
|
104
106
|
// Create the array of the project-users and contacts displayed in the combo box "Requester"
|
|
105
107
|
// -------------------------------------------------------------------------------------------
|
|
106
108
|
getProjectUsersAndContacts(projctid: string) {
|
|
107
|
-
const projectUsers = this.
|
|
109
|
+
const projectUsers = this.projectUsersService.getProjectUsersByProjectId(projctid)
|
|
108
110
|
const leads = this.tiledeskService.getAllLeadsActiveWithLimit(projctid,10000)
|
|
109
111
|
|
|
110
112
|
zip(projectUsers, leads).subscribe(
|
|
@@ -243,7 +245,7 @@ export class CreateTicketPage implements OnInit {
|
|
|
243
245
|
// -------------------------------------------------------------------------------------------------------------------
|
|
244
246
|
getProjectUserBotsAndDepts(projctid: string) {
|
|
245
247
|
// this.loadingAssignee = true;
|
|
246
|
-
const projectUsers = this.
|
|
248
|
+
const projectUsers = this.projectUsersService.getProjectUsersByProjectId( projctid)
|
|
247
249
|
const bots = this.tiledeskService.getAllBotByProjectId(projctid)
|
|
248
250
|
const depts = this.tiledeskService.getDeptsByProjectId(projctid)
|
|
249
251
|
|
|
@@ -173,7 +173,7 @@
|
|
|
173
173
|
<!-- ----------------------------------------------------------- -->
|
|
174
174
|
<app-canned-response *ngIf="SHOW_CANNED_RESPONSES"
|
|
175
175
|
id="canned"
|
|
176
|
-
[
|
|
176
|
+
[roles]="rolesCanned"
|
|
177
177
|
[conversationWith]="conversationWith"
|
|
178
178
|
[conversationWithFullname]="conversationWithFullname"
|
|
179
179
|
[currentString]="messageStr"
|
|
@@ -201,7 +201,8 @@
|
|
|
201
201
|
<!-- [tagsCannedFilter]="tagsCannedFilter" -->
|
|
202
202
|
<!-- openInfoConversation {{openInfoConversation}} - isMobile {{isMobile}} -->
|
|
203
203
|
<app-message-text-area *ngIf="(openInfoConversation === false && isMobile === true) || (openInfoConversation === true && isMobile === false) || (openInfoConversation === false && isMobile === false)"
|
|
204
|
-
[loggedUser]="loggedUser"
|
|
204
|
+
[loggedUser]="loggedUser"
|
|
205
|
+
[projectUser]="projectUser"
|
|
205
206
|
[conversationWith]="conversationWith"
|
|
206
207
|
[channelType]="channelType"
|
|
207
208
|
[channel]="conversation?.attributes?.request_channel"
|
|
@@ -213,8 +214,10 @@
|
|
|
213
214
|
[fileUploadAccept]="fileUploadAccept"
|
|
214
215
|
[emailSection]="isEmailEnabled"
|
|
215
216
|
[offlineMsgEmail]="offlineMsgEmail"
|
|
217
|
+
[cannedSection]="canShowCanned"
|
|
216
218
|
[whatsappTemplatesSection]="isWhatsappTemplatesEnabled"
|
|
217
219
|
[isOpenInfoConversation]="openInfoConversation"
|
|
220
|
+
[ticketSection]="isTicketEnabled"
|
|
218
221
|
[stylesMap]="styleMap"
|
|
219
222
|
[translationMap]="translationsMap"
|
|
220
223
|
[dropEvent]="dropEvent"
|
|
@@ -223,7 +226,8 @@
|
|
|
223
226
|
(onClickOpenCannedResponses)="onClickOpenCannedResponses($event)"
|
|
224
227
|
(eventSendMessage)="returnSendMessage($event)"
|
|
225
228
|
(onPresentModalScrollToBottom)="onPresentModalScrollToBottom($event)"
|
|
226
|
-
(onOpenFooterSection)="onOpenFooterSection($event)"
|
|
229
|
+
(onOpenFooterSection)="onOpenFooterSection($event)"
|
|
230
|
+
(onOpenTicket)="onOpenTicket($event)">
|
|
227
231
|
</app-message-text-area>
|
|
228
232
|
<!-- [events]="eventsReplaceTexareaText.asObservable()" -->
|
|
229
233
|
</ion-row>
|
|
@@ -83,7 +83,11 @@ 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 { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
87
|
+
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
88
|
+
import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
89
|
+
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
90
|
+
import { TriggerEvents } from 'src/app/services/triggerEvents/triggerEvents';
|
|
87
91
|
|
|
88
92
|
@Component({
|
|
89
93
|
selector: 'app-conversation-detail',
|
|
@@ -108,6 +112,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
108
112
|
private subscriptions: Array<any>
|
|
109
113
|
public tenant: string;
|
|
110
114
|
public loggedUser: UserModel
|
|
115
|
+
public projectUser: ProjectUser;
|
|
111
116
|
public conversationWith: string
|
|
112
117
|
public conversationWithFullname: string
|
|
113
118
|
public messages: Array<MessageModel> = []
|
|
@@ -137,6 +142,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
137
142
|
public tagsCannedFilter: Array<any> = [];
|
|
138
143
|
public SHOW_CANNED_RESPONSES: boolean = false
|
|
139
144
|
public canShowCanned: boolean = true
|
|
145
|
+
public rolesCanned: { [key: string]: boolean }
|
|
140
146
|
|
|
141
147
|
public SHOW_COPILOT_SUGGESTIONS: boolean = false;
|
|
142
148
|
|
|
@@ -171,6 +177,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
171
177
|
copilotQuestion: string = '';
|
|
172
178
|
/**COPILOT : end */
|
|
173
179
|
|
|
180
|
+
/** TICKET: start */
|
|
181
|
+
isTicketEnabled: boolean = false;
|
|
182
|
+
/** TICKET: end */
|
|
183
|
+
|
|
174
184
|
isMine = isMine
|
|
175
185
|
isInfo = isInfo
|
|
176
186
|
isFirstMessage = isFirstMessage
|
|
@@ -240,18 +250,20 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
240
250
|
public toastController: ToastController,
|
|
241
251
|
public tiledeskService: TiledeskService,
|
|
242
252
|
public projectService: ProjectService,
|
|
253
|
+
public projectUsersService: ProjectUsersService,
|
|
243
254
|
private networkService: NetworkService,
|
|
244
255
|
private events: EventsService,
|
|
245
256
|
private webSocketService: WebsocketService,
|
|
246
257
|
public projectPlanUtils: ProjectPlanUtils,
|
|
258
|
+
public triggerEvents: TriggerEvents,
|
|
247
259
|
private g: Globals,
|
|
248
260
|
) {
|
|
249
261
|
// Change list on date change
|
|
250
262
|
this.route.paramMap.subscribe((params) => {
|
|
251
263
|
this.logger.log('[CONVS-DETAIL] - constructor -> params: ', params)
|
|
252
264
|
this.conversationWith = params.get('IDConv')
|
|
253
|
-
this.conversationWithFullname = params.get('FullNameConv')
|
|
254
|
-
this.conv_type = params.get('Convtype')
|
|
265
|
+
this.conversationWithFullname = decodeURIComponent(params.get('FullNameConv'))
|
|
266
|
+
this.conv_type = decodeURIComponent(params.get('Convtype'))
|
|
255
267
|
|
|
256
268
|
this.events.publish('supportconvid:haschanged', this.conversationWith)
|
|
257
269
|
})
|
|
@@ -418,6 +430,8 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
418
430
|
ionViewDidEnter() {
|
|
419
431
|
this.logger.log('[CONVS-DETAIL] > ionViewDidEnter')
|
|
420
432
|
// this.info_content_child_enabled = true;
|
|
433
|
+
// Scroll to bottom to show the last message without animation
|
|
434
|
+
this.scrollToLastMessage()
|
|
421
435
|
}
|
|
422
436
|
|
|
423
437
|
// Unsubscibe when new page transition end
|
|
@@ -477,6 +491,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
477
491
|
this.messages = [] // list messages of conversation
|
|
478
492
|
this.isFileSelected = false // indicates if a file has been selected (image to upload)
|
|
479
493
|
this.isEmailEnabled = (this.appConfigProvider.getConfig().emailSection === 'true' || this.appConfigProvider.getConfig().emailSection === true) ? true : false;
|
|
494
|
+
this.isTicketEnabled = (this.appConfigProvider.getConfig().ticketSection === 'true' || this.appConfigProvider.getConfig().ticketSection === true) ? true : false;
|
|
480
495
|
this.isWhatsappTemplatesEnabled = (this.appConfigProvider.getConfig().whatsappTemplatesSection === 'true' || this.appConfigProvider.getConfig().whatsappTemplatesSection === true) ? true : false;
|
|
481
496
|
|
|
482
497
|
this.cannedResponsesService.initialize(appconfig.apiUrl)
|
|
@@ -534,7 +549,6 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
534
549
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT * COMPLETE *',)
|
|
535
550
|
})
|
|
536
551
|
}else {
|
|
537
|
-
this.canShowCanned = false;
|
|
538
552
|
this.offlineMsgEmail = false;
|
|
539
553
|
}
|
|
540
554
|
|
|
@@ -545,10 +559,13 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
545
559
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT RES', project)
|
|
546
560
|
if (project) {
|
|
547
561
|
const projectId = project.id_project
|
|
548
|
-
this.
|
|
562
|
+
this.projectUser = await this.projectUsersService.getProjectUserByProjectId(project._id)
|
|
549
563
|
this.offlineMsgEmail = this.checkOfflineMsgEmailIsEnabled(project)
|
|
550
564
|
this.isCopilotEnabled = this.projectPlanUtils.checkProjectProfileFeature(project, 'copilot');
|
|
551
565
|
this.fileUploadAccept = this.checkAcceptedUploadFile(project)
|
|
566
|
+
this.rolesCanned = this.checkCannedResponsesRoles()
|
|
567
|
+
this.canShowCanned = this.checkCannedResponses(project)
|
|
568
|
+
this.logger.log('[CONVS-DETAIL] this.rolesCanned ', this.canShowCanned)
|
|
552
569
|
}
|
|
553
570
|
}, (error) => {
|
|
554
571
|
this.logger.error('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT - ERROR ', error)
|
|
@@ -586,6 +603,40 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
586
603
|
return this.appConfigProvider.getConfig().fileUploadAccept
|
|
587
604
|
}
|
|
588
605
|
|
|
606
|
+
checkCannedResponses(project: Project): boolean {
|
|
607
|
+
let expires = this.projectPlanUtils.checkPlanIsExpired(project)
|
|
608
|
+
this.logger.log('[CONVS-DETAIL] checkCannedResponses expires ', expires)
|
|
609
|
+
if(expires){
|
|
610
|
+
return false
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
let hasRoleToShowCanned = this.rolesCanned[PERMISSIONS.CANNED_RESPONSES_READ]
|
|
614
|
+
this.logger.log('[CONVS-DETAIL] checkCannedResponses hasRoleToShowCanned ', hasRoleToShowCanned)
|
|
615
|
+
if(!hasRoleToShowCanned){
|
|
616
|
+
return false
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return true
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
checkCannedResponsesRoles(): { [key: string]: boolean } {
|
|
623
|
+
const permissionKeys = [
|
|
624
|
+
'CANNED_RESPONSES_CREATE',
|
|
625
|
+
'CANNED_RESPONSES_READ',
|
|
626
|
+
'CANNED_RESPONSES_UPDATE',
|
|
627
|
+
'CANNED_RESPONSES_DELETE',
|
|
628
|
+
] as const;
|
|
629
|
+
|
|
630
|
+
const roles: { [key: string]: boolean } = {};
|
|
631
|
+
for (const key of permissionKeys) {
|
|
632
|
+
const permission = PERMISSIONS[key];
|
|
633
|
+
roles[permission] = hasRole(this.projectUser, permission);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return roles;
|
|
637
|
+
|
|
638
|
+
}
|
|
639
|
+
|
|
589
640
|
// getProjectIdSelectedConversation(conversationWith: string): string{
|
|
590
641
|
// const conversationWith_segments = conversationWith.split('-')
|
|
591
642
|
// // Removes the last element of the array if is = to the separator
|
|
@@ -669,6 +720,11 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
669
720
|
"WHATSAPP.ERROR_WHATSAPP_NOT_INSTALLED",
|
|
670
721
|
"WHATSAPP.ERROR_WHATSAPP_GENERIC_ERROR",
|
|
671
722
|
|
|
723
|
+
"TICKET.OPEN_TICKET",
|
|
724
|
+
"TICKET.DESCRIPTION",
|
|
725
|
+
"TICKET.CONFIRM",
|
|
726
|
+
"TICKET.CLOSE",
|
|
727
|
+
|
|
672
728
|
"COPILOT.ASK_AI",
|
|
673
729
|
"COPILOT.NO_SUGGESTIONS_PRESENT",
|
|
674
730
|
|
|
@@ -1884,6 +1940,11 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1884
1940
|
}
|
|
1885
1941
|
|
|
1886
1942
|
|
|
1943
|
+
onOpenTicket(event) {
|
|
1944
|
+
this.logger.debug('[CONVS-DETAIL] openTicketOnExternalService - conversationWith ', this.conversationWith)
|
|
1945
|
+
const detailOBJ = { event: 'onOpenTicketExternally', request_id: this.conversationWith, conversation: this.conversation }
|
|
1946
|
+
this.triggerEvents.triggerOnOpenTicketExternally(detailOBJ)
|
|
1947
|
+
}
|
|
1887
1948
|
// -------------- START SCROLL/RESIZE -------------- //
|
|
1888
1949
|
/** */
|
|
1889
1950
|
resizeTextArea() {
|
|
@@ -1927,6 +1988,29 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
1927
1988
|
}
|
|
1928
1989
|
}
|
|
1929
1990
|
|
|
1991
|
+
/**
|
|
1992
|
+
* Scroll to last message without animation using requestAnimationFrame
|
|
1993
|
+
* This is a best practice alternative to setTimeout
|
|
1994
|
+
*/
|
|
1995
|
+
private scrollToLastMessage() {
|
|
1996
|
+
this.showIonContent = true
|
|
1997
|
+
if (this.ionContentChatArea) {
|
|
1998
|
+
// Use requestAnimationFrame for better performance
|
|
1999
|
+
requestAnimationFrame(() => {
|
|
2000
|
+
requestAnimationFrame(() => {
|
|
2001
|
+
// Double RAF ensures DOM is fully rendered
|
|
2002
|
+
this.ionContentChatArea.scrollToBottom(0).then(() => {
|
|
2003
|
+
this.logger.log('[CONVS-DETAIL] scroll posizionato all\'ultimo messaggio')
|
|
2004
|
+
}).catch((error) => {
|
|
2005
|
+
this.logger.error('[CONVS-DETAIL] errore durante lo scroll:', error)
|
|
2006
|
+
})
|
|
2007
|
+
})
|
|
2008
|
+
})
|
|
2009
|
+
} else {
|
|
2010
|
+
this.logger.warn('[CONVS-DETAIL] ionContentChatArea non disponibile')
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1930
2014
|
/**
|
|
1931
2015
|
* detectBottom
|
|
1932
2016
|
*/
|
|
@@ -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)>
|