83635: Update request a copy page and tests

This commit is contained in:
Yana De Pauw
2021-09-27 16:37:13 +02:00
committed by Art Lowel
parent 506883c960
commit 416aa7adaf
11 changed files with 119 additions and 54 deletions

View File

@@ -4,7 +4,7 @@ import { Collection } from './core/shared/collection.model';
import { Item } from './core/shared/item.model';
import { getCommunityPageRoute } from './community-page/community-page-routing-paths';
import { getCollectionPageRoute } from './collection-page/collection-page-routing-paths';
import { getItemPageRoute } from './item-page/item-page-routing-paths';
import { getItemModuleRoute, getItemPageRoute } from './item-page/item-page-routing-paths';
import { hasValue } from './shared/empty.util';
import { URLCombiner } from './core/url-combiner/url-combiner';
@@ -22,8 +22,9 @@ export function getBitstreamModuleRoute() {
export function getBitstreamDownloadRoute(bitstream): string {
return new URLCombiner(getBitstreamModuleRoute(), bitstream.uuid, 'download').toString();
}
export function getBitstreamRequestACopyRoute(bitstream): string {
return new URLCombiner(getBitstreamModuleRoute(), bitstream.uuid, 'request-a-copy').toString();
export function getBitstreamRequestACopyRoute(item, bitstream): string {
const url = new URLCombiner(getItemModuleRoute(), item.uuid, 'request-a-copy').toString();
return `${url}?bitstream=${bitstream.uuid}`;
}
export const ADMIN_MODULE_PATH = 'admin';

View File

@@ -45,14 +45,6 @@ const EDIT_BITSTREAM_AUTHORIZATIONS_PATH = ':id/authorizations';
bitstream: BitstreamPageResolver
},
},
{
// Resolve angular bitstream download URLs
path: ':id/request-a-copy',
component: BitstreamRequestACopyPageComponent,
resolve: {
bitstream: BitstreamPageResolver
},
},
{
path: EDIT_BITSTREAM_PATH,
component: EditBitstreamPageComponent,

View File

@@ -33,7 +33,7 @@
</dl>
</div>
<div class="col-2">
<ds-file-download-link [bitstream]="file">
<ds-file-download-link [bitstream]="file" [item]="item">
{{"item.page.filesection.download" | translate}}
</ds-file-download-link>
</div>
@@ -74,7 +74,7 @@
</dl>
</div>
<div class="col-2">
<ds-file-download-link [bitstream]="file">
<ds-file-download-link [bitstream]="file" [item]="item">
{{"item.page.filesection.download" | translate}}
</ds-file-download-link>
</div>

View File

@@ -12,6 +12,8 @@ import { MenuItemType } from '../shared/menu/initial-menus-state';
import { LinkMenuItemModel } from '../shared/menu/menu-item/models/link.model';
import { ThemedItemPageComponent } from './simple/themed-item-page.component';
import { ThemedFullItemPageComponent } from './full/themed-full-item-page.component';
import { BitstreamRequestACopyPageComponent } from '../shared/bitstream-request-a-copy-page/bitstream-request-a-copy-page.component';
import { BitstreamPageResolver } from '../bitstream-page/bitstream-page.resolver';
@NgModule({
imports: [
@@ -42,6 +44,10 @@ import { ThemedFullItemPageComponent } from './full/themed-full-item-page.compon
path: UPLOAD_BITSTREAM_PATH,
component: UploadBitstreamComponent,
canActivate: [AuthenticatedGuard]
},
{
path: ':request-a-copy',
component: BitstreamRequestACopyPageComponent,
}
],
data: {

View File

@@ -1,7 +1,7 @@
<ng-container *ngVar="(bitstreams$ | async) as bitstreams">
<ds-metadata-field-wrapper *ngIf="bitstreams?.length > 0" [label]="label | translate">
<div class="file-section">
<ds-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file">
<ds-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file" [item]="item">
<span>{{file?.name}}</span>
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
<span *ngIf="!last" innerHTML="{{separator}}"></span>

View File

@@ -5,8 +5,9 @@
<a [routerLink]="getBitstreamLink()">{{'bitstream-request-a-copy.alert.canDownload2'| translate}}</a>
</div>
<div>
<p>{{'bitstream-request-a-copy.intro' | translate}}</p>
<p>{{itemName}}</p>
<p>{{'bitstream-request-a-copy.intro' | translate}} <a [routerLink]="getItemPath()">{{itemName}}</a></p>
<p *ngIf="bitstream != undefined && allfiles.value === 'false'">{{'bitstream-request-a-copy.intro.bitstream.one' | translate}} {{bitstreamName}}</p>
<p *ngIf="allfiles.value === 'true'">{{'bitstream-request-a-copy.intro.bitstream.all' | translate}}</p>
</div>
<form [class]="'ng-invalid'" [formGroup]="requestCopyForm" (ngSubmit)="onSubmit()">
@@ -45,13 +46,13 @@
<div>{{'bitstream-request-a-copy.allfiles.label' |translate}}</div>
<div class="ml-4">
<input [className]="'form-check-input'" type="radio"
id="allfiles-true" formControlName="allfiles" value="true" [checked]="true">
id="allfiles-true" formControlName="allfiles" value="true">
<label class="form-check-label"
for="allfiles-true">{{'bitstream-request-a-copy.files-all-true.label' | translate}}</label>
</div>
<div class="ml-4">
<input [className]="'form-check-input'" type="radio"
id="allfiles-false" formControlName="allfiles" value="false">
id="allfiles-false" formControlName="allfiles" value="false" [attr.disabled]="bitstream === undefined ? true : null ">
<label class="form-check-label"
for="allfiles-false">{{'bitstream-request-a-copy.files-all-false.label' | translate}}</label>
</div>

View File

@@ -21,10 +21,10 @@ import { NotificationsService } from '../notifications/notifications.service';
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
import { DSONameServiceMock } from '../mocks/dso-name.service.mock';
import { Item } from '../../core/shared/item.model';
import { Bundle } from '../../core/shared/bundle.model';
import { EPerson } from '../../core/eperson/models/eperson.model';
import { ItemRequest } from '../../core/shared/item-request.model';
import { Location } from '@angular/common';
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
describe('BitstreamRequestACopyPageComponent', () => {
@@ -38,6 +38,7 @@ describe('BitstreamRequestACopyPageComponent', () => {
let itemRequestDataService;
let notificationsService;
let location;
let bitstreamDataService;
let item: Item;
let bitstream: Bitstream;
@@ -71,14 +72,8 @@ describe('BitstreamRequestACopyPageComponent', () => {
item = Object.assign(new Item(), {uuid: 'item-uuid'});
const bundle = Object.assign(new Bundle(), {
uuid: 'bundle-uuid',
item: createSuccessfulRemoteDataObject$(item)
});
bitstream = Object.assign(new Bitstream(), {
uuid: 'bitstreamUuid',
bundle: createSuccessfulRemoteDataObject$(bundle),
_links: {
content: {href: 'bitstream-content-link'},
self: {href: 'bitstream-self-link'},
@@ -87,12 +82,19 @@ describe('BitstreamRequestACopyPageComponent', () => {
activatedRoute = {
data: observableOf({
bitstream: createSuccessfulRemoteDataObject(
bitstream
dso: createSuccessfulRemoteDataObject(
item
)
}),
queryParams: observableOf({
bitstream : bitstream.uuid
})
};
bitstreamDataService = jasmine.createSpyObj('bitstreamDataService', {
findById: createSuccessfulRemoteDataObject$(bitstream)
});
router = new RouterStub();
}
@@ -109,6 +111,7 @@ describe('BitstreamRequestACopyPageComponent', () => {
{provide: ItemRequestDataService, useValue: itemRequestDataService},
{provide: NotificationsService, useValue: notificationsService},
{provide: DSONameService, useValue: new DSONameServiceMock()},
{provide: BitstreamDataService, useValue: bitstreamDataService},
]
})
.compileComponents();
@@ -143,7 +146,7 @@ describe('BitstreamRequestACopyPageComponent', () => {
it('show the form with no values filled in based on the user', () => {
expect(component.name.value).toEqual('');
expect(component.email.value).toEqual('');
expect(component.allfiles.value).toEqual('true');
expect(component.allfiles.value).toEqual('false');
expect(component.message.value).toEqual('');
});
});
@@ -163,8 +166,38 @@ describe('BitstreamRequestACopyPageComponent', () => {
fixture.detectChanges();
expect(component.name.value).toEqual(eperson.name);
expect(component.email.value).toEqual(eperson.email);
expect(component.allfiles.value).toEqual('false');
expect(component.message.value).toEqual('');
});
});
describe('when no bitstream was provided', () => {
beforeEach(waitForAsync(() => {
init();
activatedRoute = {
data: observableOf({
dso: createSuccessfulRemoteDataObject(
item
)
}),
queryParams: observableOf({
})
};
initTestbed();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BitstreamRequestACopyPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should set the all files value to true and disable the false value', () => {
expect(component.name.value).toEqual('');
expect(component.email.value).toEqual('');
expect(component.allfiles.value).toEqual('true');
expect(component.message.value).toEqual('');
const allFilesFalse = fixture.debugElement.query(By.css('#allfiles-false')).nativeElement;
expect(allFilesFalse.getAttribute('disabled')).toBeTruthy();
});
});
describe('when the user has authorization to download the file', () => {

View File

@@ -1,5 +1,5 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { map, switchMap, take } from 'rxjs/operators';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { hasValue, isNotEmpty } from '../empty.util';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
@@ -17,9 +17,10 @@ import { ItemRequestDataService } from '../../core/data/item-request-data.servic
import { ItemRequest } from '../../core/shared/item-request.model';
import { Item } from '../../core/shared/item.model';
import { NotificationsService } from '../notifications/notifications.service';
import { getItemPageRoute } from '../../item-page/item-page-routing-paths';
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
import { Location } from '@angular/common';
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
import { getItemPageRoute } from '../../item-page/item-page-routing-paths';
@Component({
selector: 'ds-bitstream-request-a-copy-page',
@@ -30,15 +31,19 @@ import { Location } from '@angular/common';
*/
export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
bitstream$: Observable<Bitstream>;
item$: Observable<Item>;
canDownload$: Observable<boolean>;
private subs: Subscription[] = [];
requestCopyForm: FormGroup;
bitstream: Bitstream;
item: Item;
itemName: string;
bitstream$: Observable<Bitstream>;
bitstream: Bitstream;
bitstreamName: string;
constructor(private location: Location,
private translateService: TranslateService,
private route: ActivatedRoute,
@@ -49,6 +54,7 @@ export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
private itemRequestDataService: ItemRequestDataService,
private notificationsService: NotificationsService,
private dsoNameService: DSONameService,
private bitstreamService: BitstreamDataService,
) {
}
@@ -66,23 +72,25 @@ export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
});
this.bitstream$ = this.route.data.pipe(
map((data) => data.bitstream),
this.item$ = this.route.data.pipe(
map((data) => data.dso),
getFirstSucceededRemoteDataPayload()
);
this.subs.push(this.item$.subscribe((item) => {
this.item = item;
this.itemName = this.dsoNameService.getName(item);
}));
this.bitstream$ = this.route.queryParams.pipe(
filter((params) => hasValue(params) && hasValue(params.bitstream)),
switchMap((params) => this.bitstreamService.findById(params.bitstream)),
getFirstSucceededRemoteDataPayload()
);
this.subs.push(this.bitstream$.subscribe((bitstream) => {
this.bitstream = bitstream;
}));
this.subs.push(this.bitstream$.pipe(
switchMap((bitstream) => bitstream.bundle),
getFirstSucceededRemoteDataPayload(),
switchMap((bundle) => bundle.item),
getFirstSucceededRemoteDataPayload(),
).subscribe((item) => {
this.item = item;
this.itemName = this.dsoNameService.getName(item);
this.bitstreamName = this.dsoNameService.getName(bitstream);
}));
this.canDownload$ = this.bitstream$.pipe(
@@ -124,9 +132,11 @@ export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
this.requestCopyForm.patchValue({allfiles: 'true'});
if (hasValue(user)) {
this.requestCopyForm.patchValue({name: user.name, email: user.email});
console.log('ping');
}
});
this.bitstream$.pipe(take(1)).subscribe((bitstream) => {
this.requestCopyForm.patchValue({allfiles: 'false'});
});
}
/**
@@ -152,10 +162,10 @@ export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
*/
onSubmit() {
const itemRequest = new ItemRequest();
if (hasValue(this.item)) {
itemRequest.itemId = this.item.uuid;
if (hasValue(this.bitstream)) {
itemRequest.bitstreamId = this.bitstream.uuid;
}
itemRequest.bitstreamId = this.bitstream.uuid;
itemRequest.itemId = this.item.uuid;
itemRequest.allfiles = this.allfiles.value;
itemRequest.requestEmail = this.email.value;
itemRequest.requestName = this.name.value;
@@ -190,6 +200,10 @@ export class BitstreamRequestACopyPageComponent implements OnInit, OnDestroy {
this.location.back();
}
getItemPath() {
return [getItemPageRoute(this.item)];
}
/**
* Retrieves the link to the bistream download page
*/

View File

@@ -7,6 +7,8 @@ import { getBitstreamModuleRoute } from '../../app-routing-paths';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { cold, getTestScheduler } from 'jasmine-marbles';
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { Item } from '../../core/shared/item.model';
import { getItemModuleRoute } from '../../item-page/item-page-routing-paths';
describe('FileDownloadLinkComponent', () => {
let component: FileDownloadLinkComponent;
@@ -16,6 +18,7 @@ describe('FileDownloadLinkComponent', () => {
let authorizationService: AuthorizationDataService;
let bitstream: Bitstream;
let item: Item;
function init() {
authorizationService = jasmine.createSpyObj('authorizationService', {
@@ -27,6 +30,12 @@ describe('FileDownloadLinkComponent', () => {
self: {href: 'obj-selflink'}
}
});
item = Object.assign(new Item(), {
uuid: 'itemUuid',
_links: {
self: {href: 'obj-selflink'}
}
});
}
function initTestbed() {
@@ -52,6 +61,7 @@ describe('FileDownloadLinkComponent', () => {
fixture = TestBed.createComponent(FileDownloadLinkComponent);
component = fixture.componentInstance;
component.bitstream = bitstream;
component.item = item;
fixture.detectChanges();
});
it('should return the bitstreamPath based on the input bitstream', () => {
@@ -83,11 +93,12 @@ describe('FileDownloadLinkComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(FileDownloadLinkComponent);
component = fixture.componentInstance;
component.item = item;
component.bitstream = bitstream;
fixture.detectChanges();
});
it('should return the bitstreamPath based on the input bitstream', () => {
expect(component.bitstreamPath$).toBeObservable(cold('-a', {a: new URLCombiner(getBitstreamModuleRoute(), bitstream.uuid, 'request-a-copy').toString()}));
expect(component.bitstreamPath$).toBeObservable(cold('-a', {a: `${new URLCombiner(getItemModuleRoute(), item.uuid, 'request-a-copy').toString()}?bitstream=${bitstream.uuid}`}));
expect(component.canDownload$).toBeObservable(cold('--a', {a: false}));
});
@@ -95,7 +106,7 @@ describe('FileDownloadLinkComponent', () => {
scheduler.flush();
fixture.detectChanges();
const link = fixture.debugElement.query(By.css('a')).nativeElement;
expect(link.href).toContain(new URLCombiner(getBitstreamModuleRoute(), bitstream.uuid, 'request-a-copy').toString());
expect(link.href).toContain(`${new URLCombiner(getItemModuleRoute(), item.uuid, 'request-a-copy').toString()}?bitstream=${bitstream.uuid}`);
const lock = fixture.debugElement.query(By.css('.fa-lock')).nativeElement;
expect(lock).toBeTruthy();
});
@@ -111,6 +122,7 @@ describe('FileDownloadLinkComponent', () => {
fixture = TestBed.createComponent(FileDownloadLinkComponent);
component = fixture.componentInstance;
component.bitstream = bitstream;
component.item = item;
fixture.detectChanges();
});
it('should return the bitstreamPath based on the input bitstream', () => {

View File

@@ -3,9 +3,10 @@ import { Bitstream } from '../../core/shared/bitstream.model';
import { getBitstreamDownloadRoute, getBitstreamRequestACopyRoute } from '../../app-routing-paths';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { isNotEmpty } from '../empty.util';
import { hasValue, isNotEmpty } from '../empty.util';
import { map } from 'rxjs/operators';
import { of as observableOf, combineLatest as observableCombineLatest, Observable } from 'rxjs';
import { Item } from '../../core/shared/item.model';
@Component({
selector: 'ds-file-download-link',
@@ -24,6 +25,8 @@ export class FileDownloadLinkComponent implements OnInit {
*/
@Input() bitstream: Bitstream;
@Input() item: Item;
/**
* Additional css classes to apply to link
*/
@@ -59,8 +62,8 @@ export class FileDownloadLinkComponent implements OnInit {
}
getBitstreamPath(canDownload: boolean, canRequestACopy: boolean) {
if (!canDownload && canRequestACopy) {
return getBitstreamRequestACopyRoute(this.bitstream);
if (!canDownload && canRequestACopy && hasValue(this.item)) {
return getBitstreamRequestACopyRoute(this.item, this.bitstream);
}
return getBitstreamDownloadRoute(this.bitstream);
}

View File

@@ -594,7 +594,10 @@
"bitstream-request-a-copy.header": "Request a copy of the file",
"bitstream-request-a-copy.intro": "Enter the following information to request a copy",
"bitstream-request-a-copy.intro": "Enter the following information to request a copy for the following item: ",
"bitstream-request-a-copy.intro.bitstream.one": "Requesting the following file: ",
"bitstream-request-a-copy.intro.bitstream.all": "Requesting all files. ",
"bitstream-request-a-copy.name.label": "Name *",