@chat21/chat21-ionic 3.4.29 → 3.4.30-rc2

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 (75) hide show
  1. package/CHANGELOG.md +120 -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 +71 -12
  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/components/canned-response/canned-response.component.html +26 -23
  9. package/src/app/components/canned-response/canned-response.component.scss +0 -2
  10. package/src/app/components/canned-response/canned-response.component.ts +3 -1
  11. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +24 -1
  12. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +30 -0
  13. package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +39 -9
  14. package/src/app/components/conversation-info/info-content/info-content.component.ts +2 -2
  15. package/src/app/components/conversation-info/info-group/info-group.component.ts +23 -21
  16. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.html +1 -1
  17. package/src/app/components/conversations-list/header-conversations-list/header-conversations-list.component.ts +5 -1
  18. package/src/app/components/navbar/navbar.component.html +3 -3
  19. package/src/app/components/navbar/navbar.component.ts +29 -38
  20. package/src/app/components/project-item/project-item.component.ts +11 -11
  21. package/src/app/components/sidebar/sidebar.component.html +65 -45
  22. package/src/app/components/sidebar/sidebar.component.ts +110 -117
  23. package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +2 -2
  24. package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +10 -7
  25. package/src/app/modals/create-ticket/create-ticket.page.ts +4 -2
  26. package/src/app/pages/conversation-detail/conversation-detail.page.html +7 -3
  27. package/src/app/pages/conversation-detail/conversation-detail.page.ts +95 -7
  28. package/src/app/pages/conversations-list/conversations-list.page.html +2 -0
  29. package/src/app/pages/conversations-list/conversations-list.page.ts +40 -2
  30. package/src/app/services/global-settings/global-settings.service.ts +11 -3
  31. package/src/app/services/nav-proxy.service.ts +0 -1
  32. package/src/app/services/project_users/project-users.service.spec.ts +16 -0
  33. package/src/app/services/project_users/project-users.service.ts +63 -0
  34. package/src/app/services/tiledesk/tiledesk.service.ts +0 -16
  35. package/src/app/services/triggerEvents/triggerEvents.ts +28 -0
  36. package/src/app/services/websocket/websocket-js.ts +59 -534
  37. package/src/app/services/websocket/websocket-js_old.ts +578 -0
  38. package/src/app/services/websocket/websocket.service.ts +9 -10
  39. package/src/app/services/websocket/websocket.worker.ts +242 -0
  40. package/src/app/shared/shared.module.ts +11 -2
  41. package/src/app/utils/globals.ts +2 -0
  42. package/src/app/utils/permissions.constants.ts +138 -0
  43. package/src/app/utils/project-utils.ts +2 -2
  44. package/src/app/utils/utils.ts +18 -1
  45. package/src/assets/i18n/ar.json +11 -1
  46. package/src/assets/i18n/az.json +11 -1
  47. package/src/assets/i18n/de.json +11 -1
  48. package/src/assets/i18n/en.json +11 -1
  49. package/src/assets/i18n/es.json +11 -1
  50. package/src/assets/i18n/fr.json +11 -1
  51. package/src/assets/i18n/it.json +13 -3
  52. package/src/assets/i18n/kk.json +11 -1
  53. package/src/assets/i18n/pt.json +11 -1
  54. package/src/assets/i18n/ru.json +11 -1
  55. package/src/assets/i18n/sr.json +11 -1
  56. package/src/assets/i18n/sv.json +11 -1
  57. package/src/assets/i18n/tr.json +11 -1
  58. package/src/assets/i18n/uk.json +11 -1
  59. package/src/assets/i18n/uz.json +12 -1
  60. package/src/assets/img/no_data_found.png +0 -0
  61. package/src/assets/js/agentDesktop-sdk.js +55 -0
  62. package/src/assets/js/chat21client.js +36 -0
  63. package/src/assets/js/mqtt-keepalive-worker.js +53 -0
  64. package/src/assets/test.html +5 -2
  65. package/src/chat-config-template.json +1 -0
  66. package/src/chat-config.json +1 -0
  67. package/src/chat21-core/models/projectUsers.ts +19 -0
  68. package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
  69. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +1 -1
  70. package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
  71. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -1
  72. package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
  73. package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
  74. package/src/chat21-core/providers/tiledesk/tiledesk-auth.service.ts +3 -0
  75. package/src/chat21-core/utils/utils.ts +16 -2
