Skip to content

Commit 460325b

Browse files
committed
feat(data-modeling): add note editing to collections and relationships
1 parent e7e965d commit 460325b

File tree

6 files changed

+133
-9
lines changed

6 files changed

+133
-9
lines changed

packages/compass-data-modeling/src/components/drawer/collection-drawer-content.tsx

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,36 @@ import {
1111
spacing,
1212
TextInput,
1313
Icon,
14+
TextArea,
1415
} from '@mongodb-js/compass-components';
1516
import {
1617
createNewRelationship,
1718
deleteRelationship,
1819
selectCurrentModelFromState,
1920
selectRelationship,
21+
updateCollectionNote,
2022
} from '../../store/diagram';
2123
import type { DataModelingState } from '../../store/reducer';
2224
import { getDefaultRelationshipName } from '../../utils';
2325
import DMDrawerSection from './dm-drawer-section';
26+
import { useChangeOnBlur } from './use-change-on-blur';
2427

2528
type CollectionDrawerContentProps = {
2629
namespace: string;
2730
relationships: Relationship[];
2831
onCreateNewRelationshipClick: (namespace: string) => void;
2932
onEditRelationshipClick: (rId: string) => void;
3033
onDeleteRelationshipClick: (rId: string) => void;
34+
note?: string;
35+
onNoteChange: (namespace: string, note: string) => void;
3136
};
3237

3338
const formFieldContainerStyles = css({
34-
marginBottom: spacing[400],
3539
marginTop: spacing[400],
40+
marginBottom: 0,
41+
'&:not(:last-child)': {
42+
marginBottom: spacing[400],
43+
},
3644
});
3745

3846
const titleBtnStyles = css({
@@ -76,7 +84,13 @@ const CollectionDrawerContent: React.FunctionComponent<
7684
onCreateNewRelationshipClick,
7785
onEditRelationshipClick,
7886
onDeleteRelationshipClick,
87+
note = '',
88+
onNoteChange,
7989
}) => {
90+
const noteInputProps = useChangeOnBlur(note, (newNote) => {
91+
onNoteChange(namespace, newNote);
92+
});
93+
8094
return (
8195
<>
8296
<DMDrawerSection label="Collection properties">
@@ -149,26 +163,36 @@ const CollectionDrawerContent: React.FunctionComponent<
149163
)}
150164
</div>
151165
</DMDrawerSection>
166+
167+
<DMDrawerSection label="Notes">
168+
<FormFieldContainer className={formFieldContainerStyles}>
169+
<TextArea label="" {...noteInputProps}></TextArea>
170+
</FormFieldContainer>
171+
</DMDrawerSection>
152172
</>
153173
);
154174
};
155175

