Skip to content

Commit 0dd8886

Browse files
authored
Merge pull request #202 from ls1intum/fix--selectable-fix-after-deleting-selected-item
fix: deselect after deleting an item
2 parents 98f772f + 44cb94a commit 0dd8886

File tree

7 files changed

+89
-31
lines changed

7 files changed

+89
-31
lines changed

library/lib/App.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,18 @@ function App({ onReactFlowInit }: AppProps) {
4949
diagramId: state.diagramId,
5050
}))
5151
)
52-
const { diagramMode } = useMetadataStore(
53-
useShallow((state) => ({
54-
readonlyDiagram: state.readonly,
55-
diagramMode: state.mode,
56-
}))
57-
)
5852

59-
const { onNodeDragStop } = useNodeDragStop()
60-
const { onDragOver } = useDragOver()
53+
const diagramMode = useMetadataStore(useShallow((state) => state.mode))
54+
const isDiagramModifiable = useDiagramModifiable()
55+
56+
const onNodeDragStop = useNodeDragStop()
57+
const onDragOver = useDragOver()
6158
const { onConnect, onConnectEnd, onConnectStart, onEdgesDelete } =
6259
useConnect()
63-
const { onReconnect } = useReconnect()
60+
const onReconnect = useReconnect()
6461
const { onBeforeDelete, onNodeDoubleClick, onEdgeDoubleClick } =
6562
useElementInteractions()
6663

