Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Commit

Permalink
Modify query and store to show subclasses (#145)
Browse files Browse the repository at this point in the history
* Modify store to accept subclasses

* modify the queryRepresentation and generated query to show subclasses

* added envVars file for jest tests files as well

* fixed rebase merge with master

* subclases is false by default and true if property datatype = wikibase-item
  • Loading branch information
guergana committed Jan 14, 2021
1 parent b70fd7e commit f965872
Show file tree
Hide file tree
Showing 16 changed files with 296 additions and 12 deletions.
1 change: 1 addition & 0 deletions .jest/setEnvVars.js
@@ -0,0 +1 @@
process.env.VUE_APP_SUBCLASS_PROPERTY = 'P279';
1 change: 1 addition & 0 deletions jest.config.js
Expand Up @@ -3,4 +3,5 @@ module.exports = {
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!(@wmde/wikit-vue-components)/)',
],
setupFiles: [ '<rootDir>/.jest/setEnvVars.js' ],
};
8 changes: 6 additions & 2 deletions src/components/QueryCondition.vue
Expand Up @@ -92,8 +92,12 @@ export default Vue.extend( {
this.$store.dispatch( 'unsetProperty', this.conditionIndex );
return;
}
this.$store.dispatch(
'updateProperty',
if ( selectedProperty.datatype === 'wikibase-item' ) {
this.$store.dispatch( 'setSubclasses', { conditionIndex: this.conditionIndex, subclasses: true } );
} else {
this.$store.dispatch( 'setSubclasses', { conditionIndex: this.conditionIndex, subclasses: false } );
}
this.$store.dispatch( 'updateProperty',
{ property: selectedProperty, conditionIndex: this.conditionIndex },
);
},
Expand Down
39 changes: 29 additions & 10 deletions src/sparql/QueryObjectBuilder.ts
@@ -1,6 +1,6 @@
import rdfNamespaces from '@/sparql/rdfNamespaces';
import QueryRepresentation, { Condition } from '@/sparql/QueryRepresentation';
import { Pattern, SelectQuery, Term } from 'sparqljs';
import { IriTerm, Pattern, PropertyPath, SelectQuery, Term } from 'sparqljs';
import PropertyValueRelation from '@/data-model/PropertyValueRelation';

export default class QueryObjectBuilder {
Expand Down Expand Up @@ -117,6 +117,33 @@ export default class QueryObjectBuilder {
}
}

private buildTriplePredicateItems( condition: Condition ): ( PropertyPath|IriTerm )[] {
const items: ( PropertyPath|IriTerm )[] = [ {
termType: 'NamedNode',
value: rdfNamespaces.p + condition.propertyId,
},
{
termType: 'NamedNode',
value: rdfNamespaces.ps + condition.propertyId,
} ];

if ( condition.subclasses ) {
items.push(
{
type: 'path',
pathType: '*',
items: [ {
termType: 'NamedNode',
value: rdfNamespaces.wdt + process.env.VUE_APP_SUBCLASS_PROPERTY,
},
],
},
);
}

return items;
}

private buildFromQueryCondition( condition: Condition ): void {
const tripleObject: Term = this.buildTripleObject( condition );

Expand All @@ -135,15 +162,7 @@ export default class QueryObjectBuilder {
},
predicate: { type: 'path',
pathType: '/',
items: [ {
termType: 'NamedNode',
value: rdfNamespaces.p + condition.propertyId,
},
{
termType: 'NamedNode',
value: rdfNamespaces.ps + condition.propertyId,
},
] },
items: this.buildTriplePredicateItems( condition ) },
object: tripleObject,
},
],
Expand Down
1 change: 1 addition & 0 deletions src/sparql/QueryRepresentation.ts
Expand Up @@ -5,6 +5,7 @@ export type Condition = {
value: string;
datatype: string; // FIXME: make enum?
propertyValueRelation: PropertyValueRelation;
subclasses: boolean;
};

