Skip to content

Commit 5163ed7

Browse files
committed
Move state to redux
1 parent 777ab8b commit 5163ed7

File tree

6 files changed

+182
-38
lines changed

6 files changed

+182
-38
lines changed

packages/compass-collection/src/components/collection-header/collection-header.spec.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,32 @@ import {
88
within,
99
userEvent,
1010
} from '@mongodb-js/testing-library-compass';
11-
import { CollectionHeader } from './collection-header';
11+
import { UnconnectedCollectionHeader } from './collection-header';
1212
import {
1313
WorkspacesServiceProvider,
1414
type WorkspacesService,
1515
} from '@mongodb-js/compass-workspaces/provider';
16+
import { MockDataGeneratorStep } from '../mock-data-generator-modal/types';
1617
import Sinon from 'sinon';
1718

1819
function renderCollectionHeader(
19-
props: Partial<ComponentProps<typeof CollectionHeader>> = {},
20+
props: Partial<ComponentProps<typeof UnconnectedCollectionHeader>> = {},
2021
workspaceService: Partial<WorkspacesService> = {}
2122
) {
2223
return render(
2324
<WorkspacesServiceProvider value={workspaceService as WorkspacesService}>
24-
<CollectionHeader
25+
<UnconnectedCollectionHeader
2526
isAtlas={false}
2627
isReadonly={false}
2728
isTimeSeries={false}
2829
isClustered={false}
2930
isFLE={false}
3031
namespace="test.test"
32+
isMockDataModalOpen={false}
33+
currentStep={MockDataGeneratorStep.AI_DISCLAIMER}
34+
onOpenMockDataModal={() => {}}
35+
onCloseMockDataModal={() => {}}
36+
onSetMockDataGeneratorStep={() => {}}
3137
{...props}
3238
/>
3339
</WorkspacesServiceProvider>

packages/compass-collection/src/components/collection-header/collection-header.tsx

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from '@mongodb-js/compass-components';
1111
import type { BreadcrumbItem } from '@mongodb-js/compass-components';
1212
import type { Signal } from '@mongodb-js/compass-components';
13-
import React, { useMemo, useState, useCallback } from 'react';
13+
import React, { useMemo } from 'react';
1414
import toNS from 'mongodb-ns';
1515
import { usePreference } from 'compass-preferences-model/provider';
1616
import CollectionHeaderActions from '../collection-header-actions';
@@ -19,7 +19,14 @@ import { useOpenWorkspace } from '@mongodb-js/compass-workspaces/provider';
1919
import { useConnectionInfo } from '@mongodb-js/compass-connections/provider';
2020
import { getConnectionTitle } from '@mongodb-js/connection-info';
2121
import MockDataGeneratorModal from '../mock-data-generator-modal/mock-data-generator-modal';
22-
import { MockDataGeneratorStep } from '../mock-data-generator-modal/types';
22+
import type { MockDataGeneratorStep } from '../mock-data-generator-modal/types';
23+
import { connect } from 'react-redux';
24+
import type { CollectionState } from '../../modules/collection-tab';
25+
import {
26+
openMockDataGeneratorModal,
27+
closeMockDataGeneratorModal,
28+
setMockDataGeneratorStep,
29+
} from '../../modules/collection-tab';
2330

2431
const collectionHeaderStyles = css({
2532
padding: spacing[400],
@@ -60,6 +67,11 @@ type CollectionHeaderProps = {
6067
sourceName?: string;
6168
editViewName?: string;
6269
sourcePipeline?: unknown[];
70+
isMockDataModalOpen: boolean;
71+
currentStep: MockDataGeneratorStep;
72+
onOpenMockDataModal: () => void;
73+
onCloseMockDataModal: () => void;
74+
onSetMockDataGeneratorStep: (step: MockDataGeneratorStep) => void;
6375
};
6476

6577
const getInsightsForPipeline = (pipeline: any[], isAtlas: boolean) => {
@@ -84,9 +96,7 @@ const getInsightsForPipeline = (pipeline: any[], isAtlas: boolean) => {
8496
return Array.from(insights);
8597
};
8698

87-
export const CollectionHeader: React.FunctionComponent<
88-
CollectionHeaderProps
89-
> = ({
99+
const CollectionHeader: React.FunctionComponent<CollectionHeaderProps> = ({
90100
namespace,
91101
isReadonly,
92102
isTimeSeries,
@@ -96,6 +106,11 @@ export const CollectionHeader: React.FunctionComponent<
96106
sourceName,
97107
editViewName,
98108
sourcePipeline,
109+
isMockDataModalOpen,
110+
currentStep,
111+
onOpenMockDataModal,
112+
onCloseMockDataModal,
113+
onSetMockDataGeneratorStep,
99114
}) => {
100115
const darkMode = useDarkMode();
101116
const showInsights = usePreference('showInsights');
@@ -108,16 +123,6 @@ export const CollectionHeader: React.FunctionComponent<
108123
const connectionId = connectionInfo.id;
109124
const connectionName = getConnectionTitle(connectionInfo);
110125

111-
// Mock Data Generator modal state
112-
const [isMockDataModalOpen, setIsMockDataModalOpen] = useState(false);
113-
const [currentStep, setCurrentStep] = useState(
114-
MockDataGeneratorStep.AI_DISCLAIMER
115-
);
116-
117-
const handleOpenMockDataModal = useCallback(() => {
118-
setIsMockDataModalOpen(true);
119-
}, []);
120-
121126
const breadcrumbItems = useMemo(() => {
122127
return [
123128
{
@@ -182,17 +187,40 @@ export const CollectionHeader: React.FunctionComponent<
182187
namespace={namespace}
183188
sourceName={sourceName}
184189
sourcePipeline={sourcePipeline}
185-
onOpenMockDataModal={handleOpenMockDataModal}
190+
onOpenMockDataModal={onOpenMockDataModal}
186191
/>
187192
</div>
188193
<MockDataGeneratorModal
189194
isOpen={isMockDataModalOpen}
190-
onOpenChange={setIsMockDataModalOpen}
195+
onClose={onCloseMockDataModal}
191196
currentStep={currentStep}
192-
onCurrentStepChange={(step) => {
193-
setCurrentStep(step);
194-
}}
197+
onCurrentStepChange={onSetMockDataGeneratorStep}
195198
/>
196199
</div>
197200
);
198201
};
202+
203+
const mapStateToProps = (state: CollectionState) => ({
204+
isMockDataModalOpen: state.mockDataGenerator.isModalOpen,
205+
currentStep: state.mockDataGenerator.currentStep,
206+
});
207+
208+
type ConnectedCollectionHeaderProps = Omit<
209+
CollectionHeaderProps,
210+
| 'isMockDataModalOpen'
211+
| 'currentStep'
212+
| 'onOpenMockDataModal'
213+
| 'onCloseMockDataModal'
214+
| 'onSetMockDataGeneratorStep'
215+
>;
216+
217+
const ConnectedCollectionHeader = connect(mapStateToProps, {
218+
onOpenMockDataModal: openMockDataGeneratorModal,
219+
onCloseMockDataModal: closeMockDataGeneratorModal,
220+
onSetMockDataGeneratorStep: setMockDataGeneratorStep,
221+
})(CollectionHeader) as React.ComponentType<ConnectedCollectionHeaderProps>;
222+
223+
export {
224+
ConnectedCollectionHeader as CollectionHeader,
225+
CollectionHeader as UnconnectedCollectionHeader, // For tests
226+
};

packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.spec.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { StepButtonLabelMap } from './constants';
88

99
describe('MockDataGeneratorModal', () => {
1010
const sandbox = Sinon.createSandbox();
11-
let onOpenChange: Sinon.SinonSpy;
11+
let onClose: Sinon.SinonSpy;
1212

1313
beforeEach(() => {
14-
onOpenChange = sandbox.spy();
14+
onClose = sandbox.spy();
1515
});
1616

1717
afterEach(() => {
@@ -28,7 +28,7 @@ describe('MockDataGeneratorModal', () => {
2828
return (
2929
<MockDataGeneratorModal
3030
isOpen={isOpen}
31-
onOpenChange={onOpenChange}
31+
onClose={onClose}
3232
currentStep={currentStepStateMock}
3333
onCurrentStepChange={(step) => {
3434
onCurrentStepChangeStateMock(step);
@@ -51,20 +51,20 @@ describe('MockDataGeneratorModal', () => {
5151
expect(screen.queryByTestId('generate-mock-data-modal')).to.not.exist;
5252
});
5353

54-
it('calls onOpenChange(false) when the modal is closed', () => {
54+
it('calls onClose when the modal is closed', () => {
5555
renderModal();
5656

5757
screen.getByLabelText('Close modal').click();
5858

59-
expect(onOpenChange.calledOnceWith(false)).to.be.true;
59+
expect(onClose.calledOnce).to.be.true;
6060
});
6161

62-
it('calls onOpenChange(false) when the cancel button is clicked', () => {
62+
it('calls onClose when the cancel button is clicked', () => {
6363
renderModal();
6464

6565
screen.getByText('Cancel').click();
6666

67-
expect(onOpenChange.calledOnceWith(false)).to.be.true;
67+
expect(onClose.calledOnce).to.be.true;
6868
});
6969

7070
it('disables the Back button on the first step', () => {

packages/compass-collection/src/components/mock-data-generator-modal/mock-data-generator-modal.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ const rightButtonsStyles = css`
3030

3131
interface Props {
3232
isOpen: boolean;
33-
onOpenChange: (isOpen: boolean) => void;
33+
onClose: () => void;
3434
currentStep: MockDataGeneratorStep;
3535
onCurrentStepChange: (step: MockDataGeneratorStep) => void;
3636
}
3737

3838
const MockDataGeneratorModal = ({
3939
isOpen,
40-
onOpenChange,
40+
onClose,
4141
currentStep,
4242
onCurrentStepChange,
4343
}: Props) => {
@@ -51,14 +51,14 @@ const MockDataGeneratorModal = ({
5151
onCurrentStepChange(previousStep);
5252
};
5353

54-
const onCancel = () => {
55-
onOpenChange(false);
56-
};
57-
5854
return (
5955
<Modal
6056
open={isOpen}
61-
setOpen={(open) => onOpenChange(open)}
57+
setOpen={(open) => {
58+
if (!open) {
59+
onClose();
60+
}
61+
}}
6262
data-testid="generate-mock-data-modal"
6363
>
6464
<ModalHeader title="Generate Mock Data" />
@@ -74,7 +74,7 @@ const MockDataGeneratorModal = ({
7474
Back
7575
</Button>
7676
<div className={rightButtonsStyles}>
77-
<Button onClick={onCancel}>Cancel</Button>
77+
<Button onClick={onClose}>Cancel</Button>
7878
<Button
7979
variant={ButtonVariant.Primary}
8080
onClick={onNext}

packages/compass-collection/src/modules/collection-tab.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/pr
66
import type { CollectionSubtab } from '@mongodb-js/compass-workspaces';
77
import type { DataService } from '@mongodb-js/compass-connections/provider';
88
import type { experimentationServiceLocator } from '@mongodb-js/compass-telemetry/provider';
9+
import { MockDataGeneratorStep } from '../components/mock-data-generator-modal/types';
910

1011
function isAction<A extends AnyAction>(
1112
action: AnyAction,
@@ -31,23 +32,47 @@ export type CollectionState = {
3132
namespace: string;
3233
metadata: CollectionMetadata | null;
3334
editViewName?: string;
35+
mockDataGenerator: {
36+
isModalOpen: boolean;
37+
currentStep: MockDataGeneratorStep;
38+
};
3439
};
3540

3641
enum CollectionActions {
3742
CollectionMetadataFetched = 'compass-collection/CollectionMetadataFetched',
43+
OpenMockDataGeneratorModal = 'compass-collection/OpenMockDataGeneratorModal',
44+
CloseMockDataGeneratorModal = 'compass-collection/CloseMockDataGeneratorModal',
45+
SetMockDataGeneratorStep = 'compass-collection/SetMockDataGeneratorStep',
3846
}
3947

4048
interface CollectionMetadataFetchedAction {
4149
type: CollectionActions.CollectionMetadataFetched;
4250
metadata: CollectionMetadata;
4351
}
4452

53+
interface OpenMockDataGeneratorModalAction {
54+
type: CollectionActions.OpenMockDataGeneratorModal;
55+
}
56+
57+
interface CloseMockDataGeneratorModalAction {
58+
type: CollectionActions.CloseMockDataGeneratorModal;
59+
}
60+
61+
interface SetMockDataGeneratorStepAction {
62+
type: CollectionActions.SetMockDataGeneratorStep;
63+
step: MockDataGeneratorStep;
64+
}
65+
4566
const reducer: Reducer<CollectionState, Action> = (
4667
state = {
4768
// TODO(COMPASS-7782): use hook to get the workspace tab id instead
4869
workspaceTabId: '',
4970
namespace: '',
5071
metadata: null,
72+
mockDataGenerator: {
73+
isModalOpen: false,
74+
currentStep: MockDataGeneratorStep.AI_DISCLAIMER,
75+
},
5176
},
5277
action
5378
) => {
@@ -62,6 +87,54 @@ const reducer: Reducer<CollectionState, Action> = (
6287
metadata: action.metadata,
6388
};
6489
}
90+
91+
if (
92+
isAction<OpenMockDataGeneratorModalAction>(
93+
action,
94+
CollectionActions.OpenMockDataGeneratorModal
95+
)
96+
) {
97+
return {
98+
...state,
99+
mockDataGenerator: {
100+
...state.mockDataGenerator,
101+
isModalOpen: true,
102+
currentStep: MockDataGeneratorStep.AI_DISCLAIMER,
103+
},
104+
};
105+
}
106+
107+
if (
108+
isAction<CloseMockDataGeneratorModalAction>(
109+
action,
110+
CollectionActions.CloseMockDataGeneratorModal
111+
)
112+
) {
113+
return {
114+
...state,
115+
mockDataGenerator: {
116+
...state.mockDataGenerator,
117+
isModalOpen: false,
118+
currentStep: MockDataGeneratorStep.AI_DISCLAIMER,
119+
},
120+
};
121+
}
122+
123+
if (
124+
isAction<SetMockDataGeneratorStepAction>(
125+
action,
126+
CollectionActions.SetMockDataGeneratorStep
127+
)
128+
) {
129+
return {
130+
...state,
131+
mockDataGenerator: {
132+
...state.mockDataGenerator,
133+
currentStep: action.step,
134+
},
135+
};
136+
}
137+
65138
return state;
66139
};
67140

@@ -71,6 +144,22 @@ export const collectionMetadataFetched = (
71144
return { type: CollectionActions.CollectionMetadataFetched, metadata };
72145
};
73146

147+
export const openMockDataGeneratorModal =
148+
(): OpenMockDataGeneratorModalAction => {
149+
return { type: CollectionActions.OpenMockDataGeneratorModal };
150+
};
151+
152+
export const closeMockDataGeneratorModal =
153+
(): CloseMockDataGeneratorModalAction => {
154+
return { type: CollectionActions.CloseMockDataGeneratorModal };
155+
};
156+
157+
export const setMockDataGeneratorStep = (
158+
step: MockDataGeneratorStep
159+
): SetMockDataGeneratorStepAction => {
160+
return { type: CollectionActions.SetMockDataGeneratorStep, step };
161+
};
162+
74163
export const selectTab = (
75164
tabName: CollectionSubtab
76165
): CollectionThunkAction<void> => {

0 commit comments

Comments
 (0)