Skip to content

Commit 7f84e27

Browse files
committed
store the layout
1 parent 27c4dca commit 7f84e27

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

packages/compass-data-modeling/src/components/diagram-editor.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { connect } from 'react-redux';
99
import type { DataModelingState } from '../store/reducer';
1010
import {
1111
applyEdit,
12+
applyInitialLayout,
1213
getCurrentDiagramFromState,
1314
redoEdit,
1415
selectCurrentModel,
@@ -127,6 +128,7 @@ const DiagramEditor: React.FunctionComponent<{
127128
onRetryClick: () => void;
128129
onCancelClick: () => void;
129130
onApplyClick: (edit: Omit<Edit, 'id' | 'timestamp'>) => void;
131+
onApplyInitialLayout: (positions: Record<string, [number, number]>) => void;
130132
}> = ({
131133
diagramLabel,
132134
step,
@@ -139,6 +141,7 @@ const DiagramEditor: React.FunctionComponent<{
139141
onRetryClick,
140142
onCancelClick,
141143
onApplyClick,
144+
onApplyInitialLayout,
142145
}) => {
143146
const isDarkMode = useDarkMode();
144147
const diagramContainerRef = useRef<HTMLDivElement | null>(null);
@@ -226,8 +229,13 @@ const DiagramEditor: React.FunctionComponent<{
226229
edges,
227230
'STAR'
228231
);
229-
// TODO: save the new positions to the model
230232
setNodes(positionedNodes);
233+
onApplyInitialLayout(
234+
positionedNodes.reduce((obj, node) => {
235+
obj[node.id] = [node.position.x, node.position.y];
236+
return obj;
237+
}, {} as Record<string, [number, number]>)
238+
);
231239
} catch (err) {
232240
console.error('Error applying layout:', err);
233241
}
@@ -427,5 +435,6 @@ export default connect(
427435
onRetryClick: retryAnalysis,
428436
onCancelClick: cancelAnalysis,
429437
onApplyClick: applyEdit,
438+
onApplyInitialLayout: applyInitialLayout,
430439
}
431440
)(DiagramEditor);

packages/compass-data-modeling/src/services/data-model-storage.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,20 @@ export const MongoDBDataModelDescriptionSchema = z.object({
8888
*/
8989
connectionId: z.string().nullable(),
9090

91-
edits: z.array(EditSchema).nonempty(),
91+
// Ensure first item exists and is 'SetModel'
92+
edits: z
93+
.array(EditSchema)
94+
.nonempty()
95+
.refine((edits) => edits[0]?.type === 'SetModel', {
96+
message: "First edit must be of type 'SetModel'",
97+
}),
9298

9399
createdAt: z.string().datetime(),
94100
updatedAt: z.string().datetime(),
95101
});
96102

103+
type SetModelEdit = Extract<Edit, { type: 'SetModel' }>;
104+
97105
export type MongoDBDataModelDescription = z.output<
98106
typeof MongoDBDataModelDescriptionSchema
99107
>;

packages/compass-data-modeling/src/store/diagram.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export enum DiagramActionTypes {
3131
OPEN_DIAGRAM = 'data-modeling/diagram/OPEN_DIAGRAM',
3232
DELETE_DIAGRAM = 'data-modeling/diagram/DELETE_DIAGRAM',
3333
RENAME_DIAGRAM = 'data-modeling/diagram/RENAME_DIAGRAM',
34+
APPLY_INITIAL_LAYOUT = 'data-modeling/diagram/APPLY_INITIAL_LAYOUT',
3435
APPLY_EDIT = 'data-modeling/diagram/APPLY_EDIT',
3536
APPLY_EDIT_FAILED = 'data-modeling/diagram/APPLY_EDIT_FAILED',
3637
UNDO_EDIT = 'data-modeling/diagram/UNDO_EDIT',
@@ -53,6 +54,11 @@ export type RenameDiagramAction = {
5354
name: string;
5455
};
5556

57+
export type ApplyInitialLayoutAction = {
58+
type: DiagramActionTypes.APPLY_INITIAL_LAYOUT;
59+
positions: Record<string, [number, number]>;
60+
};
61+
5662
export type ApplyEditAction = {
5763
type: DiagramActionTypes.APPLY_EDIT;
5864
edit: Edit;
@@ -75,6 +81,7 @@ export type DiagramActions =
7581
| OpenDiagramAction
7682
| DeleteDiagramAction
7783
| RenameDiagramAction
84+
| ApplyInitialLayoutAction
7885
| ApplyEditAction
7986
| ApplyEditFailedAction
8087
| UndoEditAction
@@ -141,6 +148,30 @@ export const diagramReducer: Reducer<DiagramState> = (
141148
updatedAt: new Date().toISOString(),
142149
};
143150
}
151+
if (isAction(action, DiagramActionTypes.APPLY_INITIAL_LAYOUT)) {
152+
const initialEdit = state.edits.current[0];
153+
if (!initialEdit || initialEdit.type !== 'SetModel') {
154+
throw new Error('No initial model edit found to apply layout to');
155+
}
156+
return {
157+
...state,
158+
edits: {
159+
...state.edits,
160+
current: [
161+
{
162+
...initialEdit,
163+
model: {
164+
...initialEdit.model,
165+
collections: initialEdit.model.collections.map((collection) => ({
166+
...collection,
167+
displayPosition: action.positions[collection.ns] || [-1, -1],
168+
})),
169+
},
170+
},
171+
],
172+
},
173+
};
174+
}
144175
if (isAction(action, DiagramActionTypes.APPLY_EDIT)) {
145176
return {
146177
...state,
@@ -232,6 +263,18 @@ export function applyEdit(
232263
};
233264
}
234265

266+
export function applyInitialLayout(
267+
positions: Record<string, [number, number]>
268+
): DataModelingThunkAction<void, ApplyInitialLayoutAction> {
269+
return (dispatch, getState, { dataModelStorage }) => {
270+
dispatch({
271+
type: DiagramActionTypes.APPLY_INITIAL_LAYOUT,
272+
positions,
273+
});
274+
void dataModelStorage.save(getCurrentDiagramFromState(getState()));
275+
};
276+
}
277+
235278
export function openDiagram(diagram: MongoDBDataModelDescription) {
236279
return { type: DiagramActionTypes.OPEN_DIAGRAM, diagram };
237280
}

0 commit comments

Comments
 (0)