mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge pull request #2213 from atmire/w2p-101289_1578_primaryBitstream-edit-implementation
Primary bitstream toggle implementation
This commit is contained in:
@@ -12,7 +12,7 @@ import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
||||
* Requesting them as embeds will limit the number of requests
|
||||
*/
|
||||
export const BITSTREAM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Bitstream>[] = [
|
||||
followLink('bundle', {}, followLink('item')),
|
||||
followLink('bundle', {}, followLink('primaryBitstream'), followLink('item')),
|
||||
followLink('format')
|
||||
];
|
||||
|
||||
|
@@ -24,6 +24,7 @@ import { createPaginatedList } from '../../shared/testing/utils.test';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
import { MetadataValueFilter } from '../../core/shared/metadata.models';
|
||||
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
|
||||
import { PrimaryBitstreamService } from '../../core/data/primary-bitstream.service';
|
||||
|
||||
const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info');
|
||||
const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning');
|
||||
@@ -32,19 +33,27 @@ const successNotification: INotification = new Notification('id', NotificationTy
|
||||
let notificationsService: NotificationsService;
|
||||
let formService: DynamicFormService;
|
||||
let bitstreamService: BitstreamDataService;
|
||||
let primaryBitstreamService: PrimaryBitstreamService;
|
||||
let bitstreamFormatService: BitstreamFormatDataService;
|
||||
let dsoNameService: DSONameService;
|
||||
let bitstream: Bitstream;
|
||||
let bitstreamID: string;
|
||||
let selectedFormat: BitstreamFormat;
|
||||
let allFormats: BitstreamFormat[];
|
||||
let router: Router;
|
||||
|
||||
let currentPrimary: string;
|
||||
let differentPrimary: string;
|
||||
let bundle;
|
||||
let comp: EditBitstreamPageComponent;
|
||||
let fixture: ComponentFixture<EditBitstreamPageComponent>;
|
||||
|
||||
describe('EditBitstreamPageComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
bitstreamID = 'current-bitstream-id';
|
||||
currentPrimary = bitstreamID;
|
||||
differentPrimary = '12345-abcde-54321-edcba';
|
||||
|
||||
allFormats = [
|
||||
Object.assign({
|
||||
id: '1',
|
||||
@@ -53,7 +62,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
mimetype: 'application/octet-stream',
|
||||
_links: {
|
||||
self: {href: 'format-selflink-1'}
|
||||
self: { href: 'format-selflink-1' }
|
||||
}
|
||||
}),
|
||||
Object.assign({
|
||||
@@ -63,7 +72,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
supportLevel: BitstreamFormatSupportLevel.Known,
|
||||
mimetype: 'image/png',
|
||||
_links: {
|
||||
self: {href: 'format-selflink-2'}
|
||||
self: { href: 'format-selflink-2' }
|
||||
}
|
||||
}),
|
||||
Object.assign({
|
||||
@@ -73,7 +82,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
supportLevel: BitstreamFormatSupportLevel.Known,
|
||||
mimetype: 'image/gif',
|
||||
_links: {
|
||||
self: {href: 'format-selflink-3'}
|
||||
self: { href: 'format-selflink-3' }
|
||||
}
|
||||
})
|
||||
] as BitstreamFormat[];
|
||||
@@ -103,15 +112,52 @@ describe('EditBitstreamPageComponent', () => {
|
||||
success: successNotification
|
||||
}
|
||||
);
|
||||
|
||||
bundle = {
|
||||
_links: {
|
||||
primaryBitstream: {
|
||||
href: 'bundle-selflink'
|
||||
}
|
||||
},
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid',
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return undefined;
|
||||
},
|
||||
}))
|
||||
};
|
||||
|
||||
const result = createSuccessfulRemoteDataObject$(bundle);
|
||||
primaryBitstreamService = jasmine.createSpyObj('PrimaryBitstreamService',
|
||||
{
|
||||
put: result,
|
||||
create: result,
|
||||
delete: result,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('EditBitstreamPageComponent no IIIF fields', () => {
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
|
||||
bundle = {
|
||||
_links: {
|
||||
primaryBitstream: {
|
||||
href: 'bundle-selflink'
|
||||
}
|
||||
},
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid',
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return undefined;
|
||||
},
|
||||
}))
|
||||
};
|
||||
const bundleName = 'ORIGINAL';
|
||||
|
||||
bitstream = Object.assign(new Bitstream(), {
|
||||
uuid: bitstreamID,
|
||||
id: bitstreamID,
|
||||
metadata: {
|
||||
'dc.description': [
|
||||
{
|
||||
@@ -128,17 +174,11 @@ describe('EditBitstreamPageComponent', () => {
|
||||
_links: {
|
||||
self: 'bitstream-selflink'
|
||||
},
|
||||
bundle: createSuccessfulRemoteDataObject$({
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid',
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return undefined;
|
||||
},
|
||||
}))
|
||||
})
|
||||
bundle: createSuccessfulRemoteDataObject$(bundle)
|
||||
});
|
||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||
commitUpdates: {},
|
||||
@@ -155,17 +195,19 @@ describe('EditBitstreamPageComponent', () => {
|
||||
imports: [TranslateModule.forRoot(), RouterTestingModule],
|
||||
declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective],
|
||||
providers: [
|
||||
{provide: NotificationsService, useValue: notificationsService},
|
||||
{provide: DynamicFormService, useValue: formService},
|
||||
{provide: ActivatedRoute,
|
||||
{ provide: NotificationsService, useValue: notificationsService },
|
||||
{ provide: DynamicFormService, useValue: formService },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}),
|
||||
snapshot: {queryParams: {}}
|
||||
data: observableOf({ bitstream: createSuccessfulRemoteDataObject(bitstream) }),
|
||||
snapshot: { queryParams: {} }
|
||||
}
|
||||
},
|
||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
||||
{provide: DSONameService, useValue: dsoNameService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{ provide: BitstreamDataService, useValue: bitstreamService },
|
||||
{ provide: DSONameService, useValue: dsoNameService },
|
||||
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
||||
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||
ChangeDetectorRef
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
@@ -203,6 +245,27 @@ describe('EditBitstreamPageComponent', () => {
|
||||
it('should put the \"New Format\" input on invisible', () => {
|
||||
expect(comp.formLayout.newFormat.grid.host).toContain('invisible');
|
||||
});
|
||||
describe('when the bitstream is the primary bitstream on the bundle', () => {
|
||||
beforeEach(() => {
|
||||
(comp as any).primaryBitstreamUUID = currentPrimary;
|
||||
comp.setForm();
|
||||
rawForm = comp.formGroup.getRawValue();
|
||||
|
||||
});
|
||||
it('should enable the primary bitstream toggle', () => {
|
||||
expect(rawForm.fileNamePrimaryContainer.primaryBitstream).toEqual(true);
|
||||
});
|
||||
});
|
||||
describe('when the bitstream is not the primary bitstream on the bundle', () => {
|
||||
beforeEach(() => {
|
||||
(comp as any).primaryBitstreamUUID = differentPrimary;
|
||||
comp.setForm();
|
||||
rawForm = comp.formGroup.getRawValue();
|
||||
});
|
||||
it('should disable the primary bitstream toggle', () => {
|
||||
expect(rawForm.fileNamePrimaryContainer.primaryBitstream).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when an unknown format is selected', () => {
|
||||
@@ -216,6 +279,83 @@ describe('EditBitstreamPageComponent', () => {
|
||||
});
|
||||
|
||||
describe('onSubmit', () => {
|
||||
describe('when the primaryBitstream changed', () => {
|
||||
describe('to the current bitstream', () => {
|
||||
beforeEach(() => {
|
||||
const rawValue = Object.assign(comp.formGroup.getRawValue(), { fileNamePrimaryContainer: { primaryBitstream: true } });
|
||||
spyOn(comp.formGroup, 'getRawValue').and.returnValue(rawValue);
|
||||
});
|
||||
|
||||
describe('from a different primary bitstream', () => {
|
||||
beforeEach(() => {
|
||||
(comp as any).primaryBitstreamUUID = differentPrimary;
|
||||
comp.onSubmit();
|
||||
});
|
||||
|
||||
it('should call put with the correct bitstream on the PrimaryBitstreamService', () => {
|
||||
expect(primaryBitstreamService.put).toHaveBeenCalledWith(jasmine.objectContaining({uuid: currentPrimary}), bundle);
|
||||
});
|
||||
});
|
||||
|
||||
describe('from no primary bitstream', () => {
|
||||
beforeEach(() => {
|
||||
(comp as any).primaryBitstreamUUID = null;
|
||||
comp.onSubmit();
|
||||
});
|
||||
|
||||
it('should call create with the correct bitstream on the PrimaryBitstreamService', () => {
|
||||
expect(primaryBitstreamService.create).toHaveBeenCalledWith(jasmine.objectContaining({uuid: currentPrimary}), bundle);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('to no primary bitstream', () => {
|
||||
beforeEach(() => {
|
||||
const rawValue = Object.assign(comp.formGroup.getRawValue(), { fileNamePrimaryContainer: { primaryBitstream: false } });
|
||||
spyOn(comp.formGroup, 'getRawValue').and.returnValue(rawValue);
|
||||
});
|
||||
|
||||
describe('from the current bitstream', () => {
|
||||
beforeEach(() => {
|
||||
(comp as any).primaryBitstreamUUID = currentPrimary;
|
||||
comp.onSubmit();
|
||||
});
|
||||
|
||||
it('should call delete on the PrimaryBitstreamService', () => {
|
||||
expect(primaryBitstreamService.delete).toHaveBeenCalledWith(jasmine.objectContaining(bundle));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('when the primaryBitstream did not change', () => {
|
||||
describe('the current bitstream stayed the primary bitstream', () => {
|
||||
beforeEach(() => {
|
||||
const rawValue = Object.assign(comp.formGroup.getRawValue(), { fileNamePrimaryContainer: { primaryBitstream: true } });
|
||||
spyOn(comp.formGroup, 'getRawValue').and.returnValue(rawValue);
|
||||
(comp as any).primaryBitstreamUUID = currentPrimary;
|
||||
comp.onSubmit();
|
||||
});
|
||||
it('should not call anything on the PrimaryBitstreamService', () => {
|
||||
expect(primaryBitstreamService.put).not.toHaveBeenCalled();
|
||||
expect(primaryBitstreamService.delete).not.toHaveBeenCalled();
|
||||
expect(primaryBitstreamService.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('the bitstream was not and did not become the primary bitstream', () => {
|
||||
beforeEach(() => {
|
||||
const rawValue = Object.assign(comp.formGroup.getRawValue(), { fileNamePrimaryContainer: { primaryBitstream: false } });
|
||||
spyOn(comp.formGroup, 'getRawValue').and.returnValue(rawValue);
|
||||
(comp as any).primaryBitstreamUUID = differentPrimary;
|
||||
comp.onSubmit();
|
||||
});
|
||||
it('should not call anything on the PrimaryBitstreamService', () => {
|
||||
expect(primaryBitstreamService.put).not.toHaveBeenCalled();
|
||||
expect(primaryBitstreamService.delete).not.toHaveBeenCalled();
|
||||
expect(primaryBitstreamService.create).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when selected format hasn\'t changed', () => {
|
||||
beforeEach(() => {
|
||||
comp.onSubmit();
|
||||
@@ -261,20 +401,13 @@ describe('EditBitstreamPageComponent', () => {
|
||||
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', () => {
|
||||
comp.itemId = 'some-uuid1';
|
||||
comp.navigateToItemEditBitstreams();
|
||||
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', () => {
|
||||
@@ -321,16 +454,22 @@ describe('EditBitstreamPageComponent', () => {
|
||||
self: 'bitstream-selflink'
|
||||
},
|
||||
bundle: createSuccessfulRemoteDataObject$({
|
||||
_links: {
|
||||
primaryBitstream: {
|
||||
href: 'bundle-selflink'
|
||||
}
|
||||
},
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid',
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return 'True';
|
||||
}
|
||||
}))
|
||||
})
|
||||
}),
|
||||
});
|
||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||
commitUpdates: {},
|
||||
@@ -357,6 +496,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
||||
{provide: DSONameService, useValue: dsoNameService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||
ChangeDetectorRef
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
@@ -371,7 +511,6 @@ describe('EditBitstreamPageComponent', () => {
|
||||
spyOn(router, 'navigate');
|
||||
});
|
||||
|
||||
|
||||
describe('on startup', () => {
|
||||
let rawForm;
|
||||
|
||||
@@ -440,16 +579,22 @@ describe('EditBitstreamPageComponent', () => {
|
||||
self: 'bitstream-selflink'
|
||||
},
|
||||
bundle: createSuccessfulRemoteDataObject$({
|
||||
_links: {
|
||||
primaryBitstream: {
|
||||
href: 'bundle-selflink'
|
||||
}
|
||||
},
|
||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||
uuid: 'some-uuid',
|
||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||
return 'True';
|
||||
}
|
||||
}))
|
||||
})
|
||||
}),
|
||||
});
|
||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||
commitUpdates: {},
|
||||
@@ -475,6 +620,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
||||
{provide: DSONameService, useValue: dsoNameService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||
ChangeDetectorRef
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
@@ -496,7 +642,7 @@ describe('EditBitstreamPageComponent', () => {
|
||||
rawForm = comp.formGroup.getRawValue();
|
||||
});
|
||||
|
||||
it('should NOT set isIIIF to true', () => {
|
||||
it('should NOT set is IIIF to true', () => {
|
||||
expect(comp.isIIIF).toBeFalse();
|
||||
});
|
||||
it('should put the \"IIIF Label\" input not to be shown', () => {
|
||||
|
@@ -1,57 +1,31 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
OnDestroy,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Bitstream } from '../../core/shared/bitstream.model';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { map, mergeMap, switchMap } from 'rxjs/operators';
|
||||
import {
|
||||
combineLatest,
|
||||
combineLatest as observableCombineLatest,
|
||||
Observable,
|
||||
of as observableOf,
|
||||
Subscription
|
||||
} from 'rxjs';
|
||||
import {
|
||||
DynamicFormControlModel,
|
||||
DynamicFormGroupModel,
|
||||
DynamicFormLayout,
|
||||
DynamicFormService,
|
||||
DynamicInputModel,
|
||||
DynamicSelectModel
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { filter, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { combineLatest, combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
|
||||
import { DynamicFormControlModel, DynamicFormGroupModel, DynamicFormLayout, DynamicFormService, DynamicInputModel, DynamicSelectModel } from '@ng-dynamic-forms/core';
|
||||
import { UntypedFormGroup } from '@angular/forms';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DynamicCustomSwitchModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/custom-switch/custom-switch.model';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import { BitstreamDataService } from '../../core/data/bitstream-data.service';
|
||||
import {
|
||||
getAllSucceededRemoteDataPayload,
|
||||
getFirstCompletedRemoteData,
|
||||
getFirstSucceededRemoteData,
|
||||
getFirstSucceededRemoteDataPayload,
|
||||
getRemoteDataPayload
|
||||
} from '../../core/shared/operators';
|
||||
import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, getFirstSucceededRemoteData, getFirstSucceededRemoteDataPayload, getRemoteDataPayload } from '../../core/shared/operators';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { BitstreamFormatDataService } from '../../core/data/bitstream-format-data.service';
|
||||
import { BitstreamFormat } from '../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../core/shared/bitstream-format-support-level';
|
||||
import { hasValue, isNotEmpty, isEmpty } from '../../shared/empty.util';
|
||||
import { hasValue, hasValueOperator, isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||
import { Metadata } from '../../core/shared/metadata.utils';
|
||||
import { Location } from '@angular/common';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
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 { DSONameService } from '../../core/breadcrumbs/dso-name.service';
|
||||
import { Item } from '../../core/shared/item.model';
|
||||
import {
|
||||
DsDynamicInputModel
|
||||
} from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model';
|
||||
import { 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 { PrimaryBitstreamService } from '../../core/data/primary-bitstream.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-edit-bitstream-page',
|
||||
@@ -76,6 +50,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
bitstreamFormatsRD$: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
||||
|
||||
/**
|
||||
* The UUID of the primary bitstream for this bundle
|
||||
*/
|
||||
primaryBitstreamUUID: string;
|
||||
|
||||
/**
|
||||
* The bitstream to edit
|
||||
*/
|
||||
@@ -203,7 +182,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
iiifLabelContainer = new DynamicFormGroupModel({
|
||||
id: 'iiifLabelContainer',
|
||||
group: [this.iiifLabelModel]
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'form-row'
|
||||
}
|
||||
@@ -213,7 +192,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||
id: 'iiifToc',
|
||||
name: 'iiifToc',
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'col col-lg-6 d-inline-block'
|
||||
}
|
||||
@@ -221,7 +200,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
iiifTocContainer = new DynamicFormGroupModel({
|
||||
id: 'iiifTocContainer',
|
||||
group: [this.iiifTocModel]
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'form-row'
|
||||
}
|
||||
@@ -231,7 +210,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||
id: 'iiifWidth',
|
||||
name: 'iiifWidth',
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'col col-lg-6 d-inline-block'
|
||||
}
|
||||
@@ -239,7 +218,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
iiifWidthContainer = new DynamicFormGroupModel({
|
||||
id: 'iiifWidthContainer',
|
||||
group: [this.iiifWidthModel]
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'form-row'
|
||||
}
|
||||
@@ -249,7 +228,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||
id: 'iiifHeight',
|
||||
name: 'iiifHeight'
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'col col-lg-6 d-inline-block'
|
||||
}
|
||||
@@ -257,7 +236,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
iiifHeightContainer = new DynamicFormGroupModel({
|
||||
id: 'iiifHeightContainer',
|
||||
group: [this.iiifHeightModel]
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'form-row'
|
||||
}
|
||||
@@ -280,7 +259,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
this.fileNameModel,
|
||||
this.primaryBitstreamModel
|
||||
]
|
||||
},{
|
||||
}, {
|
||||
grid: {
|
||||
host: 'form-row'
|
||||
}
|
||||
@@ -316,7 +295,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
},
|
||||
primaryBitstream: {
|
||||
grid: {
|
||||
host: 'col col-sm-4 d-inline-block switch'
|
||||
host: 'col col-sm-4 d-inline-block switch border-0'
|
||||
}
|
||||
},
|
||||
description: {
|
||||
@@ -380,13 +359,17 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
isIIIF = false;
|
||||
|
||||
|
||||
/**
|
||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||
* @type {Array}
|
||||
*/
|
||||
protected subs: Subscription[] = [];
|
||||
|
||||
/**
|
||||
* The parent bundle containing the Bitstream
|
||||
* @private
|
||||
*/
|
||||
private bundle: Bundle;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
@@ -397,7 +380,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
private bitstreamService: BitstreamDataService,
|
||||
public dsoNameService: DSONameService,
|
||||
private notificationsService: NotificationsService,
|
||||
private bitstreamFormatService: BitstreamFormatDataService) {
|
||||
private bitstreamFormatService: BitstreamFormatDataService,
|
||||
private primaryBitstreamService: PrimaryBitstreamService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -410,26 +395,50 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.itemId = this.route.snapshot.queryParams.itemId;
|
||||
this.entityType = this.route.snapshot.queryParams.entityType;
|
||||
this.bitstreamRD$ = this.route.data.pipe(map((data) => data.bitstream));
|
||||
this.bitstreamRD$ = this.route.data.pipe(map((data: any) => data.bitstream));
|
||||
this.bitstreamFormatsRD$ = this.bitstreamFormatService.findAll(this.findAllOptions);
|
||||
|
||||
const bitstream$ = this.bitstreamRD$.pipe(
|
||||
getFirstSucceededRemoteData(),
|
||||
getRemoteDataPayload()
|
||||
getRemoteDataPayload(),
|
||||
);
|
||||
|
||||
const allFormats$ = this.bitstreamFormatsRD$.pipe(
|
||||
getFirstSucceededRemoteData(),
|
||||
getRemoteDataPayload()
|
||||
getRemoteDataPayload(),
|
||||
);
|
||||
|
||||
const bundle$ = bitstream$.pipe(
|
||||
switchMap((bitstream: Bitstream) => bitstream.bundle),
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
);
|
||||
|
||||
const primaryBitstream$ = bundle$.pipe(
|
||||
hasValueOperator(),
|
||||
switchMap((bundle: Bundle) => this.bitstreamService.findByHref(bundle._links.primaryBitstream.href)),
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
);
|
||||
|
||||
const item$ = bundle$.pipe(
|
||||
switchMap((bundle: Bundle) => bundle.item),
|
||||
getFirstSucceededRemoteDataPayload(),
|
||||
);
|
||||
this.subs.push(
|
||||
observableCombineLatest(
|
||||
bitstream$,
|
||||
allFormats$
|
||||
).subscribe(([bitstream, allFormats]) => {
|
||||
allFormats$,
|
||||
bundle$,
|
||||
primaryBitstream$,
|
||||
item$,
|
||||
).pipe()
|
||||
.subscribe(([bitstream, allFormats, bundle, primaryBitstream, item]) => {
|
||||
this.bitstream = bitstream as Bitstream;
|
||||
this.formats = allFormats.page;
|
||||
this.bundle = bundle;
|
||||
// hasValue(primaryBitstream) because if there's no primaryBitstream on the bundle it will
|
||||
// be a success response, but empty
|
||||
this.primaryBitstreamUUID = hasValue(primaryBitstream) ? primaryBitstream.uuid : null;
|
||||
this.itemId = item.uuid;
|
||||
this.setIiifStatus(this.bitstream);
|
||||
})
|
||||
);
|
||||
@@ -460,7 +469,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
this.formGroup.patchValue({
|
||||
fileNamePrimaryContainer: {
|
||||
fileName: bitstream.name,
|
||||
primaryBitstream: false
|
||||
primaryBitstream: this.primaryBitstreamUUID === bitstream.uuid
|
||||
},
|
||||
descriptionContainer: {
|
||||
description: bitstream.firstMetadataValue('dc.description')
|
||||
@@ -571,9 +580,56 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
const updatedBitstream = this.formToBitstream(updatedValues);
|
||||
const selectedFormat = this.formats.find((f: BitstreamFormat) => f.id === updatedValues.formatContainer.selectedFormat);
|
||||
const isNewFormat = selectedFormat.id !== this.originalFormat.id;
|
||||
const isPrimary = updatedValues.fileNamePrimaryContainer.primaryBitstream;
|
||||
const wasPrimary = this.primaryBitstreamUUID === this.bitstream.uuid;
|
||||
|
||||
let bitstream$;
|
||||
let bundle$: Observable<Bundle>;
|
||||
let errorWhileSaving = false;
|
||||
|
||||
if (wasPrimary !== isPrimary) {
|
||||
let bundleRd$: Observable<RemoteData<Bundle>>;
|
||||
if (wasPrimary) {
|
||||
bundleRd$ = this.primaryBitstreamService.delete(this.bundle);
|
||||
} else if (hasValue(this.primaryBitstreamUUID)) {
|
||||
bundleRd$ = this.primaryBitstreamService.put(this.bitstream, this.bundle);
|
||||
} else {
|
||||
bundleRd$ = this.primaryBitstreamService.create(this.bitstream, this.bundle);
|
||||
}
|
||||
|
||||
const completedBundleRd$ = bundleRd$.pipe(getFirstCompletedRemoteData());
|
||||
|
||||
this.subs.push(completedBundleRd$.pipe(
|
||||
filter((bundleRd: RemoteData<Bundle>) => bundleRd.hasFailed)
|
||||
).subscribe((bundleRd: RemoteData<Bundle>) => {
|
||||
this.notificationsService.error(
|
||||
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'error.primaryBitstream.title'),
|
||||
bundleRd.errorMessage
|
||||
);
|
||||
errorWhileSaving = true;
|
||||
}));
|
||||
|
||||
bundle$ = completedBundleRd$.pipe(
|
||||
map((bundleRd: RemoteData<Bundle>) => {
|
||||
if (bundleRd.hasSucceeded) {
|
||||
return bundleRd.payload;
|
||||
} else {
|
||||
return this.bundle;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.subs.push(bundle$.pipe(
|
||||
hasValueOperator(),
|
||||
switchMap((bundle: Bundle) => this.bitstreamService.findByHref(bundle._links.primaryBitstream.href, false)),
|
||||
getFirstSucceededRemoteDataPayload()
|
||||
).subscribe((bitstream: Bitstream) => {
|
||||
this.primaryBitstreamUUID = hasValue(bitstream) ? bitstream.uuid : null;
|
||||
}));
|
||||
|
||||
} else {
|
||||
bundle$ = observableOf(this.bundle);
|
||||
}
|
||||
if (isNewFormat) {
|
||||
bitstream$ = this.bitstreamService.updateFormat(this.bitstream, selectedFormat).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
@@ -592,7 +648,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
bitstream$ = observableOf(this.bitstream);
|
||||
}
|
||||
|
||||
bitstream$.pipe(
|
||||
combineLatest([bundle$, bitstream$]).pipe(
|
||||
tap(([bundle]) => this.bundle = bundle),
|
||||
switchMap(() => {
|
||||
return this.bitstreamService.update(updatedBitstream).pipe(
|
||||
getFirstSucceededRemoteDataPayload()
|
||||
@@ -604,7 +661,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.title'),
|
||||
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content')
|
||||
);
|
||||
if (!errorWhileSaving) {
|
||||
this.navigateToItemEditBitstreams();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -615,8 +674,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
formToBitstream(rawForm): Bitstream {
|
||||
const updatedBitstream = cloneDeep(this.bitstream);
|
||||
const newMetadata = updatedBitstream.metadata;
|
||||
// TODO: Set bitstream to primary when supported
|
||||
const primary = rawForm.fileNamePrimaryContainer.primaryBitstream;
|
||||
Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName);
|
||||
if (isEmpty(rawForm.descriptionContainer.description)) {
|
||||
delete newMetadata['dc.description'];
|
||||
@@ -668,15 +725,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
||||
* otherwise retrieve the item ID based on the owning bundle's link
|
||||
*/
|
||||
navigateToItemEditBitstreams() {
|
||||
if (hasValue(this.itemId)) {
|
||||
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']));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
181
src/app/core/data/primary-bitstream.service.spec.ts
Normal file
181
src/app/core/data/primary-bitstream.service.spec.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { RequestService } from './request.service';
|
||||
import { Bitstream } from '../shared/bitstream.model';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { getMockRequestService } from '../../shared/mocks/request.service.mock';
|
||||
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { getMockRemoteDataBuildService } from '../../shared/mocks/remote-data-build.service.mock';
|
||||
import { PrimaryBitstreamService } from './primary-bitstream.service';
|
||||
import { BundleDataService } from './bundle-data.service';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||
import { CreateRequest, DeleteRequest, PostRequest, PutRequest } from './request.models';
|
||||
import { createFailedRemoteDataObject, createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { Bundle } from '../shared/bundle.model';
|
||||
import { getTestScheduler } from 'jasmine-marbles';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
|
||||
describe('PrimaryBitstreamService', () => {
|
||||
let service: PrimaryBitstreamService;
|
||||
let objectCache: ObjectCacheService;
|
||||
let requestService: RequestService;
|
||||
let halService: HALEndpointService;
|
||||
let rdbService: RemoteDataBuildService;
|
||||
let notificationService: NotificationsService;
|
||||
let bundleDataService: BundleDataService;
|
||||
|
||||
const bitstream = Object.assign(new Bitstream(), {
|
||||
uuid: 'fake-bitstream',
|
||||
_links: {
|
||||
self: { href: 'fake-bitstream-self' }
|
||||
}
|
||||
});
|
||||
|
||||
const bundle = Object.assign(new Bundle(), {
|
||||
uuid: 'fake-bundle',
|
||||
_links: {
|
||||
self: { href: 'fake-bundle-self' },
|
||||
primaryBitstream: { href: 'fake-primary-bitstream-self' },
|
||||
}
|
||||
});
|
||||
|
||||
const url = 'fake-bitstream-url';
|
||||
|
||||
beforeEach(() => {
|
||||
objectCache = jasmine.createSpyObj('objectCache', {
|
||||
remove: jasmine.createSpy('remove')
|
||||
});
|
||||
requestService = getMockRequestService();
|
||||
halService = Object.assign(new HALEndpointServiceStub(url));
|
||||
|
||||
rdbService = getMockRemoteDataBuildService();
|
||||
notificationService = new NotificationsServiceStub() as any;
|
||||
bundleDataService = jasmine.createSpyObj('bundleDataService', {'findByHref': createSuccessfulRemoteDataObject$(bundle)});
|
||||
service = new PrimaryBitstreamService(requestService, rdbService, objectCache, halService, notificationService, bundleDataService);
|
||||
});
|
||||
|
||||
describe('getHttpOptions', () => {
|
||||
it('should return a HttpOptions object with text/url-list Context-Type header', () => {
|
||||
const result = (service as any).getHttpOptions();
|
||||
expect(result.headers.get('Content-Type')).toEqual('text/uri-list');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createAndSendRequest', () => {
|
||||
const testId = '12345-12345';
|
||||
const options = {};
|
||||
const testResult = createSuccessfulRemoteDataObject(new Bundle());
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(service as any, 'getHttpOptions').and.returnValue(options);
|
||||
(requestService.generateRequestId as jasmine.Spy<any>).and.returnValue(testId);
|
||||
spyOn(rdbService, 'buildFromRequestUUID').and.returnValue(observableOf(testResult));
|
||||
});
|
||||
|
||||
it('should return a Request object with the given constructor and the given parameters', () => {
|
||||
const result = (service as any).createAndSendRequest(CreateRequest, url, bitstream.self);
|
||||
const request = new CreateRequest(testId, url, bitstream.self, options);
|
||||
getTestScheduler().expectObservable(result).toBe('(a|)', { a: testResult });
|
||||
|
||||
expect(requestService.send).toHaveBeenCalledWith(request);
|
||||
expect(rdbService.buildFromRequestUUID).toHaveBeenCalledWith(testId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('create', () => {
|
||||
const testResult = createSuccessfulRemoteDataObject(new Bundle());
|
||||
beforeEach(() => {
|
||||
spyOn((service as any), 'createAndSendRequest').and.returnValue(observableOf(testResult));
|
||||
});
|
||||
|
||||
it('should delegate the call to createAndSendRequest', () => {
|
||||
const result = service.create(bitstream, bundle);
|
||||
getTestScheduler().expectObservable(result).toBe('(a|)', { a: testResult });
|
||||
|
||||
expect((service as any).createAndSendRequest).toHaveBeenCalledWith(
|
||||
PostRequest,
|
||||
bundle._links.primaryBitstream.href,
|
||||
bitstream.self
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('put', () => {
|
||||
const testResult = createSuccessfulRemoteDataObject(new Bundle());
|
||||
beforeEach(() => {
|
||||
spyOn((service as any), 'createAndSendRequest').and.returnValue(observableOf(testResult));
|
||||
});
|
||||
|
||||
it('should delegate the call to createAndSendRequest and return the requested bundle', () => {
|
||||
const result = service.put(bitstream, bundle);
|
||||
getTestScheduler().expectObservable(result).toBe('(a|)', { a: testResult });
|
||||
|
||||
expect((service as any).createAndSendRequest).toHaveBeenCalledWith(
|
||||
PutRequest,
|
||||
bundle._links.primaryBitstream.href,
|
||||
bitstream.self
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('delete', () => {
|
||||
const testBundle = Object.assign(new Bundle(), {
|
||||
_links: {
|
||||
self: {
|
||||
href: 'test-href'
|
||||
},
|
||||
primaryBitstream: {
|
||||
href: 'test-primaryBitstream-href'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe('when the delete request succeeds', () => {
|
||||
const testResult = createSuccessfulRemoteDataObject(new Bundle());
|
||||
const bundleServiceResult = createSuccessfulRemoteDataObject(testBundle);
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn((service as any), 'createAndSendRequest').and.returnValue(observableOf(testResult));
|
||||
(bundleDataService.findByHref as jasmine.Spy<any>).and.returnValue(observableOf(bundleServiceResult));
|
||||
});
|
||||
|
||||
it('should delegate the call to createAndSendRequest', () => {
|
||||
const result = service.delete(testBundle);
|
||||
getTestScheduler().expectObservable(result).toBe('(a|)', { a: bundleServiceResult });
|
||||
|
||||
result.subscribe();
|
||||
|
||||
expect(bundleDataService.findByHref).toHaveBeenCalledWith(testBundle.self, false);
|
||||
|
||||
expect((service as any).createAndSendRequest).toHaveBeenCalledWith(
|
||||
DeleteRequest,
|
||||
testBundle._links.primaryBitstream.href,
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('when the delete request fails', () => {
|
||||
const testResult = createFailedRemoteDataObject();
|
||||
const bundleServiceResult = createSuccessfulRemoteDataObject(testBundle);
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn((service as any), 'createAndSendRequest').and.returnValue(observableOf(testResult));
|
||||
(bundleDataService.findByHref as jasmine.Spy<any>).and.returnValue(observableOf(bundleServiceResult));
|
||||
});
|
||||
|
||||
it('should delegate the call to createAndSendRequest and request the bundle from the bundleDataService', () => {
|
||||
const result = service.delete(testBundle);
|
||||
result.subscribe();
|
||||
expect((service as any).createAndSendRequest).toHaveBeenCalledWith(
|
||||
DeleteRequest,
|
||||
testBundle._links.primaryBitstream.href,
|
||||
);
|
||||
expect(bundleDataService.findByHref).toHaveBeenCalledWith(testBundle.self, true);
|
||||
|
||||
});
|
||||
|
||||
it('should delegate the call to createAndSendRequest and', () => {
|
||||
const result = service.delete(bundle);
|
||||
getTestScheduler().expectObservable(result).toBe('(a|)', { a: bundleServiceResult });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
119
src/app/core/data/primary-bitstream.service.ts
Normal file
119
src/app/core/data/primary-bitstream.service.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { Bitstream } from '../shared/bitstream.model';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RequestService } from './request.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { Observable, switchMap } from 'rxjs';
|
||||
import { RemoteData } from './remote-data';
|
||||
import { Bundle } from '../shared/bundle.model';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { GenericConstructor } from '../shared/generic-constructor';
|
||||
import { PutRequest, PostRequest, DeleteRequest } from './request.models';
|
||||
import { getAllCompletedRemoteData } from '../shared/operators';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { BundleDataService } from './bundle-data.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PrimaryBitstreamService {
|
||||
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected bundleDataService: BundleDataService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of HttpOptions object needed from primary bitstream requests.
|
||||
* i.e. with a Content-Type header set to `text/uri-list`
|
||||
* @protected
|
||||
*/
|
||||
protected getHttpOptions(): HttpOptions {
|
||||
const options: HttpOptions = Object.create({});
|
||||
let headers = new HttpHeaders();
|
||||
headers = headers.append('Content-Type', 'text/uri-list');
|
||||
options.headers = headers;
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request of the given type to the endpointURL with an optional primaryBitstreamSelfLink
|
||||
* as payload, and return the resulting Observable<RemoteData>
|
||||
*
|
||||
* @param requestType The type of request: PostRequest, PutRequest, or DeleteRequest
|
||||
* @param endpointURL The endpoint URL
|
||||
* @param primaryBitstreamSelfLink
|
||||
* @protected
|
||||
*/
|
||||
protected createAndSendRequest(
|
||||
requestType: GenericConstructor<PostRequest | PutRequest | DeleteRequest>,
|
||||
endpointURL: string,
|
||||
primaryBitstreamSelfLink?: string,
|
||||
): Observable<RemoteData<Bundle | NoContent>> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
const request = new requestType(
|
||||
requestId,
|
||||
endpointURL,
|
||||
primaryBitstreamSelfLink,
|
||||
this.getHttpOptions()
|
||||
);
|
||||
|
||||
this.requestService.send(request);
|
||||
|
||||
return this.rdbService.buildFromRequestUUID(requestId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new primaryBitstream
|
||||
*
|
||||
* @param primaryBitstream The object to create
|
||||
* @param bundle The bundle to create it on
|
||||
*/
|
||||
create(primaryBitstream: Bitstream, bundle: Bundle): Observable<RemoteData<Bundle>> {
|
||||
return this.createAndSendRequest(
|
||||
PostRequest,
|
||||
bundle._links.primaryBitstream.href,
|
||||
primaryBitstream.self
|
||||
) as Observable<RemoteData<Bundle>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing primaryBitstream
|
||||
*
|
||||
* @param primaryBitstream The object to update
|
||||
* @param bundle The bundle to update it on
|
||||
*/
|
||||
put(primaryBitstream: Bitstream, bundle: Bundle): Observable<RemoteData<Bundle>> {
|
||||
return this.createAndSendRequest(
|
||||
PutRequest,
|
||||
bundle._links.primaryBitstream.href,
|
||||
primaryBitstream.self
|
||||
) as Observable<RemoteData<Bundle>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing primaryBitstream
|
||||
*
|
||||
* @param bundle The bundle to delete it from
|
||||
*/
|
||||
delete(bundle: Bundle): Observable<RemoteData<Bundle>> {
|
||||
return this.createAndSendRequest(
|
||||
DeleteRequest,
|
||||
bundle._links.primaryBitstream.href
|
||||
).pipe(
|
||||
getAllCompletedRemoteData(),
|
||||
switchMap((rd: RemoteData<NoContent>) => {
|
||||
return this.bundleDataService.findByHref(bundle.self, rd.hasFailed);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -694,6 +694,8 @@
|
||||
|
||||
"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.hint": "Canvas label for this image. If not provided default label will be used.",
|
||||
|
Reference in New Issue
Block a user