Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,8 @@ import type {
SidebarActionableItem,
Connection,
} from './tree-data';
import type {
ContextMenuItemGroup,
ItemAction,
ItemSeparator,
} from '@mongodb-js/compass-components';
import type { ItemAction, ItemSeparator } from '@mongodb-js/compass-components';
import type { ContextMenuItemGroup } from '@mongodb-js/compass-context-menu';
import {
VisuallyHidden,
css,
Expand All @@ -28,8 +25,10 @@ import { usePreference } from 'compass-preferences-model/provider';
import type { NavigationItemActions } from './item-actions';
import {
collectionItemActions,
collectionContextMenuActions,
connectedConnectionItemActions,
databaseItemActions,
databaseContextMenuActions,
notConnectedConnectionItemActions,
} from './item-actions';
import { itemActionsToContextMenuGroups } from './context-menus';
Expand Down Expand Up @@ -248,35 +247,51 @@ const ConnectionsNavigationTree: React.FunctionComponent<
connectionStatus: item.connectionStatus,
})
);
case 'database':
return [
...itemActionsToContextMenuGroups(
item,
onItemAction,
databaseItemActions({
hasWriteActionsDisabled: item.hasWriteActionsDisabled,
})
),
// Include menu items on the connection level
...getContextMenuGroups(item.connectionItem),
];
default:
return [
...itemActionsToContextMenuGroups(
item,
onItemAction,
collectionItemActions({
hasWriteActionsDisabled: item.hasWriteActionsDisabled,
type: item.type,
isRenameCollectionEnabled,
})
),
// Include menu items on the database (and connection) level
...getContextMenuGroups(item.databaseItem),
];
case 'database': {
const {
isPerformanceTabAvailable,
isPerformanceTabSupported,
isShellEnabled,
hasWriteActionsDisabled,
connectionInfo,
} = item.connectionItem;
return itemActionsToContextMenuGroups(
item,
onItemAction,
databaseContextMenuActions({
hasWriteActionsDisabled,
isShellEnabled,
isPerformanceTabAvailable,
isPerformanceTabSupported,
isAtlas: !!connectionInfo.atlasMetadata,
})
);
}
default: {
const {
isPerformanceTabAvailable,
isPerformanceTabSupported,
isShellEnabled,
hasWriteActionsDisabled,
connectionInfo,
} = item.databaseItem.connectionItem;
return itemActionsToContextMenuGroups(
item,
onItemAction,
collectionContextMenuActions({
hasWriteActionsDisabled,
type: item.type,
isRenameCollectionEnabled,
isShellEnabled,
isPerformanceTabAvailable,
isPerformanceTabSupported,
isAtlas: !!connectionInfo.atlasMetadata,
})
);
}
}
},
[onItemAction]
[onItemAction, isRenameCollectionEnabled]
);

