mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
71894: MD field suggestions on edit item page
This commit is contained in:
@@ -1,9 +1,13 @@
|
||||
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||
import { MetadataSchemaDataService } from '../../../../core/data/metadata-schema-data.service';
|
||||
import { PaginatedList } from '../../../../core/data/paginated-list';
|
||||
import { MetadataSchema } from '../../../../core/metadata/metadata-schema.model';
|
||||
import { getRemoteDataPayload, getSucceededRemoteData } 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, take } from 'rxjs/operators';
|
||||
import { map, switchMap, take, tap } 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';
|
||||
@@ -11,6 +15,7 @@ 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';
|
||||
|
||||
@Component({
|
||||
// tslint:disable-next-line:component-selector
|
||||
@@ -60,6 +65,7 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
|
||||
constructor(
|
||||
private registryService: RegistryService,
|
||||
private objectUpdatesService: ObjectUpdatesService,
|
||||
private metadataSchemaService: MetadataSchemaDataService
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -128,25 +134,53 @@ export class EditInPlaceFieldComponent implements OnInit, OnChanges {
|
||||
*/
|
||||
findMetadataFieldSuggestions(query: string): void {
|
||||
if (isNotEmpty(query)) {
|
||||
this.registryService.queryMetadataFields(query).pipe(
|
||||
// getSucceededRemoteData(),
|
||||
this.registryService.queryMetadataFields(query, null, followLink('schema')).pipe(
|
||||
getSucceededRemoteData(),
|
||||
take(1),
|
||||
map((data) => data.payload.page)
|
||||
).subscribe(
|
||||
(fields: MetadataField[]) => this.metadataFieldSuggestions.next(
|
||||
fields.map((field: MetadataField) => {
|
||||
return {
|
||||
displayValue: field.toString().split('.').join('.​'),
|
||||
value: field.toString()
|
||||
};
|
||||
})
|
||||
)
|
||||
);
|
||||
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();
|
||||
} else {
|
||||
this.metadataFieldSuggestions.next([]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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[]) {
|
||||
this.metadataFieldSuggestions.next(
|
||||
fields.map((field: MetadataField) => {
|
||||
const fieldNameWhole = field.schemaResolved.prefix + '.' + field.toString();
|
||||
return {
|
||||
displayValue: fieldNameWhole.split('.').join('.​'),
|
||||
value: fieldNameWhole
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user should be allowed to edit this field
|
||||
* @return an observable that emits true when the user should be able to edit this field and false when they should not
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import { dataService } from '../cache/builders/build-decorators';
|
||||
import { DataService } from './data.service';
|
||||
import { RequestService } from './request.service';
|
||||
@@ -27,6 +28,7 @@ import { RequestParam } from '../cache/models/request-param.model';
|
||||
export class MetadataFieldDataService extends DataService<MetadataField> {
|
||||
protected linkPath = 'metadatafields';
|
||||
protected searchBySchemaLinkPath = 'bySchema';
|
||||
protected searchByFieldNameLinkPath = 'byFieldName';
|
||||
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
@@ -53,6 +55,29 @@ export class MetadataFieldDataService extends DataService<MetadataField> {
|
||||
return this.searchBy(this.searchBySchemaLinkPath, optionsWithSchema, ...linksToFollow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find metadata fields with either the partial metadata field name (e.g. "dc.ti") as query or an exact match to
|
||||
* at least the schema, element or qualifier
|
||||
* @param schema optional; an exact match of the prefix of the metadata schema (e.g. "dc", "dcterms", "eperson")
|
||||
* @param element optional; an exact match of the field's element (e.g. "contributor", "title")
|
||||
* @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,
|
||||
* should start with the start of the schema (e.g. "dc.ti")
|
||||
* @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
|
||||
*/
|
||||
findByFieldName(schema: string, element: string, qualifier: string, query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>) {
|
||||
const optionParams = Object.assign(new FindListOptions(), options, {
|
||||
searchParams: [
|
||||
new RequestParam('schema', hasValue(schema) ? schema : ''),
|
||||
new RequestParam('element', hasValue(element) ? element : ''),
|
||||
new RequestParam('qualifier', hasValue(qualifier) ? qualifier : ''),
|
||||
new RequestParam('query', hasValue(query) ? query : '')
|
||||
]
|
||||
});
|
||||
return this.searchBy(this.searchByFieldNameLinkPath, optionParams, ...linksToFollow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all metadata field requests
|
||||
* Used for refreshing lists after adding/updating/removing a metadata field from a metadata schema
|
||||
|
@@ -1,10 +1,13 @@
|
||||
import { autoserialize, deserialize } from 'cerialize';
|
||||
import { isNotEmpty } from '../../shared/empty.util';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { hasValue, isNotEmpty } from '../../shared/empty.util';
|
||||
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
||||
import { link, typedObject } from '../cache/builders/build-decorators';
|
||||
import { MetadataSchemaDataService } from '../data/metadata-schema-data.service';
|
||||
import { GenericConstructor } from '../shared/generic-constructor';
|
||||
import { HALLink } from '../shared/hal-link.model';
|
||||
import { HALResource } from '../shared/hal-resource.model';
|
||||
import { getRemoteDataPayload, getSucceededRemoteData } from '../shared/operators';
|
||||
import { ResourceType } from '../shared/resource-type';
|
||||
import { excludeFromEquals } from '../utilities/equals.decorators';
|
||||
import { METADATA_FIELD } from './metadata-field.resource-type';
|
||||
@@ -67,9 +70,11 @@ export class MetadataField extends ListableObject implements HALResource {
|
||||
@link(METADATA_SCHEMA)
|
||||
schema?: Observable<RemoteData<MetadataSchema>>;
|
||||
|
||||
schemaResolved?: MetadataSchema;
|
||||
|
||||
/**
|
||||
* Method to print this metadata field as a string
|
||||
* @param separator The separator between the schema, element and qualifier in the string
|
||||
* Method to print this metadata field as a string without the schema
|
||||
* @param separator The separator between element and qualifier in the string
|
||||
*/
|
||||
toString(separator: string = '.'): string {
|
||||
let key = this.element;
|
||||
@@ -79,6 +84,28 @@ 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<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
|
||||
*/
|
||||
|
@@ -297,13 +297,10 @@ export class RegistryService {
|
||||
|
||||
/**
|
||||
* Retrieve a filtered paginated list of metadata fields
|
||||
* @param query {string} The query to filter the field names by
|
||||
* @param query {string} The query to use for the metadata field name, can be partial (e.g. "dc.ti")
|
||||
* @returns an observable that emits a remote data object with a page of metadata fields that match the query
|
||||
*/
|
||||
// TODO this is temporarily disabled. The performance is too bad.
|
||||
// Querying metadatafields will need to be implemented as a search endpoint on the rest api,
|
||||
// not by downloading everything and preforming the query client side.
|
||||
queryMetadataFields(query: string): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
||||
return createSuccessfulRemoteDataObject$(new PaginatedList<MetadataField>(null, []));
|
||||
queryMetadataFields(query: string, options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<MetadataField>>): Observable<RemoteData<PaginatedList<MetadataField>>> {
|
||||
return this.metadataFieldService.findByFieldName(null, null, null, query, options, ...linksToFollow);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user