From 686fd8aabe338515b3c2caebe5d660be6f35eb77 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Fri, 10 Jan 2025 13:29:24 +0100 Subject: [PATCH 1/5] feat(compass-crud): expand/collapse all COMPASS-8233 --- .../src/components/crud-toolbar.tsx | 11 +++++++ .../src/components/document-list.tsx | 12 ++++++- .../src/components/expand-control.tsx | 31 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 packages/compass-crud/src/components/expand-control.tsx diff --git a/packages/compass-crud/src/components/crud-toolbar.tsx b/packages/compass-crud/src/components/crud-toolbar.tsx index 875e7e83456..358770fe99b 100644 --- a/packages/compass-crud/src/components/crud-toolbar.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.tsx @@ -22,6 +22,7 @@ import UpdateMenu from './update-data-menu'; import DeleteMenu from './delete-data-menu'; import { QueryBar } from '@mongodb-js/compass-query-bar'; import { useConnectionInfoRef } from '@mongodb-js/compass-connections/provider'; +import ExpandControl from './expand-control'; const crudQueryBarStyles = css({ width: '100%', @@ -107,6 +108,8 @@ export type CrudToolbarProps = { onResetClicked: () => void; onUpdateButtonClicked: () => void; onDeleteButtonClicked: () => void; + onExpandAllClicked: () => void; + onCollapseAllClicked: () => void; openExportFileDialog: (exportFullCollection?: boolean) => void; outdated: boolean; page: number; @@ -137,6 +140,8 @@ const CrudToolbar: React.FunctionComponent = ({ onResetClicked, onUpdateButtonClicked, onDeleteButtonClicked, + onExpandAllClicked, + onCollapseAllClicked, openExportFileDialog, outdated, page, @@ -293,6 +298,12 @@ const CrudToolbar: React.FunctionComponent = ({ + + + = (props) => { [view, setCurrentViewInitialScrollTop, scrollRef, viewChanged] ); + const onExpandAllClicked = useCallback(() => { + docs.forEach((doc) => !doc.expanded && doc.expand()); + }, [docs]); + + const onCollapseAllClicked = useCallback(() => { + docs.forEach((doc) => doc.expanded && doc.collapse()); + }, [docs]); + return (
= (props) => { onResetClicked={onResetClicked} onUpdateButtonClicked={onUpdateButtonClicked} onDeleteButtonClicked={onDeleteButtonClicked} + onExpandAllClicked={onExpandAllClicked} + onCollapseAllClicked={onCollapseAllClicked} openExportFileDialog={openExportFileDialog} outdated={outdated} readonly={!isEditable} diff --git a/packages/compass-crud/src/components/expand-control.tsx b/packages/compass-crud/src/components/expand-control.tsx new file mode 100644 index 00000000000..7866e31cbc0 --- /dev/null +++ b/packages/compass-crud/src/components/expand-control.tsx @@ -0,0 +1,31 @@ +import { Button, Icon, Menu, MenuItem } from '@mongodb-js/compass-components'; +import React from 'react'; + +interface ExpandControlProps { + onExpandAll: () => void; + onCollapseAll: () => void; +} + +const ExpandControl: React.FunctionComponent = ({ + onExpandAll, + onCollapseAll, +}) => { + return ( + + + + } + > + Expand all documents + Collapse all documents + + ); +}; + +export default ExpandControl; From 7c5ac4b397fe4926204cf8c17575d660d330c66b Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Fri, 10 Jan 2025 14:13:29 +0100 Subject: [PATCH 2/5] add tests and exclude table view --- .../src/components/crud-toolbar.spec.tsx | 47 +++++++++++++++++++ .../src/components/crud-toolbar.tsx | 1 + .../src/components/expand-control.tsx | 4 ++ 3 files changed, 52 insertions(+) diff --git a/packages/compass-crud/src/components/crud-toolbar.spec.tsx b/packages/compass-crud/src/components/crud-toolbar.spec.tsx index 43ce37903c3..062431b4216 100644 --- a/packages/compass-crud/src/components/crud-toolbar.spec.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.spec.tsx @@ -71,6 +71,8 @@ describe('CrudToolbar Component', function () { onResetClicked={noop} onUpdateButtonClicked={noop} onDeleteButtonClicked={noop} + onExpandAllClicked={noop} + onCollapseAllClicked={noop} openExportFileDialog={noop} outdated={false} page={0} @@ -368,6 +370,51 @@ describe('CrudToolbar Component', function () { }); }); + describe.only('expand controls', function () { + describe('table view', function () { + it('should be disabled', function () { + renderCrudToolbar({ + activeDocumentView: 'Table', + }); + + expect(screen.getByTitle('Expand Controls')).to.have.attribute( + 'aria-disabled', + 'true' + ); + }); + }); + + describe('other views', function () { + it('should provide "Expand all documents"', function () { + const onExpandAllClicked = sinon.spy(); + renderCrudToolbar({ + activeDocumentView: 'JSON', + onExpandAllClicked, + }); + + userEvent.click(screen.getByTitle('Expand Controls')); + const expandAllBtn = screen.getByText('Expand all documents'); + expect(expandAllBtn).to.be.visible; + userEvent.click(expandAllBtn); + expect(onExpandAllClicked).to.have.been.called; + }); + + it('should provide "Collapse all documents"', function () { + const onCollapseAllClicked = sinon.spy(); + renderCrudToolbar({ + activeDocumentView: 'JSON', + onCollapseAllClicked, + }); + + userEvent.click(screen.getByTitle('Expand Controls')); + const collapseAllBtn = screen.getByText('Collapse all documents'); + expect(collapseAllBtn).to.be.visible; + userEvent.click(collapseAllBtn); + expect(onCollapseAllClicked).to.have.been.called; + }); + }); + }); + it('should not render the outdated message', function () { renderCrudToolbar(); diff --git a/packages/compass-crud/src/components/crud-toolbar.tsx b/packages/compass-crud/src/components/crud-toolbar.tsx index 358770fe99b..417ba27e948 100644 --- a/packages/compass-crud/src/components/crud-toolbar.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.tsx @@ -302,6 +302,7 @@ const CrudToolbar: React.FunctionComponent = ({ void; onCollapseAll: () => void; } const ExpandControl: React.FunctionComponent = ({ + activeView, onExpandAll, onCollapseAll, }) => { @@ -17,6 +20,7 @@ const ExpandControl: React.FunctionComponent = ({ size="xsmall" aria-label="Expand Controls" title="Expand Controls" + disabled={activeView === 'Table'} > From c21dffcac026a98c34245d7d18334a8b81529ee9 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Fri, 10 Jan 2025 16:28:14 +0100 Subject: [PATCH 3/5] adjust aggregations and unite --- .../pipeline-output-options-menu.tsx | 30 ++++++++---- .../pipeline-pagination.tsx | 11 +++-- .../pipeline-results-header.tsx | 7 +-- .../pipeline-results-view-controls.tsx | 9 ---- .../actions/dropdown-menu-button.tsx | 12 +++-- .../src/components/crud-toolbar.spec.tsx | 8 ++-- .../src/components/crud-toolbar.tsx | 48 ++++++++++++++----- .../src/components/expand-control.tsx | 35 -------------- 8 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 packages/compass-crud/src/components/expand-control.tsx diff --git a/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx b/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx index 53bb82152d9..33ee10fd1b8 100644 --- a/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx +++ b/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { DropdownMenuButton } from '@mongodb-js/compass-components'; +import { css, DropdownMenuButton } from '@mongodb-js/compass-components'; import type { MenuAction } from '@mongodb-js/compass-components'; export type PipelineOutputOption = 'expand' | 'collapse'; @@ -8,19 +8,29 @@ const pipelineOptionsActions: MenuAction[] = [ { action: 'expand', label: 'Expand all fields' }, ]; +const containerStyles = css({ + display: 'flex', + alignItems: 'center', + flex: 'none', +}); + export const PipelineOutputOptionsMenu: React.FunctionComponent<{ onChangeOption: (option: PipelineOutputOption) => void; buttonText?: string; }> = ({ onChangeOption, buttonText }) => { return ( - - data-testid="pipeline-output-options" - actions={pipelineOptionsActions} - onAction={onChangeOption} - buttonText={buttonText ?? 'Output Options'} - buttonProps={{ - size: 'xsmall', - }} - > +
+ + data-testid="pipeline-output-options" + actions={pipelineOptionsActions} + onAction={onChangeOption} + buttonText={buttonText ?? 'Output Options'} + buttonProps={{ + size: 'xsmall', + title: buttonText ?? 'Output Options', + ['aria-label']: buttonText ?? 'Output Options', + }} + > +
); }; diff --git a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-pagination.tsx b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-pagination.tsx index 9f3943ef31f..3e90b264f12 100644 --- a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-pagination.tsx +++ b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-pagination.tsx @@ -26,15 +26,20 @@ type PipelinePaginationProps = { const containerStyles = css({ display: 'flex', alignItems: 'center', - gap: spacing[2], + gap: spacing[200], }); const paginationStyles = css({ display: 'flex', - gap: spacing[1], + gap: spacing[100], alignItems: 'baseline', }); +const prevNextStyles = css({ + display: 'flex', + alignItems: 'center', +}); + export const PipelinePagination: React.FunctionComponent< PipelinePaginationProps > = ({ @@ -56,7 +61,7 @@ export const PipelinePagination: React.FunctionComponent<
)} -
+
All Results -
+ - - View - = { activeAction?: Action; 'data-testid'?: string; buttonText: string; - buttonProps: ButtonProps; + buttonProps: ButtonProps & React.ButtonHTMLAttributes; hideOnNarrow?: boolean; }; @@ -89,7 +89,6 @@ export function DropdownMenuButton({ }) => { return ( ); diff --git a/packages/compass-crud/src/components/crud-toolbar.spec.tsx b/packages/compass-crud/src/components/crud-toolbar.spec.tsx index 062431b4216..43edaa4f119 100644 --- a/packages/compass-crud/src/components/crud-toolbar.spec.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.spec.tsx @@ -370,14 +370,14 @@ describe('CrudToolbar Component', function () { }); }); - describe.only('expand controls', function () { + describe('Output Options', function () { describe('table view', function () { it('should be disabled', function () { renderCrudToolbar({ activeDocumentView: 'Table', }); - expect(screen.getByTitle('Expand Controls')).to.have.attribute( + expect(screen.getByTitle('Output Options')).to.have.attribute( 'aria-disabled', 'true' ); @@ -392,7 +392,7 @@ describe('CrudToolbar Component', function () { onExpandAllClicked, }); - userEvent.click(screen.getByTitle('Expand Controls')); + userEvent.click(screen.getByTitle('Output Options')); const expandAllBtn = screen.getByText('Expand all documents'); expect(expandAllBtn).to.be.visible; userEvent.click(expandAllBtn); @@ -406,7 +406,7 @@ describe('CrudToolbar Component', function () { onCollapseAllClicked, }); - userEvent.click(screen.getByTitle('Expand Controls')); + userEvent.click(screen.getByTitle('Output Options')); const collapseAllBtn = screen.getByText('Collapse all documents'); expect(collapseAllBtn).to.be.visible; userEvent.click(collapseAllBtn); diff --git a/packages/compass-crud/src/components/crud-toolbar.tsx b/packages/compass-crud/src/components/crud-toolbar.tsx index 417ba27e948..ab843573439 100644 --- a/packages/compass-crud/src/components/crud-toolbar.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.tsx @@ -22,7 +22,6 @@ import UpdateMenu from './update-data-menu'; import DeleteMenu from './delete-data-menu'; import { QueryBar } from '@mongodb-js/compass-query-bar'; import { useConnectionInfoRef } from '@mongodb-js/compass-connections/provider'; -import ExpandControl from './expand-control'; const crudQueryBarStyles = css({ width: '100%', @@ -33,33 +32,42 @@ const crudToolbarStyles = css({ display: 'flex', flexDirection: 'column', alignItems: 'center', - gap: spacing[3], - padding: spacing[3], + gap: spacing[300], + padding: spacing[300], }); const crudBarStyles = css({ width: '100%', display: 'flex', - gap: spacing[2], + gap: spacing[200], justifyContent: 'space-between', }); const toolbarLeftActionStyles = css({ display: 'flex', alignItems: 'center', - gap: spacing[2], + gap: spacing[200], }); const toolbarRightActionStyles = css({ display: 'flex', alignItems: 'center', - gap: spacing[2], + gap: spacing[200], +}); + +const prevNextStyles = css({ + display: 'flex', + alignItems: 'center', }); const exportCollectionButtonStyles = css({ whiteSpace: 'nowrap', }); +const outputOptionsButtonStyles = css({ + whiteSpace: 'nowrap', +}); + const docsPerPageOptionStyles = css({ width: spacing[1600] + spacing[300], }); @@ -70,6 +78,12 @@ const exportDataActions: MenuAction[] = [ { action: 'export-full-collection', label: 'Export the full collection' }, ]; +type ExpandControlsOption = 'expand-all' | 'collapse-all'; +const expandControlsOptions: MenuAction[] = [ + { action: 'expand-all', label: 'Expand all documents' }, + { action: 'collapse-all', label: 'Collapse all documents' }, +]; + const OUTDATED_WARNING = `The content is outdated and no longer in sync with the current query. Press "Find" again to see the results for the current query.`; @@ -278,7 +292,7 @@ const CrudToolbar: React.FunctionComponent = ({ )} -
+
= ({
- + data-testid="crud-export-collection" + actions={expandControlsOptions} + onAction={(action: ExpandControlsOption) => + action === 'expand-all' + ? onExpandAllClicked() + : onCollapseAllClicked() + } + buttonText="" + buttonProps={{ + className: outputOptionsButtonStyles, + size: 'xsmall', + title: 'Output Options', + ['aria-label']: 'Output Options', + disabled: activeDocumentView === 'Table', + }} /> void; - onCollapseAll: () => void; -} - -const ExpandControl: React.FunctionComponent = ({ - activeView, - onExpandAll, - onCollapseAll, -}) => { - return ( - - - - } - > - Expand all documents - Collapse all documents - - ); -}; - -export default ExpandControl; From 159e625218ce39d54829c3fcee4e308d5ec236a1 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Fri, 10 Jan 2025 16:51:42 +0100 Subject: [PATCH 4/5] update test --- .../pipeline-results-view-controls.spec.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-view-controls.spec.tsx b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-view-controls.spec.tsx index dfd5b487fdf..087c97cb47f 100644 --- a/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-view-controls.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-results-workspace/pipeline-results-view-controls.spec.tsx @@ -17,7 +17,6 @@ describe('PipelineResultsViewControls', function () { ); const container = screen.getByTestId('pipeline-results-view-controls'); expect(container).to.exist; - expect(within(container).getByText('View')).to.exist; expect(within(container).getByLabelText('Document list')).to.exist; expect(within(container).getByLabelText('JSON list')).to.exist; }); From d9593452ec0986b04a9d468bc94fa2b1cf69b233 Mon Sep 17 00:00:00 2001 From: Paula Stachova Date: Mon, 13 Jan 2025 12:48:43 +0100 Subject: [PATCH 5/5] style and a11y fixes --- .../src/components/pipeline-output-options-menu.tsx | 8 +++++--- .../src/components/actions/dropdown-menu-button.tsx | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx b/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx index 33ee10fd1b8..5901dd07420 100644 --- a/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx +++ b/packages/compass-aggregations/src/components/pipeline-output-options-menu.tsx @@ -14,6 +14,8 @@ const containerStyles = css({ flex: 'none', }); +const defaultTitle = 'Output Options'; + export const PipelineOutputOptionsMenu: React.FunctionComponent<{ onChangeOption: (option: PipelineOutputOption) => void; buttonText?: string; @@ -24,11 +26,11 @@ export const PipelineOutputOptionsMenu: React.FunctionComponent<{ data-testid="pipeline-output-options" actions={pipelineOptionsActions} onAction={onChangeOption} - buttonText={buttonText ?? 'Output Options'} + buttonText={buttonText ?? defaultTitle} buttonProps={{ size: 'xsmall', - title: buttonText ?? 'Output Options', - ['aria-label']: buttonText ?? 'Output Options', + title: buttonText || defaultTitle, + ['aria-label']: buttonText || defaultTitle, }} >
diff --git a/packages/compass-components/src/components/actions/dropdown-menu-button.tsx b/packages/compass-components/src/components/actions/dropdown-menu-button.tsx index d71130a7868..d9236df3c82 100644 --- a/packages/compass-components/src/components/actions/dropdown-menu-button.tsx +++ b/packages/compass-components/src/components/actions/dropdown-menu-button.tsx @@ -122,7 +122,9 @@ export function DropdownMenuButton({ data-testid={actionTestId(dataTestId, action)} data-action={action} data-menuitem={true} - glyph={} + glyph={ + icon ? : undefined + } onClick={onClick} > {label}