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

feat(webview): use Compass' connection form in the new overview page VSCODE-488 #622

Merged
merged 7 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
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
712 changes: 641 additions & 71 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -978,8 +978,8 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@iconify-icons/codicon": "^1.2.25",
"@iconify/react": "^1.1.4",
"@leafygreen-ui/logo": "^8.0.4",
"@mongodb-js/compass-components": "^1.19.0",
"@mongodb-js/compass-components": "^1.20.0",
"@mongodb-js/connection-form": "^1.20.4",
"@mongodb-js/mongodb-constants": "^0.7.1",
"@mongosh/browser-runtime-electron": "^2.0.2",
"@mongosh/i18n": "^2.0.2",
Expand Down
16 changes: 14 additions & 2 deletions src/test/suite/views/webview-app/connect-helper.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,27 @@ import { MESSAGE_TYPES } from '../../../../views/webview-app/extension-app-messa

describe('ConnectHelper test suite', function () {
test('when rendered it should show both connection options', function () {
render(<ConnectHelper />);
render(
<ConnectHelper
onClickOpenConnectionForm={() => {
/* noop */
}}
/>
);
expect(screen.getByLabelText('Connect with connection string')).to.not.be
.null;
expect(screen.getByLabelText('Open connection form')).to.not.be.null;
});

test('when connecting with string, it should call vscode to open connection string input', function () {
const postMessageStub = Sinon.stub(vscode, 'postMessage');
render(<ConnectHelper />);
render(
<ConnectHelper
onClickOpenConnectionForm={() => {
/* noop */
}}
/>
);
screen.getByLabelText('Connect with connection string').click();
expect(postMessageStub).to.have.been.calledWithExactly({
command: MESSAGE_TYPES.OPEN_CONNECTION_STRING_INPUT,
Expand Down
5 changes: 5 additions & 0 deletions src/test/suite/views/webview-app/jest-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
const Enzyme = require('enzyme');
const Adapter = require('@wojtekmaj/enzyme-adapter-react-17');
const chai = require('chai');
const { TextEncoder, TextDecoder } = require('util');

chai.use(require('sinon-chai'));
Enzyme.configure({ adapter: new Adapter() });

// eslint-disable-next-line no-undef
jest.mock('@iconify-icons/codicon/book', () => {});

// Note applied with js dom so we do manually. (Required by node_modules/mongodb-connection-string-url/node_modules/whatwg-url/lib/encoding.js)
Object.assign(global, { TextDecoder, TextEncoder });

global.vscodeFake = {
postMessage: (message) => {},
};
Expand Down
19 changes: 19 additions & 0 deletions src/test/suite/views/webview-app/overview-page.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React from 'react';
import { expect } from 'chai';
import { cleanup, render, screen } from '@testing-library/react';
import sinon from 'sinon';

import OverviewPage from '../../../../views/webview-app/overview-page';
import * as featureFlags from '../../../../featureFlags';

describe('OverviewPage test suite', function () {
afterEach(cleanup);
Expand All @@ -26,4 +29,20 @@ describe('OverviewPage test suite', function () {
screen.getByLabelText('Close').click();
expect(screen.queryByText('Product overview')).to.be.null;
});

describe('with the new connection form feature flag useNewConnectionForm enabled', function () {
beforeEach(function () {
sinon.stub(featureFlags, 'getFeatureFlag').returns(true);
Anemy marked this conversation as resolved.
Show resolved Hide resolved

render(<OverviewPage />);
});

test('it renders the new connection form when opened', function () {
const connectionFormTestId = 'connection-form-modal';
expect(screen.queryByTestId(connectionFormTestId)).to.not.exist;

screen.getByText('Open form').click();
expect(screen.getByTestId(connectionFormTestId)).to.exist;
});
});
});
8 changes: 4 additions & 4 deletions src/views/webview-app/connect-helper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ const getOSCommandShortcutName = (): string => {
return 'Cmd';
};

const ConnectHelper: React.FC = () => {
const ConnectHelper: React.FC<{
onClickOpenConnectionForm: () => void;
}> = ({ onClickOpenConnectionForm }) => {
return (
<div className={containerStyles}>
<div className={cardContainerStyles}>
Expand Down Expand Up @@ -89,9 +91,7 @@ const ConnectHelper: React.FC = () => {
<Button
aria-label="Open connection form"
darkMode
onClick={() => {
// TODO
}}
onClick={onClickOpenConnectionForm}
>
Open form
</Button>
Expand Down
68 changes: 68 additions & 0 deletions src/views/webview-app/connection-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import CompassConnectionForm from '@mongodb-js/connection-form';
import { Modal, css, spacing } from '@mongodb-js/compass-components';
import { v4 as uuidv4 } from 'uuid';

const modalContentStyles = css({
// Override LeafyGreen width to accommodate the strict connection-form size.
width: `${spacing[6] * 12}px !important`,
});

const formContainerStyles = css({
padding: spacing[3],
position: 'relative',
display: 'flex',
flexDirection: 'column',
});

function createNewConnectionInfo() {
return {
id: uuidv4(),
connectionOptions: {
connectionString: 'mongodb://localhost:27017',
},
};
}

const initialConnectionInfo = createNewConnectionInfo();

const ConnectionForm: React.FunctionComponent<{
onConnectClicked: (onConnectClicked: unknown) => void;
onClose: () => void;
open: boolean;
}> = ({ onConnectClicked, onClose, open }) => {
return (
<>
<Modal
// Warning: This property may be removed in future
// modal releases.
contentClassName={modalContentStyles}
setOpen={() => onClose()}
open={open}
data-testid="connection-form-modal"
size="large"
>
<div className={formContainerStyles}>
<CompassConnectionForm
onConnectClicked={onConnectClicked}
initialConnectionInfo={initialConnectionInfo}
preferences={{
protectConnectionStrings: false,
forceConnectionOptions: [],
showKerberosPasswordField: false,
showOIDCDeviceAuthFlow: false,
enableOidc: false,
enableDebugUseCsfleSchemaMap: false,
protectConnectionStringsForNewConnections: false,
showOIDCAuth: false,
showKerberosAuth: false,
showCSFLE: false,
}}
/>
</div>
</Modal>
</>
Anemy marked this conversation as resolved.
Show resolved Hide resolved
);
};

export { ConnectionForm };
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { MongoDBLogo as LeafyGreenMongoDBLogo } from '@leafygreen-ui/logo';
import { MongoDBLogo as LeafyGreenMongoDBLogo } from '@mongodb-js/compass-components';
himanshusinghs marked this conversation as resolved.
Show resolved Hide resolved

import styles from './mongodb-logo.less';

Expand Down
34 changes: 31 additions & 3 deletions src/views/webview-app/overview-page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import React, { useCallback, useState } from 'react';
import { HorizontalRule, css, spacing } from '@mongodb-js/compass-components';
import React, { useCallback, useLayoutEffect, useState } from 'react';
import {
HorizontalRule,
css,
resetGlobalCSS,
spacing,
} from '@mongodb-js/compass-components';

import OverviewHeader from './overview-header';
import ConnectionStatus from './connection-status';
import ConnectHelper from './connect-helper';
import AtlasCta from './atlas-cta';
import ResourcesPanel from './resources-panel/panel';
import { ConnectionForm } from './connection-form';

const pageStyles = css({
width: '90%',
Expand All @@ -21,6 +28,7 @@

const OverviewPage: React.FC = () => {
const [showResourcesPanel, setShowResourcesPanel] = useState(false);
const [showConnectionForm, setShowConnectionForm] = useState(false);
const handleResourcesPanelClose = useCallback(
() => setShowResourcesPanel(false),
[]
Expand All @@ -29,15 +37,35 @@
() => setShowResourcesPanel(true),
[]
);

useLayoutEffect(() => {
// TODO(VSCODE-490): Move this reset css call to the top level entry point
// of the app and out of the react lifecycle.
resetGlobalCSS();
}, []);

return (
<div className={pageStyles}>
{showResourcesPanel && (
<ResourcesPanel onClose={handleResourcesPanelClose} />
)}
{showConnectionForm && (
<ConnectionForm
onConnectClicked={(connectionInfo) => {
// TODO(VSCODE-489): Type connection form and post message to the webview controller.
// Maintain connecting status.
console.log('connect', connectionInfo);

Check warning on line 57 in src/views/webview-app/overview-page.tsx

View workflow job for this annotation

GitHub Actions / Test and Build (ubuntu-latest)

Unexpected console statement

Check warning on line 57 in src/views/webview-app/overview-page.tsx

View workflow job for this annotation

GitHub Actions / Test and Build (macos-latest)

Unexpected console statement
}}
onClose={() => setShowConnectionForm(false)}
open={showConnectionForm}
/>
)}
<OverviewHeader onResourcesClick={handleResourcesClick} />
<HorizontalRule />
<ConnectionStatus />
<ConnectHelper />
<ConnectHelper
onClickOpenConnectionForm={() => setShowConnectionForm(true)}
/>
<AtlasCta />
</div>
);
Expand Down
8 changes: 8 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ module.exports = (env, argv) => {
buffer: require.resolve('buffer'),
crypto: require.resolve('crypto-browserify'),
path: require.resolve('path-browserify'),
// We don't want to bundle the mongodb driver code with the webview.
Anemy marked this conversation as resolved.
Show resolved Hide resolved
// There's a chance in the future that one of the dependencies
// like connection-form will accidentally use this as a dependency,
// when that happens the webpack with fail asking for a lot of
// polyfills. Instead of adding the polyfills we should
// update the upstream usage and, where applicable, prevent future
// regressions with lint rules.
mongodb: false,
},
},
module: {
Expand Down
Loading