@chat21/chat21-ionic 3.4.31 → 3.4.32-rc10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +167 -2
  2. package/angular.json +1 -0
  3. package/package.json +1 -1
  4. package/src/app/app.component.html +3 -1
  5. package/src/app/app.component.ts +72 -11
  6. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.html +14 -2
  7. package/src/app/chatlib/list-conversations-component/ion-list-conversations/ion-list-conversations.component.scss +39 -2
  8. package/src/app/chatlib/list-conversations-component/list-conversations.module.ts +14 -0
  9. package/src/app/components/canned-response/canned-response.component.html +26 -23
  10. package/src/app/components/canned-response/canned-response.component.scss +0 -2
  11. package/src/app/components/canned-response/canned-response.component.ts +3 -1
  12. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
  13. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
  14. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +29 -7
  15. package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
  16. package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
  17. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  18. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
  19. package/src/app/components/navbar/navbar.component.html +35 -9
  20. package/src/app/components/navbar/navbar.component.scss +71 -1
  21. package/src/app/components/navbar/navbar.component.ts +100 -42
  22. package/src/app/components/project-item/project-item.component.ts +79 -52
  23. package/src/app/components/sidebar/sidebar.component.html +65 -45
  24. package/src/app/components/sidebar/sidebar.component.ts +110 -117
  25. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +52 -11
  26. package/src/app/components/sidebar-user-details/sidebar-user-details.component.scss +304 -17
  27. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +217 -27
  28. package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
  29. package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
  30. package/src/app/pages/conversation-detail/conversation-detail.page.ts +89 -5
  31. package/src/app/pages/conversations-list/conversations-list.module.ts +3 -5
  32. package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
  33. package/src/app/pages/conversations-list/conversations-list.page.ts +120 -26
  34. package/src/app/pages/unassigned-conversations/unassigned-conversations.module.ts +16 -4
  35. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +43 -17
  36. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +25 -1
  37. package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +279 -13
  38. package/src/app/pipe/filter.pipe.spec.ts +8 -0
  39. package/src/app/pipe/filter.pipe.ts +15 -0
  40. package/src/app/pipe/find.pipe.spec.ts +8 -0
  41. package/src/app/pipe/find.pipe.ts +15 -0
  42. package/src/app/services/global-settings/global-settings.service.ts +11 -3
  43. package/src/app/services/nav-proxy.service.ts +0 -1
  44. package/src/app/services/project_users/project-users.service.spec.ts +16 -0
  45. package/src/app/services/project_users/project-users.service.ts +63 -0
  46. package/src/app/services/projects/project.service.ts +2 -1
  47. package/src/app/services/tiledesk/tiledesk.service.ts +24 -0
  48. package/src/app/services/triggerEvents/triggerEvents.ts +40 -0
  49. package/src/app/services/websocket/websocket-js.ts +59 -534
  50. package/src/app/services/websocket/websocket-js_old.ts +578 -0
  51. package/src/app/services/websocket/websocket.service.ts +67 -14
  52. package/src/app/services/websocket/websocket.worker.ts +242 -0
  53. package/src/app/shared/shared.module.ts +26 -10
  54. package/src/app/utils/globals.ts +2 -0
  55. package/src/app/utils/permissions.constants.ts +138 -0
  56. package/src/app/utils/project-utils.ts +2 -2
  57. package/src/app/utils/utils.ts +18 -1
  58. package/src/assets/i18n/ar.json +11 -1
  59. package/src/assets/i18n/az.json +11 -1
  60. package/src/assets/i18n/de.json +11 -1
  61. package/src/assets/i18n/en.json +11 -1
  62. package/src/assets/i18n/es.json +11 -1
  63. package/src/assets/i18n/fr.json +11 -1
  64. package/src/assets/i18n/it.json +13 -3
  65. package/src/assets/i18n/kk.json +11 -1
  66. package/src/assets/i18n/pt.json +11 -1
  67. package/src/assets/i18n/ru.json +11 -1
  68. package/src/assets/i18n/sr.json +11 -1
  69. package/src/assets/i18n/sv.json +11 -1
  70. package/src/assets/i18n/tr.json +11 -1
  71. package/src/assets/i18n/uk.json +11 -1
  72. package/src/assets/i18n/uz.json +12 -1
  73. package/src/assets/js/agentDesktop-sdk.js +55 -0
  74. package/src/assets/js/chat21client.js +36 -0
  75. package/src/assets/js/mqtt-keepalive-worker.js +53 -0
  76. package/src/assets/test.html +5 -2
  77. package/src/chat-config-template.json +1 -0
  78. package/src/chat-config.json +1 -0
  79. package/src/chat21-core/models/projectUsers.ts +19 -0
  80. package/src/chat21-core/models/project_user.ts +2 -1
  81. package/src/chat21-core/models/projects.ts +1 -0
  82. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  83. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  84. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
  85. package/src/chat21-core/utils/constants.ts +6 -0
  86. package/src/chat21-core/utils/convertRequestToConversation.ts +2 -2
  87. package/src/chat21-core/utils/utils.ts +53 -3
  88. package/src/variables.scss +3 -0
