diff --git a/packages/compass-connections/src/components/legacy-connections.spec.tsx b/packages/compass-connections/src/components/legacy-connections.spec.tsx index 55034c5a608..6a09b91114c 100644 --- a/packages/compass-connections/src/components/legacy-connections.spec.tsx +++ b/packages/compass-connections/src/components/legacy-connections.spec.tsx @@ -25,7 +25,7 @@ async function loadSavedConnectionAndConnect(connectionInfo: ConnectionInfo) { ) ); - const connectButton = screen.getByRole('button', { name: 'Connect' }); + const connectButton = screen.getByRole('button', { name: 'Save & Connect' }); userEvent.click(connectButton); // Wait for the connecting... modal to hide. @@ -267,7 +267,9 @@ describe.skip('Connections Component', function () { ) ); - const connectButton = screen.getByRole('button', { name: 'Connect' }); + const connectButton = screen.getByRole('button', { + name: 'Save & Connect', + }); userEvent.click(connectButton); // Wait for the connecting... modal to be shown. @@ -288,7 +290,9 @@ describe.skip('Connections Component', function () { }); it('should enable the connect button', function () { - const connectButton = screen.getByText('Connect'); + const connectButton = screen.getByRole('button', { + name: 'Save & Connect', + }); expect(connectButton).to.not.match('disabled'); }); diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 886675028fc..368e5875e65 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -313,6 +313,9 @@ type ConnectionAutoconnectCheckAction = { type ConnectionAttemptStartAction = { type: ActionTypes.ConnectionAttemptStart; connectionInfo: ConnectionInfo; + options: { + forceSave: boolean; + }; }; type ConnectionAttemptSuccessAction = { @@ -823,10 +826,13 @@ const reducer: Reducer = (state = INITIAL_STATE, action) => { state.connections, action.connectionInfo.id, { - ...(isNewConnection(state, action.connectionInfo.id) + ...(isNewConnection(state, action.connectionInfo.id) || + action.options.forceSave ? { - // For new connections, update the state with new info right - // away (we will also save it to the storage at the end) + // For new connections or when we're forcing a + // save (the Save & Connect button), update the state with new + // info right away (we will also save it to the storage at the + // end) info: action.connectionInfo, } : { @@ -1464,6 +1470,35 @@ export const connect = ( | ConnectionAttemptSuccessAction | ConnectionAttemptCancelledAction | OidcNotifyDeviceAuthAction +> => { + return connectWithOptions(connectionInfo, { forceSave: false }); +}; + +export const saveAndConnect = ( + connectionInfo: ConnectionInfo +): ConnectionsThunkAction< + Promise, + | ConnectionAttemptStartAction + | ConnectionAttemptErrorAction + | ConnectionAttemptSuccessAction + | ConnectionAttemptCancelledAction + | OidcNotifyDeviceAuthAction +> => { + return connectWithOptions(connectionInfo, { forceSave: true }); +}; + +const connectWithOptions = ( + connectionInfo: ConnectionInfo, + options: { + forceSave: boolean; + } +): ConnectionsThunkAction< + Promise, + | ConnectionAttemptStartAction + | ConnectionAttemptErrorAction + | ConnectionAttemptSuccessAction + | ConnectionAttemptCancelledAction + | OidcNotifyDeviceAuthAction > => { return async ( dispatch, @@ -1516,6 +1551,7 @@ export const connect = ( dispatch({ type: ActionTypes.ConnectionAttemptStart, connectionInfo, + options: { forceSave: options.forceSave }, }); track( diff --git a/packages/compass-connections/src/stores/connections-store.spec.tsx b/packages/compass-connections/src/stores/connections-store.spec.tsx index f0f23139ea0..680118364bf 100644 --- a/packages/compass-connections/src/stores/connections-store.spec.tsx +++ b/packages/compass-connections/src/stores/connections-store.spec.tsx @@ -323,6 +323,37 @@ describe('useConnections', function () { } }); + describe('#saveAndConnect', function () { + it('saves the connection options before connecting', async function () { + const { result, track, connectionStorage } = renderHookWithConnections( + useConnections, + { + connections: mockConnections, + preferences: defaultPreferences, + } + ); + + const updatedConnection = { + ...mockConnections[0], + savedConnectionType: 'recent' as const, + }; + + await result.current.saveAndConnect(updatedConnection); + + await waitFor(() => { + expect(track.getCall(1).firstArg).to.eq('New Connection'); + }); + + expect( + await connectionStorage.load({ id: updatedConnection.id }) + ).to.have.property('savedConnectionType', 'recent'); + + expect( + screen.getByText(`Connected to ${mockConnections[0].favorite.name}`) + ).to.exist; + }); + }); + describe('#disconnect', function () { it('disconnect even if connection is in progress cleaning up progress toasts', async function () { const { result, track } = renderHookWithConnections(useConnections, { diff --git a/packages/compass-connections/src/stores/connections-store.tsx b/packages/compass-connections/src/stores/connections-store.tsx index 1259a364e11..523fa5c7c48 100644 --- a/packages/compass-connections/src/stores/connections-store.tsx +++ b/packages/compass-connections/src/stores/connections-store.tsx @@ -5,6 +5,7 @@ type State = { connectionErrors: Record; editingConnectionInfo: ConnectionInfo; isEditingConnectionInfoModalOpen: boolean; + isEditingNewConnection: boolean; oidcDeviceAuthState: Record; }; @@ -15,6 +16,7 @@ export function useConnections(): { state: State; connect: (connectionInfo: ConnectionInfo) => Promise; + saveAndConnect: (connectionInfo: ConnectionInfo) => Promise; disconnect: (connectionId: string) => void; createNewConnection: () => void; @@ -32,16 +34,16 @@ export function useConnections(): { showNonGenuineMongoDBWarningModal: (connectionId: string) => void; } { const connectionsState = useConnectionsState(); + const editingConnection = + connectionsState.connections.byId[connectionsState.editingConnectionInfoId]; const state = { connectionErrors: Object.fromEntries( Object.entries(connectionsState.connections.byId).map(([k, v]) => { return [k, v.error ?? null]; }) ), - editingConnectionInfo: - connectionsState.connections.byId[ - connectionsState.editingConnectionInfoId - ].info, + editingConnectionInfo: editingConnection.info, + isEditingNewConnection: !!editingConnection.isBeingCreated, isEditingConnectionInfoModalOpen: connectionsState.isEditingConnectionInfoModalOpen, oidcDeviceAuthState: Object.fromEntries( @@ -52,6 +54,7 @@ export function useConnections(): { }; const { connect, + saveAndConnect, disconnect, createNewConnection, editConnection, @@ -66,6 +69,7 @@ export function useConnections(): { return { state, connect, + saveAndConnect, disconnect, createNewConnection, editConnection, diff --git a/packages/compass-connections/src/stores/store-context.tsx b/packages/compass-connections/src/stores/store-context.tsx index 39c6cc778dd..80a66aa7978 100644 --- a/packages/compass-connections/src/stores/store-context.tsx +++ b/packages/compass-connections/src/stores/store-context.tsx @@ -18,6 +18,7 @@ import type { import { cancelEditConnection, connect as connectionsConnect, + saveAndConnect, connectionsEventEmitter, createNewConnection, disconnect, @@ -87,6 +88,9 @@ function getConnectionsActions(dispatch: ConnectionsStore['dispatch']) { connect: (connectionInfo: ConnectionInfo) => { return dispatch(connectionsConnect(connectionInfo)); }, + saveAndConnect: (connectionInfo: ConnectionInfo) => { + return dispatch(saveAndConnect(connectionInfo)); + }, disconnect: (connectionId: ConnectionId) => { return dispatch(disconnect(connectionId)); }, diff --git a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx index d89835c4a7a..3abebc22e78 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx @@ -109,6 +109,7 @@ export function MultipleConnectionSidebar({ const connectionsWithStatus = useConnectionsWithStatus(); const { connect, + saveAndConnect, disconnect, createNewConnection, editConnection, @@ -120,6 +121,7 @@ export function MultipleConnectionSidebar({ showNonGenuineMongoDBWarningModal, state: { editingConnectionInfo, + isEditingNewConnection, isEditingConnectionInfoModalOpen, connectionErrors, }, @@ -184,6 +186,10 @@ export function MultipleConnectionSidebar({ [globalAppRegistry] ); + const disableEditingConnectedConnection = !!findActiveConnection( + editingConnectionInfo.id + ); + return (