Skip to content
Merged
8 changes: 7 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"out": true
},
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
"typescript.tsc.autoDetect": "off"
"typescript.tsc.autoDetect": "off",
"mdb.presetSavedConnections": [
Copy link
Contributor

Choose a reason for hiding this comment

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

I think preset and saved are a bit redundant here. Probably best to shorten it to presetConnections.

{
"name": "Local Test",
"connectionString": "mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000"
}
]
}
56 changes: 46 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,10 @@
"command": "mdb.copyConnectionString",
"title": "Copy Connection String"
},
{
"command": "mdb.openWorkspaceSettingsFile",
"title": "Open Workspace Settings"
},
{
"command": "mdb.renameConnection",
"title": "Rename Connection..."
Expand Down Expand Up @@ -499,32 +503,32 @@
"view/item/context": [
{
"command": "mdb.addDatabase",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem && mdb.isAtlasStreams == false",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem) && mdb.isAtlasStreams == false",
"group": "inline"
},
{
"command": "mdb.addDatabase",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem && mdb.isAtlasStreams == false",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem) && mdb.isAtlasStreams == false",
"group": "1@1"
},
{
"command": "mdb.addStreamProcessor",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem && mdb.isAtlasStreams == true",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem) && mdb.isAtlasStreams == true",
"group": "inline"
},
{
"command": "mdb.addStreamProcessor",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem && mdb.isAtlasStreams == true",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem) && mdb.isAtlasStreams == true",
"group": "1@1"
},
{
"command": "mdb.refreshConnection",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem)",
"group": "1@2"
},
{
"command": "mdb.treeViewOpenMongoDBShell",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem)",
"group": "2@1"
},
{
Expand All @@ -537,14 +541,19 @@
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem",
"group": "3@2"
},
{
"command": "mdb.openWorkspaceSettingsFile",
Copy link
Contributor Author

@gagik gagik Jan 13, 2025

Choose a reason for hiding this comment

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

I think it'd be nice to include ability to quickly open workspace settings here when the item is preset (piggybacking on an existing VSCode action).

We can't easily detect where this preset comes from (i.e. it could also come from user settings) so we could also include a shortcut to open user settings, but maybe we don't want to encourage that and assume they know what they're doing by that point?

If someone that defined this in their user settings (as opposed to workspace) and clicks the Open Workspace Settings, it'd open or create a .vscode/settings.json file in the workspace, and setting things there would override user settings, which seems reasonable.

"when": "view == mongoDBConnectionExplorer && (viewItem == connectedImmutableConnectionTreeItem)",
"group": "3@2"
},
{
"command": "mdb.copyConnectionString",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem)",
"group": "4@1"
},
{
"command": "mdb.disconnectFromConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && viewItem == connectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == connectedConnectionTreeItem || viewItem == connectedImmutableConnectionTreeItem)",
"group": "5@1"
},
{
Expand All @@ -559,7 +568,7 @@
},
{
"command": "mdb.connectToConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && viewItem == disconnectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == disconnectedConnectionTreeItem || viewItem == disconnectedImmutableConnectionTreeItem)",
"group": "1@1"
},
{
Expand All @@ -572,9 +581,14 @@
"when": "view == mongoDBConnectionExplorer && viewItem == disconnectedConnectionTreeItem",
"group": "2@2"
},
{
"command": "mdb.openWorkspaceSettingsFile",
"when": "view == mongoDBConnectionExplorer && (viewItem == disconnectedImmutableConnectionTreeItem)",
"group": "2@2"
},
{
"command": "mdb.copyConnectionString",
"when": "view == mongoDBConnectionExplorer && viewItem == disconnectedConnectionTreeItem",
"when": "view == mongoDBConnectionExplorer && (viewItem == disconnectedConnectionTreeItem || viewItem == disconnectedImmutableConnectionTreeItem)",
"group": "3@1"
},
{
Expand Down Expand Up @@ -1171,6 +1185,28 @@
"type": "string",
"default": "",
"description": "Specify a shell command that is run to start the browser for authenticating with the OIDC identity provider for the server connection. Leave this empty for default browser."
},
"mdb.presetSavedConnections": {
"scope": "window",
"type": "array",
"description": "Defines preset saved connections.",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the connection."
},
"connectionString": {
"type": "string",
"description": "Connection string. Do not store sensitive credentials here."
}
},
"required": [
"name",
"connectionString"
]
}
}
}
},
Expand Down
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum EXTENSION_COMMANDS {
MDB_EDIT_CONNECTION = 'mdb.editConnection',
MDB_REFRESH_CONNECTION = 'mdb.refreshConnection',
MDB_COPY_CONNECTION_STRING = 'mdb.copyConnectionString',
MDB_OPEN_WORKSPACE_SETTINGS_FILE = 'mdb.openWorkspaceSettingsFile',
MDB_REMOVE_CONNECTION_TREE_VIEW = 'mdb.treeItemRemoveConnection',
MDB_RENAME_CONNECTION = 'mdb.renameConnection',
MDB_ADD_DATABASE = 'mdb.addDatabase',
Expand Down
24 changes: 14 additions & 10 deletions src/explorer/connectionTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
import type TreeItemParent from './treeItemParentInterface';
import StreamProcessorTreeItem from './streamProcessorTreeItem';

export enum ConnectionItemContextValues {
disconnected = 'disconnectedConnectionTreeItem',
connected = 'connectedConnectionTreeItem',
}
export type ConnectionItemContextValue = `${'disconnected' | 'connected'}${
| ''
Copy link
Contributor

Choose a reason for hiding this comment

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

[extreme nit] The leading | makes the formatting really awkard - is it even worse without it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This gets automatically added by the linter 🤷

| 'Immutable'}ConnectionTreeItem`;

function getIconPath(isActiveConnection: boolean): {
light: string;
Expand All @@ -39,7 +38,7 @@
extends vscode.TreeItem
implements TreeItemParent, vscode.TreeDataProvider<ConnectionTreeItem>
{
contextValue = ConnectionItemContextValues.disconnected;
contextValue: ConnectionItemContextValue = 'disconnectedConnectionTreeItem';

private _childrenCache: {
[key: string]: DatabaseTreeItem | StreamProcessorTreeItem;
Expand All @@ -50,6 +49,7 @@
connectionId: string;

isExpanded: boolean;
isMutable: boolean;

constructor({
connectionId,
Expand All @@ -58,6 +58,7 @@
connectionController,
cacheIsUpToDate,
childrenCache,
isMutable,
}: {
connectionId: string;
collapsibleState: vscode.TreeItemCollapsibleState;
Expand All @@ -67,21 +68,24 @@
childrenCache: {
[key: string]: DatabaseTreeItem | StreamProcessorTreeItem;
}; // Existing cache.
isMutable: boolean;
}) {
super(
connectionController.getSavedConnectionName(connectionId),
collapsibleState
);

if (
const isConnected =
connectionController.getActiveConnectionId() === connectionId &&
!connectionController.isDisconnecting() &&
!connectionController.isConnecting()
) {
this.contextValue = ConnectionItemContextValues.connected;
}
!connectionController.isConnecting();

this.contextValue = `${isConnected ? 'connected' : 'disconnected'}${
isMutable ? '' : 'Immutable'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

naming here I'm not so sure about. Immutable could also be "Preset", I just thought of making this more generic. The idea is that it's not a connection that can be removed/edited/etc.

}ConnectionTreeItem`;

this.connectionId = connectionId;
this.isMutable = isMutable;
this._connectionController = connectionController;
this.isExpanded = isExpanded;
this._childrenCache = childrenCache;
Expand Down Expand Up @@ -204,7 +208,7 @@
return Object.values(this._childrenCache);
}

private async _buildChildrenCacheForDatabases(dataService: DataService) {

Check warning on line 211 in src/explorer/connectionTreeItem.ts

View workflow job for this annotation

GitHub Actions / Test and Build (ubuntu-latest)

Missing return type on function

Check warning on line 211 in src/explorer/connectionTreeItem.ts

View workflow job for this annotation

GitHub Actions / Test and Build (macos-latest)

Missing return type on function
const databases = await this.listDatabases();
databases.sort((a: string, b: string) => a.localeCompare(b));

Expand All @@ -226,7 +230,7 @@
return newChildrenCache;
}

private async _buildChildrenCacheForStreams(dataService: DataService) {

Check warning on line 233 in src/explorer/connectionTreeItem.ts

View workflow job for this annotation

GitHub Actions / Test and Build (ubuntu-latest)

Missing return type on function

Check warning on line 233 in src/explorer/connectionTreeItem.ts

View workflow job for this annotation

GitHub Actions / Test and Build (macos-latest)

Missing return type on function
const processors = await this.listStreamProcessors();
processors.sort((a, b) => a.name.localeCompare(b.name));

Expand Down
82 changes: 46 additions & 36 deletions src/explorer/explorerTreeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { DOCUMENT_ITEM } from './documentTreeItem';
import { DOCUMENT_LIST_ITEM, CollectionTypes } from './documentListTreeItem';
import EXTENSION_COMMANDS from '../commands';
import { sortTreeItemsByLabel } from './treeItemUtils';
import type { LoadedConnection } from '../storage/connectionStorage';

const log = createLogger('explorer tree controller');

Expand Down Expand Up @@ -130,6 +131,46 @@ export default class ExplorerTreeController
return element;
}

private _getConnectionExpandedState(connection: LoadedConnection): {
collapsibleState: vscode.TreeItemCollapsibleState;
isExpanded: boolean;
} {
const pastConnectionTreeItems = this._connectionTreeItems;
const isActiveConnection =
connection.id === this._connectionController.getActiveConnectionId();
const isBeingConnectedTo =
this._connectionController.isConnecting() &&
connection.id === this._connectionController.getConnectingConnectionId();

let collapsibleState = isActiveConnection
? vscode.TreeItemCollapsibleState.Expanded
: vscode.TreeItemCollapsibleState.Collapsed;

if (
pastConnectionTreeItems[connection.id] &&
!pastConnectionTreeItems[connection.id].isExpanded
) {
// Connection was manually collapsed while being active.
collapsibleState = vscode.TreeItemCollapsibleState.Collapsed;
}
if (isActiveConnection && this._connectionController.isDisconnecting()) {
// Don't show a collapsable state when the connection is being disconnected from.
collapsibleState = vscode.TreeItemCollapsibleState.None;
}
if (isBeingConnectedTo) {
// Don't show a collapsable state when the connection is being connected to.
collapsibleState = vscode.TreeItemCollapsibleState.None;
}
return {
collapsibleState,
// Set expanded when we're connecting to a connection so that it
// expands when it's connected.
isExpanded:
isBeingConnectedTo ||
collapsibleState === vscode.TreeItemCollapsibleState.Expanded,
};
}

getChildren(element?: any): Thenable<any[]> {
// When no element is present we are at the root.
if (!element) {
Expand All @@ -139,45 +180,14 @@ export default class ExplorerTreeController

// Create new connection tree items, using cached children wherever possible.
connections.forEach((connection) => {
const isActiveConnection =
connection.id === this._connectionController.getActiveConnectionId();
const isBeingConnectedTo =
this._connectionController.isConnecting() &&
connection.id ===
this._connectionController.getConnectingConnectionId();

let connectionExpandedState = isActiveConnection
? vscode.TreeItemCollapsibleState.Expanded
: vscode.TreeItemCollapsibleState.Collapsed;

if (
pastConnectionTreeItems[connection.id] &&
!pastConnectionTreeItems[connection.id].isExpanded
) {
// Connection was manually collapsed while being active.
connectionExpandedState = vscode.TreeItemCollapsibleState.Collapsed;
}
if (
isActiveConnection &&
this._connectionController.isDisconnecting()
) {
// Don't show a collapsable state when the connection is being disconnected from.
connectionExpandedState = vscode.TreeItemCollapsibleState.None;
}
if (isBeingConnectedTo) {
// Don't show a collapsable state when the connection is being connected to.
connectionExpandedState = vscode.TreeItemCollapsibleState.None;
}
const { collapsibleState, isExpanded } =
this._getConnectionExpandedState(connection);

this._connectionTreeItems[connection.id] = new ConnectionTreeItem({
connectionId: connection.id,
collapsibleState: connectionExpandedState,
// Set expanded when we're connecting to a connection so that it
// expands when it's connected.
isExpanded:
isBeingConnectedTo ||
connectionExpandedState ===
vscode.TreeItemCollapsibleState.Expanded,
collapsibleState,
isExpanded,
isMutable: connection.isMutable ?? true,
connectionController: this._connectionController,
cacheIsUpToDate: pastConnectionTreeItems[connection.id]
? pastConnectionTreeItems[connection.id].cacheIsUpToDate
Expand Down
10 changes: 10 additions & 0 deletions src/mdbExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,16 @@ export default class MDBExtensionController implements vscode.Disposable {
return true;
}
);
this.registerCommand(
EXTENSION_COMMANDS.MDB_OPEN_WORKSPACE_SETTINGS_FILE,
async () => {
await vscode.commands.executeCommand(
'workbench.action.openWorkspaceSettingsFile'
);

return true;
}
);
this.registerCommand(
EXTENSION_COMMANDS.MDB_COPY_CONNECTION_STRING,
async (element: ConnectionTreeItem): Promise<boolean> => {
Expand Down
Loading
Loading