Skip to content

Commit 919397b

Browse files
authored
feat(connection-form): up to three buttons: save, connect, save & connect COMPASS-8360 (#6341)
* save, connect, save & onnect * reformat * tests * tests * add forceSave option to connect action creator
1 parent 33f37c2 commit 919397b

File tree

12 files changed

+274
-76
lines changed

12 files changed

+274
-76
lines changed

packages/compass-connections/src/components/legacy-connections.spec.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ async function loadSavedConnectionAndConnect(connectionInfo: ConnectionInfo) {
2525
)
2626
);
2727

28-
const connectButton = screen.getByRole('button', { name: 'Connect' });
28+
const connectButton = screen.getByRole('button', { name: 'Save & Connect' });
2929
userEvent.click(connectButton);
3030

3131
// Wait for the connecting... modal to hide.
@@ -267,7 +267,9 @@ describe.skip('Connections Component', function () {
267267
)
268268
);
269269

270-
const connectButton = screen.getByRole('button', { name: 'Connect' });
270+
const connectButton = screen.getByRole('button', {
271+
name: 'Save & Connect',
272+
});
271273
userEvent.click(connectButton);
272274

273275
// Wait for the connecting... modal to be shown.
@@ -288,7 +290,9 @@ describe.skip('Connections Component', function () {
288290
});
289291

