Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(aggregations): show the search warning in all three places COMPASS-7317 #6364

Merged
merged 8 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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,18 @@ describe('FocusModeStagePreview', function () {
const preview = screen.getByTestId('focus-mode-stage-preview');
expect(within(preview).getByText(/no preview documents/i)).to.exist;
});
it('renders missing search index text for $search', async function () {
lerouxb marked this conversation as resolved.
Show resolved Hide resolved
await renderFocusModePreview({
stageOperator: '$search',
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('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
48 changes: 48 additions & 0 deletions packages/compass-aggregations/src/components/search-no-results.tsx
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