diff --git a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.spec.tsx b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.spec.tsx index 4b8de9984b0..3e34249c211 100644 --- a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.spec.tsx +++ b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.spec.tsx @@ -86,6 +86,36 @@ describe('FocusModeStagePreview', function () { const preview = screen.getByTestId('focus-mode-stage-preview'); expect(within(preview).getByText(/no preview documents/i)).to.exist; }); + for (const stageOperator of ['$search', '$searchMeta', '$vectorSearch']) { + it(`renders missing search index text for ${stageOperator}`, async function () { + await renderFocusModePreview({ + stageOperator, + documents: [], + }); + expect(screen.getByText('No preview documents')).to.exist; + expect( + screen.getByText( + 'This may be because your search has no results or your search index does not exist.' + ) + ).to.exist; + }); + + it(`does not render missing search index text for ${stageOperator} and documents.length > 0`, async function () { + await renderFocusModePreview({ + stageOperator, + documents: [ + new HadronDocument({ _id: 12345 }), + new HadronDocument({ _id: 54321 }), + ], + }); + expect(screen.queryByText('No preview documents')).to.not.exist; + expect( + screen.queryByText( + 'This may be because your search has no results or your search index does not exist.' + ) + ).to.not.exist; + }); + } it('renders $out stage preview', async function () { await renderFocusModePreview( { diff --git a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.tsx b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.tsx index 5e8839295db..1a0f1487e93 100644 --- a/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.tsx +++ b/packages/compass-aggregations/src/components/focus-mode/focus-mode-stage-preview.tsx @@ -16,6 +16,7 @@ import OutputStagePreview from '../stage-preview/output-stage-preview'; import { AtlasStagePreview } from '../stage-preview/atlas-stage-preview'; import { isAtlasOnlyStage, + isSearchStage, isMissingAtlasStageSupport, isOutputStage, } from '../../utils/stage'; @@ -24,6 +25,7 @@ import { expandPreviewDocsForStage, } from '../../modules/pipeline-builder/stage-editor'; import type { StoreStage } from '../../modules/pipeline-builder/stage-editor'; +import SearchNoResults from '../search-no-results'; const containerStyles = css({ display: 'flex', @@ -149,6 +151,8 @@ export const FocusModePreview = ({ className={documentListStyles} /> ); + } else if (isSearchStage(stageOperator)) { + content = ; } else { content = (
diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.spec.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.spec.tsx index 23cfa7706d6..11294b6f45d 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.spec.tsx @@ -55,6 +55,19 @@ describe('PipelinePreview', function () { expect(screen.getByText(/No preview documents/)).to.exist; }); + it('renders missing search index text for $search', async function () { + await renderPipelineEditor({ + atlasOperator: '$search', + previewDocs: [], + }); + expect(screen.getByText('No preview documents')).to.exist; + expect( + screen.getByText( + 'This may be because your search has no results or your search index does not exist.' + ) + ).to.exist; + }); + it('renders document list', async function () { await renderPipelineEditor({ previewDocs: [{ _id: 1 }, { _id: 2 }].map( diff --git a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.tsx b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.tsx index 8a0e5601ff0..671b1e1357b 100644 --- a/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.tsx +++ b/packages/compass-aggregations/src/components/pipeline-builder-workspace/pipeline-as-text-workspace/pipeline-preview.tsx @@ -25,6 +25,7 @@ import { expandPreviewDocs, collapsePreviewDocs, } from '../../../modules/pipeline-builder/text-editor-pipeline'; +import SearchNoResults from '../../search-no-results'; const containerStyles = css({ display: 'flex', @@ -126,6 +127,9 @@ const PreviewResults = ({ } if (previewDocs.length === 0) { + if (atlasOperator) { + return ; + } return (
diff --git a/packages/compass-aggregations/src/components/search-no-results.tsx b/packages/compass-aggregations/src/components/search-no-results.tsx new file mode 100644 index 00000000000..58c327ee7e5 --- /dev/null +++ b/packages/compass-aggregations/src/components/search-no-results.tsx @@ -0,0 +1,48 @@ +import React from 'react'; + +import { + css, + palette, + spacing, + Body, + useDarkMode, + Subtitle, +} from '@mongodb-js/compass-components'; + +const centeredContent = css({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + padding: spacing[3], + flexDirection: 'column', + textAlign: 'center', +}); + +const missingAtlasIndexLightStyles = css({ + color: palette.green.dark2, +}); + +const missingAtlasIndexDarkStyles = css({ + color: palette.green.base, +}); + +export default function SearchNoResults() { + const darkMode = useDarkMode(); + + return ( +
+ + No preview documents + + + This may be because your search has no results or your search index does + not exist. + +
+ ); +} diff --git a/packages/compass-aggregations/src/components/stage-preview/index.spec.tsx b/packages/compass-aggregations/src/components/stage-preview/index.spec.tsx index 80a6e3f9c66..b1beedab6d0 100644 --- a/packages/compass-aggregations/src/components/stage-preview/index.spec.tsx +++ b/packages/compass-aggregations/src/components/stage-preview/index.spec.tsx @@ -106,7 +106,7 @@ describe('StagePreview', function () { stageOperator: '$search', documents: [], }); - expect(screen.getByText('No results found')).to.exist; + expect(screen.getByText('No preview documents')).to.exist; expect( screen.getByText( 'This may be because your search has no results or your search index does not exist.' diff --git a/packages/compass-aggregations/src/components/stage-preview/index.tsx b/packages/compass-aggregations/src/components/stage-preview/index.tsx index b3d1868c684..b1424fae37f 100644 --- a/packages/compass-aggregations/src/components/stage-preview/index.tsx +++ b/packages/compass-aggregations/src/components/stage-preview/index.tsx @@ -9,13 +9,12 @@ import { Body, KeylineCard, useDarkMode, - Subtitle, } from '@mongodb-js/compass-components'; import { Document } from '@mongodb-js/compass-crud'; import type { RootState } from '../../modules'; import { - isAtlasOnlyStage, + isSearchStage, isMissingAtlasStageSupport, isOutputStage, } from '../../utils/stage'; @@ -26,6 +25,8 @@ import OutputStagePreivew from './output-stage-preview'; import StagePreviewHeader from './stage-preview-header'; import type { StoreStage } from '../../modules/pipeline-builder/stage-editor'; +import SearchNoResults from '../search-no-results'; + const centeredContent = css({ display: 'flex', alignItems: 'center', @@ -52,7 +53,7 @@ const emptyStylesLight = css({ stroke: palette.gray.base, }); -function EmptyIcon() { +function NoPreviewDocuments() { const darkMode = useDarkMode(); return ( @@ -97,14 +98,6 @@ const documentStyles = css({ padding: 0, }); -const missingAtlasIndexLightStyles = css({ - color: palette.green.dark2, -}); - -const missingAtlasIndexDarkStyles = css({ - color: palette.green.base, -}); - type StagePreviewProps = { index: number; isLoading: boolean; @@ -123,9 +116,8 @@ function StagePreviewBody({ shouldRenderStage, isLoading, }: StagePreviewProps) { - const darkMode = useDarkMode(); if (!shouldRenderStage) { - return ; + return ; } if (isMissingAtlasOnlyStageSupport) { @@ -153,24 +145,8 @@ function StagePreviewBody({ ); } - if (isAtlasOnlyStage(stageOperator ?? '') && documents?.length === 0) { - return ( -
- - No results found - - - This may be because your search has no results or your search index - does not exist. - -
- ); + if (isSearchStage(stageOperator) && documents?.length === 0) { + return ; } if (documents && documents.length > 0) { @@ -186,7 +162,7 @@ function StagePreviewBody({ return
{docs}
; } - return ; + return ; } const containerStyles = css({ @@ -208,7 +184,7 @@ export function StagePreview(props: StagePreviewProps) { if (props.isDisabled) { return (
- +
); } diff --git a/packages/compass-aggregations/src/utils/stage.ts b/packages/compass-aggregations/src/utils/stage.ts index 89b416ebcd6..b850b25ab1f 100644 --- a/packages/compass-aggregations/src/utils/stage.ts +++ b/packages/compass-aggregations/src/utils/stage.ts @@ -203,6 +203,21 @@ export function isAtlasOnlyStage( return !!stageOperator && ATLAS_ONLY_OPERATOR_NAMES.has(stageOperator); } +/* +Atlas Search does not return an error if there is no search index - it just +returns no results. So if the connection has access to Atlas Search and the +aggregation used a search-related stage and got no results we want to display a +different error. +*/ +export function isSearchStage( + stageOperator: string | null | undefined +): stageOperator is '$search' | '$searchMeta' | '$vectorSearch' { + if (!stageOperator) { + return false; + } + return ['$search', '$searchMeta', '$vectorSearch'].includes(stageOperator); +} + const STAGE_OPERATORS_MAP = new Map( STAGE_OPERATORS.map((stage) => [stage.value, stage]) );