76150: Implement feedback

This commit is contained in:
Yana De Pauw
2021-01-29 11:05:13 +01:00
committed by Art Lowel
parent 868b7ad37b
commit 3137f3e6c1
6 changed files with 48 additions and 47 deletions

View File

@@ -1,10 +1,11 @@
import { Inject, Injectable } from '@angular/core'; import { Inject, Injectable } from '@angular/core';
import { RawRestResponse } from '../dspace-rest/raw-rest-response.model'; import { RawRestResponse } from '../dspace-rest/raw-rest-response.model';
import { AuthService } from '../auth/auth.service'; import { AuthService } from '../auth/auth.service';
import { take } from 'rxjs/operators'; import { map, take } from 'rxjs/operators';
import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { NativeWindowRef, NativeWindowService } from '../services/window.service';
import { URLCombiner } from '../url-combiner/url-combiner'; import { URLCombiner } from '../url-combiner/url-combiner';
import { hasValue } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { Observable } from 'rxjs/internal/Observable';
/** /**
* Provides utility methods to save files on the client-side. * Provides utility methods to save files on the client-side.
@@ -17,17 +18,16 @@ export class FileService {
) { } ) { }
/** /**
* Combines an URL with a short-lived token and sets the current URL to the newly created one * Combines an URL with a short-lived token and sets the current URL to the newly created one and returns it
* *
* @param url * @param url
* file url * file url
*/ */
downloadFile(url: string) { retrieveFileDownloadLink(url: string): Observable<string> {
this.authService.getShortlivedToken().pipe(take(1)).subscribe((token) => { return this.authService.getShortlivedToken().pipe(take(1), map((token) =>
this._window.nativeWindow.location.href = hasValue(token) ? new URLCombiner(url, `?authentication-token=${token}`).toString() : url; hasValue(token) ? new URLCombiner(url, `?authentication-token=${token}`).toString() : url
}); ));
} }
/** /**
* Derives file name from the http response * Derives file name from the http response
* by looking inside content-disposition * by looking inside content-disposition

View File

@@ -35,7 +35,7 @@ describe('BitstreamDownloadPageComponent', () => {
}); });
fileService = jasmine.createSpyObj('fileService', { fileService = jasmine.createSpyObj('fileService', {
downloadFile: observableOf('content-url-with-headers') retrieveFileDownloadLink: observableOf('content-url-with-headers')
}); });
hardRedirectService = jasmine.createSpyObj('fileService', { hardRedirectService = jasmine.createSpyObj('fileService', {

View File

@@ -1,19 +1,17 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { map } from 'rxjs/operators'; import { filter, map, switchMap, take } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs/internal/Subscription';
import { hasValue, isNotEmpty } from '../empty.util'; import { hasValue, isNotEmpty } from '../empty.util';
import { getRemoteDataPayload, redirectOn4xx } from '../../core/shared/operators'; import { getRemoteDataPayload, redirectOn4xx } from '../../core/shared/operators';
import { Bitstream } from '../../core/shared/bitstream.model'; import { Bitstream } from '../../core/shared/bitstream.model';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';
import { combineLatest as observableCombineLatest, Observable } from 'rxjs'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
import { FileService } from '../../core/shared/file.service'; import { FileService } from '../../core/shared/file.service';
import { HardRedirectService } from '../../core/services/hard-redirect.service'; import { HardRedirectService } from '../../core/services/hard-redirect.service';
import { getForbiddenRoute } from '../../app-routing-paths'; import { getForbiddenRoute } from '../../app-routing-paths';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { tap } from 'rxjs/internal/operators/tap';
@Component({ @Component({
selector: 'ds-bitstream-download-page', selector: 'ds-bitstream-download-page',
@@ -22,12 +20,11 @@ import { tap } from 'rxjs/internal/operators/tap';
/** /**
* Page component for downloading a bitstream * Page component for downloading a bitstream
*/ */
export class BitstreamDownloadPageComponent implements OnInit, OnDestroy { export class BitstreamDownloadPageComponent implements OnInit {
bitstream$: Observable<Bitstream>; bitstream$: Observable<Bitstream>;
bitstreamRD$: Observable<RemoteData<Bitstream>>; bitstreamRD$: Observable<RemoteData<Bitstream>>;
subs: Subscription[] = [];
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
@@ -46,22 +43,34 @@ export class BitstreamDownloadPageComponent implements OnInit, OnDestroy {
map((data) => data.bitstream)); map((data) => data.bitstream));
this.bitstream$ = this.bitstreamRD$.pipe( this.bitstream$ = this.bitstreamRD$.pipe(
tap((v) => console.log('dfdf', v)),
redirectOn4xx(this.router, this.auth), redirectOn4xx(this.router, this.auth),
getRemoteDataPayload() getRemoteDataPayload()
); );
this.subs.push(this.bitstream$.subscribe((bitstream) => { this.bitstream$.pipe(
switchMap((bitstream: Bitstream) => {
const isAuthorized$ = this.authorizationService.isAuthorized(FeatureID.CanDownload, isNotEmpty(bitstream) ? bitstream.self : undefined); const isAuthorized$ = this.authorizationService.isAuthorized(FeatureID.CanDownload, isNotEmpty(bitstream) ? bitstream.self : undefined);
const isLoggedIn$ = this.auth.isAuthenticated(); const isLoggedIn$ = this.auth.isAuthenticated();
return observableCombineLatest([isAuthorized$, isLoggedIn$, observableOf(bitstream)]);
this.subs.push(observableCombineLatest(isAuthorized$, isLoggedIn$) }),
.subscribe(([isAuthorized, isLoggedIn]) => { filter(([isAuthorized, isLoggedIn, bitstream]: [boolean, boolean, Bitstream]) => hasValue(isAuthorized) && hasValue(isLoggedIn)),
take(1),
switchMap(([isAuthorized, isLoggedIn, bitstream]: [boolean, boolean, Bitstream]) => {
if (isAuthorized && isLoggedIn) { if (isAuthorized && isLoggedIn) {
const fileLink$ = this.fileService.downloadFile(bitstream._links.content.href); return this.fileService.retrieveFileDownloadLink(bitstream._links.content.href).pipe(
this.subs.push(fileLink$.subscribe((fileLink) => { filter((fileLink) => hasValue(fileLink)),
this.hardRedirectService.redirect(fileLink); take(1),
map((fileLink) => {
return [isAuthorized, isLoggedIn, bitstream, fileLink];
// return [isAuthorized, isLoggedIn, bitstream];
})); }));
} else {
return [[isAuthorized, isLoggedIn, bitstream, '']];
}
})
).subscribe(([isAuthorized, isLoggedIn, bitstream, fileLink]: [boolean, boolean, Bitstream, string]) => {
if (isAuthorized && isLoggedIn && isNotEmpty(fileLink)) {
this.hardRedirectService.redirect(fileLink);
} else if (isAuthorized && !isLoggedIn) { } else if (isAuthorized && !isLoggedIn) {
this.hardRedirectService.redirect(bitstream._links.content.href); this.hardRedirectService.redirect(bitstream._links.content.href);
} else if (!isAuthorized && isLoggedIn) { } else if (!isAuthorized && isLoggedIn) {
@@ -70,14 +79,6 @@ export class BitstreamDownloadPageComponent implements OnInit, OnDestroy {
this.auth.setRedirectUrl(this.router.url); this.auth.setRedirectUrl(this.router.url);
this.router.navigateByUrl('login'); this.router.navigateByUrl('login');
} }
})); });
}));
}
ngOnDestroy(): void {
this.subs
.filter((subscription) => hasValue(subscription))
.forEach((subscription) => subscription.unsubscribe());
} }
} }

