Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 6 commits into from Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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}}
Expand All @@ -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}}
Expand Down
143 changes: 138 additions & 5 deletions src/app/project/ontology/property-form/property-form.component.spec.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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']);
Expand All @@ -145,6 +212,7 @@ describe('PropertyFormComponent', () => {
TestBed.configureTestingModule({
declarations: [
LinkHostComponent,
ListHostComponent,
SimpleTextHostComponent,
PropertyFormComponent
],
Expand Down Expand Up @@ -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;
Expand All @@ -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', () => {
Expand Down Expand Up @@ -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();
Expand Down
50 changes: 27 additions & 23 deletions src/app/project/ontology/property-form/property-form.component.ts
Expand Up @@ -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
Expand Down
Expand Up @@ -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>
Expand Down
Expand Up @@ -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>
Expand Down
4 changes: 4 additions & 0 deletions src/assets/style/_elements.scss
Expand Up @@ -769,6 +769,10 @@ $gc-small: $form-width - $gc-large - 4;
font-size: 11px;
}

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

.annotation-tooltip {

p {
Expand Down