From 79abd10d46f5398f2bc0a9170ea852b82f75f158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Kilchenmann?= Date: Fri, 8 Oct 2021 10:17:57 +0200 Subject: [PATCH] feat(search): add missing search resource component (DEV-95) (#548) --- src/app/app.module.ts | 2 + .../search-resource.component.html | 7 + .../search-resource.component.scss | 0 .../search-resource.component.spec.ts | 122 ++++++++++++++++++ .../search-resource.component.ts | 63 +++++++++ .../specify-property-value.component.html | 6 +- 6 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html create mode 100644 src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.scss create mode 100644 src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts create mode 100644 src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8a8f854d99..42a66fa3e1 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -160,6 +160,7 @@ import { SearchSelectOntologyComponent } from './workspace/search/advanced-searc import { ExpertSearchComponent } from './workspace/search/expert-search/expert-search.component'; import { FulltextSearchComponent } from './workspace/search/fulltext-search/fulltext-search.component'; import { SearchPanelComponent } from './workspace/search/search-panel/search-panel.component'; +import { SearchResourceComponent } from './workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component'; // translate: AoT requires an exported function for factories export function httpLoaderFactory(httpClient: HttpClient) { @@ -310,6 +311,7 @@ export function httpLoaderFactory(httpClient: HttpClient) { UsersComponent, UsersListComponent, VisualizerComponent, + SearchResourceComponent, ], imports: [ AngularSplitModule.forRoot(), diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html new file mode 100644 index 0000000000..15ba0c034b --- /dev/null +++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.html @@ -0,0 +1,7 @@ + + diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.scss b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts new file mode 100644 index 0000000000..92c4bdb802 --- /dev/null +++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.spec.ts @@ -0,0 +1,122 @@ +import { Component, Inject, Input, OnInit, ViewChild } from '@angular/core'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { MockOntology, ResourcePropertyDefinition } from '@dasch-swiss/dsp-js'; +import { ComparisonOperatorAndValue, GreaterThan, LinkedResource, PropertyWithValue, ValueLiteral } from '../operator'; +import { SearchResourceComponent } from './search-resource.component'; + +/** + * test host component to simulate parent component. + */ +@Component({ + template: ` + ` +}) +class TestHostComponent implements OnInit { + + @ViewChild('searchRes', { static: false }) searchResource: SearchResourceComponent; + + form; + + resClass: string; + + constructor(@Inject(FormBuilder) private _fb: FormBuilder) { + } + + ngOnInit() { + this.form = this._fb.group({}); + this.resClass = 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing'; + } +} + +/** + * test component to simulate ResourceAndPropertySelectionComponent. + */ +@Component({ + selector: 'app-resource-and-property-selection', + template: '' +}) +class TestResourceAndPropertySelectionComponent implements OnInit { + + @Input() formGroup: FormGroup; + + @Input() activeOntology: string; + + @Input() resourceClassRestriction?: string; + + @Input() topLevel; + + // mock ref to child comp. + resourceClassComponent = { + selectedResourceClassIri: 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing' + }; + + // mock ref to child comp. + propertyComponents = []; + + ngOnInit() { + + const anythingOnto = MockOntology.mockReadOntology('http://0.0.0.0:3333/ontology/0001/anything/v2'); + + const linkedResValue = new ComparisonOperatorAndValue(new GreaterThan(), new ValueLiteral('0.5', 'http://www.w3.org/2001/XMLSchema#decimal')); + + const hasDecimal = anythingOnto.properties['http://0.0.0.0:3333/ontology/0001/anything/v2#hasDecimal']; + + const linkedResourceWithVal = new PropertyWithValue(hasDecimal as ResourcePropertyDefinition, linkedResValue, false); + + this.propertyComponents = [{ + getPropertySelectedWithValue: () => linkedResourceWithVal + }]; + } +} + +describe('SearchResourceComponent', () => { + let testHostComponent: TestHostComponent; + let testHostFixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + + TestBed.configureTestingModule({ + imports: [ + BrowserAnimationsModule, + ReactiveFormsModule + ], + declarations: [ + SearchResourceComponent, + TestResourceAndPropertySelectionComponent, + TestHostComponent + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + testHostFixture = TestBed.createComponent(TestHostComponent); + testHostComponent = testHostFixture.componentInstance; + + testHostFixture.detectChanges(); + }); + + it('should create', () => { + expect(testHostComponent).toBeTruthy(); + expect(testHostComponent.searchResource).toBeTruthy(); + }); + + it('should correctly determine the ontology from the resource class constraint', () => { + expect(testHostComponent.searchResource.restrictResourceClass).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#Thing'); + }); + + it('should return a specified resource', () => { + + const linkedRes = testHostComponent.searchResource.getValue(); + + expect(linkedRes instanceof LinkedResource).toBeTrue(); + expect((linkedRes as LinkedResource).resourceClass).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#Thing'); + expect((linkedRes as LinkedResource).properties.length).toEqual(1); + + expect((linkedRes as LinkedResource).properties[0].property.id).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#hasDecimal'); + + }); + +}); diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts new file mode 100644 index 0000000000..603d60d503 --- /dev/null +++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/search-resource/search-resource.component.ts @@ -0,0 +1,63 @@ +import { Component, Inject, Input, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Constants } from '@dasch-swiss/dsp-js'; +import { ResourceAndPropertySelectionComponent } from '../../../resource-and-property-selection.component'; +import { LinkedResource, PropertyValue, PropertyWithValue, Value } from '../operator'; + +// https://stackoverflow.com/questions/45661010/dynamic-nested-reactive-form-expressionchangedafterithasbeencheckederror +const resolvedPromise = Promise.resolve(null); + +@Component({ + selector: 'app-search-resource', + templateUrl: './search-resource.component.html', + styleUrls: ['./search-resource.component.scss'] +}) +export class SearchResourceComponent implements OnInit, PropertyValue { + + // parent FormGroup + @Input() formGroup: FormGroup; + + @Input() restrictResourceClass: string; + + // reference to the component that controls the resource class selection + @ViewChild('resAndPropSel') resourceAndPropertySelection: ResourceAndPropertySelectionComponent; + + type = Constants.Resource; + + form: FormGroup; + + ontology: string; + + constructor(@Inject(FormBuilder) private _fb: FormBuilder) { + } + + ngOnInit(): void { + + this.form = this._fb.group({}); + + resolvedPromise.then(() => { + this.formGroup.addControl('propValue', this.form); + }); + + // get ontology from restriction + this.ontology = this.restrictResourceClass.split('#')[0]; + } + + getValue(): Value { + + const resClassOption = this.resourceAndPropertySelection.resourceClassComponent.selectedResourceClassIri; + + let resClass; + + if (resClassOption !== false) { + resClass = resClassOption; + } + + const properties: PropertyWithValue[] = this.resourceAndPropertySelection.propertyComponents.map( + (propComp) => propComp.getPropertySelectedWithValue() + ); + + return new LinkedResource(properties, resClass); + } + +} diff --git a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html index 79d80a5407..d47352febb 100644 --- a/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html +++ b/src/app/workspace/search/advanced-search/resource-and-property-selection/search-select-property/specify-property-value/specify-property-value.component.html @@ -7,8 +7,8 @@ - + @@ -16,7 +16,7 @@ - +