const isTestEnv = process.env.NODE_ENV === 'test';
Expand Down
191 changes: 191 additions & 0 deletions packages/compass-connections-navigation/src/item-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export const collectionItemActions = ({
}

if (type === 'view') {
actions.push({ separator: true });
actions.push(
{
action: 'drop-collection',
Expand All @@ -228,6 +229,7 @@ export const collectionItemActions = ({
}

if (type !== 'timeseries' && isRenameCollectionEnabled) {
actions.push({ separator: true });
actions.push({
action: 'rename-collection',
label: 'Rename collection',
Expand All @@ -243,3 +245,192 @@ export const collectionItemActions = ({

return actions;
};

export const databaseContextMenuActions = ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

won't be able to reuse actions in this case since we decided to go a more custom route

hasWriteActionsDisabled,
isShellEnabled,
isPerformanceTabAvailable,
isPerformanceTabSupported,
isAtlas,
}: {
hasWriteActionsDisabled: boolean;
isShellEnabled: boolean;
isPerformanceTabAvailable: boolean;
isPerformanceTabSupported: boolean;
isAtlas: boolean;
}): NavigationItemActions => {
return stripNullActions([
// Database-specific actions
hasWriteActionsDisabled
? null
: {
action: 'create-collection',
icon: 'Plus',
label: 'Create collection',
},
{ separator: true },
hasWriteActionsDisabled
? null
: {
action: 'create-database',
icon: 'Plus',
label: 'Create database',
},
hasWriteActionsDisabled
? null
: {
action: 'drop-database',
icon: 'Trash',
label: 'Drop database',
},
{ separator: true },
isShellEnabled
? {
action: 'open-shell',
icon: 'Shell',
label: 'Open MongoDB shell',
}
: null,
isPerformanceTabAvailable
? {
action: 'connection-performance-metrics',
icon: 'Gauge',
label: 'View performance metrics',
isDisabled: !isPerformanceTabSupported,
disabledDescription: 'Not supported',
}
: null,
isAtlas
? null
: {
action: 'open-connection-info',
icon: 'InfoWithCircle',
label: 'Show connection info',
},
{
action: 'refresh-databases',
label: 'Refresh databases',
icon: 'Refresh',
},
{ separator: true },
{
action: 'connection-disconnect',
icon: 'Disconnect',
label: 'Disconnect',
variant: 'destructive',
},
]);
};

export const collectionContextMenuActions = ({
hasWriteActionsDisabled,
type,
isRenameCollectionEnabled,
isShellEnabled,
isPerformanceTabAvailable,
isPerformanceTabSupported,
isAtlas,
}: {
hasWriteActionsDisabled: boolean;
type: 'collection' | 'view' | 'timeseries';
isRenameCollectionEnabled: boolean;
isShellEnabled: boolean;
isPerformanceTabAvailable: boolean;
isPerformanceTabSupported: boolean;
isAtlas: boolean;
}): NavigationItemActions => {
const actions: NavigationItemActions = [
// Collection-specific actions
{
action: 'open-in-new-tab',
label: 'Open in new tab',
icon: 'OpenNewTab',
},
];

if (!hasWriteActionsDisabled) {
if (type === 'view') {
actions.push({ separator: true });
// For views: show Duplicate view, Modify view, Drop view
actions.push(
{
action: 'duplicate-view',
label: 'Duplicate view',
icon: 'Copy',
},
{
action: 'modify-view',
label: 'Modify view',
icon: 'Edit',
},
{
action: 'drop-collection',
label: 'Drop view',
icon: 'Trash',
}
);
} else {
actions.push({ separator: true });
// For collections: show Rename collection, Drop collection
if (type !== 'timeseries' && isRenameCollectionEnabled) {
actions.push({
action: 'rename-collection',
label: 'Rename collection',
icon: 'Edit',
});
}
actions.push({
action: 'create-collection',
icon: 'Plus',
label: 'Create collection',
});
actions.push({
action: 'drop-collection',
label: 'Drop collection',
icon: 'Trash',
});
}
}

// Add connection-level actions
const connectionActions = stripNullActions([
{ separator: true },
isShellEnabled
? {
action: 'open-shell',
Copy link
Collaborator

@mabaasit mabaasit Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right-clicking on db/collection, we should open shell for them, right? if you open shell from db screen, it automatically switches to that db usinguse dbName. And for collection, it switches and writes a find query.

Copy link
Collaborator

@mabaasit mabaasit Jul 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behaviour is a bit different to what a user would expect

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great point, my solution is going to be to remove this from collection level and making a note of this as a descoped feature

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feel free to ignore if its more work: for this action, we already have an item and we can do exactly what we do at other places:

  1. For dbItem we can add {initialEvaluate: use ${namespace}} to the options
  2. For collItem we can add initialEvaluate and initialInput

This way we will have same exact behaviour and also have shell in the menu.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh that seems good!

icon: 'Shell',
label: 'Open MongoDB shell',
}
: null,
isPerformanceTabAvailable
? {
action: 'connection-performance-metrics',
icon: 'Gauge',
label: 'View performance metrics',
isDisabled: !isPerformanceTabSupported,
disabledDescription: 'Not supported',
}
: null,
isAtlas
? null
: {
action: 'open-connection-info',
icon: 'InfoWithCircle',
label: 'Show connection info',
},
{
action: 'refresh-databases',
label: 'Refresh collection',
icon: 'Refresh',
},
{ separator: true },
{
action: 'connection-disconnect',
icon: 'Disconnect',
label: 'Disconnect',
variant: 'destructive',
},
]);

return [...actions, ...connectionActions];
};
Loading