From 5865b83697d1bd5d766334681c6e6957345d40c1 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Fri, 3 Dec 2021 14:26:55 -0800 Subject: [PATCH 01/22] Added iiif form fields to the bitstream edit component. --- .../edit-bitstream-page.component.ts | 134 +++++++++++++++++- src/assets/i18n/en.json5 | 17 +++ 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index f6ece7f4fae..27b4ab56d51 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -147,10 +147,34 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { name: 'newFormat' }); + /** + * The Dynamic TextArea Model for the file's description + */ + iiifLabelModel = new DynamicInputModel({ + id: 'iiifLabel', + name: 'iiifLabel' + }); + + iiifTocModel = new DynamicInputModel({ + id: 'iiifToc', + name: 'iiifToc' + }); + + iiifWidthModel = new DynamicInputModel({ + id: 'iiifWidth', + name: 'iiifWidth' + }); + + iiifHeightModel = new DynamicInputModel({ + id: 'iiifHeight', + name: 'iiifHeight' + }); + /** * All input models in a simple array for easier iterations */ - inputModels = [this.fileNameModel, this.primaryBitstreamModel, this.descriptionModel, this.selectedFormatModel, this.newFormatModel]; + inputModels = [this.fileNameModel, this.primaryBitstreamModel, this.descriptionModel, this.selectedFormatModel, + this.newFormatModel, this.iiifLabelModel, this.iiifTocModel, this.iiifWidthModel, this.iiifHeightModel]; /** * The dynamic form fields used for editing the information of a bitstream @@ -176,6 +200,30 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.selectedFormatModel, this.newFormatModel ] + }), + new DynamicFormGroupModel({ + id: 'iiifLabelContainer', + group: [ + this.iiifLabelModel + ] + }), + new DynamicFormGroupModel({ + id: 'iiifTocContainer', + group: [ + this.iiifTocModel + ] + }), + new DynamicFormGroupModel({ + id: 'iiifWidthContainer', + group: [ + this.iiifWidthModel + ] + }), + new DynamicFormGroupModel({ + id: 'iiifHeightContainer', + group: [ + this.iiifHeightModel + ] }) ]; @@ -218,6 +266,26 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { host: this.newFormatBaseLayout + ' invisible' } }, + iiifLabel: { + grid: { + host: 'd-none' + } + }, + iiifToc: { + grid: { + host: 'd-none' + } + }, + iiifWidth: { + grid: { + host: 'd-none' + } + }, + iiifHeight: { + grid: { + host: 'd-none' + } + }, fileNamePrimaryContainer: { grid: { host: 'row position-relative' @@ -232,7 +300,27 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { grid: { host: 'row' } - } + }, + iiifLabelContainer: { + grid: { + host: 'row' + } + }, + iiifTocContainer: { + grid: { + host: 'row' + } + }, + iiifWidthContainer: { + grid: { + host: 'row' + } + }, + iiifHeightContainer: { + grid: { + host: 'row' + } + }, }; /** @@ -254,6 +342,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ entityType: string; + isIIIF: boolean; + /** * Array to track all subscriptions and unsubscribe them onDestroy * @type {Array} @@ -303,6 +393,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.formats = allFormats.page; this.updateFormatModel(); this.updateForm(this.bitstream); + this.setIiifStatus(this.bitstream); }) ); @@ -467,6 +558,12 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { const primary = rawForm.fileNamePrimaryContainer.primaryBitstream; Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName); Metadata.setFirstValue(newMetadata, 'dc.description', rawForm.descriptionContainer.description); + if (this.isIIIF) { + Metadata.setFirstValue(newMetadata, 'iiif.label', rawForm.iiifLabelContainer.iiifLabel); + Metadata.setFirstValue(newMetadata, 'iiif.toc', rawForm.iiifTocContainer.iiifToc); + Metadata.setFirstValue(newMetadata, 'iiif.image.width', rawForm.iiifWidthContainer.iiifWidth); + Metadata.setFirstValue(newMetadata, 'iiif.image.height', rawForm.iiifHeightContainer.iiifHeight); + } if (isNotEmpty(rawForm.formatContainer.newFormat)) { Metadata.setFirstValue(newMetadata, 'dc.format', rawForm.formatContainer.newFormat); } @@ -497,6 +594,39 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { } } + /** + * If the parent item is iiif-enabled, the update boolean isIIIF property and show + * iiif fields in the form. + * @param bitstream + */ + setIiifStatus(bitstream: Bitstream) { + this.bitstream.bundle.pipe(getFirstSucceededRemoteDataPayload(), + mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload()))) + .subscribe((item) => { + if (item.firstMetadataValue('dspace.iiif.enabled').match('true') !== null) { + this.isIIIF = true; + this.formLayout.iiifLabel.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifToc.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifWidth.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifHeight.grid.host = this.newFormatBaseLayout; + this.formGroup.patchValue({ + iiifLabelContainer: { + iiifLabel: bitstream.firstMetadataValue('iiif.label') + }, + iiifTocContainer: { + iiifToc: bitstream.firstMetadataValue('iiif.toc') + }, + iiifWidthContainer: { + iiifWidth: bitstream.firstMetadataValue('iiif.image.width') + }, + iiifHeightContainer: { + iiifHeight: bitstream.firstMetadataValue('iiif.image.height') + } + }); + } + }); + } + /** * Unsubscribe from open subscriptions */ diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 8edc01b2780..f4cbf0e1e59 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -582,6 +582,23 @@ "bitstream.edit.notifications.error.format.title": "An error occurred saving the bitstream's format", + "bitstream.edit.form.iiifLabel.label": "IIIF Label", + + "bitstream.edit.form.iiifLabel.hint": "Canvas label for this image", + + "bitstream.edit.form.iiifToc.label": "IIIF Table of Contents", + + "bitstream.edit.form.iiifToc.hint": "Add label to make this image the start of a new range.", + + "bitstream.edit.form.iiifWidth.label": "IIIF canvas width", + + "bitstream.edit.form.iiifWidth.hint": "The canvas width should match the image width.", + + "bitstream.edit.form.iiifHeight.label": "IIIF canvas height", + + "bitstream.edit.form.iiifHeight.hint": "The canvas height should match the image height.", + + "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", "bitstream.edit.notifications.saved.title": "Bitstream saved", From 9ae38f4a6c2ad45f481939cfa42a0e4463dfd343 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Fri, 3 Dec 2021 18:00:26 -0800 Subject: [PATCH 02/22] Completed edit page and tests. --- .../edit-bitstream-page.component.spec.ts | 369 ++++++++++++------ .../edit-bitstream-page.component.ts | 5 +- 2 files changed, 244 insertions(+), 130 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 67f8866e6df..1425372e593 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -30,8 +30,10 @@ const successNotification: INotification = new Notification('id', NotificationTy let notificationsService: NotificationsService; let formService: DynamicFormService; let bitstreamService: BitstreamDataService; +let bitstreamServiceIIIF: BitstreamDataService; let bitstreamFormatService: BitstreamFormatDataService; let bitstream: Bitstream; +let bitstreamIIIFItem: Bitstream; let selectedFormat: BitstreamFormat; let allFormats: BitstreamFormat[]; let router: Router; @@ -48,7 +50,7 @@ describe('EditBitstreamPageComponent', () => { description: 'Unknown format', supportLevel: BitstreamFormatSupportLevel.Unknown, _links: { - self: { href: 'format-selflink-1' } + self: {href: 'format-selflink-1'} } }), Object.assign({ @@ -57,7 +59,7 @@ describe('EditBitstreamPageComponent', () => { description: 'Portable Network Graphics', supportLevel: BitstreamFormatSupportLevel.Known, _links: { - self: { href: 'format-selflink-2' } + self: {href: 'format-selflink-2'} } }), Object.assign({ @@ -66,7 +68,7 @@ describe('EditBitstreamPageComponent', () => { description: 'Graphics Interchange Format', supportLevel: BitstreamFormatSupportLevel.Known, _links: { - self: { href: 'format-selflink-3' } + self: {href: 'format-selflink-3'} } }) ] as BitstreamFormat[]; @@ -90,156 +92,265 @@ describe('EditBitstreamPageComponent', () => { return undefined; } }); - bitstream = Object.assign(new Bitstream(), { - metadata: { - 'dc.description': [ - { - value: 'Bitstream description' - } - ], - 'dc.title': [ - { - value: 'Bitstream title' - } - ] - }, - format: createSuccessfulRemoteDataObject$(selectedFormat), - _links: { - self: 'bitstream-selflink' - }, - bundle: createSuccessfulRemoteDataObject$({ - item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { - uuid: 'some-uuid' - })) - }) - }); - bitstreamService = jasmine.createSpyObj('bitstreamService', { - findById: createSuccessfulRemoteDataObject$(bitstream), - update: createSuccessfulRemoteDataObject$(bitstream), - updateFormat: createSuccessfulRemoteDataObject$(bitstream), - commitUpdates: {}, - patch: {} - }); - bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { - findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) - }); - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], - providers: [ - { provide: NotificationsService, useValue: notificationsService }, - { provide: DynamicFormService, useValue: formService }, - { provide: ActivatedRoute, useValue: { data: observableOf({ bitstream: createSuccessfulRemoteDataObject(bitstream) }), snapshot: { queryParams: {} } } }, - { provide: BitstreamDataService, useValue: bitstreamService }, - { provide: BitstreamFormatDataService, useValue: bitstreamFormatService }, - ChangeDetectorRef - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); + describe('EditBitstreamPageComponent without IIIF fields', () => { + beforeEach(waitForAsync(() => { + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ] + }, + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { + uuid: 'some-uuid', + firstMetadataValue: () => '', + })) + }) + }); - })); + bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { + findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) + }); - beforeEach(() => { - fixture = TestBed.createComponent(EditBitstreamPageComponent); - comp = fixture.componentInstance; - fixture.detectChanges(); - router = TestBed.inject(Router); - spyOn(router, 'navigate'); - }); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); - describe('on startup', () => { - let rawForm; + beforeEach(() => { + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); + }); - beforeEach(() => { - rawForm = comp.formGroup.getRawValue(); - }); + describe('on startup', () => { + let rawForm; - it('should fill in the bitstream\'s title', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); - }); + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); - it('should fill in the bitstream\'s description', () => { - expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); - }); + it('should fill in the bitstream\'s title', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); + }); - it('should select the correct format', () => { - expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); - }); + it('should fill in the bitstream\'s description', () => { + expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); + }); - it('should put the \"New Format\" input on invisible', () => { - expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); - }); - }); + it('should select the correct format', () => { + expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); + }); - describe('when an unknown format is selected', () => { - beforeEach(() => { - comp.updateNewFormatLayout(allFormats[0].id); - }); + it('should put the \"New Format\" input on invisible', () => { + expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); + }); + it('should put the \"IIIF Label\" input to be display: none', () => { + expect(comp.formLayout.iiifLabel.grid.host).toContain('d-none'); + }); + it('should set isIIIF to false', () => { + expect(comp.isIIIF).toBeFalse(); + }); + }); - it('should remove the invisible class from the \"New Format\" input', () => { - expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); - }); - }); + describe('when an unknown format is selected', () => { + beforeEach(() => { + comp.updateNewFormatLayout(allFormats[0].id); + }); - describe('onSubmit', () => { - describe('when selected format hasn\'t changed', () => { - beforeEach(() => { - comp.onSubmit(); + it('should remove the invisible class from the \"New Format\" input', () => { + expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); + }); }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); - }); + describe('onSubmit', () => { + describe('when selected format hasn\'t changed', () => { + beforeEach(() => { + comp.onSubmit(); + }); - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); + }); + + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + }); + }); + + describe('when selected format has changed', () => { + beforeEach(() => { + comp.formGroup.patchValue({ + formatContainer: { + selectedFormat: allFormats[2].id + } + }); + fixture.detectChanges(); + comp.onSubmit(); + }); + + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); + }); + + it('should call updateFormat', () => { + expect(bitstreamService.updateFormat).toHaveBeenCalled(); + }); + + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + }); + }); }); + describe('when the cancel button is clicked', () => { + it('should call navigateToItemEditBitstreams method', () => { + spyOn(comp, 'navigateToItemEditBitstreams'); + comp.onCancel(); + expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); + }); + }); + describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { + 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('when selected format has changed', () => { - beforeEach(() => { - comp.formGroup.patchValue({ - formatContainer: { - selectedFormat: allFormats[2].id - } + describe('EditBitstreamPageComponent with IIIF', () => { + + beforeEach(waitForAsync(() => { + bitstreamService = jasmine.createSpyObj('bitstreamService', { + findById: createSuccessfulRemoteDataObject$(bitstream), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + bitstreamIIIFItem = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ] + }, + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { + uuid: 'some-uuid', + firstMetadataValue: () => 'true', + metadata: { + 'dspace.iiif.enabled': [ + { + language: null, + value: 'true' + } + ] + } + })) + }) }); + bitstreamServiceIIIF = jasmine.createSpyObj('bitstreamService', { + findById: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), + update: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), + updateFormat: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), + commitUpdates: {}, + patch: {} + }); + + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamServiceIIIF}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + beforeEach(() => { + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; fixture.detectChanges(); - comp.onSubmit(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); + }); + describe('on startup', () => { + it('should set isIIIF to true', () => { + expect(comp.isIIIF).toBeTrue(); }); - - it('should call updateFormat', () => { - expect(bitstreamService.updateFormat).toHaveBeenCalled(); + it('should put the \"IIIF Label\" input to be shown', () => { + expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); }); - - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + it('should put the \"IIIF Toc\" input to be shown', () => { + expect(comp.formLayout.iiifToc.grid.host).toContain('col'); + }); + it('should put the \"IIIF width\" input to be shown', () => { + expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); + }); + it('should put the \"IIIF Height\" input to be shown', () => { + expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); }); }); - }); - describe('when the cancel button is clicked', () => { - it('should call navigateToItemEditBitstreams method', () => { - spyOn(comp, 'navigateToItemEditBitstreams'); - comp.onCancel(); - expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); - }); - }); - describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { - 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']); - }); - }); + + })); + }); diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 27b4ab56d51..67b470b501c 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -342,7 +342,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ entityType: string; - isIIIF: boolean; + /** + * Set to true when the parent item supports IIIF. + */ + isIIIF = false; /** * Array to track all subscriptions and unsubscribe them onDestroy From e521f2d579797a2f8ea8f1e27abe0c1a4d649b68 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Sat, 4 Dec 2021 13:54:48 -0800 Subject: [PATCH 03/22] Added tests for iiif form field content at startup --- .../edit-bitstream-page.component.spec.ts | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 1425372e593..1283ea956c6 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -276,7 +276,27 @@ describe('EditBitstreamPageComponent', () => { { value: 'Bitstream title' } - ] + ], + 'iiif.label': [ + { + value: 'chapter one' + } + ], + 'iiif.toc': [ + { + value: 'chapter one' + } + ], + 'iiif.image.width': [ + { + value: '2400' + } + ], + 'iiif.image.height': [ + { + value: '2800' + } + ], }, format: createSuccessfulRemoteDataObject$(selectedFormat), _links: { @@ -334,6 +354,11 @@ describe('EditBitstreamPageComponent', () => { }); describe('on startup', () => { + let rawForm; + + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); it('should set isIIIF to true', () => { expect(comp.isIIIF).toBeTrue(); }); @@ -349,6 +374,18 @@ describe('EditBitstreamPageComponent', () => { it('should put the \"IIIF Height\" input to be shown', () => { expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); }); + it('should fill in the iiif label', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('chapter one'); + }); + it('should fill in the iiif toc', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('chapter one'); + }); + it('should fill in the iiif width', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('2400'); + }); + it('should fill in the iiif height', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('2800'); + }); }); })); From fe5b7663e90328a44b09552c498f8ab7e0df7562 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Sun, 5 Dec 2021 18:24:16 -0800 Subject: [PATCH 04/22] All edit component tests are running and passing --- .../edit-bitstream-page.component.spec.ts | 537 +++++++++--------- 1 file changed, 264 insertions(+), 273 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 1283ea956c6..324b5712c87 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -22,6 +22,7 @@ import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } f import { getEntityEditRoute } from '../../item-page/item-page-routing-paths'; import { createPaginatedList } from '../../shared/testing/utils.test'; import { Item } from '../../core/shared/item.model'; +import { MetadataValueFilter } from '../../core/shared/metadata.models'; const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info'); const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning'); @@ -30,17 +31,16 @@ const successNotification: INotification = new Notification('id', NotificationTy let notificationsService: NotificationsService; let formService: DynamicFormService; let bitstreamService: BitstreamDataService; -let bitstreamServiceIIIF: BitstreamDataService; let bitstreamFormatService: BitstreamFormatDataService; let bitstream: Bitstream; -let bitstreamIIIFItem: Bitstream; let selectedFormat: BitstreamFormat; let allFormats: BitstreamFormat[]; let router: Router; +let comp: EditBitstreamPageComponent; +let fixture: ComponentFixture; + describe('EditBitstreamPageComponent', () => { - let comp: EditBitstreamPageComponent; - let fixture: ComponentFixture; beforeEach(waitForAsync(() => { allFormats = [ @@ -92,302 +92,293 @@ describe('EditBitstreamPageComponent', () => { return undefined; } }); - - describe('EditBitstreamPageComponent without IIIF fields', () => { - beforeEach(waitForAsync(() => { - bitstream = Object.assign(new Bitstream(), { - metadata: { - 'dc.description': [ - { - value: 'Bitstream description' - } - ], - 'dc.title': [ - { - value: 'Bitstream title' - } - ] + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ] + }, + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { + uuid: 'some-uuid', + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return undefined; }, - format: createSuccessfulRemoteDataObject$(selectedFormat), - _links: { - self: 'bitstream-selflink' - }, - bundle: createSuccessfulRemoteDataObject$({ - item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { - uuid: 'some-uuid', - firstMetadataValue: () => '', - })) - }) - }); - - bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { - findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) - }); - - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], - providers: [ - {provide: NotificationsService, useValue: notificationsService}, - {provide: DynamicFormService, useValue: formService}, - {provide: ActivatedRoute, - useValue: { - data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), - snapshot: {queryParams: {}} - } - }, - {provide: BitstreamDataService, useValue: bitstreamService}, - {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, - ChangeDetectorRef - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(EditBitstreamPageComponent); - comp = fixture.componentInstance; - fixture.detectChanges(); - router = TestBed.inject(Router); - spyOn(router, 'navigate'); - }); - - describe('on startup', () => { - let rawForm; + })) + }) + }); + bitstreamService = jasmine.createSpyObj('bitstreamService', { + findById: createSuccessfulRemoteDataObject$(bitstream), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { + findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) + }); - beforeEach(() => { - rawForm = comp.formGroup.getRawValue(); - }); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); - it('should fill in the bitstream\'s title', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); - }); + })); - it('should fill in the bitstream\'s description', () => { - expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); - }); + beforeEach(() => { + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); + }); - it('should select the correct format', () => { - expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); - }); + describe('on startup', () => { + let rawForm; - it('should put the \"New Format\" input on invisible', () => { - expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); - }); - it('should put the \"IIIF Label\" input to be display: none', () => { - expect(comp.formLayout.iiifLabel.grid.host).toContain('d-none'); - }); - it('should set isIIIF to false', () => { - expect(comp.isIIIF).toBeFalse(); - }); - }); - - describe('when an unknown format is selected', () => { - beforeEach(() => { - comp.updateNewFormatLayout(allFormats[0].id); - }); - - it('should remove the invisible class from the \"New Format\" input', () => { - expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); - }); - }); + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); - describe('onSubmit', () => { - describe('when selected format hasn\'t changed', () => { - beforeEach(() => { - comp.onSubmit(); - }); + it('should fill in the bitstream\'s title', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); + }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); - }); + it('should fill in the bitstream\'s description', () => { + expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); + }); - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); - }); - }); + it('should select the correct format', () => { + expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); + }); - describe('when selected format has changed', () => { - beforeEach(() => { - comp.formGroup.patchValue({ - formatContainer: { - selectedFormat: allFormats[2].id - } - }); - fixture.detectChanges(); - comp.onSubmit(); - }); + it('should put the \"New Format\" input on invisible', () => { + expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); + }); + }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); - }); + describe('when an unknown format is selected', () => { + beforeEach(() => { + comp.updateNewFormatLayout(allFormats[0].id); + }); - it('should call updateFormat', () => { - expect(bitstreamService.updateFormat).toHaveBeenCalled(); - }); + it('should remove the invisible class from the \"New Format\" input', () => { + expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); + }); + }); - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); - }); - }); - }); - describe('when the cancel button is clicked', () => { - it('should call navigateToItemEditBitstreams method', () => { - spyOn(comp, 'navigateToItemEditBitstreams'); - comp.onCancel(); - expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); - }); - }); - describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { - 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('onSubmit', () => { + describe('when selected format hasn\'t changed', () => { + beforeEach(() => { + comp.onSubmit(); }); - 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']); - }); + + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); }); + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + }); }); - describe('EditBitstreamPageComponent with IIIF', () => { - - beforeEach(waitForAsync(() => { - bitstreamService = jasmine.createSpyObj('bitstreamService', { - findById: createSuccessfulRemoteDataObject$(bitstream), - update: createSuccessfulRemoteDataObject$(bitstream), - updateFormat: createSuccessfulRemoteDataObject$(bitstream), - commitUpdates: {}, - patch: {} - }); - bitstreamIIIFItem = Object.assign(new Bitstream(), { - metadata: { - 'dc.description': [ - { - value: 'Bitstream description' - } - ], - 'dc.title': [ - { - value: 'Bitstream title' - } - ], - 'iiif.label': [ - { - value: 'chapter one' - } - ], - 'iiif.toc': [ - { - value: 'chapter one' - } - ], - 'iiif.image.width': [ - { - value: '2400' - } - ], - 'iiif.image.height': [ - { - value: '2800' - } - ], - }, - format: createSuccessfulRemoteDataObject$(selectedFormat), - _links: { - self: 'bitstream-selflink' - }, - bundle: createSuccessfulRemoteDataObject$({ - item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { - uuid: 'some-uuid', - firstMetadataValue: () => 'true', - metadata: { - 'dspace.iiif.enabled': [ - { - language: null, - value: 'true' - } - ] - } - })) - }) - }); - bitstreamServiceIIIF = jasmine.createSpyObj('bitstreamService', { - findById: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), - update: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), - updateFormat: createSuccessfulRemoteDataObject$(bitstreamIIIFItem), - commitUpdates: {}, - patch: {} - }); - - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], - providers: [ - {provide: NotificationsService, useValue: notificationsService}, - {provide: DynamicFormService, useValue: formService}, - {provide: ActivatedRoute, - useValue: { - data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), - snapshot: {queryParams: {}} - } - }, - {provide: BitstreamDataService, useValue: bitstreamServiceIIIF}, - {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, - ChangeDetectorRef - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - })); + describe('when selected format has changed', () => { beforeEach(() => { - fixture = TestBed.createComponent(EditBitstreamPageComponent); - comp = fixture.componentInstance; + comp.formGroup.patchValue({ + formatContainer: { + selectedFormat: allFormats[2].id + } + }); fixture.detectChanges(); - router = TestBed.inject(Router); - spyOn(router, 'navigate'); + comp.onSubmit(); }); - }); - describe('on startup', () => { - let rawForm; - - beforeEach(() => { - rawForm = comp.formGroup.getRawValue(); - }); - it('should set isIIIF to true', () => { - expect(comp.isIIIF).toBeTrue(); - }); - it('should put the \"IIIF Label\" input to be shown', () => { - expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); - }); - it('should put the \"IIIF Toc\" input to be shown', () => { - expect(comp.formLayout.iiifToc.grid.host).toContain('col'); + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); }); - it('should put the \"IIIF width\" input to be shown', () => { - expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); - }); - it('should put the \"IIIF Height\" input to be shown', () => { - expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); - }); - it('should fill in the iiif label', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('chapter one'); - }); - it('should fill in the iiif toc', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('chapter one'); - }); - it('should fill in the iiif width', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('2400'); + + it('should call updateFormat', () => { + expect(bitstreamService.updateFormat).toHaveBeenCalled(); }); - it('should fill in the iiif height', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual('2800'); + + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); }); }); + }); + describe('when the cancel button is clicked', () => { + it('should call navigateToItemEditBitstreams method', () => { + spyOn(comp, 'navigateToItemEditBitstreams'); + comp.onCancel(); + expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); + }); + }); + describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { + 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', () => { + + beforeEach(waitForAsync(() => { + bitstreamService = jasmine.createSpyObj('bitstreamService', { + findById: createSuccessfulRemoteDataObject$(bitstream), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ], + 'iiif.label': [ + { + value: 'chapter one' + } + ], + 'iiif.toc': [ + { + value: 'chapter one' + } + ], + 'iiif.image.width': [ + { + value: '2400' + } + ], + 'iiif.image.height': [ + { + value: '2800' + } + ], + }, + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + 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), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); })); + beforeEach(() => { + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); + }); + + + describe('on startup', () => { + let rawForm; + + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); + it('should set isIIIF to true', () => { + expect(comp.isIIIF).toBeTrue(); + }); + it('should put the \"IIIF Label\" input to be shown', () => { + expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); + }); + it('should put the \"IIIF Toc\" input to be shown', () => { + expect(comp.formLayout.iiifToc.grid.host).toContain('col'); + }); + it('should put the \"IIIF width\" input to be shown', () => { + expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); + }); + it('should put the \"IIIF Height\" input to be shown', () => { + expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); + }); + it('should fill in the iiif label', () => { + expect(rawForm.iiifLabelContainer.iiifLabel).toEqual('chapter one'); + }); + it('should fill in the iiif toc', () => { + expect(rawForm.iiifTocContainer.iiifToc).toEqual('chapter one'); + }); + it('should fill in the iiif width', () => { + expect(rawForm.iiifWidthContainer.iiifWidth).toEqual('2400'); + }); + it('should fill in the iiif height', () => { + expect(rawForm.iiifHeightContainer.iiifHeight).toEqual('2800'); + }); + }); }); From b4b17136a6c27bd223d601e621c7d0dffa6d7dfe Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Sun, 5 Dec 2021 18:25:12 -0800 Subject: [PATCH 05/22] Updated regex and condition for iiif.enabled metadata check. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 67b470b501c..337dae993a2 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -606,7 +606,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.bitstream.bundle.pipe(getFirstSucceededRemoteDataPayload(), mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload()))) .subscribe((item) => { - if (item.firstMetadataValue('dspace.iiif.enabled').match('true') !== null) { + const regex = /(true|yes)/i; + if (item.firstMetadataValue('dspace.iiif.enabled') && + item.firstMetadataValue('dspace.iiif.enabled').match(regex) !== null) { this.isIIIF = true; this.formLayout.iiifLabel.grid.host = this.newFormatBaseLayout; this.formLayout.iiifToc.grid.host = this.newFormatBaseLayout; From c112a036df138f8a71015447a29d33dd14a2ae59 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 6 Dec 2021 12:56:13 -0800 Subject: [PATCH 06/22] Clean up test. --- .../edit-bitstream-page.component.spec.ts | 510 +++++++++--------- 1 file changed, 258 insertions(+), 252 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 324b5712c87..2ddfaab4b49 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -42,7 +42,7 @@ let fixture: ComponentFixture; describe('EditBitstreamPageComponent', () => { - beforeEach(waitForAsync(() => { + beforeEach(() => { allFormats = [ Object.assign({ id: '1', @@ -73,13 +73,7 @@ describe('EditBitstreamPageComponent', () => { }) ] as BitstreamFormat[]; selectedFormat = allFormats[1]; - notificationsService = jasmine.createSpyObj('notificationsService', - { - info: infoNotification, - warning: warningNotification, - success: successNotification - } - ); + formService = Object.assign({ createFormGroup: (fModel: DynamicFormControlModel[]) => { const controls = {}; @@ -92,293 +86,305 @@ describe('EditBitstreamPageComponent', () => { return undefined; } }); - bitstream = Object.assign(new Bitstream(), { - metadata: { - 'dc.description': [ - { - value: 'Bitstream description' - } - ], - 'dc.title': [ - { - value: 'Bitstream title' - } - ] - }, - format: createSuccessfulRemoteDataObject$(selectedFormat), - _links: { - self: 'bitstream-selflink' - }, - bundle: createSuccessfulRemoteDataObject$({ - item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { - uuid: 'some-uuid', - firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { - return undefined; - }, - })) - }) - }); - bitstreamService = jasmine.createSpyObj('bitstreamService', { - findById: createSuccessfulRemoteDataObject$(bitstream), - update: createSuccessfulRemoteDataObject$(bitstream), - updateFormat: createSuccessfulRemoteDataObject$(bitstream), - commitUpdates: {}, - patch: {} - }); + bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) }); - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], - providers: [ - {provide: NotificationsService, useValue: notificationsService}, - {provide: DynamicFormService, useValue: formService}, - {provide: ActivatedRoute, - useValue: { - data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), - snapshot: {queryParams: {}} - } - }, - {provide: BitstreamDataService, useValue: bitstreamService}, - {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, - ChangeDetectorRef - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - - })); - - beforeEach(() => { - fixture = TestBed.createComponent(EditBitstreamPageComponent); - comp = fixture.componentInstance; - fixture.detectChanges(); - router = TestBed.inject(Router); - spyOn(router, 'navigate'); + notificationsService = jasmine.createSpyObj('notificationsService', + { + info: infoNotification, + warning: warningNotification, + success: successNotification + } + ); }); - describe('on startup', () => { - let rawForm; + describe('EditBitstreamPageComponent no IIIF fields', () => { - beforeEach(() => { - rawForm = comp.formGroup.getRawValue(); - }); + beforeEach(waitForAsync(() => { - it('should fill in the bitstream\'s title', () => { - expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); - }); - - it('should fill in the bitstream\'s description', () => { - expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); - }); + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ] + }, + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + item: createSuccessfulRemoteDataObject$(Object.assign(new Item(), { + uuid: 'some-uuid', + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return undefined; + }, + })) + }) + }); + bitstreamService = jasmine.createSpyObj('bitstreamService', { + findById: createSuccessfulRemoteDataObject$(bitstream), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { + findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) + }); - it('should select the correct format', () => { - expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); - }); + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); - it('should put the \"New Format\" input on invisible', () => { - expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); - }); - }); + })); - describe('when an unknown format is selected', () => { beforeEach(() => { - comp.updateNewFormatLayout(allFormats[0].id); + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); }); - it('should remove the invisible class from the \"New Format\" input', () => { - expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); - }); - }); + describe('on startup', () => { + let rawForm; - describe('onSubmit', () => { - describe('when selected format hasn\'t changed', () => { beforeEach(() => { - comp.onSubmit(); + rawForm = comp.formGroup.getRawValue(); + }); + + it('should fill in the bitstream\'s title', () => { + expect(rawForm.fileNamePrimaryContainer.fileName).toEqual(bitstream.name); }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); + it('should fill in the bitstream\'s description', () => { + expect(rawForm.descriptionContainer.description).toEqual(bitstream.firstMetadataValue('dc.description')); }); - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + it('should select the correct format', () => { + expect(rawForm.formatContainer.selectedFormat).toEqual(selectedFormat.id); + }); + + it('should put the \"New Format\" input on invisible', () => { + expect(comp.formLayout.newFormat.grid.host).toContain('invisible'); }); }); - describe('when selected format has changed', () => { + describe('when an unknown format is selected', () => { beforeEach(() => { - comp.formGroup.patchValue({ - formatContainer: { - selectedFormat: allFormats[2].id - } - }); - fixture.detectChanges(); - comp.onSubmit(); + comp.updateNewFormatLayout(allFormats[0].id); }); - it('should call update', () => { - expect(bitstreamService.update).toHaveBeenCalled(); + it('should remove the invisible class from the \"New Format\" input', () => { + expect(comp.formLayout.newFormat.grid.host).not.toContain('invisible'); }); + }); - it('should call updateFormat', () => { - expect(bitstreamService.updateFormat).toHaveBeenCalled(); + describe('onSubmit', () => { + describe('when selected format hasn\'t changed', () => { + beforeEach(() => { + comp.onSubmit(); + }); + + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); + }); + + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + }); }); - it('should commit the updates', () => { - expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + describe('when selected format has changed', () => { + beforeEach(() => { + comp.formGroup.patchValue({ + formatContainer: { + selectedFormat: allFormats[2].id + } + }); + fixture.detectChanges(); + comp.onSubmit(); + }); + + it('should call update', () => { + expect(bitstreamService.update).toHaveBeenCalled(); + }); + + it('should call updateFormat', () => { + expect(bitstreamService.updateFormat).toHaveBeenCalled(); + }); + + it('should commit the updates', () => { + expect(bitstreamService.commitUpdates).toHaveBeenCalled(); + }); }); }); - }); - describe('when the cancel button is clicked', () => { - it('should call navigateToItemEditBitstreams method', () => { - spyOn(comp, 'navigateToItemEditBitstreams'); - comp.onCancel(); - expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); + describe('when the cancel button is clicked', () => { + it('should call navigateToItemEditBitstreams method', () => { + spyOn(comp, 'navigateToItemEditBitstreams'); + comp.onCancel(); + expect(comp.navigateToItemEditBitstreams).toHaveBeenCalled(); + }); }); - }); - describe('when navigateToItemEditBitstreams is called, and the component has an itemId', () => { - 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 has an itemId', () => { + 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('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', () => { - beforeEach(waitForAsync(() => { - bitstreamService = jasmine.createSpyObj('bitstreamService', { - findById: createSuccessfulRemoteDataObject$(bitstream), - update: createSuccessfulRemoteDataObject$(bitstream), - updateFormat: createSuccessfulRemoteDataObject$(bitstream), - commitUpdates: {}, - patch: {} - }); - bitstream = Object.assign(new Bitstream(), { - metadata: { - 'dc.description': [ - { - value: 'Bitstream description' - } - ], - 'dc.title': [ - { - value: 'Bitstream title' - } - ], - 'iiif.label': [ - { - value: 'chapter one' - } - ], - 'iiif.toc': [ - { - value: 'chapter one' - } - ], - 'iiif.image.width': [ - { - value: '2400' - } - ], - 'iiif.image.height': [ - { - value: '2800' - } - ], - }, - format: createSuccessfulRemoteDataObject$(selectedFormat), - _links: { - self: 'bitstream-selflink' - }, - bundle: createSuccessfulRemoteDataObject$({ - 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), - update: createSuccessfulRemoteDataObject$(bitstream), - updateFormat: createSuccessfulRemoteDataObject$(bitstream), - commitUpdates: {}, - patch: {} - }); + describe('EditBitstreamPageComponent with IIIF fields', () => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), RouterTestingModule], - declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], - providers: [ - {provide: NotificationsService, useValue: notificationsService}, - {provide: DynamicFormService, useValue: formService}, - {provide: ActivatedRoute, - useValue: { - data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), - snapshot: {queryParams: {}} - } + beforeEach(waitForAsync(() => { + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ], + 'iiif.label': [ + { + value: 'chapter one' + } + ], + 'iiif.toc': [ + { + value: 'chapter one' + } + ], + 'iiif.image.width': [ + { + value: '2400' + } + ], + 'iiif.image.height': [ + { + value: '2800' + } + ], }, - {provide: BitstreamDataService, useValue: bitstreamService}, - {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, - ChangeDetectorRef - ], - schemas: [NO_ERRORS_SCHEMA] - }).compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(EditBitstreamPageComponent); - comp = fixture.componentInstance; - fixture.detectChanges(); - router = TestBed.inject(Router); - spyOn(router, 'navigate'); - }); - + format: createSuccessfulRemoteDataObject$(selectedFormat), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + 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), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); - describe('on startup', () => { - let rawForm; + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); beforeEach(() => { - rawForm = comp.formGroup.getRawValue(); - }); - it('should set isIIIF to true', () => { - expect(comp.isIIIF).toBeTrue(); - }); - it('should put the \"IIIF Label\" input to be shown', () => { - expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); - }); - it('should put the \"IIIF Toc\" input to be shown', () => { - expect(comp.formLayout.iiifToc.grid.host).toContain('col'); - }); - it('should put the \"IIIF width\" input to be shown', () => { - expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); - }); - it('should put the \"IIIF Height\" input to be shown', () => { - expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); - }); - it('should fill in the iiif label', () => { - expect(rawForm.iiifLabelContainer.iiifLabel).toEqual('chapter one'); - }); - it('should fill in the iiif toc', () => { - expect(rawForm.iiifTocContainer.iiifToc).toEqual('chapter one'); - }); - it('should fill in the iiif width', () => { - expect(rawForm.iiifWidthContainer.iiifWidth).toEqual('2400'); + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); }); - it('should fill in the iiif height', () => { - expect(rawForm.iiifHeightContainer.iiifHeight).toEqual('2800'); + + + describe('on startup', () => { + let rawForm; + + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); + it('should set isIIIF to true', () => { + expect(comp.isIIIF).toBeTrue(); + }); + it('should put the \"IIIF Label\" input to be shown', () => { + expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); + }); + it('should put the \"IIIF Toc\" input to be shown', () => { + expect(comp.formLayout.iiifToc.grid.host).toContain('col'); + }); + it('should put the \"IIIF width\" input to be shown', () => { + expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); + }); + it('should put the \"IIIF Height\" input to be shown', () => { + expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); + }); + it('should fill in the iiif label', () => { + expect(rawForm.iiifLabelContainer.iiifLabel).toEqual('chapter one'); + }); + it('should fill in the iiif toc', () => { + expect(rawForm.iiifTocContainer.iiifToc).toEqual('chapter one'); + }); + it('should fill in the iiif width', () => { + expect(rawForm.iiifWidthContainer.iiifWidth).toEqual('2400'); + }); + it('should fill in the iiif height', () => { + expect(rawForm.iiifHeightContainer.iiifHeight).toEqual('2800'); + }); }); }); }); From c1a0b21e2a1448a120eb462cf8250b12e1816eb4 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 16 Dec 2021 15:57:38 -0800 Subject: [PATCH 07/22] Added additional conditions to check before adding iiif form elements. --- .../edit-bitstream-page.component.spec.ts | 134 +++++++++++++++++- .../edit-bitstream-page.component.ts | 87 ++++++++---- 2 files changed, 189 insertions(+), 32 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 2ddfaab4b49..1be53d686ed 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -23,6 +23,7 @@ import { getEntityEditRoute } from '../../item-page/item-page-routing-paths'; 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'; const infoNotification: INotification = new Notification('id', NotificationType.Info, 'info'); const warningNotification: INotification = new Notification('id', NotificationType.Warning, 'warning'); @@ -32,6 +33,7 @@ let notificationsService: NotificationsService; let formService: DynamicFormService; let bitstreamService: BitstreamDataService; let bitstreamFormatService: BitstreamFormatDataService; +let dsoNameService: DSONameService; let bitstream: Bitstream; let selectedFormat: BitstreamFormat; let allFormats: BitstreamFormat[]; @@ -49,6 +51,7 @@ describe('EditBitstreamPageComponent', () => { shortDescription: 'Unknown', description: 'Unknown format', supportLevel: BitstreamFormatSupportLevel.Unknown, + mimetype: 'application/octet-stream', _links: { self: {href: 'format-selflink-1'} } @@ -58,6 +61,7 @@ describe('EditBitstreamPageComponent', () => { shortDescription: 'PNG', description: 'Portable Network Graphics', supportLevel: BitstreamFormatSupportLevel.Known, + mimetype: 'image/png', _links: { self: {href: 'format-selflink-2'} } @@ -67,6 +71,7 @@ describe('EditBitstreamPageComponent', () => { shortDescription: 'GIF', description: 'Graphics Interchange Format', supportLevel: BitstreamFormatSupportLevel.Known, + mimetype: 'image/gif', _links: { self: {href: 'format-selflink-3'} } @@ -104,6 +109,8 @@ describe('EditBitstreamPageComponent', () => { beforeEach(waitForAsync(() => { + const bundleName = 'ORIGINAL'; + bitstream = Object.assign(new Bitstream(), { metadata: { 'dc.description': [ @@ -140,6 +147,9 @@ describe('EditBitstreamPageComponent', () => { bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', { findAll: createSuccessfulRemoteDataObject$(createPaginatedList(allFormats)) }); + dsoNameService = jasmine.createSpyObj('dsoNameService', { + getName: bundleName + }); TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule], @@ -154,6 +164,7 @@ describe('EditBitstreamPageComponent', () => { } }, {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: DSONameService, useValue: dsoNameService}, {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, ChangeDetectorRef ], @@ -268,7 +279,10 @@ describe('EditBitstreamPageComponent', () => { describe('EditBitstreamPageComponent with IIIF fields', () => { + const bundleName = 'ORIGINAL'; + beforeEach(waitForAsync(() => { + bitstream = Object.assign(new Bitstream(), { metadata: { 'dc.description': [ @@ -302,7 +316,7 @@ describe('EditBitstreamPageComponent', () => { } ], }, - format: createSuccessfulRemoteDataObject$(selectedFormat), + format: createSuccessfulRemoteDataObject$(allFormats[1]), _links: { self: 'bitstream-selflink' }, @@ -323,19 +337,25 @@ describe('EditBitstreamPageComponent', () => { patch: {} }); + dsoNameService = jasmine.createSpyObj('dsoNameService', { + getName: bundleName + }); + TestBed.configureTestingModule({ imports: [TranslateModule.forRoot(), RouterTestingModule], declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], providers: [ {provide: NotificationsService, useValue: notificationsService}, {provide: DynamicFormService, useValue: formService}, - {provide: ActivatedRoute, + { + provide: ActivatedRoute, useValue: { data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), snapshot: {queryParams: {}} } }, {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: DSONameService, useValue: dsoNameService}, {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, ChangeDetectorRef ], @@ -387,4 +407,114 @@ describe('EditBitstreamPageComponent', () => { }); }); }); + + describe('ignore OTHERCONTENT bundle', () => { + + const bundleName = 'OTHERCONTENT'; + + beforeEach(waitForAsync(() => { + + bitstream = Object.assign(new Bitstream(), { + metadata: { + 'dc.description': [ + { + value: 'Bitstream description' + } + ], + 'dc.title': [ + { + value: 'Bitstream title' + } + ], + 'iiif.label': [ + { + value: 'chapter one' + } + ], + 'iiif.toc': [ + { + value: 'chapter one' + } + ], + 'iiif.image.width': [ + { + value: '2400' + } + ], + 'iiif.image.height': [ + { + value: '2800' + } + ], + }, + format: createSuccessfulRemoteDataObject$(allFormats[2]), + _links: { + self: 'bitstream-selflink' + }, + bundle: createSuccessfulRemoteDataObject$({ + 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), + update: createSuccessfulRemoteDataObject$(bitstream), + updateFormat: createSuccessfulRemoteDataObject$(bitstream), + commitUpdates: {}, + patch: {} + }); + + dsoNameService = jasmine.createSpyObj('dsoNameService', { + getName: bundleName + }); + + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), RouterTestingModule], + declarations: [EditBitstreamPageComponent, FileSizePipe, VarDirective], + providers: [ + {provide: NotificationsService, useValue: notificationsService}, + {provide: DynamicFormService, useValue: formService}, + {provide: ActivatedRoute, + useValue: { + data: observableOf({bitstream: createSuccessfulRemoteDataObject(bitstream)}), + snapshot: {queryParams: {}} + } + }, + {provide: BitstreamDataService, useValue: bitstreamService}, + {provide: DSONameService, useValue: dsoNameService}, + {provide: BitstreamFormatDataService, useValue: bitstreamFormatService}, + ChangeDetectorRef + ], + schemas: [NO_ERRORS_SCHEMA] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditBitstreamPageComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + router = TestBed.inject(Router); + spyOn(router, 'navigate'); + }); + + describe('EditBitstreamPageComponent with IIIF fields', () => { + let rawForm; + + beforeEach(() => { + rawForm = comp.formGroup.getRawValue(); + }); + + it('should NOT set isIIIF to true', () => { + expect(comp.isIIIF).toBeFalse(); + }); + it('should put the \"IIIF Label\" input not to be shown', () => { + expect(comp.formLayout.iiifLabel.grid.host).toContain('d-none'); + }); + }); + }); + }); diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 337dae993a2..9d91affd959 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -1,7 +1,7 @@ import { ChangeDetectionStrategy, 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 { filter, map, mergeMap, switchMap } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { DynamicFormControlModel, @@ -35,6 +35,10 @@ 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 { Bundle } from '../../core/shared/bundle.model'; +import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; +import { Collection } from '../../core/shared/collection.model'; +import { Item } from '../../core/shared/item.model'; +import { Format } from '@angular-devkit/build-angular/src/extract-i18n/schema'; @Component({ selector: 'ds-edit-bitstream-page', @@ -359,6 +363,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { private formService: DynamicFormService, private translate: TranslateService, private bitstreamService: BitstreamDataService, + private dsoNameService: DSONameService, private notificationsService: NotificationsService, private bitstreamFormatService: BitstreamFormatDataService) { } @@ -598,38 +603,60 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { } /** - * If the parent item is iiif-enabled, the update boolean isIIIF property and show - * iiif fields in the form. + * Checks bitstream mimetype to be sure it's an image, excludes bitstreams in the OTHERCONTENT bundle + * since even if the bitstream is an image it will not be displayed within the viewer, + * and finally verifies that the parent item itself is iiif-enabled. * @param bitstream */ setIiifStatus(bitstream: Bitstream) { - this.bitstream.bundle.pipe(getFirstSucceededRemoteDataPayload(), - mergeMap((bundle: Bundle) => bundle.item.pipe(getFirstSucceededRemoteDataPayload()))) - .subscribe((item) => { - const regex = /(true|yes)/i; - if (item.firstMetadataValue('dspace.iiif.enabled') && - item.firstMetadataValue('dspace.iiif.enabled').match(regex) !== null) { - this.isIIIF = true; - this.formLayout.iiifLabel.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifToc.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifWidth.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifHeight.grid.host = this.newFormatBaseLayout; - this.formGroup.patchValue({ - iiifLabelContainer: { - iiifLabel: bitstream.firstMetadataValue('iiif.label') - }, - iiifTocContainer: { - iiifToc: bitstream.firstMetadataValue('iiif.toc') - }, - iiifWidthContainer: { - iiifWidth: bitstream.firstMetadataValue('iiif.image.width') - }, - iiifHeightContainer: { - iiifHeight: bitstream.firstMetadataValue('iiif.image.height') - } - }); - } - }); + + const iiifCheck$ = this.bitstream.format.pipe( + getFirstSucceededRemoteData(), + filter((format: RemoteData) => format.payload.mimetype.includes('image/')), + mergeMap((format: RemoteData) => + this.bitstream.bundle.pipe( + getFirstSucceededRemoteData(), + filter((bundle: RemoteData) => + this.dsoNameService.getName(bundle.payload) !== 'OTHERCONTENT'), + mergeMap((bundle: RemoteData) => bundle.payload.item.pipe( + getFirstSucceededRemoteData(), + map((remoteData: RemoteData) => { + const regex = /(true|yes)/i; + return (remoteData.payload.firstMetadataValue('dspace.iiif.enabled') && + remoteData.payload.firstMetadataValue('dspace.iiif.enabled').match(regex) !== null); + }) + )) + ) + ) + ); + + // If iiifCheck$ returns true, enable the IIIF form elements. + const iiifSub = iiifCheck$.subscribe((iiif: boolean) => { + if (iiif) { + this.isIIIF = true; + this.formLayout.iiifLabel.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifToc.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifWidth.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifHeight.grid.host = this.newFormatBaseLayout; + this.formGroup.patchValue({ + iiifLabelContainer: { + iiifLabel: bitstream.firstMetadataValue('iiif.label') + }, + iiifTocContainer: { + iiifToc: bitstream.firstMetadataValue('iiif.toc') + }, + iiifWidthContainer: { + iiifWidth: bitstream.firstMetadataValue('iiif.image.width') + }, + iiifHeightContainer: { + iiifHeight: bitstream.firstMetadataValue('iiif.image.height') + } + }); + } + }); + + this.subs.push(iiifSub); + } /** From e02bb7507515f8da8b0d0d0f81bab96f545a6232 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 16 Dec 2021 16:14:02 -0800 Subject: [PATCH 08/22] Unused import. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 9d91affd959..bc724bc408b 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -36,9 +36,7 @@ import { PaginatedList } from '../../core/data/paginated-list.model'; import { getEntityEditRoute, getItemEditRoute } from '../../item-page/item-page-routing-paths'; import { Bundle } from '../../core/shared/bundle.model'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; -import { Collection } from '../../core/shared/collection.model'; import { Item } from '../../core/shared/item.model'; -import { Format } from '@angular-devkit/build-angular/src/extract-i18n/schema'; @Component({ selector: 'ds-edit-bitstream-page', From 4fbf99a4513690df6a5789d94440d991f30a919f Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Fri, 17 Dec 2021 10:14:39 -0800 Subject: [PATCH 09/22] Added change detection to assure the form updates. --- .../edit-bitstream-page.component.ts | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index bc724bc408b..9aeadb61928 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -1,4 +1,10 @@ -import { ChangeDetectionStrategy, 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 { filter, map, mergeMap, switchMap } from 'rxjs/operators'; @@ -355,8 +361,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ protected subs: Subscription[] = []; + constructor(private route: ActivatedRoute, private router: Router, + private changeDetectorRef: ChangeDetectorRef, private location: Location, private formService: DynamicFormService, private translate: TranslateService, @@ -397,9 +405,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { ).subscribe(([bitstream, allFormats]) => { this.bitstream = bitstream as Bitstream; this.formats = allFormats.page; + this.setIiifStatus(this.bitstream); // testing this.updateFormatModel(); this.updateForm(this.bitstream); - this.setIiifStatus(this.bitstream); }) ); @@ -601,13 +609,17 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { } /** - * Checks bitstream mimetype to be sure it's an image, excludes bitstreams in the OTHERCONTENT bundle - * since even if the bitstream is an image it will not be displayed within the viewer, - * and finally verifies that the parent item itself is iiif-enabled. + * Checks bitstream mimetype to be sure it's an image, excludes any bitstream in the + * THUMBNAIL bundle or in the OTHERCONTENT bundle since in that case the image bitstream + * it will never be displayed in the viewer, and last verifies that the parent item + * is iiif-enabled. * @param bitstream */ setIiifStatus(bitstream: Bitstream) { + const regexExcludeBundles = /OTHERCONTENT|THUMBNAIL/; + const regexIIIFItem = /(true|yes)/i; + const iiifCheck$ = this.bitstream.format.pipe( getFirstSucceededRemoteData(), filter((format: RemoteData) => format.payload.mimetype.includes('image/')), @@ -615,14 +627,13 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.bitstream.bundle.pipe( getFirstSucceededRemoteData(), filter((bundle: RemoteData) => - this.dsoNameService.getName(bundle.payload) !== 'OTHERCONTENT'), + this.dsoNameService.getName(bundle.payload).match(regexExcludeBundles) == null), mergeMap((bundle: RemoteData) => bundle.payload.item.pipe( getFirstSucceededRemoteData(), - map((remoteData: RemoteData) => { - const regex = /(true|yes)/i; - return (remoteData.payload.firstMetadataValue('dspace.iiif.enabled') && - remoteData.payload.firstMetadataValue('dspace.iiif.enabled').match(regex) !== null); - }) + map((remoteData: RemoteData) => + (remoteData.payload.firstMetadataValue('dspace.iiif.enabled') && + remoteData.payload.firstMetadataValue('dspace.iiif.enabled').match(regexIIIFItem) !== null) + ) )) ) ) @@ -650,6 +661,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { iiifHeight: bitstream.firstMetadataValue('iiif.image.height') } }); + // Assure that the form always detects the iiif addition. + this.changeDetectorRef.detectChanges(); } }); From b3808ba6a16479fa5b9265b0a4dd18d6d0a91711 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Fri, 17 Dec 2021 10:38:35 -0800 Subject: [PATCH 10/22] Minor update to setIIIFStatus method. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 9aeadb61928..87b8e7fe31f 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -405,7 +405,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { ).subscribe(([bitstream, allFormats]) => { this.bitstream = bitstream as Bitstream; this.formats = allFormats.page; - this.setIiifStatus(this.bitstream); // testing + this.setIiifStatus(this.bitstream); this.updateFormatModel(); this.updateForm(this.bitstream); }) @@ -611,19 +611,19 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * Checks bitstream mimetype to be sure it's an image, excludes any bitstream in the * THUMBNAIL bundle or in the OTHERCONTENT bundle since in that case the image bitstream - * it will never be displayed in the viewer, and last verifies that the parent item + * it will never be displayed in the viewer, and finally verifies that the parent item * is iiif-enabled. * @param bitstream */ setIiifStatus(bitstream: Bitstream) { const regexExcludeBundles = /OTHERCONTENT|THUMBNAIL/; - const regexIIIFItem = /(true|yes)/i; + const regexIIIFItem = /true|yes/i; const iiifCheck$ = this.bitstream.format.pipe( getFirstSucceededRemoteData(), filter((format: RemoteData) => format.payload.mimetype.includes('image/')), - mergeMap((format: RemoteData) => + mergeMap(() => this.bitstream.bundle.pipe( getFirstSucceededRemoteData(), filter((bundle: RemoteData) => From 4f6b579204275efe7f5bb78ac70eebd5a9189c30 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Fri, 17 Dec 2021 15:46:12 -0800 Subject: [PATCH 11/22] Remove metatada field when no data is provided in form. Updated comments. --- .../edit-bitstream-page.component.ts | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 87b8e7fe31f..c52ffc68c70 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -34,7 +34,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s 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 } from '../../shared/empty.util'; +import { hasValue, isNotEmpty, isEmpty } from '../../shared/empty.util'; import { Metadata } from '../../core/shared/metadata.utils'; import { Location } from '@angular/common'; import { RemoteData } from '../../core/data/remote-data'; @@ -573,10 +573,29 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName); Metadata.setFirstValue(newMetadata, 'dc.description', rawForm.descriptionContainer.description); if (this.isIIIF) { - Metadata.setFirstValue(newMetadata, 'iiif.label', rawForm.iiifLabelContainer.iiifLabel); - Metadata.setFirstValue(newMetadata, 'iiif.toc', rawForm.iiifTocContainer.iiifToc); - Metadata.setFirstValue(newMetadata, 'iiif.image.width', rawForm.iiifWidthContainer.iiifWidth); - Metadata.setFirstValue(newMetadata, 'iiif.image.height', rawForm.iiifHeightContainer.iiifHeight); + // It's helpful to remove these metadata elements entirely when the form value is empty. + // This avoids potential issues on the REST side and makes it possible to do things like + // remove an existing "table of contents" entry. + if (isEmpty(rawForm.iiifLabelContainer.iiifLabel)) { + delete newMetadata['iiif.label']; + } else { + Metadata.setFirstValue(newMetadata, 'iiif.label', rawForm.iiifLabelContainer.iiifLabel); + } + if (isEmpty(rawForm.iiifTocContainer.iiifToc)) { + delete newMetadata['iiif.toc']; + } else { + Metadata.setFirstValue(newMetadata, 'iiif.toc', rawForm.iiifTocContainer.iiifToc); + } + if (isEmpty(rawForm.iiifHeightContainer.iiifWidth)) { + delete newMetadata['iiif.image.width']; + } else { + Metadata.setFirstValue(newMetadata, 'iiif.image.width', rawForm.iiifWidthContainer.iiifWidth); + } + if (isEmpty(rawForm.iiifHeightContainer.iiifHeight)) { + delete newMetadata['iiif.image.height']; + } else { + Metadata.setFirstValue(newMetadata, 'iiif.image.height', rawForm.iiifHeightContainer.iiifHeight); + } } if (isNotEmpty(rawForm.formatContainer.newFormat)) { Metadata.setFirstValue(newMetadata, 'dc.format', rawForm.formatContainer.newFormat); @@ -609,10 +628,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { } /** - * Checks bitstream mimetype to be sure it's an image, excludes any bitstream in the - * THUMBNAIL bundle or in the OTHERCONTENT bundle since in that case the image bitstream - * it will never be displayed in the viewer, and finally verifies that the parent item - * is iiif-enabled. + * Verifies that the parent item is iiif-enabled. Checks bitstream mimetype to be + * sure it's an image, excluding bitstreams in the THUMBNAIL or OTHERCONTENT bundles. * @param bitstream */ setIiifStatus(bitstream: Bitstream) { @@ -661,7 +678,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { iiifHeight: bitstream.firstMetadataValue('iiif.image.height') } }); - // Assure that the form always detects the iiif addition. + // Assures that the form always includes the iiif additions. this.changeDetectorRef.detectChanges(); } }); From 8d3b265038bcbac777f8d56f9169ad084c796304 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Fri, 21 Jan 2022 14:43:39 -0800 Subject: [PATCH 12/22] Using DsDynamicInputModel* and updating scss for ds-dynamic-form-control-container. --- .../edit-bitstream-page.component.ts | 77 +++++++++++++------ ...amic-form-control-container.component.scss | 4 + src/assets/i18n/en.json5 | 6 +- 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index c52ffc68c70..6347c703f9a 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -43,6 +43,8 @@ import { getEntityEditRoute, getItemEditRoute } from '../../item-page/item-page- 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 { DsDynamicTextAreaModel } from '../../shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-textarea.model'; @Component({ selector: 'ds-edit-bitstream-page', @@ -102,6 +104,26 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ NOTIFICATIONS_PREFIX = 'bitstream.edit.notifications.'; + /** + * IIIF image width metadata key + */ + IMAGE_WIDTH_METADATA = 'iiif.image.width'; + + /** + * IIIF image height metadata key + */ + IMAGE_HEIGHT_METADATA = 'iiif.image.height' + + /** + * IIIF table of contents metadata key + */ + IIIF_TOC_METADATA = 'iiif.toc'; + + /** + * IIIF label metadata key + */ + IIIF_LABEL_METADATA = 'iiif.label' + /** * Options for fetching all bitstream formats */ @@ -110,7 +132,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * The Dynamic Input Model for the file's name */ - fileNameModel = new DynamicInputModel({ + fileNameModel = new DsDynamicInputModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'fileName', name: 'fileName', required: true, @@ -133,7 +156,8 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * The Dynamic TextArea Model for the file's description */ - descriptionModel = new DynamicTextAreaModel({ + descriptionModel = new DsDynamicTextAreaModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'description', name: 'description', rows: 10 @@ -156,24 +180,31 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { }); /** - * The Dynamic TextArea Model for the file's description + * The Dynamic Input Model for the iiif label */ - iiifLabelModel = new DynamicInputModel({ + iiifLabelModel = new DsDynamicInputModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifLabel', - name: 'iiifLabel' + name: 'iiifLabel', + hint: 'bitstream.edit.form.iiifLabel.hint' }); - iiifTocModel = new DynamicInputModel({ + iiifTocModel = new DsDynamicInputModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifToc', - name: 'iiifToc' + name: 'iiifToc', + hint: 'bitstream.edit.form.iiifLabel.hint' }); - iiifWidthModel = new DynamicInputModel({ + iiifWidthModel = new DsDynamicInputModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifWidth', - name: 'iiifWidth' + name: 'iiifWidth', + hint: 'bitstream.edit.form.iiifLabel.hint' }); - iiifHeightModel = new DynamicInputModel({ + iiifHeightModel = new DsDynamicInputModel({ + hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifHeight', name: 'iiifHeight' }); @@ -577,24 +608,24 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { // This avoids potential issues on the REST side and makes it possible to do things like // remove an existing "table of contents" entry. if (isEmpty(rawForm.iiifLabelContainer.iiifLabel)) { - delete newMetadata['iiif.label']; + delete newMetadata[this.IIIF_LABEL_METADATA]; } else { - Metadata.setFirstValue(newMetadata, 'iiif.label', rawForm.iiifLabelContainer.iiifLabel); + Metadata.setFirstValue(newMetadata, this.IIIF_LABEL_METADATA, rawForm.iiifLabelContainer.iiifLabel); } if (isEmpty(rawForm.iiifTocContainer.iiifToc)) { - delete newMetadata['iiif.toc']; + delete newMetadata[this.IIIF_TOC_METADATA]; } else { - Metadata.setFirstValue(newMetadata, 'iiif.toc', rawForm.iiifTocContainer.iiifToc); + Metadata.setFirstValue(newMetadata, this.IIIF_TOC_METADATA, rawForm.iiifTocContainer.iiifToc); } - if (isEmpty(rawForm.iiifHeightContainer.iiifWidth)) { - delete newMetadata['iiif.image.width']; + if (isEmpty(rawForm.iiifWidthContainer.iiifWidth)) { + delete newMetadata[this.IMAGE_WIDTH_METADATA]; } else { - Metadata.setFirstValue(newMetadata, 'iiif.image.width', rawForm.iiifWidthContainer.iiifWidth); + Metadata.setFirstValue(newMetadata, this.IMAGE_WIDTH_METADATA, rawForm.iiifWidthContainer.iiifWidth); } if (isEmpty(rawForm.iiifHeightContainer.iiifHeight)) { - delete newMetadata['iiif.image.height']; + delete newMetadata[this.IMAGE_HEIGHT_METADATA]; } else { - Metadata.setFirstValue(newMetadata, 'iiif.image.height', rawForm.iiifHeightContainer.iiifHeight); + Metadata.setFirstValue(newMetadata, this.IMAGE_HEIGHT_METADATA, rawForm.iiifHeightContainer.iiifHeight); } } if (isNotEmpty(rawForm.formatContainer.newFormat)) { @@ -666,16 +697,16 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.formLayout.iiifHeight.grid.host = this.newFormatBaseLayout; this.formGroup.patchValue({ iiifLabelContainer: { - iiifLabel: bitstream.firstMetadataValue('iiif.label') + iiifLabel: bitstream.firstMetadataValue(this.IIIF_LABEL_METADATA) }, iiifTocContainer: { - iiifToc: bitstream.firstMetadataValue('iiif.toc') + iiifToc: bitstream.firstMetadataValue(this.IIIF_TOC_METADATA) }, iiifWidthContainer: { - iiifWidth: bitstream.firstMetadataValue('iiif.image.width') + iiifWidth: bitstream.firstMetadataValue(this.IMAGE_WIDTH_METADATA) }, iiifHeightContainer: { - iiifHeight: bitstream.firstMetadataValue('iiif.image.height') + iiifHeight: bitstream.firstMetadataValue(this.IMAGE_HEIGHT_METADATA) } }); // Assures that the form always includes the iiif additions. diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss index 4e58759f4e7..05e7421e40b 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss @@ -14,3 +14,7 @@ -moz-appearance: none; appearance: none; } + +label { + margin-top: calc(0.7 * var(--ds-content-spacing)); +} \ No newline at end of file diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index f4cbf0e1e59..15c8d111ec0 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -588,15 +588,15 @@ "bitstream.edit.form.iiifToc.label": "IIIF Table of Contents", - "bitstream.edit.form.iiifToc.hint": "Add label to make this image the start of a new range.", + "bitstream.edit.form.iiifToc.hint": "Adding label makes this image the start of a new table of contents range.", "bitstream.edit.form.iiifWidth.label": "IIIF canvas width", - "bitstream.edit.form.iiifWidth.hint": "The canvas width should match the image width.", + "bitstream.edit.form.iiifWidth.hint": "The canvas width should usually match the image width.", "bitstream.edit.form.iiifHeight.label": "IIIF canvas height", - "bitstream.edit.form.iiifHeight.hint": "The canvas height should match the image height.", + "bitstream.edit.form.iiifHeight.hint": "The canvas height should usually match the image height.", "bitstream.edit.notifications.saved.content": "Your changes to this bitstream were saved.", From 0e6dae2b6147cd841eb5a892455fa3c339ba3313 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Fri, 21 Jan 2022 15:05:52 -0800 Subject: [PATCH 13/22] Added semis. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 6347c703f9a..284366d9ed8 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -112,7 +112,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * IIIF image height metadata key */ - IMAGE_HEIGHT_METADATA = 'iiif.image.height' + IMAGE_HEIGHT_METADATA = 'iiif.image.height'; /** * IIIF table of contents metadata key @@ -122,7 +122,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { /** * IIIF label metadata key */ - IIIF_LABEL_METADATA = 'iiif.label' + IIIF_LABEL_METADATA = 'iiif.label'; /** * Options for fetching all bitstream formats From 32b2e181bd8a73d7de5b1d9afde5e9b05becca28 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Fri, 21 Jan 2022 16:42:49 -0800 Subject: [PATCH 14/22] Removed unused import. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 284366d9ed8..cc8997dc5ad 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -15,8 +15,7 @@ import { DynamicFormLayout, DynamicFormService, DynamicInputModel, - DynamicSelectModel, - DynamicTextAreaModel + DynamicSelectModel } from '@ng-dynamic-forms/core'; import { FormGroup } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -185,22 +184,19 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { iiifLabelModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifLabel', - name: 'iiifLabel', - hint: 'bitstream.edit.form.iiifLabel.hint' + name: 'iiifLabel' }); iiifTocModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifToc', name: 'iiifToc', - hint: 'bitstream.edit.form.iiifLabel.hint' }); iiifWidthModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifWidth', name: 'iiifWidth', - hint: 'bitstream.edit.form.iiifLabel.hint' }); iiifHeightModel = new DsDynamicInputModel({ From 9649b5fb6872b728a54216abf26769763f5da906 Mon Sep 17 00:00:00 2001 From: Michael W Spalti Date: Sat, 22 Jan 2022 15:44:50 -0800 Subject: [PATCH 15/22] More layout changes. --- .../edit-bitstream-page.component.scss | 4 ++++ .../edit-bitstream-page.component.ts | 13 +++++++++---- ...ds-dynamic-form-control-container.component.scss | 4 ---- src/assets/i18n/en.json5 | 4 ++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss index 13de59700c1..a0f0cc173d3 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss @@ -6,3 +6,7 @@ } } } +:host ::ng-deep ds-dynamic-form-control-container > div { + margin-bottom: 1rem; +} + diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index cc8997dc5ad..9b160f486b4 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -267,6 +267,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ newFormatBaseLayout = 'col col-sm-6 d-inline-block'; + /** + * Base layout for iiif options + */ + iiifOptionsBaseLayout = 'col col-sm-6'; + /** * Layout used for structuring the form inputs */ @@ -687,10 +692,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { const iiifSub = iiifCheck$.subscribe((iiif: boolean) => { if (iiif) { this.isIIIF = true; - this.formLayout.iiifLabel.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifToc.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifWidth.grid.host = this.newFormatBaseLayout; - this.formLayout.iiifHeight.grid.host = this.newFormatBaseLayout; + this.formLayout.iiifLabel.grid.host = this.iiifOptionsBaseLayout; + this.formLayout.iiifToc.grid.host = this.iiifOptionsBaseLayout; + this.formLayout.iiifWidth.grid.host = this.iiifOptionsBaseLayout; + this.formLayout.iiifHeight.grid.host = this.iiifOptionsBaseLayout; this.formGroup.patchValue({ iiifLabelContainer: { iiifLabel: bitstream.firstMetadataValue(this.IIIF_LABEL_METADATA) diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss index 05e7421e40b..4e58759f4e7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.scss @@ -14,7 +14,3 @@ -moz-appearance: none; appearance: none; } - -label { - margin-top: calc(0.7 * var(--ds-content-spacing)); -} \ No newline at end of file diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index 15c8d111ec0..d2b770af9ea 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -584,11 +584,11 @@ "bitstream.edit.form.iiifLabel.label": "IIIF Label", - "bitstream.edit.form.iiifLabel.hint": "Canvas label for this image", + "bitstream.edit.form.iiifLabel.hint": "Canvas label for this image. If not provided default label will be used.", "bitstream.edit.form.iiifToc.label": "IIIF Table of Contents", - "bitstream.edit.form.iiifToc.hint": "Adding label makes this image the start of a new table of contents range.", + "bitstream.edit.form.iiifToc.hint": "Adding text here makes this the start of a new table of contents range.", "bitstream.edit.form.iiifWidth.label": "IIIF canvas width", From 8a30748b41d80858f931defe96d2e9a9fbe73fd9 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 24 Jan 2022 15:28:05 -0800 Subject: [PATCH 16/22] Fixed spacing issue. --- .../edit-bitstream-page/edit-bitstream-page.component.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss index a0f0cc173d3..80adde4ecca 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.scss @@ -6,7 +6,7 @@ } } } -:host ::ng-deep ds-dynamic-form-control-container > div { - margin-bottom: 1rem; +:host ::ng-deep ds-dynamic-form-control-container > div > label { + margin-top: 1.75rem; } From d91d12ed0dd07bdab077f11412e1dbfe88dfdcd7 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 27 Jan 2022 14:46:00 -0800 Subject: [PATCH 17/22] Updated dynamic form. --- .../edit-bitstream-page.component.ts | 221 +++++++++--------- src/assets/i18n/en.json5 | 4 +- 2 files changed, 117 insertions(+), 108 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 9b160f486b4..0354e9af720 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -10,8 +10,9 @@ import { ActivatedRoute, Router } from '@angular/router'; import { filter, map, mergeMap, switchMap } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { + DynamicFormControlLayout, DynamicFormControlModel, - DynamicFormGroupModel, + DynamicFormGroupModel, DynamicFormGroupModelConfig, DynamicFormLayout, DynamicFormService, DynamicInputModel, @@ -42,8 +43,13 @@ import { getEntityEditRoute, getItemEditRoute } from '../../item-page/item-page- 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, + DsDynamicInputModelConfig +} 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 { Simulate } from 'react-dom/test-utils'; +import input = Simulate.input; @Component({ selector: 'ds-edit-bitstream-page', @@ -148,9 +154,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { * The Dynamic Switch Model for the file's name */ primaryBitstreamModel = new DynamicCustomSwitchModel({ - id: 'primaryBitstream', - name: 'primaryBitstream' - }); + id: 'primaryBitstream', + name: 'primaryBitstream' + } + ); /** * The Dynamic TextArea Model for the file's description @@ -185,31 +192,80 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifLabel', name: 'iiifLabel' + }, + { + grid: { + host: 'col col-lg-6 d-inline-block' + } + }); + iiifLabelContainer = new DynamicFormGroupModel({ + id: 'iiifLabelContainer', + group: [this.iiifLabelModel] + },{ + grid: { + host: 'form-row' + } }); iiifTocModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifToc', name: 'iiifToc', + },{ + grid: { + host: 'col col-lg-6 d-inline-block' + } + }); + iiifTocContainer = new DynamicFormGroupModel({ + id: 'iiifTocContainer', + group: [this.iiifTocModel] + },{ + grid: { + host: 'form-row' + } }); iiifWidthModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifWidth', name: 'iiifWidth', + },{ + grid: { + host: 'col col-lg-6 d-inline-block' + } + }); + iiifWidthContainer = new DynamicFormGroupModel({ + id: 'iiifWidthContainer', + group: [this.iiifWidthModel] + },{ + grid: { + host: 'form-row' + } }); iiifHeightModel = new DsDynamicInputModel({ hasSelectableMetadata: false, metadataFields: [], repeatable: false, submissionId: '', id: 'iiifHeight', name: 'iiifHeight' + },{ + grid: { + host: 'col col-lg-6 d-inline-block' + } + }); + iiifHeightContainer = new DynamicFormGroupModel({ + id: 'iiifHeightContainer', + group: [this.iiifHeightModel] + },{ + grid: { + host: 'form-row' + } }); /** * All input models in a simple array for easier iterations */ inputModels = [this.fileNameModel, this.primaryBitstreamModel, this.descriptionModel, this.selectedFormatModel, - this.newFormatModel, this.iiifLabelModel, this.iiifTocModel, this.iiifWidthModel, this.iiifHeightModel]; + this.newFormatModel]; /** * The dynamic form fields used for editing the information of a bitstream @@ -222,7 +278,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.fileNameModel, this.primaryBitstreamModel ] - }), + },{ + grid: { + host: 'form-row' + } + }), new DynamicFormGroupModel({ id: 'descriptionContainer', group: [ @@ -235,30 +295,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.selectedFormatModel, this.newFormatModel ] - }), - new DynamicFormGroupModel({ - id: 'iiifLabelContainer', - group: [ - this.iiifLabelModel - ] - }), - new DynamicFormGroupModel({ - id: 'iiifTocContainer', - group: [ - this.iiifTocModel - ] - }), - new DynamicFormGroupModel({ - id: 'iiifWidthContainer', - group: [ - this.iiifWidthModel - ] - }), - new DynamicFormGroupModel({ - id: 'iiifHeightContainer', - group: [ - this.iiifHeightModel - ] }) ]; @@ -267,11 +303,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ newFormatBaseLayout = 'col col-sm-6 d-inline-block'; - /** - * Base layout for iiif options - */ - iiifOptionsBaseLayout = 'col col-sm-6'; - /** * Layout used for structuring the form inputs */ @@ -306,26 +337,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { host: this.newFormatBaseLayout + ' invisible' } }, - iiifLabel: { - grid: { - host: 'd-none' - } - }, - iiifToc: { - grid: { - host: 'd-none' - } - }, - iiifWidth: { - grid: { - host: 'd-none' - } - }, - iiifHeight: { - grid: { - host: 'd-none' - } - }, fileNamePrimaryContainer: { grid: { host: 'row position-relative' @@ -340,27 +351,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { grid: { host: 'row' } - }, - iiifLabelContainer: { - grid: { - host: 'row' - } - }, - iiifTocContainer: { - grid: { - host: 'row' - } - }, - iiifWidthContainer: { - grid: { - host: 'row' - } - }, - iiifHeightContainer: { - grid: { - host: 'row' - } - }, + } }; /** @@ -387,6 +378,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ isIIIF = false; + /** * Array to track all subscriptions and unsubscribe them onDestroy * @type {Array} @@ -413,7 +405,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { * - Translate the form labels and hints */ ngOnInit(): void { - this.formGroup = this.formService.createFormGroup(this.formModel); this.itemId = this.route.snapshot.queryParams.itemId; this.entityType = this.route.snapshot.queryParams.entityType; @@ -437,14 +428,11 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { ).subscribe(([bitstream, allFormats]) => { this.bitstream = bitstream as Bitstream; this.formats = allFormats.page; + this.setForm(); this.setIiifStatus(this.bitstream); - this.updateFormatModel(); - this.updateForm(this.bitstream); }) ); - this.updateFieldTranslations(); - this.subs.push( this.translate.onLangChange .subscribe(() => { @@ -453,6 +441,16 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { ); } + /** + * Initializes the form. + */ + setForm() { + this.formGroup = this.formService.createFormGroup(this.formModel); + this.updateFormatModel(); + this.updateForm(this.bitstream); + this.updateFieldTranslations(); + } + /** * Update the current form values with bitstream properties * @param bitstream @@ -470,6 +468,22 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { newFormat: hasValue(bitstream.firstMetadata('dc.format')) ? bitstream.firstMetadata('dc.format').value : undefined } }); + if (this.isIIIF) { + this.formGroup.patchValue({ + iiifLabelContainer: { + iiifLabel: bitstream.firstMetadataValue(this.IIIF_LABEL_METADATA) + }, + iiifTocContainer: { + iiifToc: bitstream.firstMetadataValue(this.IIIF_TOC_METADATA) + }, + iiifWidthContainer: { + iiifWidth: bitstream.firstMetadataValue(this.IMAGE_WIDTH_METADATA) + }, + iiifHeightContainer: { + iiifHeight: bitstream.firstMetadataValue(this.IMAGE_HEIGHT_METADATA) + } + }); + } this.bitstream.format.pipe( getAllSucceededRemoteDataPayload() ).subscribe((format: BitstreamFormat) => { @@ -604,13 +618,17 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { const primary = rawForm.fileNamePrimaryContainer.primaryBitstream; Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName); Metadata.setFirstValue(newMetadata, 'dc.description', rawForm.descriptionContainer.description); + console.log(this.isIIIF); if (this.isIIIF) { + console.log(rawForm); // It's helpful to remove these metadata elements entirely when the form value is empty. // This avoids potential issues on the REST side and makes it possible to do things like // remove an existing "table of contents" entry. if (isEmpty(rawForm.iiifLabelContainer.iiifLabel)) { + delete newMetadata[this.IIIF_LABEL_METADATA]; } else { + console.log(rawForm.iiifLabelContainer.iiifLabel); Metadata.setFirstValue(newMetadata, this.IIIF_LABEL_METADATA, rawForm.iiifLabelContainer.iiifLabel); } if (isEmpty(rawForm.iiifTocContainer.iiifToc)) { @@ -690,30 +708,21 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { // If iiifCheck$ returns true, enable the IIIF form elements. const iiifSub = iiifCheck$.subscribe((iiif: boolean) => { - if (iiif) { - this.isIIIF = true; - this.formLayout.iiifLabel.grid.host = this.iiifOptionsBaseLayout; - this.formLayout.iiifToc.grid.host = this.iiifOptionsBaseLayout; - this.formLayout.iiifWidth.grid.host = this.iiifOptionsBaseLayout; - this.formLayout.iiifHeight.grid.host = this.iiifOptionsBaseLayout; - this.formGroup.patchValue({ - iiifLabelContainer: { - iiifLabel: bitstream.firstMetadataValue(this.IIIF_LABEL_METADATA) - }, - iiifTocContainer: { - iiifToc: bitstream.firstMetadataValue(this.IIIF_TOC_METADATA) - }, - iiifWidthContainer: { - iiifWidth: bitstream.firstMetadataValue(this.IMAGE_WIDTH_METADATA) - }, - iiifHeightContainer: { - iiifHeight: bitstream.firstMetadataValue(this.IMAGE_HEIGHT_METADATA) - } - }); - // Assures that the form always includes the iiif additions. - this.changeDetectorRef.detectChanges(); - } - }); + if (iiif) { + this.isIIIF = true; + this.inputModels.push(this.iiifLabelModel); + this.formModel.push(this.iiifLabelContainer); + this.inputModels.push(this.iiifTocModel); + this.formModel.push(this.iiifTocContainer); + this.inputModels.push(this.iiifWidthModel); + this.formModel.push(this.iiifWidthContainer); + this.inputModels.push(this.iiifHeightModel); + this.formModel.push(this.iiifHeightContainer); + } + // re-initialize the form and detect the change. + this.setForm(); + this.changeDetectorRef.detectChanges(); + }); this.subs.push(iiifSub); diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index a93d3b3ad20..3460766b823 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -590,11 +590,11 @@ "bitstream.edit.form.iiifToc.hint": "Adding text here makes this the start of a new table of contents range.", - "bitstream.edit.form.iiifWidth.label": "IIIF canvas width", + "bitstream.edit.form.iiifWidth.label": "IIIF Canvas Width", "bitstream.edit.form.iiifWidth.hint": "The canvas width should usually match the image width.", - "bitstream.edit.form.iiifHeight.label": "IIIF canvas height", + "bitstream.edit.form.iiifHeight.label": "IIIF Canvas Height", "bitstream.edit.form.iiifHeight.hint": "The canvas height should usually match the image height.", From 47581db60aae2e7ec3c010f4b9f863e781c3894e Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 27 Jan 2022 15:08:20 -0800 Subject: [PATCH 18/22] Updated test. --- .../edit-bitstream-page.component.spec.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts index 1be53d686ed..44e48182fd9 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.spec.ts @@ -381,18 +381,6 @@ describe('EditBitstreamPageComponent', () => { it('should set isIIIF to true', () => { expect(comp.isIIIF).toBeTrue(); }); - it('should put the \"IIIF Label\" input to be shown', () => { - expect(comp.formLayout.iiifLabel.grid.host).toContain('col'); - }); - it('should put the \"IIIF Toc\" input to be shown', () => { - expect(comp.formLayout.iiifToc.grid.host).toContain('col'); - }); - it('should put the \"IIIF width\" input to be shown', () => { - expect(comp.formLayout.iiifWidth.grid.host).toContain('col'); - }); - it('should put the \"IIIF Height\" input to be shown', () => { - expect(comp.formLayout.iiifHeight.grid.host).toContain('col'); - }); it('should fill in the iiif label', () => { expect(rawForm.iiifLabelContainer.iiifLabel).toEqual('chapter one'); }); @@ -512,7 +500,7 @@ describe('EditBitstreamPageComponent', () => { expect(comp.isIIIF).toBeFalse(); }); it('should put the \"IIIF Label\" input not to be shown', () => { - expect(comp.formLayout.iiifLabel.grid.host).toContain('d-none'); + expect(rawForm.iiifLabelContainer).toBeFalsy(); }); }); }); From 7c5d31fbbdf1629ee127a15e58f8ed17a5690cc4 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 27 Jan 2022 15:21:48 -0800 Subject: [PATCH 19/22] Removed the unused imports. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 0354e9af720..1b703f6822e 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -10,9 +10,8 @@ import { ActivatedRoute, Router } from '@angular/router'; import { filter, map, mergeMap, switchMap } from 'rxjs/operators'; import { combineLatest as observableCombineLatest, Observable, of as observableOf, Subscription } from 'rxjs'; import { - DynamicFormControlLayout, DynamicFormControlModel, - DynamicFormGroupModel, DynamicFormGroupModelConfig, + DynamicFormGroupModel, DynamicFormLayout, DynamicFormService, DynamicInputModel, @@ -44,12 +43,9 @@ import { Bundle } from '../../core/shared/bundle.model'; import { DSONameService } from '../../core/breadcrumbs/dso-name.service'; import { Item } from '../../core/shared/item.model'; import { - DsDynamicInputModel, - DsDynamicInputModelConfig + 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 { Simulate } from 'react-dom/test-utils'; -import input = Simulate.input; @Component({ selector: 'ds-edit-bitstream-page', From 8bfd6ca03182ea6a977e44d154583801290d7955 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Thu, 27 Jan 2022 18:56:34 -0800 Subject: [PATCH 20/22] Form re-initialization limited to iiif enabled item. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 1b703f6822e..8b93c585421 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -714,10 +714,10 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.formModel.push(this.iiifWidthContainer); this.inputModels.push(this.iiifHeightModel); this.formModel.push(this.iiifHeightContainer); + // re-initialize the form and detect the change. + this.setForm(); + this.changeDetectorRef.detectChanges(); } - // re-initialize the form and detect the change. - this.setForm(); - this.changeDetectorRef.detectChanges(); }); this.subs.push(iiifSub); From 94b2f5322093ee5b289288ee3b4d88d37ec04d38 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 31 Jan 2022 07:40:52 -0800 Subject: [PATCH 21/22] Removed unnecessary logging. --- .../edit-bitstream-page/edit-bitstream-page.component.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts index 8b93c585421..17c648e1f22 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.ts @@ -614,9 +614,7 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { const primary = rawForm.fileNamePrimaryContainer.primaryBitstream; Metadata.setFirstValue(newMetadata, 'dc.title', rawForm.fileNamePrimaryContainer.fileName); Metadata.setFirstValue(newMetadata, 'dc.description', rawForm.descriptionContainer.description); - console.log(this.isIIIF); if (this.isIIIF) { - console.log(rawForm); // It's helpful to remove these metadata elements entirely when the form value is empty. // This avoids potential issues on the REST side and makes it possible to do things like // remove an existing "table of contents" entry. @@ -624,7 +622,6 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { delete newMetadata[this.IIIF_LABEL_METADATA]; } else { - console.log(rawForm.iiifLabelContainer.iiifLabel); Metadata.setFirstValue(newMetadata, this.IIIF_LABEL_METADATA, rawForm.iiifLabelContainer.iiifLabel); } if (isEmpty(rawForm.iiifTocContainer.iiifToc)) { From ac716c4b999d57b7d7a9b0652ae523e2e27aed3a Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 31 Jan 2022 10:38:59 -0800 Subject: [PATCH 22/22] Single form initialization. --- .../edit-bitstream-page.component.html | 2 +- .../edit-bitstream-page.component.ts | 60 ++++++++++--------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.html b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.html index cbb587cca48..4d3b948a583 100644 --- a/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.html +++ b/src/app/bitstream-page/edit-bitstream-page/edit-bitstream-page.component.html @@ -12,7 +12,7 @@

{{bitstreamRD?.payload?.name}} ({{bitstreamRD?.payl - { this.bitstream = bitstream as Bitstream; this.formats = allFormats.page; - this.setForm(); this.setIiifStatus(this.bitstream); }) ); @@ -677,31 +682,33 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { */ setIiifStatus(bitstream: Bitstream) { - const regexExcludeBundles = /OTHERCONTENT|THUMBNAIL/; + const regexExcludeBundles = /OTHERCONTENT|THUMBNAIL|LICENSE/; const regexIIIFItem = /true|yes/i; - const iiifCheck$ = this.bitstream.format.pipe( + const isImage$ = this.bitstream.format.pipe( getFirstSucceededRemoteData(), - filter((format: RemoteData) => format.payload.mimetype.includes('image/')), - mergeMap(() => - this.bitstream.bundle.pipe( - getFirstSucceededRemoteData(), - filter((bundle: RemoteData) => - this.dsoNameService.getName(bundle.payload).match(regexExcludeBundles) == null), - mergeMap((bundle: RemoteData) => bundle.payload.item.pipe( - getFirstSucceededRemoteData(), - map((remoteData: RemoteData) => - (remoteData.payload.firstMetadataValue('dspace.iiif.enabled') && - remoteData.payload.firstMetadataValue('dspace.iiif.enabled').match(regexIIIFItem) !== null) - ) - )) - ) - ) - ); + map((format: RemoteData) => format.payload.mimetype.includes('image/'))); - // If iiifCheck$ returns true, enable the IIIF form elements. - const iiifSub = iiifCheck$.subscribe((iiif: boolean) => { - if (iiif) { + const isIIIFBundle$ = this.bitstream.bundle.pipe( + getFirstSucceededRemoteData(), + map((bundle: RemoteData) => + this.dsoNameService.getName(bundle.payload).match(regexExcludeBundles) == null)); + + const isEnabled$ = this.bitstream.bundle.pipe( + getFirstSucceededRemoteData(), + map((bundle: RemoteData) => bundle.payload.item.pipe( + getFirstSucceededRemoteData(), + map((item: RemoteData) => + (item.payload.firstMetadataValue('dspace.iiif.enabled') && + item.payload.firstMetadataValue('dspace.iiif.enabled').match(regexIIIFItem) !== null) + )))); + + const iiifSub = combineLatest( + isImage$, + isIIIFBundle$, + isEnabled$ + ).subscribe(([isImage, isIIIFBundle, isEnabled]) => { + if (isImage && isIIIFBundle && isEnabled) { this.isIIIF = true; this.inputModels.push(this.iiifLabelModel); this.formModel.push(this.iiifLabelContainer); @@ -711,10 +718,9 @@ export class EditBitstreamPageComponent implements OnInit, OnDestroy { this.formModel.push(this.iiifWidthContainer); this.inputModels.push(this.iiifHeightModel); this.formModel.push(this.iiifHeightContainer); - // re-initialize the form and detect the change. - this.setForm(); - this.changeDetectorRef.detectChanges(); } + this.setForm(); + this.changeDetectorRef.detectChanges(); }); this.subs.push(iiifSub);