@chat21/chat21-ionic 3.4.32-rc4 → 3.4.32-rc5

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 CHANGED
@@ -8,6 +8,10 @@
8
8
  ### **Copyrigth**:
9
9
  *Tiledesk SRL*
10
10
 
11
+ # 3.4.32-rc5
12
+ - **added**: conversations-list — on init, fetches all projects via `getProjects` and stores them in AppStorageService under `all_projects`; before saving, checks that the key does not already contain each project (avoids duplicates).
13
+ - **changed**: conversations-list `onConversationLoaded` — project name and id are now resolved from the `all_projects` storage key instead of per-project localStorage entries.
14
+
11
15
  # 3.4.32-rc4
12
16
  - **changed**: unassigned conversations page — `onImageLoaded` and `onConversationLoaded` are now invoked for each conversation in the list (avatar URLs, last message formatting, project name).
13
17
  - **bug-fixed**: navbar project dropdown — descenders (letters like g, p, q) were being clipped; added `line-height: 1.4` and vertical padding to prevent clipping.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-ionic",
3
3
  "author": "Tiledesk SRL",
4
- "version": "3.4.32-rc4",
4
+ "version": "3.4.32-rc5",
5
5
  "license": "MIT License",
6
6
  "homepage": "https://tiledesk.com/",
