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): support subproperty in ontology editor (DEV-332) #643

Merged
merged 14 commits into from Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from 13 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
212 changes: 72 additions & 140 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -33,7 +33,7 @@
"@angular/platform-browser-dynamic": "^12.2.14",
"@angular/router": "^12.2.14",
"@ckeditor/ckeditor5-angular": "^2.0.2",
"@dasch-swiss/dsp-js": "^6.1.0",
"@dasch-swiss/dsp-js": "^6.2.0",
"@datadog/browser-rum": "^3.7.0",
"@ngx-translate/core": "^12.1.2",
"@ngx-translate/http-loader": "5.0.0",
Expand Down
54 changes: 33 additions & 21 deletions src/app/project/ontology/default-data/default-properties.ts
Expand Up @@ -33,6 +33,18 @@ export interface DefaultProperty {
}

export class DefaultProperties {

public static unsupported: DefaultProperty = {
icon: 'warning_amber',
label: 'Unsupported property type',
description: 'This property type is not supported in the ontology editor',
subPropOf: undefined,
objectType: undefined,
guiEle: undefined,
group: 'Warning'
};


public static data: PropertyCategory[] = [
{
group: 'Text',
Expand All @@ -43,7 +55,7 @@ export class DefaultProperties {
description: 'Short text such as title or name',
subPropOf: Constants.HasValue,
objectType: Constants.TextValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'SimpleText', // better element would be: 'Input',
guiEle: Constants.GuiSimpleText, // better element would be: 'Input',
group: 'Text' // redundant information, but otherwise we don't get the main group name after selecting type
},
{
Expand All @@ -52,7 +64,7 @@ export class DefaultProperties {
description: 'Long text such as description; could have line breaks',
subPropOf: Constants.HasValue,
objectType: Constants.TextValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Textarea',
guiEle: Constants.GuiTextarea,
group: 'Text'
},
{
Expand All @@ -61,7 +73,7 @@ export class DefaultProperties {
description: 'A rich text editor with formatting options',
subPropOf: Constants.HasValue,
objectType: Constants.TextValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Richtext',
guiEle: Constants.GuiRichText,
group: 'Text'
}
]
Expand All @@ -75,7 +87,7 @@ export class DefaultProperties {
description: 'Dropdown menu with values from predefined list',
subPropOf: Constants.HasValue,
objectType: Constants.ListValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'List', // better element would be: 'Pulldown' or 'Select'
guiEle: Constants.GuiPulldown, // better element would be: 'Pulldown' or 'Select'
group: 'List'
}
]
Expand All @@ -89,7 +101,7 @@ export class DefaultProperties {
description: 'Yes or no, 1 or 0, true or false',
subPropOf: Constants.HasValue,
objectType: Constants.BooleanValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Checkbox', // should be 'Toggle' but it's not supported in DSP-Tangoh,
guiEle: Constants.GuiCheckbox, // should be 'Toggle' but it's not supported in DSP-Tangoh,
group: 'Boolean'
}
]
Expand All @@ -103,7 +115,7 @@ export class DefaultProperties {
description: 'A date field with day, month and year',
subPropOf: Constants.HasValue,
objectType: Constants.DateValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Date',
guiEle: Constants.GuiDatePicker,
group: 'Date / Time'
},
// {
Expand All @@ -112,7 +124,7 @@ export class DefaultProperties {
// description: 'A period of time between two dates',
// subPropOf: Constants.HasValue,
// objectType: Constants.DateValue,
// guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Date',
// guiEle: Constants.GuiDatePicker',
kilchenmann marked this conversation as resolved.
Show resolved Hide resolved
// group: 'Date / Time'
// },
{
Expand All @@ -121,7 +133,7 @@ export class DefaultProperties {
description: 'A single timestamp on a timeline',
subPropOf: Constants.HasValue,
objectType: Constants.TimeValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'TimeStamp',
guiEle: Constants.GuiTimeStamp,
group: 'Date / Time'
},
{
Expand All @@ -130,7 +142,7 @@ export class DefaultProperties {
description: 'A time sequence with start and end point on a timeline',
subPropOf: Constants.HasValue,
objectType: Constants.IntervalValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Interval',
guiEle: Constants.GuiInterval,
group: 'Date / Time'
}
]
Expand All @@ -144,7 +156,7 @@ export class DefaultProperties {
description: 'Integer value',
subPropOf: Constants.HasValue,
objectType: Constants.IntValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Spinbox', // 'Number',
guiEle: Constants.GuiSpinbox, // 'Number',
group: 'Number'
},
{
Expand All @@ -153,16 +165,16 @@ export class DefaultProperties {
description: 'Decimal value',
subPropOf: Constants.HasValue,
objectType: Constants.DecimalValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Spinbox', // 'Number',
guiEle: Constants.GuiSpinbox, // 'Number',
group: 'Number'
},
{
icon: 'filter_3',
label: 'Page number',
description: 'The page number is needed for page classes in case of part of properties',
subPropOf: Constants.KnoraApiV2 + Constants.HashDelimiter + 'seqnum',
subPropOf: Constants.SeqNum,
objectType: Constants.IntValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Spinbox', // 'Number',
guiEle: Constants.GuiSpinbox, // 'Number',
group: 'Number'
}
]
Expand All @@ -176,26 +188,26 @@ export class DefaultProperties {
description: 'Refers to a resource class',
subPropOf: Constants.HasLinkTo,
objectType: Constants.LinkValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Searchbox', // 'Autocomplete',
guiEle: Constants.GuiSearchbox, // 'Autocomplete',
group: 'Link / Relation'
},
{
icon: 'extension',
label: 'Part of class',
description: 'Is part of a resource class',
subPropOf: Constants.KnoraApiV2 + Constants.HashDelimiter + 'isPartOf',
subPropOf: Constants.IsPartOf,
objectType: Constants.LinkValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Searchbox', // 'Autocomplete',
group: 'Relation'
guiEle: Constants.GuiSearchbox, // 'Autocomplete',
group: 'Link / Relation'
},
{
icon: 'language',
label: 'External URL',
description: 'Link to an external website',
subPropOf: Constants.HasValue,
objectType: Constants.UriValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'SimpleText',
group: 'Link'
guiEle: Constants.GuiSimpleText,
group: 'Link / Relation'
}
]
},
Expand All @@ -208,7 +220,7 @@ export class DefaultProperties {
description: 'Geographical location',
subPropOf: Constants.HasValue,
objectType: Constants.GeonameValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Geonames',
guiEle: Constants.GuiGeonames,
group: 'Location'
}
]
Expand All @@ -222,7 +234,7 @@ export class DefaultProperties {
description: 'A simple color value',
subPropOf: Constants.HasValue,
objectType: Constants.ColorValue,
guiEle: Constants.SalsahGui + Constants.HashDelimiter + 'Colorpicker',
guiEle: Constants.GuiColorPicker,
group: 'Shape'
}
]
Expand Down
14 changes: 12 additions & 2 deletions src/app/project/ontology/ontology.service.spec.ts
@@ -1,12 +1,22 @@
import { TestBed } from '@angular/core/testing';

