From 3bac6cc1b3d75e431c63a745e9065ddb865df685 Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 23 Mar 2020 17:38:36 +0100 Subject: [PATCH] 69940: Process files request --- src/app/core/core.module.ts | 2 + .../process-files-response-parsing.service.ts | 39 +++++++++++++++++++ .../data/processes/process-data.service.ts | 38 ++++++++++++++++++ src/app/core/data/request.models.ts | 10 +++++ .../detail/process-detail.component.ts | 20 ++++++++-- 5 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/app/core/data/process-files-response-parsing.service.ts diff --git a/src/app/core/core.module.ts b/src/app/core/core.module.ts index 99931d8c6c..c2d14663e6 100644 --- a/src/app/core/core.module.ts +++ b/src/app/core/core.module.ts @@ -138,6 +138,7 @@ import { Script } from '../process-page/scripts/script.model'; import { Process } from '../process-page/processes/process.model'; import { ProcessDataService } from './data/processes/process-data.service'; import { ScriptDataService } from './data/processes/script-data.service'; +import { ProcessFilesResponseParsingService } from './data/process-files-response-parsing.service'; /** * When not in production, endpoint responses can be mocked for testing purposes @@ -260,6 +261,7 @@ const PROVIDERS = [ ItemTypeDataService, ProcessDataService, ScriptDataService, + ProcessFilesResponseParsingService, // register AuthInterceptor as HttpInterceptor { provide: HTTP_INTERCEPTORS, diff --git a/src/app/core/data/process-files-response-parsing.service.ts b/src/app/core/data/process-files-response-parsing.service.ts new file mode 100644 index 0000000000..430869290e --- /dev/null +++ b/src/app/core/data/process-files-response-parsing.service.ts @@ -0,0 +1,39 @@ +import { ResponseParsingService } from './parsing.service'; +import { RestRequest } from './request.models'; +import { GenericSuccessResponse, RestResponse } from '../cache/response.models'; +import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model'; +import { isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { PaginatedList } from './paginated-list'; +import { PageInfo } from '../shared/page-info.model'; +import { Injectable } from '@angular/core'; + +@Injectable() +/** + * A ResponseParsingService used to parse DSpaceRESTV2Response coming from the REST API to a GenericSuccessResponse + * containing a PaginatedList of a process's output files + */ +export class ProcessFilesResponseParsingService implements ResponseParsingService { + parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { + const payload = data.payload; + + let page; + if (isNotEmpty(payload._embedded) && isNotEmpty(Object.keys(payload._embedded))) { + const bitstreams = payload._embedded[Object.keys(payload._embedded)[0]]; + + if (isNotEmpty(bitstreams)) { + page = new PaginatedList(Object.assign(new PageInfo(), { + elementsPerPage: bitstreams.length, + totalElements: bitstreams.length, + totalPages: 1, + currentPage: 1 + }), bitstreams); + } + } + + if (isEmpty(page)) { + page = new PaginatedList(new PageInfo(), []); + } + + return new GenericSuccessResponse(page, data.statusCode, data.statusText); + } +} diff --git a/src/app/core/data/processes/process-data.service.ts b/src/app/core/data/processes/process-data.service.ts index 7d1d08eeca..48c1d502cc 100644 --- a/src/app/core/data/processes/process-data.service.ts +++ b/src/app/core/data/processes/process-data.service.ts @@ -12,6 +12,14 @@ import { DefaultChangeAnalyzer } from '../default-change-analyzer.service'; import { Process } from '../../../process-page/processes/process.model'; import { dataService } from '../../cache/builders/build-decorators'; import { PROCESS } from '../../../process-page/processes/process.resource-type'; +import { Observable } from 'rxjs/internal/Observable'; +import { map, switchMap } from 'rxjs/operators'; +import { ProcessFilesRequest, RestRequest } from '../request.models'; +import { configureRequest, filterSuccessfulResponses } from '../../shared/operators'; +import { GenericSuccessResponse } from '../../cache/response.models'; +import { PaginatedList } from '../paginated-list'; +import { Bitstream } from '../../shared/bitstream.model'; +import { RemoteData } from '../remote-data'; @Injectable() @dataService(PROCESS) @@ -29,4 +37,34 @@ export class ProcessDataService extends DataService { protected comparator: DefaultChangeAnalyzer) { super(); } + + /** + * Get the endpoint for a process his files + * @param processId The ID of the process + */ + getFilesEndpoint(processId: string): Observable { + return this.getBrowseEndpoint().pipe( + switchMap((href) => this.halService.getEndpoint('files', `${href}/${processId}`)) + ); + } + + /** + * Get a process his output files + * @param processId The ID of the process + */ + getFiles(processId: string): Observable>> { + const request$ = this.getFilesEndpoint(processId).pipe( + map((href) => new ProcessFilesRequest(this.requestService.generateRequestId(), href)), + configureRequest(this.requestService) + ); + const requestEntry$ = request$.pipe( + switchMap((request: RestRequest) => this.requestService.getByHref(request.href)) + ); + const payload$ = requestEntry$.pipe( + filterSuccessfulResponses(), + map((response: GenericSuccessResponse>) => response.payload) + ); + + return this.rdbService.toRemoteDataObservable(requestEntry$, payload$); + } } diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts index 82149fbbc5..e5706253d5 100644 --- a/src/app/core/data/request.models.ts +++ b/src/app/core/data/request.models.ts @@ -20,6 +20,7 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { TaskResponseParsingService } from '../tasks/task-response-parsing.service'; import { ContentSourceResponseParsingService } from './content-source-response-parsing.service'; import { MappedCollectionsReponseParsingService } from './mapped-collections-reponse-parsing.service'; +import { ProcessFilesResponseParsingService } from './process-files-response-parsing.service'; /* tslint:disable:max-classes-per-file */ @@ -226,6 +227,15 @@ export class MappedCollectionsRequest extends GetRequest { } } +/** + * Request to fetch the files of a process + */ +export class ProcessFilesRequest extends GetRequest { + getResponseParser(): GenericConstructor { + return ProcessFilesResponseParsingService; + } +} + export class ConfigRequest extends GetRequest { constructor(uuid: string, href: string, public options?: HttpOptions) { super(uuid, href, null, options); diff --git a/src/app/process-page/detail/process-detail.component.ts b/src/app/process-page/detail/process-detail.component.ts index 4252138979..e2609c1781 100644 --- a/src/app/process-page/detail/process-detail.component.ts +++ b/src/app/process-page/detail/process-detail.component.ts @@ -3,9 +3,12 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Observable } from 'rxjs/internal/Observable'; import { RemoteData } from '../../core/data/remote-data'; import { Process } from '../processes/process.model'; -import { map } from 'rxjs/operators'; -import { redirectToPageNotFoundOn404 } from '../../core/shared/operators'; +import { map, switchMap } from 'rxjs/operators'; +import { getFirstSucceededRemoteDataPayload, redirectToPageNotFoundOn404 } from '../../core/shared/operators'; import { AlertType } from '../../shared/alert/aletr-type'; +import { ProcessDataService } from '../../core/data/processes/process-data.service'; +import { PaginatedList } from '../../core/data/paginated-list'; +import { Bitstream } from '../../core/shared/bitstream.model'; @Component({ selector: 'ds-process-detail', @@ -27,8 +30,14 @@ export class ProcessDetailComponent implements OnInit { */ processRD$: Observable>; + /** + * The Process's Output Files + */ + filesRD$: Observable>>; + constructor(protected route: ActivatedRoute, - protected router: Router) { + protected router: Router, + protected processService: ProcessDataService) { } /** @@ -40,6 +49,11 @@ export class ProcessDetailComponent implements OnInit { map((data) => data.process as RemoteData), redirectToPageNotFoundOn404(this.router) ); + + this.filesRD$ = this.processRD$.pipe( + getFirstSucceededRemoteDataPayload(), + switchMap((process: Process) => this.processService.getFiles(process.processId)) + ); } }