71894: refactor with new operator metadataFieldsToString instead of schemaResolved

This commit is contained in:
Marie Verdonck
2020-07-27 14:43:41 +02:00
parent 2ebb1640b4
commit 1f4ae7a035
4 changed files with 62 additions and 81 deletions

View File

@@ -1,5 +1,5 @@
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core'; 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 { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { TranslateModule } from '@ngx-translate/core'; 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 { MetadatumViewModel } from '../../../../core/shared/metadata.models';
import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model'; import { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model';
import { SharedModule } from '../../../../shared/shared.module'; 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 { followLink } from '../../../../shared/utils/follow-link-config.model';
import { EditInPlaceFieldComponent } from './edit-in-place-field.component'; import { EditInPlaceFieldComponent } from './edit-in-place-field.component';
@@ -27,22 +30,21 @@ let el: HTMLElement;
let metadataFieldService; let metadataFieldService;
let objectUpdatesService; let objectUpdatesService;
let paginatedMetadataFields; 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(), { const mdField1 = Object.assign(new MetadataField(), {
schema: mdSchema, schema: mdSchemaRD$,
element: 'contributor', element: 'contributor',
qualifier: 'author', qualifier: 'author'
schemaResolved: mdSchema,
}); });
const mdField2 = Object.assign(new MetadataField(), { const mdField2 = Object.assign(new MetadataField(), {
schema: mdSchema, schema: mdSchemaRD$,
element: 'title', element: 'title'
schemaResolved: mdSchema, }); });
const mdField3 = Object.assign(new MetadataField(), { const mdField3 = Object.assign(new MetadataField(), {
schema: mdSchema, schema: mdSchemaRD$,
element: 'description', element: 'description',
qualifier: 'abstract', qualifier: 'abstract',
schemaResolved: mdSchema,
}); });
const metadatum = Object.assign(new MetadatumViewModel(), { const metadatum = Object.assign(new MetadatumViewModel(), {
@@ -58,7 +60,7 @@ const fieldUpdate = {
}; };
let scheduler: TestScheduler; let scheduler: TestScheduler;
describe('EditInPlaceFieldComponent', () => { fdescribe('EditInPlaceFieldComponent', () => {
beforeEach(async(() => { beforeEach(async(() => {
scheduler = getTestScheduler(); scheduler = getTestScheduler();
@@ -200,18 +202,18 @@ describe('EditInPlaceFieldComponent', () => {
const metadataFieldSuggestions: InputSuggestion[] = const metadataFieldSuggestions: InputSuggestion[] =
[ [
{ displayValue: (mdField1.schemaResolved.prefix + '.' + mdField1.toString()).split('.').join('.​'), value: (mdField1.schemaResolved.prefix + '.' + mdField1.toString()) }, { displayValue: ('dc.' + mdField1.toString()).split('.').join('.​'), value: ('dc.' + mdField1.toString()) },
{ displayValue: (mdField2.schemaResolved.prefix + '.' + mdField2.toString()).split('.').join('.​'), value: (mdField2.schemaResolved.prefix + '.' + mdField2.toString()) }, { displayValue: ('dc.' + mdField2.toString()).split('.').join('.​'), value: ('dc.' + mdField2.toString()) },
{ displayValue: (mdField3.schemaResolved.prefix + '.' + mdField3.toString()).split('.').join('.​'), value: (mdField3.schemaResolved.prefix + '.' + mdField3.toString()) } { displayValue: ('dc.' + mdField3.toString()).split('.').join('.​'), value: ('dc.' + mdField3.toString()) }
]; ];
beforeEach(() => { beforeEach(fakeAsync(() => {
comp.findMetadataFieldSuggestions(query); comp.findMetadataFieldSuggestions(query);
tick();
}); fixture.detectChanges();
}));
it('it should call queryMetadataFields on the metadataFieldService with the correct query', () => { it('it should call queryMetadataFields on the metadataFieldService with the correct query', () => {
expect(metadataFieldService.queryMetadataFields).toHaveBeenCalledWith(query, null, followLink('schema')); expect(metadataFieldService.queryMetadataFields).toHaveBeenCalledWith(query, null, followLink('schema'));
}); });

View File

@@ -1,17 +1,15 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core'; import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model'; import { metadataFieldsToString } from '../../../../core/shared/operators';
import { getRemoteDataPayload, getSucceededRemoteData } from '../../../../core/shared/operators';
import { hasValue, isNotEmpty } from '../../../../shared/empty.util'; import { hasValue, isNotEmpty } from '../../../../shared/empty.util';
import { RegistryService } from '../../../../core/registry/registry.service'; import { RegistryService } from '../../../../core/registry/registry.service';
import { cloneDeep } from 'lodash'; import { cloneDeep } from 'lodash';
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; 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 { FieldChangeType } from '../../../../core/data/object-updates/object-updates.actions';
import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer'; import { FieldUpdate } from '../../../../core/data/object-updates/object-updates.reducer';
import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service'; import { ObjectUpdatesService } from '../../../../core/data/object-updates/object-updates.service';
import { NgModel } from '@angular/forms'; import { NgModel } from '@angular/forms';
import { MetadatumViewModel } from '../../../../core/shared/metadata.models'; 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 { InputSuggestion } from '../../../../shared/input-suggestions/input-suggestions.model';
import { followLink } from '../../../../shared/utils/follow-link-config.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" * Ignores fields from metadata schemas "relation" and "relationship"
* @param query The query to look for * @param query The query to look for
*/ */
findMetadataFieldSuggestions(query: string): void { findMetadataFieldSuggestions(query: string) {
if (isNotEmpty(query)) { if (isNotEmpty(query)) {
this.registryService.queryMetadataFields(query, null, followLink('schema')).pipe( return this.registryService.queryMetadataFields(query, null, followLink('schema')).pipe(
getSucceededRemoteData(), metadataFieldsToString(),
take(1), take(1))
map((data) => data.payload.page), .subscribe((fieldNames: string[]) => {
switchMap((fields: MetadataField[]) => { this.setInputSuggestions(fieldNames);
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();
} else { } else {
this.metadataFieldSuggestions.next([]); 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 * 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 * @param fields list of Metadata fields, which all require a resolved MetadataSchema
*/ */
setInputSuggestions(fields: MetadataField[]) { setInputSuggestions(fields: string[]) {
this.metadataFieldSuggestions.next( this.metadataFieldSuggestions.next(
fields.map((field: MetadataField) => { fields.map((fieldName: string) => {
const fieldNameWhole = field.schemaResolved.prefix + '.' + field.toString();
return { return {
displayValue: fieldNameWhole.split('.').join('.​'), displayValue: fieldName.split('.').join('.​'),
value: fieldNameWhole value: fieldName
}; };
}) })
); );

View File

@@ -70,8 +70,6 @@ export class MetadataField extends ListableObject implements HALResource {
@link(METADATA_SCHEMA) @link(METADATA_SCHEMA)
schema?: Observable<RemoteData<MetadataSchema>>; schema?: Observable<RemoteData<MetadataSchema>>;
schemaResolved?: MetadataSchema;
/** /**
* Method to print this metadata field as a string without the schema * Method to print this metadata field as a string without the schema
* @param separator The separator between element and qualifier in the string * @param separator The separator between element and qualifier in the string
@@ -84,28 +82,6 @@ export class MetadataField extends ListableObject implements HALResource {
return key; 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<string> {
let schemaObject: Observable<RemoteData<MetadataSchema>> = 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 * Method that returns as which type of object this object should be rendered
*/ */

View File

@@ -1,6 +1,6 @@
import { Router, UrlTree } from '@angular/router'; import { Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs'; import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
import { filter, find, flatMap, map, take, tap } from 'rxjs/operators'; import { filter, find, flatMap, map, switchMap, take, tap } from 'rxjs/operators';
import { hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util'; import { hasValue, hasValueOperator, isNotEmpty } from '../../shared/empty.util';
import { SearchResult } from '../../shared/search/search-result.model'; import { SearchResult } from '../../shared/search/search-result.model';
import { DSOSuccessResponse, RestResponse } from '../cache/response.models'; import { DSOSuccessResponse, RestResponse } from '../cache/response.models';
@@ -9,6 +9,8 @@ import { RemoteData } from '../data/remote-data';
import { RestRequest } from '../data/request.models'; import { RestRequest } from '../data/request.models';
import { RequestEntry } from '../data/request.reducer'; import { RequestEntry } from '../data/request.reducer';
import { RequestService } from '../data/request.service'; 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 { BrowseDefinition } from './browse-definition.model';
import { DSpaceObject } from './dspace-object.model'; import { DSpaceObject } from './dspace-object.model';
import { getUnauthorizedRoute } from '../../app-routing-paths'; import { getUnauthorizedRoute } from '../../app-routing-paths';
@@ -250,3 +252,27 @@ export const paginatedListToArray = () =>
hasValueOperator(), hasValueOperator(),
map((objectRD: RemoteData<PaginatedList<T>>) => objectRD.payload.page.filter((object: T) => hasValue(object))) map((objectRD: RemoteData<PaginatedList<T>>) => 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<RemoteData<PaginatedList<MetadataField>>>): Observable<string[]> =>
source.pipe(
hasValueOperator(),
map((fieldRD: RemoteData<PaginatedList<MetadataField>>) => {
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())
})
);