Skip to content

Commit

Permalink
113169: Moved the MetadataValue#isVirtual & MetadataValue#virtualValu…
Browse files Browse the repository at this point in the history
…e to the new MetadataService
  • Loading branch information
alexandrevryghem committed Mar 15, 2024
1 parent 179e7e0 commit 7b19047
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 63 deletions.
37 changes: 23 additions & 14 deletions src/app/core/data/relationship-data.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ import { FindListOptions } from './find-list-options.model';
import { testSearchDataImplementation } from './base/search-data.spec';
import { MetadataValue } from '../shared/metadata.models';
import { MetadataRepresentationType } from '../shared/metadata-representation/metadata-representation.model';
import { TestBed } from '@angular/core/testing';
import { ItemDataService } from './item-data.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { PAGINATED_RELATIONS_TO_ITEMS_OPERATOR } from '../../item-page/simple/item-types/shared/item-relationships-utils';
import { Store } from '@ngrx/store';
import { provideMockStore } from '@ngrx/store/testing';

describe('RelationshipDataService', () => {
let service: RelationshipDataService;
Expand Down Expand Up @@ -128,18 +135,6 @@ describe('RelationshipDataService', () => {
findByHref: createSuccessfulRemoteDataObject$(relatedItems[0])
});

function initTestService() {
return new RelationshipDataService(
requestService,
rdbService,
halService,
objectCache,
itemService,
null,
jasmine.createSpy('paginatedRelationsToItems').and.returnValue((v) => v),
);
}

const getRequestEntry$ = (successful: boolean) => {
return observableOf({
response: { isSuccessful: successful, payload: relationships } as any
Expand All @@ -148,11 +143,25 @@ describe('RelationshipDataService', () => {

beforeEach(() => {
requestService = getMockRequestService(getRequestEntry$(true));
service = initTestService();

TestBed.configureTestingModule({
providers: [
{ provide: RequestService, useValue: requestService },
{ provide: RemoteDataBuildService, useValue: rdbService },
{ provide: HALEndpointService, useValue: halService },
{ provide: ObjectCacheService, useValue: objectCache },
{ provide: ItemDataService, useValue: itemService },
{ provide: RequestService, useValue: requestService },
{ provide: PAGINATED_RELATIONS_TO_ITEMS_OPERATOR, useValue: jasmine.createSpy('paginatedRelationsToItems').and.returnValue((v) => v) },
{ provide: Store, useValue: provideMockStore() },
RelationshipDataService,
],
});
service = TestBed.inject(RelationshipDataService);
});

describe('composition', () => {
const initService = () => new RelationshipDataService(null, null, null, null, null, null, null);
const initService = () => new RelationshipDataService(null, null, null, null, null, null, null, null);

testSearchDataImplementation(initService);
});
Expand Down
6 changes: 4 additions & 2 deletions src/app/core/data/relationship-data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { MetadataRepresentation } from '../shared/metadata-representation/metada
import { MetadatumRepresentation } from '../shared/metadata-representation/metadatum/metadatum-representation.model';
import { ItemMetadataRepresentation } from '../shared/metadata-representation/item/item-metadata-representation.model';
import { DSpaceObject } from '../shared/dspace-object.model';
import { MetadataService } from '../metadata/metadata.service';

const relationshipListsStateSelector = (state: AppState) => state.relationshipLists;

Expand Down Expand Up @@ -89,6 +90,7 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
protected rdbService: RemoteDataBuildService,
protected halService: HALEndpointService,
protected objectCache: ObjectCacheService,
protected metadataService: MetadataService,
protected itemService: ItemDataService,
protected appStore: Store<AppState>,
@Inject(PAGINATED_RELATIONS_TO_ITEMS_OPERATOR) private paginatedRelationsToItems: (thisId: string) => (source: Observable<RemoteData<PaginatedList<Relationship>>>) => Observable<RemoteData<PaginatedList<Item>>>,
Expand Down Expand Up @@ -563,8 +565,8 @@ export class RelationshipDataService extends IdentifiableDataService<Relationshi
* @param itemType The type of item this metadata value represents (will only be used when no related item can be found, as a fallback)
*/
resolveMetadataRepresentation(metadatum: MetadataValue, parentItem: DSpaceObject, itemType: string): Observable<MetadataRepresentation> {
if (metadatum.isVirtual) {
return this.findById(metadatum.virtualValue, true, false, followLink('leftItem'), followLink('rightItem')).pipe(
if (this.metadataService.isVirtual(metadatum)) {
return this.findById(this.metadataService.virtualValue(metadatum), true, false, followLink('leftItem'), followLink('rightItem')).pipe(
getFirstSucceededRemoteData(),
switchMap((relRD: RemoteData<Relationship>) =>
observableCombineLatest(relRD.payload.leftItem, relRD.payload.rightItem).pipe(
Expand Down
16 changes: 16 additions & 0 deletions src/app/core/metadata/metadata.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { MetadataService } from './metadata.service';

describe('MetadataService', () => {
let service: MetadataService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MetadataService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
33 changes: 33 additions & 0 deletions src/app/core/metadata/metadata.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Injectable } from '@angular/core';
import { hasValue } from '../../shared/empty.util';
import { MetadataValue, VIRTUAL_METADATA_PREFIX } from '../shared/metadata.models';

/**
* Service for working with DSpace object metadata.
*/
@Injectable({
providedIn: 'root',
})
export class MetadataService {

/**
* Returns true if this Metadata authority key starts with 'virtual::'
*/
public isVirtual(metadataValue: MetadataValue | undefined): boolean {
return hasValue(metadataValue?.authority) && metadataValue.authority.startsWith(VIRTUAL_METADATA_PREFIX);
}

/**
* If this is a virtual Metadata, it returns everything in the authority key after 'virtual::'.
*
* Returns undefined otherwise.
*/
public virtualValue(metadataValue: MetadataValue | undefined): string {
if (this.isVirtual) {
return metadataValue.authority.substring(metadataValue.authority.indexOf(VIRTUAL_METADATA_PREFIX) + VIRTUAL_METADATA_PREFIX.length);
} else {
return undefined;
}
}

}
19 changes: 0 additions & 19 deletions src/app/core/shared/metadata.models.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable max-classes-per-file */
import { v4 as uuidv4 } from 'uuid';
import { autoserialize, Serialize, Deserialize } from 'cerialize';
import { hasValue } from '../../shared/empty.util';

export const VIRTUAL_METADATA_PREFIX = 'virtual::';

Expand Down Expand Up @@ -53,24 +52,6 @@ export class MetadataValue implements MetadataValueInterface {
@autoserialize
confidence: number;

/**
* Returns true if this Metadatum's authority key starts with 'virtual::'
*/
get isVirtual(): boolean {
return hasValue(this.authority) && this.authority.startsWith(VIRTUAL_METADATA_PREFIX);
}

/**
* If this is a virtual Metadatum, it returns everything in the authority key after 'virtual::'.
* Returns undefined otherwise.
*/
get virtualValue(): string {
if (this.isVirtual) {
return this.authority.substring(this.authority.indexOf(VIRTUAL_METADATA_PREFIX) + VIRTUAL_METADATA_PREFIX.length);
} else {
return undefined;
}
}
}

/** Constraints for matching metadata values. */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="d-flex flex-row ds-value-row" *ngVar="mdValue.newValue.isVirtual as isVirtual" role="row"
<div class="d-flex flex-row ds-value-row" *ngVar="metadataService.isVirtual(mdValue.newValue) as isVirtual" role="row"
cdkDrag (cdkDragStarted)="dragging.emit(true)" (cdkDragEnded)="dragging.emit(false)"
[ngClass]="{ 'ds-warning': mdValue.reordered || mdValue.change === DsoEditMetadataChangeTypeEnum.UPDATE, 'ds-danger': mdValue.change === DsoEditMetadataChangeTypeEnum.REMOVE, 'ds-success': mdValue.change === DsoEditMetadataChangeTypeEnum.ADD, 'h-100': isOnlyValue }">
<div class="flex-grow-1 ds-flex-cell ds-value-cell d-flex align-items-center" *ngVar="(mdRepresentation$ | async) as mdRepresentation" role="cell">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { map } from 'rxjs/operators';
import { getItemPageRoute } from '../../../item-page/item-page-routing-paths';
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
import { EMPTY } from 'rxjs/internal/observable/empty';
import { MetadataService } from '../../../core/metadata/metadata.service';

@Component({
selector: 'ds-dso-edit-metadata-value',
Expand Down Expand Up @@ -97,8 +98,11 @@ export class DsoEditMetadataValueComponent implements OnInit {
*/
mdRepresentationName$: Observable<string | null>;

constructor(protected relationshipService: RelationshipDataService,
protected dsoNameService: DSONameService) {
constructor(
protected relationshipService: RelationshipDataService,
protected dsoNameService: DSONameService,
protected metadataService: MetadataService,
) {
}

ngOnInit(): void {
Expand All @@ -109,7 +113,7 @@ export class DsoEditMetadataValueComponent implements OnInit {
* Initialise potential properties of a virtual metadata value
*/
initVirtualProperties(): void {
this.mdRepresentation$ = this.mdValue.newValue.isVirtual ?
this.mdRepresentation$ = this.metadataService.isVirtual(this.mdValue.newValue) ?
this.relationshipService.resolveMetadataRepresentation(this.mdValue.newValue, this.dso, 'Item')
.pipe(
map((mdRepresentation: MetadataRepresentation) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '../../../core/shared/metadata-representation/metadatum/metadatum-representation.model';
import { BrowseService } from '../../../core/browse/browse.service';
import { BrowseDefinitionDataService } from '../../../core/browse/browse-definition-data.service';
import { MetadataService } from '../../../core/metadata/metadata.service';

@Component({
selector: 'ds-metadata-representation-list',
Expand Down Expand Up @@ -62,6 +63,7 @@ export class MetadataRepresentationListComponent extends AbstractIncrementalList
constructor(
public relationshipService: RelationshipDataService,
protected browseDefinitionDataService: BrowseDefinitionDataService,
protected metadataService: MetadataService,
) {
super();
}
Expand All @@ -87,7 +89,7 @@ export class MetadataRepresentationListComponent extends AbstractIncrementalList
.slice((this.objects.length * this.incrementBy), (this.objects.length * this.incrementBy) + this.incrementBy)
.map((metadatum: any) => Object.assign(new MetadataValue(), metadatum))
.map((metadatum: MetadataValue) => {
if (metadatum.isVirtual) {
if (this.metadataService.isVirtual(metadatum)) {
return this.relationshipService.resolveMetadataRepresentation(metadatum, this.parentItem, this.itemType);
} else {
// Check for a configured browse link and return a standard metadata representation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<ng-container *ngTemplateOutlet="startTemplate?.templateRef; context: { $implicit: model };"></ng-container>
<!-- Should be *ngIf instead of class d-none, but that breaks the #componentViewContainer reference-->
<div [ngClass]="{'form-row': model.hasLanguages || isRelationship,
'd-none': value?.isVirtual && (model.hasSelectableMetadata || context?.index > 0)}">
'd-none': this.metadataService.isVirtual(value) && (model.hasSelectableMetadata || context?.index > 0)}">
<div [ngClass]="getClass('grid', 'control')">
<div>
<ng-container #componentViewContainer></ng-container>
Expand Down Expand Up @@ -51,7 +51,7 @@
</div>
</div>
<ng-container *ngTemplateOutlet="endTemplate?.templateRef; context: model"></ng-container>
<ng-container *ngIf="value?.isVirtual">
<ng-container *ngIf="this.metadataService.isVirtual(value)">
<ds-existing-metadata-list-element
*ngIf="model.hasSelectableMetadata"
[reoRel]="relationshipValue$ | async"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,12 @@ import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic
import { DsDynamicTypeBindRelationService } from './ds-dynamic-type-bind-relation.service';
import { RelationshipDataService } from '../../../../core/data/relationship-data.service';
import { SelectableListService } from '../../../object-list/selectable-list/selectable-list.service';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Store } from '@ngrx/store';
import { SubmissionObjectDataService } from '../../../../core/submission/submission-object-data.service';
import { Item } from '../../../../core/shared/item.model';
import { WorkspaceItem } from '../../../../core/submission/models/workspaceitem.model';
import { of as observableOf } from 'rxjs';
import { createSuccessfulRemoteDataObject } from '../../../remote-data.utils';
import { FormService } from '../../form.service';
import { SubmissionService } from '../../../../submission/submission.service';
import { FormBuilderService } from '../form-builder.service';
import { NgxMaskModule } from 'ngx-mask';
Expand Down Expand Up @@ -221,11 +219,9 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
{ provide: DsDynamicTypeBindRelationService, useValue: getMockDsDynamicTypeBindRelationService() },
{ provide: RelationshipDataService, useValue: {} },
{ provide: SelectableListService, useValue: {} },
{ provide: ItemDataService, useValue: {} },
{ provide: Store, useValue: {} },
{ provide: RelationshipDataService, useValue: {} },
{ provide: SelectableListService, useValue: {} },
{ provide: FormService, useValue: {} },
{ provide: FormBuilderService, useValue: {} },
{ provide: SubmissionService, useValue: {} },
{
Expand All @@ -234,7 +230,6 @@ describe('DsDynamicFormControlContainerComponent test suite', () => {
findById: () => observableOf(createSuccessfulRemoteDataObject(testWSI))
}
},
{ provide: NgZone, useValue: new NgZone({}) },
{ provide: APP_CONFIG, useValue: environment }
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
ContentChildren,
EventEmitter, Inject,
Input,
NgZone,
OnChanges,
OnDestroy,
OnInit,
Expand Down Expand Up @@ -99,7 +98,6 @@ import {
} from '../../../../core/shared/operators';
import { RemoteData } from '../../../../core/data/remote-data';
import { Item } from '../../../../core/shared/item.model';
import { ItemDataService } from '../../../../core/data/item-data.service';
import { Store } from '@ngrx/store';
import { AppState } from '../../../../app.reducer';
import { SubmissionObjectDataService } from '../../../../core/submission/submission-object-data.service';
Expand All @@ -109,7 +107,6 @@ import { ItemSearchResult } from '../../../object-collection/shared/item-search-
import { Relationship } from '../../../../core/shared/item-relationships/relationship.model';
import { Collection } from '../../../../core/shared/collection.model';
import { MetadataValue, VIRTUAL_METADATA_PREFIX } from '../../../../core/shared/metadata.models';
import { FormService } from '../../form.service';
import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer';
import { SubmissionService } from '../../../../submission/submission.service';
import { followLink } from '../../../utils/follow-link-config.model';
Expand All @@ -120,6 +117,7 @@ import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './ds-dynamic-form-cons
import { FormFieldMetadataValueObject } from '../models/form-field-metadata-value.model';
import { APP_CONFIG, AppConfig } from '../../../../../config/app-config.interface';
import { itemLinksToFollow } from '../../../utils/relation-query.utils';
import { MetadataService } from '../../../../core/metadata/metadata.service';

export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
switch (model.type) {
Expand Down Expand Up @@ -250,17 +248,15 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
protected typeBindRelationService: DsDynamicTypeBindRelationService,
protected translateService: TranslateService,
protected relationService: DynamicFormRelationService,
private modalService: NgbModal,
private relationshipService: RelationshipDataService,
private selectableListService: SelectableListService,
private itemService: ItemDataService,
private zone: NgZone,
private store: Store<AppState>,
private submissionObjectService: SubmissionObjectDataService,
private ref: ChangeDetectorRef,
private formService: FormService,
public formBuilderService: FormBuilderService,
private submissionService: SubmissionService,
protected modalService: NgbModal,
protected relationshipService: RelationshipDataService,
protected selectableListService: SelectableListService,
protected store: Store<AppState>,
protected submissionObjectService: SubmissionObjectDataService,
protected ref: ChangeDetectorRef,
protected formBuilderService: FormBuilderService,
protected submissionService: SubmissionService,
protected metadataService: MetadataService,
@Inject(APP_CONFIG) protected appConfig: AppConfig,
) {
super(ref, componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService);
Expand Down Expand Up @@ -324,8 +320,8 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
this.value = Object.assign(new FormFieldMetadataValueObject(), this.model.value);
}

if (hasValue(this.value) && this.value.isVirtual) {
const relationship$ = this.relationshipService.findById(this.value.virtualValue,
if (hasValue(this.value) && this.metadataService.isVirtual(this.value)) {
const relationship$ = this.relationshipService.findById(this.metadataService.virtualValue(this.value),
true,
true,
... itemLinksToFollow(this.fetchThumbnail)).pipe(
Expand Down

0 comments on commit 7b19047

Please sign in to comment.