Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(search): add missing search resource component (DEV-95) (#548)
  • Loading branch information
kilchenmann committed Oct 8, 2021
1 parent 37bb2a7 commit 79abd10
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Expand Up @@ -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) {
Expand Down Expand Up @@ -310,6 +311,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersComponent,
UsersListComponent,
VisualizerComponent,
SearchResourceComponent,
],
imports: [
AngularSplitModule.forRoot(),
Expand Down
@@ -0,0 +1,7 @@
<app-resource-and-property-selection
#resAndPropSel
[formGroup]="form"
[activeOntology]="ontology"
[resourceClassRestriction]="restrictResourceClass"
[topLevel]="false">
</app-resource-and-property-selection>
@@ -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: `
<app-search-resource #searchRes [formGroup]="form" [restrictResourceClass]="resClass"></app-search-resource>`
})
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<TestHostComponent>;

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');

});

});
@@ -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);
}

}
Expand Up @@ -7,16 +7,16 @@
</span>

<!-- select apt component for value specification using a switch case statement-->
<span
*ngIf="comparisonOperatorSelected !== undefined && comparisonOperatorSelected !== null && comparisonOperatorSelected.getClassName() != 'Exists'" [ngSwitch]="propertyValueType">
<span *ngIf="comparisonOperatorSelected !== undefined && comparisonOperatorSelected !== null && comparisonOperatorSelected.getClassName() != 'Exists'"
[ngSwitch]="propertyValueType">
<app-search-int-value #propertyValue [formGroup]="form" *ngSwitchCase="Constants.IntValue"></app-search-int-value>
<app-search-decimal-value #propertyValue [formGroup]="form" *ngSwitchCase="Constants.DecimalValue"></app-search-decimal-value>
<app-search-boolean-value #propertyValue [formGroup]="form" *ngSwitchCase="Constants.BooleanValue"></app-search-boolean-value>
<app-search-date-value #propertyValue [formGroup]="form" *ngSwitchCase="Constants.DateValue"></app-search-date-value>

<span *ngSwitchCase="Constants.Resource">
<span *ngIf="comparisonOperatorSelected.getClassName() == 'Match'; else elseBlock">
<!-- <app-search-resource #propertyValue [formGroup]="form" [restrictResourceClass]="objectClassConstraint"></app-search-resource> -->
<app-search-resource #propertyValue [formGroup]="form" [restrictResourceClass]="objectClassConstraint"></app-search-resource>
</span>
<ng-template #elseBlock>
<app-search-link-value #propertyValue [formGroup]="form" [restrictResourceClass]="objectClassConstraint"></app-search-link-value>
Expand Down

0 comments on commit 79abd10

Please sign in to comment.