Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React from 'react';
import { connect } from 'react-redux';
import type { Relationship } from '../services/data-model-storage';
import { Button, H3 } from '@mongodb-js/compass-components';
import {
deleteRelationship,
getCurrentDiagramFromState,
selectCurrentModel,
} from '../store/diagram';
import type { DataModelingState } from '../store/reducer';
import {
createNewRelationship,
startRelationshipEdit,
} from '../store/side-panel';
import RelationshipDrawerContent from './relationship-drawer-content';

type CollectionDrawerContentProps = {
namespace: string;
relationships: Relationship[];
shouldShowRelationshipEditingForm?: boolean;
onCreateNewRelationshipClick: (namespace: string) => void;
onEditRelationshipClick: (relationship: Relationship) => void;
onDeleteRelationshipClick: (rId: string) => void;
};

const CollectionDrawerContent: React.FunctionComponent<
CollectionDrawerContentProps
> = ({
namespace,
relationships,
shouldShowRelationshipEditingForm,
onCreateNewRelationshipClick,
onEditRelationshipClick,
onDeleteRelationshipClick,
}) => {
if (shouldShowRelationshipEditingForm) {
return <RelationshipDrawerContent></RelationshipDrawerContent>;
}

return (
<>
<H3>{namespace}</H3>
<ul>
{relationships.map((r) => {
return (
<li key={r.id}>
{r.relationship[0].fields.join(', ')}&nbsp;-&gt;&nbsp;
{r.relationship[1].fields.join(', ')}
<Button
onClick={() => {
onEditRelationshipClick(r);
}}
>
Edit
</Button>
<Button
onClick={() => {
onDeleteRelationshipClick(r.id);
}}
>
Delete
</Button>
</li>
);
})}
</ul>
<Button
onClick={() => {
onCreateNewRelationshipClick(namespace);
}}
>
Add relationship manually
</Button>
</>
);
};

export default connect(
(state: DataModelingState, ownProps: { namespace: string }) => {
return {
relationships: selectCurrentModel(
getCurrentDiagramFromState(state).edits
).relationships.filter((r) => {
const [local, foreign] = r.relationship;
return (
local.ns === ownProps.namespace || foreign.ns === ownProps.namespace
);
}),
shouldShowRelationshipEditingForm:
state.sidePanel.viewType === 'relationship-editing',
};
},
{
onCreateNewRelationshipClick: createNewRelationship,
onEditRelationshipClick: startRelationshipEdit,
onDeleteRelationshipClick: deleteRelationship,
}
)(CollectionDrawerContent);
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,15 @@ import {
Button,
css,
cx,
Body,
spacing,
palette,
useDarkMode,
} from '@mongodb-js/compass-components';
import CollectionDrawerContent from './collection-drawer-content';
import RelationshipDrawerContent from './relationship-drawer-content';

const containerStyles = css({
width: '400px',
height: '100%',

display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: spacing[400],
borderLeft: `1px solid ${palette.gray.light2}`,
});

Expand All @@ -29,21 +23,35 @@ const darkModeContainerStyles = css({
});

type DiagramEditorSidePanelProps = {
isOpen: boolean;
selectedItems: { type: 'relationship' | 'collection'; id: string } | null;
onClose: () => void;
};

