@chat21/chat21-ionic 3.4.29-rc1 → 3.4.30-rc1
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 +12 -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/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 +4 -1
- package/src/chat21-core/providers/firebase/firebase-upload.service.ts +132 -9
- package/src/chat21-core/providers/native/native-image-repo.ts +1 -1
- package/src/chat21-core/providers/native/native-upload-service.ts +117 -28
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,18 @@
|
|
|
8
8
|
### **Copyrigth**:
|
|
9
9
|
*Tiledesk SRL*
|
|
10
10
|
|
|
11
|
+
# 3.4.29-rc1
|
|
12
|
+
- **changed**: API for upload a file/image into chat
|
|
13
|
+
|
|
14
|
+
# 3.4.29 in PROD
|
|
15
|
+
- **bug-fixed**: web (Chrome >= 144) `ion-content` stopped scrolling on some pages (conversation list / contacts directory / unassigned); removed the forced `--overflow: hidden` and handled scrolling on Ionic’s internal scroll container via `ion-content::part(scroll)`
|
|
16
|
+
|
|
17
|
+
# 3.4.28 in PROD
|
|
18
|
+
- **bug-fixed**: cannot do project subscription if last_project object is not a project_user obj
|
|
19
|
+
|
|
20
|
+
# 3.4.27 in PROD
|
|
21
|
+
- **bug-fixed**: cannot find route if userFullname contains /
|
|
22
|
+
|
|
11
23
|
# 3.4.29-rc1
|
|
12
24
|
- **bug-fixed**: web (Chrome >= 144) `ion-content` stopped scrolling on some pages (conversation list / contacts directory / unassigned); removed the forced `--overflow: hidden` and handled scrolling on Ionic’s internal scroll container via `ion-content::part(scroll)`
|
|
13
25
|
|
package/package.json
CHANGED
package/src/app/app.component.ts
CHANGED
|
@@ -122,7 +122,6 @@ export class AppComponent implements OnInit {
|
|
|
122
122
|
private navService: NavProxyService,
|
|
123
123
|
// public chatPresenceHandler: ChatPresenceHandler,
|
|
124
124
|
public typingService: TypingService,
|
|
125
|
-
public uploadService: UploadService,
|
|
126
125
|
public appStorageService: AppStorageService,
|
|
127
126
|
|
|
128
127
|
// public chatConversationsHandler: ChatConversationsHandler,
|
|
@@ -556,7 +555,6 @@ export class AppComponent implements OnInit {
|
|
|
556
555
|
if (pushEngine && pushEngine !== 'none') {
|
|
557
556
|
this.notificationsService.initialize(this.tenant, vap_id_Key, platform)
|
|
558
557
|
}
|
|
559
|
-
this.uploadService.initialize();
|
|
560
558
|
|
|
561
559
|
this.setLanguage(null)
|
|
562
560
|
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
|
|
|
@@ -168,6 +168,11 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
168
168
|
|
|
169
169
|
this.project = this.projectService.getProject();
|
|
170
170
|
this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] project', this.project)
|
|
171
|
+
if (this.channelType === TYPE_DIRECT) {
|
|
172
|
+
this.uploadService.initialize();
|
|
173
|
+
} else {
|
|
174
|
+
this.uploadService.initialize(this.project?._id);
|
|
175
|
+
}
|
|
171
176
|
// use case drop
|
|
172
177
|
if (this.dropEvent) {
|
|
173
178
|
this.presentModal(this.dropEvent)
|
|
@@ -401,7 +406,10 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
|
|
|
401
406
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss currentUpload', currentUpload);
|
|
402
407
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal onDidDismiss detail.data', detail.data);
|
|
403
408
|
|
|
404
|
-
|
|
409
|
+
const uploadPromise = (that.channelType === TYPE_DIRECT)
|
|
410
|
+
? that.uploadService.upload(that.loggedUser.uid, currentUpload)
|
|
411
|
+
: that.uploadService.uploadFile(that.loggedUser.uid, currentUpload)
|
|
412
|
+
uploadPromise.then((data) => {
|
|
405
413
|
metadata.src = data.src;
|
|
406
414
|
metadata.downloadURL = data.downloadURL;
|
|
407
415
|
this.logger.log('[CONVS-DETAIL][MSG-TEXT-AREA] FIREBASE-UPLOAD presentModal invio msg metadata::: ', metadata);
|
|
@@ -83,6 +83,7 @@ import { WebsocketService } from 'src/app/services/websocket/websocket.service';
|
|
|
83
83
|
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
|
+
import { UploadService } from 'src/chat21-core/providers/abstract/upload.service';
|
|
86
87
|
import { ProjectUsersService } from 'src/app/services/project_users/project-users.service';
|
|
87
88
|
import { ProjectUser } from 'src/chat21-core/models/projectUsers';
|
|
88
89
|
import { getOSCode, hasRole } from 'src/app/utils/utils';
|
|
@@ -246,6 +247,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
246
247
|
public conversationHandlerBuilderService: ConversationHandlerBuilderService,
|
|
247
248
|
public cannedResponsesService: CannedResponsesService,
|
|
248
249
|
public imageRepoService: ImageRepoService,
|
|
250
|
+
public uploadService: UploadService,
|
|
249
251
|
public presenceService: PresenceService,
|
|
250
252
|
public toastController: ToastController,
|
|
251
253
|
public tiledeskService: TiledeskService,
|
|
@@ -493,7 +495,8 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
493
495
|
this.isEmailEnabled = (this.appConfigProvider.getConfig().emailSection === 'true' || this.appConfigProvider.getConfig().emailSection === true) ? true : false;
|
|
494
496
|
this.isTicketEnabled = (this.appConfigProvider.getConfig().ticketSection === 'true' || this.appConfigProvider.getConfig().ticketSection === true) ? true : false;
|
|
495
497
|
this.isWhatsappTemplatesEnabled = (this.appConfigProvider.getConfig().whatsappTemplatesSection === 'true' || this.appConfigProvider.getConfig().whatsappTemplatesSection === true) ? true : false;
|
|
496
|
-
|
|
498
|
+
this.fileUploadAccept = this.appConfigProvider.getConfig().fileUploadAccept
|
|
499
|
+
|
|
497
500
|
this.cannedResponsesService.initialize(appconfig.apiUrl)
|
|
498
501
|
|
|
499
502
|
if (checkPlatformIsMobile()) {
|
|
@@ -522,10 +525,10 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
522
525
|
// this.initConversationsHandler(); // nk
|
|
523
526
|
if (this.conversationWith) {
|
|
524
527
|
this.disableTextarea = false
|
|
528
|
+
this.startConversation();
|
|
525
529
|
this._getProjectIdByConversationWith(this.conversationWith)
|
|
526
530
|
this.initConversationHandler()
|
|
527
531
|
this.initGroupsHandler();
|
|
528
|
-
this.startConversation();
|
|
529
532
|
this.initSubscriptions();
|
|
530
533
|
this.getLeadDetail();
|
|
531
534
|
this.initializeTyping();
|
|
@@ -536,6 +539,7 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
|
|
|
536
539
|
}
|
|
537
540
|
|
|
538
541
|
_getProjectIdByConversationWith(conversationWith: string) {
|
|
542
|
+
console.log('[CONVS-DETAIL] - _getProjectIdByConversationWith conversationWith', conversationWith, this.channelType)
|
|
539
543
|
if (this.channelType !== TYPE_DIRECT && !this.conversationWith.startsWith('group-')) {
|
|
540
544
|
this.tiledeskService.getProjectIdByConvRecipient(conversationWith).subscribe((res) => {
|
|
541
545
|
this.logger.log('[CONVS-DETAIL] - GET PROJECTID BY CONV RECIPIENT RES + projectId', res, res.id_project)
|
|
Binary file
|
|
@@ -34,9 +34,12 @@ 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>;
|
|
41
44
|
abstract deleteProfile(userId: string, path: string): Promise<any>
|
|
42
45
|
}
|
|
@@ -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,36 @@ 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
|
+
|
|
195
326
|
public async deleteProfile(userId: string, path: string): Promise<any>{
|
|
196
327
|
const that = this;
|
|
197
328
|
const file_name_photo = 'photo.jpg';
|
|
@@ -219,13 +350,5 @@ export class FirebaseUploadService extends UploadService {
|
|
|
219
350
|
})
|
|
220
351
|
}
|
|
221
352
|
|
|
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
353
|
|
|
231
354
|
}
|
|
@@ -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,12 +48,11 @@ 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
54
|
that.http.post(url, formData, requestOptions).subscribe(data => {
|
|
53
|
-
const downloadURL = this.
|
|
55
|
+
const downloadURL = this.URL_TILEDESK_UPLOAD + 'images?path=' + encodeURIComponent(data?.['filename']);
|
|
54
56
|
resolve({downloadURL : downloadURL, src: downloadURL})
|
|
55
57
|
// that.BSStateUpload.next({upload: upload});
|
|
56
58
|
}, (error) => {
|
|
@@ -58,13 +60,12 @@ export class NativeUploadService extends UploadService {
|
|
|
58
60
|
});
|
|
59
61
|
});
|
|
60
62
|
} else {
|
|
61
|
-
this.logger.log('[NATIVE UPLOAD] - upload new file')
|
|
62
63
|
//USE FILE API
|
|
63
|
-
const url = this.
|
|
64
|
+
const url = this.URL_TILEDESK_UPLOAD + 'files/users'
|
|
64
65
|
return new Promise((resolve, reject) => {
|
|
65
66
|
that.http.post(url, formData, requestOptions).subscribe(data => {
|
|
66
|
-
const src = this.
|
|
67
|
-
const downloadURL = this.
|
|
67
|
+
const src = this.URL_TILEDESK_UPLOAD + 'files?path=' + encodeURI(data['filename']);
|
|
68
|
+
const downloadURL = this.URL_TILEDESK_UPLOAD + 'files/download' + '?path=' + encodeURI(data['filename']);
|
|
68
69
|
resolve({downloadURL : downloadURL, src: src})
|
|
69
70
|
// that.BSStateUpload.next({upload: upload});
|
|
70
71
|
}, (error) => {
|
|
@@ -76,6 +77,62 @@ export class NativeUploadService extends UploadService {
|
|
|
76
77
|
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
uploadFile(userId: string, upload: UploadModel): Promise<{downloadURL: string, src: string}> {
|
|
81
|
+
this.logger.log('[NATIVE UPLOAD] - upload new image/file ... upload', upload)
|
|
82
|
+
const headers = new HttpHeaders({
|
|
83
|
+
Authorization: this.tiledeskToken,
|
|
84
|
+
//'Content-Type': 'multipart/form-data',
|
|
85
|
+
});
|
|
86
|
+
const requestOptions = { headers: headers };
|
|
87
|
+
const formData = new FormData();
|
|
88
|
+
formData.append('file', upload.file);
|
|
89
|
+
|
|
90
|
+
const that = this;
|
|
91
|
+
const url = this.URL_TILEDESK_FILE + '/chat'
|
|
92
|
+
return new Promise((resolve, reject) => {
|
|
93
|
+
that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
|
|
94
|
+
next: (data) => {
|
|
95
|
+
const downloadURL = this.getBaseUrl() + 'files' + '?path=' + encodeURIComponent(data['filename']);
|
|
96
|
+
resolve({downloadURL : downloadURL, src: downloadURL})
|
|
97
|
+
},
|
|
98
|
+
error: (error) => {
|
|
99
|
+
reject(error)
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
uploadAsset(userId: string, upload: UploadModel, expiration: number = 60): Promise<{downloadURL: string, src: string}> {
|
|
106
|
+
this.logger.log('[NATIVE UPLOAD] - upload new asset ... upload', upload, 'expiration:', expiration)
|
|
107
|
+
const headers = new HttpHeaders({
|
|
108
|
+
Authorization: this.tiledeskToken,
|
|
109
|
+
});
|
|
110
|
+
const requestOptions = { headers: headers };
|
|
111
|
+
const formData = new FormData();
|
|
112
|
+
formData.append('file', upload.file);
|
|
113
|
+
|
|
114
|
+
const that = this;
|
|
115
|
+
const url = this.URL_TILEDESK_FILE + `/assets?expiration=${expiration}`
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
that.http.post(url, formData, requestOptions).pipe(first()).subscribe({
|
|
118
|
+
next: (data) => {
|
|
119
|
+
// API responses can vary; try common fields first, otherwise fallback to filename/path.
|
|
120
|
+
const directUrl = data?.['downloadURL'] || data?.['url'] || data?.['src'];
|
|
121
|
+
const filenameOrPath = data?.['filename'] || data?.['path'];
|
|
122
|
+
const downloadURL = directUrl || (filenameOrPath ? (this.getBaseUrl() + 'files' + '?path=' + encodeURIComponent(filenameOrPath)) : null);
|
|
123
|
+
if (!downloadURL) {
|
|
124
|
+
reject(new Error('[NATIVE UPLOAD] uploadAsset: unexpected response payload'))
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
resolve({ downloadURL: downloadURL, src: downloadURL })
|
|
128
|
+
},
|
|
129
|
+
error: (error) => {
|
|
130
|
+
reject(error)
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
79
136
|
uploadProfile(userId: string, upload: UploadModel): Promise<any> {
|
|
80
137
|
this.logger.log('[NATIVE UPLOAD] - upload new photo profile ... upload', upload)
|
|
81
138
|
const headers = new HttpHeaders({
|
|
@@ -88,14 +145,18 @@ export class NativeUploadService extends UploadService {
|
|
|
88
145
|
|
|
89
146
|
// USE IMAGE API
|
|
90
147
|
const that = this;
|
|
91
|
-
const
|
|
148
|
+
const botId = userId?.startsWith('bot_') ? userId.substring('bot_'.length) : userId
|
|
149
|
+
const url = this.URL_TILEDESK_FILE + `/users/photo?bot_id=${botId}`
|
|
92
150
|
return new Promise((resolve, reject) => {
|
|
93
|
-
that.http.put(url, formData, requestOptions).subscribe(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
151
|
+
that.http.put(url, formData, requestOptions).pipe(first()).subscribe({
|
|
152
|
+
next: (data) => {
|
|
153
|
+
const downloadURL = this.getBaseUrl() + 'files?path=' + data['thumbnail'];
|
|
154
|
+
resolve(downloadURL)
|
|
155
|
+
// that.BSStateUpload.next({upload: upload});
|
|
156
|
+
},
|
|
157
|
+
error: (error) => {
|
|
158
|
+
reject(error)
|
|
159
|
+
}
|
|
99
160
|
});
|
|
100
161
|
});
|
|
101
162
|
}
|
|
@@ -110,7 +171,7 @@ export class NativeUploadService extends UploadService {
|
|
|
110
171
|
|
|
111
172
|
//USE IMAGE API
|
|
112
173
|
const that = this;
|
|
113
|
-
const url = this.
|
|
174
|
+
const url = this.URL_TILEDESK_UPLOAD + 'images/users' + '?path=' + path.split('path=')[1]
|
|
114
175
|
return new Promise((resolve, reject) => {
|
|
115
176
|
that.http.delete(url, requestOptions).subscribe(data => {
|
|
116
177
|
// const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
|
|
@@ -122,6 +183,31 @@ export class NativeUploadService extends UploadService {
|
|
|
122
183
|
});
|
|
123
184
|
}
|
|
124
185
|
|
|
186
|
+
deleteFile(userId: string, path: string): Promise<any>{
|
|
187
|
+
this.logger.log('[NATIVE UPLOAD] - delete image ... upload', userId)
|
|
188
|
+
const headers = new HttpHeaders({
|
|
189
|
+
Authorization: this.tiledeskToken,
|
|
190
|
+
//'Content-Type': 'multipart/form-data',
|
|
191
|
+
});
|
|
192
|
+
const requestOptions = { headers: headers };
|
|
193
|
+
|
|
194
|
+
//USE IMAGE API
|
|
195
|
+
const that = this;
|
|
196
|
+
const url = this.URL_TILEDESK_FILE + '?path=' + path.split('path=')[1]
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
that.http.delete(url, requestOptions).pipe(first()).subscribe({
|
|
199
|
+
next: (data) => {
|
|
200
|
+
// const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
|
|
201
|
+
resolve(true)
|
|
202
|
+
// that.BSStateUpload.next({upload: upload});
|
|
203
|
+
},
|
|
204
|
+
error: (error) => {
|
|
205
|
+
reject(error)
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
125
211
|
deleteProfile(userId: string, path: string): Promise<any>{
|
|
126
212
|
this.logger.log('[NATIVE UPLOAD] - delete image ... upload', userId)
|
|
127
213
|
const headers = new HttpHeaders({
|
|
@@ -132,14 +218,17 @@ export class NativeUploadService extends UploadService {
|
|
|
132
218
|
|
|
133
219
|
//USE IMAGE API
|
|
134
220
|
const that = this;
|
|
135
|
-
const url = this.
|
|
221
|
+
const url = this.URL_TILEDESK_FILE + '?path=' + "uploads/users/"+ userId + "/images/photo.jpg"
|
|
136
222
|
return new Promise((resolve, reject) => {
|
|
137
|
-
that.http.delete(url, requestOptions).subscribe(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
223
|
+
that.http.delete(url, requestOptions).pipe(first()).subscribe({
|
|
224
|
+
next: (data) => {
|
|
225
|
+
// const downloadURL = this.URL_TILEDESK_IMAGES + '?path=' + data['filename'];
|
|
226
|
+
resolve(true)
|
|
227
|
+
// that.BSStateUpload.next({upload: upload});
|
|
228
|
+
},
|
|
229
|
+
error: (error) => {
|
|
230
|
+
reject(error)
|
|
231
|
+
}
|
|
143
232
|
});
|
|
144
233
|
});
|
|
145
234
|
}
|