From 1f4ae7a0352e92d1cacd6772f5d6d83aba6ba7cc Mon Sep 17 00:00:00 2001 From: Marie Verdonck Date: Mon, 27 Jul 2020 14:43:41 +0200 Subject: [PATCH] 71894: refactor with new operator metadataFieldsToString instead of schemaResolved --- .../edit-in-place-field.component.spec.ts | 40 ++++++++------- .../edit-in-place-field.component.ts | 49 +++++-------------- src/app/core/metadata/metadata-field.model.ts | 24 --------- src/app/core/shared/operators.ts | 30 +++++++++++- 4 files changed, 62 insertions(+), 81 deletions(-) diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts index e4040e34fb..b89a0a846c 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts +++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.spec.ts @@ -1,5 +1,5 @@ import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { TranslateModule } from '@ngx-translate/core'; @@ -16,7 +16,10 @@ import { RegistryService } from '../../../../core/registry/registry.service'; import { MetadatumViewModel } from '../../../../core/shared/metadata.models'; import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { SharedModule } from '../../../../shared/shared.module'; -import { createSuccessfulRemoteDataObject$ } from '../../../../shared/remote-data.utils'; +import { + createSuccessfulRemoteDataObject, + createSuccessfulRemoteDataObject$ +} from '../../../../shared/remote-data.utils'; import { followLink } from '../../../../shared/utils/follow-link-config.model'; import { EditInPlaceFieldComponent } from './edit-in-place-field.component'; @@ -27,22 +30,21 @@ let el: HTMLElement; let metadataFieldService; let objectUpdatesService; let paginatedMetadataFields; -const mdSchema = Object.assign(new MetadataSchema(), { prefix: 'dc' }) +const mdSchema = Object.assign(new MetadataSchema(), { prefix: 'dc' }); +const mdSchemaRD$ = createSuccessfulRemoteDataObject$(mdSchema); const mdField1 = Object.assign(new MetadataField(), { - schema: mdSchema, + schema: mdSchemaRD$, element: 'contributor', - qualifier: 'author', - schemaResolved: mdSchema, + qualifier: 'author' }); const mdField2 = Object.assign(new MetadataField(), { - schema: mdSchema, - element: 'title', - schemaResolved: mdSchema, }); + schema: mdSchemaRD$, + element: 'title' +}); const mdField3 = Object.assign(new MetadataField(), { - schema: mdSchema, + schema: mdSchemaRD$, element: 'description', qualifier: 'abstract', - schemaResolved: mdSchema, }); const metadatum = Object.assign(new MetadatumViewModel(), { @@ -58,7 +60,7 @@ const fieldUpdate = { }; let scheduler: TestScheduler; -describe('EditInPlaceFieldComponent', () => { +fdescribe('EditInPlaceFieldComponent', () => { beforeEach(async(() => { scheduler = getTestScheduler(); @@ -200,18 +202,18 @@ describe('EditInPlaceFieldComponent', () => { const metadataFieldSuggestions: InputSuggestion[] = [ - { displayValue: (mdField1.schemaResolved.prefix + '.' + mdField1.toString()).split('.').join('.​'), value: (mdField1.schemaResolved.prefix + '.' + mdField1.toString()) }, - { displayValue: (mdField2.schemaResolved.prefix + '.' + mdField2.toString()).split('.').join('.​'), value: (mdField2.schemaResolved.prefix + '.' + mdField2.toString()) }, - { displayValue: (mdField3.schemaResolved.prefix + '.' + mdField3.toString()).split('.').join('.​'), value: (mdField3.schemaResolved.prefix + '.' + mdField3.toString()) } + { displayValue: ('dc.' + mdField1.toString()).split('.').join('.​'), value: ('dc.' + mdField1.toString()) }, + { displayValue: ('dc.' + mdField2.toString()).split('.').join('.​'), value: ('dc.' + mdField2.toString()) }, + { displayValue: ('dc.' + mdField3.toString()).split('.').join('.​'), value: ('dc.' + mdField3.toString()) } ]; - beforeEach(() => { + beforeEach(fakeAsync(() => { comp.findMetadataFieldSuggestions(query); - - }); + tick(); + fixture.detectChanges(); + })); it('it should call queryMetadataFields on the metadataFieldService with the correct query', () => { - expect(metadataFieldService.queryMetadataFields).toHaveBeenCalledWith(query, null, followLink('schema')); }); diff --git a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts index 3dd5e2091d..7218ae10b0 100644 --- a/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts +++ b/src/app/+item-page/edit-item-page/item-metadata/edit-in-place-field/edit-in-place-field.component.ts @@ -1,17 +1,15 @@ import { Component, Input, OnChanges, OnInit } from '@angular/core'; -import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model'; -import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators'; +import { metadataFieldsToString } from '../../../../core/shared/operators'; import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { RegistryService } from '../../../../core/registry/registry.service'; import { cloneDeep } from 'lodash'; import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; -import { map, switchMap, take } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; import { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions'; import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { NgModel } from '@angular/forms'; import { MetadatumViewModel } from '../../../../core/shared/metadata.models'; -import { MetadataField } from '../../../../core/metadata/metadata-field.model'; import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { followLink } from '../../../../shared/utils/follow-link-config.model'; @@ -124,34 +122,14 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges { * Ignores fields from metadata schemas "relation" and "relationship" * @param query The query to look for */ - findMetadataFieldSuggestions(query: string): void { + findMetadataFieldSuggestions(query: string) { if (isNotEmpty(query)) { - this.registryService.queryMetadataFields(query, null, followLink('schema')).pipe( - getSucceededRemoteData(), - take(1), - map((data) => data.payload.page), - switchMap((fields: MetadataField[]) => { - return fields.map((field: MetadataField, index: number) => { - // Resolve the metadata field's schema if not already the case, to be able to form complete MD field name - if (!hasValue(field.schemaResolved)) { - field.schema.pipe( - getSucceededRemoteData(), - getRemoteDataPayload(), - map((schema: MetadataSchema) => { - field.schemaResolved = schema; - if (index == fields.length - 1) { - this.setInputSuggestions(fields); - } - }), - take(1) - ).subscribe() - } else { - this.setInputSuggestions(fields); - } - }); - } - ), - take(1)).subscribe(); + return this.registryService.queryMetadataFields(query, null, followLink('schema')).pipe( + metadataFieldsToString(), + take(1)) + .subscribe((fieldNames: string[]) => { + this.setInputSuggestions(fieldNames); + }) } else { this.metadataFieldSuggestions.next([]); } @@ -161,13 +139,12 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges { * Set the list of input suggestion with the given Metadata fields, which all require a resolved MetadataSchema * @param fields list of Metadata fields, which all require a resolved MetadataSchema */ - setInputSuggestions(fields: MetadataField[]) { + setInputSuggestions(fields: string[]) { this.metadataFieldSuggestions.next( - fields.map((field: MetadataField) => { - const fieldNameWhole = field.schemaResolved.prefix + '.' + field.toString(); + fields.map((fieldName: string) => { return { - displayValue: fieldNameWhole.split('.').join('.​'), - value: fieldNameWhole + displayValue: fieldName.split('.').join('.​'), + value: fieldName }; }) ); diff --git a/src/app/core/metadata/metadata-field.model.ts b/src/app/core/metadata/metadata-field.model.ts index 41dfa784a4..a24d1864ac 100644 --- a/src/app/core/metadata/metadata-field.model.ts +++ b/src/app/core/metadata/metadata-field.model.ts @@ -70,8 +70,6 @@ export class MetadataField extends ListableObject implements HALResource { @link(METADATA_SCHEMA) schema?: Observable>; - schemaResolved?: MetadataSchema; - /** * Method to print this metadata field as a string without the schema * @param separator The separator between element and qualifier in the string @@ -84,28 +82,6 @@ export class MetadataField extends ListableObject implements HALResource { return key; } - /** - * Method to print this metadata field as a string - * @param separator The separator between the schema, element and qualifier in the string - */ - toStringWithSchema(separator: string = '.', schemaService: MetadataSchemaDataService): Observable { - let schemaObject: Observable> = this.schema; - if (!hasValue(this.schema)) { - schemaObject = schemaService.findByHref(this._links.schema.href); - } - return schemaObject.pipe( - getSucceededRemoteData(), - getRemoteDataPayload(), - map((schemaPayload: MetadataSchema) => { - let key = this.element; - if (isNotEmpty(this.qualifier)) { - key += separator + this.qualifier; - } - return schemaPayload.namespace + separator + key; - }) - ) - } - /** * Method that returns as which type of object this object should be rendered */ diff --git a/src/app/core/shared/operators.ts b/src/app/core/shared/operators.ts index b8120d4765..0afd1d97b1 100644 --- a/src/app/core/shared/operators.ts +++ b/src/app/core/shared/operators.ts @@ -1,6 +1,6 @@ import { Router, UrlTree } from '@angular/router'; -import { Observable } from 'rxjs'; -import { filter, find, flatMap, map, take, tap } from 'rxjs/operators'; +import { Observable, combineLatest as observableCombineLatest } from 'rxjs'; +import { filter, find, flatMap, map, switchMap, take, tap } from 'rxjs/operators'; import { hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util'; import { SearchResult } from '../../shared/search/search-result.model'; import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; @@ -9,6 +9,8 @@ import { RemoteData } from '../data/remote-data'; import { RestRequest } from '../data/request.models'; import { RequestEntry } from '../data/request.reducer'; import { RequestService } from '../data/request.service'; +import { MetadataField } from '../metadata/metadata-field.model'; +import { MetadataSchema } from '../metadata/metadata-schema.model'; import { BrowseDefinition } from './browse-definition.model'; import { DSpaceObject } from './dspace-object.model'; import { getUnauthorizedRoute } from '../../app-routing-paths'; @@ -250,3 +252,27 @@ export const paginatedListToArray = () => hasValueOperator(), map((objectRD: RemoteData>) => objectRD.payload.page.filter((object: T) => hasValue(object))) ); + +/** + * Operator for turning a list of metadata fields into an array of string representing their schema.element.qualifier string + */ +export const metadataFieldsToString = () => + (source: Observable>>): Observable => + source.pipe( + hasValueOperator(), + map((fieldRD: RemoteData>) => { + return fieldRD.payload.page.filter((object: MetadataField) => hasValue(object)) + }), + switchMap((fields: MetadataField[])=> { + const fieldSchemaArray = fields.map((field: MetadataField) => { + return field.schema.pipe( + getFirstSucceededRemoteDataPayload(), + map((schema: MetadataSchema) => ({ field, schema })) + ); + }); + return observableCombineLatest(fieldSchemaArray); + }), + map((fieldSchemaArray: {field: MetadataField, schema: MetadataSchema}[]): string[] => { + return fieldSchemaArray.map((fieldSchema: {field: MetadataField, schema: MetadataSchema}) => fieldSchema.schema.prefix + '.' + fieldSchema.field.toString()) + }) + );