Skip to content

Commit 28cbfb9

Browse files
authored
chore(data-modeling): add most of the redux store logic and a basic UI for it (#6879)
* tmp: implement store and most of the business logic * wip(data-modeling): add delete / rename logic and UI triggers * fix(data-modeling): fix apply edits action
1 parent 8eec63f commit 28cbfb9

39 files changed

+2346
-152
lines changed

package-lock.json

+16-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compass-components/src/components/leafygreen.tsx

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useState } from 'react';
22

33
// This file exports `@leafygreen-ui` components and wraps some of them.
44

@@ -67,7 +67,7 @@ export type {
6767
} from '@leafygreen-ui/table';
6868
import { Tabs, Tab } from '@leafygreen-ui/tabs';
6969
import TextArea from '@leafygreen-ui/text-area';
70-
import TextInput from '@leafygreen-ui/text-input';
70+
import LeafyGreenTextInput from '@leafygreen-ui/text-input';
7171
import { SearchInput } from '@leafygreen-ui/search-input';
7272
export type { ToastProps } from '@leafygreen-ui/toast';
7373
export { ToastProvider, useToast } from '@leafygreen-ui/toast';
@@ -112,6 +112,29 @@ delete (Checkbox as React.ComponentType<any>).propTypes;
112112
// all hrefs.
113113
export { Link, Button, IconButton } from './links/link';
114114

