mirror of https://github.com/Squidex/squidex.git
13 changed files with 348 additions and 137 deletions
@ -0,0 +1,181 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. |
|||
*/ |
|||
|
|||
import { Injectable } from '@angular/core'; |
|||
import { Observable, Subject, Subscription } from 'rxjs'; |
|||
import { distinctUntilChanged, map } from 'rxjs/operators'; |
|||
|
|||
import { |
|||
DateTime, |
|||
DialogService, |
|||
ImmutableArray, |
|||
MathHelper, |
|||
State, |
|||
Types |
|||
} from '@app/framework'; |
|||
|
|||
import { AuthService } from '../services/auth.service'; |
|||
import { AssetDto, AssetsService } from './../services/assets.service'; |
|||
import { AppsState } from './apps.state'; |
|||
import { AssetsState } from './assets.state'; |
|||
|
|||
export interface Upload { |
|||
// Unique id.
|
|||
id: string; |
|||
|
|||
// The name of the asset.
|
|||
name: string; |
|||
|
|||
// The upload subscription.
|
|||
subscription: Subscription; |
|||
|
|||
// The progress.
|
|||
progress: number; |
|||
|
|||
// The status.
|
|||
status: string; |
|||
} |
|||
|
|||
interface Snapshot { |
|||
// The uploads.
|
|||
uploads: UploadList; |
|||
} |
|||
|
|||
type UploadList = ImmutableArray<Upload>; |
|||
type UploadResult = AssetDto | number; |
|||
|
|||
@Injectable() |
|||
export class AssetUploaderState extends State<Snapshot> { |
|||
public uploads = |
|||
this.changes.pipe(map(x => x.uploads), |
|||
distinctUntilChanged()); |
|||
|
|||
constructor( |
|||
private readonly appsState: AppsState, |
|||
private readonly assetsService: AssetsService, |
|||
private readonly authService: AuthService, |
|||
private readonly dialogs: DialogService |
|||
) { |
|||
super({ uploads: ImmutableArray.empty() }); |
|||
} |
|||
|
|||
public stopUpload(upload: Upload) { |
|||
upload.subscription.unsubscribe(); |
|||
|
|||
this.next(s => { |
|||
const uploads = s.uploads.removeBy('id', upload); |
|||
|
|||
return { ...s, uploads }; |
|||
}); |
|||
} |
|||
|
|||
public uploadFile(file: File, target?: AssetsState, now?: DateTime): Observable<UploadResult> { |
|||
const observable = this.assetsService.uploadFile(this.appName, file, this.user, now || DateTime.now()); |
|||
|
|||
let upload: Upload; |
|||
|
|||
const subject = new Subject<UploadResult>(); |
|||
const subscription = observable.subscribe(event => { |
|||
if (Types.isNumber(event)) { |
|||
this.update(upload, { progress: event }); |
|||
} else { |
|||
if (event.isDuplicate) { |
|||
this.dialogs.notifyError('Asset has already been uploaded.'); |
|||
} |
|||
|
|||
if (target) { |
|||
target.add(event); |
|||
} |
|||
} |
|||
|
|||
subject.next(event); |
|||
}, error => { |
|||
subject.error(error); |
|||
|
|||
this.remove(upload, 'failed'); |
|||
}, () => { |
|||
subject.complete(); |
|||
|
|||
this.remove(upload, 'completed'); |
|||
}); |
|||
|
|||
upload = { id: MathHelper.guid(), name: file.name, progress: 1, subscription, status: 'running' }; |
|||
|
|||
this.addUpload(upload); |
|||
|
|||
return subject; |
|||
} |
|||
|
|||
public uploadUpdate(asset: AssetDto, file: File, now?: DateTime): Observable<UploadResult> { |
|||
const observable = this.assetsService.replaceFile(this.appName, asset.id, file, asset.version); |
|||
|
|||
let upload: Upload; |
|||
|
|||
const subject = new Subject<UploadResult>(); |
|||
const subscription = observable.subscribe(event => { |
|||
if (Types.isNumber(event)) { |
|||
this.update(upload, { progress: event }); |
|||
|
|||
subject.next(event); |
|||
} else { |
|||
subject.next(asset.update(event.payload, this.user, event.version, now)); |
|||
} |
|||
|
|||
}, error => { |
|||
subject.error(error); |
|||
|
|||
this.remove(upload, 'failed'); |
|||
}, () => { |
|||
subject.complete(); |
|||
|
|||
this.remove(upload, 'completed'); |
|||
}); |
|||
|
|||
upload = { id: asset.id, name: file.name, progress: 1, subscription, status: 'running' }; |
|||
|
|||
this.addUpload(upload); |
|||
|
|||
return subject; |
|||
} |
|||
|
|||
private remove(upload: Upload, status: string) { |
|||
this.update(upload, { status }); |
|||
|
|||
setTimeout(() => { |
|||
this.next(s => { |
|||
const uploads = s.uploads.removeBy('id', upload); |
|||
|
|||
return { ...s, uploads }; |
|||
}); |
|||
|
|||
}, 10000); |
|||
} |
|||
|
|||
private update(upload: Upload, update: Partial<Upload>) { |
|||
this.next(s => { |
|||
const uploads = s.uploads.replaceBy('id', { ...upload, ...update }); |
|||
|
|||
return { ...s, uploads }; |
|||
}); |
|||
} |
|||
|
|||
private addUpload(upload: Upload) { |
|||
this.next(s => { |
|||
const uploads = s.uploads.push(upload); |
|||
|
|||
return { ...s, uploads }; |
|||
}); |
|||
} |
|||
|
|||
private get appName() { |
|||
return this.appsState.appName; |
|||
} |
|||
|
|||
private get user() { |
|||
return this.authService.user!.token; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue