@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.
Files changed (90) hide show
  1. package/CHANGELOG.md +131 -2
  2. package/angular.json +1 -0
  3. package/package.json +1 -1
  4. package/src/app/app.component.html +3 -1
  5. package/src/app/app.component.ts +72 -13
  6. package/src/app/chatlib/conversation-detail/message/image/image.component.html +1 -0
  7. package/src/app/chatlib/conversation-detail/message/image/image.component.ts +19 -0
  8. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +14 -2
  9. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +39 -2
  10. package/src/app/chatlib/list-conversations-component/list-conversations.module.ts +14 -0
  11. package/src/app/components/canned-response/canned-response.component.html +26 -23
  12. package/src/app/components/canned-response/canned-response.component.scss +0 -2
  13. package/src/app/components/canned-response/canned-response.component.ts +3 -1
  14. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
  15. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
  16. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +39 -9
  17. package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
  18. package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
  19. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  20. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
  21. package/src/app/components/navbar/navbar.component.html +35 -9
  22. package/src/app/components/navbar/navbar.component.scss +64 -0
  23. package/src/app/components/navbar/navbar.component.ts +100 -42
  24. package/src/app/components/project-item/project-item.component.ts +79 -51
  25. package/src/app/components/sidebar/sidebar.component.html +65 -45
  26. package/src/app/components/sidebar/sidebar.component.ts +110 -117
  27. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +3 -3
  28. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +15 -22
  29. package/src/app/directives/html-entities-encode.pipe.ts +20 -5
  30. package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
  31. package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
  32. package/src/app/pages/conversation-detail/conversation-detail.page.ts +95 -7
  33. package/src/app/pages/conversations-list/conversations-list.module.ts +3 -5
  34. package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
  35. package/src/app/pages/conversations-list/conversations-list.page.ts +51 -11
  36. package/src/app/pages/unassigned-conversations/unassigned-conversations.module.ts +16 -4
  37. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +41 -17
  38. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +10 -1
  39. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +114 -9
  40. package/src/app/services/global-settings/global-settings.service.ts +11 -3
  41. package/src/app/services/nav-proxy.service.ts +0 -1
  42. package/src/app/services/project_users/project-users.service.spec.ts +16 -0
  43. package/src/app/services/project_users/project-users.service.ts +63 -0
  44. package/src/app/services/projects/project.service.ts +2 -1
  45. package/src/app/services/tiledesk/tiledesk.service.ts +21 -16
  46. package/src/app/services/triggerEvents/triggerEvents.ts +28 -0
  47. package/src/app/services/websocket/websocket-js.ts +59 -534
  48. package/src/app/services/websocket/websocket-js_old.ts +578 -0
  49. package/src/app/services/websocket/websocket.service.ts +59 -10
  50. package/src/app/services/websocket/websocket.worker.ts +242 -0
  51. package/src/app/shared/shared.module.ts +11 -2
  52. package/src/app/utils/globals.ts +2 -0
  53. package/src/app/utils/permissions.constants.ts +138 -0
  54. package/src/app/utils/project-utils.ts +2 -2
  55. package/src/app/utils/utils.ts +18 -1
  56. package/src/assets/i18n/ar.json +11 -1
  57. package/src/assets/i18n/az.json +11 -1
  58. package/src/assets/i18n/de.json +11 -1
  59. package/src/assets/i18n/en.json +11 -1
  60. package/src/assets/i18n/es.json +11 -1
  61. package/src/assets/i18n/fr.json +11 -1
  62. package/src/assets/i18n/it.json +13 -3
  63. package/src/assets/i18n/kk.json +11 -1
  64. package/src/assets/i18n/pt.json +11 -1
  65. package/src/assets/i18n/ru.json +11 -1
  66. package/src/assets/i18n/sr.json +11 -1
  67. package/src/assets/i18n/sv.json +11 -1
  68. package/src/assets/i18n/tr.json +11 -1
  69. package/src/assets/i18n/uk.json +11 -1
  70. package/src/assets/i18n/uz.json +12 -1
  71. package/src/assets/img/no_data_found.png +0 -0
  72. package/src/assets/js/agentDesktop-sdk.js +55 -0
  73. package/src/assets/js/chat21client.js +36 -0
  74. package/src/assets/js/mqtt-keepalive-worker.js +53 -0
  75. package/src/assets/test.html +5 -2
  76. package/src/chat-config-template.json +1 -0
  77. package/src/chat-config.json +1 -0
  78. package/src/chat21-core/models/projectUsers.ts +19 -0
  79. package/src/chat21-core/models/project_user.ts +2 -1
  80. package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
  81. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  82. package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
  83. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  84. package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
  85. package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
  86. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
  87. package/src/chat21-core/utils/constants.ts +5 -0
  88. package/src/chat21-core/utils/convertRequestToConversation.ts +1 -1
  89. package/src/chat21-core/utils/utils.ts +53 -3
  90. package/src/variables.scss +3 -0
@@ -7,6 +7,13 @@ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service
7
7
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
8
8
  import { Project } from 'src/chat21-core/models/projects';
9
9
  import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
10
+ import { getUserStatusFromProjectUser } from 'src/chat21-core/utils/utils';
11
+ import { TEAMMATE_STATUS } from 'src/chat21-core/utils/constants';
12
+ import { WebsocketService } from 'src/app/services/websocket/websocket.service';
13
+ import { ProjectUser } from 'src/chat21-core/models/project_user';
14
+ import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
15
+ import { PERMISSIONS } from 'src/app/utils/permissions.constants';
16
+ import { getOSCode, hasRole } from 'src/app/utils/utils';
10
17
 