function DiagmramEditorSidePanel({
isOpen,
selectedItems,
onClose,
}: DiagramEditorSidePanelProps) {
const isDarkMode = useDarkMode();
if (!isOpen) {

if (!selectedItems) {
return null;
}

let content;

if (selectedItems.type === 'collection') {
content = (
<CollectionDrawerContent
namespace={selectedItems.id}
></CollectionDrawerContent>
);
} else if (selectedItems.type === 'relationship') {
content = <RelationshipDrawerContent></RelationshipDrawerContent>;
}

return (
<div className={cx(containerStyles, isDarkMode && darkModeContainerStyles)}>
<Body>This feature is under development.</Body>
{content}
<Button onClick={onClose} variant="primary" size="small">
Close Side Panel
</Button>
Expand All @@ -53,9 +61,8 @@ function DiagmramEditorSidePanel({

export default connect(
(state: DataModelingState) => {
const { sidePanel } = state;
return {
isOpen: sidePanel.isOpen,
selectedItems: state.diagram?.selectedItems ?? null,
};
},
{
Expand Down
41 changes: 31 additions & 10 deletions packages/compass-data-modeling/src/components/diagram-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
moveCollection,
getCurrentDiagramFromState,
selectCurrentModel,
selectCollection,
selectRelationship,
} from '../store/diagram';
import {
Banner,
Expand All @@ -38,7 +40,6 @@ import type { StaticModel } from '../services/data-model-storage';
import DiagramEditorToolbar from './diagram-editor-toolbar';
import ExportDiagramModal from './export-diagram-modal';
import { useLogger } from '@mongodb-js/compass-logging/provider';
import { openSidePanel } from '../store/side-panel';

const loadingContainerStyles = css({
width: '100%',
Expand Down Expand Up @@ -189,7 +190,9 @@ const DiagramEditor: React.FunctionComponent<{
onCancelClick: () => void;
onApplyInitialLayout: (positions: Record<string, [number, number]>) => void;
onMoveCollection: (ns: string, newPosition: [number, number]) => void;
onOpenSidePanel: () => void;
onCollectionSelect: (namespace: string) => void;
onRelationshipSelect: (rId: string) => void;
selectedItem?: string | null;
}> = ({
diagramLabel,
step,
Expand All @@ -198,7 +201,9 @@ const DiagramEditor: React.FunctionComponent<{
onCancelClick,
onApplyInitialLayout,
onMoveCollection,
onOpenSidePanel,
onCollectionSelect,
onRelationshipSelect,
selectedItem,
}) => {
const { log, mongoLogId } = useLogger('COMPASS-DATA-MODELING-DIAGRAM-EDITOR');
const isDarkMode = useDarkMode();
Expand Down Expand Up @@ -226,9 +231,10 @@ const DiagramEditor: React.FunctionComponent<{
target: target.ns,
markerStart: source.cardinality === 1 ? 'one' : 'many',
markerEnd: target.cardinality === 1 ? 'one' : 'many',
selected: selectedItem === relationship.id,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know the odds are slim but should we check for the type as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in a2967fd

};
});
}, [model?.relationships]);
}, [model?.relationships, selectedItem]);

const nodes = useMemo<NodeProps[]>(() => {
return (model?.collections ?? []).map(
Expand All @@ -241,9 +247,10 @@ const DiagramEditor: React.FunctionComponent<{
},
title: toNS(coll.ns).collection,
fields: getFieldsFromSchema(coll.jsonSchema),
selected: selectedItem === coll.ns,
})
);
}, [model?.collections]);
}, [model?.collections, selectedItem]);

const applyInitialLayout = useCallback(async () => {
try {
Expand Down Expand Up @@ -335,9 +342,19 @@ const DiagramEditor: React.FunctionComponent<{
title={diagramLabel}
edges={edges}
nodes={areNodesReady ? nodes : []}
onEdgeClick={() => {
// TODO: we have to open a side panel with edge details
onOpenSidePanel();
// With threshold too low clicking sometimes gets confused with
// dragging
// @ts-expect-error expose this prop from the component
nodeDragThreshold={3}
// @ts-expect-error expose this prop from the component
onNodeClick={(_evt, node) => {
if (node.type !== 'collection') {
return;
}
onCollectionSelect(node.id);
}}
Comment on lines +354 to +364
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: don't forget to open tickets for those changes in diagramming package

onEdgeClick={(_evt, edge) => {
onRelationshipSelect(edge.id);
}}
fitViewOptions={{
maxZoom: 1,
Expand Down Expand Up @@ -366,17 +383,21 @@ export default connect(
return {
step: step,
model: diagram
? selectCurrentModel(getCurrentDiagramFromState(state))
? selectCurrentModel(getCurrentDiagramFromState(state).edits)
: null,
editErrors: diagram?.editErrors,
diagramLabel: diagram?.name || 'Schema Preview',
selectedItem: state.diagram?.selectedItems
? state.diagram.selectedItems.id
: null,
};
},
{
onRetryClick: retryAnalysis,
onCancelClick: cancelAnalysis,
onApplyInitialLayout: applyInitialLayout,
onMoveCollection: moveCollection,
onOpenSidePanel: openSidePanel,
onCollectionSelect: selectCollection,
onRelationshipSelect: selectRelationship,
}
)(DiagramEditor);
Loading
Loading