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
|
* Requesting them as embeds will limit the number of requests
|
||||||
*/
|
*/
|
||||||
export const BITSTREAM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Bitstream>[] = [
|
export const BITSTREAM_PAGE_LINKS_TO_FOLLOW: FollowLinkConfig<Bitstream>[] = [
|
||||||
followLink('bundle', {}, followLink('item')),
|
followLink('bundle', {}, followLink('primaryBitstream'), followLink('item')),
|
||||||
followLink('format')
|
followLink('format')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@@ -24,6 +24,7 @@ import { createPaginatedList } from '../../shared/testing/utils.test';
|
|||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
import { MetadataValueFilter } from '../../core/shared/metadata.models';
|
import { MetadataValueFilter } from '../../core/shared/metadata.models';
|
||||||
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
|
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 infoNotification: INotification = new Notification('id', NotificationType.Info, 'info');
|
||||||
const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning');
|
const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning');
|
||||||
@@ -32,19 +33,27 @@ const successNotification: INotification = new Notification('id', NotificationTy
|
|||||||
let notificationsService: NotificationsService;
|
let notificationsService: NotificationsService;
|
||||||
let formService: DynamicFormService;
|
let formService: DynamicFormService;
|
||||||
let bitstreamService: BitstreamDataService;
|
let bitstreamService: BitstreamDataService;
|
||||||
|
let primaryBitstreamService: PrimaryBitstreamService;
|
||||||
let bitstreamFormatService: BitstreamFormatDataService;
|
let bitstreamFormatService: BitstreamFormatDataService;
|
||||||
let dsoNameService: DSONameService;
|
let dsoNameService: DSONameService;
|
||||||
let bitstream: Bitstream;
|
let bitstream: Bitstream;
|
||||||
|
let bitstreamID: string;
|
||||||
let selectedFormat: BitstreamFormat;
|
let selectedFormat: BitstreamFormat;
|
||||||
let allFormats: BitstreamFormat[];
|
let allFormats: BitstreamFormat[];
|
||||||
let router: Router;
|
let router: Router;
|
||||||
|
let currentPrimary: string;
|
||||||
|
let differentPrimary: string;
|
||||||
|
let bundle;
|
||||||
let comp: EditBitstreamPageComponent;
|
let comp: EditBitstreamPageComponent;
|
||||||
let fixture: ComponentFixture<EditBitstreamPageComponent>;
|
let fixture: ComponentFixture<EditBitstreamPageComponent>;
|
||||||
|
|
||||||
describe('EditBitstreamPageComponent', () => {
|
describe('EditBitstreamPageComponent', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
bitstreamID = 'current-bitstream-id';
|
||||||
|
currentPrimary = bitstreamID;
|
||||||
|
differentPrimary = '12345-abcde-54321-edcba';
|
||||||
|
|
||||||
allFormats = [
|
allFormats = [
|
||||||
Object.assign({
|
Object.assign({
|
||||||
id: '1',
|
id: '1',
|
||||||
@@ -53,7 +62,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||||
mimetype: 'application/octet-stream',
|
mimetype: 'application/octet-stream',
|
||||||
_links: {
|
_links: {
|
||||||
self: {href: 'format-selflink-1'}
|
self: { href: 'format-selflink-1' }
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Object.assign({
|
Object.assign({
|
||||||
@@ -63,7 +72,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
supportLevel: BitstreamFormatSupportLevel.Known,
|
supportLevel: BitstreamFormatSupportLevel.Known,
|
||||||
mimetype: 'image/png',
|
mimetype: 'image/png',
|
||||||
_links: {
|
_links: {
|
||||||
self: {href: 'format-selflink-2'}
|
self: { href: 'format-selflink-2' }
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Object.assign({
|
Object.assign({
|
||||||
@@ -73,7 +82,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
supportLevel: BitstreamFormatSupportLevel.Known,
|
supportLevel: BitstreamFormatSupportLevel.Known,
|
||||||
mimetype: 'image/gif',
|
mimetype: 'image/gif',
|
||||||
_links: {
|
_links: {
|
||||||
self: {href: 'format-selflink-3'}
|
self: { href: 'format-selflink-3' }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
] as BitstreamFormat[];
|
] as BitstreamFormat[];
|
||||||
@@ -103,15 +112,52 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
success: successNotification
|
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', () => {
|
describe('EditBitstreamPageComponent no IIIF fields', () => {
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
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';
|
const bundleName = 'ORIGINAL';
|
||||||
|
|
||||||
bitstream = Object.assign(new Bitstream(), {
|
bitstream = Object.assign(new Bitstream(), {
|
||||||
|
uuid: bitstreamID,
|
||||||
|
id: bitstreamID,
|
||||||
metadata: {
|
metadata: {
|
||||||
'dc.description': [
|
'dc.description': [
|
||||||
{
|
{
|
||||||
@@ -128,17 +174,11 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
_links: {
|
_links: {
|
||||||
self: 'bitstream-selflink'
|
self: 'bitstream-selflink'
|
||||||
},
|
},
|
||||||
bundle: createSuccessfulRemoteDataObject$({
|
bundle: createSuccessfulRemoteDataObject$(bundle)
|
||||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
|
||||||
uuid: 'some-uuid',
|
|
||||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
|
||||||
return undefined;
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
|
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
commitUpdates: {},
|
commitUpdates: {},
|
||||||
@@ -155,17 +195,19 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
imports: [TranslateModule.forRoot(), RouterTestingModule],
|
imports: [TranslateModule.forRoot(), RouterTestingModule],
|
||||||
declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective],
|
declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: NotificationsService, useValue: notificationsService},
|
{ provide: NotificationsService, useValue: notificationsService },
|
||||||
{provide: DynamicFormService, useValue: formService},
|
{ provide: DynamicFormService, useValue: formService },
|
||||||
{provide: ActivatedRoute,
|
{
|
||||||
|
provide: ActivatedRoute,
|
||||||
useValue: {
|
useValue: {
|
||||||
data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}),
|
data: observableOf({ bitstream: createSuccessfulRemoteDataObject(bitstream) }),
|
||||||
snapshot: {queryParams: {}}
|
snapshot: { queryParams: {} }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
{ provide: BitstreamDataService, useValue: bitstreamService },
|
||||||
{provide: DSONameService, useValue: dsoNameService},
|
{ provide: DSONameService, useValue: dsoNameService },
|
||||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
{ provide: BitstreamFormatDataService, useValue: bitstreamFormatService },
|
||||||
|
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||||
ChangeDetectorRef
|
ChangeDetectorRef
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -203,6 +245,27 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
it('should put the \"New Format\" input on invisible', () => {
|
it('should put the \"New Format\" input on invisible', () => {
|
||||||
expect(comp.formLayout.newFormat.grid.host).toContain('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', () => {
|
describe('when an unknown format is selected', () => {
|
||||||
@@ -216,6 +279,83 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('onSubmit', () => {
|
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', () => {
|
describe('when selected format hasn\'t changed', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
comp.onSubmit();
|
comp.onSubmit();
|
||||||
@@ -261,20 +401,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', () => {
|
||||||
@@ -321,16 +454,22 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
self: 'bitstream-selflink'
|
self: 'bitstream-selflink'
|
||||||
},
|
},
|
||||||
bundle: createSuccessfulRemoteDataObject$({
|
bundle: createSuccessfulRemoteDataObject$({
|
||||||
|
_links: {
|
||||||
|
primaryBitstream: {
|
||||||
|
href: 'bundle-selflink'
|
||||||
|
}
|
||||||
|
},
|
||||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||||
uuid: 'some-uuid',
|
uuid: 'some-uuid',
|
||||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||||
return 'True';
|
return 'True';
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
|
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
commitUpdates: {},
|
commitUpdates: {},
|
||||||
@@ -357,6 +496,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
{provide: BitstreamDataService, useValue: bitstreamService},
|
||||||
{provide: DSONameService, useValue: dsoNameService},
|
{provide: DSONameService, useValue: dsoNameService},
|
||||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||||
|
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||||
ChangeDetectorRef
|
ChangeDetectorRef
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -371,7 +511,6 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
spyOn(router, 'navigate');
|
spyOn(router, 'navigate');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('on startup', () => {
|
describe('on startup', () => {
|
||||||
let rawForm;
|
let rawForm;
|
||||||
|
|
||||||
@@ -440,16 +579,22 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
self: 'bitstream-selflink'
|
self: 'bitstream-selflink'
|
||||||
},
|
},
|
||||||
bundle: createSuccessfulRemoteDataObject$({
|
bundle: createSuccessfulRemoteDataObject$({
|
||||||
|
_links: {
|
||||||
|
primaryBitstream: {
|
||||||
|
href: 'bundle-selflink'
|
||||||
|
}
|
||||||
|
},
|
||||||
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), {
|
||||||
uuid: 'some-uuid',
|
uuid: 'some-uuid',
|
||||||
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string {
|
||||||
return 'True';
|
return 'True';
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
bitstreamService = jasmine.createSpyObj('bitstreamService', {
|
||||||
findById: createSuccessfulRemoteDataObject$(bitstream),
|
findById: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
|
findByHref: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
update: createSuccessfulRemoteDataObject$(bitstream),
|
update: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
updateFormat: createSuccessfulRemoteDataObject$(bitstream),
|
||||||
commitUpdates: {},
|
commitUpdates: {},
|
||||||
@@ -475,6 +620,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
{provide: BitstreamDataService, useValue: bitstreamService},
|
{provide: BitstreamDataService, useValue: bitstreamService},
|
||||||
{provide: DSONameService, useValue: dsoNameService},
|
{provide: DSONameService, useValue: dsoNameService},
|
||||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||||
|
{ provide: PrimaryBitstreamService, useValue: primaryBitstreamService },
|
||||||
ChangeDetectorRef
|
ChangeDetectorRef
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -496,7 +642,7 @@ describe('EditBitstreamPageComponent', () => {
|
|||||||
rawForm = comp.formGroup.getRawValue();
|
rawForm = comp.formGroup.getRawValue();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT set isIIIF to true', () => {
|
it('should NOT set is IIIF to true', () => {
|
||||||
expect(comp.isIIIF).toBeFalse();
|
expect(comp.isIIIF).toBeFalse();
|
||||||
});
|
});
|
||||||
it('should put the \"IIIF Label\" input not to be shown', () => {
|
it('should put the \"IIIF Label\" input not to be shown', () => {
|
||||||
|
@@ -1,57 +1,31 @@
|
|||||||
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 { filter, 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 { UntypedFormGroup } from '@angular/forms';
|
import { UntypedFormGroup } 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, hasValueOperator, 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 { PrimaryBitstreamService } from '../../core/data/primary-bitstream.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-edit-bitstream-page',
|
selector: 'ds-edit-bitstream-page',
|
||||||
@@ -76,6 +50,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
bitstreamFormatsRD$: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
bitstreamFormatsRD$: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UUID of the primary bitstream for this bundle
|
||||||
|
*/
|
||||||
|
primaryBitstreamUUID: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The bitstream to edit
|
* The bitstream to edit
|
||||||
*/
|
*/
|
||||||
@@ -191,19 +170,19 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
* The Dynamic Input Model for the iiif label
|
* The Dynamic Input Model for the iiif label
|
||||||
*/
|
*/
|
||||||
iiifLabelModel = new DsDynamicInputModel({
|
iiifLabelModel = new DsDynamicInputModel({
|
||||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||||
id: 'iiifLabel',
|
id: 'iiifLabel',
|
||||||
name: 'iiifLabel'
|
name: 'iiifLabel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
grid: {
|
grid: {
|
||||||
host: 'col col-lg-6 d-inline-block'
|
host: 'col col-lg-6 d-inline-block'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
iiifLabelContainer = new DynamicFormGroupModel({
|
iiifLabelContainer = new DynamicFormGroupModel({
|
||||||
id: 'iiifLabelContainer',
|
id: 'iiifLabelContainer',
|
||||||
group: [this.iiifLabelModel]
|
group: [this.iiifLabelModel]
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'form-row'
|
host: 'form-row'
|
||||||
}
|
}
|
||||||
@@ -213,7 +192,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||||
id: 'iiifToc',
|
id: 'iiifToc',
|
||||||
name: 'iiifToc',
|
name: 'iiifToc',
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'col col-lg-6 d-inline-block'
|
host: 'col col-lg-6 d-inline-block'
|
||||||
}
|
}
|
||||||
@@ -221,7 +200,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
iiifTocContainer = new DynamicFormGroupModel({
|
iiifTocContainer = new DynamicFormGroupModel({
|
||||||
id: 'iiifTocContainer',
|
id: 'iiifTocContainer',
|
||||||
group: [this.iiifTocModel]
|
group: [this.iiifTocModel]
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'form-row'
|
host: 'form-row'
|
||||||
}
|
}
|
||||||
@@ -231,7 +210,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||||
id: 'iiifWidth',
|
id: 'iiifWidth',
|
||||||
name: 'iiifWidth',
|
name: 'iiifWidth',
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'col col-lg-6 d-inline-block'
|
host: 'col col-lg-6 d-inline-block'
|
||||||
}
|
}
|
||||||
@@ -239,7 +218,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
iiifWidthContainer = new DynamicFormGroupModel({
|
iiifWidthContainer = new DynamicFormGroupModel({
|
||||||
id: 'iiifWidthContainer',
|
id: 'iiifWidthContainer',
|
||||||
group: [this.iiifWidthModel]
|
group: [this.iiifWidthModel]
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'form-row'
|
host: 'form-row'
|
||||||
}
|
}
|
||||||
@@ -249,7 +228,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '',
|
||||||
id: 'iiifHeight',
|
id: 'iiifHeight',
|
||||||
name: 'iiifHeight'
|
name: 'iiifHeight'
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'col col-lg-6 d-inline-block'
|
host: 'col col-lg-6 d-inline-block'
|
||||||
}
|
}
|
||||||
@@ -257,7 +236,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
iiifHeightContainer = new DynamicFormGroupModel({
|
iiifHeightContainer = new DynamicFormGroupModel({
|
||||||
id: 'iiifHeightContainer',
|
id: 'iiifHeightContainer',
|
||||||
group: [this.iiifHeightModel]
|
group: [this.iiifHeightModel]
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'form-row'
|
host: 'form-row'
|
||||||
}
|
}
|
||||||
@@ -280,11 +259,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
this.fileNameModel,
|
this.fileNameModel,
|
||||||
this.primaryBitstreamModel
|
this.primaryBitstreamModel
|
||||||
]
|
]
|
||||||
},{
|
}, {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'form-row'
|
host: 'form-row'
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
new DynamicFormGroupModel({
|
new DynamicFormGroupModel({
|
||||||
id: 'descriptionContainer',
|
id: 'descriptionContainer',
|
||||||
group: [
|
group: [
|
||||||
@@ -316,7 +295,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
},
|
},
|
||||||
primaryBitstream: {
|
primaryBitstream: {
|
||||||
grid: {
|
grid: {
|
||||||
host: 'col col-sm-4 d-inline-block switch'
|
host: 'col col-sm-4 d-inline-block switch border-0'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
@@ -380,13 +359,17 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
isIIIF = false;
|
isIIIF = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array to track all subscriptions and unsubscribe them onDestroy
|
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
*/
|
*/
|
||||||
protected subs: Subscription[] = [];
|
protected subs: Subscription[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The parent bundle containing the Bitstream
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private bundle: Bundle;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute,
|
constructor(private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
@@ -397,7 +380,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
private bitstreamService: BitstreamDataService,
|
private bitstreamService: BitstreamDataService,
|
||||||
public dsoNameService: DSONameService,
|
public dsoNameService: DSONameService,
|
||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private bitstreamFormatService: BitstreamFormatDataService) {
|
private bitstreamFormatService: BitstreamFormatDataService,
|
||||||
|
private primaryBitstreamService: PrimaryBitstreamService,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -410,35 +395,59 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
this.itemId = this.route.snapshot.queryParams.itemId;
|
this.itemId = this.route.snapshot.queryParams.itemId;
|
||||||
this.entityType = this.route.snapshot.queryParams.entityType;
|
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);
|
this.bitstreamFormatsRD$ = this.bitstreamFormatService.findAll(this.findAllOptions);
|
||||||
|
|
||||||
const bitstream$ = this.bitstreamRD$.pipe(
|
const bitstream$ = this.bitstreamRD$.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
getRemoteDataPayload()
|
getRemoteDataPayload(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const allFormats$ = this.bitstreamFormatsRD$.pipe(
|
const allFormats$ = this.bitstreamFormatsRD$.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
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(
|
this.subs.push(
|
||||||
observableCombineLatest(
|
observableCombineLatest(
|
||||||
bitstream$,
|
bitstream$,
|
||||||
allFormats$
|
allFormats$,
|
||||||
).subscribe(([bitstream, allFormats]) => {
|
bundle$,
|
||||||
this.bitstream = bitstream as Bitstream;
|
primaryBitstream$,
|
||||||
this.formats = allFormats.page;
|
item$,
|
||||||
this.setIiifStatus(this.bitstream);
|
).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);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.subs.push(
|
this.subs.push(
|
||||||
this.translate.onLangChange
|
this.translate.onLangChange
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.updateFieldTranslations();
|
this.updateFieldTranslations();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +469,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
this.formGroup.patchValue({
|
this.formGroup.patchValue({
|
||||||
fileNamePrimaryContainer: {
|
fileNamePrimaryContainer: {
|
||||||
fileName: bitstream.name,
|
fileName: bitstream.name,
|
||||||
primaryBitstream: false
|
primaryBitstream: this.primaryBitstreamUUID === bitstream.uuid
|
||||||
},
|
},
|
||||||
descriptionContainer: {
|
descriptionContainer: {
|
||||||
description: bitstream.firstMetadataValue('dc.description')
|
description: bitstream.firstMetadataValue('dc.description')
|
||||||
@@ -571,9 +580,56 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
const updatedBitstream = this.formToBitstream(updatedValues);
|
const updatedBitstream = this.formToBitstream(updatedValues);
|
||||||
const selectedFormat = this.formats.find((f: BitstreamFormat) => f.id === updatedValues.formatContainer.selectedFormat);
|
const selectedFormat = this.formats.find((f: BitstreamFormat) => f.id === updatedValues.formatContainer.selectedFormat);
|
||||||
const isNewFormat = selectedFormat.id !== this.originalFormat.id;
|
const isNewFormat = selectedFormat.id !== this.originalFormat.id;
|
||||||
|
const isPrimary = updatedValues.fileNamePrimaryContainer.primaryBitstream;
|
||||||
|
const wasPrimary = this.primaryBitstreamUUID === this.bitstream.uuid;
|
||||||
|
|
||||||
let bitstream$;
|
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) {
|
if (isNewFormat) {
|
||||||
bitstream$ = this.bitstreamService.updateFormat(this.bitstream, selectedFormat).pipe(
|
bitstream$ = this.bitstreamService.updateFormat(this.bitstream, selectedFormat).pipe(
|
||||||
getFirstCompletedRemoteData(),
|
getFirstCompletedRemoteData(),
|
||||||
@@ -592,7 +648,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
bitstream$ = observableOf(this.bitstream);
|
bitstream$ = observableOf(this.bitstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
@@ -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.title'),
|
||||||
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content')
|
this.translate.instant(this.NOTIFICATIONS_PREFIX + 'saved.content')
|
||||||
);
|
);
|
||||||
this.navigateToItemEditBitstreams();
|
if (!errorWhileSaving) {
|
||||||
|
this.navigateToItemEditBitstreams();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,8 +674,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'];
|
||||||
@@ -633,11 +690,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
Metadata.setFirstValue(newMetadata, this.IIIF_LABEL_METADATA, rawForm.iiifLabelContainer.iiifLabel);
|
Metadata.setFirstValue(newMetadata, this.IIIF_LABEL_METADATA, rawForm.iiifLabelContainer.iiifLabel);
|
||||||
}
|
}
|
||||||
if (isEmpty(rawForm.iiifTocContainer.iiifToc)) {
|
if (isEmpty(rawForm.iiifTocContainer.iiifToc)) {
|
||||||
delete newMetadata[this.IIIF_TOC_METADATA];
|
delete newMetadata[this.IIIF_TOC_METADATA];
|
||||||
} else {
|
} else {
|
||||||
Metadata.setFirstValue(newMetadata, this.IIIF_TOC_METADATA, rawForm.iiifTocContainer.iiifToc);
|
Metadata.setFirstValue(newMetadata, this.IIIF_TOC_METADATA, rawForm.iiifTocContainer.iiifToc);
|
||||||
}
|
}
|
||||||
if (isEmpty(rawForm.iiifWidthContainer.iiifWidth)) {
|
if (isEmpty(rawForm.iiifWidthContainer.iiifWidth)) {
|
||||||
delete newMetadata[this.IMAGE_WIDTH_METADATA];
|
delete newMetadata[this.IMAGE_WIDTH_METADATA];
|
||||||
} else {
|
} else {
|
||||||
@@ -668,15 +725,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']));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -701,11 +750,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy {
|
|||||||
const isEnabled$ = this.bitstream.bundle.pipe(
|
const isEnabled$ = this.bitstream.bundle.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
map((bundle: RemoteData<Bundle>) => bundle.payload.item.pipe(
|
map((bundle: RemoteData<Bundle>) => bundle.payload.item.pipe(
|
||||||
getFirstSucceededRemoteData(),
|
getFirstSucceededRemoteData(),
|
||||||
map((item: RemoteData<Item>) =>
|
map((item: RemoteData<Item>) =>
|
||||||
(item.payload.firstMetadataValue('dspace.iiif.enabled') &&
|
(item.payload.firstMetadataValue('dspace.iiif.enabled') &&
|
||||||
item.payload.firstMetadataValue('dspace.iiif.enabled').match(regexIIIFItem) !== null)
|
item.payload.firstMetadataValue('dspace.iiif.enabled').match(regexIIIFItem) !== null)
|
||||||
))));
|
))));
|
||||||
|
|
||||||
const iiifSub = combineLatest(
|
const iiifSub = combineLatest(
|
||||||
isImage$,
|
isImage$,
|
||||||
|
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.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.",
|
||||||
|
Reference in New Issue
Block a user