mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-09 02:54:13 +00:00
71894: Refactored exact FieldName search for validator after change endpoint
This commit is contained in:
@@ -63,7 +63,7 @@ const fieldUpdate = {
|
|||||||
};
|
};
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
|
|
||||||
fdescribe('EditInPlaceFieldComponent', () => {
|
describe('EditInPlaceFieldComponent', () => {
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
scheduler = getTestScheduler();
|
scheduler = getTestScheduler();
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { hasValue, isNotEmptyOperator } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { dataService } from '../cache/builders/build-decorators';
|
import { dataService } from '../cache/builders/build-decorators';
|
||||||
import { RestResponse } from '../cache/response.models';
|
|
||||||
import { configureRequest } from '../shared/operators';
|
|
||||||
import { DataService } from './data.service';
|
import { DataService } from './data.service';
|
||||||
import { RequestEntry } from './request.reducer';
|
import { PaginatedList } from './paginated-list';
|
||||||
|
import { RemoteData } from './remote-data';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
@@ -17,14 +16,10 @@ import { NotificationsService } from '../../shared/notifications/notifications.s
|
|||||||
import { METADATA_FIELD } from '../metadata/metadata-field.resource-type';
|
import { METADATA_FIELD } from '../metadata/metadata-field.resource-type';
|
||||||
import { MetadataField } from '../metadata/metadata-field.model';
|
import { MetadataField } from '../metadata/metadata-field.model';
|
||||||
import { MetadataSchema } from '../metadata/metadata-schema.model';
|
import { MetadataSchema } from '../metadata/metadata-schema.model';
|
||||||
import {
|
import { FindListOptions } from './request.models';
|
||||||
FindListOptions,
|
|
||||||
GetMetadataFieldRequest,
|
|
||||||
RestRequest
|
|
||||||
} from './request.models';
|
|
||||||
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
import { Observable } from 'rxjs/internal/Observable';
|
||||||
import { distinctUntilChanged, find, map, switchMap, tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { RequestParam } from '../cache/models/request-param.model';
|
import { RequestParam } from '../cache/models/request-param.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -70,43 +65,33 @@ export class MetadataFieldDataService extends DataService<MetadataField> {
|
|||||||
* @param qualifier optional; an exact match of the field's qualifier (e.g. "author", "alternative")
|
* @param qualifier optional; an exact match of the field's qualifier (e.g. "author", "alternative")
|
||||||
* @param query optional (if any of schema, element or qualifier used) - part of the fully qualified field,
|
* @param query optional (if any of schema, element or qualifier used) - part of the fully qualified field,
|
||||||
* should start with the start of the schema, element or qualifier (e.g. “dc.ti”, “contributor”, “auth”, “contributor.ot”)
|
* should start with the start of the schema, element or qualifier (e.g. “dc.ti”, “contributor”, “auth”, “contributor.ot”)
|
||||||
|
* @param exactName optional; the exact fully qualified field, should use the syntax schema.element.qualifier or
|
||||||
|
* schema.element if no qualifier exists (e.g. "dc.title", "dc.contributor.author"). It will only return one value
|
||||||
|
* if there's an exact match
|
||||||
* @param options The options info used to retrieve the fields
|
* @param options The options info used to retrieve the fields
|
||||||
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
|
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
|
||||||
*/
|
*/
|
||||||
searchByFieldNameParams(schema: string, element: string, qualifier: string, query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>) {
|
searchByFieldNameParams(schema: string, element: string, qualifier: string, query: string, exactName: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
||||||
const optionParams = Object.assign(new FindListOptions(), options, {
|
const optionParams = Object.assign(new FindListOptions(), options, {
|
||||||
searchParams: [
|
searchParams: [
|
||||||
new RequestParam('schema', hasValue(schema) ? schema : ''),
|
new RequestParam('schema', hasValue(schema) ? schema : ''),
|
||||||
new RequestParam('element', hasValue(element) ? element : ''),
|
new RequestParam('element', hasValue(element) ? element : ''),
|
||||||
new RequestParam('qualifier', hasValue(qualifier) ? qualifier : ''),
|
new RequestParam('qualifier', hasValue(qualifier) ? qualifier : ''),
|
||||||
new RequestParam('query', hasValue(query) ? query : '')
|
new RequestParam('query', hasValue(query) ? query : ''),
|
||||||
|
new RequestParam('exactName', hasValue(exactName) ? exactName : '')
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
return this.searchBy(this.searchByFieldNameLinkPath, optionParams, ...linksToFollow);
|
return this.searchBy(this.searchByFieldNameLinkPath, optionParams, ...linksToFollow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a specific metadata field by name. There's always at most one metadata field per name.
|
* Finds a specific metadata field by name.
|
||||||
* If the metadata field can be found it is in the response, otherwise the response will have code 404
|
* @param exactFieldName The exact fully qualified field, should use the syntax schema.element.qualifier or
|
||||||
* @param exactFieldName Exact metadata field name (ex. dc.title, dc.contributor.other)
|
* schema.element if no qualifier exists (e.g. "dc.title", "dc.contributor.author"). It will only return one value
|
||||||
|
* if there's an exact match, empty list if there is no exact match.
|
||||||
*/
|
*/
|
||||||
findByExactFieldName(exactFieldName: string): Observable<RestResponse> {
|
findByExactFieldName(exactFieldName: string): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
||||||
const request$ = this.halService.getEndpoint(this.linkPath).pipe(
|
return this.searchByFieldNameParams(null, null, null, null, exactFieldName, null);
|
||||||
isNotEmptyOperator(),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
map((endpoint: string) => `${endpoint}/name/${exactFieldName}`),
|
|
||||||
map((endpointURL: string) => new GetMetadataFieldRequest(this.requestService.generateRequestId(), endpointURL)),
|
|
||||||
configureRequest(this.requestService)
|
|
||||||
);
|
|
||||||
|
|
||||||
const requestEntry$ = request$.pipe(
|
|
||||||
switchMap((request: RestRequest) => this.requestService.getByHref(request.href))
|
|
||||||
);
|
|
||||||
|
|
||||||
return requestEntry$.pipe(
|
|
||||||
find((request: RequestEntry) => request.completed),
|
|
||||||
map((request: RequestEntry) => request.response)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -293,6 +293,6 @@ export class RegistryService {
|
|||||||
* @returns an observable that emits a remote data object with a page of metadata fields that match the query
|
* @returns an observable that emits a remote data object with a page of metadata fields that match the query
|
||||||
*/
|
*/
|
||||||
queryMetadataFields(query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
queryMetadataFields(query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
||||||
return this.metadataFieldService.searchByFieldNameParams(null, null, null, query, options, ...linksToFollow);
|
return this.metadataFieldService.searchByFieldNameParams(null, null, null, query, null, options, ...linksToFollow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { Router, UrlTree } from '@angular/router';
|
import { Router, UrlTree } from '@angular/router';
|
||||||
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
|
import { Observable, combineLatest as observableCombineLatest } from 'rxjs';
|
||||||
import { filter, find, flatMap, map, switchMap, take, tap } from 'rxjs/operators';
|
import { filter, find, flatMap, map, switchMap, 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';
|
||||||
@@ -263,7 +263,7 @@ export const metadataFieldsToString = () =>
|
|||||||
map((fieldRD: RemoteData<PaginatedList<MetadataField>>) => {
|
map((fieldRD: RemoteData<PaginatedList<MetadataField>>) => {
|
||||||
return fieldRD.payload.page.filter((object: MetadataField) => hasValue(object))
|
return fieldRD.payload.page.filter((object: MetadataField) => hasValue(object))
|
||||||
}),
|
}),
|
||||||
switchMap((fields: MetadataField[])=> {
|
switchMap((fields: MetadataField[]) => {
|
||||||
const fieldSchemaArray = fields.map((field: MetadataField) => {
|
const fieldSchemaArray = fields.map((field: MetadataField) => {
|
||||||
return field.schema.pipe(
|
return field.schema.pipe(
|
||||||
getFirstSucceededRemoteDataPayload(),
|
getFirstSucceededRemoteDataPayload(),
|
||||||
@@ -272,7 +272,7 @@ export const metadataFieldsToString = () =>
|
|||||||
});
|
});
|
||||||
return observableCombineLatest(fieldSchemaArray);
|
return observableCombineLatest(fieldSchemaArray);
|
||||||
}),
|
}),
|
||||||
map((fieldSchemaArray: {field: MetadataField, schema: MetadataSchema}[]): string[] => {
|
map((fieldSchemaArray: Array<{ field: MetadataField, schema: MetadataSchema }>): string[] => {
|
||||||
return fieldSchemaArray.map((fieldSchema: {field: MetadataField, schema: MetadataSchema}) => fieldSchema.schema.prefix + '.' + fieldSchema.field.toString())
|
return fieldSchemaArray.map((fieldSchema: { field: MetadataField, schema: MetadataSchema }) => fieldSchema.schema.prefix + '.' + fieldSchema.field.toString())
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@@ -22,7 +22,7 @@ import { InputSuggestion } from '../input-suggestions.model';
|
|||||||
/**
|
/**
|
||||||
* Component representing a form with a autocomplete functionality
|
* Component representing a form with a autocomplete functionality
|
||||||
*/
|
*/
|
||||||
export class FilterInputSuggestionsComponent extends InputSuggestionsComponent implements OnInit{
|
export class FilterInputSuggestionsComponent extends InputSuggestionsComponent implements OnInit {
|
||||||
|
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
|
|
||||||
|
@@ -2,8 +2,11 @@ import { Directive, Injectable } from '@angular/core';
|
|||||||
import { AbstractControl, AsyncValidator, NG_VALIDATORS, ValidationErrors } from '@angular/forms';
|
import { AbstractControl, AsyncValidator, NG_VALIDATORS, ValidationErrors } from '@angular/forms';
|
||||||
import { map, switchMap, take } from 'rxjs/operators';
|
import { map, switchMap, take } from 'rxjs/operators';
|
||||||
import { of as observableOf, timer as observableTimer, Observable } from 'rxjs';
|
import { of as observableOf, timer as observableTimer, Observable } from 'rxjs';
|
||||||
import { RestResponse } from '../../core/cache/response.models';
|
|
||||||
import { MetadataFieldDataService } from '../../core/data/metadata-field-data.service';
|
import { MetadataFieldDataService } from '../../core/data/metadata-field-data.service';
|
||||||
|
import { PaginatedList } from '../../core/data/paginated-list';
|
||||||
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
|
import { MetadataField } from '../../core/metadata/metadata-field.model';
|
||||||
|
import { getSucceededRemoteData } from '../../core/shared/operators';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive for validating if a ngModel value is a valid metadata field
|
* Directive for validating if a ngModel value is a valid metadata field
|
||||||
@@ -38,11 +41,12 @@ export class MetadataFieldValidator implements AsyncValidator {
|
|||||||
|
|
||||||
const res = this.metadataFieldService.findByExactFieldName(control.value)
|
const res = this.metadataFieldService.findByExactFieldName(control.value)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((response: RestResponse) => {
|
getSucceededRemoteData(),
|
||||||
if (response.isSuccessful) {
|
map((matchingFieldRD: RemoteData<PaginatedList<MetadataField>>) => {
|
||||||
return null;
|
if (matchingFieldRD.payload.pageInfo.totalElements === 0) {
|
||||||
} else {
|
|
||||||
return { invalidMetadataField: { value: control.value } };
|
return { invalidMetadataField: { value: control.value } };
|
||||||
|
} else if (matchingFieldRD.payload.pageInfo.totalElements === 1) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user