@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 +4 -0
- package/package.json +1 -1
- package/src/app/app.component.ts +0 -2
- package/src/app/chatlib/conversation-detail/message/image/image.component.html +1 -0
- package/src/app/chatlib/conversation-detail/message/image/image.component.ts +19 -0
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +10 -2
- package/src/app/directives/html-entities-encode.pipe.ts +20 -5
- package/src/app/pages/conversation-detail/conversation-detail.page.ts +6 -2
- package/src/assets/img/no_data_found.png +0 -0
- package/src/chat21-core/providers/abstract/upload.service.ts +5 -1
- package/src/chat21-core/providers/firebase/firebase-upload.service.ts +136 -9
- package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
- package/src/chat21-core/providers/native/native-upload-service.ts +143 -45
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
package/src/app/app.component.ts
CHANGED
|
@@ -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();
|
|
@@ -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)
|
package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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() + '
|
|
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
|
-
|
|
31
|
-
|
|
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<{
|
|
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.
|
|
52
|
+
const url = this.URL_TILEDESK_UPLOAD + 'images/users'
|
|
51
53
|
return new Promise((resolve, reject) => {
|
|
52
|
-
that.http.post(url, formData, requestOptions).subscribe(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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.
|
|
67
|
+
const url = this.URL_TILEDESK_UPLOAD + 'files/users'
|
|
64
68
|
return new Promise((resolve, reject) => {
|
|
65
|
-
that.http.post(url, formData, requestOptions).subscribe(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
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(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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.
|
|
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(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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.
|
|
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(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
}
|