Skip to content

Commit 82eddaa

Browse files
authored
feat: connection form as a modal COMPASS-7709 (#5578)
1 parent 1a8fae4 commit 82eddaa

File tree

8 files changed

+253
-72
lines changed

8 files changed

+253
-72
lines changed

packages/compass-sidebar/src/components/multiple-connections/saved-connections/saved-connection-list.spec.tsx

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,32 +56,55 @@ describe('SavedConnectionList Component', function () {
5656
);
5757
}
5858

59-
beforeEach(function () {
60-
doRender([FAVOURITE_CONNECTION_INFO], [NON_FAVOURITE_CONNECTION_INFO]);
61-
});
59+
describe('When saved connections exist', function () {
60+
beforeEach(function () {
61+
doRender([FAVOURITE_CONNECTION_INFO], [NON_FAVOURITE_CONNECTION_INFO]);
62+
});
6263

63-
afterEach(function () {
64-
cleanup();
65-
});
64+
afterEach(function () {
65+
cleanup();
66+
});
6667

67-
it('should render all connections', function () {
68-
[FAVOURITE_CONNECTION_INFO, NON_FAVOURITE_CONNECTION_INFO].every(
69-
(connection) => {
70-
expect(screen.queryByText(connection.favorite?.name || '<>')).to.exist;
71-
}
72-
);
73-
});
68+
it('should render all connections', function () {
69+
[FAVOURITE_CONNECTION_INFO, NON_FAVOURITE_CONNECTION_INFO].every(
70+
(connection) => {
71+
expect(screen.queryByText(connection.favorite?.name || '<>')).to
72+
.exist;
73+
}
74+
);
75+
});
76+
77+
it('should allow to create new connections', async function () {
78+
const newConnectionButton = screen.getByTestId('new-connection-button');
79+
userEvent.click(newConnectionButton);
7480

75-
it('should allow to create new connections', async function () {
76-
const newConnectionButton = screen.getByTestId('new-connection-button');
77-
userEvent.click(newConnectionButton);
81+
await waitFor(() => {
82+
expect(onNewConnectionSpy).to.have.been.called;
83+
});
84+
});
85+
86+
it('should show the number of connections', function () {
87+
expect(screen.queryByText('(2)')).to.exist;
88+
});
7889

79-
await waitFor(() => {
80-
expect(onNewConnectionSpy).to.have.been.called;
90+
it('should not show the empty connections message', function () {
91+
expect(screen.queryByText('You have not connected to any deployments')).to
92+
.be.null;
8193
});
8294
});
8395

84-
it('should show the number of connections', function () {
85-
expect(screen.queryByText('(2)')).to.exist;
96+
describe('When there are no saved connections', function () {
97+
beforeEach(function () {
98+
doRender([], []);
99+
});
100+
101+
afterEach(function () {
102+
cleanup();
103+
});
104+
105+
it('should show the empty connections message', function () {
106+
expect(screen.queryByText('You have not connected to any deployments')).to
107+
.be.visible;
108+
});
86109
});
87110
});

packages/compass-sidebar/src/components/multiple-connections/saved-connections/saved-connection-list.tsx

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import type { ConnectionInfo } from '@mongodb-js/connection-info';
22
import React from 'react';
33
import { SavedConnection } from './saved-connection';
44
import {
5+
Button,
56
Subtitle,
67
Icon,
78
IconButton,
89
css,
910
spacing,
1011
} from '@mongodb-js/compass-components';
12+
import { ButtonVariant } from '@mongodb-js/compass-components';
1113

1214
const savedConnectionListStyles = css({
1315
width: '100%',
@@ -34,13 +36,20 @@ const savedConnectionListHeaderStyles = css({
3436
flexDirection: 'row',
3537
alignContent: 'center',
3638
justifyContent: 'space-between',
39+
marginBottom: spacing[2],
3740
});
3841

3942
const savedConnectionListHeaderTitleStyles = css({
4043
marginTop: 0,
4144
marginBottom: 0,
4245
textTransform: 'uppercase',
4346
fontSize: '12px',
47+
lineHeight: '32px',
48+
});
49+
50+
const firstConnectionBtnStyles = css({
51+
width: '100%',
52+
marginTop: spacing[3],
4453
});
4554

4655
type SavedConnectionListProps = {
@@ -87,30 +96,45 @@ export function SavedConnectionList({
8796
</IconButton>
8897
</div>
8998
</header>
90-
<ul className={savedConnectionListPaddingStyles}>
91-
{favoriteConnections.map((conn) => (
92-
<SavedConnection
93-
onConnect={onConnect}
94-
onEditConnection={onEditConnection}
95-
onDuplicateConnection={onDuplicateConnection}
96-
onToggleFavoriteConnection={onToggleFavoriteConnection}
97-
onDeleteConnection={onDeleteConnection}
98-
connectionInfo={conn}
99-
key={conn.id}
100-
/>
101-
))}
102-
{nonFavoriteConnections.map((conn) => (
103-
<SavedConnection
104-
onConnect={onConnect}
105-
onEditConnection={onEditConnection}
106-
onDuplicateConnection={onDuplicateConnection}
107-
onToggleFavoriteConnection={onToggleFavoriteConnection}
108-
onDeleteConnection={onDeleteConnection}
109-
connectionInfo={conn}
110-
key={conn.id}
111-
/>
112-
))}
113-
</ul>
99+
{connectionCount ? (
100+
<ul className={savedConnectionListPaddingStyles}>
101+
{favoriteConnections.map((conn) => (
102+
<SavedConnection
103+
onConnect={onConnect}
104+
onEditConnection={onEditConnection}
105+
onDuplicateConnection={onDuplicateConnection}
106+
onToggleFavoriteConnection={onToggleFavoriteConnection}
107+
onDeleteConnection={onDeleteConnection}
108+
connectionInfo={conn}
109+
key={conn.id}
110+
/>
111+
))}
112+
{nonFavoriteConnections.map((conn) => (
113+
<SavedConnection
114+
onConnect={onConnect}
115+
onEditConnection={onEditConnection}
116+
onDuplicateConnection={onDuplicateConnection}
117+
onToggleFavoriteConnection={onToggleFavoriteConnection}
118+
onDeleteConnection={onDeleteConnection}
119+
connectionInfo={conn}
120+
key={conn.id}
121+
/>
122+
))}
123+
</ul>
124+
) : (
125+
<div>
126+
You have not connected to any deployments
127+
<Button
128+
className={firstConnectionBtnStyles}
129+
data-testid="save-connection-button"
130+
variant={ButtonVariant.Primary}
131+
leftGlyph={<Icon glyph="Plus" />}
132+
onClick={onNewConnection}
133+
>
134+
Add new connection
135+
</Button>
136+
</div>
137+
)}
114138
</div>
115139
);
116140
}

packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx

Lines changed: 98 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import React, { useCallback, useState } from 'react';
1+
import React, { useCallback, useMemo, useState } from 'react';
22
import { useConnections } from '@mongodb-js/compass-connections/provider';
33
import type { ConnectionInfo } from '@mongodb-js/connection-info';
44
import { SavedConnectionList } from './saved-connections/saved-connection-list';
55
import { OpenConnectionList } from './open-connections/open-connection-list';
66
import { ResizableSidebar, css } from '@mongodb-js/compass-components';
77
import { SidebarHeader } from './header/sidebar-header';
8+
import { ConnectionFormModal } from '@mongodb-js/connection-form';
9+
import { cloneDeep } from 'lodash';
10+
import { usePreference } from 'compass-preferences-model/provider';
811

912
// Temporary as we don't need props but this placeholder type is useful.
1013
type MultipleConnectionSidebarProps = Record<string, never>;
@@ -26,18 +29,28 @@ const noop_tmp = (() => {}) as any;
2629
// Having props here is useful as a placeholder and we will fix it with the first props.
2730
// eslint-disable-next-line
2831
export function MultipleConnectionSidebar({}: MultipleConnectionSidebarProps) {
29-
const { favoriteConnections, recentConnections, removeConnection } =
30-
useConnections({
31-
onConnected: noop_tmp, // TODO: COMPASS-7710,
32-
onConnectionAttemptStarted: noop_tmp,
33-
onConnectionFailed: noop_tmp,
34-
isConnected: true, // TODO: COMPASS-7710
35-
connectFn: noop_tmp, // TODO: COMPASS-7710
36-
appName: '', // TODO: COMPASS-7710
37-
getAutoConnectInfo: noop_tmp, // TODO: COMPASS-7710
38-
});
32+
const {
33+
connect,
34+
favoriteConnections,
35+
recentConnections,
36+
removeConnection,
37+
saveConnection,
38+
state,
39+
} = useConnections({
40+
onConnected: noop_tmp, // TODO: COMPASS-7710,
41+
onConnectionAttemptStarted: noop_tmp,
42+
onConnectionFailed: noop_tmp,
43+
isConnected: true, // TODO: COMPASS-7710
44+
connectFn: noop_tmp, // TODO: COMPASS-7710
45+
appName: '', // TODO: COMPASS-7710
46+
getAutoConnectInfo: noop_tmp, // TODO: COMPASS-7710
47+
});
48+
49+
const { activeConnectionId, activeConnectionInfo, connectionErrorMessage } =
50+
state;
3951

4052
const [isExpanded, setIsExpanded] = useState(true);
53+
const [isConnectionFormOpen, setIsConnectionFormOpen] = useState(false);
4154

4255
const onConnect = useCallback(
4356
// Placeholder for when we implement it
@@ -46,9 +59,35 @@ export function MultipleConnectionSidebar({}: MultipleConnectionSidebarProps) {
4659
[]
4760
);
4861

49-
const onNewConnection = useCallback(() => {
50-
// TODO: COMPASS-7710
51-
}, []);
62+
const onNewConnectionOpen = useCallback(
63+
() => setIsConnectionFormOpen(true),
64+
[]
65+
);
66+
const onNewConnectionClose = useCallback(
67+
() => setIsConnectionFormOpen(false),
68+
[]
69+
);
70+
const onNewConnectionToggle = useCallback(
71+
(open: boolean) => setIsConnectionFormOpen(open),
72+
[]
73+
);
74+
75+
const onNewConnectionConnect = useCallback(
76+
(connectionInfo) => {
77+
void connect({
78+
...cloneDeep(connectionInfo),
79+
}).then(() => setIsConnectionFormOpen(false));
80+
},
81+
[connect]
82+
);
83+
84+
const onSaveNewConnection = useCallback(
85+
async (connectionInfo) => {
86+
await saveConnection(connectionInfo);
87+
setIsConnectionFormOpen(false);
88+
},
89+
[saveConnection]
90+
);
5291

5392
const onEditConnection = useCallback(
5493
// Placeholder for when we implement it
@@ -78,6 +117,39 @@ export function MultipleConnectionSidebar({}: MultipleConnectionSidebarProps) {
78117
[]
79118
);
80119

120+
const protectConnectionStrings = usePreference('protectConnectionStrings');
121+
const forceConnectionOptions = usePreference('forceConnectionOptions');
122+
const showKerberosPasswordField = usePreference('showKerberosPasswordField');
123+
const showOIDCDeviceAuthFlow = usePreference('showOIDCDeviceAuthFlow');
124+
const enableOidc = usePreference('enableOidc');
125+
const enableDebugUseCsfleSchemaMap = usePreference(
126+
'enableDebugUseCsfleSchemaMap'
127+
);
128+
const protectConnectionStringsForNewConnections = usePreference(
129+
'protectConnectionStringsForNewConnections'
130+
);
131+
132+
const preferences = useMemo(
133+
() => ({
134+
protectConnectionStrings,
135+
forceConnectionOptions,
136+
showKerberosPasswordField,
137+
showOIDCDeviceAuthFlow,
138+
enableOidc,
139+
enableDebugUseCsfleSchemaMap,
140+
protectConnectionStringsForNewConnections,
141+
}),
142+
[
143+
protectConnectionStrings,
144+
forceConnectionOptions,
145+
showKerberosPasswordField,
146+
showOIDCDeviceAuthFlow,
147+
enableOidc,
148+
enableDebugUseCsfleSchemaMap,
149+
protectConnectionStringsForNewConnections,
150+
]
151+
);
152+
81153
return (
82154
<ResizableSidebar
83155
expanded={isExpanded}
@@ -91,12 +163,23 @@ export function MultipleConnectionSidebar({}: MultipleConnectionSidebarProps) {
91163
favoriteConnections={favoriteConnections}
92164
nonFavoriteConnections={recentConnections}
93165
onConnect={onConnect}
94-
onNewConnection={onNewConnection}
166+
onNewConnection={onNewConnectionOpen}
95167
onEditConnection={onEditConnection}
96168
onDeleteConnection={onDeleteConnection}
97169
onDuplicateConnection={onDuplicateConnection}
98170
onToggleFavoriteConnection={onToggleFavoriteConnection}
99171
/>
172+
<ConnectionFormModal
173+
isOpen={isConnectionFormOpen}
174+
setOpen={onNewConnectionToggle}
175+
onCancel={onNewConnectionClose}
176+
onConnectClicked={onNewConnectionConnect}
177+
key={activeConnectionId}
178+
onSaveConnectionClicked={onSaveNewConnection}
179+
initialConnectionInfo={activeConnectionInfo}
180+
connectionErrorMessage={connectionErrorMessage}
181+
preferences={preferences}
182+
/>
100183
</aside>
101184
</ResizableSidebar>
102185
);

packages/connection-form/src/components/connection-form-actions.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export type ConnectionFormModalActionsProps = {
122122
errors: ConnectionFormError[];
123123
warnings: ConnectionFormWarning[];
124124

125-
onCancel(): void;
125+
onCancel?(): void;
126126
onSave(): void;
127127
onConnect(): void;
128128
};
@@ -153,14 +153,16 @@ export function ConnectionFormModalActions({
153153
</div>
154154
)}
155155
<div className={cx(formActionItemStyles, formActionButtonsStyles)}>
156-
<Button
157-
data-testid="save-connection-button"
158-
variant={ButtonVariant.Default}
159-
disabled={false}
160-
onClick={onCancel}
161-
>
162-
Cancel
163-
</Button>
156+
{onCancel && (
157+
<Button
158+
data-testid="cancel-button"
159+
variant={ButtonVariant.Default}
160+
disabled={false}
161+
onClick={onCancel}
162+
>
163+
Cancel
164+
</Button>
165+
)}
164166

165167
<div className={saveAndConnectStyles}>
166168
<Button

0 commit comments

Comments
 (0)