From f80abb9f43030279e77cbe9c538b2114c6adfafe Mon Sep 17 00:00:00 2001 From: Kristof De Langhe Date: Mon, 19 Mar 2018 16:38:02 +0100 Subject: [PATCH] 50452: Bitstream format registry --- resources/i18n/en.json | 20 +- .../admin-registries-routing.module.ts | 4 +- .../admin-registries.module.ts | 4 +- .../bitstream-formats.component.html | 30 +++ .../bitstream-formats.component.spec.ts | 91 +++++++++ .../bitstream-formats.component.ts | 19 ++ .../metadata-registry.component.spec.ts | 11 +- .../metadata-schema.component.spec.ts | 11 +- .../registry/mock-bitstream-format.model.ts | 8 + src/app/core/registry/registry.service.ts | 176 +++++++++++++++++- 10 files changed, 360 insertions(+), 14 deletions(-) create mode 100644 src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html create mode 100644 src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts create mode 100644 src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts create mode 100644 src/app/core/registry/mock-bitstream-format.model.ts diff --git a/resources/i18n/en.json b/resources/i18n/en.json index 51079f94c0..5e97d81d8e 100644 --- a/resources/i18n/en.json +++ b/resources/i18n/en.json @@ -138,7 +138,7 @@ } }, "schema": { - "title": "DSpace Angular :: Metadata Schema", + "title": "DSpace Angular :: Metadata Schema Registry", "head": "Metadata Schema", "description": "This is the metadata schema for \"{{namespace}}\".", "fields": { @@ -148,6 +148,24 @@ "scopenote": "Scope Note" } } + }, + "bitstream-formats": { + "title": "DSpace Angular :: Bitstream Format Registry", + "head": "Bitstream Format Registry", + "description": "This list of bitstream formats provides information about known formats and their support level.", + "formats": { + "table": { + "name": "Name", + "mimetype": "MIME Type", + "supportLevel": { + "head": "Support Level", + "0": "Unknown", + "1": "Known", + "2": "Support" + }, + "internal": "internal" + } + } } } }, diff --git a/src/app/+admin/admin-registries/admin-registries-routing.module.ts b/src/app/+admin/admin-registries/admin-registries-routing.module.ts index c1b1fa1eba..8e3c322bc8 100644 --- a/src/app/+admin/admin-registries/admin-registries-routing.module.ts +++ b/src/app/+admin/admin-registries/admin-registries-routing.module.ts @@ -2,12 +2,14 @@ import { MetadataRegistryComponent } from './metadata-registry/metadata-registry import { RouterModule } from '@angular/router'; import { NgModule } from '@angular/core'; import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component'; +import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component'; @NgModule({ imports: [ RouterModule.forChild([ { path: 'metadata', component: MetadataRegistryComponent, data: { title: 'admin.registries.metadata.title' } }, - { path: 'metadata/:schemaName', component: MetadataSchemaComponent, data: { title: 'admin.registries.schema.title' } } + { path: 'metadata/:schemaName', component: MetadataSchemaComponent, data: { title: 'admin.registries.schema.title' } }, + { path: 'bitstream-formats', component: BitstreamFormatsComponent, data: { title: 'admin.registries.bitstream-formats.title' } }, ]) ] }) diff --git a/src/app/+admin/admin-registries/admin-registries.module.ts b/src/app/+admin/admin-registries/admin-registries.module.ts index 6cbcef407b..fb9dcdaa63 100644 --- a/src/app/+admin/admin-registries/admin-registries.module.ts +++ b/src/app/+admin/admin-registries/admin-registries.module.ts @@ -5,6 +5,7 @@ import { CommonModule } from '@angular/common'; import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component'; import { RouterModule } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; +import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component'; @NgModule({ imports: [ @@ -15,7 +16,8 @@ import { TranslateModule } from '@ngx-translate/core'; ], declarations: [ MetadataRegistryComponent, - MetadataSchemaComponent + MetadataSchemaComponent, + BitstreamFormatsComponent ] }) export class AdminRegistriesModule { diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html new file mode 100644 index 0000000000..87b3ba85eb --- /dev/null +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.html @@ -0,0 +1,30 @@ +
+
+
+ + + +

