From df3c8488597ed3f8617fc3c1a52c14dca38d5f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 11 Feb 2025 20:05:21 +0100 Subject: [PATCH 01/20] Add dependency on split-button --- package-lock.json | 176 ++++++++++++++++------- packages/compass-components/package.json | 1 + 2 files changed, 127 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85a27a82610..f128c87e28b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5335,9 +5335,9 @@ } }, "node_modules/@leafygreen-ui/descendants": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/descendants/-/descendants-2.0.2.tgz", - "integrity": "sha512-r1srluGlar5LuvLVxkLStzRs4Agsqn854pjOdXP7OsBZWx5oGIHZQ6Pu1cUTzbK7YBH3IFRAyRSGIB7tCxSZYg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/descendants/-/descendants-2.1.0.tgz", + "integrity": "sha512-Uq6yljMGGxAEE62n8IihwH+N74LfMZhrgm8tRdV5mzbrFj3H9b2hvux83n/aGv5jmfyELHwr7Pg4v6RWaCFFgQ==", "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/hooks": "^8.3.4", @@ -5422,17 +5422,17 @@ } }, "node_modules/@leafygreen-ui/icon-button": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.2.tgz", - "integrity": "sha512-nCotpqN4VlGejm0ybzdZH4ExP8bdQZbLElBkTEsPSf4nNCvjC5LsbIqRuK/TGIHTa4tPnTHgnx7QZb5X36Q5Qg==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.3.tgz", + "integrity": "sha512-ePVkelwDmD/HB0VF77C2XvVdP2e4J3VHPt27oBfZCLdxJkvIjqSQftBisgvveyFydK+6R8gaiei5yUCbmUPqng==", "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/a11y": "^2.0.2", - "@leafygreen-ui/box": "^4.0.2", "@leafygreen-ui/emotion": "^4.0.9", "@leafygreen-ui/icon": "^13.1.2", "@leafygreen-ui/lib": "^14.0.2", "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", "@leafygreen-ui/tokens": "^2.11.3", "polished": "^4.2.2" }, @@ -5474,9 +5474,9 @@ } }, "node_modules/@leafygreen-ui/input-option": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/input-option/-/input-option-3.0.2.tgz", - "integrity": "sha512-yBAVNvtDeBB3fVNT6O7yw+ccFGZIwPTRoCKciZFDrzuB7KETxtaWN1ClEn14sL232P2gLd1NfrgzsWLPUi9Fsg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/input-option/-/input-option-3.0.4.tgz", + "integrity": "sha512-AgX2SKh3sCAuLs9tuZi8uItt3yYzzUL+ff6mzwXa4AVcM2Ni/W308jaD1Iu6RAX5c1sZE36zM7aJyzUiAWWiiA==", "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/a11y": "^2.0.2", @@ -5485,7 +5485,7 @@ "@leafygreen-ui/palette": "^4.1.3", "@leafygreen-ui/polymorphic": "^2.0.5", "@leafygreen-ui/tokens": "^2.11.3", - "@leafygreen-ui/typography": "^20.0.2" + "@leafygreen-ui/typography": "^20.1.1" }, "peerDependencies": { "@leafygreen-ui/leafygreen-provider": "^4.0.2" @@ -5544,23 +5544,23 @@ } }, "node_modules/@leafygreen-ui/menu": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/menu/-/menu-28.0.2.tgz", - "integrity": "sha512-Z7Ureg4+5NGiUCwqnyNoA+JbylWPKLOeospkZ3L7Mqd8zdr+iUosRFVrehG62Gmx6C7htUoaV366aFtBXYnjwA==", + "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/menu/-/menu-28.0.6.tgz", + "integrity": "sha512-llGdNEkEZ8gZH0dY+ceznCfRpeqzSXW20jKDmtD09f5k8gh5w7RmH5rwJCuXpFa5KlbYAOwQtczcd/W9Ml2r8g==", "license": "Apache-2.0", "dependencies": { - "@leafygreen-ui/descendants": "^2.0.2", + "@leafygreen-ui/descendants": "^2.1.0", "@leafygreen-ui/emotion": "^4.0.9", "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/icon": "^13.1.2", - "@leafygreen-ui/icon-button": "^16.0.2", - "@leafygreen-ui/input-option": "^3.0.2", + "@leafygreen-ui/icon-button": "^16.0.3", + "@leafygreen-ui/input-option": "^3.0.4", "@leafygreen-ui/lib": "^14.0.2", "@leafygreen-ui/palette": "^4.1.3", "@leafygreen-ui/polymorphic": "^2.0.5", - "@leafygreen-ui/popover": "^13.0.2", + "@leafygreen-ui/popover": "^13.0.3", "@leafygreen-ui/tokens": "^2.11.3", - "@leafygreen-ui/typography": "^20.0.2", + "@leafygreen-ui/typography": "^20.1.1", "lodash": "^4.17.21", "polished": "^4.3.1", "react-transition-group": "^4.4.5" @@ -5628,9 +5628,9 @@ } }, "node_modules/@leafygreen-ui/popover": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/popover/-/popover-13.0.2.tgz", - "integrity": "sha512-pLqDhR50O41gN7iBf8JkhUsl2fLSSN7p++yY3do+OLQ8sRWpsvB9Plzw6eQuix4+O6mpSg25FbWn9Hp2/o4BRQ==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/popover/-/popover-13.0.3.tgz", + "integrity": "sha512-5dmqbfwO2m5hYcgtlQr58JVK1oYdOIqGOQBtx0R9fjxrObuX2XpGa7g0ej9HuqVI+LrKD/BxsbVozlaVz4WmIQ==", "license": "Apache-2.0", "dependencies": { "@floating-ui/react": "^0.26.28", @@ -5780,6 +5780,46 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "license": "MIT" }, + "node_modules/@leafygreen-ui/split-button": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/split-button/-/split-button-4.1.5.tgz", + "integrity": "sha512-vlDo9UxkEVAxMzQfW4JVHKyb8vTQfVxA1UnlKKA0HAsRblOtjldSSyOf60jg9KPvtGf/C7uMv/pM0D2sJzpcOw==", + "license": "Apache-2.0", + "dependencies": { + "@leafygreen-ui/button": "^23.0.0", + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/hooks": "^8.3.4", + "@leafygreen-ui/icon": "^13.1.2", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/menu": "^28.0.6", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", + "@leafygreen-ui/popover": "^13.0.3", + "@leafygreen-ui/tokens": "^2.11.3" + }, + "peerDependencies": { + "@leafygreen-ui/leafygreen-provider": "^4.0.2" + } + }, + "node_modules/@leafygreen-ui/split-button/node_modules/@leafygreen-ui/button": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/button/-/button-23.0.0.tgz", + "integrity": "sha512-E2yuIM1oAqW/Fe9S/mwK+GqBDThr31P+Y27cd0oPD6ZTtyWruKY60M7dBafvqCY+Q3kPPCbBr80Uo8vjs7RXYw==", + "license": "Apache-2.0", + "dependencies": { + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", + "@leafygreen-ui/ripple": "^1.1.15", + "@leafygreen-ui/tokens": "^2.11.3", + "@lg-tools/test-harnesses": "^0.1.4", + "polished": "^4.2.2" + }, + "peerDependencies": { + "@leafygreen-ui/leafygreen-provider": "^4.0.2" + } + }, "node_modules/@leafygreen-ui/tabs": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/@leafygreen-ui/tabs/-/tabs-14.0.2.tgz", @@ -5913,9 +5953,9 @@ } }, "node_modules/@leafygreen-ui/typography": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/typography/-/typography-20.0.2.tgz", - "integrity": "sha512-AqBLozuBMjos2UNEVj1A+zi2S2fXEYo0hLoM0ypDSWPwvRICLMYuR855hJiL0BlDZWBb2CrT7WdM7dLa6I+52w==", + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/typography/-/typography-20.1.1.tgz", + "integrity": "sha512-kdGZaCfdb/UcvKg0yl0YAOYEw0DAY1O5ZCez88vpzxx64KlpivwaM++25Tu414jZFyL8TYG8OqobgH7LWVRxQQ==", "license": "Apache-2.0", "dependencies": { "@leafygreen-ui/emotion": "^4.0.9", @@ -43780,6 +43820,7 @@ "@leafygreen-ui/search-input": "^5.0.2", "@leafygreen-ui/segmented-control": "^10.0.2", "@leafygreen-ui/select": "^14.0.2", + "@leafygreen-ui/split-button": "^4.1.5", "@leafygreen-ui/table": "^13.0.1", "@leafygreen-ui/tabs": "^14.0.2", "@leafygreen-ui/text-area": "^10.0.2", @@ -54133,9 +54174,9 @@ } }, "@leafygreen-ui/descendants": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/descendants/-/descendants-2.0.2.tgz", - "integrity": "sha512-r1srluGlar5LuvLVxkLStzRs4Agsqn854pjOdXP7OsBZWx5oGIHZQ6Pu1cUTzbK7YBH3IFRAyRSGIB7tCxSZYg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/descendants/-/descendants-2.1.0.tgz", + "integrity": "sha512-Uq6yljMGGxAEE62n8IihwH+N74LfMZhrgm8tRdV5mzbrFj3H9b2hvux83n/aGv5jmfyELHwr7Pg4v6RWaCFFgQ==", "requires": { "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/lib": "^14.0.2", @@ -54205,16 +54246,16 @@ } }, "@leafygreen-ui/icon-button": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.2.tgz", - "integrity": "sha512-nCotpqN4VlGejm0ybzdZH4ExP8bdQZbLElBkTEsPSf4nNCvjC5LsbIqRuK/TGIHTa4tPnTHgnx7QZb5X36Q5Qg==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.3.tgz", + "integrity": "sha512-ePVkelwDmD/HB0VF77C2XvVdP2e4J3VHPt27oBfZCLdxJkvIjqSQftBisgvveyFydK+6R8gaiei5yUCbmUPqng==", "requires": { "@leafygreen-ui/a11y": "^2.0.2", - "@leafygreen-ui/box": "^4.0.2", "@leafygreen-ui/emotion": "^4.0.9", "@leafygreen-ui/icon": "^13.1.2", "@leafygreen-ui/lib": "^14.0.2", "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", "@leafygreen-ui/tokens": "^2.11.3", "polished": "^4.2.2" } @@ -54245,9 +54286,9 @@ } }, "@leafygreen-ui/input-option": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/input-option/-/input-option-3.0.2.tgz", - "integrity": "sha512-yBAVNvtDeBB3fVNT6O7yw+ccFGZIwPTRoCKciZFDrzuB7KETxtaWN1ClEn14sL232P2gLd1NfrgzsWLPUi9Fsg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/input-option/-/input-option-3.0.4.tgz", + "integrity": "sha512-AgX2SKh3sCAuLs9tuZi8uItt3yYzzUL+ff6mzwXa4AVcM2Ni/W308jaD1Iu6RAX5c1sZE36zM7aJyzUiAWWiiA==", "requires": { "@leafygreen-ui/a11y": "^2.0.2", "@leafygreen-ui/emotion": "^4.0.9", @@ -54255,7 +54296,7 @@ "@leafygreen-ui/palette": "^4.1.3", "@leafygreen-ui/polymorphic": "^2.0.5", "@leafygreen-ui/tokens": "^2.11.3", - "@leafygreen-ui/typography": "^20.0.2" + "@leafygreen-ui/typography": "^20.1.1" } }, "@leafygreen-ui/leafygreen-provider": { @@ -54301,22 +54342,22 @@ } }, "@leafygreen-ui/menu": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/menu/-/menu-28.0.2.tgz", - "integrity": "sha512-Z7Ureg4+5NGiUCwqnyNoA+JbylWPKLOeospkZ3L7Mqd8zdr+iUosRFVrehG62Gmx6C7htUoaV366aFtBXYnjwA==", + "version": "28.0.6", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/menu/-/menu-28.0.6.tgz", + "integrity": "sha512-llGdNEkEZ8gZH0dY+ceznCfRpeqzSXW20jKDmtD09f5k8gh5w7RmH5rwJCuXpFa5KlbYAOwQtczcd/W9Ml2r8g==", "requires": { - "@leafygreen-ui/descendants": "^2.0.2", + "@leafygreen-ui/descendants": "^2.1.0", "@leafygreen-ui/emotion": "^4.0.9", "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/icon": "^13.1.2", - "@leafygreen-ui/icon-button": "^16.0.2", - "@leafygreen-ui/input-option": "^3.0.2", + "@leafygreen-ui/icon-button": "^16.0.3", + "@leafygreen-ui/input-option": "^3.0.4", "@leafygreen-ui/lib": "^14.0.2", "@leafygreen-ui/palette": "^4.1.3", "@leafygreen-ui/polymorphic": "^2.0.5", - "@leafygreen-ui/popover": "^13.0.2", + "@leafygreen-ui/popover": "^13.0.3", "@leafygreen-ui/tokens": "^2.11.3", - "@leafygreen-ui/typography": "^20.0.2", + "@leafygreen-ui/typography": "^20.1.1", "lodash": "^4.17.21", "polished": "^4.3.1", "react-transition-group": "^4.4.5" @@ -54371,9 +54412,9 @@ } }, "@leafygreen-ui/popover": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/popover/-/popover-13.0.2.tgz", - "integrity": "sha512-pLqDhR50O41gN7iBf8JkhUsl2fLSSN7p++yY3do+OLQ8sRWpsvB9Plzw6eQuix4+O6mpSg25FbWn9Hp2/o4BRQ==", + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/popover/-/popover-13.0.3.tgz", + "integrity": "sha512-5dmqbfwO2m5hYcgtlQr58JVK1oYdOIqGOQBtx0R9fjxrObuX2XpGa7g0ej9HuqVI+LrKD/BxsbVozlaVz4WmIQ==", "requires": { "@floating-ui/react": "^0.26.28", "@leafygreen-ui/emotion": "^4.0.9", @@ -54495,6 +54536,40 @@ } } }, + "@leafygreen-ui/split-button": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/split-button/-/split-button-4.1.5.tgz", + "integrity": "sha512-vlDo9UxkEVAxMzQfW4JVHKyb8vTQfVxA1UnlKKA0HAsRblOtjldSSyOf60jg9KPvtGf/C7uMv/pM0D2sJzpcOw==", + "requires": { + "@leafygreen-ui/button": "^23.0.0", + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/hooks": "^8.3.4", + "@leafygreen-ui/icon": "^13.1.2", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/menu": "^28.0.6", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", + "@leafygreen-ui/popover": "^13.0.3", + "@leafygreen-ui/tokens": "^2.11.3" + }, + "dependencies": { + "@leafygreen-ui/button": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/button/-/button-23.0.0.tgz", + "integrity": "sha512-E2yuIM1oAqW/Fe9S/mwK+GqBDThr31P+Y27cd0oPD6ZTtyWruKY60M7dBafvqCY+Q3kPPCbBr80Uo8vjs7RXYw==", + "requires": { + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/polymorphic": "^2.0.5", + "@leafygreen-ui/ripple": "^1.1.15", + "@leafygreen-ui/tokens": "^2.11.3", + "@lg-tools/test-harnesses": "^0.1.4", + "polished": "^4.2.2" + } + } + } + }, "@leafygreen-ui/tabs": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/@leafygreen-ui/tabs/-/tabs-14.0.2.tgz", @@ -54603,9 +54678,9 @@ } }, "@leafygreen-ui/typography": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@leafygreen-ui/typography/-/typography-20.0.2.tgz", - "integrity": "sha512-AqBLozuBMjos2UNEVj1A+zi2S2fXEYo0hLoM0ypDSWPwvRICLMYuR855hJiL0BlDZWBb2CrT7WdM7dLa6I+52w==", + "version": "20.1.1", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/typography/-/typography-20.1.1.tgz", + "integrity": "sha512-kdGZaCfdb/UcvKg0yl0YAOYEw0DAY1O5ZCez88vpzxx64KlpivwaM++25Tu414jZFyL8TYG8OqobgH7LWVRxQQ==", "requires": { "@leafygreen-ui/emotion": "^4.0.9", "@leafygreen-ui/icon": "^13.1.2", @@ -56295,6 +56370,7 @@ "@leafygreen-ui/search-input": "^5.0.2", "@leafygreen-ui/segmented-control": "^10.0.2", "@leafygreen-ui/select": "^14.0.2", + "@leafygreen-ui/split-button": "^4.1.5", "@leafygreen-ui/table": "^13.0.1", "@leafygreen-ui/tabs": "^14.0.2", "@leafygreen-ui/text-area": "^10.0.2", diff --git a/packages/compass-components/package.json b/packages/compass-components/package.json index 931d24b7572..99ccabba336 100644 --- a/packages/compass-components/package.json +++ b/packages/compass-components/package.json @@ -63,6 +63,7 @@ "@leafygreen-ui/search-input": "^5.0.2", "@leafygreen-ui/segmented-control": "^10.0.2", "@leafygreen-ui/select": "^14.0.2", + "@leafygreen-ui/split-button": "^4.1.5", "@leafygreen-ui/table": "^13.0.1", "@leafygreen-ui/tabs": "^14.0.2", "@leafygreen-ui/text-area": "^10.0.2", From a78cc068fa4aa09720fe6233208b8b1cb8112335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 17 Dec 2024 09:58:36 +0100 Subject: [PATCH 02/20] Make ItemActionControls hidable and use a SplitButton --- .../actions/item-action-controls.tsx | 8 ++-- .../components/actions/item-action-group.tsx | 15 ++++--- .../components/actions/item-action-menu.tsx | 19 ++++++-- .../src/components/actions/types.ts | 1 + packages/compass-components/src/index.ts | 1 + .../src/connect-button.tsx | 43 +++++++++++++++++-- 6 files changed, 72 insertions(+), 15 deletions(-) diff --git a/packages/compass-components/src/components/actions/item-action-controls.tsx b/packages/compass-components/src/components/actions/item-action-controls.tsx index 0023b1bb537..31496707a53 100644 --- a/packages/compass-components/src/components/actions/item-action-controls.tsx +++ b/packages/compass-components/src/components/actions/item-action-controls.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import { spacing } from '@leafygreen-ui/tokens'; import { css, cx } from '@leafygreen-ui/emotion'; import type { RenderMode } from '@leafygreen-ui/popover'; @@ -47,8 +47,10 @@ export function ItemActionControls({ collapseToMenuThreshold = 2, 'data-testid': dataTestId, }: ItemActionControlsProps) { + const [isHidable, setHidable] = useState(true); + const sharedProps = { - isVisible, + setHidable, onAction, className: cx('item-action-controls', className), iconClassName, @@ -61,7 +63,7 @@ export function ItemActionControls({ renderMode, }; - if (actions.length === 0) { + if (actions.length === 0 || (isHidable && !isVisible)) { return null; } diff --git a/packages/compass-components/src/components/actions/item-action-group.tsx b/packages/compass-components/src/components/actions/item-action-group.tsx index 83a86acc2e2..dde60f96de3 100644 --- a/packages/compass-components/src/components/actions/item-action-group.tsx +++ b/packages/compass-components/src/components/actions/item-action-group.tsx @@ -25,22 +25,28 @@ const containerStyle = css({ export type ItemActionGroupProps = { actions: (GroupedItemAction | ItemSeparator)[]; onAction(actionName: Action): void; + isVisible?: boolean; + /** + * Called to signal to the parent if the component wants to prevent becoming hidden. + * Note: In the current implementation, this is called when a menu is opened. + */ + setHidable?(hidable: boolean): void; className?: string; iconClassName?: string; iconStyle?: React.CSSProperties; iconSize?: ItemActionButtonSize; - isVisible?: boolean; 'data-testid'?: string; }; export function ItemActionGroup({ actions, onAction, + isVisible = true, + setHidable, className, iconClassName, iconStyle, iconSize = ItemActionButtonSize.Default, - isVisible = true, 'data-testid': dataTestId, }: ItemActionGroupProps) { const onClick: React.MouseEventHandler = useCallback( @@ -55,9 +61,7 @@ export function ItemActionGroup({ [onAction] ); - const shouldRender = isVisible && actions.length > 0; - - if (!shouldRender) { + if (!isVisible || actions.length === 0) { return null; } @@ -84,6 +88,7 @@ export function ItemActionGroup({ iconClassName={iconClassName} onClick={onClick} data-testid={actionTestId(dataTestId, itemProps.action)} + setHidable={setHidable} /> ); diff --git a/packages/compass-components/src/components/actions/item-action-menu.tsx b/packages/compass-components/src/components/actions/item-action-menu.tsx index 205f41536a8..485ea92a560 100644 --- a/packages/compass-components/src/components/actions/item-action-menu.tsx +++ b/packages/compass-components/src/components/actions/item-action-menu.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { css, cx } from '@leafygreen-ui/emotion'; import type { RenderMode } from '@leafygreen-ui/popover'; @@ -32,6 +32,12 @@ const containerStyle = css({ export type ItemActionMenuProps = { actions: MenuAction[]; + isVisible?: boolean; + /** + * Called to signal to the parent if the component wants to prevent becoming hidden. + * Note: In the current implementation, this is called when a menu is opened. + */ + setHidable?(hideable: boolean): void; onAction(actionName: Action): void; // TODO: Merge className and menuClassName className?: string; @@ -40,13 +46,13 @@ export type ItemActionMenuProps = { iconClassName?: string; iconStyle?: React.CSSProperties; iconSize?: ItemActionButtonSize; - isVisible?: boolean; 'data-testid'?: string; }; export function ItemActionMenu({ - isVisible = true, actions, + isVisible = true, + setHidable, onAction, className, menuClassName, @@ -79,6 +85,13 @@ export function ItemActionMenu({ [onAction] ); + // Opening the menu should keep it visible + useEffect(() => { + if (setHidable) { + setHidable(!isMenuOpen); + } + }, [setHidable, isMenuOpen]); + const shouldRender = isMenuOpen || (isVisible && actions.length > 0); if (!shouldRender) { diff --git a/packages/compass-components/src/components/actions/types.ts b/packages/compass-components/src/components/actions/types.ts index c7d36a07b09..83e2989d1b0 100644 --- a/packages/compass-components/src/components/actions/types.ts +++ b/packages/compass-components/src/components/actions/types.ts @@ -28,6 +28,7 @@ export type ItemComponentProps = Omit< iconStyle?: React.CSSProperties; 'data-testid'?: string; onClick(evt: React.MouseEvent): void; + setHidable?(hidable: boolean): void; }; export type ItemAction = { diff --git a/packages/compass-components/src/index.ts b/packages/compass-components/src/index.ts index e2b797c24a5..a79645f7f9d 100644 --- a/packages/compass-components/src/index.ts +++ b/packages/compass-components/src/index.ts @@ -68,6 +68,7 @@ export { Size as ButtonSize, Variant as ButtonVariant, } from '@leafygreen-ui/button'; +export { SplitButton } from '@leafygreen-ui/split-button'; export { default as LeafyGreenProvider } from '@leafygreen-ui/leafygreen-provider'; diff --git a/packages/compass-connections-navigation/src/connect-button.tsx b/packages/compass-connections-navigation/src/connect-button.tsx index c39d3848c17..8c6fa7a87db 100644 --- a/packages/compass-connections-navigation/src/connect-button.tsx +++ b/packages/compass-connections-navigation/src/connect-button.tsx @@ -1,13 +1,22 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { - Button, + css, + Icon, + MenuItem, + SplitButton, type ItemComponentProps, } from '@mongodb-js/compass-components'; import type { Actions } from './constants'; +const styles = css({ + // whiteSpace: 'nowrap', + // width: 'auto', +}); + type ConnectButtonProps = ItemComponentProps; export function ConnectButton({ + setHidable, action, tooltip, label, @@ -18,10 +27,20 @@ export function ConnectButton({ className, 'data-testid': testId, }: ConnectButtonProps) { + const [isOpen, setOpen] = useState(false); + + // Opening the menu should keep it visible + useEffect(() => { + if (setHidable) { + setHidable(!isOpen); + } + }, [setHidable, isOpen]); + return ( - + ); } From 81364a7c45984eabe5ccdefd829578f201cdf740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 17 Dec 2024 14:13:14 +0100 Subject: [PATCH 03/20] Fix menu item width --- .../compass-connections-navigation/src/connect-button.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/compass-connections-navigation/src/connect-button.tsx b/packages/compass-connections-navigation/src/connect-button.tsx index 8c6fa7a87db..ad6bed1b207 100644 --- a/packages/compass-connections-navigation/src/connect-button.tsx +++ b/packages/compass-connections-navigation/src/connect-button.tsx @@ -8,9 +8,8 @@ import { } from '@mongodb-js/compass-components'; import type { Actions } from './constants'; -const styles = css({ - // whiteSpace: 'nowrap', - // width: 'auto', +const menuItemStyles = css({ + width: 'max-content', }); type ConnectButtonProps = ItemComponentProps; @@ -58,7 +57,7 @@ export function ConnectButton({ , } > Connect in a New Window From dcffcef0d050f1a71429c2500252b00766b3f5df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 22:57:06 +0100 Subject: [PATCH 04/20] Fix event emitter types on CompassApplication --- packages/compass/src/main/application.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/compass/src/main/application.ts b/packages/compass/src/main/application.ts index 4166c9bfdf4..eac65757320 100644 --- a/packages/compass/src/main/application.ts +++ b/packages/compass/src/main/application.ts @@ -381,9 +381,6 @@ class CompassApplication { event: 'show-log-file-dialog', handler: () => void ): typeof CompassApplication; - // @ts-expect-error typescript is not happy with this overload even though it - // worked when it wasn't static and the implementation does - // match the overload declaration static on( event: 'new-window', handler: (bw: BrowserWindow) => void @@ -402,7 +399,7 @@ class CompassApplication { ): typeof CompassApplication; static on( event: string, - handler: (...args: unknown[]) => void + handler: (...args: any[]) => void ): typeof CompassApplication { this.emitter.on(event, handler); return this; From 070641fb70e7b4fd84cef2a999cecb38e8e51ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:00:04 +0100 Subject: [PATCH 05/20] Propagate from connections-navigation action through main process IPC --- packages/compass-connections-navigation/src/constants.tsx | 1 + .../src/stores/connections-store-redux.ts | 7 +++++++ packages/compass-connections/src/stores/store-context.tsx | 4 ++++ .../multiple-connections/connections-navigation.tsx | 6 ++++++ .../src/components/multiple-connections/sidebar.tsx | 4 ++++ packages/compass/src/app/index.tsx | 5 +++++ 6 files changed, 27 insertions(+) diff --git a/packages/compass-connections-navigation/src/constants.tsx b/packages/compass-connections-navigation/src/constants.tsx index 316751e78e8..ce8c7911228 100644 --- a/packages/compass-connections-navigation/src/constants.tsx +++ b/packages/compass-connections-navigation/src/constants.tsx @@ -15,6 +15,7 @@ export type Actions = | 'duplicate-connection' | 'remove-connection' | 'connection-connect' + | 'connection-connect-in-new-window' | 'connection-disconnect' | 'connection-performance-metrics' | 'open-connection-info' diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index 0e9c97d7c4c..d2efc991b82 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -1420,6 +1420,13 @@ const openConnectionClosedWithNonRetryableErrorToast = ( }); }; +export const connectInNewWindow = + (connectionInfo: ConnectionInfo): ConnectionsThunkAction => + (_dispatch, _getState, { globalAppRegistry }) => { + // TODO: Consider building a connection string? + globalAppRegistry.emit('connect-in-new-window', connectionInfo.id); + }; + export const connect = ( connectionInfo: ConnectionInfo ): ConnectionsThunkAction< diff --git a/packages/compass-connections/src/stores/store-context.tsx b/packages/compass-connections/src/stores/store-context.tsx index d78c037f4c3..f32da226196 100644 --- a/packages/compass-connections/src/stores/store-context.tsx +++ b/packages/compass-connections/src/stores/store-context.tsx @@ -18,6 +18,7 @@ import type { import { cancelEditConnection, connect as connectionsConnect, + connectInNewWindow, saveAndConnect, connectionsEventEmitter, createNewConnection, @@ -88,6 +89,9 @@ function getConnectionsActions(dispatch: ConnectionsStore['dispatch']) { connect: (connectionInfo: ConnectionInfo) => { return dispatch(connectionsConnect(connectionInfo)); }, + connectInNewWindow: (connectionInfo: ConnectionInfo) => { + return dispatch(connectInNewWindow(connectionInfo)); + }, saveAndConnect: (connectionInfo: ConnectionInfo) => { return dispatch(saveAndConnect(connectionInfo)); }, diff --git a/packages/compass-sidebar/src/components/multiple-connections/connections-navigation.tsx b/packages/compass-sidebar/src/components/multiple-connections/connections-navigation.tsx index 8efee16c79e..104571b764f 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/connections-navigation.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/connections-navigation.tsx @@ -133,6 +133,7 @@ type ConnectionsNavigationComponentProps = { updater: (filter: ConnectionsFilter) => ConnectionsFilter ): void; onConnect(info: ConnectionInfo): void; + onConnectInNewWindow(info: ConnectionInfo): void; onNewConnection(): void; onEditConnection(info: ConnectionInfo): void; onRemoveConnection(info: ConnectionInfo): void; @@ -178,6 +179,7 @@ const ConnectionsNavigation: React.FC = ({ isPerformanceTabSupported, onFilterChange, onConnect, + onConnectInNewWindow, onNewConnection, onEditConnection, onRemoveConnection, @@ -347,6 +349,9 @@ const ConnectionsNavigation: React.FC = ({ case 'connection-connect': onConnect(item.connectionInfo); return; + case 'connection-connect-in-new-window': + onConnectInNewWindow(item.connectionInfo); + return; case 'edit-connection': onEditConnection(item.connectionInfo); return; @@ -383,6 +388,7 @@ const ConnectionsNavigation: React.FC = ({ onOpenConnectionInfo, onDisconnect, onConnect, + onConnectInNewWindow, onEditConnection, onCopyConnectionString, onToggleFavoriteConnectionInfo, diff --git a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx index efa48a777eb..c1f6345717d 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx @@ -108,6 +108,7 @@ export function MultipleConnectionSidebar({ const connectionsWithStatus = useConnectionsWithStatus(); const { connect, + connectInNewWindow, disconnect, createNewConnection, editConnection, @@ -182,6 +183,9 @@ export function MultipleConnectionSidebar({ onConnect={(connectionInfo) => { void connect(connectionInfo); }} + onConnectInNewWindow={(connectionInfo) => { + connectInNewWindow(connectionInfo); + }} onNewConnection={createNewConnection} onEditConnection={(connectionInfo) => { editConnection(connectionInfo.id); diff --git a/packages/compass/src/app/index.tsx b/packages/compass/src/app/index.tsx index 620442ed9b6..51ed4b491a0 100644 --- a/packages/compass/src/app/index.tsx +++ b/packages/compass/src/app/index.tsx @@ -368,6 +368,11 @@ const app = { }); } ); + // Propagate events from global app registry to the main process + globalAppRegistry.on('connect-in-new-window', (connectionId: string) => { + void ipcRenderer?.call('app:connect-in-new-window', connectionId); + }); + // As soon as dom is ready, render and set up the rest. state.render(); marky.stop('Time to Connect rendered'); From faa13e5a912d9435d93206b297f74acb33c98d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:03:23 +0100 Subject: [PATCH 06/20] Add connection-id support to the auto-connect feature --- .../tests/auto-connect.test.ts | 33 +++++++++++++++++ packages/compass/src/main/auto-connect.ts | 37 +++++++++++++++++-- .../compass-main-connection-storage.spec.ts | 13 +++++++ .../src/compass-main-connection-storage.ts | 11 ++++++ 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/packages/compass-e2e-tests/tests/auto-connect.test.ts b/packages/compass-e2e-tests/tests/auto-connect.test.ts index 42d9d0ae24f..c66a8e5f479 100644 --- a/packages/compass-e2e-tests/tests/auto-connect.test.ts +++ b/packages/compass-e2e-tests/tests/auto-connect.test.ts @@ -12,6 +12,7 @@ import * as Selectors from '../helpers/selectors'; import os from 'os'; import path from 'path'; import { promises as fs } from 'fs'; +import { DEFAULT_CONNECTION_NAMES } from '../helpers/test-runner-context'; const connectionStringSuccess = 'mongodb://127.0.0.1:27091/test'; const connectionNameSuccess = 'Success'; @@ -21,6 +22,22 @@ const connectionNameUnreachable = 'Unreachable'; const connectionStringInvalid = 'http://example.com'; const connectionNameInvalid = 'Invalid'; +async function createDefaultConnectionAndClose(name: string | undefined) { + const compass = await init(name); + try { + const { browser } = compass; + await browser.setupDefaultConnections(); + const connectionName = DEFAULT_CONNECTION_NAMES[0]; + const connectionId = await browser.getConnectionIdByName(connectionName); + if (!connectionId) { + throw new Error('Expected a connection id'); + } + return { connectionName, connectionId }; + } finally { + await cleanup(compass); + } +} + describe('Automatically connecting from the command line', function () { let tmpdir: string; let i = 0; @@ -127,6 +144,22 @@ describe('Automatically connecting from the command line', function () { } }); + it('works with a connection id on the command line', async function () { + // Create the connection + const { connectionId, connectionName } = + await createDefaultConnectionAndClose(this.test?.fullTitle()); + const compass = await init(this.test?.fullTitle(), { + wrapBinary: positionalArgs([connectionId]), + // reuse the same user directory so we'd get the same connections + firstRun: false, + }); + try { + await waitForConnectionSuccessAndCheckConnection(compass, connectionName); + } finally { + await cleanup(compass); + } + }); + it('fails with an unreachable URL', async function () { const args = [ `--file=${path.join(tmpdir, 'exported.json')}`, diff --git a/packages/compass/src/main/auto-connect.ts b/packages/compass/src/main/auto-connect.ts index becfdd587d9..f72a5b42c07 100644 --- a/packages/compass/src/main/auto-connect.ts +++ b/packages/compass/src/main/auto-connect.ts @@ -5,6 +5,7 @@ import { hasDisallowedConnectionStringOptions } from './validate-connection-stri import COMPASS_ICON from './icon'; import { createLogger, mongoLogId } from '@mongodb-js/compass-logging'; import { redactConnectionString } from 'mongodb-connection-string-url'; +import { UUID } from 'mongodb'; const { log } = createLogger('COMPASS-AUTO-CONNECT-MAIN'); export type AutoConnectPreferences = Partial< @@ -22,7 +23,7 @@ export type AutoConnectPreferences = Partial< let autoConnectWindow: BrowserWindow['id'] | undefined = undefined; const browserWindowStates = new Map< BrowserWindow['id'], - { url?: string; disconnected?: boolean } + { url?: string; connectionId?: string; disconnected?: boolean } >(); export function resetForTesting(): void { @@ -73,6 +74,16 @@ export function registerMongoDbUrlForBrowserWindow( browserWindowStates.set(bw.id, { url }); } +export function registerConnectionIdForBrowserWindow( + bw: Pick | undefined | null, + connectionId: string +): void { + if (!bw) { + return; + } + browserWindowStates.set(bw.id, { connectionId }); +} + export const getConnectionStringFromArgs = (args?: string[]) => args?.[0]; const shouldPreventAutoConnect = async ({ @@ -111,6 +122,14 @@ export async function getWindowAutoConnectPreferences( const windowState = browserWindowStates.get(id); + // Auto connect to any connection ID, right away + if (windowState?.connectionId) { + return { + positionalArguments: [windowState.connectionId], + shouldAutoConnect: true, + }; + } + // Do not auto-connect in Compass windows other than the primary/first-created one. // Do auto-connect if this is a new window on macos that has been opened via open-url. if (autoConnectWindow !== id && !windowState?.url) { @@ -133,10 +152,10 @@ export async function getWindowAutoConnectPreferences( } if (windowState?.url) { - return Promise.resolve({ + return { positionalArguments: [windowState.url], shouldAutoConnect: true, - }); + }; } const { @@ -148,6 +167,18 @@ export async function getWindowAutoConnectPreferences( trustedConnectionString, } = preferences.getPreferences(); + // Auto connect to any connection ID, right away + if ( + !file && + positionalArguments?.length === 1 && + UUID.isValid(positionalArguments[0]) + ) { + return { + positionalArguments: [positionalArguments[0]], + shouldAutoConnect: true, + }; + } + // The about: accounts for webdriverio in the e2e tests appending the argument for every run if ( !file && diff --git a/packages/connection-storage/src/compass-main-connection-storage.spec.ts b/packages/connection-storage/src/compass-main-connection-storage.spec.ts index 00948063deb..a52a740128e 100644 --- a/packages/connection-storage/src/compass-main-connection-storage.spec.ts +++ b/packages/connection-storage/src/compass-main-connection-storage.spec.ts @@ -1379,6 +1379,19 @@ describe('ConnectionStorage', function () { ); }); + it('should return autoConnectInfo when an existing connection id is provided', async function () { + const connectionInfo = getConnectionInfo({ lastUsed: new Date() }); + await writeFakeConnection(tmpDir, { connectionInfo }); + const info = await connectionStorage.getAutoConnectInfo({ + shouldAutoConnect: true, + positionalArguments: [connectionInfo.id], + }); + expect(info?.id).to.equal(connectionInfo.id); + expect(info?.connectionOptions).to.deep.equal( + connectionInfo.connectionOptions + ); + }); + context('when autoConnectInfo is available', function () { beforeEach(async function () { await connectionStorage.getAutoConnectInfo({ diff --git a/packages/connection-storage/src/compass-main-connection-storage.ts b/packages/connection-storage/src/compass-main-connection-storage.ts index ce27ccc5466..7d089c83893 100644 --- a/packages/connection-storage/src/compass-main-connection-storage.ts +++ b/packages/connection-storage/src/compass-main-connection-storage.ts @@ -298,6 +298,17 @@ class CompassMainConnectionStorage implements ConnectionStorage { password, }); } else { + // Assuming the positional argument refers to an existing connection id + if (positionalArguments.length === 1) { + // Attempt to load it and return if found + const possibleConnection = await this.load({ + id: positionalArguments[0], + }); + if (possibleConnection) { + return possibleConnection; + } + } + // Determine if this is a valid connection string or a connection ID const connectionString = getConnectionStringFromArgs(positionalArguments); if (!connectionString) { throw new Error('Could not find a connection string'); From 48879d86bb92fd51d38272729e296e9105e423d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:04:04 +0100 Subject: [PATCH 07/20] Wire up the ConnectButton --- .../src/components/leafygreen.tsx | 6 +++ .../src/connect-button.tsx | 45 +++++++++++++++---- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/compass-components/src/components/leafygreen.tsx b/packages/compass-components/src/components/leafygreen.tsx index 0d264075ad0..fd578eac734 100644 --- a/packages/compass-components/src/components/leafygreen.tsx +++ b/packages/compass-components/src/components/leafygreen.tsx @@ -11,12 +11,14 @@ import Code, { Language } from '@leafygreen-ui/code'; import ConfirmationModal from '@leafygreen-ui/confirmation-modal'; import { default as LeafyGreenIcon } from '@leafygreen-ui/icon'; import type { Size as LeafyGreenIconSize } from '@leafygreen-ui/icon'; +export type { GlyphName } from '@leafygreen-ui/icon'; import { AtlasNavGraphic, MongoDBLogoMark, MongoDBLogo, } from '@leafygreen-ui/logo'; import { Menu, MenuSeparator, MenuItem } from '@leafygreen-ui/menu'; +export type { MenuItemProps } from '@leafygreen-ui/menu'; import { InfoSprinkle } from '@leafygreen-ui/info-sprinkle'; // If a leafygreen Menu (and therefore MenuItems) makes its way into a
, @@ -30,6 +32,10 @@ import { InfoSprinkle } from '@leafygreen-ui/info-sprinkle'; import Modal, { Footer as ModalFooter } from '@leafygreen-ui/modal'; import MarketingModal from '@leafygreen-ui/marketing-modal'; import { Pipeline, Stage } from '@leafygreen-ui/pipeline'; +export type { + InferredPolymorphicProps, + PolymorphicProps, +} from '@leafygreen-ui/polymorphic'; import Popover from '@leafygreen-ui/popover'; import { RadioBox, RadioBoxGroup } from '@leafygreen-ui/radio-box-group'; import { Radio, RadioGroup } from '@leafygreen-ui/radio-group'; diff --git a/packages/compass-connections-navigation/src/connect-button.tsx b/packages/compass-connections-navigation/src/connect-button.tsx index ad6bed1b207..362affcfcff 100644 --- a/packages/compass-connections-navigation/src/connect-button.tsx +++ b/packages/compass-connections-navigation/src/connect-button.tsx @@ -4,14 +4,36 @@ import { Icon, MenuItem, SplitButton, + type GlyphName, type ItemComponentProps, + type PolymorphicProps, + type MenuItemProps, } from '@mongodb-js/compass-components'; import type { Actions } from './constants'; const menuItemStyles = css({ - width: 'max-content', + minWidth: 'max-content', }); +type ConnectMenuItemProps = { + action: Actions; + glyph: GlyphName; +} & PolymorphicProps<'button', Omit>; + +function ConnectMenuItem({ action, glyph, ...rest }: ConnectMenuItemProps) { + return ( + } + {...rest} + /> + ); +} + +// Hack to make SplitButton consider this as a MenuItem +ConnectMenuItem.displayName = 'MenuItem'; + type ConnectButtonProps = ItemComponentProps; export function ConnectButton({ @@ -51,17 +73,24 @@ export function ConnectButton({ darkMode={false} open={isOpen} setOpen={setOpen} + triggerAriaLabel="see more connection options" menuItems={[ - }> + Connect Here - , - } + , + Connect in a New Window - , + , ]} > {label} From 70b558b67ed5a1fe9a74332ea31ec8b6d38aca48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:05:05 +0100 Subject: [PATCH 08/20] Propagate from main IPC into window manager --- packages/compass/src/main/window-manager.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/compass/src/main/window-manager.ts b/packages/compass/src/main/window-manager.ts index fe66f91cbca..57393cafc4d 100644 --- a/packages/compass/src/main/window-manager.ts +++ b/packages/compass/src/main/window-manager.ts @@ -20,6 +20,7 @@ import type { CompassApplication } from './application'; import { getWindowAutoConnectPreferences, registerMongoDbUrlForBrowserWindow, + registerConnectionIdForBrowserWindow, } from './auto-connect'; const { debug } = createLogger('COMPASS-WINDOW-MANAGER'); @@ -95,16 +96,19 @@ async function showWindowWhenReady(bw: BrowserWindow) { */ function showConnectWindow( compassApp: typeof CompassApplication, - opts: Partial< + { + rendererUrl = DEFAULT_URL, + mongodbUrl, + connectionId, + ...opts + }: Partial< BrowserWindowConstructorOptions & { rendererUrl: string; mongodbUrl: string; + connectionId: string; } > = {} ): BrowserWindow { - const rendererUrl = opts.rendererUrl ?? DEFAULT_URL; - const mongodbUrl = opts.mongodbUrl; - const windowOpts = { width: Number(DEFAULT_WIDTH), height: Number(DEFAULT_HEIGHT), @@ -143,6 +147,9 @@ function showConnectWindow( if (mongodbUrl) { registerMongoDbUrlForBrowserWindow(window, mongodbUrl); } + if (connectionId) { + registerConnectionIdForBrowserWindow(window, connectionId); + } if (networkTraffic !== true) { // https://github.com/electron/electron/issues/22995 window.webContents.session.setSpellCheckerDictionaryDownloadURL( @@ -265,6 +272,8 @@ class CompassWindowManager { return getWindowAutoConnectPreferences(bw, compassApp.preferences); }, 'test:show-connect-window': () => showConnectWindow(compassApp), + 'app:connect-in-new-window': (event, connectionId: string) => + showConnectWindow(compassApp, { connectionId }), }); ipcMain?.on('show-file', (evt, filename: string) => { From 2edd4577fd5bb9c39d7332992c207f9705993b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:05:59 +0100 Subject: [PATCH 09/20] Add a test --- .../compass-e2e-tests/helpers/selectors.ts | 12 +++++ .../tests/connection.test.ts | 45 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 9951028fe0b..fbf578994ec 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -244,6 +244,10 @@ export const ConenctionToastCancelConnectionButton = // Connections sidebar export const ConnectionsTitle = '[data-testid="connections-header"]'; export const SidebarNewConnectionButton = '[data-action="add-new-connection"]'; +export const ConnectDropdownButton = + '[data-testid="sidebar-navigation-item-actions-connection-connect-action"] + button'; +export const ConnectInNewWindowButton = + '[data-action="connection-connect-in-new-window"]'; export const ConnectionMenu = '[data-testid="sidebar-navigation-item-actions"]'; export const CreateDatabaseButton = '[data-testid="sidebar-navigation-item-actions-create-database-action"]'; @@ -365,6 +369,14 @@ export const sidebarConnectionButton = (connectionName: string): string => { )} [data-action="connection-connect"]`; }; +export const sidebarConnectionDropdownButton = ( + connectionName: string +): string => { + return `${sidebarConnection(connectionName)} ${ + Multiple.ConnectDropdownButton + }`; +}; + export const sidebarConnectionActionButton = ( connectionName: string, selector: string diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index 7865a253cef..c9d3ab16bf7 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -20,6 +20,7 @@ import { import type { Compass } from '../helpers/compass'; import type { ConnectFormState } from '../helpers/connect-form-state'; import * as Selectors from '../helpers/selectors'; +import { DEFAULT_CONNECTION_NAMES } from '../helpers/test-runner-context'; async function disconnect(browser: CompassBrowser) { try { @@ -641,6 +642,50 @@ describe('Connection string', function () { }); }); +describe('Connect in a new window', () => { + let compass: Compass; + let browser: CompassBrowser; + + before(async function () { + compass = await init(this.test?.fullTitle(), { + firstRun: false, + }); + browser = compass.browser; + await browser.setupDefaultConnections(); + }); + + after(async function () { + await cleanup(compass); + }); + + it('can connect in new window', async function (this) { + skipForWeb(this, 'connecting in new window is not supported on web'); + const connectionName = DEFAULT_CONNECTION_NAMES[0]; + const connectionSelector = Selectors.sidebarConnection(connectionName); + await browser.hover(connectionSelector); + + expect((await browser.getWindowHandles()).length).equals(1); + + const connectionElement = browser.$(connectionSelector); + await browser.clickVisible( + connectionElement.$(Selectors.ConnectDropdownButton) + ); + await browser.clickVisible( + connectionElement.$(Selectors.ConnectInNewWindowButton) + ); + + const windowsAfter = await browser.getWindowHandles(); + expect(windowsAfter.length).equals(2); + const [, newWindowHandle] = windowsAfter; + await browser.switchToWindow(newWindowHandle); + await browser.waitForConnectionResult(connectionName, { + connectionStatus: 'success', + }); + }); + + // TODO: Add a test for we to ensure the SplitButton isn't visible on Web +}); + describe('Connection form', function () { let compass: Compass; let browser: CompassBrowser; From c77f2a8b3917b214c91122fc829665894d70da95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 19 Dec 2024 23:47:50 +0100 Subject: [PATCH 10/20] Remove an outdated comment --- .../compass-connections/src/stores/connections-store-redux.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/compass-connections/src/stores/connections-store-redux.ts b/packages/compass-connections/src/stores/connections-store-redux.ts index d2efc991b82..f9a4e9abacf 100644 --- a/packages/compass-connections/src/stores/connections-store-redux.ts +++ b/packages/compass-connections/src/stores/connections-store-redux.ts @@ -1423,7 +1423,6 @@ const openConnectionClosedWithNonRetryableErrorToast = ( export const connectInNewWindow = (connectionInfo: ConnectionInfo): ConnectionsThunkAction => (_dispatch, _getState, { globalAppRegistry }) => { - // TODO: Consider building a connection string? globalAppRegistry.emit('connect-in-new-window', connectionInfo.id); }; From 0a8e1429972a57a6cd4644f950f4ddd92652874c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 6 Jan 2025 20:04:30 +0100 Subject: [PATCH 11/20] Apply suggestions from code review Co-authored-by: Sergey Petushkov --- package-lock.json | 2 ++ .../src/components/multiple-connections/sidebar.tsx | 4 +--- packages/compass/package.json | 1 + packages/compass/src/main/auto-connect.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f128c87e28b..82d06d10e0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43374,6 +43374,7 @@ "@mongodb-js/webpack-config-compass": "^1.6.0", "@segment/analytics-node": "^1.1.4", "ampersand-view": "^9.0.0", + "bson": "^6.10.1", "chai": "^4.3.4", "chalk": "^4.1.2", "clean-stack": "^2.0.0", @@ -80198,6 +80199,7 @@ "@mongosh/node-runtime-worker-thread": "^3.0.2", "@segment/analytics-node": "^1.1.4", "ampersand-view": "^9.0.0", + "bson": "^6.10.1", "chai": "^4.3.4", "chalk": "^4.1.2", "clean-stack": "^2.0.0", diff --git a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx index c1f6345717d..27c523fc4ca 100644 --- a/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx +++ b/packages/compass-sidebar/src/components/multiple-connections/sidebar.tsx @@ -183,9 +183,7 @@ export function MultipleConnectionSidebar({ onConnect={(connectionInfo) => { void connect(connectionInfo); }} - onConnectInNewWindow={(connectionInfo) => { - connectInNewWindow(connectionInfo); - }} + onConnectInNewWindow={connectInNewWindow} onNewConnection={createNewConnection} onEditConnection={(connectionInfo) => { editConnection(connectionInfo.id); diff --git a/packages/compass/package.json b/packages/compass/package.json index 10a6d36b953..ac86b2308ec 100644 --- a/packages/compass/package.json +++ b/packages/compass/package.json @@ -237,6 +237,7 @@ "@mongodb-js/webpack-config-compass": "^1.6.0", "@segment/analytics-node": "^1.1.4", "ampersand-view": "^9.0.0", + "bson": "^6.10.1", "chai": "^4.3.4", "chalk": "^4.1.2", "clean-stack": "^2.0.0", diff --git a/packages/compass/src/main/auto-connect.ts b/packages/compass/src/main/auto-connect.ts index f72a5b42c07..0ab2c63c39a 100644 --- a/packages/compass/src/main/auto-connect.ts +++ b/packages/compass/src/main/auto-connect.ts @@ -5,7 +5,7 @@ import { hasDisallowedConnectionStringOptions } from './validate-connection-stri import COMPASS_ICON from './icon'; import { createLogger, mongoLogId } from '@mongodb-js/compass-logging'; import { redactConnectionString } from 'mongodb-connection-string-url'; -import { UUID } from 'mongodb'; +import { UUID } from 'bson'; const { log } = createLogger('COMPASS-AUTO-CONNECT-MAIN'); export type AutoConnectPreferences = Partial< From 3804739e7d0b5f498393803e97aafe15e685b19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 6 Jan 2025 22:50:42 +0100 Subject: [PATCH 12/20] Add enableConnectInNewWindow preference controlling connect button --- .../src/components/actions/types.ts | 2 +- .../src/connect-button-with-menu.tsx | 97 +++++++++++++ .../src/connect-button.tsx | 131 +++++------------- .../src/preferences-schema.ts | 16 ++- packages/compass-web/src/preferences.tsx | 1 + 5 files changed, 151 insertions(+), 96 deletions(-) create mode 100644 packages/compass-connections-navigation/src/connect-button-with-menu.tsx diff --git a/packages/compass-components/src/components/actions/types.ts b/packages/compass-components/src/components/actions/types.ts index 83e2989d1b0..59bd3ae0694 100644 --- a/packages/compass-components/src/components/actions/types.ts +++ b/packages/compass-components/src/components/actions/types.ts @@ -27,7 +27,7 @@ export type ItemComponentProps = Omit< iconClassName?: string; iconStyle?: React.CSSProperties; 'data-testid'?: string; - onClick(evt: React.MouseEvent): void; + onClick: (evt: React.MouseEvent) => void; setHidable?(hidable: boolean): void; }; diff --git a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx new file mode 100644 index 00000000000..67333ecd8dc --- /dev/null +++ b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx @@ -0,0 +1,97 @@ +import React, { useState, useEffect } from 'react'; +import { + css, + Icon, + MenuItem, + SplitButton, + type GlyphName, + type ItemComponentProps, + type PolymorphicProps, + type MenuItemProps, +} from '@mongodb-js/compass-components'; +import type { Actions } from './constants'; + +const menuItemStyles = css({ + minWidth: 'max-content', +}); + +type ConnectMenuItemProps = { + action: Actions; + glyph: GlyphName; +} & PolymorphicProps<'button', Omit>; + +function ConnectMenuItem({ action, glyph, ...rest }: ConnectMenuItemProps) { + return ( + } + {...rest} + /> + ); +} + +// Hack to make SplitButton consider this as a MenuItem +ConnectMenuItem.displayName = 'MenuItem'; + +export function ConnectButtonWithMenu({ + setHidable, + action, + tooltip, + label, + iconSize, + iconStyle, + isDisabled, + onClick, + className, + 'data-testid': testId, +}: ItemComponentProps) { + const [isOpen, setOpen] = useState(false); + + // Opening the menu should keep it visible + useEffect(() => { + if (setHidable) { + setHidable(!isOpen); + } + }, [setHidable, isOpen]); + + return ( + + Connect Here + , + + Connect in a New Window + , + ]} + > + {label} + + ); +} diff --git a/packages/compass-connections-navigation/src/connect-button.tsx b/packages/compass-connections-navigation/src/connect-button.tsx index 362affcfcff..baf1cfe7674 100644 --- a/packages/compass-connections-navigation/src/connect-button.tsx +++ b/packages/compass-connections-navigation/src/connect-button.tsx @@ -1,99 +1,42 @@ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { - css, - Icon, - MenuItem, - SplitButton, - type GlyphName, + Button, type ItemComponentProps, - type PolymorphicProps, - type MenuItemProps, } from '@mongodb-js/compass-components'; import type { Actions } from './constants'; - -const menuItemStyles = css({ - minWidth: 'max-content', -}); - -type ConnectMenuItemProps = { - action: Actions; - glyph: GlyphName; -} & PolymorphicProps<'button', Omit>; - -function ConnectMenuItem({ action, glyph, ...rest }: ConnectMenuItemProps) { - return ( - } - {...rest} - /> - ); -} - -// Hack to make SplitButton consider this as a MenuItem -ConnectMenuItem.displayName = 'MenuItem'; - -type ConnectButtonProps = ItemComponentProps; - -export function ConnectButton({ - setHidable, - action, - tooltip, - label, - iconSize, - iconStyle, - isDisabled, - onClick, - className, - 'data-testid': testId, -}: ConnectButtonProps) { - const [isOpen, setOpen] = useState(false); - - // Opening the menu should keep it visible - useEffect(() => { - if (setHidable) { - setHidable(!isOpen); - } - }, [setHidable, isOpen]); - - return ( - - Connect Here - , - - Connect in a New Window - , - ]} - > - {label} - - ); +import { usePreference } from 'compass-preferences-model/provider'; +import { ConnectButtonWithMenu } from './connect-button-with-menu'; + +export function ConnectButton(props: ItemComponentProps) { + const connectInNewWindowEnabled = usePreference('enableConnectInNewWindow'); + if (connectInNewWindowEnabled) { + return ; + } else { + const { + action, + tooltip, + label, + iconSize, + iconStyle, + isDisabled, + onClick, + className, + 'data-testid': testId, + } = props; + return ( + + ); + } } diff --git a/packages/compass-preferences-model/src/preferences-schema.ts b/packages/compass-preferences-model/src/preferences-schema.ts index c1186252b7c..d306fb4d4bf 100644 --- a/packages/compass-preferences-model/src/preferences-schema.ts +++ b/packages/compass-preferences-model/src/preferences-schema.ts @@ -84,8 +84,10 @@ export type UserConfigurablePreferences = PermanentFeatureFlags & proxy: string; }; +/** + * Internally used preferences that are not configurable + */ export type InternalUserPreferences = { - // These are internally used preferences that are not configurable // by users. showedNetworkOptIn: boolean; // Has the settings dialog been shown before. id: string; @@ -98,6 +100,7 @@ export type InternalUserPreferences = { telemetryAnonymousId?: string; telemetryAtlasUserId?: string; userCreatedAt: number; + enableConnectInNewWindow: boolean; }; // UserPreferences contains all preferences stored to disk. @@ -404,6 +407,17 @@ export const storedUserPreferencesProps: Required<{ validator: z.number().default(Date.now()), type: 'number', }, + /** + * Enables a dropdown in the connections sidebar to connect in a new window. + */ + enableConnectInNewWindow: { + ui: false, + cli: false, + global: false, + description: null, + validator: z.boolean().default(true), + type: 'boolean', + }, /** * Enable/disable the AI services. This is currently set * in the atlas-service initialization where we make a request to the diff --git a/packages/compass-web/src/preferences.tsx b/packages/compass-web/src/preferences.tsx index a329c02dec6..13cdb1060cb 100644 --- a/packages/compass-web/src/preferences.tsx +++ b/packages/compass-web/src/preferences.tsx @@ -56,6 +56,7 @@ export function useCompassWebPreferences( enableCreatingNewConnections: false, enableGlobalWrites: false, optInDataExplorerGenAIFeatures: false, + enableConnectInNewWindow: false, ...initialPreferences, }) ); From 0c638cb34a75ea516f14ee9a4d02d781edfc25cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Mon, 6 Jan 2025 23:07:33 +0100 Subject: [PATCH 13/20] Add test ensuring the right connect button is displayed --- packages/compass-e2e-tests/helpers/compass.ts | 12 ++++++------ .../compass-e2e-tests/helpers/selectors.ts | 9 ++++----- .../compass-e2e-tests/tests/connection.test.ts | 18 ++++++++++++++++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/compass-e2e-tests/helpers/compass.ts b/packages/compass-e2e-tests/helpers/compass.ts index 0395fd8e6fc..8eca286c815 100644 --- a/packages/compass-e2e-tests/helpers/compass.ts +++ b/packages/compass-e2e-tests/helpers/compass.ts @@ -75,12 +75,12 @@ declare global { } } -/* -A helper so we can easily find all the tests we're skipping in compass-web. -Reason is there so you can fill it in and have it show up in search results -in a scannable manner. It is not being output at present because the tests will -be logged as pending anyway. -*/ +/** + * A helper so we can easily find all the tests we're skipping in compass-web. + * Reason is there so you can fill it in and have it show up in search results + * in a scannable manner. It is not being output at present because the tests will + * be logged as pending anyway. + */ export function skipForWeb( test: Mocha.Runnable | Mocha.Context, // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index fbf578994ec..cba86e97ae9 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -244,8 +244,9 @@ export const ConenctionToastCancelConnectionButton = // Connections sidebar export const ConnectionsTitle = '[data-testid="connections-header"]'; export const SidebarNewConnectionButton = '[data-action="add-new-connection"]'; -export const ConnectDropdownButton = - '[data-testid="sidebar-navigation-item-actions-connection-connect-action"] + button'; +export const ConnectButton = + '[data-testid="sidebar-navigation-item-actions-connection-connect-action"]'; +export const ConnectDropdownButton = `${ConnectButton} [data-testid="lg-split_button-trigger"]`; export const ConnectInNewWindowButton = '[data-action="connection-connect-in-new-window"]'; export const ConnectionMenu = '[data-testid="sidebar-navigation-item-actions"]'; @@ -372,9 +373,7 @@ export const sidebarConnectionButton = (connectionName: string): string => { export const sidebarConnectionDropdownButton = ( connectionName: string ): string => { - return `${sidebarConnection(connectionName)} ${ - Multiple.ConnectDropdownButton - }`; + return `${sidebarConnection(connectionName)} ${ConnectDropdownButton}`; }; export const sidebarConnectionActionButton = ( diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index c9d3ab16bf7..da74c5cdc71 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -20,7 +20,10 @@ import { import type { Compass } from '../helpers/compass'; import type { ConnectFormState } from '../helpers/connect-form-state'; import * as Selectors from '../helpers/selectors'; -import { DEFAULT_CONNECTION_NAMES } from '../helpers/test-runner-context'; +import { + DEFAULT_CONNECTION_NAMES, + isTestingWeb, +} from '../helpers/test-runner-context'; async function disconnect(browser: CompassBrowser) { try { @@ -660,6 +663,7 @@ describe('Connect in a new window', () => { it('can connect in new window', async function (this) { skipForWeb(this, 'connecting in new window is not supported on web'); + const connectionName = DEFAULT_CONNECTION_NAMES[0]; const connectionSelector = Selectors.sidebarConnection(connectionName); await browser.hover(connectionSelector); @@ -683,7 +687,17 @@ describe('Connect in a new window', () => { }); }); - // TODO: Add a test for we to ensure the SplitButton isn't visible on Web + it('shows correct connect button', async function (this) { + const connectionName = DEFAULT_CONNECTION_NAMES[0]; + const connectionSelector = Selectors.sidebarConnection(connectionName); + await browser.hover(connectionSelector); + + const connectionElement = browser.$(connectionSelector); + await connectionElement.$(Selectors.ConnectButton).waitForDisplayed(); + await connectionElement.$(Selectors.ConnectDropdownButton).waitForExist({ + reverse: isTestingWeb(), + }); + }); }); describe('Connection form', function () { From dce2e379364c0f066404bdd03714c6bba3580640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 11 Feb 2025 22:01:16 +0100 Subject: [PATCH 14/20] Pin icon-button@16.0.2 --- package-lock.json | 38 ++++++++++++++++++++++-- packages/compass-components/package.json | 2 +- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 82d06d10e0b..79667b81cde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43804,7 +43804,7 @@ "@leafygreen-ui/guide-cue": "^7.0.2", "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/icon": "^13.1.2", - "@leafygreen-ui/icon-button": "^16.0.2", + "@leafygreen-ui/icon-button": "16.0.2", "@leafygreen-ui/info-sprinkle": "^4.0.2", "@leafygreen-ui/leafygreen-provider": "^4.0.2", "@leafygreen-ui/logo": "^10.0.2", @@ -43869,6 +43869,25 @@ "typescript": "^5.0.4" } }, + "packages/compass-components/node_modules/@leafygreen-ui/icon-button": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.2.tgz", + "integrity": "sha512-nCotpqN4VlGejm0ybzdZH4ExP8bdQZbLElBkTEsPSf4nNCvjC5LsbIqRuK/TGIHTa4tPnTHgnx7QZb5X36Q5Qg==", + "license": "Apache-2.0", + "dependencies": { + "@leafygreen-ui/a11y": "^2.0.2", + "@leafygreen-ui/box": "^4.0.2", + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/icon": "^13.1.2", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/tokens": "^2.11.3", + "polished": "^4.2.2" + }, + "peerDependencies": { + "@leafygreen-ui/leafygreen-provider": "^4.0.2" + } + }, "packages/compass-components/node_modules/@leafygreen-ui/table": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/@leafygreen-ui/table/-/table-13.0.1.tgz", @@ -56354,7 +56373,7 @@ "@leafygreen-ui/guide-cue": "^7.0.2", "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/icon": "^13.1.2", - "@leafygreen-ui/icon-button": "^16.0.2", + "@leafygreen-ui/icon-button": "16.0.2", "@leafygreen-ui/info-sprinkle": "^4.0.2", "@leafygreen-ui/leafygreen-provider": "^4.0.2", "@leafygreen-ui/logo": "^10.0.2", @@ -56416,6 +56435,21 @@ "typescript": "^5.0.4" }, "dependencies": { + "@leafygreen-ui/icon-button": { + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/@leafygreen-ui/icon-button/-/icon-button-16.0.2.tgz", + "integrity": "sha512-nCotpqN4VlGejm0ybzdZH4ExP8bdQZbLElBkTEsPSf4nNCvjC5LsbIqRuK/TGIHTa4tPnTHgnx7QZb5X36Q5Qg==", + "requires": { + "@leafygreen-ui/a11y": "^2.0.2", + "@leafygreen-ui/box": "^4.0.2", + "@leafygreen-ui/emotion": "^4.0.9", + "@leafygreen-ui/icon": "^13.1.2", + "@leafygreen-ui/lib": "^14.0.2", + "@leafygreen-ui/palette": "^4.1.3", + "@leafygreen-ui/tokens": "^2.11.3", + "polished": "^4.2.2" + } + }, "@leafygreen-ui/table": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/@leafygreen-ui/table/-/table-13.0.1.tgz", diff --git a/packages/compass-components/package.json b/packages/compass-components/package.json index 99ccabba336..a5b7e1560cc 100644 --- a/packages/compass-components/package.json +++ b/packages/compass-components/package.json @@ -46,7 +46,7 @@ "@leafygreen-ui/guide-cue": "^7.0.2", "@leafygreen-ui/hooks": "^8.3.4", "@leafygreen-ui/icon": "^13.1.2", - "@leafygreen-ui/icon-button": "^16.0.2", + "@leafygreen-ui/icon-button": "16.0.2", "@leafygreen-ui/info-sprinkle": "^4.0.2", "@leafygreen-ui/leafygreen-provider": "^4.0.2", "@leafygreen-ui/logo": "^10.0.2", From 4be7eb5c89d1ab78e0f7f75008342881e35396c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 11 Feb 2025 22:01:38 +0100 Subject: [PATCH 15/20] Revert use of PolymorphicProps --- packages/compass-components/src/components/leafygreen.tsx | 4 ---- .../src/connect-button-with-menu.tsx | 3 +-- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/compass-components/src/components/leafygreen.tsx b/packages/compass-components/src/components/leafygreen.tsx index fd578eac734..decde3936f2 100644 --- a/packages/compass-components/src/components/leafygreen.tsx +++ b/packages/compass-components/src/components/leafygreen.tsx @@ -32,10 +32,6 @@ import { InfoSprinkle } from '@leafygreen-ui/info-sprinkle'; import Modal, { Footer as ModalFooter } from '@leafygreen-ui/modal'; import MarketingModal from '@leafygreen-ui/marketing-modal'; import { Pipeline, Stage } from '@leafygreen-ui/pipeline'; -export type { - InferredPolymorphicProps, - PolymorphicProps, -} from '@leafygreen-ui/polymorphic'; import Popover from '@leafygreen-ui/popover'; import { RadioBox, RadioBoxGroup } from '@leafygreen-ui/radio-box-group'; import { Radio, RadioGroup } from '@leafygreen-ui/radio-group'; diff --git a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx index 67333ecd8dc..488bcd71830 100644 --- a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx +++ b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx @@ -6,7 +6,6 @@ import { SplitButton, type GlyphName, type ItemComponentProps, - type PolymorphicProps, type MenuItemProps, } from '@mongodb-js/compass-components'; import type { Actions } from './constants'; @@ -18,7 +17,7 @@ const menuItemStyles = css({ type ConnectMenuItemProps = { action: Actions; glyph: GlyphName; -} & PolymorphicProps<'button', Omit>; +} & Omit; function ConnectMenuItem({ action, glyph, ...rest }: ConnectMenuItemProps) { return ( From a2744e4c12ab96f6c43ccaf4746bae97de50c89c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Tue, 11 Feb 2025 23:09:46 +0100 Subject: [PATCH 16/20] Fix ConnectMenuItem --- .../src/connect-button-with-menu.tsx | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx index 488bcd71830..ecad56e5dfa 100644 --- a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx +++ b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx @@ -1,4 +1,9 @@ -import React, { useState, useEffect } from 'react'; +import React, { + useState, + useEffect, + forwardRef, + type ButtonHTMLAttributes, +} from 'react'; import { css, Icon, @@ -17,18 +22,26 @@ const menuItemStyles = css({ type ConnectMenuItemProps = { action: Actions; glyph: GlyphName; -} & Omit; +} & Omit< + MenuItemProps & ButtonHTMLAttributes, + 'glyph' | 'as' +>; -function ConnectMenuItem({ action, glyph, ...rest }: ConnectMenuItemProps) { +export const ConnectMenuItem = forwardRef< + HTMLButtonElement, + ConnectMenuItemProps +>(function ConnectMenuItem({ action, glyph, ...rest }, ref) { return ( } {...rest} + ref={ref} /> ); -} +}); // Hack to make SplitButton consider this as a MenuItem ConnectMenuItem.displayName = 'MenuItem'; From 37815b1661a7abda64491b99af18e05c7d79a43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 13 Feb 2025 11:41:35 +0100 Subject: [PATCH 17/20] Simplify text in the connect menu --- .../src/connect-button-with-menu.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx index ecad56e5dfa..289d06a47a3 100644 --- a/packages/compass-connections-navigation/src/connect-button-with-menu.tsx +++ b/packages/compass-connections-navigation/src/connect-button-with-menu.tsx @@ -91,7 +91,7 @@ export function ConnectButtonWithMenu({ glyph="Connect" onClick={onClick} > - Connect Here + Here , - Connect in a New Window + In New Window , ]} > From d63ab8f0cea972c15a41d3b59f4bd855bd28e5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Thu, 13 Feb 2025 19:38:43 +0100 Subject: [PATCH 18/20] Reset windows after each test --- .../compass-e2e-tests/tests/connection.test.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index da74c5cdc71..4fb3d22b483 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -661,6 +661,16 @@ describe('Connect in a new window', () => { await cleanup(compass); }); + afterEach(async function () { + // Close any windows opened while testing, in reverse order + const [mainWindow, ...otherWindows] = await browser.getWindowHandles(); + for (const window of otherWindows.reverse()) { + await browser.switchToWindow(window); + await browser.closeWindow(); + } + await browser.switchToWindow(mainWindow); + }); + it('can connect in new window', async function (this) { skipForWeb(this, 'connecting in new window is not supported on web'); @@ -668,7 +678,8 @@ describe('Connect in a new window', () => { const connectionSelector = Selectors.sidebarConnection(connectionName); await browser.hover(connectionSelector); - expect((await browser.getWindowHandles()).length).equals(1); + const windowsBefore = await browser.getWindowHandles(); + expect(windowsBefore.length).equals(1); const connectionElement = browser.$(connectionSelector); await browser.clickVisible( @@ -681,6 +692,7 @@ describe('Connect in a new window', () => { const windowsAfter = await browser.getWindowHandles(); expect(windowsAfter.length).equals(2); const [, newWindowHandle] = windowsAfter; + await browser.switchToWindow(newWindowHandle); await browser.waitForConnectionResult(connectionName, { connectionStatus: 'success', From b9d0dc120abe32f03d871b8320ff05466964a14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Fri, 14 Feb 2025 10:31:40 +0100 Subject: [PATCH 19/20] Update packages/compass/src/main/window-manager.ts Co-authored-by: Sergey Petushkov --- packages/compass/src/main/window-manager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compass/src/main/window-manager.ts b/packages/compass/src/main/window-manager.ts index 57393cafc4d..6db516f5037 100644 --- a/packages/compass/src/main/window-manager.ts +++ b/packages/compass/src/main/window-manager.ts @@ -271,9 +271,9 @@ class CompassWindowManager { const bw = BrowserWindow.fromWebContents(evt.sender); return getWindowAutoConnectPreferences(bw, compassApp.preferences); }, - 'test:show-connect-window': () => showConnectWindow(compassApp), + 'test:show-connect-window': () => void showConnectWindow(compassApp), 'app:connect-in-new-window': (event, connectionId: string) => - showConnectWindow(compassApp, { connectionId }), + void showConnectWindow(compassApp, { connectionId }), }); ipcMain?.on('show-file', (evt, filename: string) => { From a4f53beda20647b75c80f18345b6a3d7524a8343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kr=C3=A6n=20Hansen?= Date: Fri, 14 Feb 2025 10:34:31 +0100 Subject: [PATCH 20/20] Add comments mentioning COMPASS-8970 --- packages/compass-e2e-tests/tests/connection.test.ts | 2 ++ packages/compass-preferences-model/src/preferences-schema.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/compass-e2e-tests/tests/connection.test.ts b/packages/compass-e2e-tests/tests/connection.test.ts index 4fb3d22b483..bf8627129cb 100644 --- a/packages/compass-e2e-tests/tests/connection.test.ts +++ b/packages/compass-e2e-tests/tests/connection.test.ts @@ -672,6 +672,7 @@ describe('Connect in a new window', () => { }); it('can connect in new window', async function (this) { + // TODO: Remove this as part of COMPASS-8970. skipForWeb(this, 'connecting in new window is not supported on web'); const connectionName = DEFAULT_CONNECTION_NAMES[0]; @@ -707,6 +708,7 @@ describe('Connect in a new window', () => { const connectionElement = browser.$(connectionSelector); await connectionElement.$(Selectors.ConnectButton).waitForDisplayed(); await connectionElement.$(Selectors.ConnectDropdownButton).waitForExist({ + // TODO: Remove this as part of COMPASS-8970. reverse: isTestingWeb(), }); }); diff --git a/packages/compass-preferences-model/src/preferences-schema.ts b/packages/compass-preferences-model/src/preferences-schema.ts index d306fb4d4bf..1d97aa1025f 100644 --- a/packages/compass-preferences-model/src/preferences-schema.ts +++ b/packages/compass-preferences-model/src/preferences-schema.ts @@ -100,6 +100,7 @@ export type InternalUserPreferences = { telemetryAnonymousId?: string; telemetryAtlasUserId?: string; userCreatedAt: number; + // TODO: Remove this as part of COMPASS-8970. enableConnectInNewWindow: boolean; }; @@ -409,6 +410,7 @@ export const storedUserPreferencesProps: Required<{ }, /** * Enables a dropdown in the connections sidebar to connect in a new window. + * TODO: Remove this as part of COMPASS-8970. */ enableConnectInNewWindow: { ui: false,