115+
// Working around leafygreen lack of support for `defaultValue` property
116+
const TextInput: typeof LeafyGreenTextInput = React.forwardRef(
117+
function TextInput({ defaultValue, value, onChange, ...props }, ref) {
118+
const [uncontrolledValue, setUncontrolledValue] = useState(
119+
String(defaultValue) ?? ''
120+
);
121+
const isControlled = typeof defaultValue === 'undefined';
122+
return (
123+
<LeafyGreenTextInput
124+
{...props}
125+
value={isControlled ? value : uncontrolledValue}
126+
onChange={(e) => {
127+
setUncontrolledValue(e.currentTarget.value);
128+
onChange?.(e);
129+
}}
130+
ref={ref}
131+
></LeafyGreenTextInput>
132+
);
133+
}
134+
);
135+
136+
TextInput.displayName = 'TextInput';
137+
115138
// 3. Export the leafygreen components.
116139
export {
117140
AtlasNavGraphic,

packages/compass-connection-import-export/src/components/select-table.tsx renamed to packages/compass-components/src/components/select-table.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import React, { useCallback } from 'react';
12
import {
23
Cell,
34
Checkbox,
@@ -7,8 +8,7 @@ import {
78
Table,
89
TableBody,
910
TableHead,
10-
} from '@mongodb-js/compass-components';
11-
import React, { useCallback } from 'react';
11+
} from './leafygreen';
1212

1313
type SelectItem = {
1414
id: string;

packages/compass-components/src/components/workspace-container.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ const darkThemeStyles = css({
9999
});
100100

101101
type WorkspaceContainerProps = {
102-
toolbar?: React.ReactNode;
102+
toolbar?: React.ReactNode | (() => void);
103103
toolbarRef?: React.Ref<HTMLDivElement>;
104104
scrollableContainerRef?: React.Ref<HTMLDivElement>;
105105
initialTopInView?: boolean;
@@ -148,7 +148,7 @@ function WorkspaceContainer({
148148
>
149149
{toolbar && (
150150
<div ref={toolbarRef} className={toolbarStyles}>
151-
{toolbar}
151+
{typeof toolbar === 'function' ? toolbar() : toolbar}
152152
</div>
153153
)}
154154
<div className={scrollBoxStyles} ref={scrollContainer}>

packages/compass-components/src/hooks/use-confirmation.tsx

+31
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { Variant as ConfirmationModalVariant } from '@leafygreen-ui/confirmation
99
import ConfirmationModal from '../components/modals/confirmation-modal';
1010
import { css } from '@leafygreen-ui/emotion';
1111
import type { ButtonProps } from '@leafygreen-ui/button';
12+
import FormFieldContainer from '../components/form-field-container';
13+
import { TextInput } from '../components/leafygreen';
1214

1315
export { ConfirmationModalVariant };
1416

@@ -207,3 +209,32 @@ export const ConfirmationModalArea: React.FunctionComponent = ({
207209
</ConfirmationModalAreaMountedContext.Provider>
208210
);
209211
};
212+
213+
export async function showPrompt(
214+
props: Omit<ConfirmationProperties, 'requiredInputText'> & {
215+
label: string;
216+
defaultValue?: string;
217+
}
218+
): Promise<string | null> {
219+
let userInput = props.defaultValue ?? '';
220+
const submitted = await showConfirmation({
221+
...props,
222+
description: (
223+
<>
224+
{props.description && <div>{props.description}</div>}
225+
<div>
226+
<FormFieldContainer>
227+
<TextInput
228+
label={props.label}
229+
defaultValue={userInput}
230+
onChange={(e) => {
231+
userInput = e.currentTarget.value;
232+
}}
233+
></TextInput>
234+
</FormFieldContainer>
235+
</div>
236+
</>
237+
),
238+
});
239+
return submitted ? userInput : null;
240+
}

packages/compass-components/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ export {
180180
ConfirmationModalVariant,
181181
ConfirmationModalArea,
182182
showConfirmation,
183+
showPrompt,
183184
} from './hooks/use-confirmation';
184185
export { showErrorDetails } from './hooks/use-error-details';
185186
export {
@@ -209,3 +210,4 @@ export {
209210
type VirtualListProps,
210211
type ItemRenderer as VirtualListItemRenderer,
211212
} from './components/virtual-list';
213+
export { SelectTable } from './components/select-table';

packages/compass-connection-import-export/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@
7272
"chai": "^4.3.6",
7373
"depcheck": "^1.4.1",
7474
"gen-esm-wrapper": "^1.1.0",
75-
"lodash": "^4.17.21",
7675
"mocha": "^10.2.0",
7776
"nyc": "^15.1.0",
7877
"sinon": "^9.2.3",

packages/compass-connection-import-export/src/components/export-modal.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import {
66
FormFieldContainer,
77
FormModal,
88
openToast,
9+
SelectTable,
910
} from '@mongodb-js/compass-components';
1011
import { FileInput } from './file-input';
1112
import { Passphrase } from './passphrase';
12-
import { SelectTable } from './select-table';
1313
import type { ImportExportResult } from '../hooks/common';
1414
import { useOpenModalThroughIpc } from '../hooks/common';
1515
import { useExportConnections } from '../hooks/use-export-connections';

packages/compass-connection-import-export/src/components/import-modal.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import {
77
FormModal,
88
spacing,
99
openToast,
10+
SelectTable,
1011
} from '@mongodb-js/compass-components';
1112
import { FileInput } from './file-input';
1213
import { Passphrase } from './passphrase';
13-
import { SelectTable } from './select-table';
1414
import type { ImportExportResult } from '../hooks/common';
1515
import { useOpenModalThroughIpc } from '../hooks/common';
1616
import { useImportConnections } from '../hooks/use-import-connections';

packages/compass-connections/src/stores/connections-store-redux.ts

+51-44
Original file line numberDiff line numberDiff line change
@@ -1479,60 +1479,67 @@ const connectWithOptions = (
14791479
return inflightConnection;
14801480
}
14811481
inflightConnection = (async () => {
1482-
const isAutoconnectAttempt = isAutoconnectInfo(
1483-
getState(),
1484-
connectionInfo.id
1485-
);
1486-
14871482
const deviceAuthAbortController = new AbortController();
14881483

1489-
connectionInfo = cloneDeep(connectionInfo);
1484+
try {
1485+
if (
1486+
getCurrentConnectionStatus(getState(), connectionInfo.id) ===
1487+
'connected'
1488+
) {
1489+
return;
1490+
}
14901491

1491-
const {
1492-
forceConnectionOptions,
1493-
browserCommandForOIDCAuth,
1494-
maximumNumberOfActiveConnections,
1495-
telemetryAnonymousId,
1496-
} = preferences.getPreferences();
1492+
const isAutoconnectAttempt = isAutoconnectInfo(
1493+
getState(),
1494+
connectionInfo.id
1495+
);
14971496

1498-
const connectionProgress = getNotificationTriggers();
1497+
connectionInfo = cloneDeep(connectionInfo);
14991498

1500-
if (
1501-
typeof maximumNumberOfActiveConnections !== 'undefined' &&
1502-
getActiveConnectionsCount(getState().connections) >=
1503-
maximumNumberOfActiveConnections
1504-
) {
1505-
connectionProgress.openMaximumConnectionsReachedToast(
1506-
maximumNumberOfActiveConnections
1507-
);
1508-
return;
1509-
}
1499+
const {
1500+
forceConnectionOptions,
1501+
browserCommandForOIDCAuth,
1502+
maximumNumberOfActiveConnections,
1503+
telemetryAnonymousId,
1504+
} = preferences.getPreferences();
15101505

1511-
dispatch({
1512-
type: ActionTypes.ConnectionAttemptStart,
1513-
connectionInfo,
1514-
options: { forceSave: options.forceSave },
1515-
});
1506+
const connectionProgress = getNotificationTriggers();
15161507

1517-
track(
1518-
'Connection Attempt',
1519-
{
1520-
is_favorite: connectionInfo.savedConnectionType === 'favorite',
1521-
is_new: isNewConnection(getState(), connectionInfo.id),
1522-
},
1523-
connectionInfo
1524-
);
1508+
if (
1509+
typeof maximumNumberOfActiveConnections !== 'undefined' &&
1510+
getActiveConnectionsCount(getState().connections) >=
1511+
maximumNumberOfActiveConnections
1512+
) {
1513+
connectionProgress.openMaximumConnectionsReachedToast(
1514+
maximumNumberOfActiveConnections
1515+
);
1516+
return;
1517+
}
15251518

1526-
debug('connecting with connectionInfo', connectionInfo);
1519+
dispatch({
1520+
type: ActionTypes.ConnectionAttemptStart,
1521+
connectionInfo,
1522+
options: { forceSave: options.forceSave },
1523+
});
15271524

1528-
log.info(
1529-
mongoLogId(1_001_000_004),
1530-
'Connection UI',
1531-
'Initiating connection attempt',
1532-
{ isAutoconnectAttempt }
1533-
);
1525+
track(
1526+
'Connection Attempt',
1527+
{
1528+
is_favorite: connectionInfo.savedConnectionType === 'favorite',
1529+
is_new: isNewConnection(getState(), connectionInfo.id),
1530+
},
1531+
connectionInfo
1532+
);
1533+
1534+
debug('connecting with connectionInfo', connectionInfo);
1535+
1536+
log.info(
1537+
mongoLogId(1_001_000_004),
1538+
'Connection UI',
1539+
'Initiating connection attempt',
1540+
{ isAutoconnectAttempt }
1541+
);
15341542

1535-
try {
15361543
// Connection form allows to start connecting with invalid connection
15371544
// strings, so throw fast if it's not valid before doing anything else
15381545
ensureWellFormedConnectionString(

packages/compass-connections/src/stores/store-context.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,15 @@ export function useConnectionIds(
271271
export function useConnectionsList(
272272
filter?: (connection: ConnectionState) => boolean
273273
) {
274-
return useSelector<ConnectionState[]>(
274+
return useSelector<(ConnectionState & { title: string })[]>(
275275
(state) => {
276276
return state.connections.ids
277277
.filter((id) => {
278278
return filter?.(state.connections.byId[id]) ?? true;
279279
})
280280
.map((id) => {
281-
return state.connections.byId[id];
281+
const connection = state.connections.byId[id];
282+
return { ...connection, title: getConnectionTitle(connection.info) };
282283
});
283284
},
284285
(a, b) => {

0 commit comments

Comments
 (0)