{{'admin.registries.bitstream-formats.description' | translate}}

+ +
+ + + + + + + + + + + + + + + +
{{'admin.registries.bitstream-formats.formats.table.name' | translate}}{{'admin.registries.bitstream-formats.formats.table.mimetype' | translate}}{{'admin.registries.bitstream-formats.formats.table.supportLevel.head' | translate}}
{{bitstreamFormat.shortDescription}}{{bitstreamFormat.mimetype}} ({{'admin.registries.bitstream-formats.formats.table.internal' | translate}}){{'admin.registries.bitstream-formats.formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}
+
+ +
+
+
diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts new file mode 100644 index 0000000000..f83f96127f --- /dev/null +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.spec.ts @@ -0,0 +1,91 @@ +import { BitstreamFormatsComponent } from './bitstream-formats.component'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { RegistryService } from '../../../core/registry/registry.service'; +import { Observable } from 'rxjs/Observable'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { CommonModule } from '@angular/common'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { By } from '@angular/platform-browser'; + +describe('BitstreamFormatsComponent', () => { + let comp: BitstreamFormatsComponent; + let fixture: ComponentFixture; + let registryService: RegistryService; + const mockFormatsList = [ + { + shortDescription: 'Unknown', + description: 'Unknown data format', + mimetype: 'application/octet-stream', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'License', + description: 'Item-specific license agreed upon to submission', + mimetype: 'text/plain; charset=utf-8', + supportLevel: 1, + internal: true, + extensions: null + }, + { + shortDescription: 'CC License', + description: 'Item-specific Creative Commons license agreed upon to submission', + mimetype: 'text/html; charset=utf-8', + supportLevel: 2, + internal: true, + extensions: null + }, + { + shortDescription: 'Adobe PDF', + description: 'Adobe Portable Document Format', + mimetype: 'application/pdf', + supportLevel: 0, + internal: false, + extensions: null + } + ]; + const mockFormats = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList))); + const registryServiceStub = { + getBitstreamFormats: () => mockFormats + }; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot()], + declarations: [BitstreamFormatsComponent], + providers: [ + { provide: RegistryService, useValue: registryServiceStub } + ] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(BitstreamFormatsComponent); + comp = fixture.componentInstance; + fixture.detectChanges(); + registryService = (comp as any).service; + }); + + it('should contain four formats', () => { + const tbody: HTMLElement = fixture.debugElement.query(By.css('#formats>tbody')).nativeElement; + expect(tbody.children.length).toBe(4); + }); + + it('should contain the correct formats', () => { + const unknownName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(1)')).nativeElement; + expect(unknownName.textContent).toBe('Unknown'); + + const licenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(2) td:nth-child(1)')).nativeElement; + expect(licenseName.textContent).toBe('License'); + + const ccLicenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(3) td:nth-child(1)')).nativeElement; + expect(ccLicenseName.textContent).toBe('CC License'); + + const adobeName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(4) td:nth-child(1)')).nativeElement; + expect(adobeName.textContent).toBe('Adobe PDF'); + }); + +}); diff --git a/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts new file mode 100644 index 0000000000..d64b48d4c5 --- /dev/null +++ b/src/app/+admin/admin-registries/bitstream-formats/bitstream-formats.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { RegistryService } from '../../../core/registry/registry.service'; +import { Observable } from 'rxjs/Observable'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list'; +import { BitstreamFormat } from '../../../core/registry/mock-bitstream-format.model'; + +@Component({ + selector: 'ds-bitstream-formats', + templateUrl: './bitstream-formats.component.html' +}) +export class BitstreamFormatsComponent { + + bitstreamFormats: Observable>>; + + constructor(registryService: RegistryService) { + this.bitstreamFormats = registryService.getBitstreamFormats(); + } +} diff --git a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts index 981c253c3a..fff4b7ee48 100644 --- a/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-registry/metadata-registry.component.spec.ts @@ -8,11 +8,12 @@ import { TranslateModule } from '@ngx-translate/core'; import { By } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; +import { RegistryService } from '../../../core/registry/registry.service'; describe('MetadataRegistryComponent', () => { let comp: MetadataRegistryComponent; let fixture: ComponentFixture; - let metadataRegistryService: MetadataRegistryService; + let registryService: RegistryService; const mockSchemasList = [ { self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', @@ -26,7 +27,7 @@ describe('MetadataRegistryComponent', () => { } ]; const mockSchemas = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); - const metadataRegistryServiceStub = { + const registryServiceStub = { getMetadataSchemas: () => mockSchemas }; @@ -35,16 +36,16 @@ describe('MetadataRegistryComponent', () => { imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot()], declarations: [MetadataRegistryComponent], providers: [ - { provide: MetadataRegistryService, useValue: metadataRegistryServiceStub } + { provide: RegistryService, useValue: registryServiceStub } ] }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(MetadataRegistryComponent); - comp = fixture.componentInstance; // SearchPageComponent test instance + comp = fixture.componentInstance; fixture.detectChanges(); - metadataRegistryService = (comp as any).service; + registryService = (comp as any).service; }); it('should contain two schemas', () => { diff --git a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts index 507684276e..2099bac7da 100644 --- a/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts +++ b/src/app/+admin/admin-registries/metadata-schema/metadata-schema.component.spec.ts @@ -10,11 +10,12 @@ import { CommonModule } from '@angular/common'; import { ActivatedRoute } from '@angular/router'; import { By } from '@angular/platform-browser'; import { MockTranslateLoader } from '../../../shared/testing/mock-translate-loader'; +import { RegistryService } from '../../../core/registry/registry.service'; describe('MetadataSchemaComponent', () => { let comp: MetadataSchemaComponent; let fixture: ComponentFixture; - let metadataRegistryService: MetadataRegistryService; + let registryService: RegistryService; const mockSchemasList = [ { self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/metadataschemas/1', @@ -58,7 +59,7 @@ describe('MetadataSchemaComponent', () => { } ]; const mockSchemas = Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockSchemasList))); - const metadataRegistryServiceStub = { + const registryServiceStub = { getMetadataSchemas: () => mockSchemas, getMetadataFieldsBySchema: (schema: MetadataSchema) => Observable.of(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFieldsList.filter((value) => value.schema === schema)))), getMetadataSchemaByName: (schemaName: string) => Observable.of(new RemoteData(false, false, true, undefined, mockSchemasList.filter((value) => value.prefix === schemaName)[0])) @@ -75,7 +76,7 @@ describe('MetadataSchemaComponent', () => { imports: [CommonModule, TranslateModule.forRoot()], declarations: [MetadataSchemaComponent], providers: [ - { provide: MetadataRegistryService, useValue: metadataRegistryServiceStub }, + { provide: RegistryService, useValue: registryServiceStub }, { provide: ActivatedRoute, useValue: activatedRouteStub } ] }).compileComponents(); @@ -83,9 +84,9 @@ describe('MetadataSchemaComponent', () => { beforeEach(() => { fixture = TestBed.createComponent(MetadataSchemaComponent); - comp = fixture.componentInstance; // SearchPageComponent test instance + comp = fixture.componentInstance; fixture.detectChanges(); - metadataRegistryService = (comp as any).service; + registryService = (comp as any).service; }); it('should contain the schema prefix in the header', () => { diff --git a/src/app/core/registry/mock-bitstream-format.model.ts b/src/app/core/registry/mock-bitstream-format.model.ts new file mode 100644 index 0000000000..f5811e367c --- /dev/null +++ b/src/app/core/registry/mock-bitstream-format.model.ts @@ -0,0 +1,8 @@ +export class BitstreamFormat { + shortDescription: string; + description: string; + mimetype: string; + supportLevel: number; + internal: boolean; + extensions: string; +} diff --git a/src/app/core/registry/registry.service.ts b/src/app/core/registry/registry.service.ts index 362478a054..7e79f45af5 100644 --- a/src/app/core/registry/registry.service.ts +++ b/src/app/core/registry/registry.service.ts @@ -5,12 +5,14 @@ import { PaginatedList } from '../data/paginated-list'; import { PageInfo } from '../shared/page-info.model'; import { MetadataSchema } from '../metadata/metadataschema.model'; import { MetadataField } from '../metadata/metadatafield.model'; +import { BitstreamFormat } from './mock-bitstream-format.model'; Injectable() export class RegistryService { metadataSchemas: MetadataSchema[]; metadataFields: MetadataField[]; + bitstreamFormats: BitstreamFormat[]; public getMetadataSchemas(): Observable>> { const pageInfo = new PageInfo(); @@ -38,6 +40,16 @@ export class RegistryService { return Observable.of(remoteData); } + public getBitstreamFormats(): Observable>> { + const pageInfo = new PageInfo(); + pageInfo.elementsPerPage = 10; + pageInfo.currentPage = 1; + + const payload = new PaginatedList(pageInfo, this.bitstreamFormats); + const remoteData = new RemoteData(false, false, true, undefined, payload); + return Observable.of(remoteData); + } + constructor() { this.metadataSchemas = [ { @@ -1018,7 +1030,169 @@ export class RegistryService { scopenote: null, schema: this.metadataSchemas[1] } - ] + ]; + this.bitstreamFormats = [ + { + shortDescription: 'Unknown', + description: 'Unknown data format', + mimetype: 'application/octet-stream', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'License', + description: 'Item-specific license agreed upon to submission', + mimetype: 'text/plain; charset=utf-8', + supportLevel: 1, + internal: true, + extensions: null + }, + { + shortDescription: 'CC License', + description: 'Item-specific Creative Commons license agreed upon to submission', + mimetype: 'text/html; charset=utf-8', + supportLevel: 2, + internal: true, + extensions: null + }, + { + shortDescription: 'Adobe PDF', + description: 'Adobe Portable Document Format', + mimetype: 'application/pdf', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'XML', + description: 'Extensible Markup Language', + mimetype: 'text/xml', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Text', + description: 'Plain Text', + mimetype: 'text/plain', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'HTML', + description: 'Hypertext Markup Language', + mimetype: 'text/html', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'CSS', + description: 'Cascading Style Sheets', + mimetype: 'text/css', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Word', + description: 'Microsoft Word', + mimetype: 'application/msword', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Word XML', + description: 'Microsoft Word XML', + mimetype: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Powerpoint', + description: 'Microsoft Powerpoint', + mimetype: 'application/vnd.ms-powerpoint', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Powerpoint XML', + description: 'Microsoft Powerpoint XML', + mimetype: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Excel', + description: 'Microsoft Excel', + mimetype: 'application/vnd.ms-excel', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'Microsoft Excel XML', + description: 'Microsoft Excel XML', + mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'MARC', + description: 'Machine-Readable Cataloging records', + mimetype: 'application/marc', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'JPEG', + description: 'Joint Photographic Experts Group/JPEG File Interchange Format (JFIF)', + mimetype: 'image/jpeg', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'GIF', + description: 'Graphics Interchange Format', + mimetype: 'image/gif', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'image/png', + description: 'Portable Network Graphics', + mimetype: 'image/png', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'TIFF', + description: 'Tag Image File Format', + mimetype: 'image/tiff', + supportLevel: 0, + internal: false, + extensions: null + }, + { + shortDescription: 'AIFF', + description: 'Audio Interchange File Format', + mimetype: 'audio/x-aiff', + supportLevel: 0, + internal: false, + extensions: null + } + ]; } }