Skip to content
Permalink
Browse files
fix(ontology-editor): bring back the gui-attr for pulldown (DEV-856) (#…
…719)

* fix(ontology-editor): bring back the gui-attr for pulldown (DEV-856)

* fix(ontology-editor): bring back the gui-attr for pulldown (DEV-856)

* test(ontology-editor): bring back the gui-attr for pulldown (DEV-856)

* style(ontology-editor): display whole id of prop or class

* test(ontology-editor): test the list property edit function

* refactor(ontology-editor): fix typos
  • Loading branch information
kilchenmann committed Apr 29, 2022
1 parent a061435 commit 0c2a43d7b9420a7c9327d0975eef2b100fc97d8e
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 32 deletions.
@@ -79,7 +79,7 @@
<span matPrefix class="ontology-prefix-icon">
<mat-icon>{{guiAttrIcon}}</mat-icon>&nbsp;
</span>
<mat-label>Select list *</mat-label>
<mat-label>Select list</mat-label>
<mat-select formControlName="guiAttr">
<mat-option *ngFor="let item of lists" [value]="item.id">
{{item.labels[0].value}}
@@ -94,7 +94,7 @@
<span matPrefix class="ontology-prefix-icon">
<mat-icon>{{guiAttrIcon}}</mat-icon>&nbsp;
</span>
<mat-label>Select resource class *</mat-label>
<mat-label>Select resource class</mat-label>
<mat-select formControlName="guiAttr">
<mat-option *ngFor="let item of resourceClasses" [value]="item.id">
{{item.label}}
@@ -14,7 +14,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
import { By } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { MockOntology, ReadOntology } from '@dasch-swiss/dsp-js';
import { ListNodeInfo, MockOntology, ReadOntology } from '@dasch-swiss/dsp-js';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
import { CacheService } from 'src/app/main/cache/cache.service';
@@ -124,13 +124,80 @@ class LinkHostComponent {

}

/**
* test host component to simulate parent component
* Property is of type resource link
*/
@Component({
template: '<app-property-form #propertyForm [propertyInfo]="propertyInfo"></app-property-form>'
})
class ListHostComponent {

@ViewChild('propertyForm') propertyFormComponent: PropertyFormComponent;

propertyInfo: PropertyInfoObject = {
'propDef': {
'id': 'http://0.0.0.0:3333/ontology/0001/anything/v2#hasOtherListItem',
'subPropertyOf': ['http://api.knora.org/ontology/knora-api/v2#hasValue'],
'comment': 'Andere listenelement',
'label': 'Andere listenelement',
'guiElement': 'http://api.knora.org/ontology/salsah-gui/v2#Pulldown',
'subjectType': 'http://0.0.0.0:3333/ontology/0001/anything/v2#Thing',
'objectType': 'http://api.knora.org/ontology/knora-api/v2#ListValue',
'isLinkProperty': false,
'isLinkValueProperty': false,
'isEditable': true,
'guiAttributes': ['hlist=<http://rdfh.ch/lists/0001/otherTreeList>'],
'comments': [{
'language': 'de',
'value': 'Andere listenelement'
}, {
'language': 'en',
'value': 'Other list element'
}, {
'language': 'fr',
'value': 'Autre elément de liste'
}, {
'language': 'it',
'value': 'Altra elemento di lista'
}],
'labels': [{
'language': 'de',
'value': 'Andere listenelement'
}, {
'language': 'en',
'value': 'Other list element'
}, {
'language': 'fr',
'value': 'Autre elément de liste'
}, {
'language': 'it',
'value': 'Altra elemento di lista'
}]
},
'propType': {
'icon': 'arrow_drop_down_circle',
'label': 'Dropdown',
'description': 'Dropdown menu with values from predefined list',
'subPropOf': 'http://api.knora.org/ontology/knora-api/v2#hasValue',
'objectType': 'http://api.knora.org/ontology/knora-api/v2#ListValue',
'guiEle': 'http://api.knora.org/ontology/salsah-gui/v2#Pulldown',
'group': 'List'
}
};

}

