Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(connect): can not select files on the connection form VSCODE-658 #898

Merged
merged 13 commits into from
Dec 10, 2024
Merged
231 changes: 117 additions & 114 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1177,9 +1177,9 @@
"@babel/core": "^7.25.8",
"@babel/parser": "^7.25.8",
"@babel/traverse": "^7.25.7",
"@mongodb-js/compass-components": "^1.30.1",
"@mongodb-js/connection-form": "^1.42.0",
"@mongodb-js/connection-info": "^0.9.1",
"@mongodb-js/compass-components": "^1.32.1",
"@mongodb-js/connection-form": "^1.45.1",
"@mongodb-js/connection-info": "^0.9.5",
"@mongodb-js/mongodb-constants": "^0.10.3",
"@mongosh/browser-runtime-electron": "^2.3.3",
"@mongosh/i18n": "^2.3.3",
Expand Down
20 changes: 18 additions & 2 deletions src/views/webview-app/extension-app-message-constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ConnectionOptions } from 'mongodb-data-service';
import type { Uri } from 'vscode';

export enum CONNECTION_STATUS {
LOADING = 'LOADING', // When the connection status has not yet been shared from the extension.
Expand All @@ -19,6 +20,8 @@ export enum MESSAGE_TYPES {
CANCEL_CONNECT = 'CANCEL_CONNECT',
CONNECT_RESULT = 'CONNECT_RESULT',
CONNECTION_FORM_OPENED = 'CONNECTION_FORM_OPENED',
OPEN_FILE_CHOOSER = 'OPEN_FILE_CHOOSER',
OPEN_FILE_CHOOSER_RESULT = 'OPEN_FILE_CHOOSER_RESULT',
CONNECTION_STATUS_MESSAGE = 'CONNECTION_STATUS_MESSAGE',
OPEN_EDIT_CONNECTION = 'OPEN_EDIT_CONNECTION',
EDIT_AND_CONNECT_CONNECTION = 'EDIT_AND_CONNECT_CONNECTION',
Expand Down Expand Up @@ -66,6 +69,11 @@ export interface EditAndConnectConnection extends BasicWebviewMessage {
};
}

export interface OpenFileChooser extends BasicWebviewMessage {
command: MESSAGE_TYPES.OPEN_FILE_CHOOSER;
requestId: string;
}

export interface ConnectMessage extends BasicWebviewMessage {
command: MESSAGE_TYPES.CONNECT;
connectionInfo: {
Expand All @@ -85,6 +93,12 @@ export interface ConnectResultsMessage extends BasicWebviewMessage {
connectionId: string;
}

export interface OpenFileChooserResultMessage extends BasicWebviewMessage {
command: MESSAGE_TYPES.OPEN_FILE_CHOOSER_RESULT;
files: Uri | Uri[] | undefined;
requestId: string;
}

export interface GetConnectionStatusMessage extends BasicWebviewMessage {
command: MESSAGE_TYPES.GET_CONNECTION_STATUS;
}
Expand Down Expand Up @@ -123,10 +137,12 @@ export type MESSAGE_FROM_WEBVIEW_TO_EXTENSION =
| OpenConnectionStringInputMessage
| OpenTrustedLinkMessage
| RenameConnectionMessage
| EditAndConnectConnection;
| EditAndConnectConnection
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
| OpenFileChooser;

export type MESSAGE_FROM_EXTENSION_TO_WEBVIEW =
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
| ConnectResultsMessage
| ConnectionStatusMessage
| ThemeChangedMessage
| OpenEditConnectionMessage;
| OpenEditConnectionMessage
| OpenFileChooserResultMessage;
95 changes: 77 additions & 18 deletions src/views/webview-app/overview-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
css,
resetGlobalCSS,
spacing,
FileInputBackendProvider,
createElectronFileInputBackend,
} from '@mongodb-js/compass-components';
import type { Uri } from 'vscode';

import OverviewHeader from './overview-header';
import ConnectionStatus from './connection-status';
Expand All @@ -13,6 +16,8 @@ import AtlasCta from './atlas-cta';
import ResourcesPanel from './resources-panel/panel';
import { ConnectionForm } from './connection-form';
import useConnectionForm from './use-connection-form';
import type { MESSAGE_FROM_EXTENSION_TO_WEBVIEW } from './extension-app-message-constants';
import { MESSAGE_TYPES } from './extension-app-message-constants';

const pageStyles = css({
width: '90%',
Expand All @@ -39,6 +44,7 @@ const OverviewPage: React.FC = () => {
handleCancelConnectClicked,
handleSaveConnectionClicked,
handleConnectClicked,
handleOpenFileChooser,
} = useConnectionForm();
const handleResourcesPanelClose = useCallback(
() => setShowResourcesPanel(false),
Expand All @@ -55,30 +61,83 @@ const OverviewPage: React.FC = () => {
resetGlobalCSS();
}, []);

function handleOpenFileChooserResult<T>(): Promise<T> {
const requestId = handleOpenFileChooser();
return new Promise((resolve) => {
const messageHandler = (event) => {
const message: MESSAGE_FROM_EXTENSION_TO_WEBVIEW = event.data;
if (
message.command === MESSAGE_TYPES.OPEN_FILE_CHOOSER_RESULT &&
message.requestId === requestId
) {
window.removeEventListener('message', messageHandler);
resolve(message.files as T);
}
};
window.addEventListener('message', messageHandler);
});
}

// Electron 32.0 removed support for the `path` property of the Web File object in favor of the webUtils.getPathForFile method.
// https://github.com/electron/electron/blob/83d704009687956fb4b69cb13ab03664d7950118/docs/breaking-changes.md%23removed-filepath
// We can not import `dialog` and `webUtils` from 'electron' in the sandboxed webview.
// To work around this, we use a custom dialog provider that uses webview APIs
// to send a message to the extension process to open the electron file dialog
// and listen for the response to get the file path and send them to the electron file input backend.
const dialogProvider = {
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
getCurrentWindow(): void {},
dialog: {
showSaveDialog(): Promise<{ canceled: boolean; filePath?: string }> {
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
return handleOpenFileChooserResult<Uri | undefined>().then(
(file?: Uri) => {
return { canceled: false, filePath: file?.path };
}
);
},
showOpenDialog(): Promise<{ canceled: boolean; filePaths: string[] }> {
return handleOpenFileChooserResult<Uri[] | undefined>().then(
(files?: Uri[]) => {
return {
canceled: false,
filePaths: files ? files?.map((file) => file.path) : [],
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
};
}
);
},
},
};

return (
<div data-testid="overview-page" className={pageStyles}>
{showResourcesPanel && (
<ResourcesPanel onClose={handleResourcesPanelClose} />
)}
{isConnectionFormOpen && (
<ConnectionForm
isConnecting={isConnecting}
initialConnectionInfo={initialConnectionInfo}
onSaveAndConnectClicked={({ id, connectionOptions }) => {
void handleSaveConnectionClicked({
id,
connectionOptions,
});
handleConnectClicked({
id,
connectionOptions,
});
}}
onCancelConnectClicked={handleCancelConnectClicked}
onClose={closeConnectionForm}
open={isConnectionFormOpen}
connectionErrorMessage={connectionErrorMessage}
/>
<FileInputBackendProvider
createFileInputBackend={createElectronFileInputBackend(
dialogProvider,
null
)}
>
<ConnectionForm
isConnecting={isConnecting}
initialConnectionInfo={initialConnectionInfo}
onSaveAndConnectClicked={({ id, connectionOptions }) => {
void handleSaveConnectionClicked({
id,
connectionOptions,
});
handleConnectClicked({
id,
connectionOptions,
});
}}
onCancelConnectClicked={handleCancelConnectClicked}
onClose={closeConnectionForm}
open={isConnectionFormOpen}
connectionErrorMessage={connectionErrorMessage}
/>
</FileInputBackendProvider>
)}
<OverviewHeader onResourcesClick={handleResourcesClick} />
<HorizontalRule />
Expand Down
6 changes: 6 additions & 0 deletions src/views/webview-app/use-connection-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
sendCancelConnectToExtension,
sendFormOpenedToExtension,
sendEditConnectionToExtension,
sendOpenFileChooserToExtension,
} from './vscode-api';
import { MESSAGE_TYPES } from './extension-app-message-constants';
import type { MESSAGE_FROM_EXTENSION_TO_WEBVIEW } from './extension-app-message-constants';
Expand Down Expand Up @@ -188,6 +189,11 @@ export default function useConnectionForm() {
type: 'close-connection-form',
});
},
handleOpenFileChooser: () => {
const requestId = uuidv4();
sendOpenFileChooserToExtension(requestId);
return requestId;
},
handleCancelConnectClicked: () => {
sendCancelConnectToExtension();
},
Expand Down
7 changes: 7 additions & 0 deletions src/views/webview-app/vscode-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export const sendConnectToExtension = (
});
};

export const sendOpenFileChooserToExtension = (requestId: string) => {
vscode.postMessage({
command: MESSAGE_TYPES.OPEN_FILE_CHOOSER,
requestId,
});
};

export const sendCancelConnectToExtension = () => {
vscode.postMessage({
command: MESSAGE_TYPES.CANCEL_CONNECT,
Expand Down
8 changes: 8 additions & 0 deletions src/views/webviewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ export default class WebviewController {
});
this._telemetryService.track(TelemetryEventTypes.CONNECTION_EDITED);
return;
case MESSAGE_TYPES.OPEN_FILE_CHOOSER:
const files = await vscode.window.showOpenDialog();
alenakhineika marked this conversation as resolved.
Show resolved Hide resolved
void panel.webview.postMessage({
command: MESSAGE_TYPES.OPEN_FILE_CHOOSER_RESULT,
files,
requestId: message.requestId,
});
return;
case MESSAGE_TYPES.CREATE_NEW_PLAYGROUND:
void vscode.commands.executeCommand(
EXTENSION_COMMANDS.MDB_CREATE_PLAYGROUND_FROM_OVERVIEW_PAGE
Expand Down
Loading