7
7
  "repository": {
@@ -58,6 +58,8 @@ 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
60
 
61
+ const PROJECTS_STORAGE_KEY = 'all_projects';
62
+
61
63
  @Component({
62
64
  selector: 'app-conversations-list',
63
65
  templateUrl: './conversations-list.page.html',
@@ -142,6 +144,7 @@ export class ConversationListPage implements OnInit {
142
144
  public platform: Platform,
143
145
  public wsService: WebsocketService,
144
146
  public g: Globals,
147
+ public appStorageService: AppStorageService,
145
148
  ) {
146
149
  this.checkPlatform();
147
150
  this.translations();
@@ -215,8 +218,45 @@ export class ConversationListPage implements OnInit {
215
218
  // @ Lifehooks
216
219
  // -----------------------------------------------
217
220
  ngOnInit() {
218
- this.getAppConfigToHideDiplayBtns()
221
+ this.getAppConfigToHideDiplayBtns();
219
222
  this.getOSCODE();
223
+ this.loadAndStoreProjects();
224
+ }
225
+
226
+ /**
227
+ * Recupera tutti i progetti con getProjects e li salva in AppStorage.
228
+ * Prima di salvare verifica che la chiave non esista già e che non contenga già ogni singolo progetto.
229
+ */
230
+ private loadAndStoreProjects() {
231
+ const token = this.tiledeskAuthService.getTiledeskToken();
232
+ if (!token) return;
233
+ this.tiledeskService.getProjects(token).subscribe((projects: Project[]) => {
234
+ if (!projects?.length) return;
235
+ let projectsMap: Record<string, Project> = {};
236
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
237
+ if (stored) {
238
+ try {
239
+ projectsMap = JSON.parse(stored) || {};
240
+ } catch (e) {
241
+ this.logger.warn('[CONVS-LIST-PAGE] loadAndStoreProjects - failed to parse stored projects', e);
242
+ }
243
+ }
244
+ let hasChanges = false;
245
+ projects.forEach((project) => {
246
+ const projectId = project.id_project?._id || project.id_project?.id;
247
+ if (!projectId) return;
248
+ if (!projectsMap[projectId]) {
249
+ projectsMap[projectId] = project.id_project;
250
+ hasChanges = true;
251
+ }
252
+ });
253
+ if (hasChanges) {
254
+ this.appStorageService.setItem(PROJECTS_STORAGE_KEY, JSON.stringify(projectsMap));
255
+ this.logger.log('[CONVS-LIST-PAGE] loadAndStoreProjects - saved', Object.keys(projectsMap).length, 'projects');
256
+ }
257
+ },
258
+ (err) => this.logger.error('[CONVS-LIST-PAGE] loadAndStoreProjects - error', err)
259
+ );
220
260
  }
221
261
 
222
262
  ngOnChanges() {
@@ -862,22 +902,32 @@ export class ConversationListPage implements OnInit {
862
902
  }
863
903
  }
864
904
 
865
- if(conversation.attributes && conversation.attributes['projectId']){
866
- let project = localStorage.getItem(conversation.attributes['projectId'])
867
- if(project){
868
- project = JSON.parse(project)
869
- conversation.attributes.project_name = project['name']
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
- }
905
+ const project = this.getProjectFromStorage(conversation);
906
+ if (project) {
907
+ if (!conversation.attributes) conversation.attributes = {};
908
+ conversation.attributes.projectId = project._id;
909
+ conversation.attributes.project_name = project.name;
879
910
  }
911
+ }
880
912
 
913
+ /** Recupera il progetto dalla chiave di storage (all_projects) */
914
+ private getProjectFromStorage(conversation: ConversationModel): Project | null {
915
+ let projectId: string | undefined;
916
+ if (conversation.attributes?.['projectId']) {
917
+ projectId = conversation.attributes['projectId'];
918
+ } else if (conversation.attributes) {
919
+ projectId = getProjectIdSelectedConversation(conversation.uid);
920
+ }
921
+ if (!projectId) return null;
922
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
923
+ this.logger.log('[CONVS-LIST-PAGE] getProjectFromStorage - stored', stored);
924
+ if (!stored) return null;
925
+ try {
926
+ const projectsMap: Record<string, Project> = JSON.parse(stored);
927
+ return projectsMap[projectId] || null;
928
+ } catch {
929
+ return null;
930
+ }
881
931
  }
882
932
 
883
933
  // isMarkdownLink(last_message_text) {
@@ -13,6 +13,9 @@ import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk
13
13
  import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
14
14
  import { getProjectIdSelectedConversation, isGroup } from 'src/chat21-core/utils/utils';
15
15
  import { ImageRepoService } from 'src/chat21-core/providers/abstract/image-repo.service';
16
+ import { Project } from 'src/chat21-core/models/projects';
17
+
18
+ const PROJECTS_STORAGE_KEY = 'all_projects';
16
19
 
17
20
 
18
21
  @Component({
@@ -56,7 +59,8 @@ export class UnassignedConversationsPage implements OnInit, OnChanges {
56
59
  private events: EventsService,
57
60
  private tiledeskAuthService: TiledeskAuthService,
58
61
  private tiledeskService: TiledeskService,
59
- public imageRepoService: ImageRepoService
62
+ public imageRepoService: ImageRepoService,
63
+ public appStorageService: AppStorageService,
60
64
  ) {
61
65
  if (this.tiledeskAuthService.getCurrentUser()) {
62
66
  this.loggedUserUid = this.tiledeskAuthService.getCurrentUser().uid;
@@ -81,6 +85,7 @@ export class UnassignedConversationsPage implements OnInit, OnChanges {
81
85
  }
82
86
  this.logger.log('[UNASSIGNED-CONVS-PAGE] unassignedConversationsList', this.unassignedConversationsList);
83
87
  this.processConversationsForDisplay();
88
+ this.loadAndStoreProjects();
84
89
  // this.buildIFRAME();
85
90
  this.listenToPostMsg();
86
91
  this.hideHotjarFeedbackBtn();
@@ -107,6 +112,72 @@ export class UnassignedConversationsPage implements OnInit, OnChanges {
107
112
  });
108
113
  }
109
114
 
115
+ /**
116
+ * Recupera tutti i progetti con getProjects e li salva in AppStorage.
117
+ * Se la chiave esiste già nello storage, salta la chiamata remota e usa i dati in cache.
118
+ * Al termine richiama processConversationsForDisplay per aggiornare i project_name.
119
+ */
120
+ private loadAndStoreProjects() {
121
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
122
+ if (stored) {
123
+ this.processConversationsForDisplay();
124
+ return;
125
+ }
126
+ const token = this.tiledeskAuthService.getTiledeskToken();
127
+ if (!token) return;
128
+ this.tiledeskService.getProjects(token).subscribe(
129
+ (projects: Project[]) => {
130
+ if (!projects?.length) return;
131
+ let projectsMap: Record<string, Project> = {};
132
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
133
+ if (stored) {
134
+ try {
135
+ projectsMap = JSON.parse(stored) || {};
136
+ } catch (e) {
137
+ this.logger.warn('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - failed to parse stored projects', e);
138
+ }
139
+ }
140
+ let hasChanges = false;
141
+ projects.forEach((project) => {
142
+ const projectId = project.id_project?._id || project.id_project?.id || project._id;
143
+ if (!projectId) return;
144
+ if (!projectsMap[projectId]) {
145
+ projectsMap[projectId] = project.id_project || project;
146
+ hasChanges = true;
147
+ }
148
+ });
149
+ if (hasChanges) {
150
+ this.appStorageService.setItem(PROJECTS_STORAGE_KEY, JSON.stringify(projectsMap));
151
+ this.logger.log('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - saved', Object.keys(projectsMap).length, 'projects');
152
+ }
153
+ this.processConversationsForDisplay();
154
+ },
155
+ (err) => {
156
+ this.logger.error('[UNASSIGNED-CONVS-PAGE] loadAndStoreProjects - error', err);
157
+ this.processConversationsForDisplay();
158
+ }
159
+ );
160
+ }
161
+
162
+ /** Recupera il progetto dalla chiave di storage (all_projects); se non trovato restituisce null */
163
+ private getProjectFromStorage(conversation: ConversationModel): Project | null {
164
+ let projectId: string | undefined;
165
+ if (conversation.attributes?.['projectId']) {
166
+ projectId = conversation.attributes['projectId'];
167
+ } else if (conversation.attributes) {
168
+ projectId = getProjectIdSelectedConversation(conversation.uid);
169
+ }
170
+ if (!projectId) return null;
171
+ const stored = this.appStorageService.getItem(PROJECTS_STORAGE_KEY);
172
+ if (!stored) return null;
173
+ try {
174
+ const projectsMap: Record<string, Project> = JSON.parse(stored);
175
+ return projectsMap[projectId] || null;
176
+ } catch {
177
+ return null;
178
+ }
179
+ }
180
+
110
181
  hideHotjarFeedbackBtn() {
111
182
  const hotjarFeedbackBtn = <HTMLElement>document.querySelector("#_hj_feedback_container > div > button")
112
183
  if (hotjarFeedbackBtn) {
@@ -370,22 +441,12 @@ export class UnassignedConversationsPage implements OnInit, OnChanges {
370
441
  }
371
442
  }
372
443
 
373
- if(conversation.attributes && conversation.attributes['projectId']){
374
- let project = localStorage.getItem(conversation.attributes['projectId'])
375
- if(project){
376
- project = JSON.parse(project)
377
- conversation.attributes.project_name = project['name']
378
- }
379
- }else if(conversation.attributes){
380
- const projectId = getProjectIdSelectedConversation(conversation.uid)
381
- let project = localStorage.getItem(projectId)
382
- if(project){
383
- project = JSON.parse(project)
384
- conversation.attributes.projectId = project['_id']
385
- conversation.attributes.project_name = project['name']
386
- }
444
+ const project = this.getProjectFromStorage(conversation);
445
+ if (project) {
446
+ if (!conversation.attributes) conversation.attributes = {};
447
+ conversation.attributes.projectId = project._id;
448
+ conversation.attributes.project_name = project.name;
387
449
  }
388
-
389
450
  }
390
451
 
391
452
  async onClose(conversation?: ConversationModel) {
@@ -7,6 +7,8 @@ import { map } from 'rxjs/operators';
7
7
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
8
8
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
9
9
  import { AppStorageService } from 'src/chat21-core/providers/abstract/app-storage.service';
10
+ import { Project } from 'src/chat21-core/models/projects';
11
+ import { Observable } from 'rxjs';
10
12
 
11
13
 
12
14
  @Injectable({
@@ -93,6 +95,39 @@ export class TiledeskService {
93
95
  }))
94
96
  }
95
97
 
98
+ public getProjects(token: string): Observable<Project[]> {
99
+ const url = this.SERVER_BASE_URL + 'projects/';
100
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECTS URL', url);
101
+
102
+ const httpOptions = {
103
+ headers: new HttpHeaders({
104
+ 'Content-Type': 'application/json',
105
+ Authorization: token
106
+ })
107
+ };
108
+
109
+ return this.http.get(url, httpOptions).pipe(map((projects: Project[]) => {
110
+ this.logger.log('[TILEDESK-SERVICE] GET PROJECTS - RES ', projects);
111
+ return projects
112
+ }))
113
+ }
114
+
115
+ public getProjectUsersByProjectId(project_id: string) {
116
+ const url = this.SERVER_BASE_URL + project_id + '/project_users/';
117
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER URL', url);
118
+
119
+ const httpOptions = {
120
+ headers: new HttpHeaders({
121
+ 'Content-Type': 'application/json',
122
+ Authorization: this.tiledeskToken
123
+ })
124
+ };
125
+ return this.http.get(url, httpOptions).pipe(map((res: any) => {
126
+ this.logger.log('[TILEDESK-SERVICE] - GET PROJECT-USER RES ', res);
127
+ return res
128
+ }))
129
+ }
130
+
96
131
  public getAllLeadsActiveWithLimit(project_id: string, limit: number) {
97
132
  const url = this.SERVER_BASE_URL + project_id + '/leads?limit=' + limit + '&with_fullname=true';
98
133
  this.logger.log('[TILEDESK-SERVICE] - GET ALL ACTIVE LEADS (LIMIT 10000) - URL', url);