From acec948a99f18565cab0625f439663fb2a75e54c Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 8 Apr 2024 15:50:26 +0200 Subject: [PATCH 01/13] chore: changes in compass-workspaces to start using MongoDBInstancesManager --- .../src/components/workspaces-provider.tsx | 1 + .../src/components/workspaces.tsx | 61 +++++++++++++------ packages/compass-workspaces/src/index.ts | 61 ++++++++++++------- packages/compass-workspaces/src/provider.tsx | 42 ++++++++++--- .../src/stores/workspaces.ts | 36 +++++++++-- packages/compass-workspaces/src/types.ts | 9 +++ .../compass/src/app/components/workspace.tsx | 7 +++ 7 files changed, 163 insertions(+), 54 deletions(-) diff --git a/packages/compass-workspaces/src/components/workspaces-provider.tsx b/packages/compass-workspaces/src/components/workspaces-provider.tsx index 29c4b0fcf3f..c093771f209 100644 --- a/packages/compass-workspaces/src/components/workspaces-provider.tsx +++ b/packages/compass-workspaces/src/components/workspaces-provider.tsx @@ -2,6 +2,7 @@ import React, { useContext, useRef } from 'react'; import type { AnyWorkspace, WorkspaceComponent } from '../'; export type AnyWorkspaceComponent = + | WorkspaceComponent<'Welcome'> | WorkspaceComponent<'My Queries'> | WorkspaceComponent<'Performance'> | WorkspaceComponent<'Databases'> diff --git a/packages/compass-workspaces/src/components/workspaces.tsx b/packages/compass-workspaces/src/components/workspaces.tsx index 4b64acce227..25c17e8a58d 100644 --- a/packages/compass-workspaces/src/components/workspaces.tsx +++ b/packages/compass-workspaces/src/components/workspaces.tsx @@ -31,6 +31,7 @@ import { useLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import { connect } from '../stores/context'; import { WorkspaceTabStateProvider } from './workspace-tab-state-provider'; import { NamespaceProvider } from '@mongodb-js/compass-app-stores/provider'; +import { ConnectionInfoProvider } from '@mongodb-js/compass-connections/provider'; const emptyWorkspaceStyles = css({ margin: '0 auto', @@ -101,6 +102,13 @@ const CompassWorkspaces: React.FunctionComponent = ({ const tabDescriptions = useMemo(() => { return tabs.map((tab) => { switch (tab.type) { + case 'Welcome': + return { + id: tab.id, + title: tab.type, + // TODO: Change this to correct glyph + iconGlyph: 'Home', + } as const; case 'My Queries': return { id: tab.id, @@ -164,23 +172,38 @@ const CompassWorkspaces: React.FunctionComponent = ({ const activeWorkspaceElement = useMemo(() => { switch (activeTab?.type) { - case 'My Queries': + case 'Welcome': + case 'My Queries': { + const Component = getWorkspacePluginByName(activeTab.type); + return ; + } case 'Performance': case 'Databases': { const Component = getWorkspacePluginByName(activeTab.type); - return ; + return ( + + + + ); } case 'Collections': { const Component = getWorkspacePluginByName(activeTab.type); return ( - { - onNamespaceNotFound(activeTab, ns); - }} - > - - + + { + onNamespaceNotFound(activeTab, ns); + }} + > + + + ); } case 'Collection': { @@ -188,14 +211,16 @@ const CompassWorkspaces: React.FunctionComponent = ({ // eslint-disable-next-line @typescript-eslint/no-unused-vars const { id, type, ...collectionMetadata } = activeTab; return ( - { - onNamespaceNotFound(activeTab, ns); - }} - > - ; - + + { + onNamespaceNotFound(activeTab, ns); + }} + > + ; + + ); } default: diff --git a/packages/compass-workspaces/src/index.ts b/packages/compass-workspaces/src/index.ts index 2eb7f72dbb0..b72ce77edc4 100644 --- a/packages/compass-workspaces/src/index.ts +++ b/packages/compass-workspaces/src/index.ts @@ -15,22 +15,26 @@ import Workspaces from './components'; import { applyMiddleware, createStore } from 'redux'; import thunk from 'redux-thunk'; import type { MongoDBInstance } from '@mongodb-js/compass-app-stores/provider'; -import { mongoDBInstanceLocator } from '@mongodb-js/compass-app-stores/provider'; +import { mongoDBInstancesManagerLocator } from '@mongodb-js/compass-app-stores/provider'; import type Collection from 'mongodb-collection-model'; import type Database from 'mongodb-database-model'; import { - dataServiceLocator, - type DataService, - type DataServiceLocator, + connectionsManagerLocator, + type ConnectionsManager, } from '@mongodb-js/compass-connections/provider'; import { WorkspacesStoreContext } from './stores/context'; import { createLoggerAndTelemetryLocator } from '@mongodb-js/compass-logging/provider'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; +import { + type MongoDBInstancesManager, + MongoDBInstancesManagerEvents, +} from '@mongodb-js/compass-app-stores/provider'; +import { type ConnectionInfo } from '@mongodb-js/connection-info'; export type WorkspacesServices = { globalAppRegistry: AppRegistry; - instance: MongoDBInstance; - dataService: DataService; + instancesManager: MongoDBInstancesManager; + connectionsManager: ConnectionsManager; logger: LoggerAndTelemetry; }; @@ -62,30 +66,44 @@ export function activateWorkspacePlugin( { initialWorkspaceTabs, }: { initialWorkspaceTabs?: OpenWorkspaceOptions[] | null }, - { globalAppRegistry, instance, dataService, logger }: WorkspacesServices, + { + globalAppRegistry, + instancesManager, + connectionsManager, + logger, + }: WorkspacesServices, { on, cleanup, addCleanup }: ActivateHelpers ) { const store = configureStore(initialWorkspaceTabs, { globalAppRegistry, - instance, - dataService, + instancesManager, + connectionsManager, logger, }); addCleanup(cleanupLocalAppRegistries); - on(instance, 'change:collections._id', (collection: Collection) => { - const { _id: from } = collection.previousAttributes(); - store.dispatch(collectionRenamed(from, collection.ns)); - }); + on( + instancesManager, + MongoDBInstancesManagerEvents.InstanceCreated, + function ( + connectionInfoId: ConnectionInfo['id'], + instance: MongoDBInstance + ) { + on(instance, 'change:collections._id', (collection: Collection) => { + const { _id: from } = collection.previousAttributes(); + store.dispatch(collectionRenamed(from, collection.ns)); + }); - on(instance, 'remove:collections', (collection: Collection) => { - store.dispatch(collectionRemoved(collection.ns)); - }); + on(instance, 'remove:collections', (collection: Collection) => { + store.dispatch(collectionRemoved(collection.ns)); + }); - on(instance, 'remove:databases', (database: Database) => { - store.dispatch(databaseRemoved(database.name)); - }); + on(instance, 'remove:databases', (database: Database) => { + store.dispatch(databaseRemoved(database.name)); + }); + } + ); on(globalAppRegistry, 'menu-share-schema-json', () => { const activeTab = getActiveTab(store.getState()); @@ -129,8 +147,8 @@ const WorkspacesPlugin = registerHadronPlugin( activate: activateWorkspacePlugin, }, { - instance: mongoDBInstanceLocator, - dataService: dataServiceLocator as DataServiceLocator, + instancesManager: mongoDBInstancesManagerLocator, + connectionsManager: connectionsManagerLocator, logger: createLoggerAndTelemetryLocator('COMPASS-WORKSPACES-UI'), } ); @@ -139,6 +157,7 @@ export default WorkspacesPlugin; export { WorkspacesProvider } from './components/workspaces-provider'; export type { OpenWorkspaceOptions, WorkspaceTab }; export type { + WelcomeWorkspace, MyQueriesWorkspace, ServerStatsWorkspace, DatabasesWorkspace, diff --git a/packages/compass-workspaces/src/provider.tsx b/packages/compass-workspaces/src/provider.tsx index de5dc2c9934..8332d55af68 100644 --- a/packages/compass-workspaces/src/provider.tsx +++ b/packages/compass-workspaces/src/provider.tsx @@ -42,18 +42,27 @@ export type WorkspacesService = { /** * Open "Databases" workspace showing list of all databases in the cluster */ - openDatabasesWorkspace(this: void, tabOptions?: TabOptions): void; + openDatabasesWorkspace( + this: void, + connectionInfoId: string, + tabOptions?: TabOptions + ): void; /** * Open "Performance" workspace showing charts of various cluster performance * metrics */ - openPerformanceWorkspace(this: void, tabOptions?: TabOptions): void; + openPerformanceWorkspace( + this: void, + connectionInfoId: string, + tabOptions?: TabOptions + ): void; /** * Open "Collections" workspace showing list of collections for a certain * database namespace */ openCollectionsWorkspace( this: void, + connectionInfoId: string, namespace: string, tabOptions?: TabOptions ): void; @@ -63,6 +72,7 @@ export type WorkspacesService = { */ openCollectionWorkspace( this: void, + connectionInfoId: string, namespace: string, options?: TabOptions & Omit< @@ -84,6 +94,7 @@ export type WorkspacesService = { */ openEditViewWorkspace( this: void, + connectionInfoId: string, viewNamespace: string, options: { sourceName: string; sourcePipeline: unknown[] } & TabOptions ): void; @@ -145,27 +156,37 @@ export const WorkspacesServiceProvider: React.FunctionComponent<{ openWorkspaceAction({ type: 'My Queries' }, tabOptions) ); }, - openDatabasesWorkspace: (tabOptions) => { + openDatabasesWorkspace: (connectionInfoId, tabOptions) => { return store.dispatch( - openWorkspaceAction({ type: 'Databases' }, tabOptions) + openWorkspaceAction( + { type: 'Databases', connectionInfoId }, + tabOptions + ) ); }, - openPerformanceWorkspace: (tabOptions) => { + openPerformanceWorkspace: (connectionInfoId, tabOptions) => { return store.dispatch( - openWorkspaceAction({ type: 'Performance' }, tabOptions) + openWorkspaceAction( + { type: 'Performance', connectionInfoId }, + tabOptions + ) ); }, - openCollectionsWorkspace: (namespace, tabOptions) => { + openCollectionsWorkspace: (connectionInfoId, namespace, tabOptions) => { return store.dispatch( - openWorkspaceAction({ type: 'Collections', namespace }, tabOptions) + openWorkspaceAction( + { type: 'Collections', connectionInfoId, namespace }, + tabOptions + ) ); }, - openCollectionWorkspace: (namespace, options) => { + openCollectionWorkspace: (connectionInfoId, namespace, options) => { const { newTab, ...collectionOptions } = options ?? {}; return store.dispatch( openWorkspaceAction( { type: 'Collection', + connectionInfoId, namespace, ...collectionOptions, }, @@ -176,12 +197,13 @@ export const WorkspacesServiceProvider: React.FunctionComponent<{ openCollectionWorkspaceSubtab(tabId, subtab) { store.dispatch(collectionSubtabSelected(tabId, subtab)); }, - openEditViewWorkspace: (viewNamespace, options) => { + openEditViewWorkspace: (connectionInfoId, viewNamespace, options) => { const { newTab, sourceName, sourcePipeline } = options ?? {}; return store.dispatch( openWorkspaceAction( { type: 'Collection', + connectionInfoId, namespace: sourceName, initialPipeline: sourcePipeline, editViewName: viewNamespace, diff --git a/packages/compass-workspaces/src/stores/workspaces.ts b/packages/compass-workspaces/src/stores/workspaces.ts index c0bb9207416..3067b548039 100644 --- a/packages/compass-workspaces/src/stores/workspaces.ts +++ b/packages/compass-workspaces/src/stores/workspaces.ts @@ -4,6 +4,7 @@ import { ObjectId } from 'bson'; import AppRegistry from 'hadron-app-registry'; import toNS from 'mongodb-ns'; import type { + WelcomeWorkspace, CollectionWorkspace, CollectionsWorkspace, DatabasesWorkspace, @@ -71,6 +72,7 @@ function isAction( } type WorkspaceTabProps = + | Omit | Omit | Omit | Omit @@ -467,11 +469,12 @@ export const getActiveTab = (state: WorkspacesState): WorkspaceTab | null => { }; export type OpenWorkspaceOptions = + | Pick, 'type'> | Pick, 'type'> - | Pick, 'type'> - | Pick, 'type'> - | Pick, 'type' | 'namespace'> - | (Pick, 'type' | 'namespace'> & + | Pick, 'type' | 'connectionInfoId'> + | Pick, 'type' | 'connectionInfoId'> + | Pick, 'type' | 'connectionInfoId' | 'namespace'> + | (Pick, 'type' | 'connectionInfoId' | 'namespace'> & Partial< Pick< Workspace<'Collection'>, @@ -514,7 +517,11 @@ export const openWorkspace = ( void, OpenWorkspaceAction | FetchCollectionInfoAction > => { - return (dispatch, getState, { instance, dataService, logger }) => { + return ( + dispatch, + getState, + { instancesManager, connectionsManager, logger } + ) => { const oldTabs = getState().tabs; if (workspaceOptions.type === 'Collection') { if (!getState().collectionInfo[workspaceOptions.namespace]) { @@ -522,6 +529,24 @@ export const openWorkspace = ( void (async () => { const { database, collection } = toNS(workspaceOptions.namespace); try { + const dataService = connectionsManager.getDataServiceForConnection( + workspaceOptions.connectionInfoId + ); + if (!dataService) { + throw new Error( + `DataService not available for connectionInfoId=${workspaceOptions.connectionInfoId}` + ); + } + + const instance = instancesManager.getMongoDBInstanceForConnection( + workspaceOptions.connectionInfoId + ); + if (!instance) { + throw new Error( + `MongoDBInstance not available for connectionInfoId=${workspaceOptions.connectionInfoId}` + ); + } + const coll = await instance.getNamespace({ dataService, database, @@ -609,6 +634,7 @@ export const openTabFromCurrent = ( return { type: WorkspacesActions.OpenTabFromCurrentActive, defaultTab: defaultTab ?? { type: 'My Queries' }, + // defaultTab: defaultTab ?? { type: 'Welcome' }, }; }; diff --git a/packages/compass-workspaces/src/types.ts b/packages/compass-workspaces/src/types.ts index 9191a1b29b8..9a24aee3be0 100644 --- a/packages/compass-workspaces/src/types.ts +++ b/packages/compass-workspaces/src/types.ts @@ -5,20 +5,27 @@ export type CollectionSubtab = | 'Indexes' | 'Validation'; +export type WelcomeWorkspace = { + type: 'Welcome'; +}; + export type MyQueriesWorkspace = { type: 'My Queries'; }; export type ServerStatsWorkspace = { type: 'Performance'; + connectionInfoId: string; }; export type DatabasesWorkspace = { type: 'Databases'; + connectionInfoId: string; }; export type CollectionsWorkspace = { type: 'Collections'; + connectionInfoId: string; namespace: string; }; @@ -29,6 +36,7 @@ export type CollectionWorkspace = { // 2. to avoid unnecessary changes in the types definition within those plugins. tabId: string; type: 'Collection'; + connectionInfoId: string; namespace: string; subTab: CollectionSubtab; initialQuery?: unknown; @@ -39,6 +47,7 @@ export type CollectionWorkspace = { }; export type AnyWorkspace = + | WelcomeWorkspace | MyQueriesWorkspace | ServerStatsWorkspace | DatabasesWorkspace diff --git a/packages/compass/src/app/components/workspace.tsx b/packages/compass/src/app/components/workspace.tsx index a2e264c30f3..fe85a72b8ed 100644 --- a/packages/compass/src/app/components/workspace.tsx +++ b/packages/compass/src/app/components/workspace.tsx @@ -62,6 +62,12 @@ export default function Workspace({
Welcome
; + }, + }, MyQueriesWorkspace, PerformanceWorkspace, DatabasesWorkspaceTab, @@ -86,6 +92,7 @@ export default function Workspace({ ]} > { From c40996b9f903b0100696947a8a833e1df7b85189 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Fri, 19 Apr 2024 18:35:00 +0200 Subject: [PATCH 02/13] chore: render WorkspacePlugin w/o ConnectionInfo Changes: - modifed WorkspacePlugin to not depend on MongoDBInstance and DataService anymore - made connectionId a tab state - WorkspaceService now asks connectionId in exposed methods - uses ConnectionInfoProvider in: - WorkspacesPlugin to wrap active workspace element - SidebarPlugin to wrap single connection sidebar - compass/workspaces.tsx to render global modals wrapped with ConnectionInfoProvider - modified places which used useOpenWorkspace hook to also pass the connectionId now --- .../collection-header-actions.spec.tsx | 2 + .../collection-header-actions.tsx | 6 +- .../collection-header.spec.tsx | 14 +++-- .../collection-header/collection-header.tsx | 12 ++-- .../search-indexes-table.tsx | 13 ++++- .../components/legacy/navigation-items.tsx | 4 +- .../legacy/sidebar-databases-navigation.tsx | 8 +-- .../active-connection-navigation.spec.tsx | 4 +- .../active-connection-navigation.tsx | 13 +++-- packages/compass-sidebar/src/index.ts | 3 +- packages/compass-sidebar/src/plugin.tsx | 31 +++++----- .../compass-sidebar/src/stores/store.spec.ts | 2 - packages/compass-sidebar/src/stores/store.ts | 6 +- .../src/components/index.tsx | 13 ++++- .../src/components/workspaces.tsx | 49 ++++++++++------ .../compass-workspaces/src/index.spec.tsx | 34 ++++++++--- packages/compass-workspaces/src/index.ts | 2 +- packages/compass-workspaces/src/provider.tsx | 38 ++++++------- .../src/stores/workspaces.spec.ts | 56 +++++++++++++++++-- .../src/stores/workspaces.ts | 21 +++---- packages/compass-workspaces/src/types.ts | 10 ++-- packages/compass/src/app/components/home.tsx | 22 ++------ .../compass/src/app/components/workspace.tsx | 39 ++++++++----- .../src/components/collections.tsx | 6 +- .../src/components/databases.tsx | 6 +- packages/databases-collections/src/index.ts | 2 + .../src/modules/create-namespace.ts | 14 ++++- .../rename-collection.spec.ts | 4 +- .../src/stores/create-namespace.spec.tsx | 5 +- .../src/stores/create-namespace.ts | 6 +- 30 files changed, 284 insertions(+), 161 deletions(-) diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx index 25fcbfdc61f..b5b6751de98 100644 --- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx +++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.spec.tsx @@ -83,6 +83,7 @@ describe('CollectionHeaderActions [Component]', function () { ); button.click(); expect(openEditViewWorkspaceStub).to.have.been.calledOnceWith( + 'TEST', 'db.coll2', { sourceName: 'db.someSource', @@ -122,6 +123,7 @@ describe('CollectionHeaderActions [Component]', function () { ); button.click(); expect(openCollectionWorkspaceStub).to.have.been.calledOnceWith( + 'TEST', 'db.editing' ); }); diff --git a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx index f6ab15efe72..8c03532ced2 100644 --- a/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx +++ b/packages/compass-collection/src/components/collection-header-actions/collection-header-actions.tsx @@ -5,6 +5,7 @@ import { css, spacing, } from '@mongodb-js/compass-components'; +import { useConnectionInfo } from '@mongodb-js/compass-connections/provider'; import { useOpenWorkspace } from '@mongodb-js/compass-workspaces/provider'; import React from 'react'; @@ -32,6 +33,7 @@ const CollectionHeaderActions: React.FunctionComponent< sourceName, sourcePipeline, }: CollectionHeaderActionsProps) => { + const { id: connectionId } = useConnectionInfo(); const { openCollectionWorkspace, openEditViewWorkspace } = useOpenWorkspace(); return (
{ if (sourceName && sourcePipeline) { - openEditViewWorkspace(namespace, { + openEditViewWorkspace(connectionId, namespace, { sourceName, sourcePipeline, }); @@ -61,7 +63,7 @@ const CollectionHeaderActions: React.FunctionComponent< size={ButtonSize.Small} onClick={() => { if (editViewName) { - openCollectionWorkspace(editViewName); + openCollectionWorkspace(connectionId, editViewName); } }} > diff --git a/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx b/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx index d6c9601ab90..cb2d5c53d42 100644 --- a/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx +++ b/packages/compass-collection/src/components/collection-header/collection-header.spec.tsx @@ -247,9 +247,10 @@ describe('CollectionHeader [Component]', function () { expect(openCollectionsWorkspaceStub.called).to.be.false; userEvent.click(item); expect(openCollectionsWorkspaceStub.calledOnce).to.be.true; - expect(openCollectionsWorkspaceStub.firstCall.firstArg).to.deep.equal( - 'db' - ); + expect(openCollectionsWorkspaceStub.firstCall.args).to.deep.equal([ + 'TEST', + 'db', + ]); }); it('for a view, opens source collection', function () { @@ -268,9 +269,10 @@ describe('CollectionHeader [Component]', function () { expect(openCollectionWorkspaceStub.called).to.be.false; userEvent.click(item); expect(openCollectionWorkspaceStub.calledOnce).to.be.true; - expect(openCollectionWorkspaceStub.firstCall.firstArg).to.deep.equal( - 'db.coll2' - ); + expect(openCollectionWorkspaceStub.firstCall.args).to.deep.equal([ + 'TEST', + 'db.coll2', + ]); }); }); }); diff --git a/packages/compass-collection/src/components/collection-header/collection-header.tsx b/packages/compass-collection/src/components/collection-header/collection-header.tsx index ea521cb7f05..27ad7803c03 100644 --- a/packages/compass-collection/src/components/collection-header/collection-header.tsx +++ b/packages/compass-collection/src/components/collection-header/collection-header.tsx @@ -18,6 +18,7 @@ import type { CollectionState } from '../../modules/collection-tab'; import { CollectionBadge } from './badges'; import { useOpenWorkspace } from '@mongodb-js/compass-workspaces/provider'; import { connect } from 'react-redux'; +import { useConnectionInfo } from '@mongodb-js/compass-connections/provider'; const collectionHeaderStyles = css({ padding: spacing[3], @@ -99,31 +100,34 @@ export const CollectionHeader: React.FunctionComponent< const showInsights = usePreference('showInsights'); const { openCollectionWorkspace, openCollectionsWorkspace } = useOpenWorkspace(); + const { id: connectionId } = useConnectionInfo(); const breadcrumbItems = useMemo(() => { return [ // TODO (COMPASS-7684): add connection name { name: toNS(namespace).database, - onClick: () => openCollectionsWorkspace(toNS(namespace).database), + onClick: () => + openCollectionsWorkspace(connectionId, toNS(namespace).database), }, // When viewing a view, show the source namespace first sourceName && { name: toNS(sourceName).collection, - onClick: () => openCollectionWorkspace(sourceName), + onClick: () => openCollectionWorkspace(connectionId, sourceName), }, // Show the current namespace { name: toNS(namespace).collection, - onClick: () => openCollectionWorkspace(namespace), + onClick: () => openCollectionWorkspace(connectionId, namespace), }, // When editing a view, show the view namespace last editViewName && { name: toNS(editViewName).collection, - onClick: () => openCollectionWorkspace(editViewName), + onClick: () => openCollectionWorkspace(connectionId, editViewName), }, ].filter(Boolean) as BreadcrumbItem[]; }, [ + connectionId, namespace, sourceName, editViewName, diff --git a/packages/compass-indexes/src/components/search-indexes-table/search-indexes-table.tsx b/packages/compass-indexes/src/components/search-indexes-table/search-indexes-table.tsx index 3b9ba29ecc1..7ebac5d3a80 100644 --- a/packages/compass-indexes/src/components/search-indexes-table/search-indexes-table.tsx +++ b/packages/compass-indexes/src/components/search-indexes-table/search-indexes-table.tsx @@ -36,6 +36,7 @@ import SearchIndexActions from './search-index-actions'; import { ZeroGraphic } from './zero-graphic'; import type { RootState } from '../../modules'; import BadgeWithIconLink from '../indexes-table/badge-with-icon-link'; +import { useConnectionInfo } from '@mongodb-js/compass-connections/provider'; export const POLLING_INTERVAL = 5000; @@ -284,6 +285,7 @@ export const SearchIndexesTable: React.FunctionComponent< pollingInterval = POLLING_INTERVAL, }) => { const { openCollectionWorkspace } = useOpenWorkspace(); + const { id: connectionId } = useConnectionInfo(); useEffect(() => { const id = setInterval(onPollIndexes, pollingInterval); @@ -323,7 +325,7 @@ export const SearchIndexesTable: React.FunctionComponent< onDropIndex={onDropIndex} onEditIndex={onEditIndex} onRunAggregateIndex={(name) => { - openCollectionWorkspace(namespace, { + openCollectionWorkspace(connectionId, namespace, { newTab: true, ...(isVectorSearchIndex ? { @@ -352,7 +354,14 @@ export const SearchIndexesTable: React.FunctionComponent< ), }; }), - [indexes, namespace, onDropIndex, onEditIndex, openCollectionWorkspace] + [ + connectionId, + indexes, + namespace, + onDropIndex, + onEditIndex, + openCollectionWorkspace, + ] ); if (!isReadyStatus(status)) { diff --git a/packages/compass-sidebar/src/components/legacy/navigation-items.tsx b/packages/compass-sidebar/src/components/legacy/navigation-items.tsx index fc61866264a..2cc8156cf11 100644 --- a/packages/compass-sidebar/src/components/legacy/navigation-items.tsx +++ b/packages/compass-sidebar/src/components/legacy/navigation-items.tsx @@ -334,7 +334,7 @@ export function NavigationItems({ {hasWorkspacePlugin('Performance') && ( onAction={onAction} - onClick={openPerformanceWorkspace} + onClick={() => openPerformanceWorkspace(connectionInfo.id)} glyph="Gauge" label="Performance" isActive={currentLocation === 'Performance'} @@ -344,7 +344,7 @@ export function NavigationItems({ )} onAction={onAction} - onClick={openDatabasesWorkspace} + onClick={() => openDatabasesWorkspace(connectionInfo.id)} glyph="Database" label="Databases" actions={databasesActions} diff --git a/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx b/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx index 8f6243ef305..51a71ce76fb 100644 --- a/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx +++ b/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx @@ -47,13 +47,13 @@ function SidebarDatabasesNavigation({ // TODO: COMPASS-7718 to use connectionId for new tabs switch (action) { case 'select-database': - openCollectionsWorkspace(ns); + openCollectionsWorkspace(connectionId, ns); return; case 'select-collection': - openCollectionWorkspace(ns); + openCollectionWorkspace(connectionId, ns); return; case 'open-in-new-tab': - openCollectionWorkspace(ns, { newTab: true }); + openCollectionWorkspace(connectionId, ns, { newTab: true }); return; case 'modify-view': { const coll = findCollection( @@ -62,7 +62,7 @@ function SidebarDatabasesNavigation({ ); if (coll && coll.sourceName && coll.pipeline) { - openEditViewWorkspace(coll._id, { + openEditViewWorkspace(connectionId, coll._id, { sourceName: coll.sourceName, sourcePipeline: coll.pipeline, newTab: true, diff --git a/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.spec.tsx b/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.spec.tsx index 85a82ab761b..a4dedcebe2e 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.spec.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.spec.tsx @@ -5,12 +5,11 @@ import ActiveConnectionNavigation from './active-connection-navigation'; import { ConnectionsManager, ConnectionsManagerProvider, - TEST_CONNECTION_INFO, + type ConnectionInfo, } from '@mongodb-js/compass-connections/provider'; import { createSidebarStore } from '../../../stores'; import { Provider } from 'react-redux'; import AppRegistry from 'hadron-app-registry'; -import { type ConnectionInfo } from '@mongodb-js/connection-info'; import { createNoopLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import userEvent from '@testing-library/user-event'; import sinon from 'sinon'; @@ -60,7 +59,6 @@ describe('', function () { } as any, connectionsManager, logger: createNoopLoggerAndTelemetry(), - initialConnectionInfo: TEST_CONNECTION_INFO, }, { on() {}, cleanup() {}, addCleanup() {} } as any )); diff --git a/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.tsx b/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.tsx index f6ef148c0f7..b35d4ed1ae8 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/active-connections/active-connection-navigation.tsx @@ -93,7 +93,6 @@ export function ActiveConnectionNavigation({ >([]); const { - // TODO: add connection id as the first parameter openDatabasesWorkspace, openCollectionsWorkspace, openCollectionWorkspace, @@ -143,13 +142,13 @@ export function ActiveConnectionNavigation({ onToggleFavoriteConnection(connectionId); return; case 'select-database': - openCollectionsWorkspace(ns); + openCollectionsWorkspace(connectionId, ns); return; case 'select-collection': - openCollectionWorkspace(ns); + openCollectionWorkspace(connectionId, ns); return; case 'open-in-new-tab': - openCollectionWorkspace(ns, { newTab: true }); + openCollectionWorkspace(connectionId, ns, { newTab: true }); return; case 'modify-view': { const coll = findCollection( @@ -158,7 +157,7 @@ export function ActiveConnectionNavigation({ ?.databases as Database[]) ?? [] ); if (coll && coll.sourceName && coll.pipeline) { - openEditViewWorkspace(coll._id, { + openEditViewWorkspace(connectionId, coll._id, { sourceName: coll.sourceName, sourcePipeline: coll.pipeline, newTab: true, @@ -198,7 +197,9 @@ export function ActiveConnectionNavigation({ connections={connections} activeNamespace={activeWorkspace?.namespace} onNamespaceAction={onNamespaceAction} - onConnectionSelect={() => openDatabasesWorkspace()} + onConnectionSelect={(connectionId) => + openDatabasesWorkspace(connectionId) + } onConnectionExpand={onConnectionToggle} expanded={namedConnections.reduce( (obj, { connectionInfo: { id: connectionId } }) => { diff --git a/packages/compass-sidebar/src/index.ts b/packages/compass-sidebar/src/index.ts index db3c1f2eada..76107c7a22a 100644 --- a/packages/compass-sidebar/src/index.ts +++ b/packages/compass-sidebar/src/index.ts @@ -27,7 +27,7 @@ export const CompassSidebarPlugin = registerHadronPlugin< component: SidebarPlugin, activate( // @eslint-ignore-next-line - { initialConnectionInfo }: SidebarPluginProps, + _, { globalAppRegistry, connectionsManager, @@ -46,7 +46,6 @@ export const CompassSidebarPlugin = registerHadronPlugin< globalAppRegistry, connectionsManager, instancesManager, - initialConnectionInfo: initialConnectionInfo, logger, }, helpers diff --git a/packages/compass-sidebar/src/plugin.tsx b/packages/compass-sidebar/src/plugin.tsx index 6cc9aa0eaff..9e2473bee0e 100644 --- a/packages/compass-sidebar/src/plugin.tsx +++ b/packages/compass-sidebar/src/plugin.tsx @@ -10,6 +10,7 @@ import { useActiveWorkspace } from '@mongodb-js/compass-workspaces/provider'; import Sidebar from './components/legacy/sidebar'; import { usePreference } from 'compass-preferences-model/provider'; import MultipleConnectionSidebar from './components/multiple-connections/sidebar'; +import { ConnectionInfoProvider } from '@mongodb-js/compass-connections/provider'; const errorBoundaryStyles = css({ width: defaultSidebarWidth, @@ -17,14 +18,14 @@ const errorBoundaryStyles = css({ export interface SidebarPluginProps { showConnectionInfo?: boolean; - initialConnectionInfo?: ConnectionInfo; + singleConnectionConnectionInfo?: ConnectionInfo; } const SidebarPlugin: React.FunctionComponent = ({ showConnectionInfo, // TODO(COMPASS-7397): the need for passing this directly to sidebar should go - // away with refactoring compoass-conneciton to a plugin - initialConnectionInfo, + // away with refactoring compass-connection to a plugin + singleConnectionConnectionInfo, }) => { const isMultiConnectionEnabled = usePreference( 'enableNewMultipleConnectionSystem' @@ -37,18 +38,20 @@ const SidebarPlugin: React.FunctionComponent = ({ if (isMultiConnectionEnabled) { sidebar = ; } else { - if (!initialConnectionInfo) { - throw new Error( - 'Could not find a connection info for the single connection sidebar.' - ); - } - sidebar = ( - + + {(connectionInfo) => { + return ( + + ); + }} + ); } diff --git a/packages/compass-sidebar/src/stores/store.spec.ts b/packages/compass-sidebar/src/stores/store.spec.ts index 07a7b104db7..321c4ea2164 100644 --- a/packages/compass-sidebar/src/stores/store.spec.ts +++ b/packages/compass-sidebar/src/stores/store.spec.ts @@ -5,7 +5,6 @@ import { createSidebarStore } from '.'; import { createInstance } from '../../test/helpers'; import { createNoopLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import type { DataService } from '@mongodb-js/compass-connections/provider'; -import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; import { MongoDBInstancesManagerEvents, type MongoDBInstancesManager, @@ -75,7 +74,6 @@ describe('SidebarStore [Store]', function () { } as any, instancesManager: instancesManager, logger: createNoopLoggerAndTelemetry(), - initialConnectionInfo: TEST_CONNECTION_INFO, }, { on() {}, cleanup() {}, addCleanup() {} } as any )); diff --git a/packages/compass-sidebar/src/stores/store.ts b/packages/compass-sidebar/src/stores/store.ts index 77decc19af7..bad2870fc9b 100644 --- a/packages/compass-sidebar/src/stores/store.ts +++ b/packages/compass-sidebar/src/stores/store.ts @@ -3,10 +3,7 @@ import thunk from 'redux-thunk'; import reducer from '../modules'; import { closeInstance, setupInstance } from '../modules/instance'; import type { ActivateHelpers, AppRegistry } from 'hadron-app-registry'; -import type { - ConnectionInfo, - ConnectionsManager, -} from '@mongodb-js/compass-connections/provider'; +import type { ConnectionsManager } from '@mongodb-js/compass-connections/provider'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import { type MongoDBInstancesManager, @@ -23,7 +20,6 @@ export function createSidebarStore( globalAppRegistry: AppRegistry; connectionsManager: ConnectionsManager; instancesManager: MongoDBInstancesManager; - initialConnectionInfo?: ConnectionInfo; logger: LoggerAndTelemetry; }, { on, cleanup }: ActivateHelpers diff --git a/packages/compass-workspaces/src/components/index.tsx b/packages/compass-workspaces/src/components/index.tsx index 285f8716acf..37b4beb68da 100644 --- a/packages/compass-workspaces/src/components/index.tsx +++ b/packages/compass-workspaces/src/components/index.tsx @@ -10,8 +10,15 @@ import { import Workspaces from './workspaces'; import { connect } from '../stores/context'; import { WorkspacesServiceProvider } from '../provider'; +import type { ConnectionInfo } from '@mongodb-js/compass-connections/provider'; type WorkspacesWithSidebarProps = { + /** + * ConnectionInfo of the connection that Compass is connected to while in + * single connection mode. This is a temporary addition until we change My + * Queries plugin to be not dependent on DataService and MongoDBInstance. + */ + singleConnectionConnectionInfo?: ConnectionInfo; /** * Current active workspace tab */ @@ -87,6 +94,7 @@ const sidebarStyles = css({ const WorkspacesWithSidebar: React.FunctionComponent< WorkspacesWithSidebarProps > = ({ + singleConnectionConnectionInfo, activeTab, activeTabCollectionInfo, openOnEmptyWorkspace, @@ -112,7 +120,10 @@ const WorkspacesWithSidebar: React.FunctionComponent< {renderSidebar && React.createElement(renderSidebar)}
- +
{renderModals && React.createElement(renderModals)} diff --git a/packages/compass-workspaces/src/components/workspaces.tsx b/packages/compass-workspaces/src/components/workspaces.tsx index 25c17e8a58d..095bd632605 100644 --- a/packages/compass-workspaces/src/components/workspaces.tsx +++ b/packages/compass-workspaces/src/components/workspaces.tsx @@ -31,7 +31,10 @@ import { useLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import { connect } from '../stores/context'; import { WorkspaceTabStateProvider } from './workspace-tab-state-provider'; import { NamespaceProvider } from '@mongodb-js/compass-app-stores/provider'; -import { ConnectionInfoProvider } from '@mongodb-js/compass-connections/provider'; +import { + type ConnectionInfo, + ConnectionInfoProvider, +} from '@mongodb-js/compass-connections/provider'; const emptyWorkspaceStyles = css({ margin: '0 auto', @@ -70,6 +73,7 @@ type CompassWorkspacesProps = { activeTab?: WorkspaceTab | null; collectionInfo: Record; openOnEmptyWorkspace?: OpenWorkspaceOptions | null; + singleConnectionConnectionInfo?: ConnectionInfo; onSelectTab(at: number): void; onSelectNextTab(): void; @@ -79,6 +83,7 @@ type CompassWorkspacesProps = { onCloseTab(at: number): void; onNamespaceNotFound( tab: WorkspaceTab, + connectionId: string, fallbackNamespace: string | null ): void; }; @@ -95,6 +100,7 @@ const CompassWorkspaces: React.FunctionComponent = ({ onCreateTab, onCloseTab, onNamespaceNotFound, + singleConnectionConnectionInfo, }) => { const { log, mongoLogId } = useLoggerAndTelemetry('COMPASS-WORKSPACES'); const { getWorkspacePluginByName } = useWorkspacePlugins(); @@ -172,36 +178,40 @@ const CompassWorkspaces: React.FunctionComponent = ({ const activeWorkspaceElement = useMemo(() => { switch (activeTab?.type) { - case 'Welcome': - case 'My Queries': { + case 'Welcome': { const Component = getWorkspacePluginByName(activeTab.type); return ; } + case 'My Queries': { + const Component = getWorkspacePluginByName(activeTab.type); + return ( + + + + ); + } case 'Performance': case 'Databases': { const Component = getWorkspacePluginByName(activeTab.type); return ( - - + + ); } case 'Collections': { const Component = getWorkspacePluginByName(activeTab.type); return ( - + { - onNamespaceNotFound(activeTab, ns); + onNamespaceNotFound(activeTab, activeTab.connectionId, ns); }} > - + ); @@ -209,13 +219,13 @@ const CompassWorkspaces: React.FunctionComponent = ({ case 'Collection': { const Component = getWorkspacePluginByName(activeTab.type); // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { id, type, ...collectionMetadata } = activeTab; + const { id, type, connectionId, ...collectionMetadata } = activeTab; return ( - + { - onNamespaceNotFound(activeTab, ns); + onNamespaceNotFound(activeTab, activeTab.connectionId, ns); }} > ; @@ -226,7 +236,12 @@ const CompassWorkspaces: React.FunctionComponent = ({ default: return null; } - }, [activeTab, getWorkspacePluginByName, onNamespaceNotFound]); + }, [ + singleConnectionConnectionInfo, + activeTab, + getWorkspacePluginByName, + onNamespaceNotFound, + ]); const onCreateNewTab = useCallback(() => { onCreateTab(openOnEmptyWorkspace); diff --git a/packages/compass-workspaces/src/index.spec.tsx b/packages/compass-workspaces/src/index.spec.tsx index b1156721fc1..7b7e4fddedb 100644 --- a/packages/compass-workspaces/src/index.spec.tsx +++ b/packages/compass-workspaces/src/index.spec.tsx @@ -7,6 +7,8 @@ import Sinon from 'sinon'; import AppRegistry from 'hadron-app-registry'; import type { AnyWorkspaceComponent } from './components/workspaces-provider'; import { useOpenWorkspace } from './provider'; +import { TestMongoDBInstanceManager } from '@mongodb-js/compass-app-stores/provider'; +import { ConnectionsManager } from '@mongodb-js/compass-connections/provider'; function mockWorkspace(name: string) { return { @@ -28,12 +30,16 @@ describe('WorkspacesPlugin', function () { return Promise.resolve(null); }, } as any; + const instancesManager = new TestMongoDBInstanceManager(); + const connectionsManager = new ConnectionsManager({ + logger: (() => {}) as any, + }); const dataService = {} as any; const Plugin = WorkspacesPlugin.withMockServices( { globalAppRegistry, - instance, - dataService, + instancesManager, + connectionsManager, }, { disableChildPluginRendering: true } ); @@ -61,18 +67,28 @@ describe('WorkspacesPlugin', function () { ); } + beforeEach(function () { + sandbox + .stub(connectionsManager, 'getDataServiceForConnection') + .returns(dataService); + sandbox + .stub(instancesManager, 'getMongoDBInstanceForConnection') + .returns(instance); + }); + afterEach(function () { (openFns as any) = null; + sandbox.restore(); sandbox.resetHistory(); cleanup(); }); const tabs = [ ['My Queries', () => openFns.openMyQueriesWorkspace()], - ['Databases', () => openFns.openDatabasesWorkspace()], - ['Performance', () => openFns.openPerformanceWorkspace()], - ['db', () => openFns.openCollectionsWorkspace('db')], - ['db > coll', () => openFns.openCollectionWorkspace('db.coll')], + ['Databases', () => openFns.openDatabasesWorkspace('1')], + ['Performance', () => openFns.openPerformanceWorkspace('1')], + ['db', () => openFns.openCollectionsWorkspace('1', 'db')], + ['db > coll', () => openFns.openCollectionWorkspace('1', 'db.coll')], ] as const; for (const suite of tabs) { @@ -89,9 +105,9 @@ describe('WorkspacesPlugin', function () { expect(onTabChangeSpy).to.have.been.calledWith(null); - openFns.openCollectionWorkspace('db.coll1', { newTab: true }); - openFns.openCollectionWorkspace('db.coll2', { newTab: true }); - openFns.openCollectionWorkspace('db.coll3', { newTab: true }); + openFns.openCollectionWorkspace('1', 'db.coll1', { newTab: true }); + openFns.openCollectionWorkspace('1', 'db.coll2', { newTab: true }); + openFns.openCollectionWorkspace('1', 'db.coll3', { newTab: true }); expect(screen.getByRole('tab', { name: 'db > coll3' })).to.have.attribute( 'aria-selected', diff --git a/packages/compass-workspaces/src/index.ts b/packages/compass-workspaces/src/index.ts index b72ce77edc4..6ba5ee70b30 100644 --- a/packages/compass-workspaces/src/index.ts +++ b/packages/compass-workspaces/src/index.ts @@ -21,6 +21,7 @@ import type Database from 'mongodb-database-model'; import { connectionsManagerLocator, type ConnectionsManager, + type ConnectionInfo, } from '@mongodb-js/compass-connections/provider'; import { WorkspacesStoreContext } from './stores/context'; import { createLoggerAndTelemetryLocator } from '@mongodb-js/compass-logging/provider'; @@ -29,7 +30,6 @@ import { type MongoDBInstancesManager, MongoDBInstancesManagerEvents, } from '@mongodb-js/compass-app-stores/provider'; -import { type ConnectionInfo } from '@mongodb-js/connection-info'; export type WorkspacesServices = { globalAppRegistry: AppRegistry; diff --git a/packages/compass-workspaces/src/provider.tsx b/packages/compass-workspaces/src/provider.tsx index 8332d55af68..cffca1142b1 100644 --- a/packages/compass-workspaces/src/provider.tsx +++ b/packages/compass-workspaces/src/provider.tsx @@ -44,7 +44,7 @@ export type WorkspacesService = { */ openDatabasesWorkspace( this: void, - connectionInfoId: string, + connectionId: string, tabOptions?: TabOptions ): void; /** @@ -53,7 +53,7 @@ export type WorkspacesService = { */ openPerformanceWorkspace( this: void, - connectionInfoId: string, + connectionId: string, tabOptions?: TabOptions ): void; /** @@ -62,7 +62,7 @@ export type WorkspacesService = { */ openCollectionsWorkspace( this: void, - connectionInfoId: string, + connectionId: string, namespace: string, tabOptions?: TabOptions ): void; @@ -72,12 +72,12 @@ export type WorkspacesService = { */ openCollectionWorkspace( this: void, - connectionInfoId: string, + connectionId: string, namespace: string, options?: TabOptions & Omit< Extract, - 'type' | 'namespace' | 'editViewName' | 'initialSubtab' + 'type' | 'namespace' | 'editViewName' | 'initialSubtab' | 'connectionId' > ): void; /** @@ -94,7 +94,7 @@ export type WorkspacesService = { */ openEditViewWorkspace( this: void, - connectionInfoId: string, + connectionId: string, viewNamespace: string, options: { sourceName: string; sourcePipeline: unknown[] } & TabOptions ): void; @@ -156,37 +156,31 @@ export const WorkspacesServiceProvider: React.FunctionComponent<{ openWorkspaceAction({ type: 'My Queries' }, tabOptions) ); }, - openDatabasesWorkspace: (connectionInfoId, tabOptions) => { + openDatabasesWorkspace: (connectionId, tabOptions) => { return store.dispatch( - openWorkspaceAction( - { type: 'Databases', connectionInfoId }, - tabOptions - ) + openWorkspaceAction({ type: 'Databases', connectionId }, tabOptions) ); }, - openPerformanceWorkspace: (connectionInfoId, tabOptions) => { + openPerformanceWorkspace: (connectionId, tabOptions) => { return store.dispatch( - openWorkspaceAction( - { type: 'Performance', connectionInfoId }, - tabOptions - ) + openWorkspaceAction({ type: 'Performance', connectionId }, tabOptions) ); }, - openCollectionsWorkspace: (connectionInfoId, namespace, tabOptions) => { + openCollectionsWorkspace: (connectionId, namespace, tabOptions) => { return store.dispatch( openWorkspaceAction( - { type: 'Collections', connectionInfoId, namespace }, + { type: 'Collections', connectionId, namespace }, tabOptions ) ); }, - openCollectionWorkspace: (connectionInfoId, namespace, options) => { + openCollectionWorkspace: (connectionId, namespace, options) => { const { newTab, ...collectionOptions } = options ?? {}; return store.dispatch( openWorkspaceAction( { type: 'Collection', - connectionInfoId, + connectionId, namespace, ...collectionOptions, }, @@ -197,13 +191,13 @@ export const WorkspacesServiceProvider: React.FunctionComponent<{ openCollectionWorkspaceSubtab(tabId, subtab) { store.dispatch(collectionSubtabSelected(tabId, subtab)); }, - openEditViewWorkspace: (connectionInfoId, viewNamespace, options) => { + openEditViewWorkspace: (connectionId, viewNamespace, options) => { const { newTab, sourceName, sourcePipeline } = options ?? {}; return store.dispatch( openWorkspaceAction( { type: 'Collection', - connectionInfoId, + connectionId, namespace: sourceName, initialPipeline: sourcePipeline, editViewName: viewNamespace, diff --git a/packages/compass-workspaces/src/stores/workspaces.spec.ts b/packages/compass-workspaces/src/stores/workspaces.spec.ts index 086cb9b1ced..07e28fb9b7a 100644 --- a/packages/compass-workspaces/src/stores/workspaces.spec.ts +++ b/packages/compass-workspaces/src/stores/workspaces.spec.ts @@ -1,6 +1,9 @@ import { expect } from 'chai'; +import { createSandbox } from 'sinon'; import { activateWorkspacePlugin } from '../index'; import * as workspacesSlice from './workspaces'; +import { TestMongoDBInstanceManager } from '@mongodb-js/compass-app-stores/provider'; +import { ConnectionsManager } from '@mongodb-js/compass-connections/provider'; describe('tabs behavior', function () { const instance = { @@ -13,11 +16,21 @@ describe('tabs behavior', function () { const globalAppRegistry = { on() {}, removeListener() {} } as any; const helpers = { on() {}, cleanup() {}, addCleanup() {} } as any; const dataService = {} as any; + const instancesManager = new TestMongoDBInstanceManager(); + const connectionsManager = new ConnectionsManager({ + logger: (() => {}) as any, + }); + const sandbox = createSandbox(); function configureStore() { return activateWorkspacePlugin( {}, - { globalAppRegistry, instance, dataService, logger: {} as any }, + { + globalAppRegistry, + instancesManager, + connectionsManager, + logger: {} as any, + }, helpers ).store; } @@ -51,6 +64,19 @@ describe('tabs behavior', function () { getActiveTab, } = workspacesSlice; + beforeEach(function () { + sandbox + .stub(connectionsManager, 'getDataServiceForConnection') + .returns(dataService); + sandbox + .stub(instancesManager, 'getMongoDBInstanceForConnection') + .returns(instance); + }); + + afterEach(function () { + sandbox.restore(); + }); + describe('openWorkspace', function () { it('should open a tab and make it active', function () { const store = configureStore(); @@ -78,7 +104,11 @@ describe('tabs behavior', function () { const store = configureStore(); openTabs(store); store.dispatch( - openWorkspace({ type: 'Collection', namespace: 'test.bar' }) + openWorkspace({ + type: 'Collection', + connectionId: '1', + namespace: 'test.bar', + }) ); const state = store.getState(); expect(state).to.have.property('tabs').have.lengthOf(3); @@ -293,7 +323,13 @@ describe('tabs behavior', function () { it('should remove all tabs with matching namespace', function () { const store = configureStore(); openTabs(store); - store.dispatch(openWorkspace({ type: 'Collections', namespace: 'test' })); + store.dispatch( + openWorkspace({ + type: 'Collections', + connectionId: '1', + namespace: 'test', + }) + ); store.dispatch(openWorkspace({ type: 'My Queries' })); const myQueriesTab = workspacesSlice.getActiveTab(store.getState()); store.dispatch(databaseRemoved('test')); @@ -340,7 +376,11 @@ describe('tabs behavior', function () { const store = configureStore(); store.dispatch( - openWorkspace({ type: 'Collection', namespace: 'foo.bar' }) + openWorkspace({ + type: 'Collection', + connectionId: '1', + namespace: 'foo.bar', + }) ); expect(store.getState().tabs).to.have.lengthOf(1); expect(getActiveTab(store.getState())).to.have.property( @@ -353,7 +393,9 @@ describe('tabs behavior', function () { ); // Replace collection tab with collections list one - store.dispatch(openFallbackTab(getActiveTab(store.getState())!, 'foo')); + store.dispatch( + openFallbackTab(getActiveTab(store.getState())!, '1', 'foo') + ); expect(store.getState().tabs).to.have.lengthOf(1); expect(getActiveTab(store.getState())).to.have.property( 'type', @@ -365,7 +407,9 @@ describe('tabs behavior', function () { ); // Replace collections list tab with the databases list - store.dispatch(openFallbackTab(getActiveTab(store.getState())!, null)); + store.dispatch( + openFallbackTab(getActiveTab(store.getState())!, '1', null) + ); expect(store.getState().tabs).to.have.lengthOf(1); expect(getActiveTab(store.getState())).to.have.property( 'type', diff --git a/packages/compass-workspaces/src/stores/workspaces.ts b/packages/compass-workspaces/src/stores/workspaces.ts index 3067b548039..9b784a64660 100644 --- a/packages/compass-workspaces/src/stores/workspaces.ts +++ b/packages/compass-workspaces/src/stores/workspaces.ts @@ -471,10 +471,10 @@ export const getActiveTab = (state: WorkspacesState): WorkspaceTab | null => { export type OpenWorkspaceOptions = | Pick, 'type'> | Pick, 'type'> - | Pick, 'type' | 'connectionInfoId'> - | Pick, 'type' | 'connectionInfoId'> - | Pick, 'type' | 'connectionInfoId' | 'namespace'> - | (Pick, 'type' | 'connectionInfoId' | 'namespace'> & + | Pick, 'type' | 'connectionId'> + | Pick, 'type' | 'connectionId'> + | Pick, 'type' | 'connectionId' | 'namespace'> + | (Pick, 'type' | 'connectionId' | 'namespace'> & Partial< Pick< Workspace<'Collection'>, @@ -530,20 +530,20 @@ export const openWorkspace = ( const { database, collection } = toNS(workspaceOptions.namespace); try { const dataService = connectionsManager.getDataServiceForConnection( - workspaceOptions.connectionInfoId + workspaceOptions.connectionId ); if (!dataService) { throw new Error( - `DataService not available for connectionInfoId=${workspaceOptions.connectionInfoId}` + `DataService not available for connectionId=${workspaceOptions.connectionId}` ); } const instance = instancesManager.getMongoDBInstanceForConnection( - workspaceOptions.connectionInfoId + workspaceOptions.connectionId ); if (!instance) { throw new Error( - `MongoDBInstance not available for connectionInfoId=${workspaceOptions.connectionInfoId}` + `MongoDBInstance not available for connectionId=${workspaceOptions.connectionId}` ); } @@ -634,7 +634,6 @@ export const openTabFromCurrent = ( return { type: WorkspacesActions.OpenTabFromCurrentActive, defaultTab: defaultTab ?? { type: 'My Queries' }, - // defaultTab: defaultTab ?? { type: 'Welcome' }, }; }; @@ -720,6 +719,7 @@ export const collectionSubtabSelected = ( export const openFallbackTab = ( tab: WorkspaceTab, + connectionId: string, fallbackNamespace?: string | null ): WorkspacesThunkAction => { return (dispatch, getState) => { @@ -729,9 +729,10 @@ export const openFallbackTab = ( type: toNS(fallbackNamespace).collection ? 'Collection' : 'Collections', + connectionId, namespace: fallbackNamespace, } - : { type: 'Databases' }; + : { type: 'Databases', connectionId }; const tabIndex = getState().tabs.findIndex((ws) => { return ws.id === tab.id; }); diff --git a/packages/compass-workspaces/src/types.ts b/packages/compass-workspaces/src/types.ts index 9a24aee3be0..bcd7f01f6f2 100644 --- a/packages/compass-workspaces/src/types.ts +++ b/packages/compass-workspaces/src/types.ts @@ -15,17 +15,17 @@ export type MyQueriesWorkspace = { export type ServerStatsWorkspace = { type: 'Performance'; - connectionInfoId: string; + connectionId: string; }; export type DatabasesWorkspace = { type: 'Databases'; - connectionInfoId: string; + connectionId: string; }; export type CollectionsWorkspace = { type: 'Collections'; - connectionInfoId: string; + connectionId: string; namespace: string; }; @@ -36,7 +36,7 @@ export type CollectionWorkspace = { // 2. to avoid unnecessary changes in the types definition within those plugins. tabId: string; type: 'Collection'; - connectionInfoId: string; + connectionId: string; namespace: string; subTab: CollectionSubtab; initialQuery?: unknown; @@ -61,7 +61,7 @@ export type Workspace = Extract< export type WorkspacePluginProps = Omit< Workspace, - 'type' + 'type' | 'connectionId' >; export type WorkspaceComponent = { diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 1ed0ba58986..65d6800bee5 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -25,7 +25,6 @@ import { AppRegistryProvider, useLocalAppRegistry } from 'hadron-app-registry'; import { ConnectionsManagerProvider, ConnectionsManager, - ConnectionInfoProvider, type ConnectionInfo, } from '@mongodb-js/compass-connections/provider'; import type { DataService } from 'mongodb-data-service'; @@ -343,21 +342,12 @@ function Home({ - - {(connectionInfo) => { - return ( - - - - ); - }} - + + + {/* TODO(COMPASS-7397): Hide but keep it in scope if diff --git a/packages/compass/src/app/components/workspace.tsx b/packages/compass/src/app/components/workspace.tsx index fe85a72b8ed..be7819e8e13 100644 --- a/packages/compass/src/app/components/workspace.tsx +++ b/packages/compass/src/app/components/workspace.tsx @@ -35,6 +35,8 @@ import { import { ImportPlugin, ExportPlugin } from '@mongodb-js/compass-import-export'; import ExplainPlanCollectionTabModal from '@mongodb-js/compass-explain-plan'; import ExportToLanguageCollectionTabModal from '@mongodb-js/compass-export-to-language'; +import { ConnectionInfoProvider } from '@mongodb-js/compass-connections/provider'; +import { usePreference } from 'compass-preferences-model/provider'; const verticalSplitStyles = css({ width: '100vw', @@ -50,14 +52,17 @@ const shellContainerStyles = css({ }); export default function Workspace({ - connectionInfo, + singleConnectionConnectionInfo, onActiveWorkspaceTabChange, }: { - connectionInfo: ConnectionInfo | null | undefined; + singleConnectionConnectionInfo?: ConnectionInfo; onActiveWorkspaceTabChange: React.ComponentProps< typeof WorkspacesPlugin >['onActiveWorkspaceTabChange']; }): React.ReactElement { + const multiConnectionsEnabled = usePreference( + 'enableNewMultipleConnectionSystem' + ); return (
{ - return ( - - ); - }} + renderSidebar={() => ( + + )} renderModals={() => { - return ( - <> + return multiConnectionsEnabled ? ( + + ) : ( + - + ); }} >
- + + +
); diff --git a/packages/databases-collections/src/components/collections.tsx b/packages/databases-collections/src/components/collections.tsx index ac32ee2406f..d09211ca425 100644 --- a/packages/databases-collections/src/components/collections.tsx +++ b/packages/databases-collections/src/components/collections.tsx @@ -48,6 +48,7 @@ const Collections: React.FunctionComponent = ({ }) => { const { id: connectionId } = useConnectionInfo(); const { openCollectionWorkspace } = useOpenWorkspace(); + const { id: connectionId } = useConnectionInfo(); useTrackOnChange( 'COMPASS-COLLECTIONS-UI', @@ -74,7 +75,10 @@ const Collections: React.FunctionComponent = ({ } const actions = Object.assign( - { onCollectionClick: openCollectionWorkspace, onRefreshClick }, + { + onCollectionClick: openCollectionWorkspace.bind(undefined, connectionId), + onRefreshClick, + }, isEditable ? { onDeleteCollectionClick, onCreateCollectionClick } : {} ); diff --git a/packages/databases-collections/src/components/databases.tsx b/packages/databases-collections/src/components/databases.tsx index 8f0ef72fe48..44999f7a889 100644 --- a/packages/databases-collections/src/components/databases.tsx +++ b/packages/databases-collections/src/components/databases.tsx @@ -84,6 +84,7 @@ const Databases: React.FunctionComponent = ({ const { id: connectionId } = useConnectionInfo(); const isPreferencesReadOnly = usePreference('readOnly'); const { openCollectionsWorkspace } = useOpenWorkspace(); + const { id: connectionId } = useConnectionInfo(); useTrackOnChange( 'COMPASS-DATABASES-UI', @@ -111,7 +112,10 @@ const Databases: React.FunctionComponent = ({ const editable = isWritable && !isPreferencesReadOnly; const actions = Object.assign( - { onDatabaseClick: openCollectionsWorkspace, onRefreshClick }, + { + onDatabaseClick: openCollectionsWorkspace.bind(undefined, connectionId), + onRefreshClick, + }, editable && !isDataLake ? { onDeleteDatabaseClick, onCreateDatabaseClick } : {} diff --git a/packages/databases-collections/src/index.ts b/packages/databases-collections/src/index.ts index 979990380e9..0a7a2abb64c 100644 --- a/packages/databases-collections/src/index.ts +++ b/packages/databases-collections/src/index.ts @@ -1,6 +1,7 @@ import { registerHadronPlugin } from 'hadron-app-registry'; import { createLoggerAndTelemetryLocator } from '@mongodb-js/compass-logging/provider'; import { + connectionInfoAccessLocator, connectionsManagerLocator, dataServiceLocator, type DataServiceLocator, @@ -49,6 +50,7 @@ export const CreateNamespacePlugin = registerHadronPlugin( >, instance: mongoDBInstanceLocator, workspaces: workspacesServiceLocator, + connectionInfoAccess: connectionInfoAccessLocator, } ); diff --git a/packages/databases-collections/src/modules/create-namespace.ts b/packages/databases-collections/src/modules/create-namespace.ts index 880368e4b07..ce4a66ccd3e 100644 --- a/packages/databases-collections/src/modules/create-namespace.ts +++ b/packages/databases-collections/src/modules/create-namespace.ts @@ -211,13 +211,21 @@ export const createNamespace = ( return async ( dispatch, getState, - { dataService: ds, globalAppRegistry, logger: { track, debug }, workspaces } + { + dataService: ds, + globalAppRegistry, + logger: { track, debug }, + workspaces, + connectionInfoAccess, + } ) => { const { databaseName } = getState(); const kind = databaseName !== null ? 'Collection' : 'Database'; const dbName = databaseName ?? data.database; const collName = data.collection; const namespace = `${dbName}.${collName}`; + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); dispatch(clearError()); @@ -244,7 +252,9 @@ export const createNamespace = ( track(`${kind} Created`, trackEvent); globalAppRegistry.emit('collection-created', namespace); - workspaces.openCollectionWorkspace(namespace, { newTab: true }); + workspaces.openCollectionWorkspace(connectionId, namespace, { + newTab: true, + }); dispatch(reset()); } catch (e) { debug('create collection failed', e); diff --git a/packages/databases-collections/src/modules/rename-collection/rename-collection.spec.ts b/packages/databases-collections/src/modules/rename-collection/rename-collection.spec.ts index 68cf9159239..ac6770cefd9 100644 --- a/packages/databases-collections/src/modules/rename-collection/rename-collection.spec.ts +++ b/packages/databases-collections/src/modules/rename-collection/rename-collection.spec.ts @@ -32,7 +32,7 @@ describe('rename collection module', function () { const extraThunkArgs: RenameCollectionPluginServices = { globalAppRegistry: appRegistry, connectionsManager: connectionsManager as any, - instancesManager: instancesManager as any, + instancesManager: instancesManager, queryStorage: favoriteQueries as any, pipelineStorage: pipelineStorage as any, }; @@ -44,7 +44,7 @@ describe('rename collection module', function () { { globalAppRegistry: appRegistry, connectionsManager: connectionsManager as any, - instancesManager: instancesManager as any, + instancesManager: instancesManager, queryStorage: favoriteQueries as any, pipelineStorage: pipelineStorage as any, } diff --git a/packages/databases-collections/src/stores/create-namespace.spec.tsx b/packages/databases-collections/src/stores/create-namespace.spec.tsx index 3ad668cb6c7..d44bb597ca8 100644 --- a/packages/databases-collections/src/stores/create-namespace.spec.tsx +++ b/packages/databases-collections/src/stores/create-namespace.spec.tsx @@ -96,8 +96,11 @@ describe('CreateNamespacePlugin', function () { {} ); + // Called with 'TEST' as first arg because in our tests the default + // connection info is TEST_CONNECTION_INFO (see connection-info-provider.tsx + // in @mongodb-js/compass-connections) expect( workspaces.openCollectionWorkspace - ).to.have.been.called.calledOnceWith('db.coll2'); + ).to.have.been.called.calledOnceWith('TEST', 'db.coll2'); }); }); diff --git a/packages/databases-collections/src/stores/create-namespace.ts b/packages/databases-collections/src/stores/create-namespace.ts index 85310c3ea41..315f05ff2e7 100644 --- a/packages/databases-collections/src/stores/create-namespace.ts +++ b/packages/databases-collections/src/stores/create-namespace.ts @@ -1,5 +1,8 @@ import type AppRegistry from 'hadron-app-registry'; -import type { DataService } from '@mongodb-js/compass-connections/provider'; +import type { + ConnectionInfoAccess, + DataService, +} from '@mongodb-js/compass-connections/provider'; import type { MongoDBInstance } from 'mongodb-instance-model'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging'; import type { Action, AnyAction } from 'redux'; @@ -25,6 +28,7 @@ export type CreateNamespaceServices = { instance: MongoDBInstance; logger: LoggerAndTelemetry; workspaces: ReturnType; + connectionInfoAccess: ConnectionInfoAccess; }; function configureStore(services: CreateNamespaceServices) { From cf0220d713014e54ae5a49ff5924d0a4fcde61e2 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Fri, 19 Apr 2024 19:36:39 +0200 Subject: [PATCH 03/13] chore: updated plugins plugins that use WorkspaceService now properly pass connectionId using ConnectionInfoAccess to the methods that require it. --- packages/compass-aggregations/src/index.ts | 3 ++ .../src/modules/create-view/index.ts | 12 +++++-- .../compass-aggregations/src/modules/index.ts | 2 ++ .../src/modules/out-results-fn.ts | 8 +++-- .../pipeline-builder/stage-editor.spec.ts | 6 ++++ .../src/modules/update-view.spec.ts | 6 ++++ .../src/modules/update-view.ts | 13 ++++++-- .../src/stores/create-view.spec.ts | 6 ++++ .../src/stores/create-view.ts | 11 ++++++- .../compass-aggregations/src/stores/store.ts | 4 +++ packages/compass-import-export/src/index.ts | 2 ++ .../src/modules/import.ts | 7 ++++- .../src/stores/import-store.ts | 11 ++++++- .../src/index.ts | 2 ++ .../src/stores/index.ts | 8 ++++- .../src/stores/open-item.ts | 31 +++++++++++++------ 16 files changed, 112 insertions(+), 20 deletions(-) diff --git a/packages/compass-aggregations/src/index.ts b/packages/compass-aggregations/src/index.ts index 4fdbfe03962..dc6942fe00e 100644 --- a/packages/compass-aggregations/src/index.ts +++ b/packages/compass-aggregations/src/index.ts @@ -6,6 +6,7 @@ import { activateCreateViewPlugin } from './stores/create-view'; import StageEditor from './components/stage-editor'; import CreateViewModal from './components/create-view-modal'; import { + connectionInfoAccessLocator, dataServiceLocator, type DataServiceLocator, } from '@mongodb-js/compass-connections/provider'; @@ -39,6 +40,7 @@ export const CompassAggregationsHadronPlugin = registerHadronPlugin( atlasAuthService: atlasAuthServiceLocator, atlasAiService: atlasAiServiceLocator, pipelineStorage: pipelineStorageLocator, + connectionInfoAccess: connectionInfoAccessLocator, } ); @@ -57,6 +59,7 @@ export const CreateViewPlugin = registerHadronPlugin( dataService: dataServiceLocator as DataServiceLocator<'createView'>, logger: createLoggerAndTelemetryLocator('COMPASS-CREATE-VIEW-UI'), workspaces: workspacesServiceLocator, + connectionInfoAccess: connectionInfoAccessLocator, } ); diff --git a/packages/compass-aggregations/src/modules/create-view/index.ts b/packages/compass-aggregations/src/modules/create-view/index.ts index 62ce5ef12b0..42a1433ea5d 100644 --- a/packages/compass-aggregations/src/modules/create-view/index.ts +++ b/packages/compass-aggregations/src/modules/create-view/index.ts @@ -203,7 +203,13 @@ export const createView = (): CreateViewThunkAction> => { return async ( dispatch, getState, - { globalAppRegistry, dataService, logger: { track }, workspaces } + { + globalAppRegistry, + dataService, + logger: { track }, + workspaces, + connectionInfoAccess, + } ) => { const state = getState(); @@ -214,6 +220,8 @@ export const createView = (): CreateViewThunkAction> => { const options = {}; dispatch(clearError()); + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); try { dispatch(toggleIsRunning(true)); @@ -226,7 +234,7 @@ export const createView = (): CreateViewThunkAction> => { const ns = `${database}.${viewName}`; track('Aggregation Saved As View', { num_stages: viewPipeline.length }); globalAppRegistry.emit('view-created', ns); - workspaces.openCollectionWorkspace(ns, { newTab: true }); + workspaces.openCollectionWorkspace(connectionId, ns, { newTab: true }); dispatch(reset()); } catch (e) { dispatch(stopWithError(e as Error)); diff --git a/packages/compass-aggregations/src/modules/index.ts b/packages/compass-aggregations/src/modules/index.ts index e7d0eacb60e..8504eac2865 100644 --- a/packages/compass-aggregations/src/modules/index.ts +++ b/packages/compass-aggregations/src/modules/index.ts @@ -44,6 +44,7 @@ import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider' import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; import type { MongoDBInstance } from 'mongodb-instance-model'; import type { DataService } from '../modules/data-service'; +import type { ConnectionInfoAccess } from '@mongodb-js/compass-connections/provider'; /** * The main application reducer. * @@ -100,6 +101,7 @@ export type PipelineBuilderExtraArgs = { atlasAiService: AtlasAiService; instance: MongoDBInstance; dataService: DataService; + connectionInfoAccess: ConnectionInfoAccess; }; export type PipelineBuilderThunkDispatch
= diff --git a/packages/compass-aggregations/src/modules/out-results-fn.ts b/packages/compass-aggregations/src/modules/out-results-fn.ts index fe684d04b0d..0d45827da5f 100644 --- a/packages/compass-aggregations/src/modules/out-results-fn.ts +++ b/packages/compass-aggregations/src/modules/out-results-fn.ts @@ -25,12 +25,16 @@ export default function reducer( export const gotoOutResults = ( namespace: string ): PipelineBuilderThunkAction => { - return (_dispatch, getState, { workspaces }) => { + return (_dispatch, getState, { workspaces, connectionInfoAccess }) => { const { outResultsFn } = getState(); + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); if (outResultsFn) { outResultsFn(namespace); } else { - workspaces.openCollectionWorkspace(namespace, { newTab: true }); + workspaces.openCollectionWorkspace(connectionId, namespace, { + newTab: true, + }); } }; }; diff --git a/packages/compass-aggregations/src/modules/pipeline-builder/stage-editor.spec.ts b/packages/compass-aggregations/src/modules/pipeline-builder/stage-editor.spec.ts index 7d669bb034c..4fe69844be5 100644 --- a/packages/compass-aggregations/src/modules/pipeline-builder/stage-editor.spec.ts +++ b/packages/compass-aggregations/src/modules/pipeline-builder/stage-editor.spec.ts @@ -29,6 +29,7 @@ import { getId } from './stage-ids'; import { defaultPreferencesInstance } from 'compass-preferences-model'; import { createNoopLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import AppRegistry from 'hadron-app-registry'; +import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; const MATCH_STAGE: StoreStage = mapBuilderStageToStoreStage( { @@ -123,6 +124,11 @@ function createStore({ preferences, logger: createNoopLoggerAndTelemetry(), dataService: {} as any, + connectionInfoAccess: { + getCurrentConnectionInfo() { + return TEST_CONNECTION_INFO; + }, + }, }) ) ); diff --git a/packages/compass-aggregations/src/modules/update-view.spec.ts b/packages/compass-aggregations/src/modules/update-view.spec.ts index 19e9948f6e5..7706a694d52 100644 --- a/packages/compass-aggregations/src/modules/update-view.spec.ts +++ b/packages/compass-aggregations/src/modules/update-view.spec.ts @@ -3,6 +3,7 @@ import { expect } from 'chai'; import { ERROR_UPDATING_VIEW, updateView } from './update-view'; import { createNoopLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import AppRegistry from 'hadron-app-registry'; +import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; describe('update-view module', function () { const thunkArg = { @@ -20,6 +21,11 @@ describe('update-view module', function () { openCollectionWorkspace() {}, }, logger: createNoopLoggerAndTelemetry(), + connectionInfoAccess: { + getCurrentConnectionInfo() { + return TEST_CONNECTION_INFO; + }, + }, }; describe('#updateView', function () { diff --git a/packages/compass-aggregations/src/modules/update-view.ts b/packages/compass-aggregations/src/modules/update-view.ts index 5869c67faff..52381ac9039 100644 --- a/packages/compass-aggregations/src/modules/update-view.ts +++ b/packages/compass-aggregations/src/modules/update-view.ts @@ -82,7 +82,13 @@ export const updateView = (): PipelineBuilderThunkAction> => { return async ( dispatch, getState, - { pipelineBuilder, workspaces, logger: { track, debug }, globalAppRegistry } + { + pipelineBuilder, + workspaces, + logger: { track, debug }, + globalAppRegistry, + connectionInfoAccess, + } ) => { dispatch(dismissViewError()); @@ -94,6 +100,9 @@ export const updateView = (): PipelineBuilderThunkAction> => { return; } + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); + const viewPipeline = getPipelineFromBuilderState( getState(), pipelineBuilder @@ -111,7 +120,7 @@ export const updateView = (): PipelineBuilderThunkAction> => { }); debug('selecting namespace', viewNamespace); globalAppRegistry.emit('view-edited', viewNamespace); - workspaces.openCollectionWorkspace(viewNamespace); + workspaces.openCollectionWorkspace(connectionId, viewNamespace); } catch (e: any) { debug('Unexpected error updating view', e); dispatch(updateViewErrorOccured(e)); diff --git a/packages/compass-aggregations/src/stores/create-view.spec.ts b/packages/compass-aggregations/src/stores/create-view.spec.ts index ba306eb3fbb..4902aa33a5f 100644 --- a/packages/compass-aggregations/src/stores/create-view.spec.ts +++ b/packages/compass-aggregations/src/stores/create-view.spec.ts @@ -1,6 +1,7 @@ import AppRegistry from 'hadron-app-registry'; import { activateCreateViewPlugin } from './create-view'; import { expect } from 'chai'; +import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; describe('CreateViewStore [Store]', function () { if ( @@ -26,6 +27,11 @@ describe('CreateViewStore [Store]', function () { dataService: ds, logger, workspaces: {} as any, + connectionInfoAccess: { + getCurrentConnectionInfo() { + return TEST_CONNECTION_INFO; + }, + }, } )); }); diff --git a/packages/compass-aggregations/src/stores/create-view.ts b/packages/compass-aggregations/src/stores/create-view.ts index 70b9eb693fb..5b47cc0c843 100644 --- a/packages/compass-aggregations/src/stores/create-view.ts +++ b/packages/compass-aggregations/src/stores/create-view.ts @@ -8,12 +8,14 @@ import type AppRegistry from 'hadron-app-registry'; import type { DataService } from 'mongodb-data-service'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import type { WorkspacesService } from '@mongodb-js/compass-workspaces/provider'; +import type { ConnectionInfoAccess } from '@mongodb-js/compass-connections/provider'; type CreateViewServices = { globalAppRegistry: AppRegistry; dataService: Pick; logger: LoggerAndTelemetry; workspaces: WorkspacesService; + connectionInfoAccess: ConnectionInfoAccess; }; export function configureStore(services: CreateViewServices) { @@ -34,13 +36,20 @@ export type CreateViewThunkAction< export function activateCreateViewPlugin( _: unknown, - { globalAppRegistry, dataService, logger, workspaces }: CreateViewServices + { + globalAppRegistry, + dataService, + logger, + workspaces, + connectionInfoAccess, + }: CreateViewServices ) { const store = configureStore({ globalAppRegistry, dataService, logger, workspaces, + connectionInfoAccess, }); const onOpenCreateView = (meta: { diff --git a/packages/compass-aggregations/src/stores/store.ts b/packages/compass-aggregations/src/stores/store.ts index 6031ee55d6d..be1386ebc29 100644 --- a/packages/compass-aggregations/src/stores/store.ts +++ b/packages/compass-aggregations/src/stores/store.ts @@ -36,6 +36,7 @@ import type { AtlasAiService } from '@mongodb-js/compass-generative-ai/provider' import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; import type { PipelineStorage } from '@mongodb-js/my-queries-storage/provider'; import { maxTimeMSChanged } from '../modules/max-time-ms'; +import type { ConnectionInfoAccess } from '@mongodb-js/compass-connections/provider'; export type ConfigureStoreOptions = CollectionTabPluginMetadata & Partial<{ @@ -72,6 +73,7 @@ export type AggregationsPluginServices = { atlasAuthService: AtlasAuthService; atlasAiService: AtlasAiService; pipelineStorage?: PipelineStorage; + connectionInfoAccess: ConnectionInfoAccess; }; export function activateAggregationsPlugin( @@ -87,6 +89,7 @@ export function activateAggregationsPlugin( atlasAiService, atlasAuthService, pipelineStorage, + connectionInfoAccess, }: AggregationsPluginServices, { on, cleanup, addCleanup }: ActivateHelpers ) { @@ -171,6 +174,7 @@ export function activateAggregationsPlugin( preferences, logger, atlasAiService, + connectionInfoAccess, }) ) ); diff --git a/packages/compass-import-export/src/index.ts b/packages/compass-import-export/src/index.ts index 9ecfb399487..1f431f71572 100644 --- a/packages/compass-import-export/src/index.ts +++ b/packages/compass-import-export/src/index.ts @@ -1,5 +1,6 @@ import { registerHadronPlugin } from 'hadron-app-registry'; import { + connectionInfoAccessLocator, dataServiceLocator, type DataServiceLocator, } from '@mongodb-js/compass-connections/provider'; @@ -27,6 +28,7 @@ export const ImportPlugin = registerHadronPlugin( workspaces: workspacesServiceLocator, preferences: preferencesLocator, logger: createLoggerAndTelemetryLocator('COMPASS-IMPORT-UI'), + connectionInfoAccess: connectionInfoAccessLocator, } ); diff --git a/packages/compass-import-export/src/modules/import.ts b/packages/compass-import-export/src/modules/import.ts index cd59d3c6495..624d69dad15 100644 --- a/packages/compass-import-export/src/modules/import.ts +++ b/packages/compass-import-export/src/modules/import.ts @@ -191,6 +191,7 @@ export const startImport = (): ImportThunkAction> => { globalAppRegistry: appRegistry, workspaces, logger: { log, mongoLogId, track, debug }, + connectionInfoAccess, } ) => { const startTime = Date.now(); @@ -404,7 +405,11 @@ export const startImport = (): ImportThunkAction> => { } else { const onReviewDocumentsClick = appRegistry ? () => { - workspaces.openCollectionWorkspace(ns, { newTab: true }); + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); + workspaces.openCollectionWorkspace(connectionId, ns, { + newTab: true, + }); } : undefined; diff --git a/packages/compass-import-export/src/stores/import-store.ts b/packages/compass-import-export/src/stores/import-store.ts index e510c4b97a2..a054405176c 100644 --- a/packages/compass-import-export/src/stores/import-store.ts +++ b/packages/compass-import-export/src/stores/import-store.ts @@ -7,12 +7,14 @@ import type { DataService } from 'mongodb-data-service'; import { cancelImport, importReducer, openImport } from '../modules/import'; import type { WorkspacesService } from '@mongodb-js/compass-workspaces/provider'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; +import type { ConnectionInfoAccess } from '@mongodb-js/compass-connections/provider'; export type ImportPluginServices = { globalAppRegistry: AppRegistry; dataService: Pick; workspaces: WorkspacesService; logger: LoggerAndTelemetry; + connectionInfoAccess: ConnectionInfoAccess; }; export function configureStore(services: ImportPluginServices) { @@ -37,13 +39,20 @@ export type ImportThunkAction = ThunkAction< export function activatePlugin( _: unknown, - { globalAppRegistry, dataService, workspaces, logger }: ImportPluginServices + { + globalAppRegistry, + dataService, + workspaces, + logger, + connectionInfoAccess, + }: ImportPluginServices ) { const store = configureStore({ globalAppRegistry, dataService, workspaces, logger, + connectionInfoAccess, }); const onOpenImport = ({ diff --git a/packages/compass-saved-aggregations-queries/src/index.ts b/packages/compass-saved-aggregations-queries/src/index.ts index 3ba896ad856..cfc1defff5d 100644 --- a/packages/compass-saved-aggregations-queries/src/index.ts +++ b/packages/compass-saved-aggregations-queries/src/index.ts @@ -1,5 +1,6 @@ import { registerHadronPlugin } from 'hadron-app-registry'; import { + connectionInfoAccessLocator, dataServiceLocator, type DataService, type DataServiceLocator, @@ -26,6 +27,7 @@ const serviceLocators = { workspaces: workspacesServiceLocator, pipelineStorage: pipelineStorageLocator, favoriteQueryStorageAccess: favoriteQueryStorageAccessLocator, + connectionInfoAccess: connectionInfoAccessLocator, }; export const MyQueriesPlugin = registerHadronPlugin< diff --git a/packages/compass-saved-aggregations-queries/src/stores/index.ts b/packages/compass-saved-aggregations-queries/src/stores/index.ts index 67dcbba3c5f..5de08c2e54b 100644 --- a/packages/compass-saved-aggregations-queries/src/stores/index.ts +++ b/packages/compass-saved-aggregations-queries/src/stores/index.ts @@ -6,7 +6,10 @@ import type { ThunkAction } from 'redux-thunk'; import itemsReducer from './aggregations-queries-items'; import openItemReducer from './open-item'; import editItemReducer from './edit-item'; -import type { DataService } from '@mongodb-js/compass-connections/provider'; +import type { + ConnectionInfoAccess, + DataService, +} from '@mongodb-js/compass-connections/provider'; import type { MongoDBInstance } from '@mongodb-js/compass-app-stores/provider'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import type { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider'; @@ -24,6 +27,7 @@ type MyQueriesServices = { pipelineStorage?: PipelineStorage; workspaces: ReturnType; favoriteQueryStorageAccess?: FavoriteQueryStorageAccess; + connectionInfoAccess: ConnectionInfoAccess; }; export function configureStore({ @@ -34,6 +38,7 @@ export function configureStore({ workspaces, pipelineStorage, favoriteQueryStorageAccess, + connectionInfoAccess, }: MyQueriesServices) { return createStore( combineReducers({ @@ -50,6 +55,7 @@ export function configureStore({ pipelineStorage, queryStorage: favoriteQueryStorageAccess?.getStorage(), workspaces, + connectionInfoAccess, }) ) ); diff --git a/packages/compass-saved-aggregations-queries/src/stores/open-item.ts b/packages/compass-saved-aggregations-queries/src/stores/open-item.ts index 9a9614a38bb..ead693e9c6f 100644 --- a/packages/compass-saved-aggregations-queries/src/stores/open-item.ts +++ b/packages/compass-saved-aggregations-queries/src/stores/open-item.ts @@ -217,7 +217,11 @@ const openItem = database: string, collection: string ): SavedQueryAggregationThunkAction => - (_dispatch, _getState, { logger: { track }, workspaces }) => { + ( + _dispatch, + _getState, + { logger: { track }, workspaces, connectionInfoAccess } + ) => { track( item.type === 'aggregation' ? 'Aggregation Opened' @@ -228,15 +232,22 @@ const openItem = } ); - workspaces.openCollectionWorkspace(`${database}.${collection}`, { - initialAggregation: - item.type === 'aggregation' ? item.aggregation : undefined, - initialQuery: - item.type === 'query' || item.type === 'updatemany' - ? item.query - : undefined, - newTab: true, - }); + const { id: connectionId } = + connectionInfoAccess.getCurrentConnectionInfo(); + + workspaces.openCollectionWorkspace( + connectionId, + `${database}.${collection}`, + { + initialAggregation: + item.type === 'aggregation' ? item.aggregation : undefined, + initialQuery: + item.type === 'query' || item.type === 'updatemany' + ? item.query + : undefined, + newTab: true, + } + ); }; export const openSavedItem = From 7125aa0ff534aedaf8dbad94ff9e8dcdfb727b33 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Fri, 19 Apr 2024 19:54:26 +0200 Subject: [PATCH 04/13] chore: rendering home conditionally with multi connections mode --- packages/compass/src/app/components/home.tsx | 84 ++++++++++++-------- 1 file changed, 53 insertions(+), 31 deletions(-) diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 65d6800bee5..716ab624b81 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -55,6 +55,7 @@ import { ImportConnectionsModal, ExportConnectionsModal, } from '@mongodb-js/compass-connection-import-export'; +import { usePreference } from 'compass-preferences-model/provider'; resetGlobalCSS(); @@ -336,6 +337,10 @@ function Home({ openConnectionImportExportModal, } = useConnectionImportExportModalRenderer(); + const multiConnectionsEnabled = usePreference( + 'enableNewMultipleConnectionSystem' + ); + return ( @@ -343,41 +348,58 @@ function Home({ - + + + {/* TODO(COMPASS-7397): Hide but keep it in scope if + connected so that the connection import/export functionality can still + be used through the application menu */} +
+
+ +
+
+ + + + + + +
- {/* TODO(COMPASS-7397): Hide but keep it in scope if - connected so that the connection import/export functionality can still - be used through the application menu */} -
-
- -
-
- - - - - - -
From 1c7e3df31b2fcb44e3c727b6199fb713d3c1d377 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 22 Apr 2024 11:20:49 +0200 Subject: [PATCH 05/13] chore: minor notes and check fixes --- .../compass-aggregations/test/configure-store.ts | 6 ++++++ .../src/components/workspaces.tsx | 6 ++---- packages/compass/src/app/components/home.tsx | 13 +++++++++++++ packages/compass/src/app/components/workspace.tsx | 6 ------ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/compass-aggregations/test/configure-store.ts b/packages/compass-aggregations/test/configure-store.ts index b3a42168cfe..8eb30bb4b2c 100644 --- a/packages/compass-aggregations/test/configure-store.ts +++ b/packages/compass-aggregations/test/configure-store.ts @@ -9,6 +9,7 @@ import type { DataService } from '../src/modules/data-service'; import { ReadOnlyPreferenceAccess } from 'compass-preferences-model/provider'; import { createNoopLoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import { AtlasAuthService } from '@mongodb-js/atlas-service/provider'; +import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; export class MockAtlasAuthService extends AtlasAuthService { isAuthenticated() { @@ -71,6 +72,11 @@ export default function configureStore( logger, atlasAiService: atlasAiService as any, atlasAuthService, + connectionInfoAccess: { + getCurrentConnectionInfo() { + return TEST_CONNECTION_INFO; + }, + }, ...services, }, createActivateHelpers() diff --git a/packages/compass-workspaces/src/components/workspaces.tsx b/packages/compass-workspaces/src/components/workspaces.tsx index 095bd632605..f3d67235b8b 100644 --- a/packages/compass-workspaces/src/components/workspaces.tsx +++ b/packages/compass-workspaces/src/components/workspaces.tsx @@ -178,10 +178,8 @@ const CompassWorkspaces: React.FunctionComponent = ({ const activeWorkspaceElement = useMemo(() => { switch (activeTab?.type) { - case 'Welcome': { - const Component = getWorkspacePluginByName(activeTab.type); - return ; - } + // TODO: Remove the ConnectionInfoProvider when we make My Queries + // workspace work independently of a DataService case 'My Queries': { const Component = getWorkspacePluginByName(activeTab.type); return ( diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 716ab624b81..3b10e2b4122 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -349,13 +349,23 @@ function Home({
@@ -365,6 +375,9 @@ function Home({ be used through the application menu */}
Welcome
; - }, - }, MyQueriesWorkspace, PerformanceWorkspace, DatabasesWorkspaceTab, From 71b4c17f3fc3164bb93ed9b3fee4fe983a2fc2d3 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 22 Apr 2024 11:46:38 +0200 Subject: [PATCH 06/13] chore: added tests for conditional rendering of home --- .../compass/src/app/components/home.spec.tsx | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/packages/compass/src/app/components/home.spec.tsx b/packages/compass/src/app/components/home.spec.tsx index 3aced672982..f94b6eee684 100644 --- a/packages/compass/src/app/components/home.spec.tsx +++ b/packages/compass/src/app/components/home.spec.tsx @@ -14,7 +14,10 @@ import * as hadronIpc from 'hadron-ipc'; import sinon from 'sinon'; import Home from './home'; import type { DataService } from 'mongodb-data-service'; -import { PreferencesProvider } from 'compass-preferences-model/provider'; +import { + PreferencesProvider, + type AllPreferences, +} from 'compass-preferences-model/provider'; import { WithAtlasProviders, WithStorageProviders } from './entrypoint'; import { TEST_CONNECTION_INFO } from '@mongodb-js/compass-connections/provider'; import { InMemoryConnectionStorage } from '@mongodb-js/connection-storage/provider'; @@ -63,7 +66,8 @@ describe('Home [Component]', function () { const testAppRegistry = new AppRegistry(); function renderHome( props: Partial> = {}, - dataService = createDataService() + dataService = createDataService(), + preferences: Partial = {} ) { render( {}; @@ -116,9 +125,10 @@ describe('Home [Component]', function () { }); describe('is not connected', function () { - it('renders the connect screen', function () { + it('shows the connect screen and hides the workspaces', function () { renderHome(); - expect(screen.getByTestId('connections')).to.be.visible; + expect(screen.getByTestId('workspaces-container')).to.not.be.displayed; + expect(screen.getByTestId('connections')).to.be.displayed; }); it('renders welcome modal and hides it', async function () { @@ -142,6 +152,16 @@ describe('Home [Component]', function () { }); expect(showSettingsSpy.callCount).to.equal(1); }); + + describe('and multi connections is enabled', function () { + it('hides the connect screen and shows the workspaces', function () { + renderHome({}, createDataService(), { + enableNewMultipleConnectionSystem: true, + }); + expect(screen.getByTestId('workspaces-container')).to.be.displayed; + expect(screen.getByTestId('connections')).to.not.be.displayed; + }); + }); }); describe('is connected', function () { @@ -175,6 +195,11 @@ describe('Home [Component]', function () { sinon.restore(); }); + it('hides the connect screen and shows the workspaces', function () { + expect(screen.getByTestId('workspaces-container')).to.be.displayed; + expect(screen.getByTestId('connections')).to.not.be.displayed; + }); + it('on `app:disconnect`', async function () { hadronIpc.ipcRenderer?.emit('app:disconnect'); await waitFor(() => { From 6f25fe4e0851c41485bda75a3028dd254c6a7785 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 22 Apr 2024 12:12:48 +0200 Subject: [PATCH 07/13] chore: remove WelcomeWorkspace related changes --- .../src/components/workspaces-provider.tsx | 1 - packages/compass-workspaces/src/components/workspaces.tsx | 7 ------- packages/compass-workspaces/src/index.ts | 1 - packages/compass-workspaces/src/stores/workspaces.ts | 3 --- packages/compass-workspaces/src/types.ts | 5 ----- 5 files changed, 17 deletions(-) diff --git a/packages/compass-workspaces/src/components/workspaces-provider.tsx b/packages/compass-workspaces/src/components/workspaces-provider.tsx index c093771f209..29c4b0fcf3f 100644 --- a/packages/compass-workspaces/src/components/workspaces-provider.tsx +++ b/packages/compass-workspaces/src/components/workspaces-provider.tsx @@ -2,7 +2,6 @@ import React, { useContext, useRef } from 'react'; import type { AnyWorkspace, WorkspaceComponent } from '../'; export type AnyWorkspaceComponent = - | WorkspaceComponent<'Welcome'> | WorkspaceComponent<'My Queries'> | WorkspaceComponent<'Performance'> | WorkspaceComponent<'Databases'> diff --git a/packages/compass-workspaces/src/components/workspaces.tsx b/packages/compass-workspaces/src/components/workspaces.tsx index f3d67235b8b..12a59357976 100644 --- a/packages/compass-workspaces/src/components/workspaces.tsx +++ b/packages/compass-workspaces/src/components/workspaces.tsx @@ -108,13 +108,6 @@ const CompassWorkspaces: React.FunctionComponent = ({ const tabDescriptions = useMemo(() => { return tabs.map((tab) => { switch (tab.type) { - case 'Welcome': - return { - id: tab.id, - title: tab.type, - // TODO: Change this to correct glyph - iconGlyph: 'Home', - } as const; case 'My Queries': return { id: tab.id, diff --git a/packages/compass-workspaces/src/index.ts b/packages/compass-workspaces/src/index.ts index 6ba5ee70b30..dc6f179acbf 100644 --- a/packages/compass-workspaces/src/index.ts +++ b/packages/compass-workspaces/src/index.ts @@ -157,7 +157,6 @@ export default WorkspacesPlugin; export { WorkspacesProvider } from './components/workspaces-provider'; export type { OpenWorkspaceOptions, WorkspaceTab }; export type { - WelcomeWorkspace, MyQueriesWorkspace, ServerStatsWorkspace, DatabasesWorkspace, diff --git a/packages/compass-workspaces/src/stores/workspaces.ts b/packages/compass-workspaces/src/stores/workspaces.ts index 9b784a64660..15a9d9566c6 100644 --- a/packages/compass-workspaces/src/stores/workspaces.ts +++ b/packages/compass-workspaces/src/stores/workspaces.ts @@ -4,7 +4,6 @@ import { ObjectId } from 'bson'; import AppRegistry from 'hadron-app-registry'; import toNS from 'mongodb-ns'; import type { - WelcomeWorkspace, CollectionWorkspace, CollectionsWorkspace, DatabasesWorkspace, @@ -72,7 +71,6 @@ function isAction
( } type WorkspaceTabProps = - | Omit | Omit | Omit | Omit @@ -469,7 +467,6 @@ export const getActiveTab = (state: WorkspacesState): WorkspaceTab | null => { }; export type OpenWorkspaceOptions = - | Pick, 'type'> | Pick, 'type'> | Pick, 'type' | 'connectionId'> | Pick, 'type' | 'connectionId'> diff --git a/packages/compass-workspaces/src/types.ts b/packages/compass-workspaces/src/types.ts index bcd7f01f6f2..1d2dcf3d625 100644 --- a/packages/compass-workspaces/src/types.ts +++ b/packages/compass-workspaces/src/types.ts @@ -5,10 +5,6 @@ export type CollectionSubtab = | 'Indexes' | 'Validation'; -export type WelcomeWorkspace = { - type: 'Welcome'; -}; - export type MyQueriesWorkspace = { type: 'My Queries'; }; @@ -47,7 +43,6 @@ export type CollectionWorkspace = { }; export type AnyWorkspace = - | WelcomeWorkspace | MyQueriesWorkspace | ServerStatsWorkspace | DatabasesWorkspace From 277a66361d90c114c50b1330f1baeefa39a501fb Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 22 Apr 2024 15:36:05 +0200 Subject: [PATCH 08/13] chore: cleaned up the render tree for compass --- packages/compass-workspaces/src/index.ts | 33 ++++++---- .../compass/src/app/components/home.spec.tsx | 18 +++--- packages/compass/src/app/components/home.tsx | 63 ++++++------------- 3 files changed, 48 insertions(+), 66 deletions(-) diff --git a/packages/compass-workspaces/src/index.ts b/packages/compass-workspaces/src/index.ts index dc6f179acbf..f5945da2f7f 100644 --- a/packages/compass-workspaces/src/index.ts +++ b/packages/compass-workspaces/src/index.ts @@ -83,6 +83,26 @@ export function activateWorkspacePlugin( addCleanup(cleanupLocalAppRegistries); + const setupInstanceListeners = (instance: MongoDBInstance) => { + on(instance, 'change:collections._id', (collection: Collection) => { + const { _id: from } = collection.previousAttributes(); + store.dispatch(collectionRenamed(from, collection.ns)); + }); + + on(instance, 'remove:collections', (collection: Collection) => { + store.dispatch(collectionRemoved(collection.ns)); + }); + + on(instance, 'remove:databases', (database: Database) => { + store.dispatch(databaseRemoved(database.name)); + }); + }; + + const existingInstances = instancesManager.listMongoDBInstances(); + for (const instance of existingInstances.values()) { + setupInstanceListeners(instance); + } + on( instancesManager, MongoDBInstancesManagerEvents.InstanceCreated, @@ -90,18 +110,7 @@ export function activateWorkspacePlugin( connectionInfoId: ConnectionInfo['id'], instance: MongoDBInstance ) { - on(instance, 'change:collections._id', (collection: Collection) => { - const { _id: from } = collection.previousAttributes(); - store.dispatch(collectionRenamed(from, collection.ns)); - }); - - on(instance, 'remove:collections', (collection: Collection) => { - store.dispatch(collectionRemoved(collection.ns)); - }); - - on(instance, 'remove:databases', (database: Database) => { - store.dispatch(databaseRemoved(database.name)); - }); + setupInstanceListeners(instance); } ); diff --git a/packages/compass/src/app/components/home.spec.tsx b/packages/compass/src/app/components/home.spec.tsx index f94b6eee684..4fe7cfed720 100644 --- a/packages/compass/src/app/components/home.spec.tsx +++ b/packages/compass/src/app/components/home.spec.tsx @@ -125,10 +125,10 @@ describe('Home [Component]', function () { }); describe('is not connected', function () { - it('shows the connect screen and hides the workspaces', function () { + it('renders the connect screen', function () { renderHome(); - expect(screen.getByTestId('workspaces-container')).to.not.be.displayed; - expect(screen.getByTestId('connections')).to.be.displayed; + expect(() => screen.getByTestId('home')).to.throw; + expect(screen.getByTestId('connections-wrapper')).to.be.displayed; }); it('renders welcome modal and hides it', async function () { @@ -154,12 +154,12 @@ describe('Home [Component]', function () { }); describe('and multi connections is enabled', function () { - it('hides the connect screen and shows the workspaces', function () { + it('renders only the workspaces', function () { renderHome({}, createDataService(), { enableNewMultipleConnectionSystem: true, }); - expect(screen.getByTestId('workspaces-container')).to.be.displayed; - expect(screen.getByTestId('connections')).to.not.be.displayed; + expect(screen.getByTestId('home')).to.be.displayed; + expect(() => screen.getByTestId('connections-wrapper')).to.throw; }); }); }); @@ -195,9 +195,9 @@ describe('Home [Component]', function () { sinon.restore(); }); - it('hides the connect screen and shows the workspaces', function () { - expect(screen.getByTestId('workspaces-container')).to.be.displayed; - expect(screen.getByTestId('connections')).to.not.be.displayed; + it('renders only the workspaces', function () { + expect(screen.getByTestId('home')).to.be.displayed; + expect(() => screen.getByTestId('connections-wrapper')).to.throw; }); it('on `app:disconnect`', async function () { diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 3b10e2b4122..b383da33712 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -59,17 +59,6 @@ import { usePreference } from 'compass-preferences-model/provider'; resetGlobalCSS(); -const homeViewStyles = css({ - display: 'flex', - flexDirection: 'column', - alignItems: 'stretch', - height: '100vh', -}); - -const hiddenStyles = css({ - display: 'none', -}); - const homePageStyles = css({ display: 'flex', flexDirection: 'row', @@ -348,43 +337,27 @@ function Home({ -
+ {multiConnectionsEnabled ? ( + + ) : isConnected ? ( -
- {/* TODO(COMPASS-7397): Hide but keep it in scope if - connected so that the connection import/export functionality can still - be used through the application menu */} -
+ ) : (
-
+ )} Date: Mon, 22 Apr 2024 15:57:49 +0200 Subject: [PATCH 09/13] chore: fix compass-web checks --- packages/compass-web/sandbox/index.tsx | 4 ++- .../sandbox/use-workspace-tab-router.tsx | 29 ++++++++++++++----- packages/compass-web/src/entrypoint.tsx | 9 +++--- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/packages/compass-web/sandbox/index.tsx b/packages/compass-web/sandbox/index.tsx index 7954fb4b430..de51c3272b6 100644 --- a/packages/compass-web/sandbox/index.tsx +++ b/packages/compass-web/sandbox/index.tsx @@ -113,7 +113,6 @@ function validateConnectionString(str: string) { } const App = () => { - const [initialCurrentTab, updateCurrentTab] = useWorkspaceTabRouter(); const [connectionsHistory, updateConnectionsHistory] = useConnectionsHistory(); const { @@ -127,6 +126,9 @@ const App = () => { const [connectionInfo, setConnectionInfo] = useState( null ); + const [initialCurrentTab, updateCurrentTab] = useWorkspaceTabRouter( + connectionInfo?.id + ); const [openCompassWeb, setOpenCompassWeb] = useState(false); const [ connectionStringValidationResult, diff --git a/packages/compass-web/sandbox/use-workspace-tab-router.tsx b/packages/compass-web/sandbox/use-workspace-tab-router.tsx index bfb861b9477..9bdab414aa4 100644 --- a/packages/compass-web/sandbox/use-workspace-tab-router.tsx +++ b/packages/compass-web/sandbox/use-workspace-tab-router.tsx @@ -1,4 +1,4 @@ -import { useCallback, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import type { OpenWorkspaceOptions, CollectionSubtab, @@ -19,29 +19,44 @@ function getCollectionSubTabFromRoute(subTab: string): CollectionSubtab { return 'Documents'; } } -function getWorkspaceTabFromRoute(route: string): OpenWorkspaceOptions { +function getWorkspaceTabFromRoute( + route: string, + connectionId: string | undefined +): OpenWorkspaceOptions | null { const [, tab, namespace = '', subTab] = route.split('/'); + if (!connectionId) { + return null; + } + if (tab === 'databases') { - return { type: 'Databases' }; + return { type: 'Databases', connectionId }; } if (tab === 'collections' && namespace) { - return { type: 'Collections', namespace }; + return { type: 'Collections', connectionId, namespace }; } if (tab === 'collection' && namespace) { return { type: 'Collection', + connectionId, namespace, initialSubtab: getCollectionSubTabFromRoute(subTab), }; } - return { type: 'Databases' }; + return { type: 'Databases', connectionId }; } -export function useWorkspaceTabRouter() { +export function useWorkspaceTabRouter(connectionId: string | undefined) { const [currentTab, setCurrentTab] = useState( () => { - return getWorkspaceTabFromRoute(window.location.pathname); + return getWorkspaceTabFromRoute(window.location.pathname, connectionId); } ); + + useEffect(() => { + setCurrentTab( + getWorkspaceTabFromRoute(window.location.pathname, connectionId) + ); + }, [connectionId]); + const updateCurrentTab = useCallback((tab: WorkspaceTab | null) => { let newPath: string; switch (tab?.type) { diff --git a/packages/compass-web/src/entrypoint.tsx b/packages/compass-web/src/entrypoint.tsx index ad009dc77d1..5590b425324 100644 --- a/packages/compass-web/src/entrypoint.tsx +++ b/packages/compass-web/src/entrypoint.tsx @@ -144,13 +144,16 @@ function CompassWorkspace({ > { return ( ); }} @@ -171,8 +174,6 @@ function CompassWorkspace({ ); } -const DEFAULT_TAB = { type: 'Databases' } as const; - const LINK_PROPS = { utmSource: 'DE', utmMedium: 'product', From a5facf3b12020169c529be5ed5619ddcea61c13d Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Mon, 22 Apr 2024 16:06:39 +0200 Subject: [PATCH 10/13] Update packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx Co-authored-by: Paula Stachova --- .../src/components/legacy/sidebar-databases-navigation.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx b/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx index 51a71ce76fb..e069b9495b2 100644 --- a/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx +++ b/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx @@ -44,7 +44,6 @@ function SidebarDatabasesNavigation({ preferencesReadOnly || connection.isDataLake || !connection.isWritable; const onNamespaceAction = useCallback( (connectionId: string, ns: string, action: Actions) => { - // TODO: COMPASS-7718 to use connectionId for new tabs switch (action) { case 'select-database': openCollectionsWorkspace(connectionId, ns); From a8582242d376f042ca93c4e16b316382e874c0f1 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 23 Apr 2024 10:18:58 +0200 Subject: [PATCH 11/13] chore: fix from merge --- packages/databases-collections/src/components/collections.tsx | 1 - packages/databases-collections/src/components/databases.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/databases-collections/src/components/collections.tsx b/packages/databases-collections/src/components/collections.tsx index d09211ca425..6cd0df17f53 100644 --- a/packages/databases-collections/src/components/collections.tsx +++ b/packages/databases-collections/src/components/collections.tsx @@ -48,7 +48,6 @@ const Collections: React.FunctionComponent = ({ }) => { const { id: connectionId } = useConnectionInfo(); const { openCollectionWorkspace } = useOpenWorkspace(); - const { id: connectionId } = useConnectionInfo(); useTrackOnChange( 'COMPASS-COLLECTIONS-UI', diff --git a/packages/databases-collections/src/components/databases.tsx b/packages/databases-collections/src/components/databases.tsx index 44999f7a889..a804c8d5c9c 100644 --- a/packages/databases-collections/src/components/databases.tsx +++ b/packages/databases-collections/src/components/databases.tsx @@ -84,7 +84,6 @@ const Databases: React.FunctionComponent = ({ const { id: connectionId } = useConnectionInfo(); const isPreferencesReadOnly = usePreference('readOnly'); const { openCollectionsWorkspace } = useOpenWorkspace(); - const { id: connectionId } = useConnectionInfo(); useTrackOnChange( 'COMPASS-DATABASES-UI', From 4f408263486b9f7c9da43fcf7d5a489ae49c649e Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 23 Apr 2024 10:36:46 +0200 Subject: [PATCH 12/13] chore: fix the issue re the placement of AppRegistryProvider --- packages/compass/src/app/components/home.tsx | 60 ++++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index b383da33712..125a1f7dcf8 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -26,6 +26,7 @@ import { ConnectionsManagerProvider, ConnectionsManager, type ConnectionInfo, + ConnectionInfoProvider, } from '@mongodb-js/compass-connections/provider'; import type { DataService } from 'mongodb-data-service'; import React, { @@ -336,8 +337,8 @@ function Home({ - - {multiConnectionsEnabled ? ( + {multiConnectionsEnabled ? ( + - ) : isConnected ? ( + + ) : isConnected ? ( + - ) : ( -
- -
- )} - - - - - - - -
+
+ ) : ( +
+ +
+ )} + + + + + + +
From 04dff3dd225c7de0a5754fd2cc667d14d4c700b8 Mon Sep 17 00:00:00 2001 From: Himanshu Singh Date: Tue, 23 Apr 2024 12:34:42 +0200 Subject: [PATCH 13/13] chore: check fixes --- packages/compass/src/app/components/home.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/compass/src/app/components/home.tsx b/packages/compass/src/app/components/home.tsx index 125a1f7dcf8..a53981f0d6f 100644 --- a/packages/compass/src/app/components/home.tsx +++ b/packages/compass/src/app/components/home.tsx @@ -26,7 +26,6 @@ import { ConnectionsManagerProvider, ConnectionsManager, type ConnectionInfo, - ConnectionInfoProvider, } from '@mongodb-js/compass-connections/provider'; import type { DataService } from 'mongodb-data-service'; import React, {