diff --git a/packages/compass-schema/src/components/compass-schema.tsx b/packages/compass-schema/src/components/compass-schema.tsx index 0d346509668..0d16168e183 100644 --- a/packages/compass-schema/src/components/compass-schema.tsx +++ b/packages/compass-schema/src/components/compass-schema.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useState } from 'react'; import type { Schema as MongodbSchema } from 'mongodb-schema'; import { connect } from 'react-redux'; import type { AnalysisState } from '../constants/analysis-states'; @@ -7,11 +7,9 @@ import { ANALYSIS_STATE_ANALYZING, ANALYSIS_STATE_COMPLETE, } from '../constants/analysis-states'; - -import { SchemaToolbar } from './schema-toolbar/schema-toolbar'; +import SchemaToolbar from './schema-toolbar'; import Field from './field'; import { ZeroGraphic } from './zero-graphic'; - import { Button, CancelLoader, @@ -36,15 +34,10 @@ import { getAtlasPerformanceAdvisorLink } from '../utils'; import { useIsLastAppliedQueryOutdated } from '@mongodb-js/compass-query-bar'; import { useTelemetry } from '@mongodb-js/compass-telemetry/provider'; import type { RootState } from '../stores/store'; -import { - analysisErrorDismissed, - type SchemaAnalysisError, - startAnalysis, - stopAnalysis, -} from '../stores/schema-analysis-reducer'; +import { startAnalysis, stopAnalysis } from '../stores/schema-analysis-reducer'; import { openExportSchema } from '../stores/schema-export-reducer'; import ExportSchemaModal from './export-schema-modal'; -import ExportSchemaLegacyBanner from './export-schema-legacy-banner'; +import ExportSchemaLegacyModal from './export-schema-legacy-modal'; const rootStyles = css({ width: '100%', @@ -376,29 +369,23 @@ const PerformanceAdvisorBanner = () => { const Schema: React.FunctionComponent<{ analysisState: AnalysisState; - error?: SchemaAnalysisError; - maxTimeMS?: number; + isExportSchemaModalOpen: boolean; schema: MongodbSchema | null; - count?: number; - resultId?: string; - onExportSchemaClicked: () => void; onStartAnalysis: () => Promise; onStopAnalysis: () => void; - onDismissError: () => void; }> = ({ analysisState, - error, + isExportSchemaModalOpen, schema, - resultId, - onExportSchemaClicked, onStartAnalysis, onStopAnalysis, - onDismissError, }) => { const onApplyClicked = useCallback(() => { void onStartAnalysis(); }, [onStartAnalysis]); + const [showLegacyExportTooltip, setShowLegacyExportTooltip] = useState(false); + const outdated = useIsLastAppliedQueryOutdated('schema'); const enablePerformanceAdvisorBanner = usePreference( @@ -414,14 +401,14 @@ const Schema: React.FunctionComponent<{ toolbar={ } > @@ -440,7 +427,11 @@ const Schema: React.FunctionComponent<{ {enableExportSchema && } - {enableExportSchema && } + {enableExportSchema && ( + + )} ); }; @@ -448,14 +439,12 @@ const Schema: React.FunctionComponent<{ export default connect( (state: RootState) => ({ analysisState: state.schemaAnalysis.analysisState, - error: state.schemaAnalysis.error, + isExportSchemaModalOpen: state.schemaExport.isOpen, schema: state.schemaAnalysis.schema, - resultId: state.schemaAnalysis.resultId, }), { onStartAnalysis: startAnalysis, onStopAnalysis: () => stopAnalysis(), onExportSchemaClicked: openExportSchema, - onDismissError: analysisErrorDismissed, } )(Schema); diff --git a/packages/compass-schema/src/components/export-schema-legacy-banner.tsx b/packages/compass-schema/src/components/export-schema-legacy-modal.tsx similarity index 96% rename from packages/compass-schema/src/components/export-schema-legacy-banner.tsx rename to packages/compass-schema/src/components/export-schema-legacy-modal.tsx index 71415ac892b..1dbcfc59b0a 100644 --- a/packages/compass-schema/src/components/export-schema-legacy-banner.tsx +++ b/packages/compass-schema/src/components/export-schema-legacy-modal.tsx @@ -16,7 +16,7 @@ import { confirmedExportLegacySchemaToClipboard, switchToSchemaExport, SchemaExportActions, - stopShowingLegacyBanner, + stopShowingLegacyModal, } from '../stores/schema-export-reducer'; const SchemaExportSVG = () => ( @@ -463,28 +463,42 @@ const optionHeaderStyles = css({ margin: '0px', }); -const ExportSchemaLegacyBanner: React.FunctionComponent<{ +const ExportSchemaLegacyModal: React.FunctionComponent<{ isOpen: boolean; onClose: () => void; onLegacyShare: () => void; onSwitchToSchemaExport: () => void; - stopShowingLegacyBanner: (choice: 'legacy' | 'export') => void; + setShowLegacyExportTooltip: (show: boolean) => void; + stopShowingLegacyModal: (choice: 'legacy' | 'export') => void; }> = ({ isOpen, onClose, onLegacyShare, onSwitchToSchemaExport, - stopShowingLegacyBanner, + setShowLegacyExportTooltip, + stopShowingLegacyModal, }) => { const [dontShowAgainChecked, setDontShowAgainChecked] = useState(false); const handleLegacyShare = useCallback(() => { - if (dontShowAgainChecked) stopShowingLegacyBanner('legacy'); + if (dontShowAgainChecked) stopShowingLegacyModal('legacy'); onLegacyShare(); - }, [onLegacyShare, dontShowAgainChecked, stopShowingLegacyBanner]); + setShowLegacyExportTooltip(true); + }, [ + onLegacyShare, + dontShowAgainChecked, + stopShowingLegacyModal, + setShowLegacyExportTooltip, + ]); const handleSwitchToNew = useCallback(() => { - if (dontShowAgainChecked) stopShowingLegacyBanner('export'); + if (dontShowAgainChecked) stopShowingLegacyModal('export'); + setShowLegacyExportTooltip(true); onSwitchToSchemaExport(); - }, [onSwitchToSchemaExport, dontShowAgainChecked, stopShowingLegacyBanner]); + }, [ + onSwitchToSchemaExport, + dontShowAgainChecked, + stopShowingLegacyModal, + setShowLegacyExportTooltip, + ]); return ( ({ - isOpen: state.schemaExport.isLegacyBannerOpen, + isOpen: state.schemaExport.isLegacyModalOpen, }), (dispatch: SchemaThunkDispatch) => ({ - onClose: () => dispatch({ type: SchemaExportActions.closeLegacyBanner }), + onClose: () => dispatch({ type: SchemaExportActions.closeLegacyModal }), onLegacyShare: () => dispatch(confirmedExportLegacySchemaToClipboard()), onSwitchToSchemaExport: () => dispatch(switchToSchemaExport()), - stopShowingLegacyBanner: (choice: 'legacy' | 'export') => - dispatch(stopShowingLegacyBanner(choice)), + stopShowingLegacyModal: (choice: 'legacy' | 'export') => + dispatch(stopShowingLegacyModal(choice)), }) -)(ExportSchemaLegacyBanner); +)(ExportSchemaLegacyModal); diff --git a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx b/packages/compass-schema/src/components/schema-toolbar.spec.tsx similarity index 98% rename from packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx rename to packages/compass-schema/src/components/schema-toolbar.spec.tsx index b9ec2a1d13c..9c70e85e7e9 100644 --- a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.spec.tsx +++ b/packages/compass-schema/src/components/schema-toolbar.spec.tsx @@ -47,6 +47,8 @@ describe('SchemaToolbar', function () { sampleSize={10} schemaResultId="123" onExportSchemaClicked={() => {}} + setShowLegacyExportTooltip={() => {}} + showLegacyExportTooltip={false} onDismissError={() => {}} {...props} /> diff --git a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx b/packages/compass-schema/src/components/schema-toolbar.tsx similarity index 71% rename from packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx rename to packages/compass-schema/src/components/schema-toolbar.tsx index d247a831ba4..0fca62f0ef2 100644 --- a/packages/compass-schema/src/components/schema-toolbar/schema-toolbar.tsx +++ b/packages/compass-schema/src/components/schema-toolbar.tsx @@ -1,4 +1,5 @@ import React, { useMemo } from 'react'; +import { connect } from 'react-redux'; import { Banner, BannerVariant, @@ -7,16 +8,22 @@ import { ErrorSummary, Icon, Link, + Tooltip, WarningSummary, css, spacing, } from '@mongodb-js/compass-components'; import { usePreference } from 'compass-preferences-model/provider'; -import type { AnalysisState } from '../../constants/analysis-states'; -import { ANALYSIS_STATE_COMPLETE } from '../../constants/analysis-states'; +import type { AnalysisState } from '../constants/analysis-states'; +import { ANALYSIS_STATE_COMPLETE } from '../constants/analysis-states'; import { QueryBar } from '@mongodb-js/compass-query-bar'; -import { type SchemaAnalysisError } from '../../stores/schema-analysis-reducer'; -import { DISTINCT_FIELDS_ABORT_THRESHOLD } from '../../modules/schema-analysis'; +import { + type SchemaAnalysisError, + analysisErrorDismissed, +} from '../stores/schema-analysis-reducer'; +import { DISTINCT_FIELDS_ABORT_THRESHOLD } from '../modules/schema-analysis'; +import type { RootState } from '../stores/store'; +import { openExportSchema } from '../stores/schema-export-reducer'; const schemaToolbarStyles = css({ display: 'flex', @@ -68,9 +75,11 @@ type SchemaToolbarProps = { onDismissError: () => void; sampleSize: number; schemaResultId: string; + setShowLegacyExportTooltip: (show: boolean) => void; + showLegacyExportTooltip: boolean; }; -const SchemaToolbar: React.FunctionComponent = ({ +export const SchemaToolbar: React.FunctionComponent = ({ analysisState, error, onDismissError, @@ -80,6 +89,8 @@ const SchemaToolbar: React.FunctionComponent = ({ onResetClicked, sampleSize, schemaResultId, + setShowLegacyExportTooltip, + showLegacyExportTooltip, }) => { const documentsNoun = useMemo( () => (sampleSize === 1 ? 'document' : 'documents'), @@ -103,15 +114,26 @@ const SchemaToolbar: React.FunctionComponent = ({
{enableExportSchema && ANALYSIS_STATE_COMPLETE && (
- + } > - Export Schema - + Next time, export the schema directly from Compass' Schema + tab. +
)}
= ({ ); }; -export { SchemaToolbar }; +export default connect( + (state: RootState) => ({ + analysisState: state.schemaAnalysis.analysisState, + error: state.schemaAnalysis.error, + sampleSize: state.schemaAnalysis.schema?.count ?? 0, + schemaResultId: state.schemaAnalysis.resultId ?? '', + }), + { + onExportSchemaClicked: openExportSchema, + onDismissError: analysisErrorDismissed, + } +)(SchemaToolbar); diff --git a/packages/compass-schema/src/stores/schema-export-reducer.ts b/packages/compass-schema/src/stores/schema-export-reducer.ts index d438ff6d515..de0fed74e23 100644 --- a/packages/compass-schema/src/stores/schema-export-reducer.ts +++ b/packages/compass-schema/src/stores/schema-export-reducer.ts @@ -23,8 +23,8 @@ export type SchemaFormat = export type ExportStatus = 'inprogress' | 'complete' | 'error'; export type SchemaExportState = { isOpen: boolean; - isLegacyBannerOpen: boolean; - legacyBannerChoice?: 'legacy' | 'export'; + isLegacyModalOpen: boolean; + legacyModalChoice?: 'legacy' | 'export'; exportedSchema?: string; exportFormat: SchemaFormat; errorMessage?: string; @@ -40,16 +40,16 @@ const getInitialState = (): SchemaExportState => ({ exportStatus: 'inprogress', exportedSchema: undefined, isOpen: false, - isLegacyBannerOpen: false, - legacyBannerChoice: undefined, + isLegacyModalOpen: false, + legacyModalChoice: undefined, }); export const enum SchemaExportActions { openExportSchema = 'schema-service/schema-export/openExportSchema', closeExportSchema = 'schema-service/schema-export/closeExportSchema', - openLegacyBanner = 'schema-service/schema-export/openLegacyBanner', - closeLegacyBanner = 'schema-service/schema-export/closeLegacyBanner', - setLegacyBannerChoice = 'schema-service/schema-export/setLegacyBannerChoice', + openLegacyModal = 'schema-service/schema-export/openLegacyModal', + closeLegacyModal = 'schema-service/schema-export/closeLegacyModal', + setLegacyModalChoice = 'schema-service/schema-export/setLegacyModalChoice', changeExportSchemaStatus = 'schema-service/schema-export/changeExportSchemaStatus', changeExportSchemaFormatStarted = 'schema-service/schema-export/changeExportSchemaFormatStarted', changeExportSchemaFormatComplete = 'schema-service/schema-export/changeExportSchemaFormatComplete', @@ -329,7 +329,9 @@ export const changeExportSchemaFormat = ( try { const schemaAccessor = schemaAccessorRef.current; if (!schemaAccessor) { - throw new Error('No schema analysis available'); + throw new Error( + "No schema analysis available. Please analyze the collection's schema before exporting." + ); } exportedSchema = await getSchemaByFormat({ @@ -420,38 +422,35 @@ export const schemaExportReducer: Reducer = ( } if ( - isAction( - action, - SchemaExportActions.openLegacyBanner - ) + isAction(action, SchemaExportActions.openLegacyModal) ) { return { ...state, - isLegacyBannerOpen: true, + isLegacyModalOpen: true, }; } if ( - isAction( + isAction( action, - SchemaExportActions.closeLegacyBanner + SchemaExportActions.closeLegacyModal ) ) { return { ...state, - isLegacyBannerOpen: false, + isLegacyModalOpen: false, }; } if ( - isAction( + isAction( action, - SchemaExportActions.setLegacyBannerChoice + SchemaExportActions.setLegacyModalChoice ) ) { return { ...state, - legacyBannerChoice: action.choice, + legacyModalChoice: action.choice, }; } @@ -512,19 +511,19 @@ export const schemaExportReducer: Reducer = ( return state; }; -// TODO clean out when phase out is confirmed COMPASS-8692 -export type openLegacyBannerAction = { - type: SchemaExportActions.openLegacyBanner; +// TODO(COMPASS-8692): clean out when phase out is confirmed. +export type openLegacyModalAction = { + type: SchemaExportActions.openLegacyModal; }; -export const openLegacyBanner = (): SchemaThunkAction => { +export const openLegacyModal = (): SchemaThunkAction => { return (dispatch, getState) => { - const choiceInState = getState().schemaExport.legacyBannerChoice; + const choiceInState = getState().schemaExport.legacyModalChoice; const savedChoice = choiceInState || localStorage.getItem(localStorageId); if (savedChoice) { if (savedChoice !== choiceInState) { dispatch({ - type: SchemaExportActions.setLegacyBannerChoice, + type: SchemaExportActions.setLegacyModalChoice, choice: savedChoice, }); } @@ -537,24 +536,24 @@ export const openLegacyBanner = (): SchemaThunkAction => { return; } } - dispatch({ type: SchemaExportActions.openLegacyBanner }); + dispatch({ type: SchemaExportActions.openLegacyModal }); }; }; -export type closeLegacyBannerAction = { - type: SchemaExportActions.closeLegacyBanner; +export type closeLegacyModalAction = { + type: SchemaExportActions.closeLegacyModal; }; -export type setLegacyBannerChoiceAction = { - type: SchemaExportActions.setLegacyBannerChoice; +export type setLegacyModalChoiceAction = { + type: SchemaExportActions.setLegacyModalChoice; choice: 'legacy' | 'export'; }; -const localStorageId = 'schemaExportLegacyBannerChoice'; +const localStorageId = 'schemaExportLegacyModalChoice'; export const switchToSchemaExport = (): SchemaThunkAction => { return (dispatch) => { - dispatch({ type: SchemaExportActions.closeLegacyBanner }); + dispatch({ type: SchemaExportActions.closeLegacyModal }); dispatch(openExportSchema()); }; }; @@ -576,7 +575,7 @@ export const confirmedExportLegacySchemaToClipboard = track, connectionInfoRef, }); - dispatch({ type: SchemaExportActions.closeLegacyBanner }); + dispatch({ type: SchemaExportActions.closeLegacyModal }); openToast( 'share-schema', hasSchema @@ -596,11 +595,11 @@ export const confirmedExportLegacySchemaToClipboard = }; }; -export const stopShowingLegacyBanner = ( +export const stopShowingLegacyModal = ( choice: 'legacy' | 'export' ): SchemaThunkAction => { return (dispatch) => { localStorage.setItem(localStorageId, choice); - dispatch({ type: SchemaExportActions.setLegacyBannerChoice, choice }); + dispatch({ type: SchemaExportActions.setLegacyModalChoice, choice }); }; }; diff --git a/packages/compass-schema/src/stores/store.ts b/packages/compass-schema/src/stores/store.ts index 076ddab4d2c..09d8054af0a 100644 --- a/packages/compass-schema/src/stores/store.ts +++ b/packages/compass-schema/src/stores/store.ts @@ -25,7 +25,7 @@ import { import { cancelExportSchema, confirmedExportLegacySchemaToClipboard, - openLegacyBanner, + openLegacyModal, schemaExportReducer, } from './schema-export-reducer'; import type { InternalLayer } from '../modules/geo'; @@ -85,7 +85,7 @@ export function activateSchemaPlugin( on(services.localAppRegistry, 'menu-share-schema-json', () => { const { enableExportSchema } = services.preferences.getPreferences(); if (enableExportSchema) { - store.dispatch(openLegacyBanner()); + store.dispatch(openLegacyModal()); return; } store.dispatch(confirmedExportLegacySchemaToClipboard());