Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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',
Expand Down Expand Up @@ -149,6 +151,8 @@ export const FocusModePreview = ({
className={documentListStyles}
/>
);
} else if (isSearchStage(stageOperator)) {
content = <SearchNoResults />;
} else {
content = (
<div className={centerStyles}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -126,6 +127,9 @@ const PreviewResults = ({
}

if (previewDocs.length === 0) {
if (atlasOperator) {
return <SearchNoResults />;
}
return (
<div className={centerStyles}>
<DocumentIcon />
Expand Down
Original file line number Diff line number Diff line change
@@ -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 (
<div className={centeredContent}>
<Subtitle
className={css(
darkMode ? missingAtlasIndexDarkStyles : missingAtlasIndexLightStyles
)}
>
No preview documents
</Subtitle>
<Body>
This may be because your search has no results or your search index does
not exist.
</Body>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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',
Expand All @@ -52,7 +53,7 @@ const emptyStylesLight = css({
stroke: palette.gray.base,
});

function EmptyIcon() {
function NoPreviewDocuments() {
const darkMode = useDarkMode();

return (
Expand Down Expand Up @@ -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;
Expand All @@ -123,9 +116,8 @@ function StagePreviewBody({
shouldRenderStage,
isLoading,
}: StagePreviewProps) {
const darkMode = useDarkMode();
if (!shouldRenderStage) {
return <EmptyIcon />;
return <NoPreviewDocuments />;
}

if (isMissingAtlasOnlyStageSupport) {
Expand Down Expand Up @@ -153,24 +145,8 @@ function StagePreviewBody({
);
}

if (isAtlasOnlyStage(stageOperator ?? '') && documents?.length === 0) {
return (
<div className={centeredContent}>
<Subtitle
className={css(
darkMode
? missingAtlasIndexDarkStyles
: missingAtlasIndexLightStyles
)}
>
No results found
</Subtitle>
<Body>
This may be because your search has no results or your search index
does not exist.
</Body>
</div>
);
if (isSearchStage(stageOperator) && documents?.length === 0) {
return <SearchNoResults />;
}

if (documents && documents.length > 0) {
Expand All @@ -186,7 +162,7 @@ function StagePreviewBody({
return <div className={documentsStyles}>{docs}</div>;
}

return <EmptyIcon />;
return <NoPreviewDocuments />;
}

const containerStyles = css({
Expand All @@ -208,7 +184,7 @@ export function StagePreview(props: StagePreviewProps) {
if (props.isDisabled) {
return (
<div className={containerStyles}>
<EmptyIcon />
<NoPreviewDocuments />
</div>
);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/compass-aggregations/src/utils/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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])
);
Expand Down
Loading