101289: #1578 fixed redirection bug

This commit is contained in:
lotte
2023-04-26 10:54:36 +02:00
parent 7008afd05f
commit 222c220c56
3 changed files with 48 additions and 79 deletions

View File

@@ -388,20 +388,13 @@ describe('EditBitstreamPageComponent', () => {
expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled();
}); });
}); });
describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { describe('when navigateToItemEditBitstreams is called', () => {
it('should redirect to the item edit page on the bitstreams tab with the itemId from the component', () => { it('should redirect to the item edit page on the bitstreams tab with the itemId from the component', () => {
comp.itemId = 'some-uuid1'; comp.itemId = 'some-uuid1';
comp.navigateToItemEditBitstreams(); comp.navigateToItemEditBitstreams();
expect(router.navigate).toHaveBeenCalledWith([getEntityEditRoute(null, 'some-uuid1'), 'bitstreams']); expect(router.navigate).toHaveBeenCalledWith([getEntityEditRoute(null, 'some-uuid1'), 'bitstreams']);
}); });
}); });
describe('when navigateToItemEditBitstreams is called, and the component does not have an itemId', () => {
it('should redirect to the item edit page on the bitstreams tab with the itemId from the bundle links ', () => {
comp.itemId = undefined;
comp.navigateToItemEditBitstreams();
expect(router.navigate).toHaveBeenCalledWith([getEntityEditRoute(null, 'some-uuid'), 'bitstreams']);
});
});
}); });
describe('EditBitstreamPageComponent with IIIF fields', () => { describe('EditBitstreamPageComponent with IIIF fields', () => {

View File

@@ -1,58 +1,32 @@
import { import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
OnDestroy,
OnInit
} from '@angular/core';
import { Bitstream } from '../../core/shared/bitstream.model'; import { Bitstream } from '../../core/shared/bitstream.model';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { map, mergeMap, switchMap } from 'rxjs/operators'; import { map, switchMap, tap } from 'rxjs/operators';
import { import { combineLatest, combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
combineLatest, import { DynamicFormControlModel, DynamicFormGroupModel, DynamicFormLayout, DynamicFormService, DynamicInputModel, DynamicSelectModel } from '@ng-dynamic-forms/core';
combineLatest as observableCombineLatest,
Observable,
of as observableOf,
Subscription
} from 'rxjs';
import {
DynamicFormControlModel,
DynamicFormGroupModel,
DynamicFormLayout,
DynamicFormService,
DynamicInputModel,
DynamicSelectModel
} from '@ng-dynamic-forms/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model'; import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import { BitstreamDataService } from '../../core/data/bitstream-data.service'; import { BitstreamDataService } from '../../core/data/bitstream-data.service';
import { import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getRemoteDataPayload } from '../../core/shared/operators';
getAllSucceededRemoteDataPayload,
getFirstCompletedRemoteData,
getFirstSucceededRemoteData,
getFirstSucceededRemoteDataPayload,
getRemoteDataPayload
} from '../../core/shared/operators';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service'; import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service';
import { BitstreamFormat } from '../../core/shared/bitstream-format.model'; import { BitstreamFormat } from '../../core/shared/bitstream-format.model';
import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level'; import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level';
import { hasValue, isNotEmpty, isEmpty } from '../../shared/empty.util'; import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
import { Metadata } from '../../core/shared/metadata.utils'; import { Metadata } from '../../core/shared/metadata.utils';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { RemoteData } from '../../core/data/remote-data'; import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList } from '../../core/data/paginated-list.model'; import { PaginatedList } from '../../core/data/paginated-list.model';
import { getEntityEditRoute, getItemEditRoute } from '../../item-page/item-page-routing-paths'; import { getEntityEditRoute } from '../../item-page/item-page-routing-paths';
import { Bundle } from '../../core/shared/bundle.model'; import { Bundle } from '../../core/shared/bundle.model';
import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
import { Item } from '../../core/shared/item.model'; import { Item } from '../../core/shared/item.model';
import { import { DsDynamicInputModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
DsDynamicInputModel
} from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
import { DsDynamicTextAreaModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-textarea.model'; import { DsDynamicTextAreaModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-textarea.model';
import { BundleDataService } from '../../core/data/bundle-data.service'; import { BundleDataService } from '../../core/data/bundle-data.service';
import { Operation } from 'fast-json-patch';
@Component({ @Component({
selector: 'ds-edit-bitstream-page', selector: 'ds-edit-bitstream-page',
@@ -440,17 +414,24 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
getFirstSucceededRemoteDataPayload(), getFirstSucceededRemoteDataPayload(),
); );
const item$ = bundle$.pipe(
switchMap((bundle: Bundle) => bundle.item),
getFirstSucceededRemoteDataPayload()
);
this.subs.push( this.subs.push(
observableCombineLatest( observableCombineLatest(
bitstream$, bitstream$,
allFormats$, allFormats$,
bundle$ bundle$,
).subscribe(([bitstream, allFormats, bundle]) => { item$,
this.bitstream = bitstream as Bitstream; ).pipe()
this.formats = allFormats.page; .subscribe(([bitstream, allFormats, bundle, item]) => {
this.bundle = bundle; this.bitstream = bitstream as Bitstream;
this.setIiifStatus(this.bitstream); this.formats = allFormats.page;
}) this.bundle = bundle;
this.itemId = item.uuid;
this.setIiifStatus(this.bitstream);
})
); );
this.subs.push( this.subs.push(
@@ -582,7 +563,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
} }
} }
/** /**
* Check for changes against the bitstream and send update requests to the REST API * Check for changes against the bitstream and send update requests to the REST API
*/ */
@@ -598,23 +578,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
let bundle$: Observable<Bundle>; let bundle$: Observable<Bundle>;
if (wasPrimary !== isPrimary) { if (wasPrimary !== isPrimary) {
let patchOperation; const patchOperations: Operation[] = this.retrieveBundlePatch(wasPrimary);
// No longer primary bitstream: remove bundle$ = this.bundleService.patch(this.bundle, patchOperations).pipe(
if (wasPrimary) {
patchOperation = {
path: this.primaryBitstreamPath,
op: 'remove'
};
} else {
// Has become primary bitstream
// If it already had a value: replace, otherwise: add
patchOperation = {
path: this.primaryBitstreamPath,
op: hasValue(this.bundle.primaryBitstreamUUID) ? 'replace' : 'add',
value: this.bitstream.uuid
};
}
bundle$ = this.bundleService.patch(this.bundle, [patchOperation]).pipe(
getFirstCompletedRemoteData(), getFirstCompletedRemoteData(),
map((bundleResponse: RemoteData<Bundle>) => { map((bundleResponse: RemoteData<Bundle>) => {
if (hasValue(bundleResponse) && bundleResponse.hasFailed) { if (hasValue(bundleResponse) && bundleResponse.hasFailed) {
@@ -649,6 +614,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
} }
combineLatest([bundle$, bitstream$]).pipe( combineLatest([bundle$, bitstream$]).pipe(
tap(([bundle]) => this.bundle = bundle),
switchMap(() => { switchMap(() => {
return this.bitstreamService.update(updatedBitstream).pipe( return this.bitstreamService.update(updatedBitstream).pipe(
getFirstSucceededRemoteDataPayload() getFirstSucceededRemoteDataPayload()
@@ -664,6 +630,24 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
}); });
} }
private retrieveBundlePatch(wasPrimary: boolean): Operation[] {
// No longer primary bitstream: remove
if (wasPrimary) {
return [{
path: this.primaryBitstreamPath,
op: 'remove'
}];
} else {
// Has become primary bitstream
// If it already had a value: replace, otherwise: add
return [{
path: this.primaryBitstreamPath,
op: hasValue(this.bundle.primaryBitstreamUUID) ? 'replace' : 'add',
value: this.bitstream.uuid
}];
}
}
/** /**
* Parse form data to an updated bitstream object * Parse form data to an updated bitstream object
* @param rawForm Raw form data * @param rawForm Raw form data
@@ -671,8 +655,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
formToBitstream(rawForm): Bitstream { formToBitstream(rawForm): Bitstream {
const updatedBitstream = cloneDeep(this.bitstream); const updatedBitstream = cloneDeep(this.bitstream);
const newMetadata = updatedBitstream.metadata; const newMetadata = updatedBitstream.metadata;
// TODO: Set bitstream to primary when supported
const primary = rawForm.fileNamePrimaryContainer.primaryBitstream;
Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName); Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName);
if (isEmpty(rawForm.descriptionContainer.description)) { if (isEmpty(rawForm.descriptionContainer.description)) {
delete newMetadata['dc.description']; delete newMetadata['dc.description'];
@@ -724,15 +706,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
* otherwise retrieve the item ID based on the owning bundle's link * otherwise retrieve the item ID based on the owning bundle's link
*/ */
navigateToItemEditBitstreams() { navigateToItemEditBitstreams() {
if (hasValue(this.itemId)) { this.router.navigate([getEntityEditRoute(this.entityType, this.itemId), 'bitstreams']);
this.router.navigate([getEntityEditRoute(this.entityType, this.itemId), 'bitstreams']);
} else {
this.bitstream.bundle.pipe(getFirstSucceededRemoteDataPayload(),
mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload())))
.subscribe((item) => {
this.router.navigate(([getItemEditRoute(item), 'bitstreams']));
});
}
} }
/** /**

View File

@@ -705,6 +705,8 @@
"bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format",
"bitstream.edit.notifications.error.primaryBitstream.title": "An error occurred saving the primary bitstream",
"bitstream.edit.form.iiifLabel.label": "IIIF Label", "bitstream.edit.form.iiifLabel.label": "IIIF Label",
"bitstream.edit.form.iiifLabel.hint": "Canvas label for this image. If not provided default label will be used.", "bitstream.edit.form.iiifLabel.hint": "Canvas label for this image. If not provided default label will be used.",