11
18
  @Component({
12
19
  selector: 'app-navbar',
@@ -21,24 +28,31 @@ export class NavbarComponent implements OnInit {
21
28
  private logger: LoggerService = LoggerInstance.getInstance();
22
29
  private tiledeskToken: string;
23
30
 
24
- public projects: Project[] = [];
31
+ public projects: ProjectUser[] = [];
25
32
  public project: any = [];
26
33
  private USER_ROLE: string;
27
34
 
28
35
  public translationsMap: Map<string, string> = new Map();
29
36
 
30
37
  public openDropdownProjects: boolean = false
38
+ public openStatusDropdownProjectId: string | null = null
39
+ public TEAMMATE_STATUS = TEAMMATE_STATUS
31
40
  private public_Key: string;
32
41
  public isVisible: boolean;
33
- public MT: boolean;
42
+ public isVisibleMT: boolean;
34
43
 
44
+ public projectUser: ProjectUser;
45
+ public roles: { [key: string]: boolean }
46
+ PERMISSIONS = PERMISSIONS;
35
47
  constructor(
36
48
  private projectService: ProjectService,
49
+ public projectUsersService: ProjectUsersService,
37
50
  private tiledeskAuthService: TiledeskAuthService,
38
51
  private appConfigProvider: AppConfigProvider,
39
52
  private translateService: CustomTranslateService,
40
53
  private events: EventsService,
41
54
  private cdref: ChangeDetectorRef,
55
+ private wsService: WebsocketService,
42
56
  ) { }
43
57
 
44
58
  ngOnInit() {
@@ -60,7 +74,10 @@ export class NavbarComponent implements OnInit {
60
74
  "NAVBAR.ADD_PROJECT",
61
75
  "NAVBAR.RECENT_PROJECTS",
62
76
  "NAVBAR.OTHER_PROJECTS",
63
- "LABEL_CHAT"
77
+ "LABEL_CHAT",
78
+ "LABEL_AVAILABLE",
79
+ "LABEL_NOT_AVAILABLE",
80
+ "LABEL_INACTIVE"
64
81
  ]
65
82
 
66
83
  this.translationsMap = this.translateService.translateLanguage(keys)
@@ -78,14 +95,17 @@ export class NavbarComponent implements OnInit {
78
95
 
79
96
  getProjects() {
80
97
  this.logger.log('[NAVBAR] calling getProjects ... ');
81
- this.projectService.getProjects().subscribe((projects: any) => {
98
+ this.projectService.getProjects().subscribe((projects: ProjectUser[]) => {
82
99
  this.logger.log('[NAVBAR] getProjects PROJECTS ', projects);
83
100
  if (projects) {
84
101
  // this.projects = projects;
85
- this.projects = projects.filter((project: any) => {
102
+ this.projects = projects.filter((project: ProjectUser) => {
86
103
  // this.logger.log('[NAVBAR] getProjects PROJECTS status ', project.id_project.status);
87
104
  return project.id_project.status === 100;
88
105
  });
106
+ this.projects.forEach((project: ProjectUser) => {
107
+ project.teammateStatus = getUserStatusFromProjectUser(project as any);
108
+ });
89
109
  this.logger.log('[NAVBAR] getProjects this.projects ', this.projects);
90
110
  }
91
111
  }, (error) => {
@@ -96,11 +116,14 @@ export class NavbarComponent implements OnInit {
96
116
  }
97
117
 
98
118
  getStoredProjectAndUserRole() {
99
- this.events.subscribe('storage:last_project',project =>{
119
+ this.events.subscribe('storage:last_project',async (project) =>{
100
120
  this.logger.log('[NAVBAR] stored_project ', project)
101
121
  if (project && project !== 'undefined') {
102
122
  this.project = project;
103
123
  this.USER_ROLE = project.role;
124
+ this.projectUser = await this.projectUsersService.getProjectUserByProjectId(project.id_project.id)
125
+ this.roles = this.checkRoles()
126
+ this.logger.log('[SIDEBAR] roles ', this.roles)
104
127
  }
105
128
  })
106
129
  }
@@ -108,44 +131,24 @@ export class NavbarComponent implements OnInit {
108
131
  getOSCODE() {
109
132
  this.public_Key = this.appConfigProvider.getConfig().t2y12PruGU9wUtEGzBJfolMIgK;
110
133
  this.logger.log('[NAVBAR] AppConfigService getAppConfig public_Key', this.public_Key)
111
- this.logger.log('[NAVBAR] public_Key', this.public_Key)
112
-
113
- let keys = this.public_Key.split("-");
114
- // this.logger.log('PUBLIC-KEY (Navbar) - public_Key keys', keys)
115
-
116
- keys.forEach(key => {
117
- // this.logger.log('NavbarComponent public_Key key', key)
118
- if (key.includes("PAY")) {
119
- // this.logger.log('PUBLIC-KEY (Navbar) - key', key);
120
- let pay = key.split(":");
121
- // this.logger.log('PUBLIC-KEY (Navbar) - pay key&value', pay);
122
- if (pay[1] === "F") {
123
- this.isVisible = false;
124
- // this.logger.log('PUBLIC-KEY (Navbar) - pay isVisible', this.isVisible);
125
- } else {
126
- this.isVisible = true;
127
- // this.logger.log('PUBLIC-KEY (Navbar) - pay isVisible', this.isVisible);
128
- }
129
- }
130
-
131
- if (key.includes("MTT")) {
132
- // this.logger.log('PUBLIC-KEY (Navbar) - key', key);
133
- let mt = key.split(":");
134
- // this.logger.log('PUBLIC-KEY (Navbar) - mt key&value', mt);
135
- if (mt[1] === "F") {
136
- this.MT = false;
137
- // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
138
- } else {
139
- this.MT = true;
140
- // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
141
- }
142
- }
143
- });
134
+
135
+ this.isVisibleMT = getOSCode("MTT", this.public_Key);
136
+
137
+ }
138
+
139
+ checkRoles(): { [key: string]: boolean } {
140
+ const permissionKeys = [
141
+ 'CHANGE_PROJECT',
142
+ 'SIMULATE_CONV',
143
+ ] as const;
144
144
 
145
- if (!this.public_Key.includes("MTT")) {
146
- this.MT = false;
147
- // this.logger.log('PUBLIC-KEY (Navbar) - mt is', this.MT);
145
+ const roles: { [key: string]: boolean } = {};
146
+ for (const key of permissionKeys) {
147
+ const permission = PERMISSIONS[key];
148
+ roles[permission] = hasRole(this.projectUser, permission);
148
149
  }
150
+
151
+ return roles;
149
152
 
150
153
  }
151
154
 
@@ -177,6 +180,61 @@ export class NavbarComponent implements OnInit {
177
180
  window.open(url, '_blank');
178
181
  }
179
182
 
183
+ toggleProjectsDropdown() {
184
+ this.openDropdownProjects = !this.openDropdownProjects
185
+ if (!this.openDropdownProjects) {
186
+ this.openStatusDropdownProjectId = null
187
+ }
188
+ }
189
+
190
+ statusDropdownPosition = { top: 0, right: 0 }
191
+
192
+ toggleStatusDropdown(event: Event, prjct: any) {
193
+ event.stopPropagation()
194
+ event.preventDefault()
195
+ const projectId = prjct?.id_project?._id
196
+ const isOpening = this.openStatusDropdownProjectId !== projectId
197
+ if (isOpening) {
198
+ const el = event.currentTarget as HTMLElement
199
+ const rect = el.getBoundingClientRect()
200
+ this.statusDropdownPosition = {
201
+ top: rect.top + rect.height / 2,
202
+ right: window.innerWidth - rect.left + 4
203
+ }
204
+ }
205
+ this.openStatusDropdownProjectId = this.openStatusDropdownProjectId === projectId ? null : projectId
206
+ }
207
+
208
+ onChangeProjectStatus(projectUser: ProjectUser, selectedStatusID: any) {
209
+ // TODO: implementare aggiornamento status progetto
210
+ this.logger.log('[NAVBAR] onChangeProjectStatus placeholder', projectUser, selectedStatusID)
211
+ this.openStatusDropdownProjectId = null
212
+
213
+ let IS_AVAILABLE = null
214
+ let profilestatus = ''
215
+ if (selectedStatusID === 1) {
216
+ IS_AVAILABLE = true
217
+ } else if (selectedStatusID === 2) {
218
+ IS_AVAILABLE = false
219
+ } else if (selectedStatusID === 3) {
220
+ IS_AVAILABLE = false
221
+ profilestatus = 'inactive'
222
+ }
223
+
224
+ this.wsService.updateCurrentUserAvailability(this.tiledeskToken, projectUser.id_project._id, IS_AVAILABLE, profilestatus).subscribe((projectUserUpdated: any) => {
225
+
226
+ this.logger.log('[NAVBAR] - PROJECT-USER UPDATED ', projectUser)
227
+ this.projects.find(p => p.id_project._id === projectUser.id_project._id).teammateStatus = getUserStatusFromProjectUser(projectUserUpdated as any);
228
+
229
+ }, (error) => {
230
+ this.logger.error('[NAVBAR] - PROJECT-USER UPDATED - ERROR ', error);
231
+
232
+ }, () => {
233
+ this.logger.log('[NAVBAR] - PROJECT-USER UPDATED * COMPLETE *');
234
+
235
+ });
236
+ }
237
+
180
238
  goToHome(id_project: string, project_name: string,) {
181
239
  // this.logger.log('!NAVBAR goToHome prjct ', prjct)
182
240
  this.logger.log('[NAVBAR] goToHome id_project ', id_project, 'project_name', project_name)
@@ -13,7 +13,7 @@ import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
13
13
  import { WebSocketJs } from 'src/app/services/websocket/websocket-js';
14
14
  import { AppConfigProvider } from 'src/app/services/app-config';
15
15
  import { ConvertRequestToConversation } from 'src/chat21-core/utils/convertRequestToConversation';
16
- import { compareValues } from 'src/chat21-core/utils/utils';
16
+ import { compareValues, getUserStatusFromProjectUser } from 'src/chat21-core/utils/utils';
17
17
  import { ProjectService } from 'src/app/services/projects/project.service';
18
18
  import { ProjectUser } from 'src/chat21-core/models/project_user';
19
19
  import { Project } from 'src/chat21-core/models/projects';
@@ -31,6 +31,8 @@ export class ProjectItemComponent implements OnInit {
31
31
  @Output() openUnsevedConvsEvent = new EventEmitter<any>()
32
32
 
33
33
  private unsubscribe$: Subject<any> = new Subject<any>();
34
+ /** ID progetti in cui l'utente è Available (per filtrare il count unserved) */
35
+ private availableProjectIds: Set<string> = new Set();
34
36
  project: any;
35
37
  tiledeskToken: string;
36
38
 
@@ -67,6 +69,7 @@ export class ProjectItemComponent implements OnInit {
67
69
 
68
70
  ngOnDestroy() {
69
71
  this.logger.log('[PROJECT-ITEM] > ngOnDestroy')
72
+ this.wsService.unsubscribeFromAllProjectConversations();
70
73
  this.unsubscribe$.next()
71
74
  this.unsubscribe$.complete()
72
75
 
@@ -87,17 +90,17 @@ export class ProjectItemComponent implements OnInit {
87
90
 
88
91
  connetWebsocket(tiledeskToken) {
89
92
 
90
- this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] tiledeskToken ', tiledeskToken)
91
- const appconfig = this.appConfigProvider.getConfig();
92
- this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', appconfig.wsUrl)
93
- const WS_URL = appconfig.wsUrl + '?token=' + tiledeskToken
94
- this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', WS_URL)
95
- this.webSocketJs.init(
96
- WS_URL,
97
- undefined,
98
- undefined,
99
- undefined
100
- );
93
+ // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] tiledeskToken ', tiledeskToken)
94
+ // const appconfig = this.appConfigProvider.getConfig();
95
+ // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', appconfig.wsUrl)
96
+ // const WS_URL = appconfig.wsUrl + '?token=' + tiledeskToken
97
+ // this.logger.log('[WEBSOCKET-JS] connetWebsocket called in [PROJECT-ITEM] wsUrl ', WS_URL)
98
+ // this.webSocketJs.init(
99
+ // WS_URL,
100
+ // undefined,
101
+ // undefined,
102
+ // undefined
103
+ // );
101
104
 
102
105
  this.getLastProjectStoredAndSubscToWSAvailabilityAndConversations();
103
106
  }
@@ -107,9 +110,7 @@ export class ProjectItemComponent implements OnInit {
107
110
  if (event && event.data) {
108
111
  if (event.data === 'hasChangedProject') {
109
112
  this.unservedRequestCount = 0;
110
- if (this.project) {
111
- this.wsService.unsubscribeToWsConversations(this.project.id_project._id)
112
- }
113
+ this.wsService.unsubscribeFromAllProjectConversations();
113
114
  this.getLastProjectStoredAndSubscToWSAvailabilityAndConversations();
114
115
  }
115
116
  }
@@ -196,10 +197,21 @@ export class ProjectItemComponent implements OnInit {
196
197
 
197
198
  let stored_project = this.getStoredProject();
198
199
 
200
+ const applySubscriptions = (projects: ProjectUser[], currentProject: ProjectUser) => {
201
+ this.project = currentProject;
202
+ if (!stored_project) {
203
+ localStorage.setItem('last_project', JSON.stringify(currentProject));
204
+ }
205
+ projects.forEach((p) => (p.teammateStatus = getUserStatusFromProjectUser(p as any)));
206
+ const ids = this.wsService.subscriptionToWsConversationsForOnlineProjects(projects);
207
+ this.availableProjectIds = new Set(ids || []);
208
+ this.doProjectSubscriptions(currentProject);
209
+ };
210
+
199
211
  if (!stored_project) {
200
212
  this.logger.log('[PROJECT-ITEM] No valid stored project, fetching remote');
201
213
  this.projectService.getProjects().subscribe(projects => {
202
- let project: Project | undefined;
214
+ let project: ProjectUser | undefined;
203
215
 
204
216
  if (this.projectID) {
205
217
  project = projects.find( p => p.id_project?._id === this.projectID );
@@ -214,9 +226,7 @@ export class ProjectItemComponent implements OnInit {
214
226
  return;
215
227
  }
216
228
 
217
- this.project = project;
218
- localStorage.setItem('last_project', JSON.stringify(project));
219
- this.doProjectSubscriptions(project);
229
+ applySubscriptions(projects, project);
220
230
 
221
231
  }, error => {
222
232
  this.logger.error('[PROJECT-ITEM] GET PROJECTS ERROR', error);
@@ -225,10 +235,14 @@ export class ProjectItemComponent implements OnInit {
225
235
  return;
226
236
  }
227
237
 
228
- // stored project valido
229
- this.project = stored_project;
230
- this.doProjectSubscriptions(stored_project);
231
-
238
+ this.projectService.getProjects().subscribe(projects => {
239
+ const currentProject = projects.find(p => p.id_project?._id === stored_project.id_project?._id) || stored_project;
240
+ applySubscriptions(projects, currentProject);
241
+ }, error => {
242
+ this.logger.error('[PROJECT-ITEM] GET PROJECTS ERROR (stored)', error);
243
+ this.project = stored_project;
244
+ this.doProjectSubscriptions(stored_project);
245
+ });
232
246
  }
233
247
 
234
248
  doProjectSubscriptions(project) {
@@ -253,7 +267,7 @@ export class ProjectItemComponent implements OnInit {
253
267
  this.wsService.subscriptionToWsCurrentProjectUserAvailability(project.id_project._id, this.project._id);
254
268
  this.listenTocurrentProjectUserUserAvailability$(project)
255
269
 
256
- this.wsService.subscriptionToWsConversations(project.id_project._id)
270
+ // Le conversations sono già sottoscritte per tutti i progetti online in subscriptionToWsConversationsForOnlineProjects
257
271
  this.updateUnservedRequestCount();
258
272
 
259
273
  }
@@ -273,6 +287,13 @@ export class ProjectItemComponent implements OnInit {
273
287
  this.avaialble_status_for_tooltip = this.translationMap.get('CHANGE_TO_YOUR_STATUS_TO_AVAILABLE')
274
288
  }
275
289
  }
290
+ const projectId = projectUser['id_project'];
291
+ if (projectUser['user_available'] === true) {
292
+ this.availableProjectIds.add(projectId);
293
+ } else {
294
+ this.availableProjectIds.delete(projectId);
295
+ }
296
+ this.recalculateUnservedCount(this.wsService.wsRequestsList);
276
297
  }
277
298
 
278
299
  }, (error) => {
@@ -308,36 +329,43 @@ export class ProjectItemComponent implements OnInit {
308
329
  });
309
330
  }
310
331
 
311
- updateUnservedRequestCount() {
332
+ private getRequestProjectId(r: any): string | undefined {
333
+ if (!r?.id_project) return undefined;
334
+ return typeof r.id_project === 'string' ? r.id_project : r.id_project?._id;
335
+ }
312
336
 
313
- this.wsService.wsRequestsList$.pipe(takeUntil(this.unsubscribe$)).pipe(skip(1)).subscribe((requests) => {
314
- if (requests) {
315
- let count = 0;
316
- requests.forEach(r => {
317
- if (r['status'] === 100) {
318
- if (this.hasmeInAgents(r['agents']) === true) {
319
- count = count + 1;
320
- let conv = this.convertRequestToConversation.getConvFromRequest(r)
321
- if(!this.unservedConversations.find((el) => {return el.uid === conv.uid})){
322
- this.unservedConversations.push(conv)
323
- this.unservedConversations.sort(compareValues('timestamp', 'desc'))
324
- }
325
- }
326
- }
327
- });
328
- //not sound if unservedRequest is already chached and web-sk is closed and restart again
329
- // this.logger.log('updateUnservedRequestCount::: count , unservedRequestCount ', count , this.unservedRequestCount)
330
- if(count > this.unservedRequestCount ){
331
- this.events.publish('unservedRequest:count', count)
337
+ private recalculateUnservedCount(requests: any[]) {
338
+ if (!requests) return;
339
+ let count = 0;
340
+ this.unservedConversations = [];
341
+ requests.forEach((r) => {
342
+ const projectId = this.getRequestProjectId(r);
343
+ if (!projectId || !this.availableProjectIds.has(projectId)) return;
344
+ if (r['status'] === 100 && this.hasmeInAgents(r['agents']) === true) {
345
+ count += 1;
346
+ const conv = this.convertRequestToConversation.getConvFromRequest(r);
347
+ if (!this.unservedConversations.find((el) => el.uid === conv.uid)) {
348
+ this.unservedConversations.push(conv);
349
+ this.unservedConversations.sort(compareValues('timestamp', 'desc'));
332
350
  }
333
- this.unservedRequestCount = count;
334
-
335
351
  }
336
- }, error => {
337
- this.logger.error('[PROJECT-ITEM] UNSERVED REQUEST COUNT * error * ', error)
338
- }, () => {
339
- this.logger.log('[PROJECT-ITEM] UNSERVED REQUEST COUNT */* COMPLETE */*')
340
- })
352
+ });
353
+ if (count > this.unservedRequestCount) {
354
+ this.events.publish('unservedRequest:count', count);
355
+ }
356
+ console.log('unservedRequestCount', count);
357
+ this.unservedRequestCount = count;
358
+ }
359
+
360
+ updateUnservedRequestCount() {
361
+ this.wsService.wsRequestsList$
362
+ .pipe(takeUntil(this.unsubscribe$))
363
+ .pipe(skip(1))
364
+ .subscribe(
365
+ (requests) => this.recalculateUnservedCount(requests),
366
+ (error) => this.logger.error('[PROJECT-ITEM] UNSERVED REQUEST COUNT * error * ', error),
367
+ () => this.logger.log('[PROJECT-ITEM] UNSERVED REQUEST COUNT */* COMPLETE */*')
368
+ );
341
369
  }
342
370
 
343
371
  hasmeInAgents(agents) {
@@ -57,25 +57,27 @@
57
57
  <!-- ------------------------------------------- -->
58
58
  <!-- HOME (click)="goToHome()"" -->
59
59
  <!-- ------------------------------------------- -->
60
- <div matTooltip="Home" #tooltip="matTooltip" matTooltipPosition='right'
61
- matTooltipHideDelay="100" matTooltipClass="custom-mat-tooltip">
62
- <a target="_self" href="{{ dashboard_home_url }}" class="customAncor">
63
- <span>
64
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
65
- <path d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z" />
66
- </svg>
67
- </span>
68
- </a>
69
- </div>
60
+ <ng-container *ngIf="roles?.[PERMISSIONS.HOME_READ]">
61
+ <div matTooltip="Home" #tooltip="matTooltip" matTooltipPosition='right'
62
+ matTooltipHideDelay="100" matTooltipClass="custom-mat-tooltip">
63
+ <a target="_self" href="{{ URLS.HOME }}" class="customAncor">
64
+ <span>
65
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
66
+ <path d="M240-200h120v-240h240v240h120v-360L480-740 240-560v360Zm-80 80v-480l320-240 320 240v480H520v-240h-80v240H160Zm320-350Z" />
67
+ </svg>
68
+ </span>
69
+ </a>
70
+ </div>
71
+ </ng-container>
70
72
 
71
73
  <!-- -------------------------------------------------------- -->
72
74
  <!-- @ Knowledge Bases -->
73
75
  <!-- -------------------------------------------------------- -->
74
- <ng-container *ngIf="USER_ROLE !== 'agent' && isVisibleKNB">
76
+ <ng-container *ngIf="USER_ROLE !== 'agent' && isVisibleKNB && roles?.[PERMISSIONS.KB_READ]">
75
77
  <div id="bot-anchor-wpr" matTooltipClass="custom-mat-tooltip"
76
- matTooltip="Knowledge Bases" #tooltip="matTooltip" matTooltipPosition='right'
78
+ matTooltip="{{translationsMap?.get('Knowledgebases')}}" #tooltip="matTooltip" matTooltipPosition='right'
77
79
  matTooltipHideDelay="100" routerLinkActive="item-active">
78
- <a target="_self" href="{{ dashboard_knb_url }}" class="customAncor">
80
+ <a target="_self" href="{{ URLS.KNOWLEDGEBASE }}" class="customAncor">
79
81
  <span>
80
82
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
81
83
  <path d="M390-120q-51 0-88-35.5T260-241q-60-8-100-53t-40-106q0-21 5.5-41.5T142-480q-11-18-16.5-38t-5.5-42q0-61 40-105.5t99-52.5q3-51 41-86.5t90-35.5q26 0 48.5 10t41.5 27q18-17 41-27t49-10q52 0 89.5 35t40.5 86q59 8 99.5 53T840-560q0 22-5.5 42T818-480q11 18 16.5 38.5T840-400q0 62-40.5 106.5T699-241q-5 50-41.5 85.5T570-120q-25 0-48.5-9.5T480-156q-19 17-42 26.5t-48 9.5Zm130-590v460q0 21 14.5 35.5T570-200q20 0 34.5-16t15.5-36q-21-8-38.5-21.5T550-306q-10-14-7.5-30t16.5-26q14-10 30-7.5t26 16.5q11 16 28 24.5t37 8.5q33 0 56.5-23.5T760-400q0-5-.5-10t-2.5-10q-17 10-36.5 15t-40.5 5q-17 0-28.5-11.5T640-440q0-17 11.5-28.5T680-480q33 0 56.5-23.5T760-560q0-33-23.5-56T680-640q-11 18-28.5 31.5T613-587q-16 6-31-1t-20-23q-5-16 1.5-31t22.5-20q15-5 24.5-18t9.5-30q0-21-14.5-35.5T570-760q-21 0-35.5 14.5T520-710Zm-80 460v-460q0-21-14.5-35.5T390-760q-21 0-35.5 14.5T340-710q0 16 9 29.5t24 18.5q16 5 23 20t2 31q-6 16-21 23t-31 1q-21-8-38.5-21.5T279-640q-32 1-55.5 24.5T200-560q0 33 23.5 56.5T280-480q17 0 28.5 11.5T320-440q0 17-11.5 28.5T280-400q-21 0-40.5-5T203-420q-2 5-2.5 10t-.5 10q0 33 23.5 56.5T280-320q20 0 37-8.5t28-24.5q10-14 26-16.5t30 7.5q14 10 16.5 26t-7.5 30q-14 19-32 33t-39 22q1 20 16 35.5t35 15.5q21 0 35.5-14.5T440-250Zm40-230Z" />
@@ -89,10 +91,10 @@
89
91
  <!-- ---------------------------------- -->
90
92
  <!-- Bot (click)="goToBots()" -->
91
93
  <!-- ---------------------------------- -->
92
- <ng-container *ngIf="USER_ROLE !== 'agent'">
93
- <div id="bot-anchor-wpr" matTooltipClass="custom-mat-tooltip" matTooltip="Bots"
94
+ <ng-container *ngIf="USER_ROLE !== 'agent' && roles?.[PERMISSIONS.FLOWS_READ]">
95
+ <div id="bot-anchor-wpr" matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('Flows')}}"
94
96
  #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
95
- <a target="_self" href="{{ dashboard_bots_url }}" id="bot-anchor" #botbtn class="customAncor">
97
+ <a target="_self" href="{{ URLS.BOTS }}" id="bot-anchor" #botbtn class="customAncor">
96
98
  <span class="bot-icon-wpr">
97
99
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"width="24px" height="24px" fill="none">
98
100
  <path d="M12,21.9c-1,0-1.8-0.3-2.5-1c-0.7-0.7-1-1.5-1-2.5c0-0.8,0.3-1.6,0.8-2.2c0.5-0.6,1.2-1,1.9-1.2v-2.3H5.5V9H3 V2.5h6.4V9H7v2.3h10V8.9c-0.8-0.2-1.4-0.6-1.9-1.2c-0.5-0.6-0.8-1.3-0.8-2.2c0-1,0.3-1.8,1-2.5c0.7-0.7,1.5-1,2.5-1 c1,0,1.8,0.3,2.5,1c0.7,0.7,1,1.5,1,2.5c0,0.8-0.3,1.6-0.8,2.2c-0.5,0.6-1.2,1-1.9,1.2v3.9h-5.7v2.3c0.8,0.2,1.4,0.6,1.9,1.2 c0.5,0.6,0.8,1.3,0.8,2.2c0,1-0.3,1.8-1,2.5C13.8,21.6,13,21.9,12,21.9z M17.8,7.5c0.5,0,1-0.2,1.4-0.6c0.4-0.4,0.6-0.8,0.6-1.4 c0-0.5-0.2-1-0.6-1.4c-0.4-0.4-0.8-0.6-1.4-0.6c-0.5,0-1,0.2-1.4,0.6C16,4.5,15.8,5,15.8,5.5c0,0.5,0.2,1,0.6,1.4S17.2,7.5,17.8,7.5 z M4.5,7.5H8V4H4.5C4.5,4,4.5,7.5,4.5,7.5z M12,20.4c0.5,0,1-0.2,1.4-0.6S14,19,14,18.5s-0.2-1-0.6-1.4c-0.4-0.4-0.8-0.6-1.4-0.6 c-0.5,0-1,0.2-1.4,0.6S10,17.9,10,18.5s0.2,1,0.6,1.4C11,20.2,11.5,20.4,12,20.4z" />
@@ -105,10 +107,10 @@
105
107
  <!-- ------------------------------------------- -->
106
108
  <!-- Conversations (MONITOR) (click)="goToConversations()" -->
107
109
  <!-- ------------------------------------------- -->
108
- <ng-container *ngIf="isVisibleMON">
109
- <div matTooltipClass="custom-mat-tooltip" matTooltip="Monitor"
110
+ <ng-container *ngIf="isVisibleMON && roles?.[PERMISSIONS.INBOX_READ]">
111
+ <div matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('Monitor')}}"
110
112
  #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
111
- <a target="_self" href="{{ dashboard_convs_url }}" class="customAncor">
113
+ <a target="_self" href="{{ URLS.MONITOR }}" class="customAncor">
112
114
  <!-- <i class="material-icons sidebar-icons">forum</i> -->
113
115
  <span>
114
116
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
@@ -123,13 +125,27 @@
123
125
 
124
126
  <div class="nav-custom sidebar-bottom">
125
127
 
128
+ <!-- ----------------------------- -->
129
+ <!-- WA broadcasts -->
130
+ <!-- ----------------------------- -->
131
+ <ng-container *ngIf="USER_ROLE !== 'agent' && roles?.[PERMISSIONS.AUTOMATIONSLOG_READ]">
132
+ <div matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('WhatsAppBroadcasts')}}"
133
+ #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
134
+ <a target="_self" href="{{ URLS.WHATSAPP }}" class="customAncor">
135
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48" height="24" width="24">
136
+ <path fill="none" fill-rule="evenodd" d="M40.6666 7.3156c-2.1744 -2.1755 -4.7577 -3.8995 -7.6012 -5.0726C30.222 1.0699 27.1745 0.4708 24.0986 0.4801 11.1899 0.4801 0.6816 10.936 0.6763 23.79c-0.0057 4.093 1.0733 8.1145 3.1269 11.655L0.48 47.52l12.4163 -3.2413c3.4367 1.8619 7.2841 2.8363 11.193 2.835h0.0094c12.9076 0 23.415 -10.4569 23.4212 -23.31 0.0078 -3.0653 -0.594 -6.1017 -1.7706 -8.9324 -1.1766 -2.8306 -2.9043 -5.399 -5.0827 -7.5557ZM24.0987 43.1794h-0.0084c-3.4845 0.001 -6.9057 -0.9315 -9.9078 -2.7007l-0.7109 -0.42 -7.3678 1.9236 1.9666 -7.1494 -0.463 -0.735C5.659 31.0132 4.6267 27.4386 4.6306 23.79c0 -10.6815 8.7371 -19.3724 19.4754 -19.3724 5.1513 -0.0092 10.0953 2.0281 13.7446 5.6638 3.6493 3.6357 5.705 8.572 5.715 13.7233 -0.0041 10.6827 -8.737 19.3747 -19.4669 19.3747Zm10.6774 -14.51c-0.5849 -0.2919 -3.465 -1.701 -3.9984 -1.8952 -0.5334 -0.1943 -0.9271 -0.292 -1.3167 0.2919 -0.3895 0.5837 -1.512 1.89 -1.8532 2.2837 -0.3413 0.3938 -0.6826 0.4368 -1.2675 0.1449 -0.5847 -0.2918 -2.4716 -0.9062 -4.707 -2.8906 -1.7399 -1.5446 -2.9137 -3.4513 -3.255 -4.0341 -0.3413 -0.5828 -0.0368 -0.8988 0.2561 -1.1886 0.2636 -0.2614 0.5849 -0.6804 0.8779 -1.0206 0.2929 -0.3403 0.3906 -0.5839 0.5848 -0.9723 0.1943 -0.3885 0.0976 -0.7288 -0.0483 -1.0195 -0.1459 -0.2909 -1.3167 -3.1585 -1.8039 -4.325 -0.4757 -1.1361 -0.9576 -0.9818 -1.3167 -0.9996 -0.3413 -0.0168 -0.7349 -0.021 -1.1225 -0.021 -0.2961 0.0077 -0.5875 0.0765 -0.856 0.2018 -0.2685 0.1253 -0.5081 0.3048 -0.7043 0.5269 -0.5364 0.5838 -2.0485 1.995 -2.0485 4.8594s2.1001 5.6364 2.3898 6.0248c0.2899 0.3886 4.1265 6.2717 9.997 8.7948 1.0901 0.4669 2.204 0.8763 3.337 1.2264 1.4017 0.4431 2.6775 0.3812 3.6854 0.2311 1.1246 -0.167 3.4651 -1.4092 3.9512 -2.7699 0.4862 -1.3608 0.4872 -2.5263 0.3413 -2.7689 -0.146 -0.2426 -0.5366 -0.3895 -1.1225 -0.6804Z" clip-rule="evenodd" stroke-width="1"></path>
137
+ </svg>
138
+ </a>
139
+ </div>
140
+ </ng-container>
141
+
126
142
  <!-- ------------------------------------------- -->
127
143
  <!-- CONTACTS (LEADS) (click)="goToContacts()" -->
128
144
  <!-- ------------------------------------------- -->
129
- <ng-container *ngIf="isVisibleCNT">
130
- <div matTooltipClass="custom-mat-tooltip" matTooltip="{{ contacts_lbl }}"
145
+ <ng-container *ngIf="isVisibleCNT && roles?.[PERMISSIONS.LEADS_READ]">
146
+ <div matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('LABEL_CONTACTS')}}"
131
147
  #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
132
- <a target="_self" href="{{ dashboard_contacts_url }}" class="customAncor">
148
+ <a target="_self" href="{{ URLS.CONTACTS }}" class="customAncor">
133
149
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
134
150
  <path d="M160-40v-80h640v80H160Zm0-800v-80h640v80H160Zm320 400q50 0 85-35t35-85q0-50-35-85t-85-35q-50 0-85 35t-35 85q0 50 35 85t85 35ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm70-80q45-56 109-88t141-32q77 0 141 32t109 88h70v-480H160v480h70Zm118 0h264q-29-20-62.5-30T480-280q-36 0-69.5 10T348-240Zm132-280q-17 0-28.5-11.5T440-560q0-17 11.5-28.5T480-600q17 0 28.5 11.5T520-560q0 17-11.5 28.5T480-520Zm0 40Z" />
135
151
  </svg>
@@ -141,10 +157,10 @@
141
157
  <!-- ------------------------------------------- -->
142
158
  <!-- ANALYTICS (click)="goToAnalytics()" -->
143
159
  <!-- ------------------------------------------- -->
144
- <ng-container *ngIf="isVisibleANA && USER_ROLE !== 'agent'">
145
- <div matTooltipClass="custom-mat-tooltip" matTooltip="{{ analytics_lbl }}"
160
+ <ng-container *ngIf="USER_ROLE !== 'agent' && isVisibleANA && roles?.[PERMISSIONS.ANALYTICS_READ]">
161
+ <div matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('Analytics')}}"
146
162
  #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100" >
147
- <a target="_self" href="{{ dashboard_analytics_url }}" class="customAncor">
163
+ <a target="_self" href="{{ URLS.ANALYTICS }}" class="customAncor">
148
164
  <!-- <i class="material-icons sidebar-icons">trending_up</i> -->
149
165
  <!-- <i class="material-icons sidebar-icons"> analytics </i> -->
150
166
  <!-- <i class="material-icons sidebar-icons"> bar_chart </i> -->
@@ -160,10 +176,10 @@
160
176
  <!-- ------------------------------------------- -->
161
177
  <!-- ACTIVITIES (click)="goToActivities()" -->
162
178
  <!-- ------------------------------------------- -->
163
- <ng-container *ngIf="isVisibleACT">
179
+ <ng-container *ngIf="isVisibleACT && roles?.[PERMISSIONS.ACTIVITIES_READ]">
164
180
  <div *ngIf="USER_ROLE !== 'agent'" matTooltipClass="custom-mat-tooltip"
165
- matTooltip="{{ activities_lbl }}" #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
166
- <a target="_self" href="{{ dashboard_activities_url }}" class="customAncor">
181
+ matTooltip="{{translationsMap?.get('Activities')}}" #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
182
+ <a target="_self" href="{{ URLS.ACTIVITIES }}" class="customAncor">
167
183
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
168
184
  <path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h168q13-36 43.5-58t68.5-22q38 0 68.5 22t43.5 58h168q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm80-80h280v-80H280v80Zm0-160h400v-80H280v80Zm0-160h400v-80H280v80Zm200-190q13 0 21.5-8.5T510-820q0-13-8.5-21.5T480-850q-13 0-21.5 8.5T450-820q0 13 8.5 21.5T480-790ZM200-200v-560 560Z" />
169
185
  </svg>
@@ -174,26 +190,30 @@
174
190
  <!-- ------------------------------------------- -->
175
191
  <!-- REQUESTS HISTORY (click)="goToHistory()" -->
176
192
  <!-- ------------------------------------------- -->
177
- <div matTooltipClass="custom-mat-tooltip" matTooltip="{{ history_lbl }}"
178
- #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
179
- <a target="_self" href="{{ dashboard_history_url }}" class="customAncor">
180
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
181
- <path d="M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z" />
182
- </svg>
183
- </a>
184
- </div>
193
+ <ng-container *ngIf="roles?.[PERMISSIONS.HISTORY_READ]">
194
+ <div matTooltipClass="custom-mat-tooltip" matTooltip="{{translationsMap?.get('History')}}"
195
+ #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
196
+ <a target="_self" href="{{URLS.HISTORY}}" class="customAncor">
197
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
198
+ <path d="M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z" />
199
+ </svg>
200
+ </a>
201
+ </div>
202
+ </ng-container>
185
203
 
186
204
  <!-- ----------------------------------------------------------------------------------- -->
187
205
  <!-- SETTINGS // old: goToSettings_CannedResponses() *ngIf="USER_ROLE !== 'agent'" (click)="goToWidgetSetUpOrToCannedResponses()" -->
188
206
  <!-- ----------------------------------------------------------------------------------- -->
189
- <div *ngIf="USER_ROLE !== 'agent'" matTooltipClass="custom-mat-tooltip"
190
- matTooltip="{{ settings_lbl }}" #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
191
- <a target="_self" href="{{ dashboard_settings_url }}" class="customAncor">
192
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
193
- <path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
194
- </svg>
195
- </a>
196
- </div>
207
+ <ng-container *ngIf="roles?.[PERMISSIONS.SETTINGS_READ]">
208
+ <div *ngIf="USER_ROLE !== 'agent'" matTooltipClass="custom-mat-tooltip"
209
+ matTooltip="{{translationsMap?.get('Settings')}}" #tooltip="matTooltip" matTooltipPosition='right' matTooltipHideDelay="100">
210
+ <a target="_self" href="{{URLS.SETTINGS}}" class="customAncor">
211
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" width="24px" height="24px" fill="none">
212
+ <path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z" />
213
+ </svg>
214
+ </a>
215
+ </div>
216
+ </ng-container>
197
217
 
198
218
  <div class="sidebar-separator">
199
219
  <!-- <i class="material-symbols-outlined sidebar-icons">
@@ -210,7 +230,7 @@
210
230
  <!-- ------------------------------------------- -->
211
231
  <!-- LOGO BRAND (click)="goToOfficialSite()" -->
212
232
  <!-- ------------------------------------------- -->
213
- <a target="_blank" href="{{ tiledesk_url }}" class="customAncor">
233
+ <a target="_blank" href="{{ URLS.TILEDESK }}" class="customAncor">
214
234
  <img [src]="LOGOS_ITEMS['COMPANY_LOGO_NO_TEXT'].icon">
215
235
  </a>
216
236
  </div>