@@ -6,6 +6,7 @@ import { UploadModel } from '../../models/upload';
6
6
  import { AppStorageService } from '../abstract/app-storage.service';
7
7
  import { LoggerService } from '../abstract/logger.service';
8
8
  import { LoggerInstance } from '../logger/loggerInstance';
9
+ import { first } from 'rxjs/operators';
9
10
 
10
11
  // @Injectable({ providedIn: 'root' })
11
12
  @Injectable()
@@ -14,8 +15,8 @@ export class NativeUploadService extends UploadService {
14
15
  BSStateUpload: BehaviorSubject<any> = new BehaviorSubject<any>(null)
15
16
 
16
17
  private tiledeskToken: string;
17
- private URL_TILEDESK_IMAGES: string;
18
18
  private URL_TILEDESK_FILE: string;
19
+ private URL_TILEDESK_UPLOAD: string;
19
20
  private logger: LoggerService = LoggerInstance.getInstance()
20
21
 
21
22
  constructor(
@@ -25,15 +26,17 @@ export class NativeUploadService extends UploadService {
25
26
  super();
26
27
  }
27
28
 
28
- initialize(): void {
29
- this.logger.info('[NATIVE UPLOAD] initialize')
30
- this.URL_TILEDESK_FILE = this.getBaseUrl() + 'files'
31
- this.URL_TILEDESK_IMAGES = this.getBaseUrl() + 'images'
29
+ initialize(projectId?: string): void {
30
+ this.logger.info('[NATIVE UPLOAD] initialize', this.getBaseUrl())
31
+ if (projectId) {
32
+ this.URL_TILEDESK_FILE = this.getBaseUrl() + projectId + '/files'
33
+ }
34
+ this.URL_TILEDESK_UPLOAD = this.getBaseUrl();
32
35
  this.tiledeskToken = this.appStorage.getItem('tiledeskToken')
33
36
  }
34
37
 
35
38
 
36
- upload(userId: string, upload: UploadModel): Promise<{ downloadURL: string, src: string}> {
39
+ upload(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}> {
37
40
  this.logger.log('[NATIVE UPLOAD] - upload new image/file ... upload', upload)
38
41
  const headers = new HttpHeaders({
39
42
  Authorization: this.tiledeskToken,
@@ -45,37 +48,93 @@ export class NativeUploadService extends UploadService {
45
48
 
46
49
  const that = this;
47
50
  if ((upload.file.type.startsWith('image') && (!upload.file.type.includes('svg')))) {
48
- this.logger.log('[NATIVE UPLOAD] - upload new image')
49
51
  //USE IMAGE API
50
- const url = this.URL_TILEDESK_IMAGES + '/users'
52
+ const url = this.URL_TILEDESK_UPLOAD + 'images/users'
51
53
  return new Promise((resolve, reject) => {
52
- that.http.post(url, formData, requestOptions).subscribe(data => {
53
- const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
54
- resolve({downloadURL : downloadURL, src: downloadURL})
55
- // that.BSStateUpload.next({upload: upload});
56
- }, (error) => {
57
- reject(error)
54
+ that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
55
+ next: (data) => {
56
+ const downloadURL = this.URL_TILEDESK_UPLOAD + 'images?path=' + encodeURIComponent(data?.['filename']);
57
+ resolve({downloadURL : downloadURL, src: downloadURL})
58
+ // that.BSStateUpload.next({upload: upload});
59
+ },
60
+ error: (error) => {
61
+ reject(error)
62
+ }
58
63
  });
59
64
  });
60
65
  } else {
61
- this.logger.log('[NATIVE UPLOAD] - upload new file')
62
66
  //USE FILE API
63
- const url = this.URL_TILEDESK_FILE + '/users'
67
+ const url = this.URL_TILEDESK_UPLOAD + 'files/users'
64
68
  return new Promise((resolve, reject) => {
65
- that.http.post(url, formData, requestOptions).subscribe(data => {
66
- const src = this.URL_TILEDESK_FILE + '?path=' + encodeURI(data['filename']);
67
- const downloadURL = this.URL_TILEDESK_FILE + '/download' + '?path=' + encodeURI(data['filename']);
68
- resolve({downloadURL : downloadURL, src: src})
69
- // that.BSStateUpload.next({upload: upload});
70
- }, (error) => {
71
- this.logger.error('[NATIVE UPLOAD] - ERROR upload new file ', error)
72
- reject(error)
69
+ that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
70
+ next: (data) => {
71
+ const src = this.URL_TILEDESK_UPLOAD + 'files?path=' + encodeURIComponent(data['filename']);
72
+ const downloadURL = this.URL_TILEDESK_UPLOAD + 'files/download' + '?path=' + encodeURIComponent(data['filename']);
73
+ resolve({downloadURL : downloadURL, src: src})
74
+ // that.BSStateUpload.next({upload: upload});
75
+ },
76
+ error: (error) => {
77
+ this.logger.error('[NATIVE UPLOAD] - ERROR upload new file ', error)
78
+ reject(error)
79
+ }
73
80
  });
74
81
  });
75
82
  }
76
83
 
77
84
  }
78
85
 
86
+ uploadFile(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}> {
87
+ this.logger.log('[NATIVE UPLOAD] - upload new image/file ... upload', upload)
88
+ const headers = new HttpHeaders({
89
+ Authorization: this.tiledeskToken,
90
+ //'Content-Type': 'multipart/form-data',
91
+ });
92
+ const requestOptions = { headers: headers };
93
+ const formData = new FormData();
94
+ formData.append('file', upload.file);
95
+
96
+ const that = this;
97
+ const url = this.URL_TILEDESK_FILE + '/chat'
98
+ return new Promise((resolve, reject) => {
99
+ that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
100
+ next: (data) => {
101
+ const src = this.URL_TILEDESK_UPLOAD + 'files?path=' + encodeURIComponent(data['filename']);
102
+ const downloadURL = this.URL_TILEDESK_UPLOAD + 'files/download?path=' + encodeURIComponent(data['filename']);
103
+ resolve({downloadURL : downloadURL, src: src})
104
+ },
105
+ error: (error) => {
106
+ reject(error)
107
+ }
108
+ });
109
+ });
110
+ }
111
+
112
+ uploadAsset(userId: string, upload: UploadModel, expiration: number = 60): Promise<{downloadURL: string, src: string}> {
113
+ this.logger.log('[NATIVE UPLOAD] - upload new asset ... upload', upload, 'expiration:', expiration)
114
+ const headers = new HttpHeaders({
115
+ Authorization: this.tiledeskToken,
116
+ });
117
+ const requestOptions = { headers: headers };
118
+ const formData = new FormData();
119
+ formData.append('file', upload.file);
120
+
121
+ const that = this;
122
+ const queryString = expiration !== undefined ? `?expiration=${encodeURIComponent(String(expiration))}` : ''
123
+ const url = this.URL_TILEDESK_FILE + `/assets${queryString}`
124
+ return new Promise((resolve, reject) => {
125
+ that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
126
+ next: (data) => {
127
+ const src = this.URL_TILEDESK_UPLOAD + 'files?path=' + data['filename'];
128
+ const downloadURL = this.URL_TILEDESK_UPLOAD + 'files/download?path=' + encodeURIComponent(data['filename']);
129
+ resolve({downloadURL : downloadURL, src: src})
130
+ },
131
+ error: (error) => {
132
+ reject(error)
133
+ }
134
+ });
135
+ });
136
+ }
137
+
79
138
  uploadProfile(userId: string, upload: UploadModel): Promise<any> {
80
139
  this.logger.log('[NATIVE UPLOAD] - upload new photo profile ... upload', upload)
81
140
  const headers = new HttpHeaders({
@@ -88,14 +147,18 @@ export class NativeUploadService extends UploadService {
88
147
 
89
148
  // USE IMAGE API
90
149
  const that = this;
91
- const url = this.URL_TILEDESK_IMAGES + `/users/photo?force=true&user_id=${userId}`
150
+ const queryString = userId?.startsWith('bot_') ? `?bot_id=${encodeURIComponent(userId.substring('bot_'.length))}` : ''
151
+ const url = this.URL_TILEDESK_FILE + `/users/photo${queryString}`
92
152
  return new Promise((resolve, reject) => {
93
- that.http.put(url, formData, requestOptions).subscribe(data => {
94
- const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['thumbnail'];
95
- resolve(downloadURL)
96
- // that.BSStateUpload.next({upload: upload});
97
- }, (error) => {
98
- reject(error)
153
+ that.http.put(url, formData, requestOptions).pipe(first()).subscribe({
154
+ next: (data) => {
155
+ const downloadURL = this.getBaseUrl() + 'files?path=' + data['thumbnail'];
156
+ resolve(downloadURL)
157
+ // that.BSStateUpload.next({upload: upload});
158
+ },
159
+ error: (error) => {
160
+ reject(error)
161
+ }
99
162
  });
100
163
  });
101
164
  }
@@ -110,18 +173,50 @@ export class NativeUploadService extends UploadService {
110
173
 
111
174
  //USE IMAGE API
112
175
  const that = this;
113
- const url = this.URL_TILEDESK_IMAGES + '/users' + '?path=' + path.split('path=')[1]
176
+ const url = this.URL_TILEDESK_UPLOAD + 'images/users' + '?path=' + path.split('path=')[1]
177
+ return new Promise((resolve, reject) => {
178
+ that.http.delete(url, requestOptions).pipe(first()).subscribe({
179
+ next: (data) => {
180
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
181
+ resolve(true)
182
+ // that.BSStateUpload.next({upload: upload});
183
+ },
184
+ error: (error) => {
185
+ reject(error)
186
+ }
187
+ });
188
+ });
189
+ }
190
+
191
+ deleteFile(userId: string, path: string): Promise<any>{
192
+ this.logger.log('[NATIVE UPLOAD] - delete image ... upload', userId)
193
+ const headers = new HttpHeaders({
194
+ Authorization: this.tiledeskToken,
195
+ //'Content-Type': 'multipart/form-data',
196
+ });
197
+ const requestOptions = { headers: headers };
198
+
199
+ //USE IMAGE API
200
+ const that = this;
201
+ const url = this.URL_TILEDESK_FILE + '?path=' + path.split('path=')[1]
114
202
  return new Promise((resolve, reject) => {
115
- that.http.delete(url, requestOptions).subscribe(data => {
116
- // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
117
- resolve(true)
118
- // that.BSStateUpload.next({upload: upload});
119
- }, (error) => {
120
- reject(error)
203
+ that.http.delete(url, requestOptions).pipe(first()).subscribe({
204
+ next: (data) => {
205
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
206
+ resolve(true)
207
+ // that.BSStateUpload.next({upload: upload});
208
+ },
209
+ error: (error) => {
210
+ reject(error)
211
+ }
121
212
  });
122
213
  });
123
214
  }
124
215
 
216
+ deleteAsset(userId: string, path: string): Promise<any>{
217
+ return this.deleteFile(userId, path);
218
+ }
219
+
125
220
  deleteProfile(userId: string, path: string): Promise<any>{
126
221
  this.logger.log('[NATIVE UPLOAD] - delete image ... upload', userId)
127
222
  const headers = new HttpHeaders({
@@ -132,14 +227,17 @@ export class NativeUploadService extends UploadService {
132
227
 
133
228
  //USE IMAGE API
134
229
  const that = this;
135
- const url = this.URL_TILEDESK_IMAGES + '/users' + '?path=' + "uploads/users/"+ userId + "/images/photo.jpg"
230
+ const url = this.URL_TILEDESK_FILE + '?path=' + "uploads/users/"+ userId + "/images/photo.jpg"
136
231
  return new Promise((resolve, reject) => {
137
- that.http.delete(url, requestOptions).subscribe(data => {
138
- // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
139
- resolve(true)
140
- // that.BSStateUpload.next({upload: upload});
141
- }, (error) => {
142
- reject(error)
232
+ that.http.delete(url, requestOptions).pipe(first()).subscribe({
233
+ next: (data) => {
234
+ // const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
235
+ resolve(true)
236
+ // that.BSStateUpload.next({upload: upload});
237
+ },
238
+ error: (error) => {
239
+ reject(error)
240
+ }
143
241
  });
144
242
  });
145
243
  }
@@ -121,6 +121,7 @@ export class TiledeskAuthService {
121
121
  this.http.post(this.URL_TILEDESK_SIGNIN_WITH_CUSTOM_TOKEN, null, requestOptions).subscribe((data) => {
122
122
  if (data['success'] && data['token']) {
123
123
  that.tiledeskToken = data['token'];
124
+ data['user'].token = tiledeskToken; // mantengo il token custom nell'oggetto user
124
125
  that.createCompleteUser(data['user']);
125
126
  this.checkAndSetInStorageTiledeskToken(that.tiledeskToken)
126
127
  this.BS_IsONLINE.next(true)
@@ -177,6 +178,8 @@ export class TiledeskAuthService {
177
178
  this.currentUser = member;
178
179
  this.logger.log('[TILEDESK-AUTH] - createCompleteUser member ', member);
179
180
  this.appStorage.setItem('currentUser', JSON.stringify(this.currentUser));
181
+ const { iat, aud, iss, jti, ...cleanUser } = user; //destructuring and rest user object
182
+ localStorage.setItem('user', JSON.stringify(cleanUser));
180
183
 
181
184
  } catch (err) {
182
185
  this.logger.error('[TILEDESK-AUTH]- createCompleteUser ERR ', err)
@@ -765,6 +765,12 @@ export function isOnMobileDevice() {
765
765
  return IS_ON_MOBILE_DEVICE;
766
766
  }
767
767
 
768
+
769
+ export function checkIfIsInIframe(){
770
+ const isInIframe = window.self !== window.top;
771
+ return isInIframe;
772
+ }
773
+
768
774
  export function checkWindowWidthIsLessThan991px() {
769
775
  // console.log('UTILS - checkWindowWidthIsLessThan991px:: ', window.innerWidth);
770
776
  if (window.innerWidth < 991) {
@@ -1018,6 +1024,14 @@ export function isAllowedUrlInText(text: string, allowedUrls: string[]) {
1018
1024
  }
1019
1025
 
1020
1026
  function extractUrls(text: string): string[] {
1021
- const urlRegex = /https?:\/\/[^\s]+/g;
1022
- return text.match(urlRegex) || [];
1027
+ // Rileva URL con o senza protocollo (http/https)
1028
+ const urlRegex = /\b((https?:\/\/)?(www\.)?[a-z0-9.-]+\.[a-z]{2,})(\/[^\s]*)?/gi;
1029
+ const matches = text.match(urlRegex) || [];
1030
+ // Normalizza: aggiunge https:// se manca, così il parsing con new URL() funziona
1031
+ return matches.map((url) => {
1032
+ if (!/^https?:\/\//i.test(url)) {
1033
+ return 'https://' + url;
1034
+ }
1035
+ return url;
1036
+ });
1023
1037
  }