156176
export default connect(
157177
(state: DataModelingState, ownProps: { namespace: string }) => {
178+
const model = selectCurrentModelFromState(state);
158179
return {
159-
relationships: selectCurrentModelFromState(state).relationships.filter(
160-
(r) => {
161-
const [local, foreign] = r.relationship;
162-
return (
163-
local.ns === ownProps.namespace || foreign.ns === ownProps.namespace
164-
);
165-
}
166-
),
180+
note:
181+
model.collections.find((collection) => {
182+
return collection.ns === ownProps.namespace;
183+
})?.note ?? '',
184+
relationships: model.relationships.filter((r) => {
185+
const [local, foreign] = r.relationship;
186+
return (
187+
local.ns === ownProps.namespace || foreign.ns === ownProps.namespace
188+
);
189+
}),
167190
};
168191
},
169192
{
170193
onCreateNewRelationshipClick: createNewRelationship,
171194
onEditRelationshipClick: selectRelationship,
172195
onDeleteRelationshipClick: deleteRelationship,
196+
onNoteChange: updateCollectionNote,
173197
}
174198
)(CollectionDrawerContent);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ function DiagramEditorSidePanel({
2222
if (selectedItems.type === 'collection') {
2323
content = (
2424
<CollectionDrawerContent
25+
key={selectedItems.id}
2526
namespace={selectedItems.id}
2627
></CollectionDrawerContent>
2728
);
2829
} else if (selectedItems.type === 'relationship') {
2930
content = (
3031
<RelationshipDrawerContent
32+
key={selectedItems.id}
3133
relationshipId={selectedItems.id}
3234
></RelationshipDrawerContent>
3335
);

packages/compass-data-modeling/src/components/drawer/relationship-drawer-content.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,30 @@ import {
1212
palette,
1313
Button,
1414
Icon,
15+
TextArea,
1516
} from '@mongodb-js/compass-components';
1617
import {
1718
deleteRelationship,
1819
getCurrentDiagramFromState,
1920
getRelationshipForCurrentModel,
2021
selectFieldsForCurrentModel,
2122
updateRelationship,
23+
updateRelationshipNote,
2224
} from '../../store/diagram';
2325
import toNS from 'mongodb-ns';
2426
import type { Relationship } from '../../services/data-model-storage';
2527
import { cloneDeep } from 'lodash';
2628
import DMDrawerSection from './dm-drawer-section';
29+
import { useChangeOnBlur } from './use-change-on-blur';
2730

2831
type RelationshipDrawerContentProps = {
2932
relationshipId: string;
3033
relationship: Relationship;
3134
fields: Record<string, string[][]>;
3235
onRelationshipUpdate: (relationship: Relationship) => void;
3336
onDeleteRelationshipClick: (rId: string) => void;
37+
note?: string;
38+
onNoteChange: (rId: string, note: string) => void;
3439
};
3540

3641
type RelationshipFormFields = {
@@ -165,11 +170,17 @@ const RelationshipDrawerContent: React.FunctionComponent<
165170
fields,
166171
onRelationshipUpdate,
167172
onDeleteRelationshipClick,
173+
note = '',
174+
onNoteChange,
168175
}) => {
169176
const collections = useMemo(() => {
170177
return Object.keys(fields);
171178
}, [fields]);
172179

180+
const noteInputProps = useChangeOnBlur(note, (newNote) => {
181+
onNoteChange(relationshipId, newNote);
182+
});
183+
173184
const {
174185
localCollection,
175186
localField,
@@ -358,6 +369,12 @@ const RelationshipDrawerContent: React.FunctionComponent<
358369
</div>
359370
</div>
360371
</DMDrawerSection>
372+
373+
<DMDrawerSection label="Notes">
374+
<FormFieldContainer className={formFieldContainerStyles}>
375+
<TextArea label="" {...noteInputProps}></TextArea>
376+
</FormFieldContainer>
377+
</DMDrawerSection>
361378
</div>
362379
);
363380
};
@@ -382,5 +399,6 @@ export default connect(
382399
{
383400
onRelationshipUpdate: updateRelationship,
384401
onDeleteRelationshipClick: deleteRelationship,
402+
onNoteChange: updateRelationshipNote,
385403
}
386404
)(RelationshipDrawerContent);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useState, useLayoutEffect } from 'react';
2+
3+
export function useChangeOnBlur(
4+
value: string,
5+
onChange: (newVal: string) => void
6+
): {
7+
value: string;
8+
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
9+
onBlur: React.FocusEventHandler;
10+
} {
11+
const [_value, setValue] = useState(value);
12+
useLayoutEffect(() => {
13+
// Usually this is in sync with local value, but if it's changed externally,
14+
// we run an effect and sync it back
15+
setValue(value);
16+
}, [value]);
17+
return {
18+
value: _value,
19+
onChange: (evt) => {
20+
setValue(evt.currentTarget.value);
21+
},
22+
onBlur: () => {
23+
onChange(_value);
24+
},
25+
};
26+
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const RelationshipSchema = z.object({
1313
id: z.string().uuid(),
1414
relationship: z.tuple([RelationshipSideSchema, RelationshipSideSchema]),
1515
isInferred: z.boolean(),
16+
note: z.string().optional(),
1617
});
1718

1819
export type Relationship = z.output<typeof RelationshipSchema>;
@@ -26,6 +27,7 @@ const CollectionSchema = z.object({
2627
indexes: z.array(z.record(z.unknown())),
2728
shardKey: z.record(z.unknown()).optional(),
2829
displayPosition: z.tuple([z.number(), z.number()]),
30+
note: z.string().optional(),
2931
});
3032

3133
export type DataModelCollection = z.output<typeof CollectionSchema>;
@@ -64,6 +66,16 @@ const EditSchemaVariants = z.discriminatedUnion('type', [
6466
ns: z.string(),
6567
newPosition: z.tuple([z.number(), z.number()]),
6668
}),
69+
z.object({
70+
type: z.literal('UpdateCollectionNote'),
71+
ns: z.string(),
72+
note: z.string(),
73+
}),
74+
z.object({
75+
type: z.literal('UpdateRelationshipNote'),
76+
id: z.string(),
77+
note: z.string(),
78+
}),
6779
]);
6880

6981
export const EditSchema = z.intersection(EditSchemaBase, EditSchemaVariants);

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,20 @@ export function deleteRelationship(
478478
};
479479
}
480480

481+
export function updateCollectionNote(
482+
ns: string,
483+
note: string
484+
): DataModelingThunkAction<boolean, ApplyEditAction | ApplyEditFailedAction> {
485+
return applyEdit({ type: 'UpdateCollectionNote', ns, note });
486+
}
487+
488+
export function updateRelationshipNote(
489+
id: string,
490+
note: string
491+
): DataModelingThunkAction<boolean, ApplyEditAction | ApplyEditFailedAction> {
492+
return applyEdit({ type: 'UpdateRelationshipNote', id, note });
493+
}
494+
481495
function _applyEdit(edit: Edit, model?: StaticModel): StaticModel {
482496
if (edit.type === 'SetModel') {
483497
return edit.model;
@@ -528,6 +542,34 @@ function _applyEdit(edit: Edit, model?: StaticModel): StaticModel {
528542
}),
529543
};
530544
}
545+
case 'UpdateCollectionNote': {
546+
return {
547+
...model,
548+
collections: model.collections.map((collection) => {
549+
if (collection.ns === edit.ns) {
550+
return {
551+
...collection,
552+
note: edit.note,
553+
};
554+
}
555+
return collection;
556+
}),
557+
};
558+
}
559+
case 'UpdateRelationshipNote': {
560+
return {
561+
...model,
562+
relationships: model.relationships.map((relationship) => {
563+
if (relationship.id === edit.id) {
564+
return {
565+
...relationship,
566+
note: edit.note,
567+
};
568+
}
569+
return relationship;
570+
}),
571+
};
572+
}
531573
default: {
532574
return model;
533575
}

0 commit comments

Comments
 (0)