Skip to content

Commit 627dd89

Browse files
committed
fix: property flags
1 parent 7da983b commit 627dd89

File tree

6 files changed

+153
-35
lines changed

6 files changed

+153
-35
lines changed

.changeset/dull-icons-own.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hydrofoil/shaperone-playground-examples": patch
3+
---
4+
5+
Horor the canAdd/canRemove flags in language multi select

.changeset/fast-ducks-swim.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hydrofoil/shaperone-core": patch
3+
---
4+
5+
Correctly set intital canAdd/canRemove flag values

demos/examples/LanguageMultiSelect/index.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,26 @@ export const component: (theme: 'lumo' | 'material') => MultiEditorComponent = t
1818
const values = property.objects.map(o => o.object)
1919
const selected = languages.filter(lang => values.find(object => object?.term.equals(lang.term)))
2020

21+
function setValues(e: any) {
22+
const newSelection = e.target.selectedItems
23+
24+
if (newSelection.length > selected.length && !property.canAdd) {
25+
e.target.selectedItems = selected
26+
return
27+
}
28+
29+
if (newSelection.length < selected.length && !property.canRemove) {
30+
e.target.selectedItems = selected
31+
return
32+
}
33+
34+
update(newSelection.map((lang: any) => lang.term))
35+
}
36+
2137
return html`<multiselect-combo-box item-id-path="id" item-label-path="label"
2238
.selectedItems="${selected}"
2339
.items="${languages}"
24-
@change="${(e: any) => { update(e.target.selectedItems.map((lang: any) => lang.term)) }}"></multiselect-combo-box>`
40+
@change="${setValues}"></multiselect-combo-box>`
2541
},
2642
loadDependencies() {
2743
return [

packages/core/models/forms/lib/stateBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ function initialisePropertyShape(params: InitPropertyShapeParams, previous: Prop
7777
}
7878

7979
const editor = editors[0]
80-
const canRemove = !!editor || canRemoveObject(shape, objects.length)
81-
const canAdd = !!editor || canAddObject(shape, objects.length)
80+
const canRemove = canRemoveObject(shape, objects.length)
81+
const canAdd = canAddObject(shape, objects.length)
8282

8383
let selectedEditor: NamedNode | undefined = editor?.term
8484
if (previous) {

packages/core/models/forms/reducers/updateObject.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { FormState, PropertyObjectState } from '../index'
77
import type { FocusNode } from '../../../index'
88
import { EditorsState } from '../../editors'
99
import { nextid } from '../lib/objectid'
10+
import { canAddObject, canRemoveObject } from '../lib/property'
1011

1112
export interface UpdateObjectParams extends BaseParams {
1213
focusNode: FocusNode
@@ -44,6 +45,8 @@ export const setPropertyObjects = formStateReducer((state: FormState, { focusNod
4445
return
4546
}
4647

48+
propertyState.canAdd = canAddObject(property, objects.terms.length)
49+
propertyState.canRemove = canRemoveObject(property, objects.terms.length)
4750
propertyState.objects = objects.map<PropertyObjectState>((object) => {
4851
const suitableEditors = editors.matchSingleEditors({ shape: property, object })
4952
return {

packages/core/test/models/forms/reducers/updateObject.test.ts

Lines changed: 121 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,55 @@ import $rdf from 'rdf-ext'
55
import { expect } from 'chai'
66
import * as sinon from 'sinon'
77
import { setObjectValue, setPropertyObjects } from '../../../../models/forms/reducers/updateObject'
8-
import { RecursivePartial, testFocusNodeState, testObjectState, testState, testStore } from '../util'
8+
import { RecursivePartial, testObjectState, testStore } from '../util'
99
import { propertyShape } from '../../../util'
1010
import { Store } from '../../../../state'
1111
import { FormState } from '../../../../models/forms'
1212

1313
const ex = ns('http://example.com/')
1414

1515
describe('core/models/forms/reducers/updateObject', () => {
16+
let store: Store
17+
let form: symbol
18+
let formState: {
19+
focusNodes: RecursivePartial<FormState['focusNodes']>
20+
focusStack: FormState['focusStack']
21+
}
22+
23+
beforeEach(() => {
24+
({ form, store } = testStore())
25+
formState = store.getState().forms.get(form)!
26+
})
27+
1628
describe('setPropertyObjects', () => {
17-
it('removes all current triples and creates new', () => {
29+
it('removes all current objects and creates new', () => {
1830
// given
1931
const graph = cf({ dataset: $rdf.dataset() })
2032
const focusNode = graph.node(ex.FocusNode)
2133
.addOut(ex.prop, ['foo1', 'foo2'])
2234
const property = propertyShape(graph.blankNode(), {
2335
path: ex.prop,
2436
})
25-
const { form, state } = testState({
26-
form: {
27-
focusNodes: {
28-
...testFocusNodeState(focusNode, {
29-
properties: [{
30-
shape: property,
31-
objects: [],
32-
name: 'prop',
33-
canRemove: true,
34-
canAdd: true,
35-
editors: [],
36-
selectedEditor: undefined,
37-
}],
38-
}),
39-
},
37+
formState.focusNodes = {
38+
[focusNode.value]: {
39+
properties: [{
40+
shape: property,
41+
objects: [],
42+
name: 'prop',
43+
canRemove: true,
44+
canAdd: true,
45+
editors: [],
46+
selectedEditor: undefined,
47+
}],
4048
},
41-
})
49+
}
4250

4351
// when
44-
const after = setPropertyObjects(state, {
52+
const after = setPropertyObjects(store.getState().forms, {
4553
focusNode,
4654
form,
4755
property,
48-
editors: testStore().store.getState().editors,
56+
editors: store.getState().editors,
4957
objects: graph.node([$rdf.literal('bar1'), $rdf.literal('bar2'), $rdf.literal('bar3')]),
5058
})
5159

@@ -55,21 +63,102 @@ describe('core/models/forms/reducers/updateObject', () => {
5563
expect(values).to.have.length(3)
5664
expect(values).to.include.members(['bar1', 'bar2', 'bar3'])
5765
})
58-
})
5966

60-
describe('setObjectValue', () => {
61-
let store: Store
62-
let form: symbol
63-
let formState: {
64-
focusNodes: RecursivePartial<FormState['focusNodes']>
65-
focusStack: FormState['focusStack']
66-
}
67-
68-
beforeEach(() => {
69-
({ form, store } = testStore())
70-
formState = store.getState().forms.get(form)!
67+
it('flips canAdd flag when max reached', () => {
68+
// given
69+
const graph = cf({ dataset: $rdf.dataset() })
70+
const focusNode = graph.node(ex.FocusNode)
71+
const property = propertyShape(graph.blankNode(), {
72+
path: ex.prop,
73+
maxCount: 2,
74+
})
75+
formState.focusNodes = {
76+
[focusNode.value]: {
77+
properties: [{
78+
shape: property,
79+
canAdd: true,
80+
}],
81+
},
82+
}
83+
84+
// when
85+
const after = setPropertyObjects(store.getState().forms, {
86+
focusNode,
87+
form,
88+
property,
89+
editors: testStore().store.getState().editors,
90+
objects: graph.node([$rdf.literal('foo'), $rdf.literal('bar')]),
91+
})
92+
93+
// then
94+
expect(after.get(form)?.focusNodes[focusNode.value].properties[0].canAdd).to.be.false
95+
})
96+
97+
it('sets canRemove flag when min reached', () => {
98+
// given
99+
const graph = cf({ dataset: $rdf.dataset() })
100+
const focusNode = graph.node(ex.FocusNode)
101+
const property = propertyShape(graph.blankNode(), {
102+
path: ex.prop,
103+
minCount: 2,
104+
})
105+
formState.focusNodes = {
106+
[focusNode.value]: {
107+
properties: [{
108+
shape: property,
109+
canRemove: true,
110+
}],
111+
},
112+
}
113+
114+
// when
115+
const after = setPropertyObjects(store.getState().forms, {
116+
focusNode,
117+
form,
118+
property,
119+
editors: testStore().store.getState().editors,
120+
objects: graph.node([$rdf.literal('foo')]),
121+
})
122+
123+
// then
124+
expect(after.get(form)?.focusNodes[focusNode.value].properties[0].canRemove).to.be.false
71125
})
72126

127+
it('sets canAdd/canRemove flags to true', () => {
128+
// given
129+
const graph = cf({ dataset: $rdf.dataset() })
130+
const focusNode = graph.node(ex.FocusNode)
131+
const property = propertyShape(graph.blankNode(), {
132+
path: ex.prop,
133+
minCount: 1,
134+
maxCount: 4,
135+
})
136+
formState.focusNodes = {
137+
[focusNode.value]: {
138+
properties: [{
139+
shape: property,
140+
canAdd: false,
141+
canRemove: false,
142+
}],
143+
},
144+
}
145+
146+
// when
147+
const after = setPropertyObjects(store.getState().forms, {
148+
focusNode,
149+
form,
150+
property,
151+
editors: testStore().store.getState().editors,
152+
objects: graph.node([$rdf.literal('foo'), $rdf.literal('bar')]),
153+
})
154+
155+
// then
156+
expect(after.get(form)?.focusNodes[focusNode.value].properties[0].canAdd).to.be.true
157+
expect(after.get(form)?.focusNodes[focusNode.value].properties[0].canRemove).to.be.true
158+
})
159+
})
160+
161+
describe('setObjectValue', () => {
73162
it('recalculates editors', () => {
74163
// given
75164
const graph = cf({ dataset: $rdf.dataset() })

0 commit comments

Comments
 (0)