From 358db18b0e9c914080608f0be076450ea2bbcbbc Mon Sep 17 00:00:00 2001 From: tpluscode Date: Sat, 5 Nov 2022 19:51:09 +0100 Subject: [PATCH 1/3] fix: no default node for select editors --- .changeset/tidy-suns-relax.md | 5 ++ .../models/resources/lib/objectValue.test.ts | 70 +++++++++++++++---- .../effects/forms/createFocusNodeState.ts | 2 +- .../core/models/resources/lib/objectValue.ts | 21 +++++- packages/testing/models/form.ts | 6 +- 5 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 .changeset/tidy-suns-relax.md diff --git a/.changeset/tidy-suns-relax.md b/.changeset/tidy-suns-relax.md new file mode 100644 index 00000000..875ccd07 --- /dev/null +++ b/.changeset/tidy-suns-relax.md @@ -0,0 +1,5 @@ +--- +"@hydrofoil/shaperone-core": patch +--- + +Do not create a new node when the editor is a `dash:*SelectEditor` diff --git a/packages/core-tests/models/resources/lib/objectValue.test.ts b/packages/core-tests/models/resources/lib/objectValue.test.ts index 5286b9e1..e03b30a0 100644 --- a/packages/core-tests/models/resources/lib/objectValue.test.ts +++ b/packages/core-tests/models/resources/lib/objectValue.test.ts @@ -9,6 +9,7 @@ import { defaultValue } from '@hydrofoil/shaperone-core/models/resources/lib/obj import { propertyShape } from '@shaperone/testing/util.js' import { Term } from 'rdf-js' import sh1 from '@hydrofoil/shaperone-core/ns.js' +import { testObjectState } from '@shaperone/testing/models/form.js' describe('core/models/resources/lib/defaultValue', () => { it('returns default value from property', () => { @@ -17,9 +18,11 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { defaultValue: literal('foo', xsd.anySimpleType), }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer?.term).to.deep.eq(literal('foo', xsd.anySimpleType)) @@ -30,9 +33,11 @@ describe('core/models/resources/lib/defaultValue', () => { const graph = cf({ dataset: $rdf.dataset() }) const property = propertyShape(graph.blankNode(), { }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer).to.be.null @@ -44,9 +49,11 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { class: foaf.Person, }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer?.term?.termType).to.eq('BlankNode') @@ -59,9 +66,11 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { nodeKind: sh.IRIOrLiteral, }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer).to.be.null @@ -73,10 +82,12 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { nodeKind: sh.IRI, }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const first = defaultValue(property, graph.blankNode()) - const second = defaultValue(property, graph.blankNode()) + const first = defaultValue({ property, focusNode, object }) + const second = defaultValue({ property, focusNode, object }) // then expect(first?.term).not.to.deep.eq(second) @@ -89,9 +100,11 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind: sh.IRI, [sh1.iriPrefix.value]: 'http://example.com/foo/', }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const term = defaultValue(property, graph.blankNode())?.term + const term = defaultValue({ property, focusNode, object })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -105,9 +118,11 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind: sh.BlankNodeOrIRI, [sh1.iriPrefix.value]: 'http://example.com/foo/', }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const term = defaultValue(property, graph.blankNode())?.term + const term = defaultValue({ property, focusNode, object })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -121,9 +136,11 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind: sh.IRIOrLiteral, [sh1.iriPrefix.value]: 'http://example.com/foo/', }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const term = defaultValue(property, graph.blankNode())?.term + const term = defaultValue({ property, focusNode, object })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -144,9 +161,11 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { nodeKind, }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer?.term?.termType).to.eq(termType) @@ -160,9 +179,11 @@ describe('core/models/resources/lib/defaultValue', () => { class: foaf.Agent, [sh1.iriPrefix.value]: 'http://example.com/foo/', }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer?.out(rdf.type).term).to.deep.eq(foaf.Agent) @@ -177,12 +198,37 @@ describe('core/models/resources/lib/defaultValue', () => { [dash.editor.value]: dash.InstancesSelectEditor, [sh1.iriPrefix.value]: 'http://example.com/foo/', }) + const focusNode = graph.blankNode() + const object = testObjectState() // when - const pointer = defaultValue(property, graph.blankNode()) + const pointer = defaultValue({ property, focusNode, object }) // then expect(pointer?.out(rdf.type).term).to.be.undefined }) }) + + const selectEditors = [ + dash.EnumSelectEditor, + dash.InstancesSelectEditor, + dash.AutoCompleteEditor, + ] + + selectEditors.forEach((editor) => { + it(`does not create a node when editor is ${editor.value}`, () => { + // given + const graph = cf({ dataset: $rdf.dataset() }) + const property = propertyShape(graph.blankNode(), { + nodeKind: sh.IRI, + }) + const object = testObjectState(undefined, { + selectedEditor: editor, + }) + const focusNode = graph.blankNode() + + // then + expect(defaultValue({ property, focusNode, object })).to.be.null + }) + }) }) diff --git a/packages/core/models/resources/effects/forms/createFocusNodeState.ts b/packages/core/models/resources/effects/forms/createFocusNodeState.ts index 4727a876..caf430f9 100644 --- a/packages/core/models/resources/effects/forms/createFocusNodeState.ts +++ b/packages/core/models/resources/effects/forms/createFocusNodeState.ts @@ -33,7 +33,7 @@ export default function createFocusNodeState(store: Store) { if (object.object) { return { shouldNotify: false } } - const [value] = defaultValue(property.shape, focusNode)?.toArray() || [] + const [value] = defaultValue({ property: property.shape, focusNode, object })?.toArray() || [] if (!value) { return { shouldNotify: false } } diff --git a/packages/core/models/resources/lib/objectValue.ts b/packages/core/models/resources/lib/objectValue.ts index 808fe117..f93428ce 100644 --- a/packages/core/models/resources/lib/objectValue.ts +++ b/packages/core/models/resources/lib/objectValue.ts @@ -6,8 +6,15 @@ import type { NamedNode } from 'rdf-js' import { nanoid } from 'nanoid' import sh1 from '../../../ns.js' import type { FocusNode } from '../../../index' +import { PropertyObjectState } from '../../forms' -export function defaultValue(property: PropertyShape, focusNode: FocusNode): MultiPointer | null { +interface DefaultValue { + property: PropertyShape + object: PropertyObjectState + focusNode: FocusNode +} + +export function defaultValue({ property, focusNode, object }: DefaultValue): MultiPointer | null { if (property.defaultValue) { return focusNode.node(property.defaultValue) } @@ -17,6 +24,10 @@ export function defaultValue(property: PropertyShape, focusNode: FocusNode): Mul nodeKind = sh.BlankNode } + if (shouldNotCreateNode(object)) { + return null + } + switch (nodeKind?.value) { case 'http://www.w3.org/ns/shacl#IRI': case 'http://www.w3.org/ns/shacl#IRIOrLiteral': @@ -29,6 +40,14 @@ export function defaultValue(property: PropertyShape, focusNode: FocusNode): Mul } } +function shouldNotCreateNode(object: PropertyObjectState) { + const editor = object.selectedEditor + + return editor && (editor.equals(dash.EnumSelectEditor) || + editor.equals(dash.InstancesSelectEditor) || + editor.equals(dash.AutoCompleteEditor)) +} + function createResourceNode(property: PropertyShape, nodeKind: NodeKind, focusNode: FocusNode) { const uriStart = property.pointer.out(sh1.iriPrefix).value let resourceNode: GraphPointer = focusNode.blankNode() diff --git a/packages/testing/models/form.ts b/packages/testing/models/form.ts index 0823842c..e7bd8c36 100644 --- a/packages/testing/models/form.ts +++ b/packages/testing/models/form.ts @@ -98,7 +98,7 @@ export function testObjectState(object?: GraphPointer, init: RecursivePartial = { @@ -165,3 +165,7 @@ export function testStore({ graph = datasetFactory.defaultGraph(), factory: { da }, } } + +function isMergeableObject(arg: any) { + return !('termType' in arg) +} From 322b0dc2168d60ccb7ab7777fafd7f5c308ad2b5 Mon Sep 17 00:00:00 2001 From: tpluscode Date: Sat, 5 Nov 2022 21:31:20 +0100 Subject: [PATCH 2/3] refactor: move selection of editors from reducer to effect --- .../models/forms/effects/addObject.test.ts | 6 +-- .../forms/reducers/addFormField.test.ts | 34 ++++++++------- .../effects/forms/addFormField.test.ts | 3 ++ .../models/resources/lib/objectValue.test.ts | 41 ++++++------------- .../core/models/forms/effects/addObject.ts | 20 ++++++++- .../models/forms/reducers/addFormField.ts | 21 ++-------- .../resources/effects/forms/addFormField.ts | 4 +- .../effects/forms/createFocusNodeState.ts | 6 ++- .../core/models/resources/lib/objectValue.ts | 15 +++---- packages/testing/models/form.ts | 6 +-- 10 files changed, 74 insertions(+), 82 deletions(-) diff --git a/packages/core-tests/models/forms/effects/addObject.test.ts b/packages/core-tests/models/forms/effects/addObject.test.ts index 682c9e2a..53320529 100644 --- a/packages/core-tests/models/forms/effects/addObject.test.ts +++ b/packages/core-tests/models/forms/effects/addObject.test.ts @@ -22,12 +22,12 @@ describe('models/forms/effects/addObject', () => { // given const property = propertyShape() const focusNode = cf({ dataset: $rdf.dataset() }).blankNode() - const matchedEditors: SingleEditorMatch[] = [{ + const editors: SingleEditorMatch[] = [{ term: dash.TextFieldEditor, score: 5, meta: {}, }] - store.getState().editors.matchSingleEditors = () => matchedEditors + store.getState().editors.matchSingleEditors = () => editors // when addObject(store)({ @@ -42,7 +42,7 @@ describe('models/forms/effects/addObject', () => { form, property, focusNode, - matchedEditors, + editors, })) }) }) diff --git a/packages/core-tests/models/forms/reducers/addFormField.test.ts b/packages/core-tests/models/forms/reducers/addFormField.test.ts index 26f0c8e1..83e0ecef 100644 --- a/packages/core-tests/models/forms/reducers/addFormField.test.ts +++ b/packages/core-tests/models/forms/reducers/addFormField.test.ts @@ -20,7 +20,7 @@ describe('core/models/forms/reducers/addObject', () => { }) const focusNode = graph.node(ex.FocusNode) const { form, store } = testStore() - const { editors, forms } = store.getState() + const { forms } = store.getState() forms.get(form)!.focusNodes = testFocusNodeState(focusNode, { properties: [testPropertyState(focusNode.blankNode(), { @@ -38,8 +38,8 @@ describe('core/models/forms/reducers/addObject', () => { form, property, focusNode, - matchedEditors: [], - editors, + editors: [], + selectedEditor: undefined, }) // then @@ -56,7 +56,7 @@ describe('core/models/forms/reducers/addObject', () => { }) const focusNode = graph.node(ex.FocusNode) const { form, store } = testStore() - const { editors, forms } = store.getState() + const { forms } = store.getState() forms.get(form)!.focusNodes = testFocusNodeState(focusNode, { properties: [testPropertyState(focusNode.blankNode(), { @@ -74,8 +74,8 @@ describe('core/models/forms/reducers/addObject', () => { form, property, focusNode, - matchedEditors: [], - editors, + editors: [], + selectedEditor: undefined, }) // then @@ -92,7 +92,7 @@ describe('core/models/forms/reducers/addObject', () => { }) const focusNode = graph.node(ex.FocusNode) const { form, store } = testStore() - const { editors, forms } = store.getState() + const { forms } = store.getState() forms.get(form)!.focusNodes = testFocusNodeState(focusNode, { properties: [testPropertyState(focusNode.blankNode(), { @@ -110,8 +110,8 @@ describe('core/models/forms/reducers/addObject', () => { form, property, focusNode, - matchedEditors: [], - editors, + editors: [], + selectedEditor: undefined, }) // then @@ -127,7 +127,7 @@ describe('core/models/forms/reducers/addObject', () => { }) const focusNode = graph.node(ex.FocusNode) const { form, store } = testStore() - const { editors, forms } = store.getState() + const { forms } = store.getState() forms.get(form)!.focusNodes = testFocusNodeState(focusNode, { properties: [testPropertyState(focusNode.blankNode(), { @@ -145,8 +145,8 @@ describe('core/models/forms/reducers/addObject', () => { form, property, focusNode, - matchedEditors: [], - editors, + editors: [], + selectedEditor: undefined, }) // then @@ -163,7 +163,7 @@ describe('core/models/forms/reducers/addObject', () => { }) const focusNode = graph.node(ex.FocusNode) const { form, store } = testStore() - const { editors, forms } = store.getState() + const { forms } = store.getState() forms.get(form)!.focusNodes = testFocusNodeState(focusNode, { properties: [testPropertyState(focusNode.blankNode(), { @@ -181,12 +181,16 @@ describe('core/models/forms/reducers/addObject', () => { form, property, focusNode, - matchedEditors: [{ + editors: [{ + term: dash.FooEditor, + score: 100, + meta: {} as any, + }, { term: dash.TextFieldEditor, score: 10, meta: {} as any, }], - editors, + selectedEditor: dash.FooEditor, }) // then diff --git a/packages/core-tests/models/resources/effects/forms/addFormField.test.ts b/packages/core-tests/models/resources/effects/forms/addFormField.test.ts index ab413f95..8d8f2044 100644 --- a/packages/core-tests/models/resources/effects/forms/addFormField.test.ts +++ b/packages/core-tests/models/resources/effects/forms/addFormField.test.ts @@ -42,6 +42,7 @@ describe('models/resources/effects/forms/addFormField', () => { form, focusNode, property, + selectedEditor: undefined, }) // then @@ -64,6 +65,7 @@ describe('models/resources/effects/forms/addFormField', () => { form, focusNode, property, + selectedEditor: undefined, }) // then @@ -88,6 +90,7 @@ describe('models/resources/effects/forms/addFormField', () => { form, focusNode, property, + selectedEditor: undefined, }) // then diff --git a/packages/core-tests/models/resources/lib/objectValue.test.ts b/packages/core-tests/models/resources/lib/objectValue.test.ts index e03b30a0..704f4097 100644 --- a/packages/core-tests/models/resources/lib/objectValue.test.ts +++ b/packages/core-tests/models/resources/lib/objectValue.test.ts @@ -9,7 +9,6 @@ import { defaultValue } from '@hydrofoil/shaperone-core/models/resources/lib/obj import { propertyShape } from '@shaperone/testing/util.js' import { Term } from 'rdf-js' import sh1 from '@hydrofoil/shaperone-core/ns.js' -import { testObjectState } from '@shaperone/testing/models/form.js' describe('core/models/resources/lib/defaultValue', () => { it('returns default value from property', () => { @@ -19,10 +18,9 @@ describe('core/models/resources/lib/defaultValue', () => { defaultValue: literal('foo', xsd.anySimpleType), }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer?.term).to.deep.eq(literal('foo', xsd.anySimpleType)) @@ -34,10 +32,9 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer).to.be.null @@ -50,10 +47,9 @@ describe('core/models/resources/lib/defaultValue', () => { class: foaf.Person, }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer?.term?.termType).to.eq('BlankNode') @@ -67,10 +63,9 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind: sh.IRIOrLiteral, }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer).to.be.null @@ -83,11 +78,10 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind: sh.IRI, }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const first = defaultValue({ property, focusNode, object }) - const second = defaultValue({ property, focusNode, object }) + const first = defaultValue({ property, focusNode }) + const second = defaultValue({ property, focusNode }) // then expect(first?.term).not.to.deep.eq(second) @@ -101,10 +95,9 @@ describe('core/models/resources/lib/defaultValue', () => { [sh1.iriPrefix.value]: 'http://example.com/foo/', }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const term = defaultValue({ property, focusNode, object })?.term + const term = defaultValue({ property, focusNode })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -119,10 +112,9 @@ describe('core/models/resources/lib/defaultValue', () => { [sh1.iriPrefix.value]: 'http://example.com/foo/', }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const term = defaultValue({ property, focusNode, object })?.term + const term = defaultValue({ property, focusNode })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -137,10 +129,9 @@ describe('core/models/resources/lib/defaultValue', () => { [sh1.iriPrefix.value]: 'http://example.com/foo/', }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const term = defaultValue({ property, focusNode, object })?.term + const term = defaultValue({ property, focusNode })?.term // then expect(term?.termType).to.eq('NamedNode') @@ -162,10 +153,9 @@ describe('core/models/resources/lib/defaultValue', () => { nodeKind, }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer?.term?.termType).to.eq(termType) @@ -180,10 +170,9 @@ describe('core/models/resources/lib/defaultValue', () => { [sh1.iriPrefix.value]: 'http://example.com/foo/', }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer?.out(rdf.type).term).to.deep.eq(foaf.Agent) @@ -199,10 +188,9 @@ describe('core/models/resources/lib/defaultValue', () => { [sh1.iriPrefix.value]: 'http://example.com/foo/', }) const focusNode = graph.blankNode() - const object = testObjectState() // when - const pointer = defaultValue({ property, focusNode, object }) + const pointer = defaultValue({ property, focusNode }) // then expect(pointer?.out(rdf.type).term).to.be.undefined @@ -222,13 +210,10 @@ describe('core/models/resources/lib/defaultValue', () => { const property = propertyShape(graph.blankNode(), { nodeKind: sh.IRI, }) - const object = testObjectState(undefined, { - selectedEditor: editor, - }) const focusNode = graph.blankNode() // then - expect(defaultValue({ property, focusNode, object })).to.be.null + expect(defaultValue({ property, focusNode, editor })).to.be.null }) }) }) diff --git a/packages/core/models/forms/effects/addObject.ts b/packages/core/models/forms/effects/addObject.ts index ca9064eb..2929b7c1 100644 --- a/packages/core/models/forms/effects/addObject.ts +++ b/packages/core/models/forms/effects/addObject.ts @@ -1,23 +1,39 @@ import { PropertyShape } from '@rdfine/shacl' +import { NamedNode } from 'rdf-js' import type { Store } from '../../../state' import { FocusNode } from '../../../index' import { BaseParams } from '../../index' +import { SingleEditorMatch } from '../../editors' export function addObject(store: Store) { const dispatch = store.getDispatch() return function ({ form, property, focusNode }: { focusNode: FocusNode; property: PropertyShape } & BaseParams) { - const { editors, resources } = store.getState() + const { editors: editorsState, resources } = store.getState() const graph = resources.get(form)?.graph if (!graph) { return } + const matchedEditors = editorsState.matchSingleEditors({ shape: property }) + let editors: SingleEditorMatch[] + let selectedEditor: NamedNode | undefined + if (property.editor?.id.termType === 'NamedNode') { + selectedEditor = property.editor.id + editors = [ + { term: selectedEditor, score: null, meta: editorsState.metadata.node(selectedEditor) }, + ...matchedEditors, + ] + } else { + editors = matchedEditors + selectedEditor = editors[0]?.term + } + dispatch.forms.addFormField({ form, property, focusNode, - matchedEditors: editors.matchSingleEditors({ shape: property }), editors, + selectedEditor, }) } } diff --git a/packages/core/models/forms/reducers/addFormField.ts b/packages/core/models/forms/reducers/addFormField.ts index 727187a8..98953a07 100644 --- a/packages/core/models/forms/reducers/addFormField.ts +++ b/packages/core/models/forms/reducers/addFormField.ts @@ -4,30 +4,17 @@ import type { FocusNode } from '../../..' import { objectStateProducer } from '../objectStateProducer.js' import { formStateReducer, BaseParams } from '../../index.js' import { canAddObject, canRemoveObject } from '../lib/property.js' -import type { EditorsState, SingleEditorMatch } from '../../editors' +import type { SingleEditorMatch } from '../../editors' import { nextid } from '../lib/objectid.js' export interface Params extends BaseParams { focusNode: FocusNode property: PropertyShape - matchedEditors: SingleEditorMatch[] - editors: EditorsState + editors: SingleEditorMatch[] + selectedEditor: NamedNode | undefined } -export const addFormField = formStateReducer(objectStateProducer((state, { property, editors: { metadata }, matchedEditors }, currentProperty) => { - let editors: SingleEditorMatch[] - let selectedEditor: NamedNode | undefined - if (property.editor?.id.termType === 'NamedNode') { - selectedEditor = property.editor.id - editors = [ - { term: selectedEditor, score: null, meta: metadata.node(selectedEditor) }, - ...matchedEditors, - ] - } else { - editors = matchedEditors - selectedEditor = editors[0]?.term - } - +export const addFormField = formStateReducer(objectStateProducer((state, { property, editors, selectedEditor }, currentProperty) => { currentProperty.objects.push({ key: nextid(), editors, diff --git a/packages/core/models/resources/effects/forms/addFormField.ts b/packages/core/models/resources/effects/forms/addFormField.ts index 5fe7fb6a..cee4aa56 100644 --- a/packages/core/models/resources/effects/forms/addFormField.ts +++ b/packages/core/models/resources/effects/forms/addFormField.ts @@ -6,7 +6,7 @@ import { defaultValue } from '../../lib/objectValue.js' export default function (store: Store) { const dispatch = store.getDispatch() - return function ({ form, focusNode, property }: Pick): void { + return function ({ form, focusNode, property, selectedEditor }: Pick): void { const { resources, editors } = store.getState() const state = resources.get(form) @@ -14,7 +14,7 @@ export default function (store: Store) { return } - const pointer = defaultValue(property, focusNode) + const pointer = defaultValue({ property, focusNode, editor: selectedEditor }) const predicate = property.getPathProperty(true).id if (!pointer || focusNode.has(predicate, pointer).terms.length) { return diff --git a/packages/core/models/resources/effects/forms/createFocusNodeState.ts b/packages/core/models/resources/effects/forms/createFocusNodeState.ts index caf430f9..d3c93e20 100644 --- a/packages/core/models/resources/effects/forms/createFocusNodeState.ts +++ b/packages/core/models/resources/effects/forms/createFocusNodeState.ts @@ -33,7 +33,11 @@ export default function createFocusNodeState(store: Store) { if (object.object) { return { shouldNotify: false } } - const [value] = defaultValue({ property: property.shape, focusNode, object })?.toArray() || [] + const [value] = defaultValue({ + property: property.shape, + focusNode, + editor: object.selectedEditor, + })?.toArray() || [] if (!value) { return { shouldNotify: false } } diff --git a/packages/core/models/resources/lib/objectValue.ts b/packages/core/models/resources/lib/objectValue.ts index f93428ce..074879f3 100644 --- a/packages/core/models/resources/lib/objectValue.ts +++ b/packages/core/models/resources/lib/objectValue.ts @@ -6,15 +6,14 @@ import type { NamedNode } from 'rdf-js' import { nanoid } from 'nanoid' import sh1 from '../../../ns.js' import type { FocusNode } from '../../../index' -import { PropertyObjectState } from '../../forms' interface DefaultValue { property: PropertyShape - object: PropertyObjectState + editor?: NamedNode focusNode: FocusNode } -export function defaultValue({ property, focusNode, object }: DefaultValue): MultiPointer | null { +export function defaultValue({ property, focusNode, editor }: DefaultValue): MultiPointer | null { if (property.defaultValue) { return focusNode.node(property.defaultValue) } @@ -24,7 +23,7 @@ export function defaultValue({ property, focusNode, object }: DefaultValue): Mul nodeKind = sh.BlankNode } - if (shouldNotCreateNode(object)) { + if (editor && shouldNotCreateNode(editor)) { return null } @@ -40,12 +39,10 @@ export function defaultValue({ property, focusNode, object }: DefaultValue): Mul } } -function shouldNotCreateNode(object: PropertyObjectState) { - const editor = object.selectedEditor - - return editor && (editor.equals(dash.EnumSelectEditor) || +function shouldNotCreateNode(editor: NamedNode) { + return editor.equals(dash.EnumSelectEditor) || editor.equals(dash.InstancesSelectEditor) || - editor.equals(dash.AutoCompleteEditor)) + editor.equals(dash.AutoCompleteEditor) } function createResourceNode(property: PropertyShape, nodeKind: NodeKind, focusNode: FocusNode) { diff --git a/packages/testing/models/form.ts b/packages/testing/models/form.ts index e7bd8c36..0823842c 100644 --- a/packages/testing/models/form.ts +++ b/packages/testing/models/form.ts @@ -98,7 +98,7 @@ export function testObjectState(object?: GraphPointer, init: RecursivePartial = { @@ -165,7 +165,3 @@ export function testStore({ graph = datasetFactory.defaultGraph(), factory: { da }, } } - -function isMergeableObject(arg: any) { - return !('termType' in arg) -} From 86bd1feb940639050800640fddb20fd4e3fdb32e Mon Sep 17 00:00:00 2001 From: tpluscode Date: Sat, 5 Nov 2022 21:47:27 +0100 Subject: [PATCH 3/3] test: missing test case --- .../models/forms/effects/addObject.test.ts | 32 ++++++++++++++++++- packages/testing/package.json | 1 + packages/testing/util.ts | 3 +- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/core-tests/models/forms/effects/addObject.test.ts b/packages/core-tests/models/forms/effects/addObject.test.ts index 53320529..1b2cfe84 100644 --- a/packages/core-tests/models/forms/effects/addObject.test.ts +++ b/packages/core-tests/models/forms/effects/addObject.test.ts @@ -3,7 +3,7 @@ import cf from 'clownface' import $rdf from 'rdf-ext' import { expect } from 'chai' import { sinon } from '@shaperone/testing' -import { dash } from '@tpluscode/rdf-ns-builders' +import { dash } from '@tpluscode/rdf-ns-builders/loose' import { testStore } from '@shaperone/testing/models/form.js' import { addObject } from '@hydrofoil/shaperone-core/models/forms/effects/addObject.js' import { Store } from '@hydrofoil/shaperone-core/state' @@ -43,6 +43,36 @@ describe('models/forms/effects/addObject', () => { property, focusNode, editors, + selectedEditor: dash.TextFieldEditor, + })) + }) + + it('takes property editor as default match', () => { + // given + const property = propertyShape({ + editor: dash.FooEditor, + }) + const focusNode = cf({ dataset: $rdf.dataset() }).blankNode() + store.getState().editors.matchSingleEditors = () => [{ + term: dash.TextFieldEditor, + score: 5, + meta: {}, + }] + + // when + addObject(store)({ + form, + property, + focusNode, + }) + + // then + const dispatch = store.getDispatch() + expect(dispatch.forms.addFormField).to.have.been.calledWith(sinon.match({ + form, + property, + focusNode, + selectedEditor: dash.FooEditor, })) }) }) diff --git a/packages/testing/package.json b/packages/testing/package.json index 50afb241..fc5076af 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -7,6 +7,7 @@ "@hydrofoil/shaperone-core": "*", "@rdf-esm/dataset": "^0.5.1", "@rdf-esm/namespace": "^0.5.2", + "@rdfine/dash": "^0.2.4", "@rdfine/shacl": "^0.8.7", "@tpluscode/rdfine": "^0.5.39", "@tpluscode/rdf-ns-builders": "^2.0.0", diff --git a/packages/testing/util.ts b/packages/testing/util.ts index dad94c5d..025f2476 100644 --- a/packages/testing/util.ts +++ b/packages/testing/util.ts @@ -4,8 +4,9 @@ import RdfResource, { Initializer, ResourceIdentifier } from '@tpluscode/rdfine/ import clownface, { GraphPointer } from 'clownface' import * as $rdf from '@rdf-esm/dataset' import PropertyShapeEx from '@hydrofoil/shaperone-core/models/shapes/lib/PropertyShape.js' +import { PropertyShapeMixinEx } from '@rdfine/dash/extensions/sh' -RdfResource.factory.addMixin(PropertyShapeEx) +RdfResource.factory.addMixin(PropertyShapeEx, PropertyShapeMixinEx) function isPointer(arg: GraphPointer | Initializer | undefined): arg is GraphPointer { return (arg && '_context' in arg) || false