diff --git a/package-lock.json b/package-lock.json index aec20cb51c8..03baba4d0db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48844,6 +48844,7 @@ "@mongodb-js/compass-schema-validation": "^6.24.1", "@mongodb-js/compass-sidebar": "^5.24.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", @@ -60582,6 +60583,7 @@ "@mongodb-js/compass-schema-validation": "^6.24.1", "@mongodb-js/compass-sidebar": "^5.24.1", "@mongodb-js/compass-workspaces": "^0.5.1", + "@mongodb-js/connection-storage": "*", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", diff --git a/packages/compass-home/src/components/home.tsx b/packages/compass-home/src/components/home.tsx index 15fb5e737bd..574d88fd42e 100644 --- a/packages/compass-home/src/components/home.tsx +++ b/packages/compass-home/src/components/home.tsx @@ -52,6 +52,7 @@ import { ConnectionStorageContext, ConnectionRepositoryContextProvider, } from '@mongodb-js/connection-storage/provider'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; resetGlobalCSS(); @@ -385,14 +386,16 @@ function Home({ scopeName="Connected Application" > - - - - - + + + + + + + )} diff --git a/packages/compass-web/package.json b/packages/compass-web/package.json index 0712eff10ab..e47ad6be0fd 100644 --- a/packages/compass-web/package.json +++ b/packages/compass-web/package.json @@ -72,12 +72,13 @@ "@mongodb-js/compass-field-store": "^9.0.19", "@mongodb-js/compass-generative-ai": "^0.8.1", "@mongodb-js/compass-indexes": "^5.23.1", + "@mongodb-js/compass-logging": "^1.2.14", "@mongodb-js/compass-query-bar": "^8.25.1", "@mongodb-js/compass-schema": "^6.25.1", "@mongodb-js/compass-schema-validation": "^6.24.1", "@mongodb-js/compass-sidebar": "^5.24.1", "@mongodb-js/compass-workspaces": "^0.5.1", - "@mongodb-js/compass-logging": "^1.2.14", + "@mongodb-js/connection-storage": "^0.8.1", "@mongodb-js/eslint-config-compass": "^1.0.17", "@mongodb-js/mocha-config-compass": "^1.3.7", "@mongodb-js/prettier-config-compass": "^1.0.1", @@ -93,8 +94,8 @@ "@types/sinon-chai": "^3.2.5", "buffer": "^6.0.3", "chai": "^4.3.6", - "debug": "^4.2.0", "compass-preferences-model": "^2.18.1", + "debug": "^4.2.0", "depcheck": "^1.4.1", "eslint": "^7.25.0", "events": "^3.3.0", @@ -102,6 +103,7 @@ "mocha": "^10.2.0", "mongodb-connection-string-url": "^2.6.0", "mongodb-data-service": "^22.18.1", + "mongodb-log-writer": "^1.3.0", "nyc": "^15.1.0", "path-browserify": "^1.0.1", "prettier": "^2.7.1", @@ -110,7 +112,6 @@ "sinon": "^17.0.1", "util": "^0.12.5", "vm-browserify": "^1.1.2", - "whatwg-url": "^13.0.0", - "mongodb-log-writer": "^1.3.0" + "whatwg-url": "^13.0.0" } } diff --git a/packages/compass-web/sandbox/index.tsx b/packages/compass-web/sandbox/index.tsx index 8be942eb440..1d06756b7c3 100644 --- a/packages/compass-web/sandbox/index.tsx +++ b/packages/compass-web/sandbox/index.tsx @@ -27,6 +27,7 @@ import { LoggerAndTelemetryProvider } from '@mongodb-js/compass-logging/provider import { mongoLogId } from '@mongodb-js/compass-logging'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging'; import type { MongoLogWriter } from 'mongodb-log-writer'; +import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer'; const sandboxContainerStyles = css({ width: '100%', @@ -84,7 +85,7 @@ const historyItemButtonStyles = css({ resetGlobalCSS(); -function getHistory(): string[] { +function getHistory(): ConnectionInfo[] { try { const b64Str = localStorage.getItem('CONNECTIONS_HISTORY'); if (!b64Str) { @@ -139,11 +140,16 @@ const App = () => { } return { type: 'Databases' }; }); - const [connectionsHistory, setConnectionsHistory] = useState(() => { + const [connectionsHistory, setConnectionsHistory] = useState< + ConnectionInfo[] + >(() => { return getHistory(); }); const [focused, setFocused] = useState(false); const [connectionString, setConnectionString] = useState(''); + const [connectionInfo, setConnectionInfo] = useState( + null + ); const [openCompassWeb, setOpenCompassWeb] = useState(false); const [ connectionStringValidationResult, @@ -165,10 +171,22 @@ const App = () => { const onConnectClick = useCallback(() => { setOpenCompassWeb(true); setConnectionsHistory((history) => { - if (history.includes(connectionString)) { + const info = history.find( + (info) => info.connectionOptions.connectionString === connectionString + ); + if (info) { + setConnectionInfo(info); return history; } - history.unshift(connectionString); + + const newInfo: ConnectionInfo = { + id: Math.random().toString(36).slice(2), + connectionOptions: { + connectionString, + }, + }; + setConnectionInfo(newInfo); + history.unshift(newInfo); if (history.length > 10) { history.pop(); } @@ -211,13 +229,13 @@ const App = () => { }, }); - if (openCompassWeb) { + if (openCompassWeb && connectionInfo) { return ( { let newPath: string; @@ -290,11 +308,11 @@ const App = () => {
    - {connectionsHistory.map((connectionString) => { + {connectionsHistory.map((connectionInfo) => { return ( @@ -302,10 +320,14 @@ const App = () => { className={historyItemButtonStyles} type="button" onClick={() => { - onChangeConnectionString(connectionString); + onChangeConnectionString( + connectionInfo.connectionOptions.connectionString + ); }} > - {redactConnectionString(connectionString)} + {redactConnectionString( + connectionInfo.connectionOptions.connectionString + )} ); diff --git a/packages/compass-web/src/index.spec.tsx b/packages/compass-web/src/index.spec.tsx index b9ec86b135d..a681927c57e 100644 --- a/packages/compass-web/src/index.spec.tsx +++ b/packages/compass-web/src/index.spec.tsx @@ -63,7 +63,10 @@ describe('CompassWeb', function () { ) { return render( {}} {...props} // @ts-expect-error see component props description diff --git a/packages/compass-web/src/index.tsx b/packages/compass-web/src/index.tsx index 0818b018a15..9a2a2375f4c 100644 --- a/packages/compass-web/src/index.tsx +++ b/packages/compass-web/src/index.tsx @@ -55,6 +55,8 @@ import { import { AtlasAiServiceProvider } from '@mongodb-js/compass-generative-ai/provider'; import type { AtlasUserInfo } from '@mongodb-js/atlas-service/renderer'; import { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; +import { ConnectionInfoProvider } from '@mongodb-js/connection-storage/provider'; +import type { ConnectionInfo } from '@mongodb-js/connection-storage/renderer'; class CloudAtlasAuthService extends AtlasAuthService { signIn() { @@ -88,15 +90,17 @@ const WithAtlasProviders: React.FC = ({ children }) => { ); }; -type CompassWebProps = { - darkMode?: boolean; - connectionString: string; - initialPreferences?: Partial; -} & Pick< +type CompassWorkspaceProps = Pick< React.ComponentProps, 'initialWorkspaceTabs' | 'onActiveWorkspaceTabChange' >; +type CompassWebProps = { + darkMode?: boolean; + connectionInfo: ConnectionInfo; + initialPreferences?: Partial; +} & CompassWorkspaceProps; + const loadingContainerStyles = css({ width: '100%', height: '100%', @@ -129,6 +133,66 @@ function LoadingScreen({ connectionString }: { connectionString: string }) { ); } +function CompassWorkspace({ + initialWorkspaceTabs, + onActiveWorkspaceTabChange, +}: CompassWorkspaceProps) { + return ( + + +
    + { + return ( + + ); + }} + renderModals={() => { + return ( + <> + + + + + + ); + }} + > +
    +
    +
    + ); +} + const DEFAULT_TAB = { type: 'Databases' } as const; const connectedContainerStyles = css({ @@ -139,7 +203,7 @@ const connectedContainerStyles = css({ const CompassWeb = ({ darkMode, - connectionString, + connectionInfo, initialWorkspaceTabs, onActiveWorkspaceTabChange, initialPreferences, @@ -174,7 +238,7 @@ const CompassWeb = ({ const connectFn = (__TEST_MONGODB_DATA_SERVICE_CONNECT_FN as typeof connect) ?? connect; ds = await connectFn({ - connectionOptions: { connectionString }, + connectionOptions: connectionInfo.connectionOptions, signal: controller.signal, }); dataService.current = ds; @@ -186,7 +250,7 @@ const CompassWeb = ({ return () => { void ds?.disconnect(); }; - }, [connectionString, __TEST_MONGODB_DATA_SERVICE_CONNECT_FN]); + }, [connectionInfo, __TEST_MONGODB_DATA_SERVICE_CONNECT_FN]); // Re-throw connection error so that parent component can render an // appropriate error screen with an error boundary (only relevant while we are @@ -198,7 +262,9 @@ const CompassWeb = ({ if (!connected || !dataService.current) { return ( - + ); } @@ -208,64 +274,16 @@ const CompassWeb = ({ - - - - -
    - { - return ( - - ); - }} - renderModals={() => { - return ( - <> - - - - - - ); - }} - > -
    -
    -
    -
    -
    + + + + + + +
    diff --git a/packages/connection-info/src/connection-info.ts b/packages/connection-info/src/connection-info.ts index 5d5042d4d6f..76c9d879ad0 100644 --- a/packages/connection-info/src/connection-info.ts +++ b/packages/connection-info/src/connection-info.ts @@ -1,5 +1,19 @@ import type { ConnectionOptions } from 'mongodb-data-service'; +interface AtlasClusterMetadata { + orgId: string; + /** + * Project ID that uniquely identifies an Atlas project. Legacy name is "groupId" + * as projects were previously identified as "groups". + * https://www.mongodb.com/docs/atlas/api/atlas-admin-api-ref/#project-id + */ + projectId: string; + clusterId: string; + clusterName: string; + clusterType: string; + regionalBaseUrl: string; +} + export interface ConnectionInfo { /** * Unique ID of the connection. @@ -25,6 +39,11 @@ export interface ConnectionInfo { * The options used to connect */ connectionOptions: ConnectionOptions; + + /** + * The metdata for the Atlas cluster + */ + atlasMetadata?: AtlasClusterMetadata; } export interface ConnectionFavoriteOptions { diff --git a/packages/connection-storage/src/provider.ts b/packages/connection-storage/src/provider.ts index 906531c7297..55c1dfd3cd1 100644 --- a/packages/connection-storage/src/provider.ts +++ b/packages/connection-storage/src/provider.ts @@ -1,6 +1,6 @@ import { createContext, createElement, useMemo, useContext } from 'react'; import { ConnectionRepository } from './connection-repository'; -import type { ConnectionStorage } from './renderer'; +import type { ConnectionInfo, ConnectionStorage } from './renderer'; import { createServiceLocator, createServiceProvider, @@ -59,3 +59,19 @@ export const connectionRepositoryLocator = createServiceLocator( useConnectionRepositoryContext, 'connectionRepositoryLocator' ); + +const ConnectionInfoContext = createContext(null); +export function useConnectionInfoContext() { + const connectionInfo = useContext(ConnectionInfoContext); + if (!connectionInfo) { + throw new Error( + 'Could not find the current ConnectionInfo. Did you forget to setup the ConnectionInfoContext?' + ); + } + return connectionInfo; +} +export const ConnectionInfoProvider = ConnectionInfoContext.Provider; +export const connectionInfoLocator = createServiceLocator( + useConnectionInfoContext, + 'connectionInfoLocator' +);