290292
it('should enable the connect button', function () {
291-
const connectButton = screen.getByText('Connect');
293+
const connectButton = screen.getByRole('button', {
294+
name: 'Save & Connect',
295+
});
292296
expect(connectButton).to.not.match('disabled');
293297
});
294298

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

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ type ConnectionAutoconnectCheckAction = {
313313
type ConnectionAttemptStartAction = {
314314
type: ActionTypes.ConnectionAttemptStart;
315315
connectionInfo: ConnectionInfo;
316+
options: {
317+
forceSave: boolean;
318+
};
316319
};
317320

318321
type ConnectionAttemptSuccessAction = {
@@ -823,10 +826,13 @@ const reducer: Reducer<State, Action> = (state = INITIAL_STATE, action) => {
823826
state.connections,
824827
action.connectionInfo.id,
825828
{
826-
...(isNewConnection(state, action.connectionInfo.id)
829+
...(isNewConnection(state, action.connectionInfo.id) ||
830+
action.options.forceSave
827831
? {
828-
// For new connections, update the state with new info right
829-
// away (we will also save it to the storage at the end)
832+
// For new connections or when we're forcing a
833+
// save (the Save & Connect button), update the state with new
834+
// info right away (we will also save it to the storage at the
835+
// end)
830836
info: action.connectionInfo,
831837
}
832838
: {
@@ -1464,6 +1470,35 @@ export const connect = (
14641470
| ConnectionAttemptSuccessAction
14651471
| ConnectionAttemptCancelledAction
14661472
| OidcNotifyDeviceAuthAction
1473+
> => {
1474+
return connectWithOptions(connectionInfo, { forceSave: false });
1475+
};
1476+
1477+
export const saveAndConnect = (
1478+
connectionInfo: ConnectionInfo
1479+
): ConnectionsThunkAction<
1480+
Promise<void>,
1481+
| ConnectionAttemptStartAction
1482+
| ConnectionAttemptErrorAction
1483+
| ConnectionAttemptSuccessAction
1484+
| ConnectionAttemptCancelledAction
1485+
| OidcNotifyDeviceAuthAction
1486+
> => {
1487+
return connectWithOptions(connectionInfo, { forceSave: true });
1488+
};
1489+
1490+
const connectWithOptions = (
1491+
connectionInfo: ConnectionInfo,
1492+
options: {
1493+
forceSave: boolean;
1494+
}
1495+
): ConnectionsThunkAction<
1496+
Promise<void>,
1497+
| ConnectionAttemptStartAction
1498+
| ConnectionAttemptErrorAction
1499+
| ConnectionAttemptSuccessAction
1500+
| ConnectionAttemptCancelledAction
1501+
| OidcNotifyDeviceAuthAction
14671502
> => {
14681503
return async (
14691504
dispatch,
@@ -1516,6 +1551,7 @@ export const connect = (
15161551
dispatch({
15171552
type: ActionTypes.ConnectionAttemptStart,
15181553
connectionInfo,
1554+
options: { forceSave: options.forceSave },
15191555
});
15201556

15211557
track(

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,37 @@ describe('useConnections', function () {
323323
}
324324
});
325325

326+
describe('#saveAndConnect', function () {
327+
it('saves the connection options before connecting', async function () {
328+
const { result, track, connectionStorage } = renderHookWithConnections(
329+
useConnections,
330+
{
331+
connections: mockConnections,
332+
preferences: defaultPreferences,
333+
}
334+
);
335+
336+
const updatedConnection = {
337+
...mockConnections[0],
338+
savedConnectionType: 'recent' as const,
339+
};
340+
341+
await result.current.saveAndConnect(updatedConnection);
342+
343+
await waitFor(() => {
344+
expect(track.getCall(1).firstArg).to.eq('New Connection');
345+
});
346+
347+
expect(
348+
await connectionStorage.load({ id: updatedConnection.id })
349+
).to.have.property('savedConnectionType', 'recent');
350+
351+
expect(
352+
screen.getByText(`Connected to ${mockConnections[0].favorite.name}`)
353+
).to.exist;
354+
});
355+
});
356+
326357
describe('#disconnect', function () {
327358
it('disconnect even if connection is in progress cleaning up progress toasts', async function () {
328359
const { result, track } = renderHookWithConnections(useConnections, {

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ type State = {
55
connectionErrors: Record<string, Error | null>;
66
editingConnectionInfo: ConnectionInfo;
77
isEditingConnectionInfoModalOpen: boolean;
8+
isEditingNewConnection: boolean;
89
oidcDeviceAuthState: Record<string, { url: string; code: string }>;
910
};
1011

@@ -15,6 +16,7 @@ export function useConnections(): {
1516
state: State;
1617

1718
connect: (connectionInfo: ConnectionInfo) => Promise<void>;
19+
saveAndConnect: (connectionInfo: ConnectionInfo) => Promise<void>;
1820
disconnect: (connectionId: string) => void;
1921

2022
createNewConnection: () => void;
@@ -32,16 +34,16 @@ export function useConnections(): {
3234
showNonGenuineMongoDBWarningModal: (connectionId: string) => void;
3335
} {
3436
const connectionsState = useConnectionsState();
37+
const editingConnection =
38+
connectionsState.connections.byId[connectionsState.editingConnectionInfoId];
3539
const state = {
3640
connectionErrors: Object.fromEntries(
3741
Object.entries(connectionsState.connections.byId).map(([k, v]) => {
3842
return [k, v.error ?? null];
3943
})
4044
),
41-
editingConnectionInfo:
42-
connectionsState.connections.byId[
43-
connectionsState.editingConnectionInfoId
44-
].info,
45+
editingConnectionInfo: editingConnection.info,
46+
isEditingNewConnection: !!editingConnection.isBeingCreated,
4547
isEditingConnectionInfoModalOpen:
4648
connectionsState.isEditingConnectionInfoModalOpen,
4749
oidcDeviceAuthState: Object.fromEntries(
@@ -52,6 +54,7 @@ export function useConnections(): {
5254
};
5355
const {
5456
connect,
57+
saveAndConnect,
5558
disconnect,
5659
createNewConnection,
5760
editConnection,
@@ -66,6 +69,7 @@ export function useConnections(): {
6669
return {
6770
state,
6871
connect,
72+
saveAndConnect,
6973
disconnect,
7074
createNewConnection,
7175
editConnection,

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type {
1818
import {
1919
cancelEditConnection,
2020
connect as connectionsConnect,
21+
saveAndConnect,
2122
connectionsEventEmitter,
2223
createNewConnection,
2324
disconnect,
@@ -87,6 +88,9 @@ function getConnectionsActions(dispatch: ConnectionsStore['dispatch']) {
8788
connect: (connectionInfo: ConnectionInfo) => {
8889
return dispatch(connectionsConnect(connectionInfo));
8990
},
91+
saveAndConnect: (connectionInfo: ConnectionInfo) => {
92+
return dispatch(saveAndConnect(connectionInfo));
93+
},
9094
disconnect: (connectionId: ConnectionId) => {
9195
return dispatch(disconnect(connectionId));
9296
},

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

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export function MultipleConnectionSidebar({
109109
const connectionsWithStatus = useConnectionsWithStatus();
110110
const {
111111
connect,
112+
saveAndConnect,
112113
disconnect,
113114
createNewConnection,
114115
editConnection,
@@ -120,6 +121,7 @@ export function MultipleConnectionSidebar({
120121
showNonGenuineMongoDBWarningModal,
121122
state: {
122123
editingConnectionInfo,
124+
isEditingNewConnection,
123125
isEditingConnectionInfoModalOpen,
124126
connectionErrors,
125127
},
@@ -184,6 +186,10 @@ export function MultipleConnectionSidebar({
184186
[globalAppRegistry]
185187
);
186188

189+
const disableEditingConnectedConnection = !!findActiveConnection(
190+
editingConnectionInfo.id
191+
);
192+
187193
return (
188194
<ResizableSidebar data-testid="navigation-sidebar" useNewTheme={true}>
189195
<aside className={sidebarStyles}>
@@ -229,7 +235,7 @@ export function MultipleConnectionSidebar({
229235
{editingConnectionInfo && (
230236
<ConnectionFormModal
231237
disableEditingConnectedConnection={
232-
!!findActiveConnection(editingConnectionInfo.id)
238+
disableEditingConnectedConnection
233239
}
234240
onDisconnectClicked={() => disconnect(editingConnectionInfo.id)}
235241
isOpen={isEditingConnectionInfoModalOpen}
@@ -240,20 +246,31 @@ export function MultipleConnectionSidebar({
240246
}
241247
}}
242248
initialConnectionInfo={editingConnectionInfo}
243-
onSaveAndConnectClicked={(connectionInfo) => {
244-
void connect(connectionInfo);
245-
}}
246-
onSaveClicked={(connectionInfo) => {
247-
return saveEditedConnection(connectionInfo);
248-
}}
249-
onCancel={() => {
250-
cancelEditConnection(editingConnectionInfo.id);
251-
}}
252249
connectionErrorMessage={
253250
connectionErrors[editingConnectionInfo.id]?.message
254251
}
255252
openSettingsModal={openSettingsModal}
256253
{...formPreferences}
254+
onCancel={() => {
255+
cancelEditConnection(editingConnectionInfo.id);
256+
}}
257+
onSaveClicked={(connectionInfo) => {
258+
return saveEditedConnection(connectionInfo);
259+
}}
260+
onConnectClicked={
261+
isEditingNewConnection || disableEditingConnectedConnection
262+
? undefined
263+
: (connectionInfo) => {
264+
void connect(connectionInfo);
265+
}
266+
}
267+
onSaveAndConnectClicked={
268+
disableEditingConnectedConnection
269+
? undefined
270+
: (connectionInfo) => {
271+
void saveAndConnect(connectionInfo);
272+
}
273+
}
257274
/>
258275
)}
259276
<MappedCsfleModal

packages/compass-web/src/entrypoint.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ describe('CompassWeb', function () {
8181
screen.getAllByRole('button', { name: 'Add new connection' })[0]
8282
);
8383
await waitFor(() => {
84-
screen.getByRole('button', { name: 'Connect' });
84+
screen.getByRole('button', { name: 'Save & Connect' });
8585
});
86-
userEvent.click(screen.getByRole('button', { name: 'Connect' }));
86+
userEvent.click(screen.getByRole('button', { name: 'Save & Connect' }));
8787
return result;
8888
}
8989

packages/connection-form/src/components/connection-form-actions.spec.tsx renamed to packages/connection-form/src/components/connection-form-modal-actions.spec.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { render, screen, userEvent } from '@mongodb-js/testing-library-compass';
33
import { expect } from 'chai';
44
import sinon from 'sinon';
55

6-
import { ConnectionFormModalActions } from './connection-form-actions';
6+
import { ConnectionFormModalActions } from './connection-form-modal-actions';
77

88
describe('<ConnectionFormModalActions />', function () {
99
it('should show warnings', function () {
@@ -30,7 +30,7 @@ describe('<ConnectionFormModalActions />', function () {
3030
expect(screen.getByText('Error!')).to.be.visible;
3131
});
3232

33-
describe('Connect Button', function () {
33+
describe('Save&Connect Button', function () {
3434
it('should call onSaveAndConnect function', function () {
3535
const onSaveAndConnectSpy = sinon.spy();
3636
render(
@@ -41,7 +41,9 @@ describe('<ConnectionFormModalActions />', function () {
4141
onSaveAndConnect={onSaveAndConnectSpy}
4242
></ConnectionFormModalActions>
4343
);
44-
const connectButton = screen.getByRole('button', { name: 'Connect' });
44+
const connectButton = screen.getByRole('button', {
45+
name: 'Save & Connect',
46+
});
4547
userEvent.click(connectButton);
4648

4749
expect(onSaveAndConnectSpy).to.have.been.calledOnce;
@@ -54,7 +56,8 @@ describe('<ConnectionFormModalActions />', function () {
5456
warnings={[]}
5557
></ConnectionFormModalActions>
5658
);
57-
expect(screen.queryByRole('button', { name: 'Connect' })).to.not.exist;
59+
expect(screen.queryByRole('button', { name: 'Save & Connect' })).to.not
60+
.exist;
5861
});
5962
});
6063

packages/connection-form/src/components/connection-form-actions.tsx renamed to packages/connection-form/src/components/connection-form-modal-actions.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export type ConnectionFormModalActionsProps = {
4545
onCancel?(): void;
4646
onSave?(): void;
4747
onSaveAndConnect?(): void;
48+
onConnect?(): void;
4849
};
4950

5051
export function ConnectionFormModalActions({
@@ -53,6 +54,7 @@ export function ConnectionFormModalActions({
5354
onCancel,
5455
onSave,
5556
onSaveAndConnect,
57+
onConnect,
5658
}: ConnectionFormModalActionsProps): React.ReactElement {
5759
const saveAndConnectLabel = useConnectionFormSetting('saveAndConnectLabel');
5860
return (
@@ -102,9 +104,21 @@ export function ConnectionFormModalActions({
102104
</div>
103105
)}
104106

107+
{onConnect && (
108+
<Button
109+
data-testid={'connect-button'}
110+
variant={ButtonVariant.PrimaryOutline}
111+
onClick={onConnect}
112+
>
113+
Connect
114+
</Button>
115+
)}
116+
105117
{onSaveAndConnect && (
106118
<Button
107-
data-testid="connect-button"
119+
data-testid={
120+
onConnect ? 'save-and-connect-button' : 'connect-button'
121+
}
108122
variant={ButtonVariant.Primary}
109123
onClick={onSaveAndConnect}
110124
>

0 commit comments

Comments
 (0)