From 1ee91d1127de7c8a6d3ca75aa52f1d2eb49c5f71 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Wed, 7 May 2025 15:23:31 -0400 Subject: [PATCH 01/16] add index from index suggestions --- .../src/modules/create-index.tsx | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index d2cbfdd3b8e..4109111a7ba 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -490,6 +490,8 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< return (dispatch, getState, { track, preferences }) => { // @experiment Early Journey Indexes Guidance & Awareness | Jira Epic: CLOUDP-239367 const currentTab = getState().createIndex.currentTab; + const isQueryFlow = currentTab === 'QueryFlow'; + const indexSuggestions = getState().createIndex.indexSuggestions; const { enableIndexesGuidanceExp, showIndexesGuidanceVariant } = preferences.getPreferences(); @@ -504,7 +506,17 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< }); // Check for field errors. - if ( + if (isQueryFlow) { + if (!indexSuggestions) { + // TODO in CLOUDP-311787: add info banner and update the current error banner to take in fetchingSuggestionsError as well + dispatch( + errorEncountered( + 'No suggested index found. Please choose "Start with an Index" at the top to continue.' + ) + ); + return; + } + } else if ( getState().createIndex.fields.some( (field: Field) => field.name === '' || field.type === '' ) @@ -518,11 +530,19 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< let spec: Record; try { - spec = Object.fromEntries( - getState().createIndex.fields.map((field) => { - return [field.name, fieldTypeToIndexDirection(field.type)]; - }) - ); + if (isQueryFlow) { + // Gather from suggested index + if (indexSuggestions) { + spec = indexSuggestions; + } + } else { + // Gather from the index input fields + spec = Object.fromEntries( + getState().createIndex.fields.map((field) => { + return [field.name, fieldTypeToIndexDirection(field.type)]; + }) + ); + } } catch (e) { dispatch(errorEncountered((e as any).message)); return; From 3dea357020745c2c216cdd7b1bb4884487745833 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Thu, 8 May 2025 11:46:46 -0400 Subject: [PATCH 02/16] disable the create index button when data is not complete --- .../create-index-actions.tsx | 41 ++++++++++++++++++- .../create-index-form/index-flow-section.tsx | 7 +--- .../create-index-modal/create-index-modal.tsx | 1 + .../utils/create-index-modal-validation.ts | 5 +++ 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 packages/compass-indexes/src/utils/create-index-modal-validation.ts diff --git a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.tsx b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.tsx index 6ce3c05f8eb..20c20501d4c 100644 --- a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.tsx +++ b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.tsx @@ -1,5 +1,9 @@ import React from 'react'; import { css, Banner, spacing, Button } from '@mongodb-js/compass-components'; +import { connect } from 'react-redux'; +import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; +import type { Field, Tab } from '../../modules/create-index'; +import type { RootState } from '../../modules'; const containerStyles = css({ display: 'flex', @@ -27,12 +31,37 @@ function CreateIndexActions({ onErrorBannerCloseClick, onCreateIndexClick, onCancelCreateIndexClick, + fields, + currentTab, + showIndexesGuidanceVariant, + indexSuggestions, }: { error: string | null; onErrorBannerCloseClick: () => void; onCreateIndexClick: () => void; onCancelCreateIndexClick: () => void; + fields: Field[]; + currentTab: Tab; + showIndexesGuidanceVariant: boolean; + indexSuggestions: Record | null; }) { + let isCreateIndexButtonDisabled = false; + + if (showIndexesGuidanceVariant) { + // Disable create index button if the user is in Query Flow and has no suggestions + if (currentTab === 'QueryFlow') { + if (indexSuggestions === null) { + isCreateIndexButtonDisabled = true; + } + } + // Or if they are in the Index Flow but have not completed the fields + else { + if (!areAllFieldsFilledIn(fields)) { + isCreateIndexButtonDisabled = true; + } + } + } + return (
{error && ( @@ -61,6 +90,7 @@ function CreateIndexActions({ onClick={onCreateIndexClick} variant="primary" className={createIndexButtonStyles} + disabled={isCreateIndexButtonDisabled} > Create Index @@ -68,4 +98,13 @@ function CreateIndexActions({ ); } -export default CreateIndexActions; +const mapState = ({ createIndex }: RootState) => { + const { fields, currentTab, indexSuggestions } = createIndex; + return { + fields, + currentTab, + indexSuggestions, + }; +}; + +export default connect(mapState)(CreateIndexActions); diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index e367e3629d3..c1b10298af9 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -15,6 +15,7 @@ import { import React, { useState, useCallback } from 'react'; import type { Field } from '../../modules/create-index'; import MDBCodeViewer from './mdb-code-viewer'; +import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; const flexContainerStyles = css({ display: 'flex', @@ -152,16 +153,12 @@ const IndexFlowSection = ({ const [isCodeEquivalentToggleChecked, setIsCodeEquivalentToggleChecked] = useState(false); - const areAllFieldsFilledIn = fields.every((field) => { - return field.name && field.type; - }); - const hasUnsupportedQueryTypes = fields.some((field) => { return field.type === '2dsphere' || field.type === 'text'; }); const isCoveredQueriesButtonDisabled = - !areAllFieldsFilledIn || hasUnsupportedQueryTypes; + !areAllFieldsFilledIn(fields) || hasUnsupportedQueryTypes; const indexNameTypeMap = fields.reduce>( (accumulator, currentValue) => { diff --git a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx index 70b8aba6318..97bd1a76338 100644 --- a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx +++ b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx @@ -117,6 +117,7 @@ function CreateIndexModal({ onErrorBannerCloseClick={onErrorBannerCloseClick} onCreateIndexClick={onCreateIndexClick} onCancelCreateIndexClick={onCancelCreateIndexClick} + showIndexesGuidanceVariant={showIndexesGuidanceVariant} /> diff --git a/packages/compass-indexes/src/utils/create-index-modal-validation.ts b/packages/compass-indexes/src/utils/create-index-modal-validation.ts new file mode 100644 index 00000000000..f90b614c859 --- /dev/null +++ b/packages/compass-indexes/src/utils/create-index-modal-validation.ts @@ -0,0 +1,5 @@ +import type { Field } from '../modules/create-index'; + +export const areAllFieldsFilledIn = (fields: Field[]) => { + return fields.every((field) => field.name && field.type); +}; From 8d084827127ddd07652c8d0a415467b5d7357908 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Thu, 8 May 2025 13:42:00 -0400 Subject: [PATCH 03/16] add disable show suggested index button logic --- .../create-index-form/query-flow-section.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index b9b973c3017..d7c18d4e8d2 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -20,6 +20,7 @@ import type { SuggestedIndexFetchedProps, } from '../../modules/create-index'; import { connect } from 'react-redux'; +import { parseFilter } from 'mongodb-query-parser'; const inputQueryContainerStyles = css({ display: 'flex', @@ -97,6 +98,8 @@ const QueryFlowSection = ({ fetchingSuggestionsState: IndexSuggestionState; }) => { const [inputQuery, setInputQuery] = React.useState(''); + const [hasNewChanges, setHasNewChanges] = React.useState(false); + const completer = useMemo( () => createQueryAutocompleter({ @@ -121,9 +124,24 @@ const QueryFlowSection = ({ collectionName, inputQuery: sanitizedInputQuery, }); + + setHasNewChanges(false); }, [inputQuery, dbName, collectionName, onSuggestedIndexButtonClick]); + const handleQueryInputChange = useCallback((text: string) => { + setInputQuery(text); + setHasNewChanges(true); + }, []); + const isFetchingIndexSuggestions = fetchingSuggestionsState === 'fetching'; + let isShowSuggestionsButtonDisabled = !hasNewChanges; + + // Validate query upon typing + try { + parseFilter(inputQuery); + } catch (e) { + isShowSuggestionsButtonDisabled = true; + } return ( <> @@ -144,7 +162,7 @@ const QueryFlowSection = ({ copyable={false} formattable={false} text={inputQuery} - onChangeText={(text) => setInputQuery(text)} + onChangeText={(text) => handleQueryInputChange(text)} placeholder="Type a query: { field: 'value' }" completer={completer} className={codeEditorStyles} @@ -156,6 +174,7 @@ const QueryFlowSection = ({ onClick={handleSuggestedIndexButtonClick} className={suggestedIndexButtonStyles} size="small" + disabled={isShowSuggestionsButtonDisabled} > Show suggested index From f9bf9ea6940ae28f4f2216cc9bb3b9a595915ed6 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Mon, 19 May 2025 14:41:00 -0400 Subject: [PATCH 04/16] disable covered queries button if there's no changes to fields --- .../create-index-form/index-flow-section.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index c1b10298af9..21cff954059 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -12,7 +12,7 @@ import { InfoSprinkle, Tooltip, } from '@mongodb-js/compass-components'; -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useEffect } from 'react'; import type { Field } from '../../modules/create-index'; import MDBCodeViewer from './mdb-code-viewer'; import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; @@ -152,13 +152,16 @@ const IndexFlowSection = ({ }: IndexFlowSectionProps) => { const [isCodeEquivalentToggleChecked, setIsCodeEquivalentToggleChecked] = useState(false); + const [hasFieldChanges, setHasFieldChanges] = useState(false); const hasUnsupportedQueryTypes = fields.some((field) => { return field.type === '2dsphere' || field.type === 'text'; }); const isCoveredQueriesButtonDisabled = - !areAllFieldsFilledIn(fields) || hasUnsupportedQueryTypes; + !areAllFieldsFilledIn(fields) || + hasUnsupportedQueryTypes || + !hasFieldChanges; const indexNameTypeMap = fields.reduce>( (accumulator, currentValue) => { @@ -190,6 +193,11 @@ const IndexFlowSection = ({ optimalQueries: generateOptimalQueries(coveredQueriesArr), showCoveredQueries: true, }); + setHasFieldChanges(false); + }, [fields]); + + useEffect(() => { + setHasFieldChanges(true); }, [fields]); const { coveredQueries, optimalQueries, showCoveredQueries } = From cdbc49bf1e3585c820f4ca5beb879bfb61c89c1e Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Mon, 19 May 2025 15:59:59 -0400 Subject: [PATCH 05/16] adjusting error message and added analytics for error parsing --- .../query-flow-section.spec.tsx | 2 +- .../src/modules/create-index.tsx | 34 +++++-------------- .../compass-telemetry/src/telemetry-events.ts | 18 +++++++++- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.spec.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.spec.tsx index 2582dbd03d2..d151f7b0520 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.spec.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.spec.tsx @@ -66,7 +66,7 @@ describe('QueryFlowSection', () => { type: ActionTypes.SuggestedIndexesFetched, sampleDocs: [], indexSuggestions: { a: 1, b: 2 }, - fetchingSuggestionsError: null, + error: null, indexSuggestionsState: 'success', }); }); diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index 4109111a7ba..2732bc25f53 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -306,9 +306,6 @@ export type State = { // state of the index suggestions fetchingSuggestionsState: IndexSuggestionState; - // error specific to fetching index suggestions - fetchingSuggestionsError: string | null; - // index suggestions in a format such as {fieldName: 1} indexSuggestions: Record | null; @@ -324,7 +321,6 @@ export const INITIAL_STATE: State = { options: INITIAL_OPTIONS_STATE, currentTab: 'IndexFlow', fetchingSuggestionsState: 'initial', - fetchingSuggestionsError: null, indexSuggestions: null, sampleDocs: null, }; @@ -367,7 +363,7 @@ export type SuggestedIndexFetchedAction = { type: ActionTypes.SuggestedIndexesFetched; sampleDocs: Array; indexSuggestions: { [key: string]: number } | null; - fetchingSuggestionsError: string | null; + error: string | null; indexSuggestionsState: IndexSuggestionState; }; @@ -389,7 +385,7 @@ export const fetchIndexSuggestions = ({ Promise, SuggestedIndexFetchedAction | SuggestedIndexesRequestedAction > => { - return async (dispatch, getState, { dataService }) => { + return async (dispatch, getState, { dataService, track }) => { dispatch({ type: ActionTypes.SuggestedIndexesRequested, }); @@ -422,26 +418,13 @@ export const fetchIndexSuggestions = ({ analyzedNamespace ); const results = await mql.suggestIndex([query]); - const indexSuggestions = results?.index || null; - - // TODO in CLOUDP-311787: add info banner and update the current error banner to take in fetchingSuggestionsError as well - if (!indexSuggestions) { - dispatch({ - type: ActionTypes.SuggestedIndexesFetched, - sampleDocs: sampleDocuments, - indexSuggestions, - fetchingSuggestionsError: - 'No suggested index found. Please choose "Start with an Index" at the top to continue.', - indexSuggestionsState: 'error', - }); - return; - } + const indexSuggestions = results?.index; dispatch({ type: ActionTypes.SuggestedIndexesFetched, sampleDocs: sampleDocuments, indexSuggestions, - fetchingSuggestionsError: null, + error: null, indexSuggestionsState: 'success', }); } catch (e: unknown) { @@ -449,12 +432,14 @@ export const fetchIndexSuggestions = ({ type: ActionTypes.SuggestedIndexesFetched, sampleDocs: sampleDocuments, indexSuggestions: null, - fetchingSuggestionsError: + error: e instanceof Error ? 'Error parsing query. Please follow query structure. ' + e.message : 'Error parsing query. Please follow query structure.', indexSuggestionsState: 'error', }); + + track('Error parsing query', { context: 'Create Index Modal' }); } }; }; @@ -508,7 +493,6 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< // Check for field errors. if (isQueryFlow) { if (!indexSuggestions) { - // TODO in CLOUDP-311787: add info banner and update the current error banner to take in fetchingSuggestionsError as well dispatch( errorEncountered( 'No suggested index found. Please choose "Start with an Index" at the top to continue.' @@ -780,7 +764,7 @@ const reducer: Reducer = (state = INITIAL_STATE, action) => { return { ...state, fetchingSuggestionsState: 'fetching', - fetchingSuggestionsError: null, + error: null, indexSuggestions: null, }; } @@ -794,7 +778,7 @@ const reducer: Reducer = (state = INITIAL_STATE, action) => { return { ...state, fetchingSuggestionsState: action.indexSuggestionsState, - fetchingSuggestionsError: action.fetchingSuggestionsError, + error: action.error, indexSuggestions: action.indexSuggestions, sampleDocs: action.sampleDocs, }; diff --git a/packages/compass-telemetry/src/telemetry-events.ts b/packages/compass-telemetry/src/telemetry-events.ts index 91e53ba04e0..fa6d17a6c94 100644 --- a/packages/compass-telemetry/src/telemetry-events.ts +++ b/packages/compass-telemetry/src/telemetry-events.ts @@ -2693,6 +2693,20 @@ type CreateIndexButtonClickedEvent = CommonEvent<{ }; }>; +type CreateIndexErrorParsingQueryEvent = CommonEvent<{ + name: 'Error parsing query'; + payload: { + context: CreateIndexModalContext; + }; +}>; + +type CreateIndexErrorGettingCoveredQueriesEvent = CommonEvent<{ + name: 'Error generating covered queries'; + payload: { + context: CreateIndexModalContext; + }; +}>; + export type TelemetryEvent = | AggregationCanceledEvent | AggregationCopiedEvent @@ -2815,4 +2829,6 @@ export type TelemetryEvent = | CumulativeLayoutShiftEvent | TimeToFirstByteEvent | ExperimentViewedEvent - | CreateIndexButtonClickedEvent; + | CreateIndexButtonClickedEvent + | CreateIndexErrorParsingQueryEvent + | CreateIndexErrorGettingCoveredQueriesEvent; From b0f34364ef62c08243d53d4b7e329cc17e8ecf69 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Mon, 19 May 2025 17:07:55 -0400 Subject: [PATCH 06/16] finished adding error and segment event for covered queries --- .../create-index-form/index-flow-section.tsx | 48 +++++++++++++++---- .../create-index-form/query-flow-section.tsx | 8 +++- .../src/modules/create-index.tsx | 14 ++---- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index 21cff954059..656150a799c 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -13,9 +13,14 @@ import { Tooltip, } from '@mongodb-js/compass-components'; import React, { useState, useCallback, useEffect } from 'react'; -import type { Field } from '../../modules/create-index'; +import { errorEncountered, type Field } from '../../modules/create-index'; import MDBCodeViewer from './mdb-code-viewer'; import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; +import { connect } from 'react-redux'; +import { + TrackFunction, + useTelemetry, +} from '@mongodb-js/compass-telemetry/provider'; const flexContainerStyles = css({ display: 'flex', @@ -78,10 +83,12 @@ export type IndexFlowSectionProps = { createIndexFieldsComponent: JSX.Element | null; dbName: string; collectionName: string; + onErrorEncountered: (error: string) => void; }; const generateCoveredQueries = ( - coveredQueriesArr: Array> + coveredQueriesArr: Array>, + track: TrackFunction ) => { const rows = []; for (let i = 0; i < coveredQueriesArr.length; i++) { @@ -93,6 +100,14 @@ const generateCoveredQueries = ( ); } + if (rows.length === 0) { + track('Error generating covered queries', { + context: 'Create Index Modal', + }); + throw new Error( + 'Error generating covered query examples. Please try again later.' + ); + } return <>{rows}; }; @@ -149,6 +164,7 @@ const IndexFlowSection = ({ fields, dbName, collectionName, + onErrorEncountered, }: IndexFlowSectionProps) => { const [isCodeEquivalentToggleChecked, setIsCodeEquivalentToggleChecked] = useState(false); @@ -157,6 +173,7 @@ const IndexFlowSection = ({ const hasUnsupportedQueryTypes = fields.some((field) => { return field.type === '2dsphere' || field.type === 'text'; }); + const track = useTelemetry(); const isCoveredQueriesButtonDisabled = !areAllFieldsFilledIn(fields) || @@ -188,13 +205,18 @@ const IndexFlowSection = ({ return { [field.name]: index + 1 }; }); - setCoveredQueriesObj({ - coveredQueries: generateCoveredQueries(coveredQueriesArr), - optimalQueries: generateOptimalQueries(coveredQueriesArr), - showCoveredQueries: true, - }); + try { + setCoveredQueriesObj({ + coveredQueries: generateCoveredQueries(coveredQueriesArr, track), + optimalQueries: generateOptimalQueries(coveredQueriesArr), + showCoveredQueries: true, + }); + } catch (e) { + onErrorEncountered(e.message); + } + setHasFieldChanges(false); - }, [fields]); + }, [fields, onErrorEncountered, track]); useEffect(() => { setHasFieldChanges(true); @@ -320,4 +342,12 @@ const IndexFlowSection = ({ ); }; -export default IndexFlowSection; +const mapState = () => { + return {}; +}; + +const mapDispatch = { + onErrorEncountered: errorEncountered, +}; + +export default connect(mapState, mapDispatch)(IndexFlowSection); diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index 9b5729fe2e2..9244ccc81f0 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -81,6 +81,8 @@ const insightStyles = css({ display: 'flex', alignItems: 'center', gap: spacing[100], + marginBottom: spacing[200], + height: spacing[500], }); const QueryFlowSection = ({ @@ -107,9 +109,11 @@ const QueryFlowSection = ({ initialQuery: Document | null; }) => { const [inputQuery, setInputQuery] = React.useState( - JSON.stringify(initialQuery?.filter ?? {}, null, 2) + JSON.stringify(initialQuery?.filter, null, 2) + ); + const [hasNewChanges, setHasNewChanges] = React.useState( + initialQuery !== null ); - const [hasNewChanges, setHasNewChanges] = React.useState(false); const completer = useMemo( () => createQueryAutocompleter({ diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index ea7d4b9313f..d869bb25d17 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -348,7 +348,7 @@ export const createIndexClosed = () => ({ type: ActionTypes.CreateIndexClosed, }); -const errorEncountered = (error: string): ErrorEncounteredAction => ({ +export const errorEncountered = (error: string): ErrorEncounteredAction => ({ type: ActionTypes.ErrorEncountered, error, }); @@ -497,16 +497,8 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< }); // Check for field errors. - if (isQueryFlow) { - if (!indexSuggestions) { - dispatch( - errorEncountered( - 'No suggested index found. Please choose "Start with an Index" at the top to continue.' - ) - ); - return; - } - } else if ( + if ( + !isQueryFlow && getState().createIndex.fields.some( (field: Field) => field.name === '' || field.type === '' ) From 45cf375cc2b09ba294139fc1758a258e1248ef58 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 20 May 2025 11:33:07 -0400 Subject: [PATCH 07/16] fix lint issues for opening from nudge --- packages/compass-crud/src/stores/crud-store.ts | 2 +- .../components/create-index-form/create-index-form.tsx | 3 +-- .../components/create-index-form/index-flow-section.tsx | 8 +++----- .../components/create-index-form/query-flow-section.tsx | 4 ++-- .../components/create-index-modal/create-index-modal.tsx | 3 +-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/compass-crud/src/stores/crud-store.ts b/packages/compass-crud/src/stores/crud-store.ts index 3dee965b3b7..40b0b98e451 100644 --- a/packages/compass-crud/src/stores/crud-store.ts +++ b/packages/compass-crud/src/stores/crud-store.ts @@ -1834,7 +1834,7 @@ class CrudStoreImpl openCreateIndexModal() { this.localAppRegistry.emit('open-create-index-modal', { - query: EJSON.serialize(this.queryBar.getLastAppliedQuery('crud')), + query: EJSON.serialize(this.queryBar.getLastAppliedQuery('crud').filter), }); } diff --git a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx index c0cb3edc257..0ef14ba05ca 100644 --- a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx +++ b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx @@ -21,7 +21,6 @@ import { usePreference } from 'compass-preferences-model/provider'; import IndexFlowSection from './index-flow-section'; import QueryFlowSection from './query-flow-section'; import toNS from 'mongodb-ns'; -import type { Document } from 'bson'; const createIndexModalFieldsStyles = css({ margin: `${spacing[600]}px 0 ${spacing[800]}px 0`, @@ -50,7 +49,7 @@ export type CreateIndexFormProps = { onRemoveFieldClick: (idx: number) => void; // Minus icon. onTabClick: (tab: Tab) => void; showIndexesGuidanceVariant?: boolean; - query: Document | null; + query: string | null; }; function CreateIndexForm({ diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index 656150a799c..43d80af0db1 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -17,10 +17,8 @@ import { errorEncountered, type Field } from '../../modules/create-index'; import MDBCodeViewer from './mdb-code-viewer'; import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; import { connect } from 'react-redux'; -import { - TrackFunction, - useTelemetry, -} from '@mongodb-js/compass-telemetry/provider'; +import type { TrackFunction } from '@mongodb-js/compass-telemetry/provider'; +import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; const flexContainerStyles = css({ display: 'flex', @@ -212,7 +210,7 @@ const IndexFlowSection = ({ showCoveredQueries: true, }); } catch (e) { - onErrorEncountered(e.message); + onErrorEncountered(e instanceof Error ? e.message : String(e)); } setHasFieldChanges(false); diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index 9244ccc81f0..4ed7fbd69e1 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -106,10 +106,10 @@ const QueryFlowSection = ({ }: SuggestedIndexFetchedProps) => Promise; indexSuggestions: Record | null; fetchingSuggestionsState: IndexSuggestionState; - initialQuery: Document | null; + initialQuery: string | null; }) => { const [inputQuery, setInputQuery] = React.useState( - JSON.stringify(initialQuery?.filter, null, 2) + initialQuery ? JSON.stringify(initialQuery, null, 2) : '' ); const [hasNewChanges, setHasNewChanges] = React.useState( initialQuery !== null diff --git a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx index 43deed72bd8..a8953aefd03 100644 --- a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx +++ b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx @@ -29,14 +29,13 @@ import { import { useConnectionInfoRef } from '@mongodb-js/compass-connections/provider'; import { usePreference } from 'compass-preferences-model/provider'; import CreateIndexModalHeader from './create-index-modal-header'; -import type { Document } from 'bson'; type CreateIndexModalProps = React.ComponentProps & { isVisible: boolean; namespace: string; error: string | null; currentTab: Tab; - query: Document | null; + query: string | null; onErrorBannerCloseClick: () => void; onCreateIndexClick: () => void; onCancelCreateIndexClick: () => void; From 9ee4bda66bde012e2bd3fa30b092426bfda9bc0a Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 20 May 2025 11:43:02 -0400 Subject: [PATCH 08/16] fix more typing and clear error when there's new changes --- packages/compass-crud/src/stores/crud-store.ts | 2 +- .../create-index-form/index-flow-section.tsx | 12 ++++++++++-- .../compass-indexes/src/modules/create-index.tsx | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/compass-crud/src/stores/crud-store.ts b/packages/compass-crud/src/stores/crud-store.ts index 40b0b98e451..34b61bfa6ba 100644 --- a/packages/compass-crud/src/stores/crud-store.ts +++ b/packages/compass-crud/src/stores/crud-store.ts @@ -1834,7 +1834,7 @@ class CrudStoreImpl openCreateIndexModal() { this.localAppRegistry.emit('open-create-index-modal', { - query: EJSON.serialize(this.queryBar.getLastAppliedQuery('crud').filter), + query: EJSON.serialize(this.queryBar.getLastAppliedQuery('crud')?.filter), }); } diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index 43d80af0db1..dfc646f352a 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -13,7 +13,11 @@ import { Tooltip, } from '@mongodb-js/compass-components'; import React, { useState, useCallback, useEffect } from 'react'; -import { errorEncountered, type Field } from '../../modules/create-index'; +import { + errorCleared, + errorEncountered, + type Field, +} from '../../modules/create-index'; import MDBCodeViewer from './mdb-code-viewer'; import { areAllFieldsFilledIn } from '../../utils/create-index-modal-validation'; import { connect } from 'react-redux'; @@ -82,6 +86,7 @@ export type IndexFlowSectionProps = { dbName: string; collectionName: string; onErrorEncountered: (error: string) => void; + onErrorCleared: () => void; }; const generateCoveredQueries = ( @@ -163,6 +168,7 @@ const IndexFlowSection = ({ dbName, collectionName, onErrorEncountered, + onErrorCleared, }: IndexFlowSectionProps) => { const [isCodeEquivalentToggleChecked, setIsCodeEquivalentToggleChecked] = useState(false); @@ -218,7 +224,8 @@ const IndexFlowSection = ({ useEffect(() => { setHasFieldChanges(true); - }, [fields]); + onErrorCleared(); + }, [fields, onErrorCleared]); const { coveredQueries, optimalQueries, showCoveredQueries } = coveredQueriesObj; @@ -346,6 +353,7 @@ const mapState = () => { const mapDispatch = { onErrorEncountered: errorEncountered, + onErrorCleared: errorCleared, }; export default connect(mapState, mapDispatch)(IndexFlowSection); diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index d869bb25d17..994d22943c5 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -77,7 +77,7 @@ type ErrorClearedAction = { export type CreateIndexOpenedAction = { type: ActionTypes.CreateIndexOpened; - query?: BsonDocument; + query?: string; }; type CreateIndexClosedAction = { @@ -314,7 +314,7 @@ export type State = { sampleDocs: Array | null; // base query to be used for query flow index creation - query: BsonDocument | null; + query: string | null; }; export const INITIAL_STATE: State = { From cfe7f9cb8c8150887d5ddfa9fb7ac53ce5bdd5d0 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 20 May 2025 11:54:59 -0400 Subject: [PATCH 09/16] more linting + error handling --- .../create-index-form/query-flow-section.tsx | 4 +++ .../src/modules/create-index.tsx | 35 ++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index 4ed7fbd69e1..f183bdd5369 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -153,6 +153,10 @@ const QueryFlowSection = ({ // Validate query upon typing try { parseFilter(inputQuery); + + if (!inputQuery.startsWith('{') || !inputQuery.endsWith('}')) { + isShowSuggestionsButtonDisabled = true; + } } catch (e) { isShowSuggestionsButtonDisabled = true; } diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index 994d22943c5..0d7ce221911 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -412,6 +412,19 @@ export const fetchIndexSuggestions = ({ } } + const throwError = (e?: unknown) => { + dispatch({ + type: ActionTypes.SuggestedIndexesFetched, + sampleDocs: sampleDocuments || [], + indexSuggestions: null, + error: + e instanceof Error + ? 'Error parsing query. Please follow query structure. ' + e.message + : 'Error parsing query. Please follow query structure.', + indexSuggestionsState: 'error', + }); + }; + // Analyze namespace and fetch suggestions try { const analyzedNamespace = mql.analyzeNamespace( @@ -426,6 +439,14 @@ export const fetchIndexSuggestions = ({ const results = await mql.suggestIndex([query]); const indexSuggestions = results?.index; + if ( + !indexSuggestions || + Object.keys(indexSuggestions as Record).length === 0 + ) { + throwError(); + return; + } + dispatch({ type: ActionTypes.SuggestedIndexesFetched, sampleDocs: sampleDocuments, @@ -434,18 +455,8 @@ export const fetchIndexSuggestions = ({ indexSuggestionsState: 'success', }); } catch (e: unknown) { - dispatch({ - type: ActionTypes.SuggestedIndexesFetched, - sampleDocs: sampleDocuments, - indexSuggestions: null, - error: - e instanceof Error - ? 'Error parsing query. Please follow query structure. ' + e.message - : 'Error parsing query. Please follow query structure.', - indexSuggestionsState: 'error', - }); - track('Error parsing query', { context: 'Create Index Modal' }); + throwError(e); } }; }; @@ -509,7 +520,7 @@ export const createIndexFormSubmitted = (): IndexesThunkAction< const formIndexOptions = getState().createIndex.options; - let spec: Record; + let spec: Record = {}; try { if (isQueryFlow) { From a0f5f199f0a8d6bc1ffe7d7b6a9b2d78be194101 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Fri, 23 May 2025 10:44:15 -0400 Subject: [PATCH 10/16] fixed initialQuery typing, wrapped validation inside useMemo, and added comments for cleaning --- .../create-index-form/index-flow-section.tsx | 1 + .../create-index-form/query-flow-section.tsx | 27 +++++++++++-------- .../src/modules/create-index.tsx | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx index dfc646f352a..93c9bb957ce 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx @@ -104,6 +104,7 @@ const generateCoveredQueries = ( } if (rows.length === 0) { + // TODO: remove this in CLOUDP-320224 track('Error generating covered queries', { context: 'Create Index Modal', }); diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index f183bdd5369..0eaaa938ce1 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -108,12 +108,13 @@ const QueryFlowSection = ({ fetchingSuggestionsState: IndexSuggestionState; initialQuery: string | null; }) => { - const [inputQuery, setInputQuery] = React.useState( - initialQuery ? JSON.stringify(initialQuery, null, 2) : '' - ); + const [inputQuery, setInputQuery] = React.useState(initialQuery || ''); const [hasNewChanges, setHasNewChanges] = React.useState( initialQuery !== null ); + const [isShowSuggestionsButtonDisabled, setIsShowSuggestionsButtonDisabled] = + React.useState(true); + const completer = useMemo( () => createQueryAutocompleter({ @@ -148,18 +149,22 @@ const QueryFlowSection = ({ }, []); const isFetchingIndexSuggestions = fetchingSuggestionsState === 'fetching'; - let isShowSuggestionsButtonDisabled = !hasNewChanges; // Validate query upon typing - try { - parseFilter(inputQuery); + useMemo(() => { + let _isShowSuggestionsButtonDisabled = !hasNewChanges; + try { + parseFilter(inputQuery); - if (!inputQuery.startsWith('{') || !inputQuery.endsWith('}')) { - isShowSuggestionsButtonDisabled = true; + if (!inputQuery.startsWith('{') || !inputQuery.endsWith('}')) { + _isShowSuggestionsButtonDisabled = true; + } + } catch (e) { + _isShowSuggestionsButtonDisabled = true; + } finally { + setIsShowSuggestionsButtonDisabled(_isShowSuggestionsButtonDisabled); } - } catch (e) { - isShowSuggestionsButtonDisabled = true; - } + }, [hasNewChanges, inputQuery]); return ( <> diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index 0d7ce221911..2167486cc78 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -455,6 +455,7 @@ export const fetchIndexSuggestions = ({ indexSuggestionsState: 'success', }); } catch (e: unknown) { + // TODO: remove this in CLOUDP-320224 track('Error parsing query', { context: 'Create Index Modal' }); throwError(e); } From 90317a19a45f70e375713b66063cb7e24f08109e Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Fri, 23 May 2025 10:53:43 -0400 Subject: [PATCH 11/16] fixed up typing more --- .../src/components/create-index-form/create-index-form.tsx | 3 ++- .../components/create-index-form/query-flow-section.tsx | 7 +++++-- .../components/create-index-modal/create-index-modal.tsx | 3 ++- packages/compass-indexes/src/modules/create-index.tsx | 6 +++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx index 0ef14ba05ca..373361d30f8 100644 --- a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx +++ b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx @@ -21,6 +21,7 @@ import { usePreference } from 'compass-preferences-model/provider'; import IndexFlowSection from './index-flow-section'; import QueryFlowSection from './query-flow-section'; import toNS from 'mongodb-ns'; +import type { Document as BsonDocument } from 'bson'; const createIndexModalFieldsStyles = css({ margin: `${spacing[600]}px 0 ${spacing[800]}px 0`, @@ -49,7 +50,7 @@ export type CreateIndexFormProps = { onRemoveFieldClick: (idx: number) => void; // Minus icon. onTabClick: (tab: Tab) => void; showIndexesGuidanceVariant?: boolean; - query: string | null; + query: BsonDocument | null; }; function CreateIndexForm({ diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index 0eaaa938ce1..b79a1f7fc22 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -7,6 +7,7 @@ import { useFocusRing, ParagraphSkeleton, } from '@mongodb-js/compass-components'; +import type { Document as BsonDocument } from 'bson'; import React, { useMemo, useCallback } from 'react'; import { css, spacing } from '@mongodb-js/compass-components'; import { @@ -106,9 +107,11 @@ const QueryFlowSection = ({ }: SuggestedIndexFetchedProps) => Promise; indexSuggestions: Record | null; fetchingSuggestionsState: IndexSuggestionState; - initialQuery: string | null; + initialQuery: BsonDocument | null; }) => { - const [inputQuery, setInputQuery] = React.useState(initialQuery || ''); + const [inputQuery, setInputQuery] = React.useState( + JSON.stringify(initialQuery ?? '', null, 2) + ); const [hasNewChanges, setHasNewChanges] = React.useState( initialQuery !== null ); diff --git a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx index a8953aefd03..bd5ba5a0ea6 100644 --- a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx +++ b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx @@ -29,13 +29,14 @@ import { import { useConnectionInfoRef } from '@mongodb-js/compass-connections/provider'; import { usePreference } from 'compass-preferences-model/provider'; import CreateIndexModalHeader from './create-index-modal-header'; +import type { Document as BsonDocument } from 'bson'; type CreateIndexModalProps = React.ComponentProps & { isVisible: boolean; namespace: string; error: string | null; currentTab: Tab; - query: string | null; + query: BsonDocument | null; onErrorBannerCloseClick: () => void; onCreateIndexClick: () => void; onCancelCreateIndexClick: () => void; diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index 2167486cc78..5b4ed1203a2 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -77,7 +77,7 @@ type ErrorClearedAction = { export type CreateIndexOpenedAction = { type: ActionTypes.CreateIndexOpened; - query?: string; + query?: BsonDocument; }; type CreateIndexClosedAction = { @@ -314,7 +314,7 @@ export type State = { sampleDocs: Array | null; // base query to be used for query flow index creation - query: string | null; + query: BsonDocument | null; }; export const INITIAL_STATE: State = { @@ -339,7 +339,7 @@ function getInitialState(): State { //------- -export const createIndexOpened = (query?: BsonDocument) => ({ +export const createIndexOpened = (query?: Document) => ({ type: ActionTypes.CreateIndexOpened, query, }); From ac4a2960a1935daaf79cdaa9d5e9c0c919a59d19 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 27 May 2025 10:54:45 -0400 Subject: [PATCH 12/16] fixed index flow section test by wrapping it in provider --- .../index-flow-section.spec.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx b/packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx index 22574ea61ee..4132fadc4a8 100644 --- a/packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx +++ b/packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx @@ -3,8 +3,11 @@ import { render, screen } from '@mongodb-js/testing-library-compass'; import IndexFlowSection from './index-flow-section'; import { expect } from 'chai'; import type { Field } from '../../modules/create-index'; +import { Provider } from 'react-redux'; +import { setupStore } from '../../../test/setup-store'; describe('IndexFlowSection', () => { + const store = setupStore(); const renderComponent = ({ createIndexFieldsComponent, fields, @@ -13,12 +16,14 @@ describe('IndexFlowSection', () => { fields?: Field[]; }) => { render( - + + + ); }; From 0027f2ae242b5f363ae1183a19d2a1352e717c56 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 27 May 2025 10:59:23 -0400 Subject: [PATCH 13/16] changed document to use mongodb one --- .../src/components/create-index-form/create-index-form.tsx | 4 ++-- .../src/components/create-index-form/query-flow-section.tsx | 4 ++-- .../src/components/create-index-modal/create-index-modal.tsx | 4 ++-- packages/compass-indexes/src/modules/create-index.tsx | 5 ++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx index 373361d30f8..38b46e01153 100644 --- a/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx +++ b/packages/compass-indexes/src/components/create-index-form/create-index-form.tsx @@ -21,7 +21,7 @@ import { usePreference } from 'compass-preferences-model/provider'; import IndexFlowSection from './index-flow-section'; import QueryFlowSection from './query-flow-section'; import toNS from 'mongodb-ns'; -import type { Document as BsonDocument } from 'bson'; +import type { Document } from 'mongodb'; const createIndexModalFieldsStyles = css({ margin: `${spacing[600]}px 0 ${spacing[800]}px 0`, @@ -50,7 +50,7 @@ export type CreateIndexFormProps = { onRemoveFieldClick: (idx: number) => void; // Minus icon. onTabClick: (tab: Tab) => void; showIndexesGuidanceVariant?: boolean; - query: BsonDocument | null; + query: Document | null; }; function CreateIndexForm({ diff --git a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx index b79a1f7fc22..0c304747fff 100644 --- a/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx +++ b/packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx @@ -7,7 +7,7 @@ import { useFocusRing, ParagraphSkeleton, } from '@mongodb-js/compass-components'; -import type { Document as BsonDocument } from 'bson'; +import type { Document } from 'mongodb'; import React, { useMemo, useCallback } from 'react'; import { css, spacing } from '@mongodb-js/compass-components'; import { @@ -107,7 +107,7 @@ const QueryFlowSection = ({ }: SuggestedIndexFetchedProps) => Promise; indexSuggestions: Record | null; fetchingSuggestionsState: IndexSuggestionState; - initialQuery: BsonDocument | null; + initialQuery: Document | null; }) => { const [inputQuery, setInputQuery] = React.useState( JSON.stringify(initialQuery ?? '', null, 2) diff --git a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx index bd5ba5a0ea6..88205465d46 100644 --- a/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx +++ b/packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx @@ -29,14 +29,14 @@ import { import { useConnectionInfoRef } from '@mongodb-js/compass-connections/provider'; import { usePreference } from 'compass-preferences-model/provider'; import CreateIndexModalHeader from './create-index-modal-header'; -import type { Document as BsonDocument } from 'bson'; +import type { Document } from 'mongodb'; type CreateIndexModalProps = React.ComponentProps & { isVisible: boolean; namespace: string; error: string | null; currentTab: Tab; - query: BsonDocument | null; + query: Document | null; onErrorBannerCloseClick: () => void; onCreateIndexClick: () => void; onCancelCreateIndexClick: () => void; diff --git a/packages/compass-indexes/src/modules/create-index.tsx b/packages/compass-indexes/src/modules/create-index.tsx index 5b4ed1203a2..1bfe5c17a96 100644 --- a/packages/compass-indexes/src/modules/create-index.tsx +++ b/packages/compass-indexes/src/modules/create-index.tsx @@ -1,5 +1,4 @@ import type { Document } from 'mongodb'; -import type { Document as BsonDocument } from 'bson'; import { EJSON, ObjectId } from 'bson'; import type { CreateIndexesOptions, IndexDirection } from 'mongodb'; import { isCollationValid } from 'mongodb-query-parser'; @@ -77,7 +76,7 @@ type ErrorClearedAction = { export type CreateIndexOpenedAction = { type: ActionTypes.CreateIndexOpened; - query?: BsonDocument; + query?: Document; }; type CreateIndexClosedAction = { @@ -314,7 +313,7 @@ export type State = { sampleDocs: Array | null; // base query to be used for query flow index creation - query: BsonDocument | null; + query: Document | null; }; export const INITIAL_STATE: State = { From e7d6b2493a96b976e008837f441c4d39ce647cba Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 27 May 2025 12:20:39 -0400 Subject: [PATCH 14/16] added provider to create-index-form.spec.tsx too --- .../create-index-form.spec.tsx | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-form/create-index-form.spec.tsx b/packages/compass-indexes/src/components/create-index-form/create-index-form.spec.tsx index 507bea611c4..12e495ec2ef 100644 --- a/packages/compass-indexes/src/components/create-index-form/create-index-form.spec.tsx +++ b/packages/compass-indexes/src/components/create-index-form/create-index-form.spec.tsx @@ -5,10 +5,13 @@ import type { Field } from '../../modules/create-index'; import { expect } from 'chai'; import type { SinonSpy } from 'sinon'; +import { setupStore } from '../../../test/setup-store'; import sinon from 'sinon'; +import { Provider } from 'react-redux'; describe('CreateIndexForm', () => { let onTabClickSpy: SinonSpy; + const store = setupStore(); beforeEach(function () { onTabClickSpy = sinon.spy(); @@ -20,24 +23,26 @@ describe('CreateIndexForm', () => { showIndexesGuidanceVariant?: boolean; }) => { render( - {}} - onSelectFieldTypeClick={() => {}} - onAddFieldClick={() => {}} - onRemoveFieldClick={() => {}} - onTabClick={onTabClickSpy} - showIndexesGuidanceVariant={showIndexesGuidanceVariant || false} - query={null} - /> + + {}} + onSelectFieldTypeClick={() => {}} + onAddFieldClick={() => {}} + onRemoveFieldClick={() => {}} + onTabClick={onTabClickSpy} + showIndexesGuidanceVariant={showIndexesGuidanceVariant || false} + query={null} + /> + ); }; From cab72ad56d16eece9582a3e8d2e258e44acf6d1d Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 27 May 2025 12:55:38 -0400 Subject: [PATCH 15/16] fix tests for create-index-actions.spec.tsx --- ...spec.jsx => create-index-actions.spec.tsx} | 80 ++++++------------- 1 file changed, 23 insertions(+), 57 deletions(-) rename packages/compass-indexes/src/components/create-index-actions/{create-index-actions.spec.jsx => create-index-actions.spec.tsx} (62%) diff --git a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.jsx b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx similarity index 62% rename from packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.jsx rename to packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx index f76599042c2..6e2e96d7645 100644 --- a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.jsx +++ b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx @@ -8,13 +8,16 @@ import { userEvent, within, } from '@mongodb-js/testing-library-compass'; +import { setupStore } from '../../../test/setup-store'; +import { Provider } from 'react-redux'; -import CreateIndexActions from '../create-index-actions'; +import CreateIndexActions from '.'; describe('CreateIndexActions Component', function () { let clearErrorSpy; let onCreateIndexClickSpy; let closeCreateIndexModalSpy; + const store = setupStore(); beforeEach(function () { clearErrorSpy = sinon.spy(); @@ -28,15 +31,21 @@ describe('CreateIndexActions Component', function () { closeCreateIndexModalSpy = null; }); - it('renders a cancel button', function () { + const renderComponent = (error?: string) => { render( - + + + ); + }; + it('renders a cancel button', function () { + renderComponent(); const button = screen.getByTestId('create-index-actions-cancel-button'); expect(button.textContent).to.be.equal('Cancel'); @@ -44,14 +53,7 @@ describe('CreateIndexActions Component', function () { context('onCancel', function () { it('calls the closeCreateIndexModal function', function () { - render( - - ); + renderComponent(); const button = screen.getByTestId('create-index-actions-cancel-button'); userEvent.click(button); @@ -61,14 +63,7 @@ describe('CreateIndexActions Component', function () { context('onConfirm', function () { it('calls the onCreateIndexClick function', function () { - render( - - ); + renderComponent(); const button = screen.getByTestId( 'create-index-actions-create-index-button' @@ -79,15 +74,7 @@ describe('CreateIndexActions Component', function () { }); it('renders a create index button', function () { - render( - - ); - + renderComponent(); const button = screen.getByTestId( 'create-index-actions-create-index-button' ); @@ -96,14 +83,7 @@ describe('CreateIndexActions Component', function () { context('with error', function () { it('renders error banner', function () { - render( - - ); + renderComponent('Some error happened!'); const errorBanner = screen.getByTestId( 'create-index-actions-error-banner-wrapper' @@ -112,14 +92,7 @@ describe('CreateIndexActions Component', function () { }); it('closes error banner', function () { - render( - - ); + renderComponent('Some error happened!'); const errorBanner = screen.getByTestId( 'create-index-actions-error-banner-wrapper' @@ -133,14 +106,7 @@ describe('CreateIndexActions Component', function () { context('without error', function () { it('does not render error banner', function () { - render( - - ); + renderComponent(); const errorBanner = screen.queryByTestId( 'create-index-actions-error-banner-wrapper' From 16706e7bb93780dde8239ddd6ed95e3b6ba06092 Mon Sep 17 00:00:00 2001 From: Ruby Dong Date: Tue, 27 May 2025 13:58:54 -0400 Subject: [PATCH 16/16] add typing for the spys --- .../create-index-actions/create-index-actions.spec.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx index 6e2e96d7645..11b3aa88bd3 100644 --- a/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx +++ b/packages/compass-indexes/src/components/create-index-actions/create-index-actions.spec.tsx @@ -14,9 +14,9 @@ import { Provider } from 'react-redux'; import CreateIndexActions from '.'; describe('CreateIndexActions Component', function () { - let clearErrorSpy; - let onCreateIndexClickSpy; - let closeCreateIndexModalSpy; + let clearErrorSpy: any; + let onCreateIndexClickSpy: any; + let closeCreateIndexModalSpy: any; const store = setupStore(); beforeEach(function () {