From 92b05299324b5123868274b754efe4376ff978a7 Mon Sep 17 00:00:00 2001 From: Kevin Mas Ruiz Date: Mon, 22 Apr 2024 17:48:59 +0200 Subject: [PATCH] chore: adapt DropNamespacePlugin to multiple connections COMPASS-7863 (#5721) * chore: drop namespace plugin * chore: remove console.log * chore: fix tests * chore: fix linter * chore: fix linting issues --- .../legacy/sidebar-databases-navigation.tsx | 4 ++-- .../active-connection-navigation.tsx | 4 ++-- .../src/collections.tsx | 6 +++-- .../src/databases.tsx | 8 +++++-- .../src/collections-plugin.spec.tsx | 1 + .../src/components/collections.tsx | 12 ++++++++-- .../src/components/databases.tsx | 12 ++++++++-- packages/databases-collections/src/index.ts | 4 +--- .../src/modules/collections.ts | 7 +++++- .../src/modules/databases.ts | 7 ++++-- .../src/stores/drop-namespace.spec.tsx | 9 ++++--- .../src/stores/drop-namespace.tsx | 24 +++++++++++++++---- 12 files changed, 73 insertions(+), 25 deletions(-) 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 7912d66c11d..8f6243ef305 100644 --- a/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx +++ b/packages/compass-sidebar/src/components/legacy/sidebar-databases-navigation.tsx @@ -160,13 +160,13 @@ const onNamespaceAction = ( const ns = toNS(namespace); switch (action) { case 'drop-database': - emit('open-drop-database', ns.database); + emit('open-drop-database', connectionId, ns.database); return; case 'rename-collection': emit('open-rename-collection', connectionId, ns); return; case 'drop-collection': - emit('open-drop-collection', ns); + emit('open-drop-collection', connectionId, ns); return; case 'create-collection': emit('open-create-collection', ns); 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 f57431ce40b..f6ef148c0f7 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 @@ -284,13 +284,13 @@ const onNamespaceAction = ( const ns = toNS(namespace); switch (action) { case 'drop-database': - emit('open-drop-database', ns.database); + emit('open-drop-database', connectionId, ns.database); return; case 'rename-collection': emit('open-rename-collection', connectionId, ns); return; case 'drop-collection': - emit('open-drop-collection', ns); + emit('open-drop-collection', connectionId, ns); return; case 'create-collection': emit('open-create-collection', ns); diff --git a/packages/databases-collections-list/src/collections.tsx b/packages/databases-collections-list/src/collections.tsx index 79110f39846..d376e8a6b89 100644 --- a/packages/databases-collections-list/src/collections.tsx +++ b/packages/databases-collections-list/src/collections.tsx @@ -75,12 +75,14 @@ function collectionPropertyToBadge({ } const CollectionsList: React.FunctionComponent<{ + connectionId: string; collections: Collection[]; onCollectionClick(id: string): void; - onDeleteCollectionClick?: (id: string) => void; + onDeleteCollectionClick?: (connectionId: string, id: string) => void; onCreateCollectionClick?: () => void; onRefreshClick?: () => void; }> = ({ + connectionId, collections, onCollectionClick, onCreateCollectionClick, @@ -103,7 +105,7 @@ const CollectionsList: React.FunctionComponent<{ { name: 'index_size', label: 'Total index size' }, ]} onItemClick={onCollectionClick} - onDeleteItemClick={onDeleteCollectionClick} + onDeleteItemClick={(ns) => onDeleteCollectionClick?.(connectionId, ns)} onCreateItemClick={onCreateCollectionClick} onRefreshClick={onRefreshClick} renderItem={({ diff --git a/packages/databases-collections-list/src/databases.tsx b/packages/databases-collections-list/src/databases.tsx index 85d7d82613e..9584aed1cda 100644 --- a/packages/databases-collections-list/src/databases.tsx +++ b/packages/databases-collections-list/src/databases.tsx @@ -22,12 +22,14 @@ const DATABASE_CARD_HEIGHT = 154; const DATABASE_CARD_LIST_HEIGHT = 118; const DatabasesList: React.FunctionComponent<{ + connectionId: string; databases: Database[]; onDatabaseClick(id: string): void; - onDeleteDatabaseClick?: (id: string) => void; + onDeleteDatabaseClick?: (connectionId: string, id: string) => void; onCreateDatabaseClick?: () => void; onRefreshClick?: () => void; }> = ({ + connectionId, databases, onDatabaseClick, onCreateDatabaseClick, @@ -48,7 +50,9 @@ const DatabasesList: React.FunctionComponent<{ { name: 'index_count', label: 'Indexes' }, ]} onItemClick={onDatabaseClick} - onDeleteItemClick={onDeleteDatabaseClick} + onDeleteItemClick={(database) => + onDeleteDatabaseClick?.(connectionId, database) + } onCreateItemClick={onCreateDatabaseClick} onRefreshClick={onRefreshClick} renderItem={({ diff --git a/packages/databases-collections/src/collections-plugin.spec.tsx b/packages/databases-collections/src/collections-plugin.spec.tsx index 6de5c5d498d..24f88902e12 100644 --- a/packages/databases-collections/src/collections-plugin.spec.tsx +++ b/packages/databases-collections/src/collections-plugin.spec.tsx @@ -81,6 +81,7 @@ describe('Collections [Plugin]', function () { userEvent.click(screen.getByRole('button', { name: /Delete/ })); expect(appRegistry.emit).to.have.been.calledWithMatch( 'open-drop-collection', + 'TEST', { ns: 'foo.bar' } ); }); diff --git a/packages/databases-collections/src/components/collections.tsx b/packages/databases-collections/src/components/collections.tsx index 9170c3a9403..ac32ee2406f 100644 --- a/packages/databases-collections/src/components/collections.tsx +++ b/packages/databases-collections/src/components/collections.tsx @@ -17,6 +17,7 @@ import { import type Collection from 'mongodb-collection-model'; import toNS from 'mongodb-ns'; import { useOpenWorkspace } from '@mongodb-js/compass-workspaces/provider'; +import { useConnectionInfo } from '@mongodb-js/compass-connections/provider'; const ERROR_WARNING = 'An error occurred while loading collections'; @@ -30,7 +31,7 @@ type CollectionsListProps = { collectionsLoadingStatus: string; collectionsLoadingError?: string | null; isEditable: boolean; - onDeleteCollectionClick(ns: string): void; + onDeleteCollectionClick(connectionId: string, ns: string): void; onCreateCollectionClick(dbName: string): void; onRefreshClick(): void; }; @@ -45,6 +46,7 @@ const Collections: React.FunctionComponent = ({ onCreateCollectionClick: _onCreateCollectionClick, onRefreshClick, }) => { + const { id: connectionId } = useConnectionInfo(); const { openCollectionWorkspace } = useOpenWorkspace(); useTrackOnChange( @@ -76,7 +78,13 @@ const Collections: React.FunctionComponent = ({ isEditable ? { onDeleteCollectionClick, onCreateCollectionClick } : {} ); - return ; + return ( + + ); }; const ConnectedCollections = connect( diff --git a/packages/databases-collections/src/components/databases.tsx b/packages/databases-collections/src/components/databases.tsx index f168fd63363..8f0ef72fe48 100644 --- a/packages/databases-collections/src/components/databases.tsx +++ b/packages/databases-collections/src/components/databases.tsx @@ -19,6 +19,7 @@ import { } from '../modules/databases'; import { useTrackOnChange } from '@mongodb-js/compass-logging/provider'; import { useOpenWorkspace } from '@mongodb-js/compass-workspaces/provider'; +import { useConnectionInfo } from '@mongodb-js/compass-connections/provider'; const errorContainerStyles = css({ padding: spacing[3], @@ -64,7 +65,7 @@ type DatabasesProps = { isWritable: boolean; isGenuineMongoDB: boolean; isDataLake: boolean; - onDeleteDatabaseClick(ns: string): void; + onDeleteDatabaseClick(connectionId: string, ns: string): void; onCreateDatabaseClick(): void; onRefreshClick(): void; }; @@ -80,6 +81,7 @@ const Databases: React.FunctionComponent = ({ onCreateDatabaseClick, onRefreshClick, }) => { + const { id: connectionId } = useConnectionInfo(); const isPreferencesReadOnly = usePreference('readOnly'); const { openCollectionsWorkspace } = useOpenWorkspace(); @@ -115,7 +117,13 @@ const Databases: React.FunctionComponent = ({ : {} ); - return ; + return ( + + ); }; const mapStateToProps = (state: DatabasesState) => { diff --git a/packages/databases-collections/src/index.ts b/packages/databases-collections/src/index.ts index 6980fdd9262..979990380e9 100644 --- a/packages/databases-collections/src/index.ts +++ b/packages/databases-collections/src/index.ts @@ -60,9 +60,7 @@ export const DropNamespacePlugin = registerHadronPlugin( }, { logger: createLoggerAndTelemetryLocator('COMPASS-DROP-NAMESPACE-UI'), - dataService: dataServiceLocator as DataServiceLocator< - 'dropDatabase' | 'dropCollection' - >, + connectionsManager: connectionsManagerLocator, } ); diff --git a/packages/databases-collections/src/modules/collections.ts b/packages/databases-collections/src/modules/collections.ts index a92b9ea7583..402628740d3 100644 --- a/packages/databases-collections/src/modules/collections.ts +++ b/packages/databases-collections/src/modules/collections.ts @@ -94,10 +94,15 @@ export const createNewCollection = ( }; export const deleteCollection = ( + connectionId: string, namespace: string ): CollectionsThunkAction => { return (_dispatch, _getState, { globalAppRegistry }) => { - globalAppRegistry.emit('open-drop-collection', toNS(namespace)); + globalAppRegistry.emit( + 'open-drop-collection', + connectionId, + toNS(namespace) + ); }; }; diff --git a/packages/databases-collections/src/modules/databases.ts b/packages/databases-collections/src/modules/databases.ts index e8a219d4b7c..f0ed781b123 100644 --- a/packages/databases-collections/src/modules/databases.ts +++ b/packages/databases-collections/src/modules/databases.ts @@ -97,9 +97,12 @@ export const createDatabase = (): DatabasesThunkAction => { }; }; -export const dropDatabase = (ns: string): DatabasesThunkAction => { +export const dropDatabase = ( + connectionId: string, + ns: string +): DatabasesThunkAction => { return (_dispatch, _getState, { globalAppRegistry }) => { - globalAppRegistry.emit('open-drop-database', ns); + globalAppRegistry.emit('open-drop-database', connectionId, ns); }; }; diff --git a/packages/databases-collections/src/stores/drop-namespace.spec.tsx b/packages/databases-collections/src/stores/drop-namespace.spec.tsx index 1c31c1c6f9c..6fa932f04da 100644 --- a/packages/databases-collections/src/stores/drop-namespace.spec.tsx +++ b/packages/databases-collections/src/stores/drop-namespace.spec.tsx @@ -14,11 +14,14 @@ describe('DropNamespacePlugin', function () { dropDatabase: sandbox.stub().resolves(true), dropCollection: sandbox.stub().resolves(true), }; + const connectionsManager = { + getDataServiceForConnection: sandbox.stub().returns(dataService), + } as any; beforeEach(function () { const Plugin = DropNamespacePlugin.withMockServices({ globalAppRegistry: appRegistry, - dataService, + connectionsManager, }); render(); }); @@ -29,7 +32,7 @@ describe('DropNamespacePlugin', function () { }); it('should ask for confirmation and delete collection on `open-drop-collection` event', async function () { - appRegistry.emit('open-drop-collection', toNS('test.to-drop')); + appRegistry.emit('open-drop-collection', 'TEST', toNS('test.to-drop')); expect( screen.getByText( @@ -58,7 +61,7 @@ describe('DropNamespacePlugin', function () { }); it('should ask for confirmation and delete database on `open-drop-database` event', async function () { - appRegistry.emit('open-drop-database', 'db-to-drop'); + appRegistry.emit('open-drop-database', 'TEST', 'db-to-drop'); expect( screen.getByText('Are you sure you want to drop database "db-to-drop"?') diff --git a/packages/databases-collections/src/stores/drop-namespace.tsx b/packages/databases-collections/src/stores/drop-namespace.tsx index 38940bca03b..e7b55e17e57 100644 --- a/packages/databases-collections/src/stores/drop-namespace.tsx +++ b/packages/databases-collections/src/stores/drop-namespace.tsx @@ -7,7 +7,7 @@ import { } from '@mongodb-js/compass-components'; import type { LoggerAndTelemetry } from '@mongodb-js/compass-logging/provider'; import type AppRegistry from 'hadron-app-registry'; -import type { DataService } from '@mongodb-js/compass-connections/provider'; +import type { ConnectionsManager } from '@mongodb-js/compass-connections/provider'; import toNS from 'mongodb-ns'; import type { ActivateHelpers } from 'hadron-app-registry'; @@ -15,22 +15,30 @@ type NS = ReturnType; type DropNamespaceServices = { globalAppRegistry: AppRegistry; - dataService: Pick; + connectionsManager: ConnectionsManager; logger: LoggerAndTelemetry; }; export function activatePlugin( _: unknown, - { globalAppRegistry, dataService, logger: { track } }: DropNamespaceServices, + { + globalAppRegistry, + connectionsManager, + logger: { track }, + }: DropNamespaceServices, { on, cleanup, signal }: ActivateHelpers ) { - const onDropNamespace = async (namespace: string | NS) => { + const onDropNamespace = async ( + connectionId: string, + namespace: string | NS + ) => { // `drop-collection` is emitted with NS, `drop-database` is emitted with a // string, we're keeping compat with both for now to avoid conflicts with // other refactoring if (typeof namespace === 'string') { namespace = toNS(namespace); } + const { ns, validCollectionName: isCollection, @@ -53,6 +61,14 @@ export function activatePlugin( if (confirmed) { try { const method = isCollection ? 'dropCollection' : 'dropDatabase'; + const dataService = + connectionsManager.getDataServiceForConnection(connectionId); + if (!dataService) { + throw new Error( + 'unreachable: only available when there is an open connection.' + ); + } + await dataService[method](ns); globalAppRegistry.emit( isCollection ? 'collection-dropped' : 'database-dropped',