From 2368df95136889008287bfdf141921c63cdc62b1 Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Sat, 22 Dec 2018 23:03:45 -0500 Subject: [PATCH 1/6] DS-4107 Retrieve and model metadata as a map --- .../modify-item-overview.component.html | 14 ++- .../modify-item-overview.component.ts | 4 +- .../metadata-uri-values.component.html | 4 +- .../metadata-uri-values.component.ts | 3 +- .../metadata-values.component.html | 4 +- .../metadata-values.component.ts | 4 +- .../full-file-section.component.html | 2 +- .../full/full-item-page.component.html | 12 +- .../full/full-item-page.component.ts | 4 +- .../item-page-specific-field.component.html | 2 +- .../item-page-title-field.component.html | 2 +- .../uri/item-page-uri-field.component.html | 2 +- .../normalized-search-result.model.ts | 4 +- src/app/+search-page/search-result.model.ts | 4 +- src/app/core/browse/browse.service.ts | 12 +- .../models/normalized-dspace-object.model.ts | 9 +- .../data/search-response-parsing.service.ts | 16 +-- .../dspace-rest-v2/dspace-rest-v2.service.ts | 6 +- src/app/core/metadata/metadata.service.ts | 54 ++------ src/app/core/shared/collection.model.ts | 10 +- src/app/core/shared/community.model.ts | 8 +- src/app/core/shared/dspace-object.model.ts | 65 ++++------ src/app/core/shared/metadata.interfaces.ts | 30 +++++ src/app/core/shared/metadata.model.ts | 119 ++++++++++++++++++ src/app/core/shared/metadatum.model.ts | 23 ---- .../comcol-form/comcol-form.component.ts | 25 ++-- .../abstract-listable-element.component.ts | 5 - .../item-grid-element.component.html | 10 +- ...-search-result-grid-element.component.html | 12 +- .../search-result-grid-element.component.ts | 40 ++---- .../item-list-element.component.html | 14 +-- ...-search-result-list-element.component.html | 4 +- ...-search-result-list-element.component.html | 4 +- ...-search-result-list-element.component.html | 20 +-- .../search-result-list-element.component.ts | 40 ++---- 35 files changed, 310 insertions(+), 281 deletions(-) create mode 100644 src/app/core/shared/metadata.interfaces.ts create mode 100644 src/app/core/shared/metadata.model.ts delete mode 100644 src/app/core/shared/metadatum.model.ts diff --git a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html index d59d29ddbf..861c20ada7 100644 --- a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html +++ b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html @@ -7,10 +7,12 @@ - - {{metadatum.key}} - {{metadatum.value}} - {{metadatum.language}} - + + + {{entry.key}} + {{value.value}} + {{value.language}} + + - \ No newline at end of file + diff --git a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.ts b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.ts index d32a98d5e0..282f8687e1 100644 --- a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.ts +++ b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.ts @@ -1,6 +1,6 @@ import {Component, Input, OnInit} from '@angular/core'; import {Item} from '../../../core/shared/item.model'; -import {Metadatum} from '../../../core/shared/metadatum.model'; +import {MetadataMap} from '../../../core/shared/metadata.interfaces'; @Component({ selector: 'ds-modify-item-overview', @@ -12,7 +12,7 @@ import {Metadatum} from '../../../core/shared/metadatum.model'; export class ModifyItemOverviewComponent implements OnInit { @Input() item: Item; - metadata: Metadatum[]; + metadata: MetadataMap; ngOnInit(): void { this.metadata = this.item.metadata; diff --git a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html index cc618bcd50..344a32841b 100644 --- a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html +++ b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html @@ -1,5 +1,5 @@ - - {{ linktext || metadatum.value }} + + {{ linktext || value.value }} diff --git a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts index 212dcddee8..b5870f16b8 100644 --- a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts +++ b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts @@ -1,6 +1,7 @@ import { Component, Input } from '@angular/core'; import { MetadataValuesComponent } from '../metadata-values/metadata-values.component'; +import { MetadataValue } from '../../../core/shared/metadata.interfaces'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component as a link. @@ -18,7 +19,7 @@ export class MetadataUriValuesComponent extends MetadataValuesComponent { @Input() linktext: any; - @Input() values: any; + @Input() values: MetadataValue[]; @Input() separator: string; diff --git a/src/app/+item-page/field-components/metadata-values/metadata-values.component.html b/src/app/+item-page/field-components/metadata-values/metadata-values.component.html index f16655c63c..fbc1e11a07 100644 --- a/src/app/+item-page/field-components/metadata-values/metadata-values.component.html +++ b/src/app/+item-page/field-components/metadata-values/metadata-values.component.html @@ -1,5 +1,5 @@ - - {{metadatum.value}} + + {{value.value}} diff --git a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts index 1c94b56d57..2be7291dcd 100644 --- a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from '@angular/core'; -import { Metadatum } from '../../../core/shared/metadatum.model'; +import { MetadataValue } from '../../../core/shared/metadata.interfaces'; /** * This component renders the configured 'values' into the ds-metadata-field-wrapper component. @@ -12,7 +12,7 @@ import { Metadatum } from '../../../core/shared/metadatum.model'; }) export class MetadataValuesComponent { - @Input() values: Metadatum[]; + @Input() values: MetadataValue[]; @Input() separator: string; diff --git a/src/app/+item-page/full/field-components/file-section/full-file-section.component.html b/src/app/+item-page/full/field-components/file-section/full-file-section.component.html index d5a7febeb9..a68993cd16 100644 --- a/src/app/+item-page/full/field-components/file-section/full-file-section.component.html +++ b/src/app/+item-page/full/field-components/file-section/full-file-section.component.html @@ -17,7 +17,7 @@
{{"item.page.filesection.description" | translate}}
-
{{file.findMetadata("dc.description")}}
+
{{file.firstMetadataValue("dc.description")}}
diff --git a/src/app/+item-page/full/full-item-page.component.html b/src/app/+item-page/full/full-item-page.component.html index 1d0c4ab812..7080ba2e96 100644 --- a/src/app/+item-page/full/full-item-page.component.html +++ b/src/app/+item-page/full/full-item-page.component.html @@ -9,11 +9,13 @@
- - - - - + + + + + + +
{{metadatum.key}}{{metadatum.value}}{{metadatum.language}}
{{entry.key}}{{value.value}}{{value.language}}
diff --git a/src/app/+item-page/full/full-item-page.component.ts b/src/app/+item-page/full/full-item-page.component.ts index d09ac268ec..fcb724b564 100644 --- a/src/app/+item-page/full/full-item-page.component.ts +++ b/src/app/+item-page/full/full-item-page.component.ts @@ -6,7 +6,7 @@ import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { ItemPageComponent } from '../simple/item-page.component'; -import { Metadatum } from '../../core/shared/metadatum.model'; +import { MetadataMap } from '../../core/shared/metadata.interfaces'; import { ItemDataService } from '../../core/data/item-data.service'; import { RemoteData } from '../../core/data/remote-data'; @@ -34,7 +34,7 @@ export class FullItemPageComponent extends ItemPageComponent implements OnInit { itemRD$: Observable>; - metadata$: Observable; + metadata$: Observable; constructor(route: ActivatedRoute, items: ItemDataService, metadataService: MetadataService) { super(route, items, metadataService); diff --git a/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html b/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html index 4a27848ec6..c0d948fc76 100644 --- a/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html @@ -1,3 +1,3 @@
- +
diff --git a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html index 4c53e2e3e2..40f54ec636 100644 --- a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html @@ -1,3 +1,3 @@

- +

diff --git a/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html b/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html index fde79d6a04..771fef53fc 100644 --- a/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html @@ -1,3 +1,3 @@
- +
diff --git a/src/app/+search-page/normalized-search-result.model.ts b/src/app/+search-page/normalized-search-result.model.ts index 0683c74aed..3c1a46872c 100644 --- a/src/app/+search-page/normalized-search-result.model.ts +++ b/src/app/+search-page/normalized-search-result.model.ts @@ -1,5 +1,5 @@ import { autoserialize } from 'cerialize'; -import { Metadatum } from '../core/shared/metadatum.model'; +import { MetadataMap } from '../core/shared/metadata.interfaces'; import { ListableObject } from '../shared/object-collection/shared/listable-object.model'; /** @@ -16,6 +16,6 @@ export class NormalizedSearchResult implements ListableObject { * The metadata that was used to find this item, hithighlighted */ @autoserialize - hitHighlights: Metadatum[]; + hitHighlights: MetadataMap; } diff --git a/src/app/+search-page/search-result.model.ts b/src/app/+search-page/search-result.model.ts index 00b1c62a99..b2e5eafdec 100644 --- a/src/app/+search-page/search-result.model.ts +++ b/src/app/+search-page/search-result.model.ts @@ -1,5 +1,5 @@ import { DSpaceObject } from '../core/shared/dspace-object.model'; -import { Metadatum } from '../core/shared/metadatum.model'; +import { MetadataMap } from '../core/shared/metadata.interfaces'; import { ListableObject } from '../shared/object-collection/shared/listable-object.model'; /** @@ -14,6 +14,6 @@ export class SearchResult implements ListableObject { /** * The metadata that was used to find this item, hithighlighted */ - hitHighlights: Metadatum[]; + hitHighlights: MetadataMap; } diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index b807a77e99..41675632dd 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -38,8 +38,8 @@ import { DSpaceObject } from '../shared/dspace-object.model'; export class BrowseService { protected linkPath = 'browses'; - private static toSearchKeyArray(metadatumKey: string): string[] { - const keyParts = metadatumKey.split('.'); + private static toSearchKeyArray(metadataKey: string): string[] { + const keyParts = metadataKey.split('.'); const searchFor = []; searchFor.push('*'); for (let i = 0; i < keyParts.length - 1; i++) { @@ -47,7 +47,7 @@ export class BrowseService { const nextPart = [...prevParts, '*'].join('.'); searchFor.push(nextPart); } - searchFor.push(metadatumKey); + searchFor.push(metadataKey); return searchFor; } @@ -179,8 +179,8 @@ export class BrowseService { return this.rdb.toRemoteDataObservable(requestEntry$, payload$); } - getBrowseURLFor(metadatumKey: string, linkPath: string): Observable { - const searchKeyArray = BrowseService.toSearchKeyArray(metadatumKey); + getBrowseURLFor(metadataKey: string, linkPath: string): Observable { + const searchKeyArray = BrowseService.toSearchKeyArray(metadataKey); return this.getBrowseDefinitions().pipe( getRemoteDataPayload(), map((browseDefinitions: BrowseDefinition[]) => browseDefinitions @@ -191,7 +191,7 @@ export class BrowseService { ), map((def: BrowseDefinition) => { if (isEmpty(def) || isEmpty(def._links) || isEmpty(def._links[linkPath])) { - throw new Error(`A browse endpoint for ${linkPath} on ${metadatumKey} isn't configured`); + throw new Error(`A browse endpoint for ${linkPath} on ${metadataKey} isn't configured`); } else { return def._links[linkPath]; } diff --git a/src/app/core/cache/models/normalized-dspace-object.model.ts b/src/app/core/cache/models/normalized-dspace-object.model.ts index 030e17364a..87bd4b4369 100644 --- a/src/app/core/cache/models/normalized-dspace-object.model.ts +++ b/src/app/core/cache/models/normalized-dspace-object.model.ts @@ -1,7 +1,6 @@ import { autoserialize, autoserializeAs, deserialize, serialize } from 'cerialize'; import { DSpaceObject } from '../../shared/dspace-object.model'; - -import { Metadatum } from '../../shared/metadatum.model'; +import { MetadataMap } from '../../shared/metadata.interfaces'; import { ResourceType } from '../../shared/resource-type'; import { mapsTo } from '../builders/build-decorators'; import { NormalizedObject } from './normalized-object.model'; @@ -46,10 +45,10 @@ export class NormalizedDSpaceObject extends NormalizedObject { type: ResourceType; /** - * An array containing all metadata of this DSpaceObject + * All metadata of this DSpaceObject */ - @autoserializeAs(Metadatum) - metadata: Metadatum[]; + @autoserialize + metadata: MetadataMap; /** * An array of DSpaceObjects that are direct parents of this DSpaceObject diff --git a/src/app/core/data/search-response-parsing.service.ts b/src/app/core/data/search-response-parsing.service.ts index 7ee2b60f89..46b2572c4e 100644 --- a/src/app/core/data/search-response-parsing.service.ts +++ b/src/app/core/data/search-response-parsing.service.ts @@ -7,7 +7,7 @@ import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response. import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer'; import { hasValue } from '../../shared/empty.util'; import { SearchQueryResponse } from '../../+search-page/search-service/search-query-response.model'; -import { Metadatum } from '../shared/metadatum.model'; +import { MetadataMap, MetadataValue } from '../shared/metadata.interfaces'; @Injectable() export class SearchResponseParsingService implements ResponseParsingService { @@ -16,17 +16,17 @@ export class SearchResponseParsingService implements ResponseParsingService { parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { const payload = data.payload._embedded.searchResult; - const hitHighlights = payload._embedded.objects + const hitHighlights: MetadataMap[] = payload._embedded.objects .map((object) => object.hitHighlights) .map((hhObject) => { + const mdMap: MetadataMap = {}; if (hhObject) { - return Object.keys(hhObject).map((key) => Object.assign(new Metadatum(), { - key: key, - value: hhObject[key].join('...') - })) - } else { - return []; + for (const key of Object.keys(hhObject)) { + const value: MetadataValue = { value: hhObject[key].join('...'), language: null }; + mdMap[key] = [ value ]; + } } + return mdMap; }); const dsoSelfLinks = payload._embedded.objects diff --git a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts index 20d6b1dfb3..6bf5eb0818 100644 --- a/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts +++ b/src/app/core/dspace-rest-v2/dspace-rest-v2.service.ts @@ -91,9 +91,9 @@ export class DSpaceRESTv2Service { const form: FormData = new FormData(); form.append('name', dso.name); if (dso.metadata) { - for (const i of Object.keys(dso.metadata)) { - if (isNotEmpty(dso.metadata[i].value)) { - form.append(dso.metadata[i].key, dso.metadata[i].value); + for (const key of Object.keys(dso.metadata)) { + for (const value of dso.allMetadataValues(key)) { + form.append(key, value); } } } diff --git a/src/app/core/metadata/metadata.service.ts b/src/app/core/metadata/metadata.service.ts index 9dbfae3f90..736bf11923 100644 --- a/src/app/core/metadata/metadata.service.ts +++ b/src/app/core/metadata/metadata.service.ts @@ -294,6 +294,10 @@ export class MetadataService { } } + private hasType(value: string): boolean { + return this.currentObject.value.hasMetadata('dc.type', { value: value, ignoreCase: true }); + } + /** * Returns true if this._item is a dissertation * @@ -301,14 +305,7 @@ export class MetadataService { * true if this._item has a dc.type equal to 'Thesis' */ private isDissertation(): boolean { - let isDissertation = false; - for (const metadatum of this.currentObject.value.metadata) { - if (metadatum.key === 'dc.type') { - isDissertation = metadatum.value.toLowerCase() === 'thesis'; - break; - } - } - return isDissertation; + return this.hasType('thesis'); } /** @@ -318,40 +315,15 @@ export class MetadataService { * true if this._item has a dc.type equal to 'Technical Report' */ private isTechReport(): boolean { - let isTechReport = false; - for (const metadatum of this.currentObject.value.metadata) { - if (metadatum.key === 'dc.type') { - isTechReport = metadatum.value.toLowerCase() === 'technical report'; - break; - } - } - return isTechReport; + return this.hasType('technical report'); } private getMetaTagValue(key: string): string { - let value: string; - for (const metadatum of this.currentObject.value.metadata) { - if (metadatum.key === key) { - value = metadatum.value; - } - } - return value; + return this.currentObject.value.firstMetadataValue(key); } private getFirstMetaTagValue(keys: string[]): string { - let value: string; - for (const metadatum of this.currentObject.value.metadata) { - for (const key of keys) { - if (key === metadatum.key) { - value = metadatum.value; - break; - } - } - if (value !== undefined) { - break; - } - } - return value; + return this.currentObject.value.firstMetadataValue(keys); } private getMetaTagValuesAndCombine(key: string): string { @@ -359,15 +331,7 @@ export class MetadataService { } private getMetaTagValues(keys: string[]): string[] { - const values: string[] = []; - for (const metadatum of this.currentObject.value.metadata) { - for (const key of keys) { - if (key === metadatum.key) { - values.push(metadatum.value); - } - } - } - return values; + return this.currentObject.value.allMetadataValues(keys); } private addMetaTag(property: string, content: string): void { diff --git a/src/app/core/shared/collection.model.ts b/src/app/core/shared/collection.model.ts index 8fdc14bd6e..c630c9dd57 100644 --- a/src/app/core/shared/collection.model.ts +++ b/src/app/core/shared/collection.model.ts @@ -16,7 +16,7 @@ export class Collection extends DSpaceObject { * Corresponds to the metadata field dc.description */ get introductoryText(): string { - return this.findMetadata('dc.description'); + return this.firstMetadataValue('dc.description'); } /** @@ -24,7 +24,7 @@ export class Collection extends DSpaceObject { * Corresponds to the metadata field dc.description.abstract */ get shortDescription(): string { - return this.findMetadata('dc.description.abstract'); + return this.firstMetadataValue('dc.description.abstract'); } /** @@ -32,7 +32,7 @@ export class Collection extends DSpaceObject { * Corresponds to the metadata field dc.rights */ get copyrightText(): string { - return this.findMetadata('dc.rights'); + return this.firstMetadataValue('dc.rights'); } /** @@ -40,7 +40,7 @@ export class Collection extends DSpaceObject { * Corresponds to the metadata field dc.rights.license */ get license(): string { - return this.findMetadata('dc.rights.license'); + return this.firstMetadataValue('dc.rights.license'); } /** @@ -48,7 +48,7 @@ export class Collection extends DSpaceObject { * Corresponds to the metadata field dc.description.tableofcontents */ get sidebarText(): string { - return this.findMetadata('dc.description.tableofcontents'); + return this.firstMetadataValue('dc.description.tableofcontents'); } /** diff --git a/src/app/core/shared/community.model.ts b/src/app/core/shared/community.model.ts index c5f6e0ab87..c4e703fd7f 100644 --- a/src/app/core/shared/community.model.ts +++ b/src/app/core/shared/community.model.ts @@ -17,7 +17,7 @@ export class Community extends DSpaceObject { * Corresponds to the metadata field dc.description */ get introductoryText(): string { - return this.findMetadata('dc.description'); + return this.firstMetadataValue('dc.description'); } /** @@ -25,7 +25,7 @@ export class Community extends DSpaceObject { * Corresponds to the metadata field dc.description.abstract */ get shortDescription(): string { - return this.findMetadata('dc.description.abstract'); + return this.firstMetadataValue('dc.description.abstract'); } /** @@ -33,7 +33,7 @@ export class Community extends DSpaceObject { * Corresponds to the metadata field dc.rights */ get copyrightText(): string { - return this.findMetadata('dc.rights'); + return this.firstMetadataValue('dc.rights'); } /** @@ -41,7 +41,7 @@ export class Community extends DSpaceObject { * Corresponds to the metadata field dc.description.tableofcontents */ get sidebarText(): string { - return this.findMetadata('dc.description.tableofcontents'); + return this.firstMetadataValue('dc.description.tableofcontents'); } /** diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 3e08da151c..1dba79865f 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -1,5 +1,5 @@ -import { Metadatum } from './metadatum.model' -import { isEmpty, isNotEmpty } from '../../shared/empty.util'; +import { MetadataMap, MetadataValue, MetadataValueFilter } from './metadata.interfaces'; +import { Metadata } from './metadata.model'; import { CacheableObject } from '../cache/object-cache.reducer'; import { RemoteData } from '../data/remote-data'; import { ResourceType } from './resource-type'; @@ -35,14 +35,14 @@ export class DSpaceObject implements CacheableObject, ListableObject { * The name for this DSpaceObject */ get name(): string { - return this.findMetadata('dc.title'); + return this.firstMetadataValue('dc.title'); } /** - * An array containing all metadata of this DSpaceObject + * All metadata of this DSpaceObject */ @autoserialize - metadata: Metadatum[] = []; + metadata: MetadataMap; /** * An array of DSpaceObjects that are direct parents of this DSpaceObject @@ -54,42 +54,29 @@ export class DSpaceObject implements CacheableObject, ListableObject { */ owner: Observable>; - /** - * Find a metadata field by key and language - * - * This method returns the value of the first element - * in the metadata array that matches the provided - * key and language - * - * @param key - * @param language - * @return string - */ - findMetadata(key: string, language?: string): string { - const metadatum = this.metadata.find((m: Metadatum) => { - return m.key === key && (isEmpty(language) || m.language === language) - }); - if (isNotEmpty(metadatum)) { - return metadatum.value; - } else { - return undefined; - } + /** Gets all matching metadata in this DSpaceObject. See `Metadata.all` for more information. */ + allMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): MetadataValue[] { + return Metadata.all(this.metadata, keyOrKeys, valueFilter); } - /** - * Find metadata by an array of keys - * - * This method returns the values of the element - * in the metadata array that match the provided - * key(s) - * - * @param key(s) - * @return Array - */ - filterMetadata(keys: string[]): Metadatum[] { - return this.metadata.filter((metadatum: Metadatum) => { - return keys.some((key) => key === metadatum.key); - }); + /** Like `allMetadata`, but only returns string values. */ + allMetadataValues(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string[] { + return Metadata.allValues(this.metadata, keyOrKeys, valueFilter); + } + + /** Gets the first matching metadata in this DSpaceObject, or `undefined`. */ + firstMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): MetadataValue { + return Metadata.first(this.metadata, keyOrKeys, valueFilter); + } + + /** Like `firstMetadata`, but only returns a string value, or `undefined`. */ + firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { + return Metadata.firstValue(this.metadata, keyOrKeys, valueFilter); + } + + /** Checks for matching metadata in this DSpaceObject. */ + hasMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): boolean { + return Metadata.has(this.metadata, keyOrKeys, valueFilter); } } diff --git a/src/app/core/shared/metadata.interfaces.ts b/src/app/core/shared/metadata.interfaces.ts new file mode 100644 index 0000000000..3590117ce8 --- /dev/null +++ b/src/app/core/shared/metadata.interfaces.ts @@ -0,0 +1,30 @@ +/** A map of metadata keys to an ordered list of MetadataValue objects. */ +export interface MetadataMap { + [ key: string ]: MetadataValue[]; +} + +/** A single metadata value and its properties. */ +export interface MetadataValue { + + /** The language. */ + language: string; + + /** The string value. */ + value: string; +} + +/** Constraints for matching metadata values. */ +export interface MetadataValueFilter { + + /** The language constraint. */ + language?: string; + + /** The value constraint. */ + value?: string; + + /** Whether the value constraint should match without regard to case. */ + ignoreCase?: boolean; + + /** Whether the value constraint should match as a substring. */ + substring?: boolean; +} diff --git a/src/app/core/shared/metadata.model.ts b/src/app/core/shared/metadata.model.ts new file mode 100644 index 0000000000..c774af189b --- /dev/null +++ b/src/app/core/shared/metadata.model.ts @@ -0,0 +1,119 @@ +import { isEmpty } from '../../shared/empty.util'; +import { MetadataMap, MetadataValue, MetadataValueFilter } from './metadata.interfaces'; + +/** + * Static utility methods for working with DSpace metadata. + */ +export class Metadata { + + /** + * Gets all matching metadata. + * + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). Values will only be returned from one map -- + * the first with at least one match. + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported, so `'*'` will + * match all keys, `'dc.date.*'` will match all qualified dc dates, and so on. Exact keys will be evaluated + * (and matches returned) in the order they are given in the parameter. When multiple keys match a wildcard, + * they are evaluated in the order they are stored in the map (alphanumeric if obtained from the REST api). + * If duplicate or overlapping keys are specified, the first one takes precedence. For example, specifying + * `['dc.date', 'dc.*', '*']` will cause any `dc.date` values to be evaluated (and returned, if matched) + * first, followed by any other `dc` metadata values, followed by any other (non-dc) metadata values. + * @param {MetadataValueFilter} filter The value filter to use. + * @returns {MetadataValue[]} the matching values or an empty array. + */ + public static all(mapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], + filter?: MetadataValueFilter): MetadataValue[] { + const mdMaps: MetadataMap[] = mapOrMaps instanceof Array ? mapOrMaps : [ mapOrMaps ]; + const matches: MetadataValue[] = []; + for (const mdMap of mdMaps) { + for (const mdKey of Metadata.resolveKeys(mdMap, keyOrKeys)) { + const candidates = mdMap[mdKey]; + if (candidates) { + for (const candidate of candidates) { + if (Metadata.valueMatches(candidate, filter)) { + matches.push(candidate); + } + } + } + } + if (!isEmpty(matches)) { + return matches; + } + } + return matches; + } + + /** Like `all`, but only returns string values. */ + public static allValues(mapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], + filter?: MetadataValueFilter): string[] { + return Metadata.all(mapOrMaps, keyOrKeys, filter).map((mdValue) => mdValue.value); + } + + /** Gets the first matching MetadataValue object in a map, or `undefined`. */ + public static first(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], + filter?: MetadataValueFilter): MetadataValue { + const mdMaps: MetadataMap[] = mdMapOrMaps instanceof Array ? mdMapOrMaps : [ mdMapOrMaps ]; + for (const mdMap of mdMaps) { + for (const key of Metadata.resolveKeys(mdMap, keyOrKeys)) { + const values: MetadataValue[] = mdMap[key]; + if (values) { + return values.find((value: MetadataValue) => Metadata.valueMatches(value, filter)); + } + } + } + } + + /** Like `first`, but only returns a string value, or `undefined`. */ + public static firstValue(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], + filter?: MetadataValueFilter): string { + const value = Metadata.first(mdMapOrMaps, keyOrKeys, filter); + return value === undefined ? undefined : value.value; + } + + /** Checks the given map for a matching value. */ + public static has(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], + filter?: MetadataValueFilter): boolean { + return Metadata.first(mdMapOrMaps, keyOrKeys, filter) !== undefined; + } + + /** Checks if a value matches a filter. */ + public static valueMatches(mdValue: MetadataValue, filter: MetadataValueFilter) { + if (!filter) { + return true; + } else if (filter.language && filter.language !== mdValue.language) { + return false; + } else if (filter.value) { + let fValue = filter.value; + let mValue = mdValue.value; + if (filter.ignoreCase) { + fValue = filter.value.toLowerCase(); + mValue = mdValue.value.toLowerCase(); + } + if (filter.substring) { + return mValue.includes(fValue); + } else { + return mValue === fValue; + } + } + return true; + } + + /** Gets the list of keys in the map limited by, and in the order given by `keyOrKeys` */ + private static resolveKeys(mdMap: MetadataMap, keyOrKeys: string | string[]): string[] { + const inputKeys: string[] = keyOrKeys instanceof Array ? keyOrKeys : [ keyOrKeys ]; + const outputKeys: string[] = []; + for (const inputKey of inputKeys) { + if (inputKey.includes('*')) { + const inputKeyRegex = new RegExp('^' + inputKey.replace('.', '\.').replace('*', '.*') + '$'); + for (const mapKey of Object.keys(mdMap)) { + if (!outputKeys.includes(mapKey) && inputKeyRegex.test(mapKey)) { + outputKeys.push(mapKey); + } + } + } else if (mdMap.hasOwnProperty(inputKey) && !outputKeys.includes(inputKey)) { + outputKeys.push(inputKey); + } + } + return outputKeys; + } +} diff --git a/src/app/core/shared/metadatum.model.ts b/src/app/core/shared/metadatum.model.ts deleted file mode 100644 index a3c5830608..0000000000 --- a/src/app/core/shared/metadatum.model.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { autoserialize } from 'cerialize'; - -export class Metadatum { - - /** - * The metadata field of this Metadatum - */ - @autoserialize - key: string; - - /** - * The language of this Metadatum - */ - @autoserialize - language: string; - - /** - * The value of this Metadatum - */ - @autoserialize - value: string; - -} diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts index 17710fd1c6..0e0195aaaa 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.ts @@ -8,6 +8,7 @@ import { FormGroup } from '@angular/forms'; import { DynamicFormControlModel } from '@ng-dynamic-forms/core/src/model/dynamic-form-control.model'; import { TranslateService } from '@ngx-translate/core'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { MetadataMap, MetadataValue } from '../../../core/shared/metadata.interfaces'; import { isNotEmpty } from '../../empty.util'; import { ResourceType } from '../../../core/shared/resource-type'; @@ -64,7 +65,7 @@ export class ComColFormComponent implements OnInit { ngOnInit(): void { this.formModel.forEach( (fieldModel: DynamicInputModel) => { - fieldModel.value = this.dso.findMetadata(fieldModel.name); + fieldModel.value = this.dso.firstMetadataValue(fieldModel.name); } ); this.formGroup = this.formService.createFormGroup(this.formModel); @@ -77,20 +78,24 @@ export class ComColFormComponent implements OnInit { } /** - * Checks which new fields where added and sends the updated version of the DSO to the parent component + * Checks which new fields were added and sends the updated version of the DSO to the parent component */ onSubmit() { - const metadata = this.formModel.map( - (fieldModel: DynamicInputModel) => { - return { key: fieldModel.name, value: fieldModel.value } + const formMetadata = new Object() as MetadataMap; + this.formModel.forEach((fieldModel: DynamicInputModel) => { + const value: MetadataValue = { value: fieldModel.value as string, language: null }; + if (formMetadata.hasOwnProperty(fieldModel.name)) { + formMetadata[fieldModel.name].push(value); + } else { + formMetadata[fieldModel.name] = [ value ]; } - ); - const filteredOldMetadata = this.dso.metadata.filter((filter) => !metadata.map((md) => md.key).includes(filter.key)); - const filteredNewMetadata = metadata.filter((md) => isNotEmpty(md.value)); + }); - const newMetadata = [...filteredOldMetadata, ...filteredNewMetadata]; const updatedDSO = Object.assign({}, this.dso, { - metadata: newMetadata, + metadata: { + ...this.dso.metadata, + ...formMetadata + }, type: ResourceType.Community }); this.submitForm.emit(updatedDSO); diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index 59df86fdff..d52036b5dc 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -1,6 +1,5 @@ import { Component, Inject } from '@angular/core'; import { ListableObject } from '../listable-object.model'; -import { hasValue } from '../../../empty.util'; @Component({ selector: 'ds-abstract-object-element', @@ -11,8 +10,4 @@ export class AbstractListableElementComponent { public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) { this.object = listableObject as T; } - - hasValue(data) { - return hasValue(data); - } } diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html index 728dba7549..6bb2cfa99d 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html @@ -5,19 +5,19 @@
-

{{object.findMetadata('dc.title')}}

+

{{object.firstMetadataValue('dc.title')}}

-

- {{authorMd.value}} +

+ {{author}} ; - {{object.findMetadata("dc.date.issued")}} + {{object.firstMetadataValue("dc.date.issued")}}

-

{{object.findMetadata("dc.description.abstract") }}

+

{{object.firstMetadataValue("dc.description.abstract")}}

diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html index 1e4f6f3c64..c7e2f524f3 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html @@ -8,20 +8,20 @@
-

+

-

- {{dso.findMetadata("dc.date.issued")}} - , - + {{dso.firstMetadataValue('dc.date.issued')}} + , +

- +

diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index 5fd1c87edd..c3a80604db 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -2,12 +2,11 @@ import { Component, Inject } from '@angular/core'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { Metadatum } from '../../../core/shared/metadatum.model'; -import { isEmpty, hasNoValue, hasValue } from '../../empty.util'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { TruncatableService } from '../../truncatable/truncatable.service'; import { Observable } from 'rxjs'; +import { Metadata } from '../../../core/shared/metadata.model'; @Component({ selector: 'ds-search-result-grid-element', @@ -22,39 +21,14 @@ export class SearchResultGridElementComponent, K exten this.dso = this.object.dspaceObject; } - getValues(keys: string[]): string[] { - const results: string[] = new Array(); - this.object.hitHighlights.forEach( - (md: Metadatum) => { - if (keys.indexOf(md.key) > -1) { - results.push(md.value); - } - } - ); - if (isEmpty(results)) { - this.dso.filterMetadata(keys).forEach( - (md: Metadatum) => { - results.push(md.value); - } - ); - } - return results; + /** Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. */ + allMetadataValues(keyOrKeys: string | string[]): string[] { + return Metadata.allValues([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } - getFirstValue(key: string): string { - let result: string; - this.object.hitHighlights.some( - (md: Metadatum) => { - if (key === md.key) { - result = md.value; - return true; - } - } - ); - if (hasNoValue(result)) { - result = this.dso.findMetadata(key); - } - return result; + /** Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. */ + firstMetadataValue(keyOrKeys: string | string[]): string { + return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } isCollapsed(): Observable { diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-list-element.component.html index 711ce19037..8179b77629 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.html @@ -1,23 +1,23 @@ - {{object.findMetadata("dc.title")}} + {{object.firstMetadataValue("dc.title")}}
- - {{authorMd.value}} + {{author}} ; - ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}}) + ({{object.firstMetadataValue("dc.publisher")}}, {{object.firstMetadataValue("dc.date.issued")}}) -
- {{object.findMetadata("dc.description.abstract")}} +
+ {{object.firstMetadataValue("dc.description.abstract")}}
diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html index be549b2b76..b4af631e83 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.html @@ -1,2 +1,2 @@ - -
+ +
diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html index 150ca503cc..9444a63771 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.html @@ -1,2 +1,2 @@ - -
+ +
diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html index 584d476e73..6261220459 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html @@ -1,24 +1,24 @@ + [innerHTML]="firstMetadataValue('dc.title')"> - () - ) + - + -
+
+ [innerHTML]="firstMetadataValue('dc.description.abstract')">
- \ No newline at end of file + diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index 6a3b698dd6..a9a3050ac8 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -3,11 +3,10 @@ import { Observable } from 'rxjs'; import { SearchResult } from '../../../+search-page/search-result.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; -import { Metadatum } from '../../../core/shared/metadatum.model'; -import { hasNoValue, isEmpty } from '../../empty.util'; import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component'; import { TruncatableService } from '../../truncatable/truncatable.service'; +import { Metadata } from '../../../core/shared/metadata.model'; @Component({ selector: 'ds-search-result-list-element', @@ -22,39 +21,14 @@ export class SearchResultListElementComponent, K exten this.dso = this.object.dspaceObject; } - getValues(keys: string[]): string[] { - const results: string[] = new Array(); - this.object.hitHighlights.forEach( - (md: Metadatum) => { - if (keys.indexOf(md.key) > -1) { - results.push(md.value); - } - } - ); - if (isEmpty(results)) { - this.dso.filterMetadata(keys).forEach( - (md: Metadatum) => { - results.push(md.value); - } - ); - } - return results; + /** Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. */ + allMetadataValues(keyOrKeys: string | string[]): string[] { + return Metadata.allValues([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } - getFirstValue(key: string): string { - let result: string; - this.object.hitHighlights.some( - (md: Metadatum) => { - if (key === md.key) { - result = md.value; - return true; - } - } - ); - if (hasNoValue(result)) { - result = this.dso.findMetadata(key); - } - return result; + /** Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. */ + firstMetadataValue(keyOrKeys: string | string[]): string { + return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } isCollapsed(): Observable { From ea9ce6194cf567b4e7522952c70388db66a1bd06 Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Sat, 22 Dec 2018 23:05:57 -0500 Subject: [PATCH 2/6] DS-4107 Update tests and mocks for metadata as map --- ...-page-sub-community-list.component.spec.ts | 44 ++-- .../modify-item-overview.component.spec.ts | 28 ++- .../collections/collections.component.spec.ts | 14 +- .../search-results.component.spec.ts | 118 +++++----- .../auth-response-parsing.service.spec.ts | 37 +-- src/app/core/browse/browse.service.spec.ts | 28 +-- .../remote-data-build.service.spec.ts | 28 ++- ...wse-items-response-parsing-service.spec.ts | 45 ++-- .../core/metadata/metadata.service.spec.ts | 21 +- .../comcol-form/comcol-form.component.spec.ts | 42 ++-- src/app/shared/mocks/mock-item.ts | 222 +++++++++--------- .../collection-grid-element.component.spec.ts | 28 ++- .../community-grid-element.component.spec.ts | 28 ++- .../item-grid-element.component.spec.ts | 50 ++-- ...arch-result-grid-element.component.spec.ts | 32 +-- ...arch-result-grid-element.component.spec.ts | 32 +-- ...arch-result-grid-element.component.spec.ts | 54 +++-- ...rowse-entry-list-element.component.spec.ts | 3 +- .../collection-list-element.component.spec.ts | 28 ++- .../community-list-element.component.spec.ts | 28 ++- .../item-list-element.component.spec.ts | 50 ++-- ...arch-result-list-element.component.spec.ts | 32 +-- ...arch-result-list-element.component.spec.ts | 32 +-- ...arch-result-list-element.component.spec.ts | 54 +++-- .../search-form/search-form.component.spec.ts | 119 +++++----- 25 files changed, 646 insertions(+), 551 deletions(-) diff --git a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts index ace748c7de..3e6190ae6d 100644 --- a/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts +++ b/src/app/+community-page/sub-community-list/community-page-sub-community-list.component.spec.ts @@ -18,42 +18,38 @@ describe('SubCommunityList Component', () => { const subcommunities = [Object.assign(new Community(), { id: '123456789-1', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'SubCommunity 1' - }] + metadata: { + 'dc.title': [ + { language: 'en_US', value: 'SubCommunity 1' } + ] + } }), Object.assign(new Community(), { id: '123456789-2', - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'SubCommunity 2' - }] + metadata: { + 'dc.title': [ + { language: 'en_US', value: 'SubCommunity 2' } + ] + } }) ]; const emptySubCommunitiesCommunity = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }], + metadata: { + 'dc.title': [ + { language: 'en_US', value: 'Test title' } + ] + }, subcommunities: observableOf(new RemoteData(true, true, true, undefined, new PaginatedList(new PageInfo(), []))) }); const mockCommunity = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }], + metadata: { + 'dc.title': [ + { language: 'en_US', value: 'Test title' } + ] + }, subcommunities: observableOf(new RemoteData(true, true, true, undefined, new PaginatedList(new PageInfo(), subcommunities))) }) diff --git a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.spec.ts b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.spec.ts index 942357dc5a..07ad9a347c 100644 --- a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.spec.ts +++ b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.spec.ts @@ -11,10 +11,14 @@ const mockItem = Object.assign(new Item(), { id: 'fake-id', handle: 'fake/handle', lastModified: '2018', - metadata: [ - {key: 'dc.title', value: 'Mock item title', language: 'en'}, - {key: 'dc.contributor.author', value: 'Mayer, Ed', language: ''} - ] + metadata: { + 'dc.title': [ + { value: 'Mock item title', language: 'en' } + ], + 'dc.contributor.author': [ + { value: 'Mayer, Ed', language: '' } + ] + } }); describe('ModifyItemOverviewComponent', () => { @@ -37,19 +41,19 @@ describe('ModifyItemOverviewComponent', () => { const metadataRows = fixture.debugElement.queryAll(By.css('tr.metadata-row')); expect(metadataRows.length).toEqual(2); - const titleRow = metadataRows[0].queryAll(By.css('td')); - expect(titleRow.length).toEqual(3); - - expect(titleRow[0].nativeElement.innerHTML).toContain('dc.title'); - expect(titleRow[1].nativeElement.innerHTML).toContain('Mock item title'); - expect(titleRow[2].nativeElement.innerHTML).toContain('en'); - - const authorRow = metadataRows[1].queryAll(By.css('td')); + const authorRow = metadataRows[0].queryAll(By.css('td')); expect(authorRow.length).toEqual(3); expect(authorRow[0].nativeElement.innerHTML).toContain('dc.contributor.author'); expect(authorRow[1].nativeElement.innerHTML).toContain('Mayer, Ed'); expect(authorRow[2].nativeElement.innerHTML).toEqual(''); + const titleRow = metadataRows[1].queryAll(By.css('td')); + expect(titleRow.length).toEqual(3); + + expect(titleRow[0].nativeElement.innerHTML).toContain('dc.title'); + expect(titleRow[1].nativeElement.innerHTML).toContain('Mock item title'); + expect(titleRow[2].nativeElement.innerHTML).toContain('en'); + }); }); diff --git a/src/app/+item-page/field-components/collections/collections.component.spec.ts b/src/app/+item-page/field-components/collections/collections.component.spec.ts index 865ce78a39..53fcded9e3 100644 --- a/src/app/+item-page/field-components/collections/collections.component.spec.ts +++ b/src/app/+item-page/field-components/collections/collections.component.spec.ts @@ -14,12 +14,14 @@ let collectionsComponent: CollectionsComponent; let fixture: ComponentFixture; const mockCollection1: Collection = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - }] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const succeededMockItem: Item = Object.assign(new Item(), {owningCollection: observableOf(new RemoteData(false, false, true, null, mockCollection1))}); diff --git a/src/app/+search-page/search-results/search-results.component.spec.ts b/src/app/+search-page/search-results/search-results.component.spec.ts index b7ac11553a..8d0566d1df 100644 --- a/src/app/+search-page/search-results/search-results.component.spec.ts +++ b/src/app/+search-page/search-results/search-results.component.spec.ts @@ -111,33 +111,38 @@ export const objects = [ id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', type: ResourceType.Community, - metadata: [ - { - key: 'dc.description', - language: null, - value: '' - }, - { - key: 'dc.description.abstract', - language: null, - value: 'This is a test community to hold content for the OR2017 demostration' - }, - { - key: 'dc.description.tableofcontents', - language: null, - value: '' - }, - { - key: 'dc.rights', - language: null, - value: '' - }, - { - key: 'dc.title', - language: null, - value: 'OR2017 - Demonstration' - } - ] + metadata: { + 'dc.description': [ + { + language: null, + value: '' + } + ], + 'dc.description.abstract': [ + { + language: null, + value: 'This is a test community to hold content for the OR2017 demostration' + } + ], + 'dc.description.tableofcontents': [ + { + language: null, + value: '' + } + ], + 'dc.rights': [ + { + language: null, + value: '' + } + ], + 'dc.title': [ + { + language: null, + value: 'OR2017 - Demonstration' + } + ] + } }), Object.assign(new Community(), { @@ -160,33 +165,38 @@ export const objects = [ id: '9076bd16-e69a-48d6-9e41-0238cb40d863', uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', type: ResourceType.Community, - metadata: [ - { - key: 'dc.description', - language: null, - value: '

This is the introductory text for the Sample Community on the DSpace Demonstration Site. It is editable by System or Community Administrators (of this Community).

\r\n

DSpace Communities may contain one or more Sub-Communities or Collections (of Items).

\r\n

This particular Community has its own logo (the DuraSpace logo).

' - }, - { - key: 'dc.description.abstract', - language: null, - value: 'This is a sample top-level community' - }, - { - key: 'dc.description.tableofcontents', - language: null, - value: '

This is the news section for this Sample Community. System or Community Administrators (of this Community) can edit this News field.

' - }, - { - key: 'dc.rights', - language: null, - value: '

If this Community had special copyright text to display, it would be displayed here.

' - }, - { - key: 'dc.title', - language: null, - value: 'Sample Community' - } - ] + metadata: { + 'dc.description': [ + { + language: null, + value: '

This is the introductory text for the Sample Community on the DSpace Demonstration Site. It is editable by System or Community Administrators (of this Community).

\r\n

DSpace Communities may contain one or more Sub-Communities or Collections (of Items).

\r\n

This particular Community has its own logo (the DuraSpace logo).

' + } + ], + 'dc.description.abstract': [ + { + language: null, + value: 'This is a sample top-level community' + } + ], + 'dc.description.tableofcontents': [ + { + language: null, + value: '

This is the news section for this Sample Community. System or Community Administrators (of this Community) can edit this News field.

' + } + ], + 'dc.rights': [ + { + language: null, + value: '

If this Community had special copyright text to display, it would be displayed here.

' + } + ], + 'dc.title': [ + { + language: null, + value: 'Sample Community' + } + ] + } } ) ]; diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index a4131db489..ee9f2e571b 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -60,23 +60,26 @@ describe('AuthResponseParsingService', () => { handle: null, id: '4dc70ab5-cd73-492f-b007-3179d2d9296b', lastActive: '2018-05-14T17:03:31.277+0000', - metadata: [ - { - key: 'eperson.firstname', - language: null, - value: 'User' - }, - { - key: 'eperson.lastname', - language: null, - value: 'Test' - }, - { - key: 'eperson.language', - language: null, - value: 'en' - } - ], + metadata: { + 'eperson.firstname': [ + { + language: null, + value: 'User' + } + ], + 'eperson.lastname': [ + { + language: null, + value: 'Test' + } + ], + 'eperson.language': [ + { + language: null, + value: 'en' + } + ] + }, name: 'User Test', netid: 'myself@testshib.org', requireCertificate: false, diff --git a/src/app/core/browse/browse.service.spec.ts b/src/app/core/browse/browse.service.spec.ts index da75e1a877..1ce0f6b156 100644 --- a/src/app/core/browse/browse.service.spec.ts +++ b/src/app/core/browse/browse.service.spec.ts @@ -219,44 +219,44 @@ describe('BrowseService', () => { }})); }); - it('should return the URL for the given metadatumKey and linkPath', () => { - const metadatumKey = 'dc.date.issued'; + it('should return the URL for the given metadataKey and linkPath', () => { + const metadataKey = 'dc.date.issued'; const linkPath = 'items'; const expectedURL = browseDefinitions[0]._links[linkPath]; - const result = service.getBrowseURLFor(metadatumKey, linkPath); + const result = service.getBrowseURLFor(metadataKey, linkPath); const expected = cold('c-d-', { c: undefined, d: expectedURL }); expect(result).toBeObservable(expected); }); - it('should work when the definition uses a wildcard in the metadatumKey', () => { - const metadatumKey = 'dc.contributor.author'; // should match dc.contributor.* in the definition + it('should work when the definition uses a wildcard in the metadataKey', () => { + const metadataKey = 'dc.contributor.author'; // should match dc.contributor.* in the definition const linkPath = 'items'; const expectedURL = browseDefinitions[1]._links[linkPath]; - const result = service.getBrowseURLFor(metadatumKey, linkPath); + const result = service.getBrowseURLFor(metadataKey, linkPath); const expected = cold('c-d-', { c: undefined, d: expectedURL }); expect(result).toBeObservable(expected); }); it('should throw an error when the key doesn\'t match', () => { - const metadatumKey = 'dc.title'; // isn't in the definitions + const metadataKey = 'dc.title'; // isn't in the definitions const linkPath = 'items'; - const result = service.getBrowseURLFor(metadatumKey, linkPath); - const expected = cold('c-#-', { c: undefined }, new Error(`A browse endpoint for ${linkPath} on ${metadatumKey} isn't configured`)); + const result = service.getBrowseURLFor(metadataKey, linkPath); + const expected = cold('c-#-', { c: undefined }, new Error(`A browse endpoint for ${linkPath} on ${metadataKey} isn't configured`)); expect(result).toBeObservable(expected); }); it('should throw an error when the link doesn\'t match', () => { - const metadatumKey = 'dc.date.issued'; + const metadataKey = 'dc.date.issued'; const linkPath = 'collections'; // isn't in the definitions - const result = service.getBrowseURLFor(metadatumKey, linkPath); - const expected = cold('c-#-', { c: undefined }, new Error(`A browse endpoint for ${linkPath} on ${metadatumKey} isn't configured`)); + const result = service.getBrowseURLFor(metadataKey, linkPath); + const expected = cold('c-#-', { c: undefined }, new Error(`A browse endpoint for ${linkPath} on ${metadataKey} isn't configured`)); expect(result).toBeObservable(expected); }); @@ -271,10 +271,10 @@ describe('BrowseService', () => { spyOn(service, 'getBrowseDefinitions').and .returnValue(hot('----')); - const metadatumKey = 'dc.date.issued'; + const metadataKey = 'dc.date.issued'; const linkPath = 'items'; - const result = service.getBrowseURLFor(metadatumKey, linkPath); + const result = service.getBrowseURLFor(metadataKey, linkPath); const expected = cold('b---', { b: undefined }); expect(result).toBeObservable(expected); }); diff --git a/src/app/core/cache/builders/remote-data-build.service.spec.ts b/src/app/core/cache/builders/remote-data-build.service.spec.ts index e4444ca803..272969050d 100644 --- a/src/app/core/cache/builders/remote-data-build.service.spec.ts +++ b/src/app/core/cache/builders/remote-data-build.service.spec.ts @@ -8,20 +8,24 @@ import { of as observableOf } from 'rxjs'; const pageInfo = new PageInfo(); const array = [ Object.assign(new Item(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Item nr 1' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Item nr 1' + } + ] + } }), Object.assign(new Item(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Item nr 2' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Item nr 2' + } + ] + } }) ]; const paginatedList = new PaginatedList(pageInfo, array); diff --git a/src/app/core/data/browse-items-response-parsing-service.spec.ts b/src/app/core/data/browse-items-response-parsing-service.spec.ts index 99ea474dc6..f512a9af26 100644 --- a/src/app/core/data/browse-items-response-parsing-service.spec.ts +++ b/src/app/core/data/browse-items-response-parsing-service.spec.ts @@ -24,13 +24,14 @@ describe('BrowseItemsResponseParsingService', () => { uuid: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', name: 'Development of Local Supply Chain : A Critical Link for Concentrated Solar Power in India', handle: '10986/17472', - metadata: [ - { - key: 'dc.creator', - value: 'World Bank', - language: null - } - ], + metadata: { + 'dc.creator': [ + { + value: 'World Bank', + language: null + } + ] + }, inArchive: true, discoverable: true, withdrawn: false, @@ -56,13 +57,14 @@ describe('BrowseItemsResponseParsingService', () => { uuid: '27c6f976-257c-4ad0-a0ef-c5e34ffe4d5b', name: 'Development of Local Supply Chain : The Missing Link for Concentrated Solar Power Projects in India', handle: '10986/17475', - metadata: [ - { - key: 'dc.creator', - value: 'World Bank', - language: null - } - ], + metadata: { + 'dc.creator': [ + { + value: 'World Bank', + language: null + } + ] + }, inArchive: true, discoverable: true, withdrawn: false, @@ -115,13 +117,14 @@ describe('BrowseItemsResponseParsingService', () => { uuid: 'd7b6bc6f-ff6c-444a-a0d3-0cd9b68043e7', name: 'Development of Local Supply Chain : A Critical Link for Concentrated Solar Power in India', handle: '10986/17472', - metadata: [ - { - key: 'dc.creator', - value: 'World Bank', - language: null - } - ], + metadata: { + 'dc.creator': [ + { + value: 'World Bank', + language: null + } + ] + }, inArchive: true, discoverable: true, withdrawn: false, diff --git a/src/app/core/metadata/metadata.service.spec.ts b/src/app/core/metadata/metadata.service.spec.ts index 90c811db7a..f2dd0770ed 100644 --- a/src/app/core/metadata/metadata.service.spec.ts +++ b/src/app/core/metadata/metadata.service.spec.ts @@ -37,6 +37,7 @@ import { HttpClient } from '@angular/common/http'; import { EmptyError } from 'rxjs/internal-compatibility'; import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service'; import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service'; +import { MetadataValue } from '../shared/metadata.interfaces'; /* tslint:disable:max-classes-per-file */ @Component({ @@ -152,7 +153,7 @@ describe('MetadataService', () => { expect(title.getTitle()).toEqual('Test PowerPoint Document'); expect(tagStore.get('citation_title')[0].content).toEqual('Test PowerPoint Document'); expect(tagStore.get('citation_author')[0].content).toEqual('Doe, Jane'); - expect(tagStore.get('citation_date')[0].content).toEqual('1650-06-26T19:58:25Z'); + expect(tagStore.get('citation_date')[0].content).toEqual('1650-06-26'); expect(tagStore.get('citation_issn')[0].content).toEqual('123456789'); expect(tagStore.get('citation_language')[0].content).toEqual('en'); expect(tagStore.get('citation_keywords')[0].content).toEqual('keyword1; keyword2; keyword3'); @@ -216,22 +217,18 @@ describe('MetadataService', () => { const mockType = (mockItem: Item, type: string): Item => { const typedMockItem = Object.assign(new Item(), mockItem) as Item; - for (const metadatum of typedMockItem.metadata) { - if (metadatum.key === 'dc.type') { - metadatum.value = type; - break; - } - } + typedMockItem.metadata['dc.type'] = [ { value: type } ] as MetadataValue[]; return typedMockItem; } const mockPublisher = (mockItem: Item): Item => { const publishedMockItem = Object.assign(new Item(), mockItem) as Item; - publishedMockItem.metadata.push({ - key: 'dc.publisher', - language: 'en_US', - value: 'Mock Publisher' - }); + publishedMockItem.metadata['dc.publisher'] = [ + { + language: 'en_US', + value: 'Mock Publisher' + } + ] as MetadataValue[]; return publishedMockItem; } diff --git a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts index a6f5e0d45a..cc1e2063ff 100644 --- a/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts +++ b/src/app/shared/comcol-forms/comcol-form/comcol-form.component.spec.ts @@ -11,7 +11,6 @@ import { ResourceType } from '../../../core/shared/resource-type'; import { ComColFormComponent } from './comcol-form.component'; import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { hasValue } from '../../empty.util'; -import { Metadatum } from '../../../core/shared/metadatum.model'; describe('ComColFormComponent', () => { let comp: ComColFormComponent; @@ -29,23 +28,24 @@ describe('ComColFormComponent', () => { return undefined; } }; - const titleMD = { key: 'dc.title', value: 'Community Title' } as Metadatum; - const randomMD = { key: 'dc.random', value: 'Random metadata excluded from form' } as Metadatum; - const abstractMD = { - key: 'dc.description.abstract', - value: 'Community description' - } as Metadatum; - const newTitleMD = { key: 'dc.title', value: 'New Community Title' } as Metadatum; + const dcTitle = 'dc.title'; + const dcRandom = 'dc.random'; + const dcAbstract = 'dc.description.abstract'; + + const titleMD = { [dcTitle]: [ { value: 'Community Title', language: null } ] }; + const randomMD = { [dcRandom]: [ { value: 'Random metadata excluded from form', language: null } ] }; + const abstractMD = { [dcAbstract]: [ { value: 'Community description', language: null } ] }; + const newTitleMD = { [dcTitle]: [ { value: 'New Community Title', language: null } ] }; const formModel = [ new DynamicInputModel({ id: 'title', - name: newTitleMD.key, - value: 'New Community Title' + name: dcTitle, + value: newTitleMD[dcTitle][0].value }), new DynamicInputModel({ id: 'abstract', - name: abstractMD.key, - value: abstractMD.value + name: dcAbstract, + value: abstractMD[dcAbstract][0].value }) ]; @@ -87,10 +87,10 @@ describe('ComColFormComponent', () => { comp.dso = Object.assign( new Community(), { - metadata: [ - titleMD, - randomMD - ] + metadata: { + ...titleMD, + ...randomMD + } } ); @@ -101,11 +101,11 @@ describe('ComColFormComponent', () => { {}, new Community(), { - metadata: [ - randomMD, - newTitleMD, - abstractMD - ], + metadata: { + ...newTitleMD, + ...randomMD, + ...abstractMD + }, type: ResourceType.Community }, ) diff --git a/src/app/shared/mocks/mock-item.ts b/src/app/shared/mocks/mock-item.ts index 2e5c764ee2..98881436b9 100644 --- a/src/app/shared/mocks/mock-item.ts +++ b/src/app/shared/mocks/mock-item.ts @@ -51,13 +51,14 @@ export const MockItem: Item = Object.assign(new Item(), { id: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', uuid: 'cf9b0c8e-a1eb-4b65-afd0-567366448713', type: 'bitstream', - metadata: [ - { - key: 'dc.title', - language: null, - value: 'test_word.docx' - } - ] + metadata: { + 'dc.title': [ + { + language: null, + value: 'test_word.docx' + } + ] + } }, { sizeBytes: 31302, @@ -85,13 +86,14 @@ export const MockItem: Item = Object.assign(new Item(), { id: '99b00f3c-1cc6-4689-8158-91965bee6b28', uuid: '99b00f3c-1cc6-4689-8158-91965bee6b28', type: 'bitstream', - metadata: [ - { - key: 'dc.title', - language: null, - value: 'test_pdf.pdf' - } - ] + metadata: { + 'dc.title': [ + { + language: null, + value: 'test_pdf.pdf' + } + ] + } } ] } @@ -100,98 +102,106 @@ export const MockItem: Item = Object.assign(new Item(), { id: '0ec7ff22-f211-40ab-a69e-c819b0b1f357', uuid: '0ec7ff22-f211-40ab-a69e-c819b0b1f357', type: 'item', - metadata: [ - { - key: 'dc.creator', - language: 'en_US', - value: 'Doe, Jane' - }, - { - key: 'dc.date.accessioned', - language: null, - value: '1650-06-26T19:58:25Z' - }, - { - key: 'dc.date.available', - language: null, - value: '1650-06-26T19:58:25Z' - }, - { - key: 'dc.date.issued', - language: null, - value: '1650-06-26' - }, - { - key: 'dc.identifier.issn', - language: 'en_US', - value: '123456789' - }, - { - key: 'dc.identifier.uri', - language: null, - value: 'http://dspace7.4science.it/xmlui/handle/10673/6' - }, - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' - }, - { - key: 'dc.description.provenance', - language: 'en', - value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' - }, - { - key: 'dc.description.provenance', - language: 'en', - value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' - }, - { - key: 'dc.description.provenance', - language: 'en', - value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' - }, - { - key: 'dc.description.provenance', - language: 'en', - value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' - }, - { - key: 'dc.language', - language: 'en_US', - value: 'en' - }, - { - key: 'dc.rights', - language: 'en_US', - value: '© Jane Doe' - }, - { - key: 'dc.subject', - language: 'en_US', - value: 'keyword1' - }, - { - key: 'dc.subject', - language: 'en_US', - value: 'keyword2' - }, - { - key: 'dc.subject', - language: 'en_US', - value: 'keyword3' - }, - { - key: 'dc.title', - language: 'en_US', - value: 'Test PowerPoint Document' - }, - { - key: 'dc.type', - language: 'en_US', - value: 'text' - } - ], + metadata: { + 'dc.creator': [ + { + language: 'en_US', + value: 'Doe, Jane' + } + ], + 'dc.date.accessioned': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.available': [ + { + language: null, + value: '1650-06-26T19:58:25Z' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '1650-06-26' + } + ], + 'dc.identifier.issn': [ + { + language: 'en_US', + value: '123456789' + } + ], + 'dc.identifier.uri': [ + { + language: null, + value: 'http://dspace7.4science.it/xmlui/handle/10673/6' + } + ], + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'This is really just a sample abstract. If it was a real abstract it would contain useful information about this test document. Sorry though, nothing useful in this paragraph. You probably shouldn\'t have even bothered to read it!' + } + ], + 'dc.description.provenance': [ + { + language: 'en', + value: 'Made available in DSpace on 2012-06-26T19:58:25Z (GMT). No. of bitstreams: 2\r\ntest_ppt.ppt: 12707328 bytes, checksum: a353fc7d29b3c558c986f7463a41efd3 (MD5)\r\ntest_ppt.pptx: 12468572 bytes, checksum: 599305edb4ebee329667f2c35b14d1d6 (MD5)' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T09:17:34Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2013-06-13T11:04:16Z (GMT).' + }, + { + language: 'en', + value: 'Restored into DSpace on 2017-04-24T19:44:08Z (GMT).' + } + ], + 'dc.language': [ + { + language: 'en_US', + value: 'en' + } + ], + 'dc.rights': [ + { + language: 'en_US', + value: '© Jane Doe' + } + ], + 'dc.subject': [ + { + language: 'en_US', + value: 'keyword1' + }, + { + language: 'en_US', + value: 'keyword2' + }, + { + language: 'en_US', + value: 'keyword3' + } + ], + 'dc.title': [ + { + language: 'en_US', + value: 'Test PowerPoint Document' + } + ], + 'dc.type': [ + { + language: 'en_US', + value: 'text' + } + ] + }, owningCollection: observableOf({ self: 'https://dspace7.4science.it/dspace-spring-rest/api/core/collections/1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb', requestPending: false, diff --git a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts index cc72ff3043..66807c6b20 100644 --- a/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/collection-grid-element/collection-grid-element.component.spec.ts @@ -8,21 +8,25 @@ let collectionGridElementComponent: CollectionGridElementComponent; let fixture: ComponentFixture; const mockCollectionWithAbstract: Collection = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - }] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCollectionWithoutAbstract: Collection = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CollectionGridElementComponent', () => { diff --git a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts index dabb137ea7..bb6c81144a 100644 --- a/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/community-grid-element/community-grid-element.component.spec.ts @@ -8,21 +8,25 @@ let communityGridElementComponent: CommunityGridElementComponent; let fixture: ComponentFixture; const mockCommunityWithAbstract: Community = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - }] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCommunityWithoutAbstract: Community = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CommunityGridElementComponent', () => { diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts index f2aa594296..7b286cc415 100644 --- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.spec.ts @@ -11,31 +11,37 @@ let fixture: ComponentFixture; const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.contributor.author', - language: 'en_US', - value: 'Smith, Donald' - }, - { - key: 'dc.date.issued', - language: null, - value: '2015-06-26' - }] + metadata: { + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } }); const mockItemWithoutAuthorAndDate: Item = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'This is just another title' - }, - { - key: 'dc.type', - language: null, - value: 'Article' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ] + } }); describe('ItemGridElementComponent', () => { diff --git a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts index 8e6ff0696f..e8f8b1330e 100644 --- a/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/collection-search-result/collection-search-result-grid-element.component.spec.ts @@ -16,25 +16,29 @@ const truncatableServiceStub: any = { }; const mockCollectionWithAbstract: CollectionSearchResult = new CollectionSearchResult(); -mockCollectionWithAbstract.hitHighlights = []; +mockCollectionWithAbstract.hitHighlights = {}; mockCollectionWithAbstract.dspaceObject = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - } ] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCollectionWithoutAbstract: CollectionSearchResult = new CollectionSearchResult(); -mockCollectionWithoutAbstract.hitHighlights = []; +mockCollectionWithoutAbstract.hitHighlights = {}; mockCollectionWithoutAbstract.dspaceObject = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - } ] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CollectionSearchResultGridElementComponent', () => { diff --git a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts index df8fdf026d..e111e624c5 100644 --- a/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/community-search-result/community-search-result-grid-element.component.spec.ts @@ -16,25 +16,29 @@ const truncatableServiceStub: any = { }; const mockCommunityWithAbstract: CommunitySearchResult = new CommunitySearchResult(); -mockCommunityWithAbstract.hitHighlights = []; +mockCommunityWithAbstract.hitHighlights = {}; mockCommunityWithAbstract.dspaceObject = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - } ] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCommunityWithoutAbstract: CommunitySearchResult = new CommunitySearchResult(); -mockCommunityWithoutAbstract.hitHighlights = []; +mockCommunityWithoutAbstract.hitHighlights = {}; mockCommunityWithoutAbstract.dspaceObject = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - } ] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CommunitySearchResultGridElementComponent', () => { diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts index ecc218f11d..0103fa5c49 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.spec.ts @@ -17,37 +17,43 @@ const truncatableServiceStub: any = { }; const mockItemWithAuthorAndDate: ItemSearchResult = new ItemSearchResult(); -mockItemWithAuthorAndDate.hitHighlights = []; +mockItemWithAuthorAndDate.hitHighlights = {}; mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.contributor.author', - language: 'en_US', - value: 'Smith, Donald' - }, - { - key: 'dc.date.issued', - language: null, - value: '2015-06-26' - }] + metadata: { + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } }); const mockItemWithoutAuthorAndDate: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutAuthorAndDate.hitHighlights = []; +mockItemWithoutAuthorAndDate.hitHighlights = {}; mockItemWithoutAuthorAndDate.dspaceObject = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'This is just another title' - }, - { - key: 'dc.type', - language: null, - value: 'Article' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ] + } }); describe('ItemSearchResultGridElementComponent', () => { diff --git a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts index de53f2e095..54b58e131a 100644 --- a/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts +++ b/src/app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.spec.ts @@ -2,7 +2,6 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { TruncatePipe } from '../../utils/truncate.pipe'; -import { Metadatum } from '../../../core/shared/metadatum.model'; import { BrowseEntryListElementComponent } from './browse-entry-list-element.component'; import { BrowseEntry } from '../../../core/shared/browse-entry.model'; @@ -33,7 +32,7 @@ describe('MetadataListElementComponent', () => { browseEntryListElementComponent = fixture.componentInstance; })); - describe('When the metadatum is loaded', () => { + describe('When the metadata is loaded', () => { beforeEach(() => { browseEntryListElementComponent.object = mockValue; fixture.detectChanges(); diff --git a/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts b/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts index a31af1e50c..bde6b4b97a 100644 --- a/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts +++ b/src/app/shared/object-list/collection-list-element/collection-list-element.component.spec.ts @@ -8,21 +8,25 @@ let collectionListElementComponent: CollectionListElementComponent; let fixture: ComponentFixture; const mockCollectionWithAbstract: Collection = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - }] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCollectionWithoutAbstract: Collection = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CollectionListElementComponent', () => { diff --git a/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts b/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts index 08147d8573..46ba27eb00 100644 --- a/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts +++ b/src/app/shared/object-list/community-list-element/community-list-element.component.spec.ts @@ -8,21 +8,25 @@ let communityListElementComponent: CommunityListElementComponent; let fixture: ComponentFixture; const mockCommunityWithAbstract: Community = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - }] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCommunityWithoutAbstract: Community = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CommunityListElementComponent', () => { diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts index 64108fd5b0..392d81bee4 100644 --- a/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts +++ b/src/app/shared/object-list/item-list-element/item-list-element.component.spec.ts @@ -11,31 +11,37 @@ let fixture: ComponentFixture; const mockItemWithAuthorAndDate: Item = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.contributor.author', - language: 'en_US', - value: 'Smith, Donald' - }, - { - key: 'dc.date.issued', - language: null, - value: '2015-06-26' - }] + metadata: { + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } }); const mockItemWithoutAuthorAndDate: Item = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'This is just another title' - }, - { - key: 'dc.type', - language: null, - value: 'Article' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ] + } }); describe('ItemListElementComponent', () => { diff --git a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts index 2ffaf38b53..e897071a00 100644 --- a/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component.spec.ts @@ -16,25 +16,29 @@ const truncatableServiceStub: any = { }; const mockCollectionWithAbstract: CollectionSearchResult = new CollectionSearchResult(); -mockCollectionWithAbstract.hitHighlights = []; +mockCollectionWithAbstract.hitHighlights = {}; mockCollectionWithAbstract.dspaceObject = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - } ] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCollectionWithoutAbstract: CollectionSearchResult = new CollectionSearchResult(); -mockCollectionWithoutAbstract.hitHighlights = []; +mockCollectionWithoutAbstract.hitHighlights = {}; mockCollectionWithoutAbstract.dspaceObject = Object.assign(new Collection(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - } ] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CollectionSearchResultListElementComponent', () => { diff --git a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts index 70877d0744..75d5966767 100644 --- a/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/community-search-result/community-search-result-list-element.component.spec.ts @@ -16,25 +16,29 @@ const truncatableServiceStub: any = { }; const mockCommunityWithAbstract: CommunitySearchResult = new CommunitySearchResult(); -mockCommunityWithAbstract.hitHighlights = []; +mockCommunityWithAbstract.hitHighlights = {}; mockCommunityWithAbstract.dspaceObject = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.description.abstract', - language: 'en_US', - value: 'Short description' - } ] + metadata: { + 'dc.description.abstract': [ + { + language: 'en_US', + value: 'Short description' + } + ] + } }); const mockCommunityWithoutAbstract: CommunitySearchResult = new CommunitySearchResult(); -mockCommunityWithoutAbstract.hitHighlights = []; +mockCommunityWithoutAbstract.hitHighlights = {}; mockCommunityWithoutAbstract.dspaceObject = Object.assign(new Community(), { - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'Test title' - } ] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'Test title' + } + ] + } }); describe('CommunitySearchResultListElementComponent', () => { diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts index bdc8ebcecf..8567fc1782 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.spec.ts @@ -17,37 +17,43 @@ const truncatableServiceStub: any = { }; const mockItemWithAuthorAndDate: ItemSearchResult = new ItemSearchResult(); -mockItemWithAuthorAndDate.hitHighlights = []; +mockItemWithAuthorAndDate.hitHighlights = {}; mockItemWithAuthorAndDate.dspaceObject = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.contributor.author', - language: 'en_US', - value: 'Smith, Donald' - }, - { - key: 'dc.date.issued', - language: null, - value: '2015-06-26' - }] + metadata: { + 'dc.contributor.author': [ + { + language: 'en_US', + value: 'Smith, Donald' + } + ], + 'dc.date.issued': [ + { + language: null, + value: '2015-06-26' + } + ] + } }); const mockItemWithoutAuthorAndDate: ItemSearchResult = new ItemSearchResult(); -mockItemWithoutAuthorAndDate.hitHighlights = []; +mockItemWithoutAuthorAndDate.hitHighlights = {}; mockItemWithoutAuthorAndDate.dspaceObject = Object.assign(new Item(), { bitstreams: observableOf({}), - metadata: [ - { - key: 'dc.title', - language: 'en_US', - value: 'This is just another title' - }, - { - key: 'dc.type', - language: null, - value: 'Article' - }] + metadata: { + 'dc.title': [ + { + language: 'en_US', + value: 'This is just another title' + } + ], + 'dc.type': [ + { + language: null, + value: 'Article' + } + ] + } }); describe('ItemSearchResultListElementComponent', () => { diff --git a/src/app/shared/search-form/search-form.component.spec.ts b/src/app/shared/search-form/search-form.component.spec.ts index 004d0c5b21..b164abee1f 100644 --- a/src/app/shared/search-form/search-form.component.spec.ts +++ b/src/app/shared/search-form/search-form.component.spec.ts @@ -30,6 +30,7 @@ describe('SearchFormComponent', () => { }); it('should display scopes when available with default and all scopes', () => { + comp.scopes = objects; fixture.detectChanges(); const select: HTMLElement = de.query(By.css('select')).nativeElement; @@ -121,33 +122,38 @@ export const objects: DSpaceObject[] = [ id: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', uuid: '7669c72a-3f2a-451f-a3b9-9210e7a4c02f', type: ResourceType.Community, - metadata: [ - { - key: 'dc.description', - language: null, - value: '' - }, - { - key: 'dc.description.abstract', - language: null, - value: 'This is a test community to hold content for the OR2017 demostration' - }, - { - key: 'dc.description.tableofcontents', - language: null, - value: '' - }, - { - key: 'dc.rights', - language: null, - value: '' - }, - { - key: 'dc.title', - language: null, - value: 'OR2017 - Demonstration' - } - ] + metadata: { + 'dc.description': [ + { + language: null, + value: '' + } + ], + 'dc.description.abstract': [ + { + language: null, + value: 'This is a test community to hold content for the OR2017 demostration' + } + ], + 'dc.description.tableofcontents': [ + { + language: null, + value: '' + } + ], + 'dc.rights': [ + { + language: null, + value: '' + } + ], + 'dc.title': [ + { + language: null, + value: 'OR2017 - Demonstration' + } + ] + } }), Object.assign(new Community(), { @@ -170,33 +176,38 @@ export const objects: DSpaceObject[] = [ id: '9076bd16-e69a-48d6-9e41-0238cb40d863', uuid: '9076bd16-e69a-48d6-9e41-0238cb40d863', type: ResourceType.Community, - metadata: [ - { - key: 'dc.description', - language: null, - value: '

This is the introductory text for the Sample Community on the DSpace Demonstration Site. It is editable by System or Community Administrators (of this Community).

\r\n

DSpace Communities may contain one or more Sub-Communities or Collections (of Items).

\r\n

This particular Community has its own logo (the DuraSpace logo).

' - }, - { - key: 'dc.description.abstract', - language: null, - value: 'This is a sample top-level community' - }, - { - key: 'dc.description.tableofcontents', - language: null, - value: '

This is the news section for this Sample Community. System or Community Administrators (of this Community) can edit this News field.

' - }, - { - key: 'dc.rights', - language: null, - value: '

If this Community had special copyright text to display, it would be displayed here.

' - }, - { - key: 'dc.title', - language: null, - value: 'Sample Community' - } - ] + metadata: { + 'dc.description': [ + { + language: null, + value: '

This is the introductory text for the Sample Community on the DSpace Demonstration Site. It is editable by System or Community Administrators (of this Community).

\r\n

DSpace Communities may contain one or more Sub-Communities or Collections (of Items).

\r\n

This particular Community has its own logo (the DuraSpace logo).

' + } + ], + 'dc.description.abstract': [ + { + language: null, + value: 'This is a sample top-level community' + } + ], + 'dc.description.tableofcontents': [ + { + language: null, + value: '

This is the news section for this Sample Community. System or Community Administrators (of this Community) can edit this News field.

' + } + ], + 'dc.rights': [ + { + language: null, + value: '

If this Community had special copyright text to display, it would be displayed here.

' + } + ], + 'dc.title': [ + { + language: null, + value: 'Sample Community' + } + ] + } } ) ]; From 6474cbfafbf9a5859ad22eae474fd343feda8cc4 Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Sat, 22 Dec 2018 23:08:00 -0500 Subject: [PATCH 3/6] DS-4107 Add tests for Metadata utility methods --- src/app/core/shared/metadata.model.spec.ts | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/app/core/shared/metadata.model.spec.ts diff --git a/src/app/core/shared/metadata.model.spec.ts b/src/app/core/shared/metadata.model.spec.ts new file mode 100644 index 0000000000..8f44dee5fd --- /dev/null +++ b/src/app/core/shared/metadata.model.spec.ts @@ -0,0 +1,174 @@ +import { MetadataValue, MetadataValueFilter } from './metadata.interfaces'; +import { Metadata } from './metadata.model'; + +const mdValue = (value: string, language?: string): MetadataValue => { + return { value: value, language: language === undefined ? null : language }; +} + +const dcDescription = mdValue('Some description'); +const dcAbstract = mdValue('Some abstract'); +const dcTitle0 = mdValue('Title 0'); +const dcTitle1 = mdValue('Title 1'); +const dcTitle2 = mdValue('Title 2', 'en_US'); +const bar = mdValue('Bar'); + +const singleMap = { 'dc.title': [ dcTitle0 ] }; + +const multiMap = { + 'dc.description': [ dcDescription ], + 'dc.description.abstract': [ dcAbstract ], + 'dc.title': [ dcTitle1, dcTitle2 ], + 'foo': [ bar ] +}; + +const testMethod = (fn, resultKind, mapOrMaps, keyOrKeys, expected, filter?) => { + const keys = keyOrKeys instanceof Array ? keyOrKeys : [ keyOrKeys ]; + describe('and key' + (keys.length === 1 ? (' ' + keys[0]) : ('s ' + JSON.stringify(keys))) + + ' with ' + (filter === undefined ? 'no filter' : 'filter ' + JSON.stringify(filter)), () => { + const result = fn(mapOrMaps, keys, filter); + let shouldReturn; + if (resultKind === 'boolean') { + shouldReturn = expected; + } else if (expected === undefined) { + shouldReturn = 'undefined'; + } else if (expected instanceof Array) { + shouldReturn = 'an array with ' + expected.length + ' ' + (expected.length > 1 ? 'ordered ' : '') + + resultKind + (expected.length !== 1 ? 's' : ''); + } else { + shouldReturn = 'a ' + resultKind; + } + it('should return ' + shouldReturn, () => { + expect(result).toEqual(expected); + }); + }) +}; + +describe('Metadata', () => { + + describe('all method', () => { + + const testAll = (mapOrMaps, keyOrKeys, expected, filter?: MetadataValueFilter) => + testMethod(Metadata.all, 'value', mapOrMaps, keyOrKeys, expected, filter); + + describe('with emptyMap', () => { + testAll({}, 'foo', []); + testAll({}, '*', []); + }); + describe('with singleMap', () => { + testAll(singleMap, 'foo', []); + testAll(singleMap, '*', [ dcTitle0 ]); + testAll(singleMap, '*', [], { value: 'baz' }); + testAll(singleMap, 'dc.title', [ dcTitle0 ]); + testAll(singleMap, 'dc.*', [ dcTitle0 ]); + }); + describe('with multiMap', () => { + testAll(multiMap, 'foo', [ bar ]); + testAll(multiMap, '*', [ dcDescription, dcAbstract, dcTitle1, dcTitle2, bar ]); + testAll(multiMap, 'dc.title', [ dcTitle1, dcTitle2 ]); + testAll(multiMap, 'dc.*', [ dcDescription, dcAbstract, dcTitle1, dcTitle2 ]); + testAll(multiMap, [ 'dc.title', 'dc.*' ], [ dcTitle1, dcTitle2, dcDescription, dcAbstract ]); + }); + describe('with [ singleMap, multiMap ]', () => { + testAll([ singleMap, multiMap ], 'foo', [ bar ]); + testAll([ singleMap, multiMap ], '*', [ dcTitle0 ]); + testAll([ singleMap, multiMap ], 'dc.title', [ dcTitle0 ]); + testAll([ singleMap, multiMap ], 'dc.*', [ dcTitle0 ]); + }); + describe('with [ multiMap, singleMap ]', () => { + testAll([ multiMap, singleMap ], 'foo', [ bar ]); + testAll([ multiMap, singleMap ], '*', [ dcDescription, dcAbstract, dcTitle1, dcTitle2, bar ]); + testAll([ multiMap, singleMap ], 'dc.title', [ dcTitle1, dcTitle2 ]); + testAll([ multiMap, singleMap ], 'dc.*', [ dcDescription, dcAbstract, dcTitle1, dcTitle2 ]); + testAll([ multiMap, singleMap ], [ 'dc.title', 'dc.*' ], [ dcTitle1, dcTitle2, dcDescription, dcAbstract ]); + }); + }); + + describe('allValues method', () => { + + const testAllValues = (mapOrMaps, keyOrKeys, expected) => + testMethod(Metadata.allValues, 'string', mapOrMaps, keyOrKeys, expected); + + describe('with emptyMap', () => { + testAllValues({}, '*', []); + }); + describe('with singleMap', () => { + testAllValues([ singleMap, multiMap ], '*', [ dcTitle0.value ]); + }); + describe('with [ multiMap, singleMap ]', () => { + testAllValues([ multiMap, singleMap ], '*', [ dcDescription.value, dcAbstract.value, dcTitle1.value, dcTitle2.value, bar.value ]); + }); + }); + + describe('first method', () => { + + const testFirst = (mapOrMaps, keyOrKeys, expected) => + testMethod(Metadata.first, 'value', mapOrMaps, keyOrKeys, expected); + + describe('with emptyMap', () => { + testFirst({}, '*', undefined); + }); + describe('with singleMap', () => { + testFirst(singleMap, '*', dcTitle0); + }); + describe('with [ multiMap, singleMap ]', () => { + testFirst([ multiMap, singleMap ], '*', dcDescription); + }); + }); + + describe('firstValue method', () => { + + const testFirstValue = (mapOrMaps, keyOrKeys, expected) => + testMethod(Metadata.firstValue, 'value', mapOrMaps, keyOrKeys, expected); + + describe('with emptyMap', () => { + testFirstValue({}, '*', undefined); + }); + describe('with singleMap', () => { + testFirstValue(singleMap, '*', dcTitle0.value); + }); + describe('with [ multiMap, singleMap ]', () => { + testFirstValue([ multiMap, singleMap ], '*', dcDescription.value); + }); + }); + + describe('has method', () => { + + const testHas = (mapOrMaps, keyOrKeys, expected, filter?: MetadataValueFilter) => + testMethod(Metadata.has, 'boolean', mapOrMaps, keyOrKeys, expected, filter); + + describe('with emptyMap', () => { + testHas({}, '*', false); + }); + describe('with singleMap', () => { + testHas(singleMap, '*', true); + testHas(singleMap, '*', false, { value: 'baz' }); + }); + describe('with [ multiMap, singleMap ]', () => { + testHas([ multiMap, singleMap ], '*', true); + }); + }); + + describe('valueMatches method', () => { + + const testValueMatches = (value: MetadataValue, expected: boolean, filter?: MetadataValueFilter) => { + describe('with value ' + JSON.stringify(value) + ' and filter ' + + (filter === undefined ? 'undefined' : JSON.stringify(filter)), () => { + const result = Metadata.valueMatches(value, filter); + it('should return ' + expected, () => { + expect(result).toEqual(expected); + }); + }); + }; + + testValueMatches(mdValue('a'), true); + testValueMatches(mdValue('a'), true, { value: 'a' }); + testValueMatches(mdValue('a'), false, { value: 'A' }); + testValueMatches(mdValue('a'), true, { value: 'A', ignoreCase: true }); + testValueMatches(mdValue('ab'), false, { value: 'b' }); + testValueMatches(mdValue('ab'), true, { value: 'b', substring: true }); + testValueMatches(mdValue('a'), true, { language: null }); + testValueMatches(mdValue('a'), false, { language: 'en_US' }); + testValueMatches(mdValue('a', 'en_US'), true, { language: 'en_US' }); + }); + +}); From 4c8747a3455026b9ec363a7935d26e99d6e78b4c Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Thu, 14 Feb 2019 14:46:27 -0500 Subject: [PATCH 4/6] DS-4107 Improve TypeDocs --- src/app/core/browse/browse.service.ts | 3 + src/app/core/shared/dspace-object.model.ts | 40 ++++++++-- src/app/core/shared/metadata.model.ts | 80 ++++++++++++++----- .../search-result-grid-element.component.ts | 14 +++- .../search-result-list-element.component.ts | 14 +++- 5 files changed, 124 insertions(+), 27 deletions(-) diff --git a/src/app/core/browse/browse.service.ts b/src/app/core/browse/browse.service.ts index 41675632dd..f0d8935b5c 100644 --- a/src/app/core/browse/browse.service.ts +++ b/src/app/core/browse/browse.service.ts @@ -34,6 +34,9 @@ import { URLCombiner } from '../url-combiner/url-combiner'; import { Item } from '../shared/item.model'; import { DSpaceObject } from '../shared/dspace-object.model'; +/** + * Service that performs all actions that have to do with browse. + */ @Injectable() export class BrowseService { protected linkPath = 'browses'; diff --git a/src/app/core/shared/dspace-object.model.ts b/src/app/core/shared/dspace-object.model.ts index 1dba79865f..edd82eca85 100644 --- a/src/app/core/shared/dspace-object.model.ts +++ b/src/app/core/shared/dspace-object.model.ts @@ -54,27 +54,57 @@ export class DSpaceObject implements CacheableObject, ListableObject { */ owner: Observable>; - /** Gets all matching metadata in this DSpaceObject. See `Metadata.all` for more information. */ + /** + * Gets all matching metadata in this DSpaceObject. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {MetadataValue[]} the matching values or an empty array. + */ allMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): MetadataValue[] { return Metadata.all(this.metadata, keyOrKeys, valueFilter); } - /** Like `allMetadata`, but only returns string values. */ + /** + * Like [[allMetadata]], but only returns string values. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {string[]} the matching string values or an empty array. + */ allMetadataValues(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string[] { return Metadata.allValues(this.metadata, keyOrKeys, valueFilter); } - /** Gets the first matching metadata in this DSpaceObject, or `undefined`. */ + /** + * Gets the first matching MetadataValue object in this DSpaceObject, or `undefined`. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {MetadataValue} the first matching value, or `undefined`. + */ firstMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): MetadataValue { return Metadata.first(this.metadata, keyOrKeys, valueFilter); } - /** Like `firstMetadata`, but only returns a string value, or `undefined`. */ + /** + * Like [[firstMetadata]], but only returns a string value, or `undefined`. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {string} the first matching string value, or `undefined`. + */ firstMetadataValue(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): string { return Metadata.firstValue(this.metadata, keyOrKeys, valueFilter); } - /** Checks for matching metadata in this DSpaceObject. */ + /** + * Checks for a matching metadata value in this DSpaceObject. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {boolean} whether a match is found. + */ hasMetadata(keyOrKeys: string | string[], valueFilter?: MetadataValueFilter): boolean { return Metadata.has(this.metadata, keyOrKeys, valueFilter); } diff --git a/src/app/core/shared/metadata.model.ts b/src/app/core/shared/metadata.model.ts index c774af189b..c64827ffdb 100644 --- a/src/app/core/shared/metadata.model.ts +++ b/src/app/core/shared/metadata.model.ts @@ -2,23 +2,27 @@ import { isEmpty } from '../../shared/empty.util'; import { MetadataMap, MetadataValue, MetadataValueFilter } from './metadata.interfaces'; /** - * Static utility methods for working with DSpace metadata. + * Utility class for working with DSpace object metadata. + * + * When specifying metadata keys, wildcards are supported, so `'*'` will match all keys, `'dc.date.*'` will + * match all qualified dc dates, and so on. Exact keys will be evaluated (and matches returned) in the order + * they are given. + * + * When multiple keys in a map match a given wildcard, they are evaluated in the order they are stored in + * the map (alphanumeric if obtained from the REST api). If duplicate or overlapping keys are specified, the + * first one takes precedence. For example, specifying `['dc.date', 'dc.*', '*']` will cause any `dc.date` + * values to be evaluated (and returned, if matched) first, followed by any other `dc` metadata values, + * followed by any other (non-dc) metadata values. */ export class Metadata { /** - * Gets all matching metadata. + * Gets all matching metadata in the map(s). * - * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). Values will only be returned from one map -- - * the first with at least one match. - * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported, so `'*'` will - * match all keys, `'dc.date.*'` will match all qualified dc dates, and so on. Exact keys will be evaluated - * (and matches returned) in the order they are given in the parameter. When multiple keys match a wildcard, - * they are evaluated in the order they are stored in the map (alphanumeric if obtained from the REST api). - * If duplicate or overlapping keys are specified, the first one takes precedence. For example, specifying - * `['dc.date', 'dc.*', '*']` will cause any `dc.date` values to be evaluated (and returned, if matched) - * first, followed by any other `dc` metadata values, followed by any other (non-dc) metadata values. - * @param {MetadataValueFilter} filter The value filter to use. + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). When multiple maps are given, they will be + * checked in order, and only values from the first with at least one match will be returned. + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. * @returns {MetadataValue[]} the matching values or an empty array. */ public static all(mapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], @@ -43,13 +47,28 @@ export class Metadata { return matches; } - /** Like `all`, but only returns string values. */ + /** + * Like [[Metadata.all]], but only returns string values. + * + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). When multiple maps are given, they will be + * checked in order, and only values from the first with at least one match will be returned. + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {string[]} the matching string values or an empty array. + */ public static allValues(mapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): string[] { return Metadata.all(mapOrMaps, keyOrKeys, filter).map((mdValue) => mdValue.value); } - /** Gets the first matching MetadataValue object in a map, or `undefined`. */ + /** + * Gets the first matching MetadataValue object in the map(s), or `undefined`. + * + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {MetadataValue} the first matching value, or `undefined`. + */ public static first(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): MetadataValue { const mdMaps: MetadataMap[] = mdMapOrMaps instanceof Array ? mdMapOrMaps : [ mdMapOrMaps ]; @@ -63,20 +82,40 @@ export class Metadata { } } - /** Like `first`, but only returns a string value, or `undefined`. */ + /** + * Like [[Metadata.first]], but only returns a string value, or `undefined`. + * + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {string} the first matching string value, or `undefined`. + */ public static firstValue(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): string { const value = Metadata.first(mdMapOrMaps, keyOrKeys, filter); return value === undefined ? undefined : value.value; } - /** Checks the given map for a matching value. */ + /** + * Checks for a matching metadata value in the given map(s). + * + * @param {MetadataMap|MetadataMap[]} mapOrMaps The source map(s). + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + * @param {MetadataValueFilter} filter The value filter to use. If unspecified, no filtering will be done. + * @returns {boolean} whether a match is found. + */ public static has(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): boolean { return Metadata.first(mdMapOrMaps, keyOrKeys, filter) !== undefined; } - /** Checks if a value matches a filter. */ + /** + * Checks if a value matches a filter. + * + * @param {MetadataValue} mdValue the value to check. + * @param {MetadataValueFilter} filter the filter to use. + * @returns {boolean} whether the filter matches, or true if no filter is given. + */ public static valueMatches(mdValue: MetadataValue, filter: MetadataValueFilter) { if (!filter) { return true; @@ -98,7 +137,12 @@ export class Metadata { return true; } - /** Gets the list of keys in the map limited by, and in the order given by `keyOrKeys` */ + /** + * Gets the list of keys in the map limited by, and in the order given by `keyOrKeys`. + * + * @param {MetadataMap} mdMap The source map. + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see above. + */ private static resolveKeys(mdMap: MetadataMap, keyOrKeys: string | string[]): string[] { const inputKeys: string[] = keyOrKeys instanceof Array ? keyOrKeys : [ keyOrKeys ]; const outputKeys: string[] = []; diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts index c3a80604db..0901b7b8cc 100644 --- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts +++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts @@ -21,12 +21,22 @@ export class SearchResultGridElementComponent, K exten this.dso = this.object.dspaceObject; } - /** Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. */ + /** + * Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @returns {string[]} the matching string values or an empty array. + */ allMetadataValues(keyOrKeys: string | string[]): string[] { return Metadata.allValues([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } - /** Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. */ + /** + * Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @returns {string} the first matching string value, or `undefined`. + */ firstMetadataValue(keyOrKeys: string | string[]): string { return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } diff --git a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts index a9a3050ac8..2a16b0b754 100644 --- a/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts +++ b/src/app/shared/object-list/search-result-list-element/search-result-list-element.component.ts @@ -21,12 +21,22 @@ export class SearchResultListElementComponent, K exten this.dso = this.object.dspaceObject; } - /** Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. */ + /** + * Gets all matching metadata string values from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @returns {string[]} the matching string values or an empty array. + */ allMetadataValues(keyOrKeys: string | string[]): string[] { return Metadata.allValues([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } - /** Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. */ + /** + * Gets the first matching metadata string value from hitHighlights or dso metadata, preferring hitHighlights. + * + * @param {string|string[]} keyOrKeys The metadata key(s) in scope. Wildcards are supported; see [[Metadata]]. + * @returns {string} the first matching string value, or `undefined`. + */ firstMetadataValue(keyOrKeys: string | string[]): string { return Metadata.firstValue([this.object.hitHighlights, this.dso.metadata], keyOrKeys); } From e499f792e87b26ace299fecc3f0e501843062778 Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Thu, 14 Feb 2019 14:52:43 -0500 Subject: [PATCH 5/6] DS-4107 Use isUndefined and isNotUndefined where appropriate --- src/app/core/shared/metadata.model.spec.ts | 9 +++++---- src/app/core/shared/metadata.model.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app/core/shared/metadata.model.spec.ts b/src/app/core/shared/metadata.model.spec.ts index 8f44dee5fd..dfeff8d600 100644 --- a/src/app/core/shared/metadata.model.spec.ts +++ b/src/app/core/shared/metadata.model.spec.ts @@ -1,8 +1,9 @@ +import { isUndefined } from '../../shared/empty.util'; import { MetadataValue, MetadataValueFilter } from './metadata.interfaces'; import { Metadata } from './metadata.model'; const mdValue = (value: string, language?: string): MetadataValue => { - return { value: value, language: language === undefined ? null : language }; + return { value: value, language: isUndefined(language) ? null : language }; } const dcDescription = mdValue('Some description'); @@ -24,12 +25,12 @@ const multiMap = { const testMethod = (fn, resultKind, mapOrMaps, keyOrKeys, expected, filter?) => { const keys = keyOrKeys instanceof Array ? keyOrKeys : [ keyOrKeys ]; describe('and key' + (keys.length === 1 ? (' ' + keys[0]) : ('s ' + JSON.stringify(keys))) - + ' with ' + (filter === undefined ? 'no filter' : 'filter ' + JSON.stringify(filter)), () => { + + ' with ' + (isUndefined(filter) ? 'no filter' : 'filter ' + JSON.stringify(filter)), () => { const result = fn(mapOrMaps, keys, filter); let shouldReturn; if (resultKind === 'boolean') { shouldReturn = expected; - } else if (expected === undefined) { + } else if (isUndefined(expected)) { shouldReturn = 'undefined'; } else if (expected instanceof Array) { shouldReturn = 'an array with ' + expected.length + ' ' + (expected.length > 1 ? 'ordered ' : '') @@ -152,7 +153,7 @@ describe('Metadata', () => { const testValueMatches = (value: MetadataValue, expected: boolean, filter?: MetadataValueFilter) => { describe('with value ' + JSON.stringify(value) + ' and filter ' - + (filter === undefined ? 'undefined' : JSON.stringify(filter)), () => { + + (isUndefined(filter) ? 'undefined' : JSON.stringify(filter)), () => { const result = Metadata.valueMatches(value, filter); it('should return ' + expected, () => { expect(result).toEqual(expected); diff --git a/src/app/core/shared/metadata.model.ts b/src/app/core/shared/metadata.model.ts index c64827ffdb..2b29659252 100644 --- a/src/app/core/shared/metadata.model.ts +++ b/src/app/core/shared/metadata.model.ts @@ -1,4 +1,4 @@ -import { isEmpty } from '../../shared/empty.util'; +import { isEmpty, isNotUndefined, isUndefined } from '../../shared/empty.util'; import { MetadataMap, MetadataValue, MetadataValueFilter } from './metadata.interfaces'; /** @@ -93,7 +93,7 @@ export class Metadata { public static firstValue(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): string { const value = Metadata.first(mdMapOrMaps, keyOrKeys, filter); - return value === undefined ? undefined : value.value; + return isUndefined(value) ? undefined : value.value; } /** @@ -106,7 +106,7 @@ export class Metadata { */ public static has(mdMapOrMaps: MetadataMap | MetadataMap[], keyOrKeys: string | string[], filter?: MetadataValueFilter): boolean { - return Metadata.first(mdMapOrMaps, keyOrKeys, filter) !== undefined; + return isNotUndefined(Metadata.first(mdMapOrMaps, keyOrKeys, filter)); } /** From c2c59cd85a63b63ce0db91c3e9959e85a60f4cff Mon Sep 17 00:00:00 2001 From: Chris Wilper Date: Wed, 20 Feb 2019 16:36:09 -0500 Subject: [PATCH 6/6] DS-4107 Improve variable naming --- .../modify-item-overview.component.html | 10 +++++----- .../metadata-uri-values.component.html | 4 ++-- .../metadata-uri-values.component.ts | 2 +- .../metadata-values/metadata-values.component.html | 4 ++-- .../metadata-values/metadata-values.component.ts | 2 +- src/app/+item-page/full/full-item-page.component.html | 10 +++++----- .../item-page-specific-field.component.html | 2 +- .../title/item-page-title-field.component.html | 2 +- .../uri/item-page-uri-field.component.html | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html index 861c20ada7..ce6e01df3d 100644 --- a/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html +++ b/src/app/+item-page/edit-item-page/modify-item-overview/modify-item-overview.component.html @@ -7,11 +7,11 @@ - - - {{entry.key}} - {{value.value}} - {{value.language}} + + + {{mdEntry.key}} + {{mdValue.value}} + {{mdValue.language}} diff --git a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html index 344a32841b..b5d7c118dd 100644 --- a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html +++ b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.html @@ -1,5 +1,5 @@ - - {{ linktext || value.value }} + + {{ linktext || mdValue.value }} diff --git a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts index b5870f16b8..09d855e951 100644 --- a/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts +++ b/src/app/+item-page/field-components/metadata-uri-values/metadata-uri-values.component.ts @@ -19,7 +19,7 @@ export class MetadataUriValuesComponent extends MetadataValuesComponent { @Input() linktext: any; - @Input() values: MetadataValue[]; + @Input() mdValues: MetadataValue[]; @Input() separator: string; diff --git a/src/app/+item-page/field-components/metadata-values/metadata-values.component.html b/src/app/+item-page/field-components/metadata-values/metadata-values.component.html index fbc1e11a07..980c940255 100644 --- a/src/app/+item-page/field-components/metadata-values/metadata-values.component.html +++ b/src/app/+item-page/field-components/metadata-values/metadata-values.component.html @@ -1,5 +1,5 @@ - - {{value.value}} + + {{mdValue.value}} diff --git a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts index 2be7291dcd..708bdb49c7 100644 --- a/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts +++ b/src/app/+item-page/field-components/metadata-values/metadata-values.component.ts @@ -12,7 +12,7 @@ import { MetadataValue } from '../../../core/shared/metadata.interfaces'; }) export class MetadataValuesComponent { - @Input() values: MetadataValue[]; + @Input() mdValues: MetadataValue[]; @Input() separator: string; diff --git a/src/app/+item-page/full/full-item-page.component.html b/src/app/+item-page/full/full-item-page.component.html index 7080ba2e96..7aec57da0c 100644 --- a/src/app/+item-page/full/full-item-page.component.html +++ b/src/app/+item-page/full/full-item-page.component.html @@ -9,11 +9,11 @@
- - - - - + + + + + diff --git a/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html b/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html index c0d948fc76..d6a569198c 100644 --- a/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/item-page-specific-field.component.html @@ -1,3 +1,3 @@
- +
diff --git a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html index 40f54ec636..aac85d335f 100644 --- a/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/title/item-page-title-field.component.html @@ -1,3 +1,3 @@

- +

diff --git a/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html b/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html index 771fef53fc..a5561b22e5 100644 --- a/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html +++ b/src/app/+item-page/simple/field-components/specific-field/uri/item-page-uri-field.component.html @@ -1,3 +1,3 @@
- +
{{entry.key}}{{value.value}}{{value.language}}
{{mdEntry.key}}{{mdValue.value}}{{mdValue.language}}