export default interface QueryRepresentation {
Expand Down
1 change: 1 addition & 0 deletions src/store/RootState.ts
Expand Up @@ -27,6 +27,7 @@ export interface ConditionRow {
propertyValueRelationData: {
value: PropertyValueRelation;
};
subclasses: boolean;
readonly conditionId: string;
}

Expand Down
4 changes: 4 additions & 0 deletions src/store/actions.ts
Expand Up @@ -88,6 +88,10 @@ export default ( searchEntityRepository: SearchEntityRepository, metricsCollecto
setOmitLabels( context: ActionContext<RootState, RootState>, omitLabels: boolean ): void {
context.commit( 'setOmitLabels', omitLabels );
},
setSubclasses( context: ActionContext<RootState, RootState>,
payload: { subclasses: boolean; conditionIndex: number } ): void {
context.commit( 'setSubclasses', payload );
},
setErrors( context: ActionContext<RootState, RootState>, errors: Error[] ): void {
context.commit( 'setErrors', errors );
},
Expand Down
6 changes: 6 additions & 0 deletions src/store/getters.ts
Expand Up @@ -27,6 +27,7 @@ export default {
value: getQueryValueFromStoreValue( condition.propertyData.datatype, condition.valueData.value ),
propertyValueRelation: condition.propertyValueRelationData.value,
datatype: condition.propertyData.datatype,
subclasses: condition.subclasses,
};
} ),
...rootState.useLimit && { limit: rootState.limit },
Expand Down Expand Up @@ -87,6 +88,11 @@ export default {
omitLabels( rootState: RootState ): boolean {
return rootState.omitLabels;
},
subclasses( rootState: RootState ) {
return ( conditionIndex: number ): boolean => {
return rootState.conditionRows[ conditionIndex ].subclasses;
};
},
getErrors( rootState: RootState ): Error[] {
return rootState.errors;
},
Expand Down
1 change: 1 addition & 0 deletions src/store/index.ts
Expand Up @@ -31,6 +31,7 @@ export function getFreshConditionRow(): ConditionRow {
propertyValueRelationData: {
value: PropertyValueRelation.Matching,
},
subclasses: false,
conditionId: `condition-id-${Math.random()}`,
};
}
Expand Down
3 changes: 3 additions & 0 deletions src/store/mutations.ts
Expand Up @@ -34,6 +34,9 @@ export default {
setOmitLabels( state: RootState, omitLabels: boolean ): void {
state.omitLabels = omitLabels;
},
setSubclasses( state: RootState, payload: { subclasses: boolean; conditionIndex: number } ): void {
state.conditionRows[ payload.conditionIndex ].subclasses = payload.subclasses;
},
setErrors( state: RootState, errors: Error[] ): void {
state.errors = errors;
},
Expand Down
40 changes: 40 additions & 0 deletions tests/unit/components/QueryCondition.spec.ts
Expand Up @@ -102,6 +102,46 @@ describe( 'QueryCondition.vue', () => {
expect( store.dispatch ).toHaveBeenCalledWith( 'updateValue', { value: userInput, conditionIndex } );
} );

it( 'set subclasses to true when property type is wikibase-item', async () => {

const property = { label: 'postal code', id: 'P123', datatype: 'wikibase-item' };
const propertyGetter = () => () => ( property );
const store = newStore( propertyGetter );
const conditionIndex = 0;
store.dispatch = jest.fn();
const wrapper = shallowMount( QueryCondition, {
store,
localVue,
propsData: {
'condition-index': 0,
},
} );

wrapper.findAllComponents( PropertyLookup ).at( conditionIndex ).vm.$emit( 'input', property );

expect( store.dispatch ).toHaveBeenCalledWith( 'setSubclasses', { subclasses: true, conditionIndex } );
} );

it( 'set subclasses to false when property type is string', async () => {

const property = { label: 'postal code', id: 'P123', datatype: 'string' };
const propertyGetter = () => () => ( property );
const store = newStore( propertyGetter );
const conditionIndex = 0;
store.dispatch = jest.fn();
const wrapper = shallowMount( QueryCondition, {
store,
localVue,
propsData: {
'condition-index': 0,
},
} );

wrapper.findAllComponents( PropertyLookup ).at( conditionIndex ).vm.$emit( 'input', property );

expect( store.dispatch ).toHaveBeenCalledWith( 'setSubclasses', { subclasses: false, conditionIndex } );
} );

it( 'removes current row when the removeCondition button is clicked', async () => {
const store = newStore();
const conditionIndex = 0;
Expand Down
71 changes: 71 additions & 0 deletions tests/unit/sparql/QueryObjectBuilder.spec.ts
Expand Up @@ -53,6 +53,7 @@ describe( 'QueryObjectBuilder', () => {
value: 'XXXX',
datatype: 'string',
propertyValueRelation: PropertyValueRelation.Matching,
subclasses: false,
},
],
omitLabels: true,
Expand Down Expand Up @@ -112,6 +113,7 @@ describe( 'QueryObjectBuilder', () => {
value: 'XXXX',
propertyValueRelation: PropertyValueRelation.Matching,
datatype: 'string',
subclasses: false,
},
],
omitLabels: true,
Expand Down Expand Up @@ -202,6 +204,7 @@ describe( 'QueryObjectBuilder', () => {
value: 'XXXX',
datatype: 'string',
propertyValueRelation: PropertyValueRelation.Matching,
subclasses: false,
},
],
omitLabels: false,
Expand All @@ -210,4 +213,72 @@ describe( 'QueryObjectBuilder', () => {
expect( actual ).toMatchObject( expected );
} );

it( 'with subclasses', () => {
const prefixes = allNamespaces;
const builder = new QueryObjectBuilder();
const expected = {
queryType: 'SELECT',
variables: [
{
termType: 'Variable',
value: 'item',
},
],
where: [
{
type: 'bgp',
triples: [
{
subject: {
termType: 'Variable',
value: 'item',
},
predicate: { type: 'path',
pathType: '/',
items: [ {
termType: 'NamedNode',
value: 'http://www.wikidata.org/prop/P281',
},
{
termType: 'NamedNode',
value: 'http://www.wikidata.org/prop/statement/P281',
},
{
type: 'path',
pathType: '*',
items: [ {
termType: 'NamedNode',
value: 'http://www.wikidata.org/prop/direct/P279',
},
],
},
] },
object: {
termType: 'Literal',
value: 'XXXX',
},
},
],
},
],
type: 'query',
prefixes: prefixes,
};

const actual = builder.buildFromQueryRepresentation( {
conditions: [
{
propertyId: 'P281',
value: 'XXXX',
datatype: 'string',
propertyValueRelation: PropertyValueRelation.Matching,
subclasses: true,
},
],
omitLabels: true,
} );

expect( actual ).toStrictEqual( expected );
} );

} );

0 comments on commit f965872

Please sign in to comment.