Mercurial > hg > ng2-query-ismi
changeset 39:7578b21cdf2e
make relation types configurable.
relations can have custom labels for incoming or outgoing direction.
author | casties |
---|---|
date | Sun, 14 Feb 2016 19:40:07 +0100 |
parents | 313a5360c2d3 |
children | 896ae7eefb33 |
files | app/ismi-relation-types.ts app/query-select.component.ts app/query.service.ts app/relation-type.ts app/result-type.ts |
diffstat | 5 files changed, 158 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/ismi-relation-types.ts Sun Feb 14 19:40:07 2016 +0100 @@ -0,0 +1,54 @@ +import {RelationType, invNamePrefix} from './relation-type'; + +export var RELATION_TYPES: {[name:string]: RelationType} = {}; + +addRelationType('is_part_of', 'is included in', 'includes'); +addRelationType('is_exemplar_of', 'title of witness', 'witnesses to title'); +addRelationType('was_created_by', 'created by', 'works of'); +addRelationType('has_subject', 'subject of title', 'titles with subject'); +addRelationType('has_role', 'role of person', 'persons with role'); +addRelationType('is_alias_name_of', 'person name for alias', 'alias of person'); +addRelationType('is_alias_title_of', 'title name for alias', 'alias of title'); +addRelationType('is_commentary_on', 'is commentary on', 'list of commentaries'); +addRelationType('has_title_written_as', 'title in witness', 'witness with title as'); +addRelationType('has_author_written_as', 'author in witness', 'witness with author as'); +addRelationType('lived_in', 'place person lived in', 'persons who lived in'); +addRelationType('was_copied_by', 'witness copied by', 'witnesses that were copied by'); +addRelationType('was_born_in', 'place person was born in', 'persons who were born in'); +addRelationType('owned_by', 'codex owned by', 'persons who owned codex'); +addRelationType('was_student_of', 'studied with', 'persons studying with'); +addRelationType('died_in', 'place person died in', 'persons who died in'); +addRelationType('was_created_in', 'place title was created', 'titles that were created in'); +addRelationType('was_copied_in', 'place witness was copied', 'witnesses that were copied in'); +addRelationType('misattributed_to', 'title misattributed to', 'misattributions to person'); +addRelationType('was_dedicated_to', 'text dedicated to', 'texts that were dedicated to'); +addRelationType('is_version_of', 'standard text of different version', 'different version of standard text'); +addRelationType('is_translation_of', 'original text of a translation', 'translation of a text'); +addRelationType('has_floruit_date', 'floruit date of person', 'persons with floruit date'); +addRelationType('was_studied_by', 'persons studying this text', 'text studied by'); +//addRelationType('', '', ''); + +export function getRelationType(name: string, isOutgoing?: boolean): RelationType { + if (isOutgoing === false) { + // add prefix to name + name = invNamePrefix + name; + } + let rt = RELATION_TYPES[name]; + if (rt == null) { + if (name.indexOf(invNamePrefix) == 0) { + // inverse relation + name = name.substr(invNamePrefix.length); + rt = new RelationType(name, false); + } else { + rt = new RelationType(name, true); + } + } + return rt; +} + +function addRelationType(name: string, outLabel: string, inLabel: string) { + // add outgoing relation + RELATION_TYPES[name] = new RelationType(name, true, outLabel); + // add inverse relation + RELATION_TYPES[invNamePrefix + name] = new RelationType(name, false, inLabel); +} \ No newline at end of file
--- a/app/query-select.component.ts Sun Feb 14 19:38:36 2016 +0100 +++ b/app/query-select.component.ts Sun Feb 14 19:40:07 2016 +0100 @@ -6,6 +6,7 @@ import {QueryService} from './query.service'; import {NormalizationService} from './normalization.service'; +import {getRelationType} from './ismi-relation-types'; @Component({ @@ -21,7 +22,7 @@ </option> </select> - <span *ngIf="selectedMode?.id=='type_is' || selectedMode?.id=='relation_is'"> + <span *ngIf="selectedMode?.id=='type_is'"> <select *ngIf="queryOptions" [ngModel]="selectedOption" (change)="onSelectOption($event)"> <option></option> <option *ngFor="#option of queryOptions" [value]="option"> @@ -30,6 +31,15 @@ </select> </span> + <span *ngIf="selectedMode?.id=='relation_is'"> + <select *ngIf="queryOptions" [ngModel]="selectedOption" (change)="onSelectOption($event)"> + <option></option> + <option *ngFor="#option of queryOptions" [value]="option.getName()"> + {{option.getLabel()}} + </option> + </select> + </span> + <span *ngIf="selectedMode?.id=='att_contains' || selectedMode?.id=='att_contains_norm'"> <select [ngModel]="selectedOption" (change)="selectedOption=$event.target.value"> <option></option> @@ -116,36 +126,57 @@ console.debug("Submit! selectedMode=", this.selectedMode, " selectedOption=", this.selectedOption, " queryInput=", this.queryInput); var step: QueryStep; if (this.selectedMode.id == 'type_is') { - var opt = this.selectedOption; + /* + * type_is + */ + let opt = this.selectedOption; if (opt) { step = new QueryStep(this.selectedMode, {'objectType': opt}); } } else if (this.selectedMode.id == 'relation_is') { - var opt = this.selectedOption; + /* + * relation_is + */ + let opt = this.selectedOption; if (opt) { - step = new QueryStep(this.selectedMode, {'relationType': opt}); + let rel = getRelationType(opt); + step = new QueryStep(this.selectedMode, {'relationType': rel}); + } + } else if (this.selectedMode.id == 'id_is') { + /* + * id is + */ + let val = this.queryInput; + if (val) { + step = new QueryStep(this.selectedMode, {'value': val}); } } else if (this.selectedMode.id == 'att_contains') { - var att = this.selectedOption; - var val = this.queryInput; + /* + * att_contains + */ + let att = this.selectedOption; + let val = this.queryInput; if (att && val) { step = new QueryStep(this.selectedMode, {'attribute': att, 'value': val}); } - } else if (this.selectedMode.id == 'id_is') { - var val = this.queryInput; - if (val) { - step = new QueryStep(this.selectedMode, {'value': val}); - } } else if (this.selectedMode.id == 'att_num_range') { - var att = this.selectedOption; - var nlo = this.queryInput; - var nhi = this.queryInput2; + /* + * att_num_range + */ + let att = this.selectedOption; + let nlo = this.queryInput; + let nhi = this.queryInput2; if (att && nlo && nhi) { step = new QueryStep(this.selectedMode, {'attribute': att, 'numLo': nlo, 'numHi': nhi}); } } else if (this.selectedMode.id == 'att_contains_norm') { - var att = this.selectedOption; - var val = this.queryInput; + /* + * att_contains_norm + * + * calls normalization service and submits event in callback + */ + let att = this.selectedOption; + let val = this.queryInput; if (att && val) { // run search term through normalizer this._normService.fetchArabicTranslitNormalizedString(val) @@ -165,6 +196,9 @@ } } + /* + * set step and submit change event + */ if (step != null) { this._queryService.setQueryStep(this.index, step); this.queryChanged.emit(this._queryService.getState());
--- a/app/query.service.ts Sun Feb 14 19:38:36 2016 +0100 +++ b/app/query.service.ts Sun Feb 14 19:40:07 2016 +0100 @@ -9,16 +9,16 @@ import {QueryStep} from './query-step'; import {getResultType} from './result-type'; import {ISMI_RESULT_TYPES} from './ismi-result-types'; +import {getRelationType} from './ismi-relation-types'; @Injectable() export class QueryService { - public neo4jBaseUrl = 'https://ismi-dev.mpiwg-berlin.mpg.de/neo4j-ismi/db/data'; - //public neo4jBaseUrl = 'http://localhost:7474/db/data'; + //public neo4jBaseUrl = 'https://ismi-dev.mpiwg-berlin.mpg.de/neo4j-ismi/db/data'; + public neo4jBaseUrl = 'http://localhost:7474/db/data'; public neo4jAuthentication = {'user': 'neo4j', 'password': 'neo5j'}; public typeAttribute = '_type'; public excludedAttributes = {}; - public invRelPrefix = '<- '; public state: QueryState; public objectTypes: string[]; @@ -149,15 +149,14 @@ */ if (mode === 'relation_is') { nIdx += 1; - var rel = params.relationType; - if (rel.indexOf(this.invRelPrefix) == 0) { + let rel = params.relationType; + if (rel.isOutgoing()) { + queryMatch += `-[:\`${rel.getName()}\`]->(n${nIdx})`; + } else { // inverse relation - rel = rel.substr(this.invRelPrefix.length); - queryMatch += `<-[:${rel}]-(n${nIdx})`; - } else { - queryMatch += `-[:${rel}]->(n${nIdx})`; + queryMatch += `<-[:\`${rel.getName()}\`]-(n${nIdx})`; } - queryReturn = `RETURN n${nIdx}`; + queryReturn = `RETURN DISTINCT n${nIdx}`; returnType = 'node'; } @@ -292,7 +291,8 @@ // outgoing aka forward relations resIdx += 1; let rels = data.results[resIdx].data.map(elem => elem.row[0]) - .filter(elem => elem[0] != "_"); + .filter(elem => elem[0] != "_") + .map(elem => getRelationType(elem, true)); this.state.resultRelations = rels; } if (this.state.inRelsCypherQuery) { @@ -300,7 +300,7 @@ resIdx += 1; let rels = data.results[resIdx].data.map(elem => elem.row[0]) .filter(elem => elem[0] != "_") - .map((r) => this.invRelPrefix + r); + .map(elem => getRelationType(elem, false)); this.state.resultRelations = this.state.resultRelations.concat(rels); } },
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/relation-type.ts Sun Feb 14 19:40:07 2016 +0100 @@ -0,0 +1,38 @@ + +export var invLabelPrefix = '<- '; +export var invNamePrefix = '-'; +export var rawLabelPrefix = '('; +export var rawLabelPostfix = ')'; + +export class RelationType { + public name: string; + public label: string; + public outgoing: boolean; + + constructor (name: string, isOutgoing: boolean, label?:string) { + this.name = name; + this.outgoing = isOutgoing; + if (label != null) { + this.label = label; + } else { + // create label using name + if (isOutgoing) { + this.label = rawLabelPrefix + name + rawLabelPostfix; + } else { + this.label = rawLabelPrefix + invLabelPrefix + name + rawLabelPostfix; + } + } + } + + getLabel() { + return this.label; + } + + getName() { + return this.name; + } + + isOutgoing() { + return this.outgoing; + } +}
--- a/app/result-type.ts Sun Feb 14 19:38:36 2016 +0100 +++ b/app/result-type.ts Sun Feb 14 19:40:07 2016 +0100 @@ -13,7 +13,10 @@ this.deniedAttributes = deniedAttributes; } - getColumns(attributes: string[], allAttributes=true) { + /** + * Return columns for the given list of attributes. + */ + getColumns(attributes: string[], allAttributes=true): ResultColumn[] { let atts = attributes.slice(); let cols = []; // allowed attributes