67-
const isDiagramModifiable = useDiagramModifiable()
68-
6964
return (
7065
<div style={{ display: "flex", flex: 1 }}>
7166
{diagramMode === ApollonMode.Modelling && <Sidebar />}

library/lib/edges/GenericEdge.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const GenericEdge = ({
6565
const { handleDelete } = useToolbar({ id })
6666
const { getNode, getEdges, screenToFlowPosition, getNodes } = useReactFlow()
6767
const [customPoints, setCustomPoints] = useState<IPoint[]>([])
68-
const { onReconnect } = useReconnect()
68+
const onReconnect = useReconnect()
6969
const { setEdges, assessments } = useDiagramStore(
7070
useShallow((state) => ({
7171
setEdges: state.setEdges,

library/lib/hooks/useDragOver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ export const useDragOver = () => {
66
event.dataTransfer.dropEffect = "move"
77
}, [])
88

9-
return { onDragOver }
9+
return onDragOver
1010
}

library/lib/hooks/useNodeDragStop.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,5 +105,5 @@ export const useNodeDragStop = () => {
105105
[screenToFlowPosition, nodes, getIntersectingNodes, setNodes]
106106
)
107107

108-
return { onNodeDragStop }
108+
return onNodeDragStop
109109
}

library/lib/hooks/useReconnect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ export const useReconnect = () => {
2424
},
2525
[]
2626
)
27-
return { onReconnect }
27+
return onReconnect
2828
}

library/lib/store/diagramStore.ts

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ export type DiagramStore = {
5151
onNodesChange: OnNodesChange
5252
onEdgesChange: OnEdgesChange
5353
reset: () => void
54-
setSelectedElementsId: (elementId: string | null) => void
54+
setSelectedElementsId: (
55+
payload: string[] | ((edges: string[]) => string[])
56+
) => void
5557
getAssessment: (id: string) => Assessment | undefined
5658
setAssessments: (
5759
assessments:
@@ -75,18 +77,13 @@ export const createDiagramStore = (
7577
set({ diagramId }, undefined, "setDiagramId")
7678
},
7779

78-
setSelectedElementsId: (elementId) => {
79-
if (elementId === null) {
80-
set({ selectedElementIds: [] }, undefined, "setSelectedElementsId")
81-
} else {
82-
set(
83-
(state) => ({
84-
selectedElementIds: [...state.selectedElementIds, elementId],
85-
}),
86-
undefined,
87-
"setSelectedElementsId"
88-
)
89-
}
80+
setSelectedElementsId: (payload) => {
81+
const selectedElementIds =
82+
typeof payload === "function"
83+
? payload(get().selectedElementIds)
84+
: payload
85+
86+
set({ selectedElementIds }, undefined, "setNodes")
9087
},
9188
addNode: (node) => {
9289
ydoc.transact(() => {
@@ -207,6 +204,15 @@ export const createDiagramStore = (
207204
if (change.type === "add" || change.type === "replace") {
208205
getNodesMap(ydoc).set(change.item.id, change.item)
209206
} else if (change.type === "remove") {
207+
set(
208+
(state) => ({
209+
selectedElementIds: state.selectedElementIds.filter(
210+
(id) => id !== change.id
211+
),
212+
}),
213+
undefined,
214+
"onNodesChange-remove-selectedElementIds"
215+
)
210216
const deletedNode = getNodesMap(ydoc).get(change.id)
211217
if (deletedNode) {
212218
const connectedEdges = getConnectedEdges(
@@ -286,6 +292,15 @@ export const createDiagramStore = (
286292
if (change.type === "add" || change.type === "replace") {
287293
getEdgesMap(ydoc).set(change.item.id, change.item)
288294
} else if (change.type === "remove") {
295+
set(
296+
(state) => ({
297+
selectedElementIds: state.selectedElementIds.filter(
298+
(id) => id !== change.id
299+
),
300+
}),
301+
undefined,
302+
"onNodesChange-remove"
303+
)
289304
getEdgesMap(ydoc).delete(change.id)
290305
}
291306
}
@@ -309,6 +324,27 @@ export const createDiagramStore = (
309324
}
310325
})
311326

327+
// Find removed nodes that are not in the Yjs document
328+
// and remove them from the selectedElementIds
329+
// This is necessary to keep the selection in sync with the Yjs document
330+
// and to avoid selecting nodes that are no longer present in state
331+
const removedNodes = get().nodes.filter(
332+
(node) =>
333+
!preserveSelectedNodesAfterYdoc.some((n) => n.id === node.id)
334+
)
335+
if (removedNodes.length > 0) {
336+
set(
337+
(state) => ({
338+
selectedElementIds: state.selectedElementIds.filter(
339+
(id) =>
340+
!removedNodes.some((removedNode) => removedNode.id === id)
341+
),
342+
}),
343+
undefined,
344+
"updateNodesFromYjs-selection-remove"
345+
)
346+
}
347+
312348
set(
313349
{
314350
nodes: preserveSelectedNodesAfterYdoc,
@@ -329,6 +365,28 @@ export const createDiagramStore = (
329365
return edge
330366
}
331367
})
368+
369+
// Find removed edges that are not in the Yjs document
370+
// and remove them from the selectedElementIds
371+
// This is necessary to keep the selection in sync with the Yjs document
372+
// and to avoid selecting edges that are no longer present in state
373+
const removedEdges = get().edges.filter(
374+
(edge) =>
375+
!preserveSelectedEdgesAfterYdoc.some((e) => e.id === edge.id)
376+
)
377+
if (removedEdges.length > 0) {
378+
set(
379+
(state) => ({
380+
selectedElementIds: state.selectedElementIds.filter(
381+
(id) =>
382+
!removedEdges.some((removedEdge) => removedEdge.id === id)
383+
),
384+
}),
385+
undefined,
386+
"updateEdgesFromYjs-selection-remove"
387+
)
388+
}
389+
332390
set(
333391
{ edges: preserveSelectedEdgesAfterYdoc },
334392
undefined,

standalone/webapp/src/pages/ApollonPlayground.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ export const ApollonPlayground: React.FC = () => {
3636
mode: ApollonMode.Modelling,
3737
locale: Locale.en,
3838
readonly: false,
39-
model: diagram.model,
4039
})
4140

4241
useEffect(() => {
4342
if (containerRef.current) {
44-
const instance = new ApollonEditor(containerRef.current, apollonOptions)
43+
const createApollonOptions: ApollonOptions = {
44+
...apollonOptions,
45+
model: diagram.model,
46+
}
47+
const instance = new ApollonEditor(
48+
containerRef.current,
49+
createApollonOptions
50+
)
4551

4652
instance.subscribeToModelChange((model) => {
4753
updateModel(model)
@@ -106,7 +112,6 @@ export const ApollonPlayground: React.FC = () => {
106112
...prev!,
107113
mode: selectedMode,
108114
}))
109-
console.log("DEBUG selectedMode", selectedMode)
110115
}}
111116
>
112117
<option value={ApollonMode.Assessment}>Assessment</option>

0 commit comments

Comments
 (0)