diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts new file mode 100644 index 00000000000..0068109918f --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/constants.ts @@ -0,0 +1 @@ +export const DEFAULT_OUTPUT_DOCS_COUNT = 1000; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/mock-generator-modal.tsx b/packages/compass-collection/src/components/mock-data-generator-modal/mock-generator-modal.tsx new file mode 100644 index 00000000000..3d42da426f9 --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/mock-generator-modal.tsx @@ -0,0 +1,104 @@ +import React, { useState } from 'react'; + +import { css } from '@mongodb-js/compass-components'; + +import { + Button, + Modal, + ModalHeader, + ModalBody, + ModalFooter, + ButtonVariant, +} from '@mongodb-js/compass-components'; +import { MockDataGeneratorSteps } from './types'; +import { DEFAULT_OUTPUT_DOCS_COUNT } from './constants'; + +const footerStyles = css` + flex-direction: row; + justify-content: space-between; +`; + +const rightButtonsStyles = css` + display: flex; + gap: 8px; + flex-direction: row; +`; + +interface Props { + isOpen: boolean; + setIsOpen: (isOpen: boolean) => void; +} + +const MockDataGeneratorModal = ({ isOpen, setIsOpen }: Props) => { + const [currentStep, setCurrentStep] = useState( + MockDataGeneratorSteps.AI_DISCLAIMER + ); + const [rawSchema, setRawSchema] = useState(null); + const [fakerSchema, setFakerSchema] = useState(null); + const [outputDocsCount, setOutputDocsCount] = useState( + DEFAULT_OUTPUT_DOCS_COUNT + ); + const [validationRules, setValidationRules] = useState(null); + const [sampleDoc, setSampleDoc] = useState(null); + + const resetState = () => { + setCurrentStep(MockDataGeneratorSteps.AI_DISCLAIMER); + setRawSchema(null); + setFakerSchema(null); + setOutputDocsCount(DEFAULT_OUTPUT_DOCS_COUNT); + setValidationRules(null); + setSampleDoc(null); + }; + + const onNext = () => { + if (currentStep < MockDataGeneratorSteps.GENERATE_DATA) { + setCurrentStep(currentStep + 1); + } else { + // Final step, close the modal + setIsOpen(false); + resetState(); + } + }; + + const onBack = () => { + if (currentStep > MockDataGeneratorSteps.AI_DISCLAIMER) { + setCurrentStep(currentStep - 1); + } + }; + + const onCancel = () => { + setIsOpen(false); + }; + + return ( + setIsOpen(false)} + data-testid="generate-mock-data-modal" + > + + + {currentStep === MockDataGeneratorSteps.AI_DISCLAIMER &&
} + {currentStep === MockDataGeneratorSteps.SCHEMA_CONFIRMATION && ( +
+ )} + {currentStep === MockDataGeneratorSteps.SCHEMA_EDITOR &&
} + {currentStep === MockDataGeneratorSteps.DOCUMENT_COUNT &&
} + {currentStep === MockDataGeneratorSteps.PREVIEW_DATA &&
} + {currentStep === MockDataGeneratorSteps.GENERATE_DATA &&
} +
+ + + +
+ + +
+
+
+ ); +}; + +export default MockDataGeneratorModal; diff --git a/packages/compass-collection/src/components/mock-data-generator-modal/types.ts b/packages/compass-collection/src/components/mock-data-generator-modal/types.ts new file mode 100644 index 00000000000..c1ca93a830c --- /dev/null +++ b/packages/compass-collection/src/components/mock-data-generator-modal/types.ts @@ -0,0 +1,8 @@ +export enum MockDataGeneratorSteps { + AI_DISCLAIMER = 1, + SCHEMA_CONFIRMATION = 2, + SCHEMA_EDITOR = 3, + DOCUMENT_COUNT = 4, + PREVIEW_DATA = 5, + GENERATE_DATA = 6, +} diff --git a/packages/compass-telemetry/src/experimentation-provider.tsx b/packages/compass-telemetry/src/experimentation-provider.tsx new file mode 100644 index 00000000000..044cbaacabd --- /dev/null +++ b/packages/compass-telemetry/src/experimentation-provider.tsx @@ -0,0 +1,86 @@ +import React, { createContext, useContext, useMemo } from 'react'; + +interface ExperimentAssignmentData { + variant: string | null; + isInSample: boolean; +} + +interface ExperimentData { + assignmentDate: Date; + entityId: string; + entityType: string; + id: string; + tag: string; + testGroupDatabaseId: string; + testGroupId: string; + testId: string; + testName: string; +} + +interface SDKAssignment { + assignmentData: ExperimentAssignmentData; + experimentData: ExperimentData | null; +} + +interface UseAssignmentResponse { + assignment: SDKAssignment | null; + asyncStatus: 'LOADING' | 'SUCCESS' | 'ERROR'; + error?: Error; +} + +interface BasicAPICallingFunctionOptions { + timeoutMs?: number; + team?: string; +} + +type UseAssignmentHookFn = ( + experimentName: string, + trackIsInSample: boolean, + options?: BasicAPICallingFunctionOptions +) => UseAssignmentResponse; + +type AssignExperimentFn = ( + experimentName: string, + options?: BasicAPICallingFunctionOptions +) => Promise<'SUCCESS' | 'ERROR' | null>; + +interface CompassExperimentationProviderContextValue { + useAssignment: UseAssignmentHookFn; + assignExperiment: AssignExperimentFn; +} + +const ExperimentationContext = + createContext({ + useAssignment() { + return { + assignment: null, + asyncStatus: 'SUCCESS' as const, + }; + }, + assignExperiment() { + return Promise.resolve(null); + }, + }); + +// Provider component that accepts MMS experiment utils as props +export const CompassExperimentationProvider: React.FC<{ + children: React.ReactNode; + useAssignment: UseAssignmentHookFn; + assignExperiment: AssignExperimentFn; +}> = ({ children, useAssignment, assignExperiment }) => { + const contextValue = useMemo( + () => ({ useAssignment, assignExperiment }), + [useAssignment, assignExperiment] + ); + + return ( + + {children} + + ); +}; + +// Hook for components to access experiment assignment +export const useAssignment = (...args: Parameters) => { + return useContext(ExperimentationContext).useAssignment(...args); +}; diff --git a/packages/compass-telemetry/src/index.ts b/packages/compass-telemetry/src/index.ts index a2e155c8073..e7cadf9d208 100644 --- a/packages/compass-telemetry/src/index.ts +++ b/packages/compass-telemetry/src/index.ts @@ -5,3 +5,5 @@ export type { IdentifyTraits, ExtraConnectionData, } from './types'; + +export { CompassExperimentationProvider } from './experimentation-provider'; diff --git a/packages/compass-web/src/index.tsx b/packages/compass-web/src/index.tsx index 2c6525f50c2..e9078380492 100644 --- a/packages/compass-web/src/index.tsx +++ b/packages/compass-web/src/index.tsx @@ -4,3 +4,5 @@ export type { OpenWorkspaceOptions, WorkspaceTab, } from '@mongodb-js/compass-workspaces'; + +export { CompassExperimentationProvider } from '@mongodb-js/compass-telemetry';