@@ -2,23 +2,13 @@
2
2
  #user-details {
3
3
  background-color: var(--sidebar-background-color);
4
4
  color: var(--sidebar-color);
5
- // height: calc(100% - 60px);
6
5
  height: 100%;
7
6
  overflow-y: auto;
8
7
  padding: 16px 12px 32px;
9
8
  position: absolute;
10
- // left: -60px;
11
- // top: 60px;
12
- // top: 0px;
13
- // transform: translate(305px);
14
- // transform: translate(60px);
15
- transition: transform 0.5s;
9
+ transition: left 0.5s;
16
10
  width: 305px;
17
11
  left: -245px;
18
- // z-index: 1029;
19
- // transform: translateX(-100%);
20
- // -webkit-transform: translateX(-100%);
21
- // display: none;
22
12
  }
23
13
 
24
14
  // #user-details::-webkit-scrollbar {
@@ -33,11 +23,8 @@
33
23
  // }
34
24
 
35
25
  #user-details.active {
36
- // transform: translate(0);
37
- transform: translate(60px);
38
26
  display: block;
39
- // left: 0px;
40
- left: 10px;
27
+ left: 70px; /* 10px + 60px (equivalente a transform: translate(60px)) - evita containing block per position: fixed */
41
28
  }
42
29
 
