@chat21/chat21-ionic 3.4.32-rc1 → 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.
- package/CHANGELOG.md +40 -0
- package/package.json +1 -1
- package/src/app/components/navbar/navbar.component.scss +7 -1
- package/src/app/components/project-item/project-item.component.ts +0 -1
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +51 -10
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.scss +304 -17
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +202 -5
- package/src/app/pages/conversations-list/conversations-list.page.ts +69 -15
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.html +7 -5
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.scss +15 -0
- package/src/app/pages/unassigned-conversations/unassigned-conversations.page.ts +171 -10
- package/src/app/pipe/filter.pipe.spec.ts +8 -0
- package/src/app/pipe/filter.pipe.ts +15 -0
- package/src/app/pipe/find.pipe.spec.ts +8 -0
- package/src/app/pipe/find.pipe.ts +15 -0
- package/src/app/services/tiledesk/tiledesk.service.ts +19 -0
- package/src/app/services/triggerEvents/triggerEvents.ts +12 -0
- package/src/app/services/websocket/websocket.service.ts +9 -5
- package/src/app/shared/shared.module.ts +22 -15
- package/src/chat21-core/models/projects.ts +1 -0
- package/src/chat21-core/utils/constants.ts +2 -1
- package/src/chat21-core/utils/convertRequestToConversation.ts +1 -1
|
@@ -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';
|
|
@@ -17,12 +17,14 @@ 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
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';
|
|
20
22
|
@Component({
|
|
21
23
|
selector: 'app-sidebar-user-details',
|
|
22
24
|
templateUrl: './sidebar-user-details.component.html',
|
|
23
25
|
styleUrls: ['./sidebar-user-details.component.scss'],
|
|
24
26
|
})
|
|
25
|
-
export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
27
|
+
export class SidebarUserDetailsComponent implements OnInit, OnChanges, OnDestroy {
|
|
26
28
|
// HAS_CLICKED_OPEN_USER_DETAIL: boolean = false;
|
|
27
29
|
// @Output() onCloseUserDetailsSidebar = new EventEmitter();
|
|
28
30
|
|
|
@@ -55,6 +57,15 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
55
57
|
selectedStatus: any;
|
|
56
58
|
TEAMMATE_STATUS = TEAMMATE_STATUS;
|
|
57
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;
|
|
58
69
|
|
|
59
70
|
translationsMap: Map<string, string> = new Map();
|
|
60
71
|
|
|
@@ -71,7 +82,7 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
71
82
|
public appConfigProvider: AppConfigProvider,
|
|
72
83
|
public events: EventsService,
|
|
73
84
|
private eRef: ElementRef,
|
|
74
|
-
|
|
85
|
+
private projectService: ProjectService,
|
|
75
86
|
) { }
|
|
76
87
|
|
|
77
88
|
ngOnInit() {
|
|
@@ -80,11 +91,47 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
80
91
|
this.subcribeToAuthStateChanged();
|
|
81
92
|
this.listenTocurrentProjectUserUserAvailability$();
|
|
82
93
|
this.listenToCurrentStoredProject();
|
|
94
|
+
this.listenToUserGoOnline();
|
|
83
95
|
this.getOSCODE();
|
|
96
|
+
this.setupUserDetailsCloseObserver();
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
ngOnChanges() { }
|
|
87
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
|
+
|
|
88
135
|
subcribeToAuthStateChanged() {
|
|
89
136
|
this.messagingAuthService.BSAuthStateChanged.subscribe((state) => {
|
|
90
137
|
this.logger.log('[SIDEBAR-USER-DETAILS] BSAuthStateChanged ', state)
|
|
@@ -240,6 +287,8 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
240
287
|
.set('LABEL_LOGOUT', text['LABEL_LOGOUT'])
|
|
241
288
|
.set('SubscriptionPaymentProblem', text['SubscriptionPaymentProblem'])
|
|
242
289
|
.set('ThePlanHasExpired', text['ThePlanHasExpired'])
|
|
290
|
+
.set('NAVBAR.RECENT_PROJECTS', text['NAVBAR.RECENT_PROJECTS'])
|
|
291
|
+
.set('NAVBAR.OTHER_PROJECTS', text['NAVBAR.OTHER_PROJECTS'])
|
|
243
292
|
|
|
244
293
|
this.TEAMMATE_STATUS.forEach(element => {
|
|
245
294
|
element.label = this.translationsMap.get(element.label)
|
|
@@ -255,6 +304,36 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
255
304
|
this.logger.log('[SIDEBAR-USER-DETAILS] AppConfigService getAppConfig', this.appConfigProvider.getConfig());
|
|
256
305
|
|
|
257
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
|
+
});
|
|
258
337
|
}
|
|
259
338
|
|
|
260
339
|
listenToCurrentStoredProject() {
|
|
@@ -268,9 +347,9 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
268
347
|
name: projectObjct['id_project']['name'],
|
|
269
348
|
profile: projectObjct['id_project']['profile'],
|
|
270
349
|
isActiveSubscription: projectObjct['id_project']['isActiveSubscription'],
|
|
271
|
-
trialExpired: projectObjct['id_project']['trialExpired']
|
|
350
|
+
trialExpired: projectObjct['id_project']['trialExpired'],
|
|
351
|
+
teammateStatus: getUserStatusFromProjectUser(projectObjct as any)
|
|
272
352
|
}
|
|
273
|
-
|
|
274
353
|
if (this.project.profile.type === 'free') {
|
|
275
354
|
|
|
276
355
|
if (this.project.trialExpired === false) {
|
|
@@ -285,11 +364,17 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
285
364
|
}
|
|
286
365
|
|
|
287
366
|
this.wsService.subscriptionToWsCurrentProjectUserAvailability(this.project._id, projectObjct._id);
|
|
367
|
+
if (this.tiledeskToken) {
|
|
368
|
+
this.getProjects();
|
|
369
|
+
}
|
|
288
370
|
}
|
|
289
371
|
})
|
|
290
372
|
|
|
291
373
|
try {
|
|
292
374
|
this.tiledeskToken = this.appStorageService.getItem('tiledeskToken');
|
|
375
|
+
if (this.tiledeskToken) {
|
|
376
|
+
this.getProjects();
|
|
377
|
+
}
|
|
293
378
|
// this.logger.log('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', this.tiledeskToken)
|
|
294
379
|
} catch (err) {
|
|
295
380
|
this.logger.error('[SIDEBAR-USER-DETAILS] - GET STORED TOKEN ', err)
|
|
@@ -350,6 +435,118 @@ export class SidebarUserDetailsComponent implements OnInit, OnChanges {
|
|
|
350
435
|
});
|
|
351
436
|
}
|
|
352
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
|
+
|
|
353
550
|
changeAvailabilityStateInUserDetailsSidebar(selectedStatusID) {
|
|
354
551
|
this.logger.log('[SIDEBAR-USER-DETAILS] - changeAvailabilityState projectid', this.project._id, ' available 1: ', selectedStatusID);
|
|
355
552
|
|
|
@@ -57,6 +57,9 @@ import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
|
57
57
|
import { PERMISSIONS } from 'src/app/utils/permissions.constants';
|
|
58
58
|
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
59
59
|
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
60
|
+
import { ProjectService } from 'src/app/services/projects/project.service';
|
|
61
|
+
|
|
62
|
+
import { PROJECTS_STORAGE_KEY } from 'src/chat21-core/utils/constants';
|
|
60
63
|
|
|
61
64
|
@Component({
|
|
62
65
|
selector: 'app-conversations-list',
|
|
@@ -138,10 +141,13 @@ export class ConversationListPage implements OnInit {
|
|
|
138
141
|
public tiledeskService: TiledeskService,
|
|
139
142
|
public tiledeskAuthService: TiledeskAuthService,
|
|
140
143
|
public projectUsersService: ProjectUsersService,
|
|
144
|
+
public projectService: ProjectService,
|
|
141
145
|
public appConfigProvider: AppConfigProvider,
|
|
142
146
|
public platform: Platform,
|
|
143
147
|
public wsService: WebsocketService,
|
|
144
148
|
public g: Globals,
|
|
149
|
+
public appStorageService: AppStorageService,
|
|
150
|
+
private triggerEvents: TriggerEvents,
|
|
145
151
|
) {
|
|
146
152
|
this.checkPlatform();
|
|
147
153
|
this.translations();
|
|
@@ -215,8 +221,45 @@ export class ConversationListPage implements OnInit {
|
|
|
215
221
|
// @ Lifehooks
|
|
216
222
|
// -----------------------------------------------
|
|
217
223
|
ngOnInit() {
|
|
218
|
-
this.getAppConfigToHideDiplayBtns()
|
|
224
|
+
this.getAppConfigToHideDiplayBtns();
|
|
219
225
|
this.getOSCODE();
|
|
226
|
+
this.loadAndStoreProjects();
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Recupera tutti i progetti con getProjects e li salva in AppStorage.
|
|
231
|
+
* Prima di salvare verifica che la chiave non esista già e che non contenga già ogni singolo progetto.
|
|
232
|
+
*/
|
|
233
|
+
private loadAndStoreProjects() {
|
|
234
|
+
const token = this.tiledeskAuthService.getTiledeskToken();
|
|
235
|
+
if (!token) return;
|
|
236
|
+
this.projectService.getProjects().subscribe((projects: Project[]) => {
|
|
237
|
+
if (!projects?.length) return;
|
|
238
|
+
let projectsMap: Record<string, Project> = {};
|
|
239
|
+
const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
|
|
240
|
+
if (stored) {
|
|
241
|
+
try {
|
|
242
|
+
projectsMap = JSON.parse(stored) || {};
|
|
243
|
+
} catch (e) {
|
|
244
|
+
this.logger.warn('[CONVS-LIST-PAGE] loadAndStoreProjects - failed to parse stored projects', e);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
let hasChanges = false;
|
|
248
|
+
projects.forEach((project) => {
|
|
249
|
+
const projectId = project.id_project?._id || project.id_project?.id;
|
|
250
|
+
if (!projectId) return;
|
|
251
|
+
if (!projectsMap[projectId]) {
|
|
252
|
+
projectsMap[projectId] = project.id_project;
|
|
253
|
+
hasChanges = true;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
if (hasChanges) {
|
|
257
|
+
this.appStorageService.setItem(PROJECTS_STORAGE_KEY, JSON.stringify(projectsMap));
|
|
258
|
+
this.logger.log('[CONVS-LIST-PAGE] loadAndStoreProjects - saved', Object.keys(projectsMap).length, 'projects');
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
(err) => this.logger.error('[CONVS-LIST-PAGE] loadAndStoreProjects - error', err)
|
|
262
|
+
);
|
|
220
263
|
}
|
|
221
264
|
|
|
222
265
|
ngOnChanges() {
|
|
@@ -795,6 +838,7 @@ export class ConversationListPage implements OnInit {
|
|
|
795
838
|
this.logger.log('[CONVS-LIST-PAGE] onConversationSelected active conversation.uid ', conversation.uid)
|
|
796
839
|
this.events.publish('convList:onConversationSelected', conversation)
|
|
797
840
|
}
|
|
841
|
+
this.triggerEvents.triggerOnConversationChanged(conversation)
|
|
798
842
|
}
|
|
799
843
|
|
|
800
844
|
onImageLoaded(conversation: any) {
|
|
@@ -862,22 +906,32 @@ export class ConversationListPage implements OnInit {
|
|
|
862
906
|
}
|
|
863
907
|
}
|
|
864
908
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
if(
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}
|
|
871
|
-
}else if(conversation.attributes){
|
|
872
|
-
const projectId = getProjectIdSelectedConversation(conversation.uid)
|
|
873
|
-
let project = localStorage.getItem(projectId)
|
|
874
|
-
if(project){
|
|
875
|
-
project = JSON.parse(project)
|
|
876
|
-
conversation.attributes.projectId = project['_id']
|
|
877
|
-
conversation.attributes.project_name = project['name']
|
|
878
|
-
}
|
|
909
|
+
const project = this.getProjectFromStorage(conversation);
|
|
910
|
+
if (project) {
|
|
911
|
+
if (!conversation.attributes) conversation.attributes = {};
|
|
912
|
+
conversation.attributes.projectId = project._id;
|
|
913
|
+
conversation.attributes.project_name = project.name;
|
|
879
914
|
}
|
|
915
|
+
}
|
|
880
916
|
|
|
917
|
+
/** Recupera il progetto dalla chiave di storage (all_projects) */
|
|
918
|
+
private getProjectFromStorage(conversation: ConversationModel): Project | null {
|
|
919
|
+
let projectId: string | undefined;
|
|
920
|
+
if (conversation.attributes?.['projectId']) {
|
|
921
|
+
projectId = conversation.attributes['projectId'];
|
|
922
|
+
} else if (conversation.attributes) {
|
|
923
|
+
projectId = getProjectIdSelectedConversation(conversation.uid);
|
|
924
|
+
}
|
|
925
|
+
if (!projectId) return null;
|
|
926
|
+
const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
|
|
927
|
+
this.logger.log('[CONVS-LIST-PAGE] getProjectFromStorage - stored', stored);
|
|
928
|
+
if (!stored) return null;
|
|
929
|
+
try {
|
|
930
|
+
const projectsMap: Record<string, Project> = JSON.parse(stored);
|
|
931
|
+
return projectsMap[projectId] || null;
|
|
932
|
+
} catch {
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
881
935
|
}
|
|
882
936
|
|
|
883
937
|
// isMarkdownLink(last_message_text) {
|
|
@@ -40,11 +40,13 @@
|
|
|
40
40
|
</ion-list-conversations>
|
|
41
41
|
</ng-container>
|
|
42
42
|
<ng-template #noConvs>
|
|
43
|
-
<
|
|
44
|
-
<ion-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
<div class="no-convs-container">
|
|
44
|
+
<ion-item id="no-convs" class="ion-text-center" lines="none">
|
|
45
|
+
<ion-label class="ion-text-wrap" color="medium">
|
|
46
|
+
{{ 'LABEL_MSG_PUSH_START_CHAT' | translate }}
|
|
47
|
+
</ion-label>
|
|
48
|
+
</ion-item>
|
|
49
|
+
</div>
|
|
48
50
|
</ng-template>
|
|
49
51
|
</ion-list>
|
|
50
52
|
</div>
|
|
@@ -233,3 +233,18 @@ ion-content::part(scroll) {
|
|
|
233
233
|
min-height: calc(100vh - var(--header-height, 56px));
|
|
234
234
|
height: 100%;
|
|
235
235
|
}
|
|
236
|
+
|
|
237
|
+
// -------------------------------------------------
|
|
238
|
+
// Empty state - label centrata nell'altezza disponibile
|
|
239
|
+
// -------------------------------------------------
|
|
240
|
+
.no-convs-container {
|
|
241
|
+
display: flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
justify-content: center;
|
|
244
|
+
min-height: calc(100vh - var(--header-height, 56px));
|
|
245
|
+
width: 100%;
|
|
246
|
+
|
|
247
|
+
ion-item {
|
|
248
|
+
--background: transparent;
|
|
249
|
+
}
|
|
250
|
+
}
|