describe('PropertyFormComponent', () => {
let simpleTextHostComponent: SimpleTextHostComponent;
let simpleTextHostFixture: ComponentFixture<SimpleTextHostComponent>;

let linkHostComponent: LinkHostComponent;
let linkHostFixture: ComponentFixture<LinkHostComponent>;

let listHostComponent: ListHostComponent;
let listHostFixture: ComponentFixture<ListHostComponent>;

beforeEach(waitForAsync(() => {

const cacheServiceSpyOnto = jasmine.createSpyObj('CacheServiceOnto', ['get']);
@@ -145,6 +212,7 @@ describe('PropertyFormComponent', () => {
TestBed.configureTestingModule({
declarations: [
LinkHostComponent,
ListHostComponent,
SimpleTextHostComponent,
PropertyFormComponent
],
@@ -183,16 +251,66 @@ describe('PropertyFormComponent', () => {
}));

beforeEach(() => {
const cacheSpyOnto = TestBed.inject(CacheService);

// mock cache service for currentOntology
(cacheSpyOnto as jasmine.SpyObj<CacheService>).get.and.callFake(
const cacheSpyOnto = TestBed.inject(CacheService);
(cacheSpyOnto as jasmine.SpyObj<CacheService>).get.withArgs('currentOntology').and.callFake (
() => {
const response: ReadOntology = MockOntology.mockReadOntology('http://0.0.0.0:3333/ontology/0001/anything/v2');
return of(response);
}
);

// mock cache service for currentOntologyLists
const cacheSpyLists = TestBed.inject(CacheService);
(cacheSpyLists as jasmine.SpyObj<CacheService>).get.withArgs('currentOntologyLists').and.callFake(
() => {
const response: ListNodeInfo[] = [{
'comments': [],
'id': 'http://rdfh.ch/lists/0001/otherTreeList',
'isRootNode': true,
'labels': [{
'language': 'en',
'value': 'Tree list root'
}],
'projectIri': 'http://rdfh.ch/projects/0001'
}, {
'comments': [{
'language': 'en',
'value': 'a list that is not in used in ontology or data'
}],
'id': 'http://rdfh.ch/lists/0001/notUsedList',
'isRootNode': true,
'labels': [{
'language': 'de',
'value': 'unbenutzte Liste'
}, {
'language': 'en',
'value': 'a list that is not used'
}],
'name': 'notUsedList',
'projectIri': 'http://rdfh.ch/projects/0001'
}, {
'comments': [{
'language': 'en',
'value': 'Anything Tree List'
}],
'id': 'http://rdfh.ch/lists/0001/treeList',
'isRootNode': true,
'labels': [{
'language': 'de',
'value': 'Listenwurzel'
}, {
'language': 'en',
'value': 'Tree list root'
}],
'name': 'treelistroot',
'projectIri': 'http://rdfh.ch/projects/0001'
}];
return of(response);
}
);

// simple text
simpleTextHostFixture = TestBed.createComponent(SimpleTextHostComponent);
simpleTextHostComponent = simpleTextHostFixture.componentInstance;
@@ -207,6 +325,12 @@ describe('PropertyFormComponent', () => {

expect(linkHostComponent).toBeTruthy();

// list
listHostFixture = TestBed.createComponent(ListHostComponent);
listHostComponent = listHostFixture.componentInstance;
listHostFixture.detectChanges();

expect(listHostComponent).toBeTruthy();
});

it('should create an instance', () => {
@@ -257,17 +381,26 @@ describe('PropertyFormComponent', () => {

});

it('expect link to other resource called "Thing"', () => {
it('expect link to other resource called "Thing" ( = guiAttribute)', () => {
expect(linkHostComponent.propertyFormComponent).toBeTruthy();
expect(linkHostComponent.propertyFormComponent.propertyInfo.propDef).toBeDefined();
expect(linkHostComponent.propertyFormComponent.propertyInfo.propType).toBeDefined();

const form = linkHostComponent.propertyFormComponent.propertyForm;

expect(form.controls['guiAttr'].value).toEqual('http://0.0.0.0:3333/ontology/0001/anything/v2#Thing');

});

it('expect link to List called "Tree list root" ( = guiAttribute)', () => {
expect(listHostComponent.propertyFormComponent).toBeTruthy();
expect(listHostComponent.propertyFormComponent.propertyInfo.propDef).toBeDefined();
expect(listHostComponent.propertyFormComponent.propertyInfo.propType).toBeDefined();

const form = listHostComponent.propertyFormComponent.propertyForm;
expect(form.controls['guiAttr'].value).toEqual('http://rdfh.ch/lists/0001/otherTreeList');

});

it('expect "required" toggle switch (cardinality) to be disabled', () => {
expect(simpleTextHostComponent.propertyFormComponent).toBeTruthy();
expect(simpleTextHostComponent.propertyFormComponent.propertyInfo.propDef).toBeDefined();
@@ -337,31 +337,35 @@ export class PropertyFormComponent implements OnInit {
// disable the input and set the validator as not required
this.propertyForm.controls['guiAttr'].disable();

switch (type.guiEle) {
// prop type is a list
case Constants.GuiList:
case Constants.GuiRadio:
this.showGuiAttr = true;
// gui attribute value for lists looks as follow: hlist=<http://rdfh.ch/lists/00FF/73d0ec0302>
// get index from guiAttr array where value starts with hlist=
const i = this.guiAttributes.findIndex(element => element.includes('hlist'));
// find content beteween pointy brackets to get list iri
const re = /\<([^)]+)\>/;
const listIri = this.guiAttributes[i].match(re)[1];

this.propertyForm.controls['guiAttr'].setValue(listIri);
break;

// prop type is resource pointer: link to or part of
case Constants.GuiSearchbox:
this.showGuiAttr = true;
this.propertyForm.controls['guiAttr'].setValue(this.propertyInfo.propDef.objectType);
break;

default:
this.showGuiAttr = false;
if (type.objectType) {
switch (type.objectType) {
// prop type is a list
case Constants.ListValue:
this.showGuiAttr = true;
// gui attribute value for lists looks as follows: hlist=<http://rdfh.ch/lists/00FF/73d0ec0302>
// get index from guiAttr array where value starts with hlist=
const i = this.guiAttributes.findIndex(element => element.includes('hlist'));
// find content between pointy brackets to get list iri
const re = /\<([^)]+)\>/;
const listIri = this.guiAttributes[i].match(re)[1];

this.propertyForm.controls['guiAttr'].setValue(listIri);
break;

// prop type is resource pointer: link to or part of
case Constants.LinkValue:
this.showGuiAttr = true;
this.propertyForm.controls['guiAttr'].setValue(this.propertyInfo.propDef.objectType);
break;

default:
this.showGuiAttr = false;
}
} else {
this.showGuiAttr = false;
}


} else {
// depending on the selected property type,
// we have to define gui element attributes
@@ -20,7 +20,7 @@
</div>

<div mat-line class="info additional-info" [class.flex]="propCard" [class.with-line-break]="!propCard">
<span [matTooltip]="'id: ' + propDef.id" matTooltipPosition="above" class="mat-caption">
<span [matTooltip]="'id: ' + propDef.id" matTooltipPosition="above" matTooltipClass="wide-tooltip" class="mat-caption">
{{propDef.id | split: '#':1}}
</span>
<span class="fill-remaining-space center">&nbsp;&middot;&nbsp;</span>
@@ -7,7 +7,7 @@
{{resourceClass.label | appTruncate: 24}}
</mat-card-title>
<mat-card-subtitle>
<span [matTooltip]="'id: ' + resourceClass.id" matTooltipPosition="above">
<span [matTooltip]="'id: ' + resourceClass.id" matTooltipPosition="above" matTooltipClass="wide-tooltip">
{{resourceClass.id | split: '#':1}}
</span>
<span>&nbsp;&middot;&nbsp;</span>
@@ -769,6 +769,10 @@ $gc-small: $form-width - $gc-large - 4;
font-size: 11px;
}

.wide-tooltip {
max-width: unset !important;
}

.annotation-tooltip {

p {

0 comments on commit 0c2a43d

Please sign in to comment.