Skip to content

Commit 91242aa

Browse files
committed
store the layout
1 parent 08324ff commit 91242aa

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
selectCurrentModel,
1415
} from '../store/diagram';
@@ -120,6 +121,7 @@ const DiagramEditor: React.FunctionComponent<{
120121
onRetryClick: () => void;
121122
onCancelClick: () => void;
122123
onApplyClick: (edit: Omit<Edit, 'id' | 'timestamp'>) => void;
124+
onApplyInitialLayout: (positions: Record<string, [number, number]>) => void;
123125
}> = ({
124126
diagramLabel,
125127
step,
@@ -128,6 +130,7 @@ const DiagramEditor: React.FunctionComponent<{
128130
onRetryClick,
129131
onCancelClick,
130132
onApplyClick,
133+
onApplyInitialLayout,
131134
}) => {
132135
const isDarkMode = useDarkMode();
133136
const diagramContainerRef = useRef<HTMLDivElement | null>(null);
@@ -215,8 +218,13 @@ const DiagramEditor: React.FunctionComponent<{
215218
edges,
216219
'STAR'
217220
);
218-
// TODO: save the new positions to the model
219221
setNodes(positionedNodes);
222+
onApplyInitialLayout(
223+
positionedNodes.reduce((obj, node) => {
224+
obj[node.id] = [node.position.x, node.position.y];
225+
return obj;
226+
}, {} as Record<string, [number, number]>)
227+
);
220228
} catch (err) {
221229
console.error('Error applying layout:', err);
222230
}
@@ -388,5 +396,6 @@ export default connect(
388396
onRetryClick: retryAnalysis,
389397
onCancelClick: cancelAnalysis,
390398
onApplyClick: applyEdit,
399+
onApplyInitialLayout: applyInitialLayout,
391400
}
392401
)(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
@@ -32,6 +32,7 @@ export enum DiagramActionTypes {
3232
OPEN_DIAGRAM = 'data-modeling/diagram/OPEN_DIAGRAM',
3333
DELETE_DIAGRAM = 'data-modeling/diagram/DELETE_DIAGRAM',
3434
RENAME_DIAGRAM = 'data-modeling/diagram/RENAME_DIAGRAM',
35+
APPLY_INITIAL_LAYOUT = 'data-modeling/diagram/APPLY_INITIAL_LAYOUT',
3536
APPLY_EDIT = 'data-modeling/diagram/APPLY_EDIT',
3637
APPLY_EDIT_FAILED = 'data-modeling/diagram/APPLY_EDIT_FAILED',
3738
UNDO_EDIT = 'data-modeling/diagram/UNDO_EDIT',
@@ -56,6 +57,11 @@ export type RenameDiagramAction = {
5657
name: string;
5758
};
5859

60+
export type ApplyInitialLayoutAction = {
61+
type: DiagramActionTypes.APPLY_INITIAL_LAYOUT;
62+
positions: Record<string, [number, number]>;
63+
};
64+
5965
export type ApplyEditAction = {
6066
type: DiagramActionTypes.APPLY_EDIT;
6167
edit: Edit;
@@ -86,6 +92,7 @@ export type DiagramActions =
8692
| OpenDiagramAction
8793
| DeleteDiagramAction
8894
| RenameDiagramAction
95+
| ApplyInitialLayoutAction
8996
| ApplyEditAction
9097
| ApplyEditFailedAction
9198
| UndoEditAction
@@ -152,6 +159,30 @@ export const diagramReducer: Reducer<DiagramState> = (
152159
updatedAt: new Date().toISOString(),
153160
};
154161
}
162+
if (isAction(action, DiagramActionTypes.APPLY_INITIAL_LAYOUT)) {
163+
const initialEdit = state.edits.current[0];
164+
if (!initialEdit || initialEdit.type !== 'SetModel') {
165+
throw new Error('No initial model edit found to apply layout to');
166+
}
167+
return {
168+
...state,
169+
edits: {
170+
...state.edits,
171+
current: [
172+
{
173+
...initialEdit,
174+
model: {
175+
...initialEdit.model,
176+
collections: initialEdit.model.collections.map((collection) => ({
177+
...collection,
178+
displayPosition: action.positions[collection.ns] || [-1, -1],
179+
})),
180+
},
181+
},
182+
],
183+
},
184+
};
185+
}
155186
if (isAction(action, DiagramActionTypes.APPLY_EDIT)) {
156187
return {
157188
...state,
@@ -255,6 +286,18 @@ export function applyEdit(
255286
};
256287
}
257288

289+
export function applyInitialLayout(
290+
positions: Record<string, [number, number]>
291+
): DataModelingThunkAction<void, ApplyInitialLayoutAction> {
292+
return (dispatch, getState, { dataModelStorage }) => {
293+
dispatch({
294+
type: DiagramActionTypes.APPLY_INITIAL_LAYOUT,
295+
positions,
296+
});
297+
void dataModelStorage.save(getCurrentDiagramFromState(getState()));
298+
};
299+
}
300+
258301
export function openDiagram(diagram: MongoDBDataModelDescription) {
259302
return { type: DiagramActionTypes.OPEN_DIAGRAM, diagram };
260303
}

0 commit comments

Comments
 (0)