From c78f03a0d988fc824812be32a625c9d3cc8fcf05 Mon Sep 17 00:00:00 2001 From: Anemy Date: Mon, 24 Jan 2022 13:54:20 -0500 Subject: [PATCH 1/6] Show new save connection edit modal from connect-form in sidebar --- .../favorite-button/favorite-button.jsx | 50 ++++++ .../favorite-button.module.less} | 2 +- .../favorite-button.spec.js} | 18 +- .../src/components/favorite-button/index.js | 2 + .../src/components/is-favorite-pill/index.js | 2 - .../is-favorite-pill/is-favorite-pill.jsx | 55 ------ .../sidebar-instance/sidebar-instance.jsx | 158 +++++++++--------- .../src/components/sidebar/sidebar.jsx | 5 - packages/compass-sidebar/src/modules/index.js | 9 +- .../src/modules/is-modal-visible.js | 41 ----- .../src/modules/is-modal-visible.spec.js | 41 ----- 11 files changed, 142 insertions(+), 241 deletions(-) create mode 100644 packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx rename packages/compass-sidebar/src/components/{is-favorite-pill/is-favorite-pill.module.less => favorite-button/favorite-button.module.less} (95%) rename packages/compass-sidebar/src/components/{is-favorite-pill/is-favorite-pill.spec.js => favorite-button/favorite-button.spec.js} (74%) create mode 100644 packages/compass-sidebar/src/components/favorite-button/index.js delete mode 100644 packages/compass-sidebar/src/components/is-favorite-pill/index.js delete mode 100644 packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.jsx delete mode 100644 packages/compass-sidebar/src/modules/is-modal-visible.js delete mode 100644 packages/compass-sidebar/src/modules/is-modal-visible.spec.js diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx new file mode 100644 index 00000000000..7aeccbf770e --- /dev/null +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx @@ -0,0 +1,50 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import FontAwesome from 'react-fontawesome'; + +import styles from './favorite-button.module.less'; + +const FavoriteButton = ({ + favoriteOptions, + toggleIsFavoriteModalVisible +}) => { + /** + * Shows modal when the favorite pill is clicked. + * + * @param {Object} evt - The click event. + */ + // function clickFavoritePill(evt) { + // evt.preventDefault(); + // evt.stopPropagation(); + // this.props.toggleIsModalVisible(true); + // } + + const isFavorite = !!favoriteOptions; + const fontAwesomeName = isFavorite ? 'star' : 'star-o'; + const hex = favoriteOptions?.color; + const style = { + backgroundColor: hex || '#243642', + color: isFavorite ? '#ffffff' : '#88989a' + }; + + return ( +
+ +
+ ); +}; + +FavoriteButton.displayName = 'FavoriteButton'; +FavoriteButton.propTypes = { + // Can be undefined. See ConnectionFavoriteOptions of ConnectionInfo. + favoriteOptions: PropTypes.object, + toggleIsFavoriteModalVisible: PropTypes.func.isRequired +}; + +export default FavoriteButton; diff --git a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.module.less b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less similarity index 95% rename from packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.module.less rename to packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less index 9b17e074741..8e460d4a482 100644 --- a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.module.less +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less @@ -1,4 +1,4 @@ -.is-favorite-pill { +.favorite-button { font-size: 11px; padding: 0px 0px 12px 36px; align-items: center; diff --git a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.spec.js b/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js similarity index 74% rename from packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.spec.js rename to packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js index e73d793ec32..810425ecad3 100644 --- a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.spec.js +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js @@ -1,10 +1,10 @@ import React from 'react'; import { shallow } from 'enzyme'; -import IsFavoritePill from './is-favorite-pill'; +import FavoriteButton from './favorite-button'; -import styles from './is-favorite-pill.module.less'; +import styles from './favorite-button.module.less'; -describe('IsFavoritePill [Component]', () => { +describe('FavoriteButton [Component]', () => { context('when it is a new connection', () => { const connectionModel = { connection: { @@ -20,7 +20,7 @@ describe('IsFavoritePill [Component]', () => { beforeEach(() => { component = shallow( - {}} connectionModel={connectionModel} isSidebarCollapsed={isSidebarCollapsed} /> @@ -32,8 +32,8 @@ describe('IsFavoritePill [Component]', () => { }); it('displays the the default pill', () => { - expect(component.find(`.${styles['is-favorite-pill']}`)).to.be.present(); - expect(component.find(`.${styles['is-favorite-pill-text']}`)).to.be.present(); + expect(component.find(`.${styles['favorite-button']}`)).to.be.present(); + expect(component.find(`.${styles['favorite-button-text']}`)).to.be.present(); expect(component.find('FontAwesome[name="star-o"]')).to.be.present(); }); }); @@ -53,7 +53,7 @@ describe('IsFavoritePill [Component]', () => { beforeEach(() => { component = shallow( - {}} connectionModel={connectionModel} isSidebarCollapsed={isSidebarCollapsed} /> @@ -65,8 +65,8 @@ describe('IsFavoritePill [Component]', () => { }); it('displays the the filled with no color pill', () => { - expect(component.find(`.${styles['is-favorite-pill']}`)).to.be.present(); - expect(component.find(`.${styles['is-favorite-pill-text']}`)).to.be.present(); + expect(component.find(`.${styles['favorite-button']}`)).to.be.present(); + expect(component.find(`.${styles['favorite-button-text']}`)).to.be.present(); expect(component.find('FontAwesome[name="star"]')).to.be.present(); }); }); diff --git a/packages/compass-sidebar/src/components/favorite-button/index.js b/packages/compass-sidebar/src/components/favorite-button/index.js new file mode 100644 index 00000000000..3f77e52ae93 --- /dev/null +++ b/packages/compass-sidebar/src/components/favorite-button/index.js @@ -0,0 +1,2 @@ +import FavoriteButton from './favorite-button'; +export default FavoriteButton; diff --git a/packages/compass-sidebar/src/components/is-favorite-pill/index.js b/packages/compass-sidebar/src/components/is-favorite-pill/index.js deleted file mode 100644 index d04c31518ac..00000000000 --- a/packages/compass-sidebar/src/components/is-favorite-pill/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import IsFavoritePill from './is-favorite-pill'; -export default IsFavoritePill; diff --git a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.jsx b/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.jsx deleted file mode 100644 index 5111148091f..00000000000 --- a/packages/compass-sidebar/src/components/is-favorite-pill/is-favorite-pill.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import FontAwesome from 'react-fontawesome'; - -import styles from './is-favorite-pill.module.less'; - -/** - * The component for is favorite pill. - */ -class IsFavoritePill extends PureComponent { - static displayName = 'IsFavoritePill'; - static propTypes = { - connectionModel: PropTypes.object.isRequired, - toggleIsModalVisible: PropTypes.func.isRequired - } - - /** - * Shows modal when the favorite pill is clicked. - * - * @param {Object} evt - The click event. - */ - clickFavoritePill(evt) { - evt.preventDefault(); - evt.stopPropagation(); - this.props.toggleIsModalVisible(true); - } - - /** - * Renders the component. - * - * @returns {Component} The component. - */ - render() { - const isFavorite = this.props.connectionModel.connection.isFavorite; - const fontAwesomeName = isFavorite ? 'star' : 'star-o'; - const hex = this.props.connectionModel.connection.color; - const style = { - backgroundColor: hex || '#243642', - color: isFavorite ? '#ffffff' : '#88989a' - }; - - return ( -
- - -  FAVORITE - -
- ); - } -} - -export default IsFavoritePill; diff --git a/packages/compass-sidebar/src/components/sidebar-instance/sidebar-instance.jsx b/packages/compass-sidebar/src/components/sidebar-instance/sidebar-instance.jsx index 1094322862b..3b3d732fadb 100644 --- a/packages/compass-sidebar/src/components/sidebar-instance/sidebar-instance.jsx +++ b/packages/compass-sidebar/src/components/sidebar-instance/sidebar-instance.jsx @@ -1,94 +1,92 @@ -import React, { PureComponent } from 'react'; +import React, { useCallback, useState } from 'react'; import PropTypes from 'prop-types'; +import { SaveConnectionModal } from '@mongodb-js/connect-form'; + import SidebarInstanceStats from '../sidebar-instance-stats'; import SidebarInstanceDetails from '../sidebar-instance-details'; import NonGenuineWarningPill from '../non-genuine-warning-pill'; -import IsFavoritePill from '../is-favorite-pill'; -import { FavoriteModal } from '@mongodb-js/compass-connect'; +import FavoriteButton from '../favorite-button'; import styles from './sidebar-instance.module.less'; -class SidebarInstance extends PureComponent { - static displayName = 'SidebarInstance'; - static propTypes = { - instance: PropTypes.object, - databases: PropTypes.array, - isExpanded: PropTypes.bool.isRequired, - isGenuineMongoDB: PropTypes.bool.isRequired, - toggleIsDetailsExpanded: PropTypes.func.isRequired, - globalAppRegistryEmit: PropTypes.func.isRequired, - detailsPlugins: PropTypes.array.isRequired, - connectionModel: PropTypes.object, - toggleIsModalVisible: PropTypes.func.isRequired, - isModalVisible: PropTypes.bool.isRequired, - saveFavorite: PropTypes.func.isRequired - }; +export const SidebarInstance = ({ + instance, + databases, + isExpanded, + isGenuineMongoDB, + toggleIsDetailsExpanded, + globalAppRegistryEmit, + detailsPlugins, + connectionModel, + saveFavorite +}) => { + const [ isFavoriteModalVisible, setIsFavoriteModalVisible ] = useState(false); /** - * Closes the favorite modal. - */ - closeFavoriteModal() { - this.props.toggleIsModalVisible(false); - } + * Saves the current connection to favorites. + * + * @param {String} name - The favorite name. + * @param {String} color - The favorite color. + */ - /** - * Saves the current connection to favorites. - * - * @param {String} name - The favorite name. - * @param {String} color - The favorite color. - */ - saveFavorite(name, color) { - this.props.saveFavorite(this.props.connectionModel.connection, name, color); - this.props.toggleIsModalVisible(false); - } + // (name, color) + const onClickSaveFavorite = useCallback((connectionInfo) => { + console.log('save!', connectionInfo); + // saveFavorite(connectionModel.connection, name, color); + setIsFavoriteModalVisible(false); + }, [connectionModel, saveFavorite, setIsFavoriteModalVisible]); - /** - * Renders the favorite modal. - * - * @returns {React.Component} - */ - renderFavoriteModal() { - if (this.props.isModalVisible) { - return ( - - ); - } - } + return ( +
+ + setIsFavoriteModalVisible( + !isFavoriteModalVisible + )} + /> + setIsFavoriteModalVisible(false)} + onSaveClicked={(favoriteInfo) => onClickSaveFavorite(favoriteInfo)} + /> + + +
+ ); +}; - /** - * Renders the SidebarInstance component. - * - * @returns {React.Component} - */ - render() { - return ( -
- - - {this.renderFavoriteModal()} - - -
- ); - } -} +SidebarInstance.displayName = 'SidebarInstance'; +SidebarInstance.propTypes = { + instance: PropTypes.object, + databases: PropTypes.array, + isExpanded: PropTypes.bool.isRequired, + isGenuineMongoDB: PropTypes.bool.isRequired, + toggleIsDetailsExpanded: PropTypes.func.isRequired, + globalAppRegistryEmit: PropTypes.func.isRequired, + detailsPlugins: PropTypes.array.isRequired, + connectionModel: PropTypes.object, + toggleIsModalVisible: PropTypes.func.isRequired, + isModalVisible: PropTypes.bool.isRequired, + saveFavorite: PropTypes.func.isRequired +}; export default SidebarInstance; diff --git a/packages/compass-sidebar/src/components/sidebar/sidebar.jsx b/packages/compass-sidebar/src/components/sidebar/sidebar.jsx index 648125673e7..275f123ed06 100644 --- a/packages/compass-sidebar/src/components/sidebar/sidebar.jsx +++ b/packages/compass-sidebar/src/components/sidebar/sidebar.jsx @@ -16,7 +16,6 @@ import { toggleIsDetailsExpanded } from '../../modules/is-details-expanded'; import { toggleIsGenuineMongoDBVisible } from '../../modules/is-genuine-mongodb-visible'; import { changeFilterRegex } from '../../modules/databases'; import { openLink } from '../../modules/link'; -import { toggleIsModalVisible } from '../../modules/is-modal-visible'; import { saveFavorite } from '../../modules/connection-model'; import { NavigationItems } from './navigation-items'; @@ -186,8 +185,6 @@ class Sidebar extends PureComponent { toggleIsDetailsExpanded={this.props.toggleIsDetailsExpanded} globalAppRegistryEmit={this.props.globalAppRegistryEmit} connectionModel={this.props.connectionModel} - toggleIsModalVisible={this.props.toggleIsModalVisible} - isModalVisible={this.props.isModalVisible} saveFavorite={this.props.saveFavorite} /> )} @@ -241,7 +238,6 @@ const mapStateToProps = (state) => ({ isGenuineMongoDB: state.isGenuineMongoDB, isGenuineMongoDBVisible: state.isGenuineMongoDBVisible, connectionModel: state.connectionModel, - isModalVisible: state.isModalVisible, }); /** @@ -256,7 +252,6 @@ const MappedSidebar = connect( changeFilterRegex, openLink, globalAppRegistryEmit, - toggleIsModalVisible, saveFavorite }, )(Sidebar); diff --git a/packages/compass-sidebar/src/modules/index.js b/packages/compass-sidebar/src/modules/index.js index a54c76d22c8..10cf8e516fc 100644 --- a/packages/compass-sidebar/src/modules/index.js +++ b/packages/compass-sidebar/src/modules/index.js @@ -30,9 +30,6 @@ import isGenuineMongoDBVisible, { import connectionModel, { INITIAL_STATE as CONNECTION_MODEL_IS } from './connection-model'; -import isModalVisible, { - INITIAL_STATE as MODAL_VISIBLE_IS -} from './is-modal-visible'; /** * The reducer. @@ -48,8 +45,7 @@ const reducer = combineReducers({ isGenuineMongoDB, isGenuineMongoDBVisible, isDataLake, - connectionModel, - isModalVisible + connectionModel }); /** @@ -72,8 +68,7 @@ const rootReducer = (state, action) => { isGenuineMongoDB: GENUINE_IS, isGenuineMongoDBVisible: IS_VISIBLE_IS, isDataLake: DL_INITIAL_STATE, - connectionModel: CONNECTION_MODEL_IS, - isModalVisible: MODAL_VISIBLE_IS + connectionModel: CONNECTION_MODEL_IS }; } return reducer(state, action); diff --git a/packages/compass-sidebar/src/modules/is-modal-visible.js b/packages/compass-sidebar/src/modules/is-modal-visible.js deleted file mode 100644 index b425812be6b..00000000000 --- a/packages/compass-sidebar/src/modules/is-modal-visible.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The prefix. - */ -const PREFIX = 'sidebar/is-modal-visible'; - -/** - * Toggle is modal visible action. - */ -export const TOGGLE_IS_MODAL_VISIBLE = `${PREFIX}/TOGGLE_IS_MODAL_VISIBLE`; - -/** - * The initial state of the is modal visible attribute. - */ -export const INITIAL_STATE = false; - -/** - * Reducer function for handle state change of the is modal visible attribute. - * - * @param {String} state - The state. - * @param {Object} action - The action. - * - * @returns {String} The new state. - */ -export default function reducer(state = INITIAL_STATE, action) { - if (action.type === TOGGLE_IS_MODAL_VISIBLE) { - return action.isModalVisible; - } - return state; -} - -/** - * Toggle is modal visible action creator. - * - * @param {Boolean} isModalVisible - The is modal visible attribute. - * - * @returns {Object} The action. - */ -export const toggleIsModalVisible = (isModalVisible) => ({ - type: TOGGLE_IS_MODAL_VISIBLE, - isModalVisible -}); diff --git a/packages/compass-sidebar/src/modules/is-modal-visible.spec.js b/packages/compass-sidebar/src/modules/is-modal-visible.spec.js deleted file mode 100644 index 0450c92e9c7..00000000000 --- a/packages/compass-sidebar/src/modules/is-modal-visible.spec.js +++ /dev/null @@ -1,41 +0,0 @@ -import reducer, { - INITIAL_STATE, - TOGGLE_IS_MODAL_VISIBLE, - toggleIsModalVisible -} from './is-modal-visible'; - -describe('is-modal-visible module', () => { - describe('reducer', () => { - context('when the action is toggleIsModalVisible', () => { - it('returns the new state', () => { - expect(reducer(undefined, toggleIsModalVisible(true))).to.equal(true); - }); - }); - - context('when an action is not provided', () => { - it('returns the default state', () => { - expect(reducer(undefined, {})).to.equal(INITIAL_STATE); - }); - }); - }); - - describe('#toggleIsModalVisible', () => { - context('when it is a data lake', () => { - it('sets true in the action', () => { - expect(toggleIsModalVisible(true)).to.deep.equal({ - type: TOGGLE_IS_MODAL_VISIBLE, - isModalVisible: true - }); - }); - }); - - context('when it is not a data lake', () => { - it('sets false in the action', () => { - expect(toggleIsModalVisible(false)).to.deep.equal({ - type: TOGGLE_IS_MODAL_VISIBLE, - isModalVisible: false - }); - }); - }); - }); -}); From 066c10e6715abc6311528cdf6c0c0b14fd39b615 Mon Sep 17 00:00:00 2001 From: Anemy Date: Mon, 24 Jan 2022 17:22:23 -0500 Subject: [PATCH 2/6] enable saving with new favorite modal from sidebar --- package-lock.json | 12 +- packages/compass-home/src/components/home.tsx | 98 +++++++++++--- .../compass-home/src/components/workspace.tsx | 12 +- packages/compass-sidebar/karma.conf.js | 7 +- packages/compass-sidebar/package.json | 6 +- .../favorite-button/favorite-button.jsx | 28 ++-- .../favorite-button/favorite-button.spec.js | 35 ++--- .../sidebar-instance/sidebar-instance.jsx | 37 ++---- .../sidebar-title/sidebar-title.jsx | 121 ++++++++++-------- .../src/components/sidebar/sidebar.jsx | 19 +-- .../src/modules/connection-model.js | 92 ------------- .../src/modules/connection-model.spec.js | 77 ----------- packages/compass-sidebar/src/modules/index.js | 9 +- packages/compass-sidebar/src/plugin.js | 43 ++++--- packages/compass-sidebar/src/stores/store.js | 5 - .../components/sidebar-instance.spec.js | 11 +- .../renderer/components/sidebar-title.spec.js | 21 ++- .../test/renderer/components/sidebar.spec.js | 36 +++--- .../src/components/connect-form.tsx | 2 +- .../components/save-connection-modal.spec.tsx | 19 +-- .../src/components/save-connection-modal.tsx | 16 +-- 21 files changed, 291 insertions(+), 415 deletions(-) delete mode 100644 packages/compass-sidebar/src/modules/connection-model.js delete mode 100644 packages/compass-sidebar/src/modules/connection-model.spec.js diff --git a/package-lock.json b/package-lock.json index 6adbdcca674..2d62fa61630 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77221,9 +77221,9 @@ "license": "SSPL", "dependencies": { "@mongodb-js/compass-aggregations": "^8.18.1", + "@mongodb-js/compass-components": "^0.9.1", "@mongodb-js/compass-query-history": "^8.17.1", "mongodb-data-service": "^21.15.1", - "@mongodb-js/compass-components": "^0.9.1", "react": "^16.14.0", "react-dom": "^16.14.0", "react-redux": "^5.1.2", @@ -88049,11 +88049,11 @@ "@hot-loader/react-dom": "^16.9.0", "@mongodb-js/compass-app-stores": "^5.17.1", "@mongodb-js/compass-components": "^0.9.1", - "@mongodb-js/compass-connect": "^7.17.1", "@mongodb-js/compass-databases-navigation": "^0.3.1", "@mongodb-js/compass-deployment-awareness": "^11.17.1", "@mongodb-js/compass-server-version": "^5.17.1", "@mongodb-js/compass-ssh-tunnel-status": "^6.17.1", + "@mongodb-js/connect-form": "^0.4.1", "autoprefixer": "^9.4.6", "babel-loader": "^8.2.2", "chai": "^4.2.0", @@ -88135,7 +88135,7 @@ }, "peerDependencies": { "@mongodb-js/compass-components": "^0.9.1", - "@mongodb-js/compass-connect": "^7.17.1", + "@mongodb-js/connect-form": "^0.4.1", "debug": "*", "prop-types": "^15.7.2", "react": "^16.14.0", @@ -124528,8 +124528,8 @@ "version": "file:packages/compass-saved-aggregations-queries", "requires": { "@mongodb-js/compass-aggregations": "^8.18.1", - "@mongodb-js/compass-query-history": "^8.17.1", "@mongodb-js/compass-components": "^0.9.1", + "@mongodb-js/compass-query-history": "^8.17.1", "@mongodb-js/eslint-config-compass": "^0.5.0", "@mongodb-js/mocha-config-compass": "^0.7.0", "@mongodb-js/prettier-config-compass": "^0.4.0", @@ -124548,7 +124548,7 @@ "eslint": "^7.25.0", "hadron-app-registry": "^8.7.0", "mocha": "^8.4.0", - "mongodb-data-service": "*", + "mongodb-data-service": "^21.15.1", "nyc": "^15.1.0", "prettier": "2.3.2", "react": "^16.14.0", @@ -132695,11 +132695,11 @@ "@hot-loader/react-dom": "^16.9.0", "@mongodb-js/compass-app-stores": "^5.17.1", "@mongodb-js/compass-components": "^0.9.1", - "@mongodb-js/compass-connect": "^7.17.1", "@mongodb-js/compass-databases-navigation": "^0.3.1", "@mongodb-js/compass-deployment-awareness": "^11.17.1", "@mongodb-js/compass-server-version": "^5.17.1", "@mongodb-js/compass-ssh-tunnel-status": "^6.17.1", + "@mongodb-js/connect-form": "^0.4.1", "@mongodb-js/mongodb-redux-common": "^1.7.0", "autoprefixer": "^9.4.6", "babel-loader": "^8.2.2", diff --git a/packages/compass-home/src/components/home.tsx b/packages/compass-home/src/components/home.tsx index fca12c810f1..abf9390c65e 100644 --- a/packages/compass-home/src/components/home.tsx +++ b/packages/compass-home/src/components/home.tsx @@ -5,9 +5,12 @@ import { DataService, convertConnectionInfoToModel, getConnectionTitle, + ConnectionStorage, } from 'mongodb-data-service'; import toNS from 'mongodb-ns'; import Connections from '@mongodb-js/compass-connections'; +import ipc from 'hadron-ipc'; +import debugModule from 'debug'; import Workspace from './workspace'; import Namespace from '../types/namespace'; @@ -17,7 +20,8 @@ import { useAppRegistryRole, } from '../contexts/app-registry-context'; import updateTitle from '../modules/update-title'; -import ipc from 'hadron-ipc'; + +const debug = debugModule('mongodb-compass:home:home'); const homeViewStyles = css({ display: 'flex', @@ -41,24 +45,31 @@ const defaultNS: Namespace = { collection: '', }; -type State = { - connectionTitle: string; - isConnected: boolean; - namespace: Namespace; -}; +type State = + | { + connectionInfo: undefined; + isConnected: false; + namespace: Namespace; + } + | { + connectionInfo: ConnectionInfo; + isConnected: true; + namespace: Namespace; + }; -const initialState = { - connectionTitle: '', - isConnected: false, +const initialState: State = { + connectionInfo: undefined, namespace: defaultNS, + isConnected: false, }; type Action = | { type: 'connected'; - connectionTitle: string; + connectionInfo: ConnectionInfo; } | { type: 'disconnected' } + | { type: 'update-connection-info'; connectionInfo: ConnectionInfo } | { type: 'update-namespace'; namespace: Namespace }; function reducer(state: State, action: Action): State { @@ -66,9 +77,17 @@ function reducer(state: State, action: Action): State { case 'connected': return { ...state, + connectionInfo: action.connectionInfo, namespace: { ...defaultNS }, isConnected: true, - connectionTitle: action.connectionTitle, + }; + case 'update-connection-info': + return { + ...state, + isConnected: true, + connectionInfo: { + ...action.connectionInfo, + }, }; case 'update-namespace': return { @@ -89,13 +108,35 @@ function hideCollectionSubMenu() { void ipc.ipcRenderer?.call('window:hide-collection-submenu'); } -function Home({ appName }: { appName: string }): React.ReactElement | null { +async function saveConnectionInfo( + connectionInfo: ConnectionInfo, + connectionStorage: ConnectionStorage +) { + try { + await connectionStorage.save(connectionInfo); + debug(`saved connection with id ${connectionInfo.id || ''}`); + } catch (err) { + debug( + `error saving connection with id ${connectionInfo.id || ''}: ${ + (err as Error).message + }` + ); + } +} + +function Home({ + appName, + connectionStorage = new ConnectionStorage(), +}: { + appName: string; + connectionStorage: ConnectionStorage; +}): React.ReactElement | null { const appRegistry = useAppRegistryContext(); const connectRole = useAppRegistryRole(AppRegistryRoles.APPLICATION_CONNECT); const connectedDataService = useRef(); const showNewConnectForm = process.env.USE_NEW_CONNECT_FORM === 'true'; - const [{ connectionTitle, isConnected, namespace }, dispatch] = useReducer( + const [{ connectionInfo, isConnected, namespace }, dispatch] = useReducer( reducer, { ...initialState } ); @@ -108,7 +149,7 @@ function Home({ appName }: { appName: string }): React.ReactElement | null { connectedDataService.current = ds; dispatch({ type: 'connected', - connectionTitle: getConnectionTitle(connectionInfo) || '', + connectionInfo, }); } @@ -133,6 +174,19 @@ function Home({ appName }: { appName: string }): React.ReactElement | null { ); } + const updateAndSaveConnectionInfo = useCallback( + (newConnectionInfo: ConnectionInfo) => { + // Currently we silently fail if saving the favorite fails. + void saveConnectionInfo(newConnectionInfo, connectionStorage); + + dispatch({ + type: 'update-connection-info', + connectionInfo: newConnectionInfo, + }); + }, + [connectionStorage] + ); + function onSelectDatabase(ns: string) { hideCollectionSubMenu(); dispatch({ @@ -178,10 +232,10 @@ function Home({ appName }: { appName: string }): React.ReactElement | null { }, [appName]); useEffect(() => { - if (isConnected) { - updateTitle(appName, connectionTitle, namespace); + if (isConnected && connectionInfo) { + updateTitle(appName, getConnectionTitle(connectionInfo) || '', namespace); } - }, [isConnected, appName, connectionTitle, namespace]); + }, [isConnected, appName, connectionInfo, namespace]); useEffect(() => { async function handleDisconnectClicked() { @@ -247,8 +301,14 @@ function Home({ appName }: { appName: string }): React.ReactElement | null { }; }, [appRegistry, onDataServiceDisconnected]); - if (isConnected) { - return ; + if (isConnected && connectionInfo) { + return ( + + ); } if (showNewConnectForm) { diff --git a/packages/compass-home/src/components/workspace.tsx b/packages/compass-home/src/components/workspace.tsx index 5d426520848..07d5c390e9d 100644 --- a/packages/compass-home/src/components/workspace.tsx +++ b/packages/compass-home/src/components/workspace.tsx @@ -9,6 +9,7 @@ import { useAppRegistryComponent, useAppRegistryRole, } from '../contexts/app-registry-context'; +import { ConnectionInfo } from 'mongodb-data-service'; const homeViewStyles = css({ display: 'flex', @@ -36,9 +37,13 @@ const homePageContentStyles = css({ }); export default function Workspace({ + connectionInfo, namespace, + updateAndSaveConnectionInfo, }: { + connectionInfo: ConnectionInfo; namespace: Namespace; + updateAndSaveConnectionInfo: (connectionInfo: ConnectionInfo) => void; }): React.ReactElement { const SidebarComponent = useAppRegistryComponent( AppRegistryComponents.SIDEBAR_COMPONENT @@ -56,7 +61,12 @@ export default function Workspace({
- {SidebarComponent && } + {SidebarComponent && ( + + )} {FindInPage && } {globalModals && diff --git a/packages/compass-sidebar/karma.conf.js b/packages/compass-sidebar/karma.conf.js index 08ce1816432..222a54c5087 100644 --- a/packages/compass-sidebar/karma.conf.js +++ b/packages/compass-sidebar/karma.conf.js @@ -6,7 +6,7 @@ module.exports = (config) => { singleRun: true, files: ['test/karma-setup.js'], reporters: ['mocha'], - preprocessors: { 'test/karma-setup.js': ['webpack', 'sourcemap', 'electron'] }, + preprocessors: { 'test/karma-setup.js': ['webpack', 'sourcemap'] }, browsers: ['Compass'], frameworks: ['mocha', 'chai', 'sinon', 'chai-sinon'], webpack: webpackConfig, @@ -28,9 +28,12 @@ module.exports = (config) => { customLaunchers: { Compass: { base: 'Electron', + flags: ['--no-sandbox'], browserWindowOptions: { webPreferences: { - nodeIntegration: true + nodeIntegration: true, + contextIsolation: false, + enableRemoteModule: true } } } diff --git a/packages/compass-sidebar/package.json b/packages/compass-sidebar/package.json index 57d1b9350b4..08349b78b71 100644 --- a/packages/compass-sidebar/package.json +++ b/packages/compass-sidebar/package.json @@ -17,7 +17,7 @@ "start:watch": "npm run clean && webpack --config ./config/webpack.watch.config.js", "test": "cross-env NODE_ENV=test mocha-webpack \"./src/**/*.spec.js\"", "test:watch": "cross-env NODE_ENV=test mocha-webpack \"./src/**/*.spec.js\" --watch", - "test:karma": "npm run prestart && xvfb-maybe cross-env NODE_ENV=test karma start", + "test:karma": "xvfb-maybe cross-env NODE_ENV=test karma start", "cover": "nyc npm run test", "test-check-ci": "npm run cover && npm run test:karma && npm run compile && npm run check", "check": "npm run lint && npm run depcheck", @@ -30,7 +30,7 @@ "license": "SSPL", "peerDependencies": { "@mongodb-js/compass-components": "^0.9.1", - "@mongodb-js/compass-connect": "^7.17.1", + "@mongodb-js/connect-form": "^0.4.1", "debug": "*", "prop-types": "^15.7.2", "react": "^16.14.0", @@ -51,11 +51,11 @@ "@hot-loader/react-dom": "^16.9.0", "@mongodb-js/compass-app-stores": "^5.17.1", "@mongodb-js/compass-components": "^0.9.1", - "@mongodb-js/compass-connect": "^7.17.1", "@mongodb-js/compass-databases-navigation": "^0.3.1", "@mongodb-js/compass-deployment-awareness": "^11.17.1", "@mongodb-js/compass-server-version": "^5.17.1", "@mongodb-js/compass-ssh-tunnel-status": "^6.17.1", + "@mongodb-js/connect-form": "^0.4.1", "autoprefixer": "^9.4.6", "babel-loader": "^8.2.2", "chai": "^4.2.0", diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx index 7aeccbf770e..40b08e098f9 100644 --- a/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx @@ -1,6 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import FontAwesome from 'react-fontawesome'; +import { + mergeProps, + useFocusRing +} from '@mongodb-js/compass-components'; import styles from './favorite-button.module.less'; @@ -8,17 +12,6 @@ const FavoriteButton = ({ favoriteOptions, toggleIsFavoriteModalVisible }) => { - /** - * Shows modal when the favorite pill is clicked. - * - * @param {Object} evt - The click event. - */ - // function clickFavoritePill(evt) { - // evt.preventDefault(); - // evt.stopPropagation(); - // this.props.toggleIsModalVisible(true); - // } - const isFavorite = !!favoriteOptions; const fontAwesomeName = isFavorite ? 'star' : 'star-o'; const hex = favoriteOptions?.color; @@ -27,11 +20,20 @@ const FavoriteButton = ({ color: isFavorite ? '#ffffff' : '#88989a' }; + const focusRingProps = useFocusRing(); + const buttonProps = mergeProps({ + type: 'button', + 'aria-label': 'Edit saved connection', + title: 'Edit saved connection', + onClick: () => toggleIsFavoriteModalVisible(), + className: styles['favorite-button-text'], + style + }, focusRingProps); + return (
this.onNavigationItemClick()} /> @@ -184,8 +181,8 @@ class Sidebar extends PureComponent { isGenuineMongoDB={this.props.isGenuineMongoDB} toggleIsDetailsExpanded={this.props.toggleIsDetailsExpanded} globalAppRegistryEmit={this.props.globalAppRegistryEmit} - connectionModel={this.props.connectionModel} - saveFavorite={this.props.saveFavorite} + connectionInfo={this.props.connectionInfo} + updateConnectionInfo={this.props.updateConnectionInfo} /> )} {process.env.COMPASS_SHOW_YOUR_QUERIES_TAB === 'true' && ( @@ -236,8 +233,7 @@ const mapStateToProps = (state) => ({ detailsPlugins: state.detailsPlugins, isDataLake: state.isDataLake, isGenuineMongoDB: state.isGenuineMongoDB, - isGenuineMongoDBVisible: state.isGenuineMongoDBVisible, - connectionModel: state.connectionModel, + isGenuineMongoDBVisible: state.isGenuineMongoDBVisible }); /** @@ -251,8 +247,7 @@ const MappedSidebar = connect( toggleIsGenuineMongoDBVisible, changeFilterRegex, openLink, - globalAppRegistryEmit, - saveFavorite + globalAppRegistryEmit }, )(Sidebar); diff --git a/packages/compass-sidebar/src/modules/connection-model.js b/packages/compass-sidebar/src/modules/connection-model.js deleted file mode 100644 index f2c1a63ce16..00000000000 --- a/packages/compass-sidebar/src/modules/connection-model.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Change connection action name. - */ -export const CHANGE_CONNECTION = 'sidebar/connection/CHANGE_CONNECTION'; - -/** - * Save favorite action name. - */ -export const SAVE_FAVORITE = 'sidebar/connection/SAVE_FAVORITE'; - -/** - * The initial state of the connection. - */ -export const INITIAL_STATE = { connection: {} }; - -/** - * Changes the connection. - * - * @param {Object} state - The state. - * @param {Object} action - The action. - * - * @returns {Object} The new state. - */ -const doChangeConnection = (state, action) => { - return { ...state, connection: action.connection }; -}; - -/** - * Saves the favorite. - * - * @param {Object} state - The state. - * @param {Object} action - The action. - * - * @returns {Object} The new state. - */ -const doSaveFavorite = (state, action) => { - action.connection.set({ isFavorite: true, name: action.name, color: action.color }); - action.connection.save(); - - return { ...state, connection: action.connection }; -}; - -/** - * To not have a huge switch statement in the reducer. - */ -const MAPPINGS = { - [CHANGE_CONNECTION]: doChangeConnection, - [SAVE_FAVORITE]: doSaveFavorite -}; - -/** - * Reducer function for handle state changes. - * - * @param {String} state - The status state. - * @param {Object} action - The action. - * - * @returns {String} The new state. - */ -export default function reducer(state = INITIAL_STATE, action) { - const fn = MAPPINGS[action.type]; - - return fn ? fn(state, action) : state; -} - -/** - * Change connection action creator. - * - * @param {Connection} connection - The connection. - * - * @returns {Object} The action. - */ -export const changeConnection = (connection) => ({ - type: CHANGE_CONNECTION, - connection -}); - -/** - * Save favorite action creator. - * - * @param {Object} connection - The connection. - * @param {String} name - The connection name. - * @param {String} color - The connection color. - * - * @returns {Object} The action. - */ -export const saveFavorite = (connection, name, color) => ({ - type: SAVE_FAVORITE, - connection, - name, - color -}); - diff --git a/packages/compass-sidebar/src/modules/connection-model.spec.js b/packages/compass-sidebar/src/modules/connection-model.spec.js deleted file mode 100644 index cf561836bfb..00000000000 --- a/packages/compass-sidebar/src/modules/connection-model.spec.js +++ /dev/null @@ -1,77 +0,0 @@ -import reducer, { - INITIAL_STATE, - CHANGE_CONNECTION, - SAVE_FAVORITE, - changeConnection, - saveFavorite -} from './connection-model'; - -describe('connection module', () => { - const connection = { - hostname: '127.0.0.1', - port: 27017, - isFavorite: false, - name: 'Local', - save: () => {}, - destroy: () => {}, - set(favorite) { - this.name = favorite.name; - this.color = favorite.color; - this.isFavorite = favorite.isFavorite; - } - }; - - describe('reducer', () => { - context('when the action is changeConnection', () => { - it('returns the new state', () => { - expect(reducer(undefined, changeConnection(connection))).to.deep.equal({ - connection - }); - }); - }); - - context('when the action is saveFavorite', () => { - it('returns the new state', () => { - const newConnection = saveFavorite(connection, 'My Favorite', '#d4366e'); - const state = reducer(undefined, newConnection); - - expect(state.connection.name).to.equal('My Favorite'); - expect(state.connection.color).to.equal('#d4366e'); - expect(state.connection.isFavorite).to.equal(true); - }); - }); - - context('when an action is not provided', () => { - it('returns the default state', () => { - expect(reducer(undefined, {})).to.equal(INITIAL_STATE); - }); - }); - }); - - describe('#changeConnection', () => { - context('when the connection is a favourite', () => { - it('sets the favourite name in the action', () => { - const favourite = { ...connection, isFavorite: true, name: 'New name' }; - - expect(changeConnection(favourite)).to.deep.equal({ - type: CHANGE_CONNECTION, - connection: favourite - }); - }); - }); - - context('when the favourite connection should be updated', () => { - it('sets the favourite name, color and isFavorite flag', () => { - const name = 'Simple connection'; - const color = '#59c1e2'; - - expect(saveFavorite(connection, name, color)).to.deep.equal({ - type: SAVE_FAVORITE, - connection, - name, - color - }); - }); - }); - }); -}); diff --git a/packages/compass-sidebar/src/modules/index.js b/packages/compass-sidebar/src/modules/index.js index 10cf8e516fc..069b29feeae 100644 --- a/packages/compass-sidebar/src/modules/index.js +++ b/packages/compass-sidebar/src/modules/index.js @@ -27,9 +27,6 @@ import isGenuineMongoDB, { import isGenuineMongoDBVisible, { INITIAL_STATE as IS_VISIBLE_IS } from './is-genuine-mongodb-visible'; -import connectionModel, { - INITIAL_STATE as CONNECTION_MODEL_IS -} from './connection-model'; /** * The reducer. @@ -44,8 +41,7 @@ const reducer = combineReducers({ isWritable, isGenuineMongoDB, isGenuineMongoDBVisible, - isDataLake, - connectionModel + isDataLake }); /** @@ -67,8 +63,7 @@ const rootReducer = (state, action) => { isWritable: IS_WRITABLE_INITIAL_STATE, isGenuineMongoDB: GENUINE_IS, isGenuineMongoDBVisible: IS_VISIBLE_IS, - isDataLake: DL_INITIAL_STATE, - connectionModel: CONNECTION_MODEL_IS + isDataLake: DL_INITIAL_STATE }; } return reducer(state, action); diff --git a/packages/compass-sidebar/src/plugin.js b/packages/compass-sidebar/src/plugin.js index 85ba456df2e..c5d46893357 100644 --- a/packages/compass-sidebar/src/plugin.js +++ b/packages/compass-sidebar/src/plugin.js @@ -1,24 +1,35 @@ -import React, { Component } from 'react'; +import React from 'react'; import { Provider } from 'react-redux'; +import PropTypes from 'prop-types'; import Sidebar from './components/sidebar'; import store from './stores'; -class Plugin extends Component { - static displayName = 'SidebarPlugin'; - /** - * Connect the Plugin to the store and render. - * - * @returns {React.Component} The rendered component. - */ - render() { - return ( - - - - ); - } +/** + * Connect the Plugin to the store and render. + * + * @returns {React.Component} The rendered component. + */ +function SidebarPlugin({ + connectionInfo, + updateAndSaveConnectionInfo +}) { + return ( + + + + ); } -export default Plugin; +SidebarPlugin.displayName = 'SidebarPlugin'; +SidebarPlugin.propTypes = { + connectionInfo: PropTypes.object.isRequired, + updateAndSaveConnectionInfo: PropTypes.func.isRequired +}; + + +export default SidebarPlugin; diff --git a/packages/compass-sidebar/src/stores/store.js b/packages/compass-sidebar/src/stores/store.js index e8d7d3df975..25ee2253b98 100644 --- a/packages/compass-sidebar/src/stores/store.js +++ b/packages/compass-sidebar/src/stores/store.js @@ -13,7 +13,6 @@ import { toggleIsDataLake } from '../modules/is-data-lake'; import { loadDetailsPlugins } from '../modules/details-plugins'; import { toggleIsGenuineMongoDB } from '../modules/is-genuine-mongodb'; import { toggleIsGenuineMongoDBVisible } from '../modules/is-genuine-mongodb-visible'; -import { changeConnection } from '../modules/connection-model'; const store = createStore(reducer, applyMiddleware(thunk)); @@ -60,10 +59,6 @@ store.onActivated = (appRegistry) => { store.dispatch(loadDetailsPlugins(appRegistry)); - appRegistry.on('data-service-connected', (_, dataService, connectionInfo, legacyConnectionModel) => { - store.dispatch(changeConnection(legacyConnectionModel)); - }); - appRegistry.on('instance-destroyed', () => { onInstanceChange.cancel(); onDatabasesChange.cancel(); diff --git a/packages/compass-sidebar/test/renderer/components/sidebar-instance.spec.js b/packages/compass-sidebar/test/renderer/components/sidebar-instance.spec.js index a264aa0b923..ea9433a6e47 100644 --- a/packages/compass-sidebar/test/renderer/components/sidebar-instance.spec.js +++ b/packages/compass-sidebar/test/renderer/components/sidebar-instance.spec.js @@ -16,10 +16,13 @@ describe('SidebarInstance [Component]', () => { detailsPlugins={[]} globalAppRegistryEmit={() => {}} toggleIsDetailsExpanded={() => {}} - connectionModel={{ connection: {} }} - toggleIsModalVisible={() => {}} - saveFavorite={() => {}} - isModalVisible={false} + connectionInfo={{ + connectionOptions: { + connectionString: 'mongodb://localhost:27017' + }, + id: '123' + }} + updateConnectionInfo={() => {}} />); }); diff --git a/packages/compass-sidebar/test/renderer/components/sidebar-title.spec.js b/packages/compass-sidebar/test/renderer/components/sidebar-title.spec.js index e337629681b..149a841aa14 100644 --- a/packages/compass-sidebar/test/renderer/components/sidebar-title.spec.js +++ b/packages/compass-sidebar/test/renderer/components/sidebar-title.spec.js @@ -8,14 +8,11 @@ import { SidebarTitle as SidebarTitleClass } from '../../../src/components/sideb import styles from '../../../src/components/sidebar-title/sidebar-title.module.less'; describe('SidebarTitle [Component]', () => { - const connectionModel = { - connection: { - authStrategy: 'MONGODB', - isSrvRecord: false, - readPreference: 'primaryPreferred', - attributes: { hostanme: 'localhost' }, - isFavorite: false - } + const connectionInfo = { + connectionOptions: { + connectionString: 'mongodb://localhost:27020?readPreference=primaryPreferred' + }, + id: '123' }; context('when sidebar is collapsed', () => { @@ -27,7 +24,7 @@ describe('SidebarTitle [Component]', () => { component = shallow( ); @@ -55,7 +52,7 @@ describe('SidebarTitle [Component]', () => { component = shallow( ); @@ -83,7 +80,7 @@ describe('SidebarTitle [Component]', () => { ); @@ -112,7 +109,7 @@ describe('SidebarTitle [Component]', () => { activeNamespace={''} changeActiveNamespace={changeActiveNamespaceFake} globalAppRegistryEmit={globalAppRegistryEmit} - connectionModel={connectionModel} + connectionInfo={connectionInfo} isSidebarExpanded /> ); diff --git a/packages/compass-sidebar/test/renderer/components/sidebar.spec.js b/packages/compass-sidebar/test/renderer/components/sidebar.spec.js index 19027fb5e65..a75a3cd5f9a 100644 --- a/packages/compass-sidebar/test/renderer/components/sidebar.spec.js +++ b/packages/compass-sidebar/test/renderer/components/sidebar.spec.js @@ -8,6 +8,16 @@ import SidebarInstance from '../../../src/components/sidebar-instance'; import styles from '../../../src/components/sidebar/sidebar.module.less'; describe('Sidebar [Component]', () => { + const connectionInfo = { + connectionOptions: { + connectionString: 'mongodb://localhost:27020?readPreference=primaryPreferred' + }, + id: '123', + favorite: { + name: 'my favorite' + } + }; + describe('when rendered with the store', () => { let component; @@ -16,6 +26,8 @@ describe('Sidebar [Component]', () => { {}} + updateConnectionInfo={()=>{}} + connectionInfo={connectionInfo} /> ); @@ -31,16 +43,6 @@ describe('Sidebar [Component]', () => { }); describe('when it is open (not collapsed)', () => { - const connectionModel = { - connection: { - authStrategy: 'MONGODB', - isSrvRecord: false, - readPreference: 'primaryPreferred', - attributes: { hostanme: 'localhost' }, - isFavorite: true - } - }; - let component; let emitSpy; let saveFavoriteSpy; @@ -52,7 +54,7 @@ describe('Sidebar [Component]', () => { { isGenuineMongoDB isGenuineMongoDBVisible={false} toggleIsGenuineMongoDBVisible={()=>{}} - isModalVisible={false} openLink={() => {}} isDetailsExpanded={false} toggleIsDetailsExpanded={() => {}} @@ -79,7 +80,7 @@ describe('Sidebar [Component]', () => { filterDatabases={() => {}} changeDatabases={() => {}} changeFilterRegex={() => {}} - toggleIsModalVisible={()=>{}} + updateConnectionInfo={()=>{}} saveFavorite={saveFavoriteSpy} /> @@ -116,7 +117,8 @@ describe('Sidebar [Component]', () => { component = mount( {}} + connectionInfo={connectionInfo} /> ); @@ -148,7 +150,8 @@ describe('Sidebar [Component]', () => { component = mount( {}} + connectionInfo={connectionInfo} /> ); @@ -181,7 +184,8 @@ describe('Sidebar [Component]', () => { component = mount( {}} + connectionInfo={connectionInfo} /> ); diff --git a/packages/connect-form/src/components/connect-form.tsx b/packages/connect-form/src/components/connect-form.tsx index 713281c2d71..bf47b01040a 100644 --- a/packages/connect-form/src/components/connect-form.tsx +++ b/packages/connect-form/src/components/connect-form.tsx @@ -228,7 +228,7 @@ function ConnectForm({ } }} key={initialConnectionInfo.id} - initialConnectionInfo={initialConnectionInfo} + initialFavoriteInfo={initialConnectionInfo.favorite} /> )} diff --git a/packages/connect-form/src/components/save-connection-modal.spec.tsx b/packages/connect-form/src/components/save-connection-modal.spec.tsx index d4d1cd9b9af..73072df4ec7 100644 --- a/packages/connect-form/src/components/save-connection-modal.spec.tsx +++ b/packages/connect-form/src/components/save-connection-modal.spec.tsx @@ -25,12 +25,7 @@ describe('SaveConnectionModal Component', function () { onSaveClicked={onSaveSpy} onCancelClicked={onCancelSpy} open - initialConnectionInfo={{ - id: 'test', - connectionOptions: { - connectionString: 'pineapples', - }, - }} + initialFavoriteInfo={undefined} /> ); }); @@ -95,15 +90,9 @@ describe('SaveConnectionModal Component', function () { onSaveClicked={onSaveSpy} onCancelClicked={onCancelSpy} open - initialConnectionInfo={{ - id: 'test', - connectionOptions: { - connectionString: 'pineapples', - }, - favorite: { - name: 'pineapples', - color: '#326fde', - }, + initialFavoriteInfo={{ + name: 'pineapples', + color: '#326fde', }} /> ); diff --git a/packages/connect-form/src/components/save-connection-modal.tsx b/packages/connect-form/src/components/save-connection-modal.tsx index 8f75788efef..f6b3c6a9bed 100644 --- a/packages/connect-form/src/components/save-connection-modal.tsx +++ b/packages/connect-form/src/components/save-connection-modal.tsx @@ -5,10 +5,7 @@ import { css, spacing, } from '@mongodb-js/compass-components'; -import { - ConnectionInfo, - ConnectionFavoriteOptions, -} from 'mongodb-data-service'; +import { ConnectionFavoriteOptions } from 'mongodb-data-service'; import FormFieldContainer from './form-field-container'; import SavedConnectionColorPicker from './saved-connection-color-picker'; @@ -18,32 +15,29 @@ const connectionNameInputStyles = css({ }); function SaveConnectionModal({ - initialConnectionInfo, + initialFavoriteInfo, onCancelClicked, onSaveClicked, open, }: { - initialConnectionInfo: ConnectionInfo; + initialFavoriteInfo?: ConnectionFavoriteOptions; onCancelClicked: () => void; onSaveClicked: (favoriteInfo: ConnectionFavoriteOptions) => Promise; open: boolean; }): React.ReactElement { const [editingFavorite, setEditingFavorite] = useState({ name: '', - ...initialConnectionInfo.favorite, + ...initialFavoriteInfo, }); return ( { void onSaveClicked({ - ...initialConnectionInfo.favorite, ...editingFavorite, }); }} From ca7c7d47a56bfd2ac959db364e23e373a505109c Mon Sep 17 00:00:00 2001 From: Anemy Date: Mon, 24 Jan 2022 17:43:19 -0500 Subject: [PATCH 3/6] update tests, remove old connection model code --- .../compass-home/src/components/home.spec.tsx | 26 ++++++++++++++++--- packages/compass-home/src/components/home.tsx | 16 ++++-------- .../src/components/connections.tsx | 2 +- .../src/stores/connections-store.ts | 4 +-- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/compass-home/src/components/home.spec.tsx b/packages/compass-home/src/components/home.spec.tsx index 2b39e5e4983..4ff1df70a91 100644 --- a/packages/compass-home/src/components/home.spec.tsx +++ b/packages/compass-home/src/components/home.spec.tsx @@ -5,6 +5,7 @@ import { expect } from 'chai'; import AppRegistry from 'hadron-app-registry'; import ipc from 'hadron-ipc'; import sinon from 'sinon'; + import AppRegistryContext from '../contexts/app-registry-context'; import Home from '.'; @@ -26,9 +27,14 @@ const getComponent = (name: string) => { const createDataService = () => ({}); describe('Home [Component]', function () { + let mockConnectionStorage; + let testAppRegistry: AppRegistry; beforeEach(function () { testAppRegistry = new AppRegistry(); + mockConnectionStorage = { + save: sinon.spy(), + }; [ 'Collection.Workspace', 'Database.Workspace', @@ -55,7 +61,10 @@ describe('Home [Component]', function () { beforeEach(function () { render( - + ); }); @@ -76,7 +85,10 @@ describe('Home [Component]', function () { ) { render( - + ); testAppRegistry.emit('data-service-connected', null, dataService, { @@ -201,7 +213,10 @@ describe('Home [Component]', function () { beforeEach(function () { render( - + ); }); @@ -227,7 +242,10 @@ describe('Home [Component]', function () { beforeEach(function () { const { unmount } = render( - + ); unmount(); diff --git a/packages/compass-home/src/components/home.tsx b/packages/compass-home/src/components/home.tsx index abf9390c65e..5331b0c4859 100644 --- a/packages/compass-home/src/components/home.tsx +++ b/packages/compass-home/src/components/home.tsx @@ -3,7 +3,6 @@ import { css } from '@mongodb-js/compass-components'; import { ConnectionInfo, DataService, - convertConnectionInfoToModel, getConnectionTitle, ConnectionStorage, } from 'mongodb-data-service'; @@ -129,7 +128,7 @@ function Home({ connectionStorage = new ConnectionStorage(), }: { appName: string; - connectionStorage: ConnectionStorage; + connectionStorage?: ConnectionStorage; }): React.ReactElement | null { const appRegistry = useAppRegistryContext(); const connectRole = useAppRegistryRole(AppRegistryRoles.APPLICATION_CONNECT); @@ -155,22 +154,17 @@ function Home({ // TODO: Remove this comment once we only have one connections package: // This is currently only used by the new connections package. - // We've moved to not calling the `data-service-connected` event inside - // of connections and instead call it here. - async function onConnected( + // We've moved to calling the `data-service-connected` event here instead + // of inside `connections`/`compass-connect` and instead call it here. + function onConnected( connectionInfo: ConnectionInfo, dataService: DataService ) { - const legacyConnectionModel = await convertConnectionInfoToModel( - connectionInfo - ); - appRegistry.emit( 'data-service-connected', null, // No error connecting. dataService, - connectionInfo, - legacyConnectionModel // TODO: Remove this once we remove the dependency in compass-sidebar. + connectionInfo ); } diff --git a/packages/connections/src/components/connections.tsx b/packages/connections/src/components/connections.tsx index d7109159eaf..03edf80c22e 100644 --- a/packages/connections/src/components/connections.tsx +++ b/packages/connections/src/components/connections.tsx @@ -56,7 +56,7 @@ function Connections({ onConnected: ( connectionInfo: ConnectionInfo, dataService: DataService - ) => Promise; + ) => void; connectionStorage?: ConnectionStore; connectFn?: (connectionOptions: ConnectionOptions) => Promise; }): React.ReactElement { diff --git a/packages/connections/src/stores/connections-store.ts b/packages/connections/src/stores/connections-store.ts index 455dc8e6085..c418c5f2c25 100644 --- a/packages/connections/src/stores/connections-store.ts +++ b/packages/connections/src/stores/connections-store.ts @@ -190,7 +190,7 @@ export function useConnections( onConnected: ( connectionInfo: ConnectionInfo, dataService: DataService - ) => Promise, + ) => void, connectionStorage: ConnectionStore, connectFn: (connectionOptions: ConnectionOptions) => Promise ): { @@ -242,7 +242,7 @@ export function useConnections( ) { // After connecting and the UI is updated we notify the rest of Compass. try { - await onConnected(connectionInfo, dataService); + onConnected(connectionInfo, dataService); // Update lastUsed date as now and save the connection. connectionInfo.lastUsed = new Date(); From 5edcb54de443165ee6d87cc238e4cadc1e143038 Mon Sep 17 00:00:00 2001 From: Anemy Date: Wed, 26 Jan 2022 02:36:41 -0500 Subject: [PATCH 4/6] use same action handling pattern as before --- .../compass-home/src/components/home.spec.tsx | 26 +--- packages/compass-home/src/components/home.tsx | 98 +++------------ .../compass-home/src/components/workspace.tsx | 12 +- packages/compass-sidebar/package.json | 2 + .../src/components/sidebar/sidebar.jsx | 9 +- .../src/modules/connection-info.js | 114 ++++++++++++++++++ .../src/modules/connection-info.spec.js | 95 +++++++++++++++ packages/compass-sidebar/src/modules/index.js | 5 + packages/compass-sidebar/src/plugin.js | 16 +-- packages/compass-sidebar/src/stores/store.js | 5 + .../test/renderer/components/sidebar.spec.js | 16 +-- 11 files changed, 257 insertions(+), 141 deletions(-) create mode 100644 packages/compass-sidebar/src/modules/connection-info.js create mode 100644 packages/compass-sidebar/src/modules/connection-info.spec.js diff --git a/packages/compass-home/src/components/home.spec.tsx b/packages/compass-home/src/components/home.spec.tsx index 4ff1df70a91..2b39e5e4983 100644 --- a/packages/compass-home/src/components/home.spec.tsx +++ b/packages/compass-home/src/components/home.spec.tsx @@ -5,7 +5,6 @@ import { expect } from 'chai'; import AppRegistry from 'hadron-app-registry'; import ipc from 'hadron-ipc'; import sinon from 'sinon'; - import AppRegistryContext from '../contexts/app-registry-context'; import Home from '.'; @@ -27,14 +26,9 @@ const getComponent = (name: string) => { const createDataService = () => ({}); describe('Home [Component]', function () { - let mockConnectionStorage; - let testAppRegistry: AppRegistry; beforeEach(function () { testAppRegistry = new AppRegistry(); - mockConnectionStorage = { - save: sinon.spy(), - }; [ 'Collection.Workspace', 'Database.Workspace', @@ -61,10 +55,7 @@ describe('Home [Component]', function () { beforeEach(function () { render( - + ); }); @@ -85,10 +76,7 @@ describe('Home [Component]', function () { ) { render( - + ); testAppRegistry.emit('data-service-connected', null, dataService, { @@ -213,10 +201,7 @@ describe('Home [Component]', function () { beforeEach(function () { render( - + ); }); @@ -242,10 +227,7 @@ describe('Home [Component]', function () { beforeEach(function () { const { unmount } = render( - + ); unmount(); diff --git a/packages/compass-home/src/components/home.tsx b/packages/compass-home/src/components/home.tsx index 5331b0c4859..eba1441ffa0 100644 --- a/packages/compass-home/src/components/home.tsx +++ b/packages/compass-home/src/components/home.tsx @@ -4,12 +4,9 @@ import { ConnectionInfo, DataService, getConnectionTitle, - ConnectionStorage, } from 'mongodb-data-service'; import toNS from 'mongodb-ns'; import Connections from '@mongodb-js/compass-connections'; -import ipc from 'hadron-ipc'; -import debugModule from 'debug'; import Workspace from './workspace'; import Namespace from '../types/namespace'; @@ -19,8 +16,7 @@ import { useAppRegistryRole, } from '../contexts/app-registry-context'; import updateTitle from '../modules/update-title'; - -const debug = debugModule('mongodb-compass:home:home'); +import ipc from 'hadron-ipc'; const homeViewStyles = css({ display: 'flex', @@ -44,31 +40,24 @@ const defaultNS: Namespace = { collection: '', }; -type State = - | { - connectionInfo: undefined; - isConnected: false; - namespace: Namespace; - } - | { - connectionInfo: ConnectionInfo; - isConnected: true; - namespace: Namespace; - }; +type State = { + connectionTitle: string; + isConnected: boolean; + namespace: Namespace; +}; -const initialState: State = { - connectionInfo: undefined, - namespace: defaultNS, +const initialState = { + connectionTitle: '', isConnected: false, + namespace: defaultNS, }; type Action = | { type: 'connected'; - connectionInfo: ConnectionInfo; + connectionTitle: string; } | { type: 'disconnected' } - | { type: 'update-connection-info'; connectionInfo: ConnectionInfo } | { type: 'update-namespace'; namespace: Namespace }; function reducer(state: State, action: Action): State { @@ -76,17 +65,9 @@ function reducer(state: State, action: Action): State { case 'connected': return { ...state, - connectionInfo: action.connectionInfo, namespace: { ...defaultNS }, isConnected: true, - }; - case 'update-connection-info': - return { - ...state, - isConnected: true, - connectionInfo: { - ...action.connectionInfo, - }, + connectionTitle: action.connectionTitle, }; case 'update-namespace': return { @@ -107,35 +88,13 @@ function hideCollectionSubMenu() { void ipc.ipcRenderer?.call('window:hide-collection-submenu'); } -async function saveConnectionInfo( - connectionInfo: ConnectionInfo, - connectionStorage: ConnectionStorage -) { - try { - await connectionStorage.save(connectionInfo); - debug(`saved connection with id ${connectionInfo.id || ''}`); - } catch (err) { - debug( - `error saving connection with id ${connectionInfo.id || ''}: ${ - (err as Error).message - }` - ); - } -} - -function Home({ - appName, - connectionStorage = new ConnectionStorage(), -}: { - appName: string; - connectionStorage?: ConnectionStorage; -}): React.ReactElement | null { +function Home({ appName }: { appName: string }): React.ReactElement | null { const appRegistry = useAppRegistryContext(); const connectRole = useAppRegistryRole(AppRegistryRoles.APPLICATION_CONNECT); const connectedDataService = useRef(); const showNewConnectForm = process.env.USE_NEW_CONNECT_FORM === 'true'; - const [{ connectionInfo, isConnected, namespace }, dispatch] = useReducer( + const [{ connectionTitle, isConnected, namespace }, dispatch] = useReducer( reducer, { ...initialState } ); @@ -148,7 +107,7 @@ function Home({ connectedDataService.current = ds; dispatch({ type: 'connected', - connectionInfo, + connectionTitle: getConnectionTitle(connectionInfo) || '', }); } @@ -168,19 +127,6 @@ function Home({ ); } - const updateAndSaveConnectionInfo = useCallback( - (newConnectionInfo: ConnectionInfo) => { - // Currently we silently fail if saving the favorite fails. - void saveConnectionInfo(newConnectionInfo, connectionStorage); - - dispatch({ - type: 'update-connection-info', - connectionInfo: newConnectionInfo, - }); - }, - [connectionStorage] - ); - function onSelectDatabase(ns: string) { hideCollectionSubMenu(); dispatch({ @@ -226,10 +172,10 @@ function Home({ }, [appName]); useEffect(() => { - if (isConnected && connectionInfo) { - updateTitle(appName, getConnectionTitle(connectionInfo) || '', namespace); + if (isConnected) { + updateTitle(appName, connectionTitle, namespace); } - }, [isConnected, appName, connectionInfo, namespace]); + }, [isConnected, appName, connectionTitle, namespace]); useEffect(() => { async function handleDisconnectClicked() { @@ -295,14 +241,8 @@ function Home({ }; }, [appRegistry, onDataServiceDisconnected]); - if (isConnected && connectionInfo) { - return ( - - ); + if (isConnected) { + return ; } if (showNewConnectForm) { diff --git a/packages/compass-home/src/components/workspace.tsx b/packages/compass-home/src/components/workspace.tsx index 07d5c390e9d..5d426520848 100644 --- a/packages/compass-home/src/components/workspace.tsx +++ b/packages/compass-home/src/components/workspace.tsx @@ -9,7 +9,6 @@ import { useAppRegistryComponent, useAppRegistryRole, } from '../contexts/app-registry-context'; -import { ConnectionInfo } from 'mongodb-data-service'; const homeViewStyles = css({ display: 'flex', @@ -37,13 +36,9 @@ const homePageContentStyles = css({ }); export default function Workspace({ - connectionInfo, namespace, - updateAndSaveConnectionInfo, }: { - connectionInfo: ConnectionInfo; namespace: Namespace; - updateAndSaveConnectionInfo: (connectionInfo: ConnectionInfo) => void; }): React.ReactElement { const SidebarComponent = useAppRegistryComponent( AppRegistryComponents.SIDEBAR_COMPONENT @@ -61,12 +56,7 @@ export default function Workspace({
- {SidebarComponent && ( - - )} + {SidebarComponent && } {FindInPage && }
{globalModals && diff --git a/packages/compass-sidebar/package.json b/packages/compass-sidebar/package.json index 08349b78b71..f8c149414a4 100644 --- a/packages/compass-sidebar/package.json +++ b/packages/compass-sidebar/package.json @@ -32,6 +32,7 @@ "@mongodb-js/compass-components": "^0.9.1", "@mongodb-js/connect-form": "^0.4.1", "debug": "*", + "mongodb-data-service": "^21.15.1", "prop-types": "^15.7.2", "react": "^16.14.0", "react-bootstrap": "^0.32.1", @@ -136,6 +137,7 @@ "xvfb-maybe": "^0.2.1" }, "dependencies": { + "@mongodb-js/compass-logging": "^0.6.1", "@mongodb-js/mongodb-redux-common": "^1.7.0" }, "homepage": "https://github.com/mongodb-js/compass", diff --git a/packages/compass-sidebar/src/components/sidebar/sidebar.jsx b/packages/compass-sidebar/src/components/sidebar/sidebar.jsx index b5227ad135e..ed3face3bcf 100644 --- a/packages/compass-sidebar/src/components/sidebar/sidebar.jsx +++ b/packages/compass-sidebar/src/components/sidebar/sidebar.jsx @@ -15,6 +15,7 @@ import SidebarDatabasesNavigation from '../sidebar-databases-navigation'; import { toggleIsDetailsExpanded } from '../../modules/is-details-expanded'; import { toggleIsGenuineMongoDBVisible } from '../../modules/is-genuine-mongodb-visible'; import { changeFilterRegex } from '../../modules/databases'; +import { updateAndSaveConnectionInfo } from '../../modules/connection-info'; import { openLink } from '../../modules/link'; import { NavigationItems } from './navigation-items'; @@ -52,7 +53,7 @@ class Sidebar extends PureComponent { toggleIsGenuineMongoDBVisible: PropTypes.func.isRequired, globalAppRegistryEmit: PropTypes.func.isRequired, connectionInfo: PropTypes.object.isRequired, - updateConnectionInfo: PropTypes.func.isRequired + updateAndSaveConnectionInfo: PropTypes.func.isRequired }; state = { @@ -182,7 +183,7 @@ class Sidebar extends PureComponent { toggleIsDetailsExpanded={this.props.toggleIsDetailsExpanded} globalAppRegistryEmit={this.props.globalAppRegistryEmit} connectionInfo={this.props.connectionInfo} - updateConnectionInfo={this.props.updateConnectionInfo} + updateConnectionInfo={this.props.updateAndSaveConnectionInfo} /> )} {process.env.COMPASS_SHOW_YOUR_QUERIES_TAB === 'true' && ( @@ -226,6 +227,7 @@ class Sidebar extends PureComponent { * @returns {Object} The mapped properties. */ const mapStateToProps = (state) => ({ + connectionInfo: state.connectionInfo.connectionInfo, instance: state.instance, databases: state.databases.databases, isDetailsExpanded: state.isDetailsExpanded, @@ -247,7 +249,8 @@ const MappedSidebar = connect( toggleIsGenuineMongoDBVisible, changeFilterRegex, openLink, - globalAppRegistryEmit + globalAppRegistryEmit, + updateAndSaveConnectionInfo }, )(Sidebar); diff --git a/packages/compass-sidebar/src/modules/connection-info.js b/packages/compass-sidebar/src/modules/connection-info.js new file mode 100644 index 00000000000..1b3324cf958 --- /dev/null +++ b/packages/compass-sidebar/src/modules/connection-info.js @@ -0,0 +1,114 @@ +import { + ConnectionStorage +} from 'mongodb-data-service'; +import { createLoggerAndTelemetry } from '@mongodb-js/compass-logging'; + +const { debug } = createLoggerAndTelemetry('COMPASS-SIDEBAR'); + +/** + * Change connection action name. + */ +const CHANGE_CONNECTION_INFO = 'sidebar/connection/CHANGE_CONNECTION_INFO'; + +/** +* Save favorite connection action name. +*/ +const SAVE_CONNECTION_INFO = 'sidebar/connection/SAVE_CONNECTION_INFO'; + +/** +* The initial state of the connection. +*/ +export const INITIAL_STATE = { + connectionInfo: { + connectionOptions: { + connectionString: 'mongodb://localhost:27017' + } + }, + connectionStorage: new ConnectionStorage() +}; + +async function saveConnectionInfo(connectionInfo, connectionStorage) { + try { + await connectionStorage.save(connectionInfo); + debug(`saved connection with id ${connectionInfo.id || ''}`); + } catch (err) { + // Currently we silently fail if saving the favorite fails. + debug( + `error saving connection with id ${connectionInfo.id || ''}: ${ + err.message + }` + ); + } +} + +/** +* Changes the connection. +* +* @param {Object} state - The state. +* @param {Object} action - The action. +* +* @returns {Object} The new state. +*/ +const doChangeConnectionInfo = (state, action) => { + return { ...state, connectionInfo: action.connectionInfo }; +}; + +/** +* Saves the new favorite connection info. +* +* @param {Object} state - The state. +* @param {Object} action - The action. +* +* @returns {Object} The new state. +*/ +const doSaveConnectionInfo = (state, action) => { + saveConnectionInfo(action.connectionInfo, state.connectionStorage); + + return { ...state, connectionInfo: action.connectionInfo }; +}; + +/** +* To not have a huge switch statement in the reducer. +*/ +const MAPPINGS = { + [CHANGE_CONNECTION_INFO]: doChangeConnectionInfo, + [SAVE_CONNECTION_INFO]: doSaveConnectionInfo +}; + +/** +* Reducer function for handle state changes. +* +* @param {String} state - The status state. +* @param {Object} action - The action. +* +* @returns {String} The new state. +*/ +export default function reducer(state = INITIAL_STATE, action) { + const fn = MAPPINGS[action.type]; + + return fn ? fn(state, action) : state; +} + +/** +* Change connection action creator. +* +* @param {Object} connectionInfo - The connection info object. +* +* @returns {Object} The action. +*/ +export const changeConnectionInfo = (connectionInfo) => ({ + type: CHANGE_CONNECTION_INFO, + connectionInfo +}); + +/** +* Save connection info action creator. +* +* @param {Object} connectionInfo - The connection info object. +* +* @returns {Object} The action. +*/ +export const updateAndSaveConnectionInfo = (connectionInfo) => ({ + type: SAVE_CONNECTION_INFO, + connectionInfo +}); diff --git a/packages/compass-sidebar/src/modules/connection-info.spec.js b/packages/compass-sidebar/src/modules/connection-info.spec.js new file mode 100644 index 00000000000..6feca986802 --- /dev/null +++ b/packages/compass-sidebar/src/modules/connection-info.spec.js @@ -0,0 +1,95 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; + +import reducer, { + INITIAL_STATE, + changeConnectionInfo, + updateAndSaveConnectionInfo +} from './connection-info'; + +describe('connection info module', () => { + const connectionInfoNotFavorite = { + connectionOptions: { + connectionString: 'mongodb://outerspace:27000' + }, + id: '123' + }; + + describe('reducer', () => { + context('when the action is changeConnectionInfo', () => { + it('returns the new state', () => { + expect(reducer(undefined, changeConnectionInfo(connectionInfoNotFavorite))).to.deep.equal({ + connectionInfo: connectionInfoNotFavorite, + connectionStorage: {} + }); + }); + + it('does not call the connection storage to save', () => { + const saveSpy = sinon.spy(); + reducer({ + connectionStorage: { + save: saveSpy + } + }, changeConnectionInfo(connectionInfoNotFavorite)); + + expect(saveSpy.callCount).to.equal(0); + }); + }); + + context('when the action is updateAndSaveConnectionInfo', () => { + it('returns the new state', () => { + const newConnection = updateAndSaveConnectionInfo({ + ...connectionInfoNotFavorite, + favorite: { + name: 'My Favorite', + color: '#d4366e' + } + }); + const state = reducer({ + connectionStorage: { + save: () => {} + } + }, newConnection); + + expect(state.connectionInfo.favorite.name).to.equal('My Favorite'); + expect(state.connectionInfo.favorite.color).to.equal('#d4366e'); + }); + + it('calls to save the connection info in the connection storage', () => { + const newConnection = updateAndSaveConnectionInfo( + { + ...connectionInfoNotFavorite, + favorite: { + name: 'My Favorite', + color: '#d4366e' + } + } + ); + const saveSpy = sinon.spy(); + reducer({ + connectionStorage: { + save: saveSpy + } + }, newConnection); + + expect(saveSpy.callCount).to.equal(1); + expect(saveSpy.firstCall.args[0]).to.deep.equal({ + connectionOptions: { + connectionString: 'mongodb://outerspace:27000' + }, + id: '123', + favorite: { + name: 'My Favorite', + color: '#d4366e' + } + }); + }); + }); + + context('when an action is not provided', () => { + it('returns the default state', () => { + expect(reducer(undefined, {})).to.equal(INITIAL_STATE); + }); + }); + }); +}); diff --git a/packages/compass-sidebar/src/modules/index.js b/packages/compass-sidebar/src/modules/index.js index 069b29feeae..19daf15a188 100644 --- a/packages/compass-sidebar/src/modules/index.js +++ b/packages/compass-sidebar/src/modules/index.js @@ -27,6 +27,9 @@ import isGenuineMongoDB, { import isGenuineMongoDBVisible, { INITIAL_STATE as IS_VISIBLE_IS } from './is-genuine-mongodb-visible'; +import connectionInfo, { + INITIAL_STATE as CONNECTION_INFO_IS +} from './connection-info'; /** * The reducer. @@ -34,6 +37,7 @@ import isGenuineMongoDBVisible, { const reducer = combineReducers({ appRegistry, databases, + connectionInfo, description, detailsPlugins, instance, @@ -56,6 +60,7 @@ const rootReducer = (state, action) => { if (action.type === RESET) { return { ...state, + connectionInfo: CONNECTION_INFO_IS, databases: DATABASES_INITIAL_STATE, description: DESCRIPTION_INITIAL_STATE, instance: INSTANCE_INITIAL_STATE, diff --git a/packages/compass-sidebar/src/plugin.js b/packages/compass-sidebar/src/plugin.js index c5d46893357..aa8c1d12936 100644 --- a/packages/compass-sidebar/src/plugin.js +++ b/packages/compass-sidebar/src/plugin.js @@ -1,6 +1,5 @@ import React from 'react'; import { Provider } from 'react-redux'; -import PropTypes from 'prop-types'; import Sidebar from './components/sidebar'; import store from './stores'; @@ -11,25 +10,14 @@ import store from './stores'; * * @returns {React.Component} The rendered component. */ -function SidebarPlugin({ - connectionInfo, - updateAndSaveConnectionInfo -}) { +function SidebarPlugin() { return ( - + ); } SidebarPlugin.displayName = 'SidebarPlugin'; -SidebarPlugin.propTypes = { - connectionInfo: PropTypes.object.isRequired, - updateAndSaveConnectionInfo: PropTypes.func.isRequired -}; - export default SidebarPlugin; diff --git a/packages/compass-sidebar/src/stores/store.js b/packages/compass-sidebar/src/stores/store.js index 25ee2253b98..4b4165e02f3 100644 --- a/packages/compass-sidebar/src/stores/store.js +++ b/packages/compass-sidebar/src/stores/store.js @@ -13,6 +13,7 @@ import { toggleIsDataLake } from '../modules/is-data-lake'; import { loadDetailsPlugins } from '../modules/details-plugins'; import { toggleIsGenuineMongoDB } from '../modules/is-genuine-mongodb'; import { toggleIsGenuineMongoDBVisible } from '../modules/is-genuine-mongodb-visible'; +import { changeConnectionInfo } from '../modules/connection-info'; const store = createStore(reducer, applyMiddleware(thunk)); @@ -59,6 +60,10 @@ store.onActivated = (appRegistry) => { store.dispatch(loadDetailsPlugins(appRegistry)); + appRegistry.on('data-service-connected', (_, dataService, connectionInfo) => { + store.dispatch(changeConnectionInfo(connectionInfo)); + }); + appRegistry.on('instance-destroyed', () => { onInstanceChange.cancel(); onDatabasesChange.cancel(); diff --git a/packages/compass-sidebar/test/renderer/components/sidebar.spec.js b/packages/compass-sidebar/test/renderer/components/sidebar.spec.js index a75a3cd5f9a..e63a10277e3 100644 --- a/packages/compass-sidebar/test/renderer/components/sidebar.spec.js +++ b/packages/compass-sidebar/test/renderer/components/sidebar.spec.js @@ -26,8 +26,6 @@ describe('Sidebar [Component]', () => { {}} - updateConnectionInfo={()=>{}} - connectionInfo={connectionInfo} /> ); @@ -80,7 +78,7 @@ describe('Sidebar [Component]', () => { filterDatabases={() => {}} changeDatabases={() => {}} changeFilterRegex={() => {}} - updateConnectionInfo={()=>{}} + updateAndSaveConnectionInfo={()=>{}} saveFavorite={saveFavoriteSpy} /> @@ -116,10 +114,7 @@ describe('Sidebar [Component]', () => { beforeEach(() => { component = mount( - {}} - connectionInfo={connectionInfo} - /> + ); component.find('[data-test-id="toggle-sidebar"]').simulate('click'); @@ -149,10 +144,7 @@ describe('Sidebar [Component]', () => { beforeEach(() => { component = mount( - {}} - connectionInfo={connectionInfo} - /> + ); component.find('[data-test-id="toggle-sidebar"]').simulate('click'); @@ -184,7 +176,7 @@ describe('Sidebar [Component]', () => { component = mount( {}} + updateAndSaveConnectionInfo={()=>{}} connectionInfo={connectionInfo} /> From 209b8f34139180dadb47e3cf0c40bb84f2ce57dc Mon Sep 17 00:00:00 2001 From: Anemy Date: Wed, 26 Jan 2022 12:34:28 -0500 Subject: [PATCH 5/6] Use favorite icon from compass-components --- .../src/components/icons/favorite-icon.tsx | 21 ++++++++++++------- .../favorite-button/favorite-button.jsx | 13 ++++++++---- .../favorite-button.module.less | 6 +++++- .../favorite-button/favorite-button.spec.js | 17 ++++++++------- .../src/hooks/use-connect-form.spec.ts | 1 - 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/packages/compass-components/src/components/icons/favorite-icon.tsx b/packages/compass-components/src/components/icons/favorite-icon.tsx index 26ff47d18cc..ee177393b42 100644 --- a/packages/compass-components/src/components/icons/favorite-icon.tsx +++ b/packages/compass-components/src/components/icons/favorite-icon.tsx @@ -7,11 +7,15 @@ import { gold } from '../../compass-ui-colors'; export function FavoriteIcon({ // When it's a favorite, the star is filled in with gold. isFavorite = false, + favoriteColor = gold, darkMode = false, + showCircle = true, size = spacing[4], }: { isFavorite?: boolean; + favoriteColor?: string; darkMode?: boolean; + showCircle?: boolean; size?: number; }): React.ReactElement { const stroke = darkMode ? uiColors.white : uiColors.black; @@ -24,15 +28,18 @@ export function FavoriteIcon({ fill="none" xmlns="http://www.w3.org/2000/svg" > + {showCircle && ( + + )} - diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx index 40b08e098f9..34b633c0f24 100644 --- a/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import FontAwesome from 'react-fontawesome'; import { + FavoriteIcon, mergeProps, useFocusRing } from '@mongodb-js/compass-components'; @@ -13,7 +13,6 @@ const FavoriteButton = ({ toggleIsFavoriteModalVisible }) => { const isFavorite = !!favoriteOptions; - const fontAwesomeName = isFavorite ? 'star' : 'star-o'; const hex = favoriteOptions?.color; const style = { backgroundColor: hex || '#243642', @@ -35,8 +34,14 @@ const FavoriteButton = ({ ); diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less index 8e460d4a482..cb1c3d9df2c 100644 --- a/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less @@ -7,11 +7,15 @@ &-text { text-transform: uppercase; + display: flex; + align-items: center; + flex-direction: row; border-radius: 14px; border-style: solid; border-width: 1px; border-color: transparent; - padding: 3px 10px; + padding: 1px 10px; + padding-left: 6px; margin-right: 5px; font-weight: bold; cursor: pointer; diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js b/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js index 385d5ed2f37..81115dad5f2 100644 --- a/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.spec.js @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { mount } from 'enzyme'; import FavoriteButton from './favorite-button'; import styles from './favorite-button.module.less'; @@ -9,7 +9,7 @@ describe('FavoriteButton [Component]', () => { let component; beforeEach(() => { - component = shallow( + component = mount( {}} favoriteOptions={undefined} @@ -21,10 +21,11 @@ describe('FavoriteButton [Component]', () => { component = null; }); - it('displays the the default pill', () => { + it('displays the the default button without star filled in', () => { expect(component.find(`.${styles['favorite-button']}`)).to.be.present(); expect(component.find(`.${styles['favorite-button-text']}`)).to.be.present(); - expect(component.find('FontAwesome[name="star-o"]')).to.be.present(); + let starStyle = component.find('#favoriteIconStar').get(0).props; + expect(starStyle).to.have.property('fill', 'none'); }); }); @@ -32,7 +33,7 @@ describe('FavoriteButton [Component]', () => { let component; beforeEach(() => { - component = shallow( + component = mount( {}} favoriteOptions={{ @@ -47,10 +48,12 @@ describe('FavoriteButton [Component]', () => { component = null; }); - it('displays the the filled with no color pill', () => { + it('displays the the filled in star', () => { expect(component.find(`.${styles['favorite-button']}`)).to.be.present(); expect(component.find(`.${styles['favorite-button-text']}`)).to.be.present(); - expect(component.find('FontAwesome[name="star"]')).to.be.present(); + + let starStyle = component.find('#favoriteIconStar').get(0).props; + expect(starStyle).to.have.property('fill', '#ffffff'); }); }); }); diff --git a/packages/connect-form/src/hooks/use-connect-form.spec.ts b/packages/connect-form/src/hooks/use-connect-form.spec.ts index c8f7d0c3d2e..371b0347a45 100644 --- a/packages/connect-form/src/hooks/use-connect-form.spec.ts +++ b/packages/connect-form/src/hooks/use-connect-form.spec.ts @@ -612,7 +612,6 @@ describe('use-connect-form hook', function () { } = handleConnectionFormFieldUpdate( { type: 'update-ssh-options', - currentTab: 'password', key: 'host', value: 'localhost', }, From 0a5758488352d8264bc2a6e2bb087c4bcffa981b Mon Sep 17 00:00:00 2001 From: Anemy Date: Thu, 27 Jan 2022 10:14:51 -0500 Subject: [PATCH 6/6] remove border so focus ring works nice --- .../components/favorite-button/favorite-button.module.less | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less index cb1c3d9df2c..84a21c96b17 100644 --- a/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less +++ b/packages/compass-sidebar/src/components/favorite-button/favorite-button.module.less @@ -11,10 +11,8 @@ align-items: center; flex-direction: row; border-radius: 14px; - border-style: solid; - border-width: 1px; - border-color: transparent; - padding: 1px 10px; + border: none; + padding: 2px 11px; padding-left: 6px; margin-right: 5px; font-weight: bold;