43
30
  .user-details-btn-close {
@@ -175,15 +162,315 @@
175
162
  .availability-section {
176
163
  top: 320px;
177
164
  text-align: center;
178
- background-color: var(--user-detail-select-background);
165
+ background-color: var(--sidebar-user-detail-select-background);
179
166
  padding: 4px 0px;
180
- width: 192px;
181
167
  border-radius: 4px;
168
+ // width: 192px;
182
169
  -webkit-transform: translateX(-50%);
183
170
  transform: translateX(-50%);
184
171
  left: 50%;
185
172
  margin: auto;
186
173
  position: absolute;
174
+ font-size: 14px;
175
+ z-index: 2;
176
+
177
+ .btn{
178
+ display: flex;
179
+ position: relative;
180
+ flex-flow: row nowrap;
181
+ align-items: center;
182
+ justify-content: center;
183
+
184
+ border: 1px solid transparent;
185
+ transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
186
+ margin: 0px;
187
+ box-shadow: none;
188
+ }
189
+
190
+ .dropdown-toggle{
191
+ background-color: transparent;
192
+ color: inherit;
193
+ padding: 0px 15px;
194
+ }
195
+
196
+ .project-dropdown,
197
+ .projects-dropdown-toggle {
198
+ // max-width: 180px;
199
+ white-space: nowrap;
200
+ overflow: hidden;
201
+ text-overflow: ellipsis;
202
+ font-family: var(--header-font-family);
203
+
204
+ .material-icons{
205
+ font-size: 20px;
206
+ }
207
+ }
208
+
209
+ button.btn.project-dropdown,
210
+ button.btn.projects-dropdown-toggle {
211
+ padding-top: 4px;
212
+ padding-bottom: 4px;
213
+ background-color: var(--sidebar-user-detail-select-background);
214
+ color: var(--sidebar-user-detail-select-color);
215
+ border: 1px solid var(--sidebar-user-detail-select-background);
216
+ }
217
+
218
+ .teammate-status-in-drawer {
219
+ width: 190px;
220
+ }
221
+
222
+ /* projects-dropdown-wrapper - stile come ng-select .ng-select-container (teammate-status-in-drawer) */
223
+ .projects-dropdown-wrapper {
224
+ position: relative;
225
+ min-height: 36px;
226
+ padding: 6px 12px;
227
+ background-color: var(--sidebar-user-detail-select-background);
228
+ color: var(--sidebar-user-detail-select-color);
229
+ border: 1px solid var(--sidebar-user-detail-select-background);
230
+ border-radius: 4px;
231
+ display: flex;
232
+ align-items: center;
233
+ text-align: left;
234
+ font-size: 14px;
235
+ line-height: 1.4;
236
+ width: 250px;
237
+
238
+ .projects-dropdown-toggle {
239
+ background-color: transparent !important;
240
+ border: none !important;
241
+ padding: 0 !important;
242
+ min-height: auto;
243
+ flex: 1;
244
+ justify-content: space-between;
245
+ color: inherit;
246
+ font-size: inherit;
247
+ }
248
+
249
+ .projects-dropdown-toggle-label {
250
+ text-transform: capitalize;
251
+ overflow: hidden;
252
+ text-overflow: ellipsis;
253
+ white-space: nowrap;
254
+ display: flex;
255
+ align-items: center;
256
+ gap: 8px;
257
+ }
258
+
259
+ .dropdown-menu {
260
+ left: 0;
261
+ right: 0;
262
+ min-width: 100%;
263
+ }
264
+ }
265
+
266
+ li{
267
+ position: relative;
268
+ display: block
269
+ }
270
+
271
+ /* projects_dropdown - stessi colori ng-select (.ng-dropdown-panel) */
272
+ .dropdown-menu {
273
+ border-radius: 4px;
274
+ border: 1px solid var(--sidebar-user-detail-select-background);
275
+ box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
276
+
277
+ position: absolute;
278
+ top: 100%;
279
+ right: 0;
280
+ left: auto;
281
+ z-index: 1000;
282
+ display: none;
283
+ float: left;
284
+ min-width: 160px;
285
+ padding: 5px 0;
286
+ margin: 8px 0 0;
287
+ font-size: 14px;
288
+ text-align: left;
289
+ list-style: none;
290
+ background-color: var(--sidebar-user-detail-select-background);
291
+ -webkit-background-clip: padding-box;
292
+ background-clip: padding-box;
293
+ color: var(--sidebar-user-detail-select-color);
294
+ max-height: 250px;
295
+ overflow-y: auto;
296
+ }
297
+
298
+ .dropdown-menu:not(.open){
299
+ margin-top: -20px;
300
+ opacity: 0;
301
+ visibility: hidden;
302
+ display: block;
303
+ }
304
+
305
+ .dropdown-menu.open{
306
+ margin-top: 12px; //0;
307
+ opacity: 1;
308
+ visibility: visible;
309
+ display: block;
310
+ transition: all 150ms linear;
311
+ }
312
+
313
+ .dropdown-menu li {
314
+ position: relative;
315
+
316
+ .li-selected{
317
+ color: var(--sidebar-user-detail-select-color);
318
+ background-color: var(--sidebar-user-detail-select-hover-background);
319
+ }
320
+
321
+ &.section-title{
322
+ padding-left: 24px;
323
+ font-size: 12px;
324
+ color: var(--sidebar-user-detail-color);
325
+ font-weight: 400
326
+ }
327
+ }
328
+
329
+ .dropdown-menu li>a{
330
+ font-size: 13px;
331
+ padding: 10px 12px;
332
+ border-radius: 2px;
333
+ transition: all 150ms linear;
334
+
335
+ display: block;
336
+ clear: both;
337
+ font-weight: 400;
338
+ line-height: 1.42857143;
339
+ color: var(--sidebar-user-detail-select-color);
340
+ white-space: nowrap;
341
+ text-decoration: none;
342
+ margin: 0px;
343
+ cursor: auto;
344
+
345
+ img {
346
+ width: 15px;
347
+ height: 15px;
348
+ position: relative;
349
+ top: 1px;
350
+ }
351
+ .material-icons {
352
+ vertical-align: middle;
353
+ }
354
+
355
+ &:hover{
356
+ background-color: var(--sidebar-user-detail-select-hover-background);
357
+ color: var(--sidebar-user-detail-select-color);
358
+ box-shadow: none;
359
+ }
360
+
361
+ &.project-item-row {
362
+ display: flex;
363
+ align-items: center;
364
+ justify-content: space-between;
365
+ gap: 8px;
366
+
367
+ .project-item-name {
368
+ flex: 1;
369
+ min-width: 0;
370
+ text-align: left;
371
+ overflow: hidden;
372
+ text-overflow: ellipsis;
373
+ }
374
+
375
+ .project-item-status {
376
+ cursor: pointer;
377
+ flex: 0 0 10%;
378
+ display: flex;
379
+ justify-content: flex-end;
380
+ align-items: center;
381
+
382
+ &.project-item-status-wrapper {
383
+ position: relative;
384
+
385
+ .project-item-status-name {
386
+ margin-right: 4px;
387
+ color: #a9afbb;
388
+ font-size: 9px;
389
+
390
+ }
391
+ }
392
+
393
+ .status-dropdown {
394
+ position: absolute;
395
+ right: 100%;
396
+ top: 50%;
397
+ transform: translateY(-50%);
398
+ margin-right: 4px;
399
+ min-width: 140px;
400
+ padding: 4px 0;
401
+ background-color: var(--sidebar-user-detail-select-background);
402
+ border: 1px solid var(--sidebar-user-detail-select-background);
403
+ border-radius: 4px;
404
+ box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
405
+ z-index: 1001;
406
+ list-style: none;
407
+
408
+ &.status-dropdown-fixed {
409
+ right: auto;
410
+ left: auto;
411
+ margin-right: 0;
412
+ transform: translateY(-50%);
413
+ }
414
+
415
+ .status-dropdown-option {
416
+ display: flex;
417
+ align-items: center;
418
+ padding: 8px 16px;
419
+ font-size: 13px;
420
+ color: var(--sidebar-user-detail-select-color);
421
+ cursor: pointer;
422
+ white-space: nowrap;
423
+
424
+ &:hover {
425
+ background-color: var(--sidebar-user-detail-select-hover-background);
426
+ color: var(--sidebar-user-detail-select-color);
427
+ }
428
+ }
429
+ }
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ /* Status dropdown fuori da #user-details - stessi colori ng-select */
436
+ .status-dropdown-outside {
437
+ position: fixed !important;
438
+ z-index: 1100;
439
+ min-width: 140px;
440
+ padding: 4px 0;
441
+ background-color: var(--sidebar-user-detail-select-background);
442
+ border: 1px solid var(--sidebar-user-detail-select-background);
443
+ border-radius: 4px;
444
+ box-shadow: 0 2px 5px 0 rgb(0, 0, 0, 0.26);
445
+ list-style: none;
446
+
447
+ /* Triangolino in alto a sinistra, fuori dal container, con leggero gap in basso */
448
+ &::before {
449
+ content: '';
450
+ position: absolute;
451
+ left: -7px;
452
+ top: 10px;
453
+ width: 0;
454
+ height: 0;
455
+ border-top: 7px solid transparent;
456
+ border-bottom: 7px solid transparent;
457
+ border-right: 7px solid var(--sidebar-user-detail-select-background);
458
+ }
459
+
460
+ .status-dropdown-option {
461
+ display: flex;
462
+ align-items: center;
463
+ padding: 8px 16px;
464
+ font-size: 13px;
465
+ color: var(--sidebar-user-detail-select-color);
466
+ cursor: pointer;
467
+ white-space: nowrap;
468
+
469
+ &:hover {
470
+ background-color: var(--sidebar-user-detail-select-hover-background);
471
+ color: var(--sidebar-user-detail-select-color);
472
+ }
473
+ }
187
474
  }
188
475
 
189
476
  .first-divider {
@@ -1,4 +1,4 @@
1
- import { Component, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnInit, Output } from '@angular/core';
1
+ import { Component, ElementRef, EventEmitter, HostListener, Input, OnDestroy, OnChanges, OnInit, Output } from '@angular/core';
2
2
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
3
3
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
4
4
  import { TranslateService } from '@ngx-translate/core';
@@ -10,21 +10,25 @@ import { WebsocketService } from 'src/app/services/websocket/websocket.service';
10
10
  import { skip } from 'rxjs/operators';
11
11
  import { AppConfigProvider } from 'src/app/services/app-config';
12
12
  import { EventsService } from 'src/app/services/events-service';
13
- import { tranlatedLanguage } from '../../../chat21-core/utils/constants';
13
+ import { TEAMMATE_STATUS, tranlatedLanguage } from '../../../chat21-core/utils/constants';
14
14
  import { avatarPlaceholder, getColorBck } from 'src/chat21-core/utils/utils-user';
15
15
  import { environment } from 'src/environments/environment';
16
16
  import { Project } from 'src/chat21-core/models/projects';
17
17
  import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
18
18
  import { getOSCode } from 'src/app/utils/utils';
19
+ import { getUserStatusFromProjectUser } from 'src/chat21-core/utils/utils';
20
+ import { ProjectService } from 'src/app/services/projects/project.service';
21
+ import { ProjectUser } from 'src/chat21-core/models/project_user';
19
22
  @Component({
20
23
  selector: 'app-sidebar-user-details',
21
24
  templateUrl: './sidebar-user-details.component.html',
22
25
  styleUrls: ['./sidebar-user-details.component.scss'],
23
26
  })
24
- export class SidebarUserDetailsComponent implements OnInit, OnChanges {
27
+ export class SidebarUserDetailsComponent implements OnInit, OnChanges, OnDestroy {
25
28
  // HAS_CLICKED_OPEN_USER_DETAIL: boolean = false;
26
29
  // @Output() onCloseUserDetailsSidebar = new EventEmitter();
27
30
 
31
+ @Input() logOut: boolean;
28
32
 
29
33
  public browserLang: string;
30
34
  private logger: LoggerService = LoggerInstance.getInstance()
@@ -51,14 +55,20 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
51
55
  DASHBOARD_URL: string;
52
56
 
53
57
  selectedStatus: any;
54
- teammateStatus = [
55
- { id: 1, name: 'Available', avatar: 'assets/img/teammate-status/avaible.svg', label: "LABEL_AVAILABLE" },
56
- { id: 2, name: 'Unavailable', avatar: 'assets/img/teammate-status/unavaible.svg', label: "LABEL_NOT_AVAILABLE" },
57
- { id: 3, name: 'Inactive', avatar: 'assets/img/teammate-status/inactive.svg', label: "LABEL_INACTIVE" },
58
- ];
58
+ TEAMMATE_STATUS = TEAMMATE_STATUS;
59
+
60
+ projects: ProjectUser[] = [];
61
+ selectedProjectForStatus: ProjectUser | null = null;
62
+ public openDropdownProjects: boolean = false
63
+ public openStatusDropdownProjectId: string | null = null
64
+ statusDropdownPosition = { top: 0, left: 0 };
65
+ isVisibleMT = false;
66
+ isVisibleMPA = false;
67
+ private userDetailsMutationObserver: MutationObserver | null = null;
68
+ private statusDropdownCloseTimeout: any = null;
59
69
 
60
70
  translationsMap: Map<string, string> = new Map();
61
-
71
+
62
72
  docEnabled: boolean = true;
63
73
  BRAND_BASE_INFO = BRAND_BASE_INFO;
64
74
 
@@ -72,7 +82,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
72
82
  public appConfigProvider: AppConfigProvider,
73
83
  public events: EventsService,
74
84
  private eRef: ElementRef,
75
-
85
+ private projectService: ProjectService,
76
86
  ) { }
77
87
 
78
88
  ngOnInit() {
@@ -81,11 +91,47 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
81
91
  this.subcribeToAuthStateChanged();
82
92
  this.listenTocurrentProjectUserUserAvailability$();
83
93
  this.listenToCurrentStoredProject();
94
+ this.listenToUserGoOnline();
84
95
  this.getOSCODE();
96
+ this.setupUserDetailsCloseObserver();
85
97
  }
86
98
 
87
99
  ngOnChanges() { }
88
100
 
101
+ ngOnDestroy(): void {
102
+ this.userDetailsMutationObserver?.disconnect();
103
+ this.userDetailsMutationObserver = null;
104
+ this.cancelStatusDropdownClose();
105
+ }
106
+
107
+ /**
108
+ * Osserva la rimozione della classe 'active' da #user-details (es. chiusura via click avatar nel sidebar)
109
+ * per chiudere i dropdown aperti
110
+ */
111
+ private setupUserDetailsCloseObserver(): void {
112
+ setTimeout(() => {
113
+ const el = document.getElementById('user-details');
114
+ if (!el) return;
115
+ this.userDetailsMutationObserver = new MutationObserver((mutations) => {
116
+ mutations.forEach((mutation) => {
117
+ if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
118
+ const target = mutation.target as HTMLElement;
119
+ if (!target.classList.contains('active')) {
120
+ this.closeDropdowns();
121
+ }
122
+ }
123
+ });
124
+ });
125
+ this.userDetailsMutationObserver.observe(el, { attributes: true, attributeFilter: ['class'] });
126
+ }, 0);
127
+ }
128
+
129
+ private closeDropdowns(): void {
130
+ this.openDropdownProjects = false;
131
+ this.openStatusDropdownProjectId = null;
132
+ this.selectedProjectForStatus = null;
133
+ }
134
+
89
135
  subcribeToAuthStateChanged() {
90
136
  this.messagingAuthService.BSAuthStateChanged.subscribe((state) => {
91
137
  this.logger.log('[SIDEBAR-USER-DETAILS] BSAuthStateChanged ', state)
@@ -241,8 +287,10 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
241
287
  .set('LABEL_LOGOUT', text['LABEL_LOGOUT'])
242
288
  .set('SubscriptionPaymentProblem', text['SubscriptionPaymentProblem'])
243
289
  .set('ThePlanHasExpired', text['ThePlanHasExpired'])
290
+ .set('NAVBAR.RECENT_PROJECTS', text['NAVBAR.RECENT_PROJECTS'])
291
+ .set('NAVBAR.OTHER_PROJECTS', text['NAVBAR.OTHER_PROJECTS'])
244
292
 
245
- this.teammateStatus.forEach(element => {
293
+ this.TEAMMATE_STATUS.forEach(element => {
246
294
  element.label = this.translationsMap.get(element.label)
247
295
  });
248
296
 
@@ -256,12 +304,42 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
256
304
  this.logger.log('[SIDEBAR-USER-DETAILS] AppConfigService getAppConfig', this.appConfigProvider.getConfig());
257
305
 
258
306
  this.isVisiblePAY = getOSCode("PAY", this.public_Key);
307
+ this.isVisibleMT = getOSCode("MTT", this.public_Key);
308
+ this.isVisibleMPA = getOSCode("MPA", this.public_Key);
309
+ }
310
+
311
+ listenToUserGoOnline() {
312
+ this.events.subscribe('go:online', (isOnline: boolean) => {
313
+ this.logger.log('[SIDEBAR-USER-DETAILS] listen to go:online --> ', isOnline);
314
+ if (isOnline) {
315
+ this.tiledeskToken = this.tiledeskAuthService.getTiledeskToken();
316
+ this.getProjects();
317
+ }
318
+ });
319
+ }
320
+
321
+ getProjects() {
322
+ this.logger.log('[SIDEBAR-USER-DETAILS] calling getProjects ... ');
323
+ this.projectService.getProjects().subscribe((projects: ProjectUser[]) => {
324
+ this.logger.log('[SIDEBAR-USER-DETAILS] getProjects PROJECTS ', projects);
325
+ if (projects) {
326
+ this.projects = projects.filter((prj: ProjectUser) => prj?.id_project?.status === 100);
327
+ this.projects.forEach((prj: ProjectUser) => {
328
+ prj.teammateStatus = getUserStatusFromProjectUser(prj as any);
329
+ });
330
+ this.logger.log('[SIDEBAR-USER-DETAILS] getProjects this.projects ', this.projects);
331
+ }
332
+ }, (error) => {
333
+ this.logger.error('[SIDEBAR-USER-DETAILS] getProjects - ERROR ', error);
334
+ }, () => {
335
+ this.logger.log('[SIDEBAR-USER-DETAILS] getProjects - COMPLETE');
336
+ });
259
337
  }
260
338
 
261
339
  listenToCurrentStoredProject() {
262
340
  this.events.subscribe('storage:last_project', projectObjct => {
263
341
  if (projectObjct && projectObjct !== 'undefined') {
264
- // this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED PROJECT ', projectObjct)
342
+ this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED PROJECT ', projectObjct)
265
343
 
266
344
  //TODO: recuperare info da root e non da id_project
267
345
  this.project = {
@@ -269,9 +347,9 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
269
347
  name: projectObjct['id_project']['name'],
270
348
  profile: projectObjct['id_project']['profile'],
271
349
  isActiveSubscription: projectObjct['id_project']['isActiveSubscription'],
272
- trialExpired: projectObjct['id_project']['trialExpired']
350
+ trialExpired: projectObjct['id_project']['trialExpired'],
351
+ teammateStatus: getUserStatusFromProjectUser(projectObjct as any)
273
352
  }
274
-
275
353
  if (this.project.profile.type === 'free') {
276
354
 
277
355
  if (this.project.trialExpired === false) {
@@ -284,11 +362,19 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
284
362
  } else if (this.project.profile.type === 'payment' && this.project.profile.name === 'enterprise') {
285
363
  this.getEnterprisePlanTranslation();
286
364
  }
365
+
366
+ this.wsService.subscriptionToWsCurrentProjectUserAvailability(this.project._id, projectObjct._id);
367
+ if (this.tiledeskToken) {
368
+ this.getProjects();
369
+ }
287
370
  }
288
371
  })
289
372
 
290
373
  try {
291
374
  this.tiledeskToken = this.appStorageService.getItem('tiledeskToken');
375
+ if (this.tiledeskToken) {
376
+ this.getProjects();
377
+ }
292
378
  // this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', this.tiledeskToken)
293
379
  } catch (err) {
294
380
  this.logger.error('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', err)
@@ -325,19 +411,11 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
325
411
  this.logger.log('[SIDEBAR-USER-DETAILS] - $UBSC TO WS USER AVAILABILITY & BUSY STATUS RES ', projectUser);
326
412
 
327
413
  if (projectUser) {
328
- if (projectUser['user_available'] === false && projectUser['profileStatus'] === 'inactive') {
329
- // this.logger.log('teammateStatus ', this.teammateStatus)
330
- this.selectedStatus = this.teammateStatus[2].id;
331
- this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[2].name);
332
- this.teammateStatus = this.teammateStatus.slice(0)
333
- } else if (projectUser['user_available'] === false && (projectUser['profileStatus'] === '' || !projectUser['profileStatus'])) {
334
- this.selectedStatus = this.teammateStatus[1].id;
335
- this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[1].name);
336
- this.teammateStatus = this.teammateStatus.slice(0)
337
- } else if (projectUser['user_available'] === true && (projectUser['profileStatus'] === '' || !projectUser['profileStatus'])) {
338
- this.selectedStatus = this.teammateStatus[0].id
339
- this.teammateStatus = this.teammateStatus.slice(0)
340
- this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', this.teammateStatus[0].name);
414
+ const status = getUserStatusFromProjectUser(projectUser as any);
415
+ if (status) {
416
+ this.selectedStatus = status.id;
417
+ this.logger.debug('[SIDEBAR-USER-DETAILS] - PROFILE_STATUS selected option', status.name);
418
+ this.TEAMMATE_STATUS = this.TEAMMATE_STATUS.slice(0);
341
419
  }
342
420
  this.IS_BUSY = projectUser['isBusy']
343
421
  this.USER_ROLE = projectUser['role']
@@ -357,6 +435,118 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
357
435
  });
358
436
  }
359
437
 
438
+ getCurrentStatusAvatar(): string {
439
+ const status = this.TEAMMATE_STATUS?.find(s => s.id === this.selectedStatus);
440
+ return status?.avatar || 'assets/img/teammate-status/avaible.svg';
441
+ }
442
+
443
+ getCurrentStatusLabel(): string {
444
+ const status = this.TEAMMATE_STATUS?.find(s => s.id === this.selectedStatus);
445
+ return status?.label || status?.name || '';
446
+ }
447
+
448
+ toggleProjectsDropdown() {
449
+ this.openDropdownProjects = !this.openDropdownProjects;
450
+ if (!this.openDropdownProjects) {
451
+ this.openStatusDropdownProjectId = null;
452
+ this.selectedProjectForStatus = null;
453
+ }
454
+ }
455
+
456
+ openStatusDropdownOnHover(event: Event, prjct: any) {
457
+ this.cancelStatusDropdownClose();
458
+ const projectId = prjct?.id_project?._id;
459
+ const el = event.currentTarget as HTMLElement;
460
+ const rect = el.getBoundingClientRect();
461
+ this.statusDropdownPosition = {
462
+ top: rect.top,
463
+ left: rect.right + 10
464
+ };
465
+ this.selectedProjectForStatus = prjct;
466
+ this.openStatusDropdownProjectId = projectId;
467
+ }
468
+
469
+ closeStatusDropdownOnLeave() {
470
+ this.cancelStatusDropdownClose();
471
+ this.statusDropdownCloseTimeout = setTimeout(() => {
472
+ this.closeDropdowns();
473
+ this.statusDropdownCloseTimeout = null;
474
+ }, 150);
475
+ }
476
+
477
+ cancelStatusDropdownClose() {
478
+ if (this.statusDropdownCloseTimeout) {
479
+ clearTimeout(this.statusDropdownCloseTimeout);
480
+ this.statusDropdownCloseTimeout = null;
481
+ }
482
+ }
483
+
484
+ onChangeProjectStatus(projectUser: ProjectUser, selectedStatusID: any) {
485
+ this.logger.log('[SIDEBAR-USER-DETAILS] onChangeProjectStatus', projectUser, selectedStatusID)
486
+ this.openStatusDropdownProjectId = null
487
+ this.selectedProjectForStatus = null
488
+
489
+ let IS_AVAILABLE = null
490
+ let profilestatus = ''
491
+ if (selectedStatusID === 1) {
492
+ IS_AVAILABLE = true
493
+ } else if (selectedStatusID === 2) {
494
+ IS_AVAILABLE = false
495
+ } else if (selectedStatusID === 3) {
496
+ IS_AVAILABLE = false
497
+ profilestatus = 'inactive'
498
+ }
499
+
500
+ this.wsService.updateCurrentUserAvailability(this.tiledeskToken, projectUser.id_project._id, IS_AVAILABLE, profilestatus).subscribe((projectUserUpdated: any) => {
501
+
502
+ this.logger.log('[NAVBAR] - PROJECT-USER UPDATED ', projectUser)
503
+ this.projects.find(p => p.id_project._id === projectUser.id_project._id).teammateStatus = getUserStatusFromProjectUser(projectUserUpdated as any);
504
+
505
+ if(projectUser.id_project._id === this.project._id) {
506
+ this.project.teammateStatus = getUserStatusFromProjectUser(projectUserUpdated as any);
507
+ }
508
+ }, (error) => {
509
+ this.logger.error('[NAVBAR] - PROJECT-USER UPDATED - ERROR ', error);
510
+
511
+ }, () => {
512
+ this.logger.log('[NAVBAR] - PROJECT-USER UPDATED * COMPLETE *');
513
+
514
+ });
515
+ }
516
+
517
+ onStatusDropdownOptionClick(status: { id: number; name: string; avatar: string; label: string }, projectUser: ProjectUser | null) {
518
+ if (!projectUser) return;
519
+ this.changeProjectStatus(projectUser, status.id);
520
+ this.openStatusDropdownProjectId = null;
521
+ this.selectedProjectForStatus = null;
522
+ if (projectUser?.id_project?._id === this.project?._id) {
523
+ this.selectedStatus = status.id;
524
+ }
525
+ }
526
+
527
+ changeProjectStatus(projectUser: ProjectUser, selectedStatusID: number) {
528
+ this.logger.log('[SIDEBAR-USER-DETAILS] changeProjectStatus projectid', projectUser?.id_project?._id, ' status: ', selectedStatusID);
529
+ let IS_AVAILABLE: boolean | null = null;
530
+ let profilestatus = '';
531
+ if (selectedStatusID === 1) {
532
+ IS_AVAILABLE = true;
533
+ } else if (selectedStatusID === 2) {
534
+ IS_AVAILABLE = false;
535
+ } else if (selectedStatusID === 3) {
536
+ IS_AVAILABLE = false;
537
+ profilestatus = 'inactive';
538
+ }
539
+ this.wsService.updateCurrentUserAvailability(this.tiledeskToken, projectUser.id_project._id, IS_AVAILABLE, profilestatus).subscribe((updated: any) => {
540
+ this.logger.log('[SIDEBAR-USER-DETAILS] - PROJECT-USER UPDATED ', updated);
541
+ const p = this.projects.find(prj => prj?.id_project?._id === projectUser?.id_project?._id);
542
+ if (p) {
543
+ p.teammateStatus = getUserStatusFromProjectUser(updated as any);
544
+ }
545
+ }, (error) => {
546
+ this.logger.error('[SIDEBAR-USER-DETAILS] - PROJECT-USER UPDATED - ERROR ', error);
547
+ });
548
+ }
549
+
360
550
  changeAvailabilityStateInUserDetailsSidebar(selectedStatusID) {
361
551
  this.logger.log('[SIDEBAR-USER-DETAILS] - changeAvailabilityState projectid', this.project._id, ' available 1: ', selectedStatusID);
362
552