From 5365c6c7e63b56ad84a71dd06612bd970a65a672 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 7 Oct 2021 14:14:07 +0300 Subject: [PATCH] update file download service --- .editorconfig | 4 + .eslintrc.json | 1 + .../downloads-list-screen.component.ts | 50 +++++++------ .../file-download-btn.component.ts | 5 +- .../upload-download/model/download-status.ts | 50 +++++++++++++ .../model/download-status.wrapper.ts | 53 ------------- .../services/file-download.service.ts | 74 ++++++++++--------- libs/red-ui-http/src/lib/api.module.ts | 2 - .../src/lib/model/downloadResponse.ts | 2 +- .../src/lib/model/downloadStatus.ts | 50 ++++++------- .../src/lib/model/downloadStatusResponse.ts | 4 +- .../src/lib/model/prepareDownloadRequest.ts | 6 +- 12 files changed, 154 insertions(+), 147 deletions(-) create mode 100644 apps/red-ui/src/app/modules/upload-download/model/download-status.ts delete mode 100644 apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts diff --git a/.editorconfig b/.editorconfig index 7ac0fdd9b..49601a81f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,5 +14,9 @@ max_line_length = 140 max_line_length = off trim_trailing_whitespace = false +[*.ts] +ij_typescript_use_double_quotes = false +ij_typescript_enforce_trailing_comma = keep + [{*.json, .prettierrc, .eslintrc}] indent_size = 2 diff --git a/.eslintrc.json b/.eslintrc.json index 925cd52ff..567c024ba 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -184,6 +184,7 @@ "prefer-const": "error", "radix": "error", "curly": "error", + "quotes": ["error", "single"], "comma-dangle": [ "error", { diff --git a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts index e30bb92fd..97d23d6be 100644 --- a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts +++ b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts @@ -1,22 +1,34 @@ -import { Component, forwardRef, Injector, OnInit } from '@angular/core'; +import { Component, forwardRef, Injector } from '@angular/core'; import { FileDownloadService } from '@upload-download/services/file-download.service'; -import { DownloadStatusWrapper } from '@upload-download/model/download-status.wrapper'; -import { DownloadControllerService } from '@redaction/red-ui-http'; -import { CircleButtonTypes, DefaultListingServices, ListingComponent, LoadingService, TableColumnConfig } from '@iqser/common-ui'; +import { DownloadStatus } from '@upload-download/model/download-status'; +import { + CircleButtonTypes, + DefaultListingServicesTmp, + EntitiesService, + ListingComponent, + LoadingService, + TableColumnConfig, +} from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { timer } from 'rxjs'; import { RouterHistoryService } from '@services/router-history.service'; @Component({ selector: 'redaction-downloads-list-screen', templateUrl: './downloads-list-screen.component.html', styleUrls: ['./downloads-list-screen.component.scss'], - providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DownloadsListScreenComponent) }], + providers: [ + ...DefaultListingServicesTmp, + { provide: EntitiesService, useExisting: FileDownloadService }, + { + provide: ListingComponent, + useExisting: forwardRef(() => DownloadsListScreenComponent), + }, + ], }) -export class DownloadsListScreenComponent extends ListingComponent implements OnInit { +export class DownloadsListScreenComponent extends ListingComponent { readonly circleButtonTypes = CircleButtonTypes; readonly tableHeaderLabel = _('downloads-list.table-header.title'); - readonly tableColumnConfigs: TableColumnConfig[] = [ + readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('downloads-list.table-col-names.name'), width: '2fr' }, { label: _('downloads-list.table-col-names.size') }, { label: _('downloads-list.table-col-names.date') }, @@ -28,37 +40,27 @@ export class DownloadsListScreenComponent extends ListingComponent { - await this._loadData(); - }); - this._loadingService.stop(); - } - - downloadItem(download: DownloadStatusWrapper) { + downloadItem(download: DownloadStatus) { this._loadingService.loadWhile(this.fileDownloadService.performDownload(download)); } - deleteItems(downloads?: DownloadStatusWrapper[]) { + deleteItems(downloads?: DownloadStatus[]) { this._loadingService.loadWhile(this._deleteItems(downloads)); } - private async _deleteItems(downloads?: DownloadStatusWrapper[]) { + private async _deleteItems(downloads?: DownloadStatus[]) { const storageIds = (downloads || this.listingService.selected).map(d => d.storageId); - await this._downloadControllerService.deleteDownload({ storageIds }).toPromise(); + await this.fileDownloadService.delete({ storageIds }).toPromise(); this.listingService.setSelected([]); await this._loadData(); } private async _loadData() { - await this.fileDownloadService.getDownloadStatus().toPromise(); - this.entitiesService.setEntities(this.fileDownloadService.downloads); + await this.fileDownloadService.loadAll().toPromise(); } } diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts index c03b703ce..96faf040d 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts @@ -45,7 +45,10 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr downloadFiles($event: MouseEvent) { $event.stopPropagation(); this.addSubscription = this._fileDownloadService - .downloadFiles(this.files, this.dossier) + .downloadFiles( + this.files.map(f => f.fileId), + this.dossier.dossierId, + ) .subscribe(() => this._toaster.info(_('download-status.queued'))); } } diff --git a/apps/red-ui/src/app/modules/upload-download/model/download-status.ts b/apps/red-ui/src/app/modules/upload-download/model/download-status.ts new file mode 100644 index 000000000..7dec1bd37 --- /dev/null +++ b/apps/red-ui/src/app/modules/upload-download/model/download-status.ts @@ -0,0 +1,50 @@ +import { DownloadFileType, DownloadStatusType, IDownloadStatus, List } from '@redaction/red-ui-http'; +import { IListable } from '@iqser/common-ui'; + +export class DownloadStatus implements IDownloadStatus, IListable { + readonly creationDate?: string; + readonly dossierId?: string; + readonly downloadFileTypes?: List; + readonly fileIds?: List; + readonly fileSize?: number; + readonly filename?: string; + readonly lastDownload?: string; + readonly mimeType?: string; + readonly status?: DownloadStatusType; + readonly storageId?: string; + readonly userId?: string; + readonly size?: string; + inProgress: boolean; + + constructor(downloadStatus: IDownloadStatus) { + this.creationDate = downloadStatus.creationDate; + this.dossierId = downloadStatus.dossierId; + this.downloadFileTypes = downloadStatus.downloadFileTypes; + this.fileIds = downloadStatus.fileIds; + this.fileSize = downloadStatus.fileSize; + this.filename = downloadStatus.filename; + this.lastDownload = downloadStatus.lastDownload; + this.mimeType = downloadStatus.mimeType; + this.status = downloadStatus.status; + this.storageId = downloadStatus.storageId; + this.userId = downloadStatus.userId; + this.size = this._size; + } + + get id() { + return this.storageId; + } + + get searchKey(): string { + return this.storageId; + } + + get isReady() { + return this.status === 'READY'; + } + + private get _size() { + const i = this.fileSize === 0 ? 0 : Math.floor(Math.log(this.fileSize) / Math.log(1024)); + return (this.fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + } +} diff --git a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts b/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts deleted file mode 100644 index d81e5f778..000000000 --- a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { DownloadStatus } from '@redaction/red-ui-http'; -import { IListable } from '@iqser/common-ui'; - -export class DownloadStatusWrapper implements IListable { - inProgress: boolean; - - constructor(private _downloadStatus: DownloadStatus) {} - - get id() { - return this.storageId; - } - - get searchKey(): string { - return this.storageId; - } - - get size() { - const i = this._downloadStatus.fileSize === 0 ? 0 : Math.floor(Math.log(this._downloadStatus.fileSize) / Math.log(1024)); - return (this._downloadStatus.fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; - } - - get creationDate() { - return this._downloadStatus.creationDate; - } - - get filename() { - return this._downloadStatus.filename; - } - - get lastDownload() { - return this._downloadStatus.lastDownload; - } - - get mimeType() { - return this._downloadStatus.mimeType; - } - - get dossierId() { - return this._downloadStatus.dossierId; - } - - get isReady() { - return this._downloadStatus.status === 'READY'; - } - - get status() { - return this._downloadStatus.status; - } - - get storageId() { - return this._downloadStatus.storageId; - } -} diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 91bb55e48..205ac900a 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -1,59 +1,57 @@ -import { ApplicationRef, Injectable } from '@angular/core'; -import { DownloadControllerService, FileManagementControllerService } from '@redaction/red-ui-http'; +import { Injectable, Injector } from '@angular/core'; +import { + DownloadResponse, + DownloadStatusResponse, + IDownloadStatus, + PrepareDownloadRequest, + RemoveDownloadRequest, +} from '@redaction/red-ui-http'; import { interval, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; -import { TranslateService } from '@ngx-translate/core'; -import { Dossier } from '@state/model/dossier'; -import { File } from '@models/file/file'; -import { mergeMap, tap } from 'rxjs/operators'; -import { DownloadStatusWrapper } from '../model/download-status.wrapper'; -import { AppStateService } from '@state/app-state.service'; +import { map, mergeMap, tap } from 'rxjs/operators'; +import { DownloadStatus } from '../model/download-status'; import { KeycloakService } from 'keycloak-angular'; import { UserService } from '@services/user.service'; -import { List } from '@iqser/common-ui'; +import { EntitiesService, List, RequiredParam, Validate } from '@iqser/common-ui'; @Injectable() -export class FileDownloadService { - downloads: DownloadStatusWrapper[] = []; - - hasPendingDownloads; +export class FileDownloadService extends EntitiesService { + hasPendingDownloads = false; constructor( private readonly _userService: UserService, - private readonly _applicationRef: ApplicationRef, private readonly _keycloakService: KeycloakService, - private readonly _appStateService: AppStateService, - private readonly _translateService: TranslateService, private readonly _configService: ConfigService, - private readonly _downloadControllerService: DownloadControllerService, - private readonly _fileManagementControllerService: FileManagementControllerService, + protected readonly _injector: Injector, ) { + super(_injector, DownloadStatus, 'async/download'); interval(5000).subscribe(() => { if (_userService.currentUser.isUser) { - this.getDownloadStatus().subscribe(() => {}); + this.loadAll().subscribe(() => {}); } }); } - downloadFiles(files: List, dossier: Dossier): Observable { - return this._downloadControllerService - .prepareDownload({ - fileIds: files.map(f => f.fileId), - dossierId: dossier.id, - }) - .pipe(mergeMap(() => this.getDownloadStatus())); + downloadFiles(fileIds: List, dossierId: string): Observable { + return this.prepareDownload({ + fileIds, + dossierId, + }).pipe(mergeMap(() => this.loadAll())); } - getDownloadStatus() { - return this._downloadControllerService.getDownloadStatus().pipe( - tap(statusResponse => { - this.downloads = statusResponse.downloadStatus.map(d => new DownloadStatusWrapper(d)); - this.hasPendingDownloads = !!this.downloads.find(f => !f.lastDownload && f.isReady); - }), + loadAll(): Observable { + return this.getStatuses().pipe( + map(entities => entities.map(entity => new DownloadStatus(entity))), + tap(entities => this.setEntities(entities)), + tap(() => (this.hasPendingDownloads = !!this.all.find(f => !f.lastDownload && f.isReady))), ); } - async performDownload(status: DownloadStatusWrapper) { + getStatuses(): Observable { + return super._getOne(['status']).pipe(map(res => res.downloadStatus)); + } + + async performDownload(status: DownloadStatus) { const token = await this._keycloakService.getToken(); const anchor = document.createElement('a'); anchor.href = `${this._configService.values.API_URL}/async/download?access_token=${encodeURIComponent( @@ -66,4 +64,14 @@ export class FileDownloadService { anchor.click(); document.body.removeChild(anchor); } + + @Validate() + prepareDownload(@RequiredParam() body: PrepareDownloadRequest): Observable { + return this._post(body, `${this._defaultModelPath}/prepare`); + } + + @Validate() + delete(@RequiredParam() body: RemoveDownloadRequest): Observable { + return super._post(body, `${this._defaultModelPath}/delete`); + } } diff --git a/libs/red-ui-http/src/lib/api.module.ts b/libs/red-ui-http/src/lib/api.module.ts index fe2fb53ce..5ff95bf33 100644 --- a/libs/red-ui-http/src/lib/api.module.ts +++ b/libs/red-ui-http/src/lib/api.module.ts @@ -1,7 +1,6 @@ import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { Configuration } from './configuration'; import { HttpClient } from '@angular/common/http'; -import { DownloadControllerService } from './api/downloadController.service'; import { FileManagementControllerService } from './api/fileManagementController.service'; import { GeneralSettingsControllerService } from './api/generalSettingsController.service'; import { InfoControllerService } from './api/infoController.service'; @@ -26,7 +25,6 @@ import { StatusReportControllerService } from './api/statusReportController.serv declarations: [], exports: [], providers: [ - DownloadControllerService, FileManagementControllerService, GeneralSettingsControllerService, InfoControllerService, diff --git a/libs/red-ui-http/src/lib/model/downloadResponse.ts b/libs/red-ui-http/src/lib/model/downloadResponse.ts index 89677868c..b875b7ac0 100644 --- a/libs/red-ui-http/src/lib/model/downloadResponse.ts +++ b/libs/red-ui-http/src/lib/model/downloadResponse.ts @@ -11,5 +11,5 @@ */ export interface DownloadResponse { - storageId?: string; + readonly storageId?: string; } diff --git a/libs/red-ui-http/src/lib/model/downloadStatus.ts b/libs/red-ui-http/src/lib/model/downloadStatus.ts index c84a2913a..583eaf860 100644 --- a/libs/red-ui-http/src/lib/model/downloadStatus.ts +++ b/libs/red-ui-http/src/lib/model/downloadStatus.ts @@ -9,35 +9,27 @@ * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ +import { DownloadFileType } from './dossier'; +import { List } from '../red-types'; -export interface DownloadStatus { - creationDate?: string; - dossierId?: string; - downloadFileTypes?: Array; - fileIds?: Array; - fileSize?: number; - filename?: string; - lastDownload?: string; - mimeType?: string; - status?: DownloadStatus.StatusEnum; - storageId?: string; - userId?: string; +export interface IDownloadStatus { + readonly creationDate?: string; + readonly dossierId?: string; + readonly downloadFileTypes?: List; + readonly fileIds?: List; + readonly fileSize?: number; + readonly filename?: string; + readonly lastDownload?: string; + readonly mimeType?: string; + readonly status?: DownloadStatusType; + readonly storageId?: string; + readonly userId?: string; } -export namespace DownloadStatus { - export type DownloadFileTypesEnum = 'ANNOTATED' | 'FLATTEN' | 'ORIGINAL' | 'PREVIEW' | 'REDACTED'; - export const DownloadFileTypesEnum = { - ANNOTATED: 'ANNOTATED' as DownloadFileTypesEnum, - FLATTEN: 'FLATTEN' as DownloadFileTypesEnum, - ORIGINAL: 'ORIGINAL' as DownloadFileTypesEnum, - PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, - REDACTED: 'REDACTED' as DownloadFileTypesEnum, - }; - export type StatusEnum = 'FAILED' | 'GENERATING' | 'QUEUED' | 'READY'; - export const StatusEnum = { - FAILED: 'FAILED' as StatusEnum, - GENERATING: 'GENERATING' as StatusEnum, - QUEUED: 'QUEUED' as StatusEnum, - READY: 'READY' as StatusEnum, - }; -} +export const DownloadStatuses = { + FAILED: 'FAILED', + GENERATING: 'GENERATING', + QUEUED: 'QUEUED', + READY: 'READY', +} as const; +export type DownloadStatusType = keyof typeof DownloadStatuses; diff --git a/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts b/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts index 7945e9202..a35b3942d 100644 --- a/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts +++ b/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts @@ -9,8 +9,8 @@ * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ -import { DownloadStatus } from './downloadStatus'; +import { IDownloadStatus } from './downloadStatus'; export interface DownloadStatusResponse { - downloadStatus?: Array; + downloadStatus?: IDownloadStatus[]; } diff --git a/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts b/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts index f5e9b4f20..6fe625402 100644 --- a/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts +++ b/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts @@ -10,10 +10,12 @@ * Do not edit the class manually. */ +import { List } from '../red-types'; + /** * Object containing information on which file and report types should be included in the download. */ export interface PrepareDownloadRequest { - dossierId?: string; - fileIds?: Array; + readonly dossierId?: string; + readonly fileIds?: List; }