View File

@@ -82,7 +82,7 @@ export class ItemDetailPreviewComponent {
first()) first())
.subscribe((url) => { .subscribe((url) => {
const fileUrl = `${url}/${uuid}/content`; const fileUrl = `${url}/${uuid}/content`;
this.fileService.downloadFile(fileUrl); this.fileService.retrieveFileDownloadLink(fileUrl);
}); });
} }

View File

@@ -41,7 +41,7 @@ import { FormBuilderService } from '../../../../shared/form/builder/form-builder
function getMockFileService(): FileService { function getMockFileService(): FileService {
return jasmine.createSpyObj('FileService', { return jasmine.createSpyObj('FileService', {
downloadFile: jasmine.createSpy('downloadFile'), retrieveFileDownloadLink: jasmine.createSpy('retrieveFileDownloadLink'),
getFileNameFromResponseContentDisposition: jasmine.createSpy('getFileNameFromResponseContentDisposition') getFileNameFromResponseContentDisposition: jasmine.createSpy('getFileNameFromResponseContentDisposition')
}); });
} }
@@ -232,7 +232,7 @@ describe('SubmissionSectionUploadFileComponent test suite', () => {
tick(); tick();
expect(fileService.downloadFile).toHaveBeenCalled(); expect(fileService.retrieveFileDownloadLink).toHaveBeenCalled();
})); }));
it('should save Bitstream File data properly when form is valid', fakeAsync(() => { it('should save Bitstream File data properly when form is valid', fakeAsync(() => {

View File

@@ -224,7 +224,7 @@ export class SubmissionSectionUploadFileComponent implements OnChanges, OnInit {
first()) first())
.subscribe((url) => { .subscribe((url) => {
const fileUrl = `${url}/${this.fileData.uuid}/content`; const fileUrl = `${url}/${this.fileData.uuid}/content`;
this.fileService.downloadFile(fileUrl); this.fileService.retrieveFileDownloadLink(fileUrl);
}); });
} }