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

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,16 @@
8
8
  ### **Copyrigth**:
9
9
  *Tiledesk SRL*
10
10
 
11
+ # 3.4.32-rc4
12
+ - **changed**: unassigned conversations page — `onImageLoaded` and `onConversationLoaded` are now invoked for each conversation in the list (avatar URLs, last message formatting, project name).
13
+ - **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.
14
+
15
+ # 3.4.32-rc3
16
+ - **bug-fixed**: unassigned conversations list was reset on each WebSocket subscription; conversations from other projects were lost when subscribing to multiple online projects. Added `skipClear` parameter to `subscriptionToWsConversations` so the list is cleared only once when subscribing to all online projects.
17
+ - **changed**: unassigned conversations empty state — centered the "no conversations" label both vertically and horizontally within the full viewport height.
18
+
19
+ # 3.4.32-rc2
20
+
11
21
  # 3.4.32-rc1
12
22
  - **added**: ability to change availability status for each project the logged-in user belongs to.
13
23
  - **changed**: unserved-request.page refactor html and ts refactor
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-rc1",
4
+ "version": "3.4.32-rc4",
5
5
  "license": "MIT License",
6
6
  "homepage": "https://tiledesk.com/",
7
7
  "repository": {
@@ -94,12 +94,18 @@ ion-navbar{
94
94
  overflow: hidden;
95
95
  text-overflow: ellipsis;
96
96
  font-family: var(--header-font-family);
97
-
97
+ line-height: 1.4;
98
+
98
99
  .material-icons{
99
100
  font-size: 20px;
100
101
  }
101
102
  }
102
103
 
104
+ button.btn.project-dropdown {
105
+ padding-top: 4px;
106
+ padding-bottom: 4px;
107
+ }
108
+
103
109
  li{
104
110
  position: relative;
105
111
  display: block
@@ -16,7 +16,6 @@ import { ConvertRequestToConversation } from 'src/chat21-core/utils/convertReque
16
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
- import { Project } from 'src/chat21-core/models/projects';
20
19
 
21
20
  @Component({
22
21
  selector: 'app-project-item',
@@ -40,11 +40,13 @@
40
40
  </ion-list-conversations>
41
41
  </ng-container>
42
42
  <ng-template #noConvs>
43
- <ion-item id="no-convs" class="ion-text-center" lines="none">
44
- <ion-label class="ion-text-wrap" color="medium">
45
- {{ 'LABEL_MSG_PUSH_START_CHAT' | translate }}
46
- </ion-label>
47
- </ion-item>
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
+ }
@@ -1,4 +1,4 @@
1
- import { Component, Input, OnInit, SecurityContext } from '@angular/core';
1
+ import { Component, Input, OnChanges, OnInit, SecurityContext, SimpleChanges } from '@angular/core';
2
2
  import { AlertController, ModalController } from '@ionic/angular';
3
3
  import { Router } from '@angular/router';
4
4
  import { NavProxyService } from 'src/app/services/nav-proxy.service';
@@ -11,6 +11,8 @@ import { EventsService } from 'src/app/services/events-service';
11
11
  import { ConversationModel } from 'src/chat21-core/models/conversation';
12
12
  import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
13
13
  import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
14
+ import { getProjectIdSelectedConversation, isGroup } from 'src/chat21-core/utils/utils';
15
+ import { ImageRepoService } from 'src/chat21-core/providers/abstract/image-repo.service';
14
16
 
15
17
 
16
18
  @Component({
@@ -18,7 +20,7 @@ import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
18
20
  templateUrl: './unassigned-conversations.page.html',
19
21
  styleUrls: ['./unassigned-conversations.page.scss'],
20
22
  })
21
- export class UnassignedConversationsPage implements OnInit {
23
+ export class UnassignedConversationsPage implements OnInit, OnChanges {
22
24
 
23
25
  @Input() iframe_URL: any;
24
26
  @Input() callerBtn: string;
@@ -35,6 +37,7 @@ export class UnassignedConversationsPage implements OnInit {
35
37
  // @Input() unassigned_convs_url: any;
36
38
 
37
39
  iframe_url_sanitized: any;
40
+ private loggedUserUid: string;
38
41
  private logger: LoggerService = LoggerInstance.getInstance();
39
42
  // has_loaded: boolean;
40
43
  ion_content: any;
@@ -52,8 +55,13 @@ export class UnassignedConversationsPage implements OnInit {
52
55
  private translateService: CustomTranslateService,
53
56
  private events: EventsService,
54
57
  private tiledeskAuthService: TiledeskAuthService,
55
- private tiledeskService: TiledeskService
56
- ) { }
58
+ private tiledeskService: TiledeskService,
59
+ public imageRepoService: ImageRepoService
60
+ ) {
61
+ if (this.tiledeskAuthService.getCurrentUser()) {
62
+ this.loggedUserUid = this.tiledeskAuthService.getCurrentUser().uid;
63
+ }
64
+ }
57
65
 
58
66
  ngOnInit() {
59
67
  const keys = [
@@ -63,6 +71,7 @@ export class UnassignedConversationsPage implements OnInit {
63
71
  'LABEL_MSG_PUSH_START_CHAT'
64
72
  ];
65
73
  this.translationMap = this.translateService.translateLanguage(keys);
74
+
66
75
  this.unassignedConversationsList = this.unassignedConversations ?? [];
67
76
  if (!this.stylesMap) {
68
77
  this.stylesMap = new Map([['themeColor', '#165CEE']]);
@@ -71,16 +80,33 @@ export class UnassignedConversationsPage implements OnInit {
71
80
  this.translationMapConversation = this.translateService.translateLanguage(['CLOSED', 'Resolve']);
72
81
  }
73
82
  this.logger.log('[UNASSIGNED-CONVS-PAGE] unassignedConversationsList', this.unassignedConversationsList);
83
+ this.processConversationsForDisplay();
74
84
  // this.buildIFRAME();
75
85
  this.listenToPostMsg();
76
86
  this.hideHotjarFeedbackBtn();
77
87
  this.events.subscribe('style', (data)=>this.loadStyle(data))
78
88
  }
79
89
 
90
+ ngOnChanges(changes: SimpleChanges) {
91
+ if (changes['unassignedConversations'] && changes['unassignedConversations'].currentValue) {
92
+ this.unassignedConversationsList = this.unassignedConversations ?? [];
93
+ this.processConversationsForDisplay();
94
+ }
95
+ }
96
+
80
97
  ngOnDestroy(){
81
98
  this.logger.log('[UNASSIGNED-CONVS-PAGE] - onDestroy called', this.iframe_URL);
82
99
  }
83
100
 
101
+ /** Chiama onImageLoaded e onConversationLoaded per ogni conversazione in lista */
102
+ private processConversationsForDisplay() {
103
+ if (!this.unassignedConversationsList?.length) return;
104
+ this.unassignedConversationsList.forEach((conv) => {
105
+ this.onImageLoaded(conv);
106
+ this.onConversationLoaded(conv);
107
+ });
108
+ }
109
+
84
110
  hideHotjarFeedbackBtn() {
85
111
  const hotjarFeedbackBtn = <HTMLElement>document.querySelector("#_hj_feedback_container > div > button")
86
112
  if (hotjarFeedbackBtn) {
@@ -165,8 +191,7 @@ export class UnassignedConversationsPage implements OnInit {
165
191
  }, {
166
192
  text: 'Ok',
167
193
  handler: () => {
168
- let user = this.tiledeskAuthService.getCurrentUser();
169
- this.tiledeskService.addParticipant(request.uid, user.uid, request.attributes.projectId).subscribe((res: any) => {
194
+ this.tiledeskService.addParticipant(request.uid, this.loggedUserUid, request.attributes.projectId).subscribe((res: any) => {
170
195
  this.logger.log('[APP-COMP] addParticipant - RES ', res);
171
196
  this.onClose(request);
172
197
  }, (error) => {
@@ -280,12 +305,87 @@ export class UnassignedConversationsPage implements OnInit {
280
305
  this.presentAlertConfirmJoinRequest(conversation)
281
306
  }
282
307
 
283
- onImageLoaded(conversation: ConversationModel) {
284
- this.logger.log('[UNASSIGNED-CONVS-PAGE] onImageLoaded', conversation);
308
+ onImageLoaded(conversation: any) {
309
+ // this.logger.log('[CONVS-LIST-PAGE] onImageLoaded', conversation)
310
+ let conversation_with_fullname = conversation.sender_fullname
311
+ let conversation_with = conversation.sender
312
+ if (conversation.sender === this.loggedUserUid) {
313
+ conversation_with = conversation.recipient
314
+ conversation_with_fullname = conversation.recipient_fullname
315
+ } else if (isGroup(conversation)) {
316
+ // conversation_with_fullname = conv.sender_fullname;
317
+ // conv.last_message_text = conv.last_message_text;
318
+ conversation_with = conversation.recipient
319
+ conversation_with_fullname = conversation.recipient_fullname
320
+ }
321
+ if (!conversation_with.startsWith('support-group')) {
322
+ conversation.image = this.imageRepoService.getImagePhotoUrl(conversation_with)
323
+ }
285
324
  }
286
325
 
287
326
  onConversationLoaded(conversation: ConversationModel) {
288
- this.logger.log('[UNASSIGNED-CONVS-PAGE] onConversationLoaded', conversation);
327
+ this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded ', conversation)
328
+ // this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded is new? ', conversation.is_new)
329
+ // if (conversation.is_new === false) {
330
+ // this.ionContentConvList.scrollToTop(0);
331
+ // }
332
+
333
+ const keys = ['YOU', 'SENT_AN_IMAGE', 'SENT_AN_ATTACHMENT']
334
+ const translationMap = this.translateService.translateLanguage(keys)
335
+ // Fixes the bug: if a snippet of code is pasted and sent it is not displayed correctly in the convesations list
336
+
337
+ var regex = /<br\s*[\/]?>/gi
338
+ if (conversation ) { //&& conversation.last_message_text
339
+ conversation.last_message_text = conversation.last_message_text.replace(regex, '',)
340
+
341
+ //FIX-BUG: 'YOU: YOU: YOU: text' on last-message-text in conversation-list
342
+ if (conversation.sender === this.loggedUserUid && !conversation.last_message_text.includes(': ')) {
343
+ // this.logger.log('[CONVS-LIST-PAGE] onConversationLoaded', conversation)
344
+
345
+ if (conversation.type !== 'image' && conversation.type !== 'file') {
346
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + conversation.last_message_text
347
+ } else if (conversation.type === 'image') {
348
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT AN IMAGE');
349
+ // this.logger.log("[CONVS-LIST-PAGE] translationMap.get('YOU')")
350
+ const SENT_AN_IMAGE = (conversation['last_message_text'] = translationMap.get('SENT_AN_IMAGE'))
351
+
352
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + SENT_AN_IMAGE
353
+ } else if (conversation.type === 'file') {
354
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT FILE')
355
+ const SENT_AN_ATTACHMENT = (conversation['last_message_text'] = translationMap.get('SENT_AN_ATTACHMENT'))
356
+ conversation.last_message_text = translationMap.get('YOU') + ': ' + SENT_AN_ATTACHMENT
357
+ }
358
+ } else {
359
+ if (conversation.type === 'image') {
360
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT AN IMAGE');
361
+ // this.logger.log("[CONVS-LIST-PAGE] translationMap.get('YOU')")
362
+ const SENT_AN_IMAGE = (conversation['last_message_text'] = translationMap.get('SENT_AN_IMAGE'))
363
+
364
+ conversation.last_message_text = SENT_AN_IMAGE
365
+ } else if (conversation.type === 'file') {
366
+ // this.logger.log('[CONVS-LIST-PAGE] HAS SENT FILE')
367
+ const SENT_AN_ATTACHMENT = (conversation['last_message_text'] = translationMap.get('SENT_AN_ATTACHMENT'))
368
+ conversation.last_message_text = SENT_AN_ATTACHMENT
369
+ }
370
+ }
371
+ }
372
+
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
+ }
387
+ }
388
+
289
389
  }
290
390
 
291
391
  async onClose(conversation?: ConversationModel) {
@@ -94,16 +94,20 @@ export class WebsocketService {
94
94
  * Sottoscrive alle conversations di un singolo progetto.
95
95
  * Mantenuto per retrocompatibilità. Preferire subscriptionToWsConversationsForOnlineProjects
96
96
  * per sottoscrivere ai progetti online con status Available.
97
+ * @param project_id ID del progetto
98
+ * @param skipClear Se true, non svuota wsRequestsList (usato quando si sottoscrivono più progetti in sequenza)
97
99
  */
98
- subscriptionToWsConversations(project_id) {
100
+ subscriptionToWsConversations(project_id, skipClear = false) {
99
101
  // console.log("[WS-SERV] - CALLED SUBSC TO WS CONVS - PROJECT ID ", project_id);
100
102
  var self = this;
101
- this.wsRequestsList = [];
103
+ if (!skipClear) {
104
+ this.wsRequestsList = [];
105
+ }
102
106
 
103
- this.webSocketJs.ref('/' + project_id + '/requests', 'getCurrentProjectAndSubscribeTo_WsRequests',
107
+ this.webSocketJs.ref('/' + project_id + '/requests', 'getCurrentProjectAndSubscribeTo_WsRequests_' + project_id,
104
108
 
105
109
  function (data) {
106
- // console.log("[WS-SERV] - CONVS - CREATE DATA ", data);
110
+ // console.log("[WS-SERV] - CONVS - CREATE DATA for project ", project_id, data);
107
111
  if (data) {
108
112
  // ------------------------------------------------
109
113
  // @ Agents - pass in data agents get from snapshot
@@ -326,7 +330,7 @@ export class WebsocketService {
326
330
  this.subscribedConversationProjectIds
327
331
  );
328
332
  this.subscribedConversationProjectIds.forEach((projectId) =>
329
- this.subscriptionToWsConversations(projectId)
333
+ this.subscriptionToWsConversations(projectId, true)
330
334
  );
331
335
  return this.subscribedConversationProjectIds;
332
336
  }