import { CacheService } from 'src/app/main/cache/cache.service';
import { OntologyService } from './ontology.service';


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

const cacheServiceSpy = jasmine.createSpyObj('CacheService', ['get']);

beforeEach(() => {
TestBed.configureTestingModule({});
TestBed.configureTestingModule({
providers: [
{
provide: CacheService,
useValue: cacheServiceSpy
},
]
});
service = TestBed.inject(OntologyService);
});

Expand Down
108 changes: 106 additions & 2 deletions src/app/project/ontology/ontology.service.ts
@@ -1,5 +1,16 @@
import { Injectable } from '@angular/core';
import { Cardinality, Constants } from '@dasch-swiss/dsp-js';
import {
Cardinality,
Constants, ReadOntology,
ResourcePropertyDefinitionWithAllLanguages
} from '@dasch-swiss/dsp-js';
import { Observable, of } from 'rxjs';
import { CacheService } from 'src/app/main/cache/cache.service';
import {
DefaultProperties,
DefaultProperty,
PropertyCategory
} from './default-data/default-properties';

/**
* helper methods for the ontology editor
Expand All @@ -9,7 +20,12 @@ import { Cardinality, Constants } from '@dasch-swiss/dsp-js';
})
export class OntologyService {

constructor() { }
// list of default property types
defaultProperties: PropertyCategory[] = DefaultProperties.data;

constructor(
private _cache: CacheService
) { }

/**
* create a unique name (id) for resource classes or properties;
Expand Down Expand Up @@ -79,4 +95,92 @@ export class OntologyService {
return Cardinality._0_1;
}
}

getSuperProperty(property: ResourcePropertyDefinitionWithAllLanguages): string {
// get ontology from property info
const ontoIri = property.id.split(Constants.HashDelimiter)[0];

let superPropIri: string;

// get iri from sub properties
if (property.subPropertyOf.length) {
for (const subProp of property.subPropertyOf) {
const baseOntoIri = subProp.split(Constants.HashDelimiter)[0];
// compare with knora base ontology
if (baseOntoIri !== Constants.KnoraApiV2) {
// the property is not a subproperty of knora base ontology
// get property iri from another ontology
this._cache.get('currentProjectOntologies').subscribe(
(ontologies: ReadOntology[]) => {
const onto = ontologies.find(i => i.id === baseOntoIri);
superPropIri = onto.properties[subProp].subPropertyOf[0];
}
);
}

if (superPropIri) {
kilchenmann marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
}

return (superPropIri ? superPropIri : undefined);
}

/**
* get default property information for a certain ontology property
*/
getDefaultPropType(property: ResourcePropertyDefinitionWithAllLanguages): Observable<DefaultProperty> {
let propType: DefaultProperty;

if (!property.guiElement) {
// we don't know what element to use, so it's unsupported property
return of (DefaultProperties.unsupported);
}

for (const group of this.defaultProperties) {
if (property.subPropertyOf.length) {
for (const subProp of property.subPropertyOf) {
// if subProp is of type "link to" or "part of" we have to check the subproperty;
// otherwise we get the necessary property info from the objectType
if (subProp === Constants.HasLinkTo || subProp === Constants.IsPartOf) {
propType = (group.elements.find(i =>
i.guiEle === property.guiElement && i.subPropOf === subProp
));
} else {

// if the property is type of number or list, the gui element is not relevant
// because the app supports only one gui element (at the moment): the spinbox resp. the list pulldown
if (property.objectType === Constants.DecimalValue || property.objectType === Constants.ListValue) {
propType = (group.elements.find(i =>
i.objectType === property.objectType
));
} else if (property.objectType === Constants.IntValue && subProp === Constants.SeqNum) {
propType = (group.elements.find(i =>
i.objectType === property.objectType && i.subPropOf === Constants.SeqNum
));
} else {
propType = (group.elements.find(i =>
i.guiEle === property.guiElement && i.objectType === property.objectType
));
}

}
}
if (propType) {
kilchenmann marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
}

if (!propType) {
// property type could not be found in the list of default properties
// maybe it's not supported e.g. if propDef.objectType === Constants.GeomValue || propDef.subPropertyOf[0] === Constants.HasRepresentation
return of (DefaultProperties.unsupported);
}

// return of(propType);
return of (propType);

}
}
Expand Up @@ -5,8 +5,8 @@

<p *ngIf="resClassIri && propertyInfo.propDef" class="note warning mat-caption center">
You're adding an already existing property to this class.
The property can't modified here. If you want to modify it,
go to the "properties" view.
The property can't be modified here.<br>
If you want to modify the label, the comment or the type, please go to the "properties" view.
<!-- Be careful when editing it, it could have an effect in other resource classes if it is used there. -->
</p>

Expand All @@ -31,6 +31,9 @@
</mat-option>
</mat-optgroup>
</mat-select>
<mat-hint *ngIf="unsupportedPropertyType" class="ontology-warning-with-prefix">
{{propertyForm.controls['propType'].value.description}}
</mat-hint>
</mat-form-field>

<!-- name -->
Expand Down