Skip to content

Commit 2ae7c7a

Browse files
Merge remote-tracking branch 'origin/main' into beta-releases
2 parents 6451dc2 + ed2a43e commit 2ae7c7a

36 files changed

+1670
-1771
lines changed

THIRD-PARTY-NOTICES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
The following third-party software is used by and included in **Mongodb Compass**.
2-
This document was automatically generated on Sun Jul 28 2024.
2+
This document was automatically generated on Tue Jul 30 2024.
33

44
## List of dependencies
55

package-lock.json

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/compass-connections/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@
5353
"dependencies": {
5454
"@mongodb-js/compass-components": "^1.28.1",
5555
"@mongodb-js/compass-logging": "^1.4.2",
56-
"@mongodb-js/compass-telemetry": "^1.1.2",
5756
"@mongodb-js/compass-maybe-protect-connection-string": "^0.23.1",
57+
"@mongodb-js/compass-telemetry": "^1.1.2",
58+
"@mongodb-js/compass-utils": "^0.6.7",
5859
"@mongodb-js/connection-form": "^1.35.0",
5960
"@mongodb-js/connection-info": "^0.5.2",
6061
"@mongodb-js/connection-storage": "^0.16.1",
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import React, { useCallback } from 'react';
2+
import { css, Link, spacing, useToast } from '@mongodb-js/compass-components';
3+
import type { ConnectionInfo } from '@mongodb-js/connection-info';
4+
import { getConnectionTitle } from '@mongodb-js/connection-info';
5+
import { usePreference } from 'compass-preferences-model/provider';
6+
import ConnectionString from 'mongodb-connection-string-url';
7+
import { isCancelError } from '@mongodb-js/compass-utils';
8+
9+
export function isOIDCAuth(connectionString: string): boolean {
10+
const authMechanismString = (
11+
new ConnectionString(connectionString).searchParams.get('authMechanism') ||
12+
''
13+
).toUpperCase();
14+
15+
return authMechanismString === 'MONGODB-OIDC';
16+
}
17+
18+
export function getConnectionErrorMessage(err?: any) {
19+
return isCancelError(err) ? null : err?.message ?? null;
20+
}
21+
22+
export function getConnectingStatusText(connectionInfo: ConnectionInfo) {
23+
const connectionTitle = getConnectionTitle(connectionInfo);
24+
const isOIDC = isOIDCAuth(connectionInfo.connectionOptions.connectionString);
25+
return {
26+
title: `Connecting to ${connectionTitle}`,
27+
description: isOIDC ? 'Go to the browser to complete authentication' : '',
28+
};
29+
}
30+
31+
type ConnectionErrorToastBodyProps = {
32+
info?: ConnectionInfo | null;
33+
onReview: () => void;
34+
};
35+
36+
const connectionErrorToastBodyStyles = css({
37+
display: 'flex',
38+
alignItems: 'start',
39+
gap: spacing[2],
40+
});
41+
42+
const connectionErrorToastActionMessageStyles = css({
43+
marginTop: spacing[1],
44+
flexGrow: 0,
45+
});
46+
47+
function ConnectionErrorToastBody({
48+
info,
49+
onReview,
50+
}: ConnectionErrorToastBodyProps): React.ReactElement {
51+
return (
52+
<span className={connectionErrorToastBodyStyles}>
53+
<span data-testid="connection-error-text">
54+
There was a problem connecting{' '}
55+
{info ? `to ${getConnectionTitle(info)}` : ''}
56+
</span>
57+
{info && (
58+
<Link
59+
className={connectionErrorToastActionMessageStyles}
60+
hideExternalIcon={true}
61+
onClick={onReview}
62+
data-testid="connection-error-review"
63+
>
64+
REVIEW
65+
</Link>
66+
)}
67+
</span>
68+
);
69+
}
70+
71+
const noop = () => undefined;
72+
73+
export function useConnectionStatusToasts() {
74+
const enableNewMultipleConnectionSystem = usePreference(
75+
'enableNewMultipleConnectionSystem'
76+
);
77+
const { openToast, closeToast } = useToast('connection-status');
78+
79+
const openConnectionStartedToast = useCallback(
80+
(connectionInfo: ConnectionInfo, onCancelClick: () => void) => {
81+
const { title, description } = getConnectingStatusText(connectionInfo);
82+
openToast(connectionInfo.id, {
83+
title,
84+
description,
85+
dismissible: true,
86+
variant: 'progress',
87+
actionElement: (
88+
<Link
89+
hideExternalIcon={true}
90+
onClick={() => {
91+
closeToast(connectionInfo.id);
92+
onCancelClick();
93+
}}
94+
>
95+
CANCEL
96+
</Link>
97+
),
98+
});
99+
},
100+
[closeToast, openToast]
101+
);
102+
103+
const openConnectionSucceededToast = useCallback(
104+
(connectionInfo: ConnectionInfo) => {
105+
openToast(connectionInfo.id, {
106+
title: `Connected to ${getConnectionTitle(connectionInfo)}`,
107+
variant: 'success',
108+
timeout: 3_000,
109+
});
110+
},
111+
[openToast]
112+
);
113+
114+
const openConnectionFailedToast = useCallback(
115+
(
116+
// Connection info might be missing if we failed connecting before we
117+
// could even resolve connection info. Currently the only case where this
118+
// can happen is autoconnect flow
119+
connectionInfo: ConnectionInfo | null | undefined,
120+
error: Error,
121+
onReviewClick: () => void
122+
) => {
123+
const failedToastId = connectionInfo?.id ?? 'failed';
124+
125+
openToast(failedToastId, {
126+
title: error.message,
127+
description: (
128+
<ConnectionErrorToastBody
129+
info={connectionInfo}
130+
onReview={() => {
131+
closeToast(failedToastId);
132+
onReviewClick();
133+
}}
134+
/>
135+
),
136+
variant: 'warning',
137+
});
138+
},
139+
[closeToast, openToast]
140+
);
141+
142+
const openMaximumConnectionsReachedToast = useCallback(
143+
(maxConcurrentConnections: number) => {
144+
const message = `Only ${maxConcurrentConnections} connection${
145+
maxConcurrentConnections > 1 ? 's' : ''
146+
} can be connected to at the same time. First disconnect from another connection.`;
147+
148+
openToast('max-connections-reached', {
149+
title: 'Maximum concurrent connections limit reached',
150+
description: message,
151+
variant: 'warning',
152+
timeout: 5_000,
153+
});
154+
},
155+
[openToast]
156+
);
157+
158+
return enableNewMultipleConnectionSystem
159+
? {
160+
openConnectionStartedToast,
161+
openConnectionSucceededToast,
162+
openConnectionFailedToast,
163+
openMaximumConnectionsReachedToast,
164+
closeConnectionStatusToast: closeToast,
165+
}
166+
: {
167+
openConnectionStartedToast: noop,
168+
openConnectionSucceededToast: noop,
169+
openConnectionFailedToast: noop,
170+
openMaximumConnectionsReachedToast: noop,
171+
closeConnectionStatusToast: noop,
172+
};
173+
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
import { ConnectionsManager, ConnectionsManagerProvider } from '../provider';
2525
import type { DataService } from 'mongodb-data-service';
2626
import { createNoopLogger } from '@mongodb-js/compass-logging/provider';
27+
import { ConnectionsProvider } from './connections-provider';
2728

2829
function getConnectionsManager(mockTestConnectFn?: typeof connect) {
2930
const { log } = createNoopLogger();
@@ -75,7 +76,9 @@ describe('Connections Component', function () {
7576
<PreferencesProvider value={preferences}>
7677
<ConnectionStorageProvider value={mockStorage}>
7778
<ConnectionsManagerProvider value={getConnectionsManager()}>
78-
<Connections appRegistry={{} as any} />
79+
<ConnectionsProvider>
80+
<Connections appRegistry={{} as any} />
81+
</ConnectionsProvider>
7982
</ConnectionsManagerProvider>
8083
</ConnectionStorageProvider>
8184
</PreferencesProvider>

0 commit comments

Comments
 (0)