Skip to content
Merged
Changes from 6 commits
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
159 changes: 121 additions & 38 deletions packages/compass-data-modeling/src/components/new-diagram-form.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import React, { useMemo, useState } from 'react';
import { connect } from 'react-redux';
import type { DataModelingState } from '../store/reducer';
import { useConnectionsList } from '@mongodb-js/compass-connections/provider';
Expand Down Expand Up @@ -29,9 +29,28 @@ import {
Option,
Select,
SelectTable,
spacing,
SpinLoader,
Body,
TextInput,
SearchInput,
} from '@mongodb-js/compass-components';

const footerStyles = css({
flexDirection: 'row',
alignItems: 'center',
});

const footerTextStyles = css({ marginRight: 'auto' });

const footerActionsStyles = css({ display: 'flex', gap: spacing[200] });

const formContainerStyles = css({
display: 'flex',
flexDirection: 'column',
gap: spacing[400],
});

const FormStepContainer: React.FunctionComponent<{
title: string;
description?: string;
Expand All @@ -41,6 +60,7 @@ const FormStepContainer: React.FunctionComponent<{
isNextDisabled: boolean;
nextLabel: string;
previousLabel: string;
footerText?: React.ReactNode;
}> = ({
title,
description,
Expand All @@ -51,31 +71,103 @@ const FormStepContainer: React.FunctionComponent<{
nextLabel,
previousLabel,
children,
footerText,
}) => {
return (
<>
<ModalHeader title={title} subtitle={description}></ModalHeader>
<ModalBody>{children}</ModalBody>
<ModalFooter>
<Button
onClick={onNextClick}
disabled={isNextDisabled}
isLoading={isLoading}
data-testid="new-diagram-confirm-button"
variant="primary"
>
{nextLabel}
</Button>
<Button onClick={onPreviousClick}>{previousLabel}</Button>
<ModalFooter className={footerStyles}>
<Body className={footerTextStyles}>{footerText}</Body>
<div className={footerActionsStyles}>
<Button onClick={onPreviousClick}>{previousLabel}</Button>
<Button
onClick={onNextClick}
disabled={isNextDisabled}
isLoading={isLoading}
data-testid="new-diagram-confirm-button"
variant="primary"
loadingIndicator={<SpinLoader />}
>
{nextLabel}
</Button>
</div>
</ModalFooter>
</>
);
};

const selectTableStyles = css({
maxHeight: 300,
height: 300,
overflow: 'scroll',
});

function SelectCollectionsStep({
collections,
selectedCollections,
onCollectionsSelect,
}: {
collections: string[];
selectedCollections: string[];
onCollectionsSelect: (colls: string[]) => void;
}) {
const [searchTerm, setSearchTerm] = useState('');
const filteredCollections = useMemo(() => {
try {
const regex = new RegExp(searchTerm, 'i');
return collections.filter((x) => regex.test(x));
} catch {
return collections;
}
}, [collections, searchTerm]);
return (
<FormFieldContainer className={formContainerStyles}>
<SearchInput
aria-label="Search collections"
value={searchTerm}
data-testId="new-diagram-search-collections"
onChange={(e) => {
setSearchTerm(e.target.value);
}}
/>
<SelectTable
className={selectTableStyles}
items={filteredCollections.map((collName) => {
return {
id: collName,
selected: selectedCollections.includes(collName),
'data-testid': `new-diagram-collection-checkbox-${collName}`,
};
})}
columns={[['id', 'Collection Name']]}
onChange={(items) => {
// When a user is searching, less collections are shown to the user
// and we need to keep existing selected collections selected.
const currentSelectedItems = selectedCollections.filter(
(collName) => {
const item = items.find((x) => x.id === collName);
// The already selected item was not shown to the user (using search),
// and we have to keep it selected.
return item ? item.selected : true;
}
);

const newSelectedItems = items
.filter((item) => {
return item.selected;
})
.map((item) => {
return item.id;
});
onCollectionsSelect(
Array.from(new Set([...newSelectedItems, ...currentSelectedItems]))
);
}}
></SelectTable>
</FormFieldContainer>
);
}

type NewDiagramFormProps = {
isModalOpen: boolean;
formStep:
Expand Down Expand Up @@ -137,6 +229,7 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
isConfirmDisabled,
onCancelAction,
cancelLabel,
footerText,
} = useMemo(() => {
switch (currentStep) {
case 'enter-name':
Expand Down Expand Up @@ -170,13 +263,19 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
return {
title: `Select collections for ${selectedDatabase ?? ''}`,
description:
'These collections will be included to the generated diagram',
'These collections will be included in your generated diagram.',
onConfirmAction: onCollectionsSelectionConfirm,
confirmActionLabel: 'Generate',
isConfirmDisabled:
!selectedCollections || selectCollections.length === 0,
onCancelAction: onDatabaseSelectCancel,
cancelLabel: 'Back',
footerText: (
<>
<strong>{selectedCollections.length}</strong>/
<strong>{collections.length}</strong> total collections selected.
Copy link
Member

Choose a reason for hiding this comment

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

nit, the s here could be not plural if there is only 1 collection possible (same with the description)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed in 250eb40

</>
),
};
}
}, [
Expand All @@ -193,6 +292,7 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
selectedCollections,
selectedConnectionId,
selectedDatabase,
collections,
]);

const formContent = useMemo(() => {
Expand All @@ -212,7 +312,7 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
);
case 'select-connection':
return (
<FormFieldContainer>
<FormFieldContainer className={formContainerStyles}>
<Select
label=""
value={selectedConnectionId ?? ''}
Expand Down Expand Up @@ -256,29 +356,11 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
);
case 'select-collections':
return (
<FormFieldContainer>
<SelectTable
className={selectTableStyles}
items={collections.map((collName) => {
return {
id: collName,
selected: selectedCollections.includes(collName),
'data-testid': `new-diagram-collection-checkbox-${collName}`,
};
})}
columns={[['id', 'Collection Name']]}
onChange={(items) => {
const selectedItems = items
.filter((item) => {
return item.selected;
})
.map((item) => {
return item.id;
});
onCollectionsSelect(selectedItems);
}}
></SelectTable>
</FormFieldContainer>
<SelectCollectionsStep
collections={collections}
onCollectionsSelect={onCollectionsSelect}
selectedCollections={selectedCollections}
/>
);
}
}, [
Expand Down Expand Up @@ -315,6 +397,7 @@ const NewDiagramForm: React.FunctionComponent<NewDiagramFormProps> = ({
previousLabel={cancelLabel}
isNextDisabled={isConfirmDisabled}
isLoading={isLoading}
footerText={footerText}
>
{formContent}
</FormStepContainer>
Expand Down
Loading