@chat21/chat21-ionic 3.4.30 → 3.4.31

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.31 in PROD
12
+ - **changed**: enhance HTML entities encoding by normalizing line breaks and handling null/undefined inputs
13
+ - **changed**: API for upload a file/image into chat
14
+
11
15
  # 3.4.30 in PROD
12
16
  - **changed**: when the app is in background, play a sound whenever a new message arrives.
13
17
 
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.30",
4
+ "version": "3.4.31",
5
5
  "license": "MIT License",
6
6
  "homepage": "https://tiledesk.com/",
7
7
  "repository": {
@@ -119,7 +119,6 @@ export class AppComponent implements OnInit {
119
119
  private navService: NavProxyService,
120
120
  // public chatPresenceHandler: ChatPresenceHandler,
121
121
  public typingService: TypingService,
122
- public uploadService: UploadService,
123
122
  public appStorageService: AppStorageService,
124
123
 
125
124
  // public chatConversationsHandler: ChatConversationsHandler,
@@ -547,7 +546,6 @@ export class AppComponent implements OnInit {
547
546
  if (pushEngine && pushEngine !== 'none') {
548
547
  this.notificationsService.initialize(this.tenant, vap_id_Key, platform)
549
548
  }
550
- this.uploadService.initialize();
551
549
 
552
550
  this.setLanguage(null)
553
551
  this.initAuthentication();
@@ -8,5 +8,6 @@
8
8
  [height]="height"
9
9
  [src]="metadata.src"
10
10
  (load)="onLoaded($event)"
11
+ (error)="onError($event)"
11
12
  (click)="openImageViewerModal(metadata.src, metadata.name)" />
12
13
  </div>
@@ -15,6 +15,7 @@ export class ImageComponent implements OnInit {
15
15
  loading: boolean = true
16
16
  modal: any
17
17
  span: any
18
+ private readonly fallbackSrc = 'assets/img/no_data_found.png'
18
19
 
19
20
  constructor() { }
20
21
 
@@ -26,6 +27,24 @@ export class ImageComponent implements OnInit {
26
27
  this.onElementRendered.emit({element: "image", status:true})
27
28
  }
28
29
 
30
+ onError(event: Event) {
31
+ this.loading = false
32
+ const img = event?.target as HTMLImageElement | null
33
+ if (!img) {
34
+ return
35
+ }
36
+ // avoid infinite loop if fallback image fails too
37
+ if (img.src && img.src.includes(this.fallbackSrc)) {
38
+ return
39
+ }
40
+ img.src = this.fallbackSrc
41
+ // also update metadata so click-to-open uses the fallback consistently
42
+ if (this.metadata) {
43
+ this.metadata.src = this.fallbackSrc
44
+ }
45
+ this.onElementRendered.emit({ element: 'image', status: true })
46
+ }
47
+
29
48
  _downloadImage(url: string, fileName: string) {
30
49
  // console.log('Image COMP - IMAGE URL ', url)
31
50
  // console.log('Image COMP - IMAGE FILENAME ', fileName)
@@ -12,7 +12,7 @@ import { LoaderPreviewPage } from 'src/app/modals/loader-preview/loader-preview.
12
12
  // Services
13
13
  import { UploadService } from 'src/chat21-core/providers/abstract/upload.service';
14
14
  // utils
15
- import { TYPE_MSG_EMAIL, TYPE_MSG_TEXT, CHANNEL_TYPE } from 'src/chat21-core/utils/constants';
15
+ import { TYPE_MSG_EMAIL, TYPE_MSG_TEXT, CHANNEL_TYPE, TYPE_DIRECT } from 'src/chat21-core/utils/constants';
16
16
  // Models
17
17
  import { UploadModel } from 'src/chat21-core/models/upload';
18
18
 
@@ -162,6 +162,11 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
162
162
 
163
163
  this.project = this.projectService.getProject();
164
164
  this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] project', this.project)
165
+ if (this.channelType === TYPE_DIRECT) {
166
+ this.uploadService.initialize();
167
+ } else {
168
+ this.uploadService.initialize(this.project?._id);
169
+ }
165
170
  // use case drop
166
171
  if (this.dropEvent) {
167
172
  this.presentModal(this.dropEvent)
@@ -384,7 +389,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
384
389
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss currentUpload', currentUpload);
385
390
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss detail.data', detail.data);
386
391
 
387
- that.uploadService.upload(that.loggedUser.uid, currentUpload).then((data) => {
392
+ const uploadPromise = (that.channelType === TYPE_DIRECT)
393
+ ? that.uploadService.upload(that.loggedUser.uid, currentUpload)
394
+ : that.uploadService.uploadFile(that.loggedUser.uid, currentUpload)
395
+ uploadPromise.then((data) => {
388
396
  metadata.src = data.src;
389
397
  metadata.downloadURL = data.downloadURL;
390
398
  this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal invio msg metadata::: ', metadata);
@@ -1,5 +1,5 @@
1
1
  import { Pipe, PipeTransform } from '@angular/core';
2
- import { htmlEntities, replaceEndOfLine } from 'src/chat21-core/utils/utils';
2
+ import { htmlEntities } from 'src/chat21-core/utils/utils';
3
3
 
4
4
  @Pipe({
5
5
  name: 'htmlEntiesEncode'
@@ -8,10 +8,25 @@ import { htmlEntities, replaceEndOfLine } from 'src/chat21-core/utils/utils';
8
8
  export class HtmlEntitiesEncodePipe implements PipeTransform {
9
9
 
10
10
  transform(text: any, args?: any): any {
11
- text = htmlEntities(text);
12
- text = replaceEndOfLine(text);
13
- text = text.trim();
14
- return text;
11
+ if (text === null || text === undefined) {
12
+ return text;
13
+ }
14
+
15
+ // Normalize line breaks BEFORE encoding HTML:
16
+ // - real CRLF/CR/LF to LF
17
+ // - escaped sequences (\n, \r, \r\n) to LF
18
+ // - HTML <br> tags (if present) to LF
19
+ let normalized = String(text)
20
+ .replace(/\r\n/g, '\n')
21
+ .replace(/\r/g, '\n')
22
+ .replace(/\\r\\n/g, '\n')
23
+ .replace(/\\n/g, '\n')
24
+ .replace(/\\r/g, '\n')
25
+ .replace(/<br\s*\/?>/gi, '\n');
26
+
27
+ normalized = htmlEntities(normalized);
28
+ normalized = normalized.trim();
29
+ return normalized;
15
30
  }
16
31
 
17
32
  }
@@ -84,6 +84,7 @@ import { Project } from 'src/chat21-core/models/projects';
84
84
  import { Globals } from 'src/app/utils/globals';
85
85
  import { ProjectService } from 'src/app/services/projects/project.service';
86
86
  import { getOSCode } from 'src/app/utils/utils';
87
+ import { UploadService } from 'src/chat21-core/providers/abstract/upload.service';
87
88
 
88
89
  @Component({
89
90
  selector: 'app-conversation-detail',
@@ -236,6 +237,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
236
237
  public conversationHandlerBuilderService: ConversationHandlerBuilderService,
237
238
  public cannedResponsesService: CannedResponsesService,
238
239
  public imageRepoService: ImageRepoService,
240
+ public uploadService: UploadService,
239
241
  public presenceService: PresenceService,
240
242
  public toastController: ToastController,
241
243
  public tiledeskService: TiledeskService,
@@ -478,7 +480,8 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
478
480
  this.isFileSelected = false // indicates if a file has been selected (image to upload)
479
481
  this.isEmailEnabled = (this.appConfigProvider.getConfig().emailSection === 'true' || this.appConfigProvider.getConfig().emailSection === true) ? true : false;
480
482
  this.isWhatsappTemplatesEnabled = (this.appConfigProvider.getConfig().whatsappTemplatesSection === 'true' || this.appConfigProvider.getConfig().whatsappTemplatesSection === true) ? true : false;
481
-
483
+ this.fileUploadAccept = this.appConfigProvider.getConfig().fileUploadAccept
484
+
482
485
  this.cannedResponsesService.initialize(appconfig.apiUrl)
483
486
 
484
487
  if (checkPlatformIsMobile()) {
@@ -507,10 +510,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
507
510
  // this.initConversationsHandler(); // nk
508
511
  if (this.conversationWith) {
509
512
  this.disableTextarea = false
513
+ this.startConversation();
510
514
  this._getProjectIdByConversationWith(this.conversationWith)
511
515
  this.initConversationHandler()
512
516
  this.initGroupsHandler();
513
- this.startConversation();
514
517
  this.initSubscriptions();
515
518
  this.getLeadDetail();
516
519
  this.initializeTyping();
@@ -521,6 +524,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
521
524
  }
522
525
 
523
526
  _getProjectIdByConversationWith(conversationWith: string) {
527
+ console.log('[CONVS-DETAIL] - _getProjectIdByConversationWith conversationWith', conversationWith, this.channelType)
524
528
  if (this.channelType !== TYPE_DIRECT && !this.conversationWith.startsWith('group-')) {
525
529
  this.tiledeskService.getProjectIdByConvRecipient(conversationWith).subscribe((res) => {
526
530
  this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT RES + projectId', res, res.id_project)
Binary file
@@ -34,9 +34,13 @@ export abstract class UploadService {
34
34
  // abstract tenant = environment.tenant;
35
35
 
36
36
  // functions
37
- abstract initialize(): void;
37
+ abstract initialize(projectId?: string): void;
38
38
  abstract upload(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}>;
39
+ abstract uploadFile(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}>;
40
+ abstract uploadAsset(userId: string, upload: UploadModel, expiration?: number): Promise<{downloadURL: string, src: string}>;
39
41
  abstract uploadProfile(userId: string, upload: UploadModel): Promise<any>;
40
42
  abstract delete(userId: string, path: string): Promise<any>;
43
+ abstract deleteFile(userId: string, path: string): Promise<any>;
44
+ abstract deleteAsset(userId: string, path: string): Promise<any>
41
45
  abstract deleteProfile(userId: string, path: string): Promise<any>
42
46
  }
@@ -42,7 +42,7 @@ export class FirebaseUploadService extends UploadService {
42
42
  });
43
43
  }
44
44
 
45
- public initialize() {
45
+ public async initialize(projectId?: string) {
46
46
  this.logger.log('[FIREBASEUploadSERVICE] initialize');
47
47
  }
48
48
 
@@ -104,6 +104,107 @@ export class FirebaseUploadService extends UploadService {
104
104
 
105
105
  }
106
106
 
107
+ public uploadFile(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: any}> {
108
+ const that = this;
109
+ const uid = this.createGuid();
110
+ const urlImagesNodeFirebase = '/public/images/' + userId + '/' + uid + '/' + upload.file.name;
111
+ this.logger.debug('[FIREBASEUploadSERVICE] pushUpload ', urlImagesNodeFirebase, upload.file);
112
+
113
+ // Create a root reference
114
+ const storageRef = firebase.storage().ref();
115
+ this.logger.debug('[FIREBASEUploadSERVICE] storageRef', storageRef);
116
+
117
+ // Create a reference to 'mountains.jpg'
118
+ const mountainsRef = storageRef.child(urlImagesNodeFirebase);
119
+ this.logger.debug('[FIREBASEUploadSERVICE] mountainsRef ', mountainsRef);
120
+
121
+ // const metadata = {};
122
+ const metadata = { name: upload.file.name, contentType: upload.file.type, contentDisposition: 'attachment; filename=' + upload.file.name };
123
+
124
+ let uploadTask = mountainsRef.put(upload.file, metadata);
125
+
126
+ return new Promise((resolve, reject) => {
127
+ uploadTask.on('state_changed', function progress(snapshot) {
128
+ // Observe state change events such as progress, pause, and resume
129
+ // Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
130
+ var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
131
+ that.logger.debug('[FIREBASEUploadSERVICE] Upload is ' + progress + '% done');
132
+
133
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
134
+ // BehaviorSubject publish the upload progress state - the subscriber is in ion-conversastion-detail.component.ts > listenToUploadFileProgress()
135
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
136
+
137
+ that.BSStateUpload.next({ upload: progress, type: upload.file.type });
138
+
139
+ switch (snapshot.state) {
140
+ case firebase.storage.TaskState.PAUSED: // or 'paused'
141
+ that.logger.debug('[FIREBASEUploadSERVICE] Upload is paused');
142
+
143
+ break;
144
+ case firebase.storage.TaskState.RUNNING: // or 'running'
145
+ that.logger.debug('[FIREBASEUploadSERVICE] Upload is running');
146
+
147
+ break;
148
+ }
149
+ }, function error(error) {
150
+ // Handle unsuccessful uploads
151
+ reject(error)
152
+ }, async function complete() {
153
+ // Handle successful uploads on complete
154
+ that.logger.debug('[FIREBASEUploadSERVICE] Upload is complete', upload);
155
+
156
+ const downloadURL = await uploadTask.snapshot.ref.getDownloadURL();
157
+ resolve({downloadURL: downloadURL, src: downloadURL})
158
+ // that.BSStateUpload.next({upload: upload});
159
+
160
+ });
161
+ })
162
+ }
163
+
164
+ public uploadAsset(userId: string, upload: UploadModel, expiration: number = 60): Promise<{downloadURL: string, src: any}> {
165
+ // expiration is ignored on Firebase, but kept for API compatibility with NativeUploadService
166
+ const that = this;
167
+ const uid = this.createGuid();
168
+ const urlAssetsNodeFirebase = '/public/assets/' + userId + '/' + uid + '/' + upload.file.name;
169
+ this.logger.debug('[FIREBASEUploadSERVICE] uploadAsset ', urlAssetsNodeFirebase, upload.file, 'expiration:', expiration);
170
+
171
+ // Create a root reference
172
+ const storageRef = firebase.storage().ref();
173
+ this.logger.debug('[FIREBASEUploadSERVICE] storageRef', storageRef);
174
+
175
+ const assetRef = storageRef.child(urlAssetsNodeFirebase);
176
+ this.logger.debug('[FIREBASEUploadSERVICE] assetRef ', assetRef);
177
+
178
+ const metadata = { name: upload.file.name, contentType: upload.file.type, contentDisposition: 'attachment; filename=' + upload.file.name };
179
+
180
+ let uploadTask = assetRef.put(upload.file, metadata);
181
+
182
+ return new Promise((resolve, reject) => {
183
+ uploadTask.on('state_changed', function progress(snapshot) {
184
+ var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
185
+ that.logger.debug('[FIREBASEUploadSERVICE] uploadAsset is ' + progress + '% done');
186
+
187
+ that.BSStateUpload.next({ upload: progress, type: upload.file.type });
188
+
189
+ switch (snapshot.state) {
190
+ case firebase.storage.TaskState.PAUSED:
191
+ that.logger.debug('[FIREBASEUploadSERVICE] uploadAsset is paused');
192
+ break;
193
+ case firebase.storage.TaskState.RUNNING:
194
+ that.logger.debug('[FIREBASEUploadSERVICE] uploadAsset is running');
195
+ break;
196
+ }
197
+ }, function error(error) {
198
+ reject(error)
199
+ }, async function complete() {
200
+ that.logger.debug('[FIREBASEUploadSERVICE] uploadAsset is complete', upload);
201
+
202
+ const downloadURL = await uploadTask.snapshot.ref.getDownloadURL();
203
+ resolve({downloadURL: downloadURL, src: downloadURL})
204
+ });
205
+ })
206
+ }
207
+
107
208
  public uploadProfile(userId: string, upload: UploadModel): Promise<any> {
108
209
  const that = this;
109
210
  const urlImagesNodeFirebase = '/profiles/' + userId + '/photo.jpg'
@@ -192,6 +293,40 @@ export class FirebaseUploadService extends UploadService {
192
293
  })
193
294
  }
194
295
 
296
+ public async deleteFile(userId: string, path: string): Promise<any>{
297
+ const that = this;
298
+ const file_name_photo = 'photo.jpg';
299
+ const file_name_thumb_photo = 'thumb_photo.jpg';
300
+
301
+ that.logger.debug('[FIREBASEUploadSERVICE] delete image for USER', userId, path);
302
+
303
+ let uid = path.split(userId)[1].split('%2F')[1]; // get the UID of the image
304
+ let imageName = path.split(uid + '%2F')[1].split('?')[0];
305
+
306
+ // Create a root reference
307
+ const storageRef = firebase.storage().ref();
308
+ const ref = storageRef.child('public/images/' + userId + '/'+ uid + '/')
309
+ let arrayPromise = []
310
+ await ref.listAll().then((dir => {
311
+ dir.items.forEach(fileRef => arrayPromise.push(this.deleteFile(ref.fullPath, fileRef.name)));
312
+ })).catch(error => {
313
+ that.logger.error('[FIREBASEUploadSERVICE] delete: listAll error', error)
314
+ })
315
+
316
+ //AWAIT to return ALL the promise delete()
317
+ return new Promise((resolve, reject)=> {
318
+ Promise.all(arrayPromise).then(()=>{
319
+ resolve(true)
320
+ }).catch((error)=>{
321
+ reject(error)
322
+ })
323
+ })
324
+ }
325
+
326
+ public async deleteAsset(userId: string, path: string): Promise<any>{
327
+ return this.deleteProfile(userId, path);
328
+ }
329
+
195
330
  public async deleteProfile(userId: string, path: string): Promise<any>{
196
331
  const that = this;
197
332
  const file_name_photo = 'photo.jpg';
@@ -219,13 +354,5 @@ export class FirebaseUploadService extends UploadService {
219
354
  })
220
355
  }
221
356
 
222
- // // ------------------------------------
223
- // // Delete the file photo
224
- // // ------------------------------------
225
- private deleteFile(pathToFile, fileName){
226
- const ref = firebase.storage().ref(pathToFile);
227
- const childRef = ref.child(fileName);
228
- return childRef.delete()
229
- }
230
357
 
231
358
  }
@@ -16,7 +16,7 @@ export class NativeImageRepoService extends ImageRepoService {
16
16
  * @param uid
17
17
  */
18
18
  getImagePhotoUrl(uid: string): string {
19
- this.baseImageURL = this.getImageBaseUrl() + 'images'
19
+ this.baseImageURL = this.getImageBaseUrl() + 'files'
20
20
  let sender_id = '';
21
21
  if (uid.includes('bot_')) {
22
22
  sender_id = uid.slice(4)
@@ -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
  }