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..5901dd07420 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,31 @@ const pipelineOptionsActions: MenuAction[] = [ { action: 'expand', label: 'Expand all fields' }, ]; +const containerStyles = css({ + display: 'flex', + alignItems: 'center', + flex: 'none', +}); + +const defaultTitle = 'Output Options'; + 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 ?? defaultTitle} + buttonProps={{ + size: 'xsmall', + title: buttonText || defaultTitle, + ['aria-label']: buttonText || defaultTitle, + }} + > +
); }; 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 ( ); @@ -120,7 +122,9 @@ export function DropdownMenuButton({ data-testid={actionTestId(dataTestId, action)} data-action={action} data-menuitem={true} - glyph={} + glyph={ + icon ? : undefined + } onClick={onClick} > {label} diff --git a/packages/compass-crud/src/components/crud-toolbar.spec.tsx b/packages/compass-crud/src/components/crud-toolbar.spec.tsx index 43ce37903c3..43edaa4f119 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('Output Options', function () { + describe('table view', function () { + it('should be disabled', function () { + renderCrudToolbar({ + activeDocumentView: 'Table', + }); + + expect(screen.getByTitle('Output Options')).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('Output Options')); + 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('Output Options')); + 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 875e7e83456..ab843573439 100644 --- a/packages/compass-crud/src/components/crud-toolbar.tsx +++ b/packages/compass-crud/src/components/crud-toolbar.tsx @@ -32,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], }); @@ -69,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.`; @@ -107,6 +122,8 @@ export type CrudToolbarProps = { onResetClicked: () => void; onUpdateButtonClicked: () => void; onDeleteButtonClicked: () => void; + onExpandAllClicked: () => void; + onCollapseAllClicked: () => void; openExportFileDialog: (exportFullCollection?: boolean) => void; outdated: boolean; page: number; @@ -137,6 +154,8 @@ const CrudToolbar: React.FunctionComponent = ({ onResetClicked, onUpdateButtonClicked, onDeleteButtonClicked, + onExpandAllClicked, + onCollapseAllClicked, openExportFileDialog, outdated, page, @@ -273,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', + }} + /> + = (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}