import { Box, Button, CustomModalLayout, Heading, ModalMobileLayout, Text, } from '@wix/design-system'; import { getImportModalStepProps } from './getImportModalStepProps'; import React, { Suspense, lazy, useEffect, useMemo, useState } from 'react'; import { observer } from 'mobx-react-lite'; import { useCreateImport } from '@wix/bex-core'; import { detectFieldType } from '@wix/patterns-fields'; import { ImportButtonModalLayoutProps } from './ImportProps'; import { addEventListener } from '@wix/bex-core/util'; import { useIsMobile } from '../../hooks/useIsMobile'; import { CustomDrawerLayout } from '../CustomDrawerLayout'; import { ImportStepper } from './ImportStepper'; import { MessageActionModal } from '../ActionModal'; import { ModalWrapper } from '../CollectionModal'; import { PatternsFieldsProvider } from '../../providers'; import { useToolbarCollectionContext } from '../ToolbarCollectionContext'; function _ImportButtonModalLayout(props: ImportButtonModalLayoutProps) { const { config, importModalState, renderFieldEditor, ...rest } = props; const isMobile = useIsMobile(); // The config is read live off the table's source, which is in context here (the // consumer builds `config` above the collection provider, so it can't be). Pass // the toolbar's fields source to ImportState, which builds the effective config. const toolbar = useToolbarCollectionContext(); const createImport = useCreateImport({ importInputs: config, fieldsSource: toolbar.collectionFieldsSource?.fieldsSource, // Media-aware detection (image/video/document/audio) lives in // patterns-fields; core defaults to primitive detection without it. // ImportState wires the schema-backed `mergeFields` from the source, so // created columns refresh with no wiring here (CAIRO-4400). detectColumnType: detectFieldType, importModalState, }); const [state] = useState(() => createImport()); // The create/edit-field editor follows the destination and is loaded on demand, // so neither the CMS nor the DataExtension editor is bundled until an import // that can create fields actually opens. A `renderFieldEditor` prop overrides. const isPlatformized = Boolean(config?.destination); const FieldEditor = useMemo( () => lazy(() => isPlatformized ? import('../DataExtension/DataExtensionImportFieldEditor').then( (m) => ({ default: m.DataExtensionImportFieldEditor }), ) : import('./CmsImportFieldEditor').then((m) => ({ default: m.CmsImportFieldEditor, })), ), [isPlatformized], ); const { onRequestClose, children, removeContentPadding, ...customModalLayoutProps } = getImportModalStepProps({ state, isMobile, }); const wrappedChildren = state.currentStep !== 'progress' && state.currentStep !== 'summary' ? ( {children} ) : ( children ); // The configuration step's "new field" helper reads field-type names from the // patterns-fields translations, which require this provider. Only mounted when // field creation is enabled (the only case a "new" mapping can exist), so the // fields container isn't initialized for plain imports. const content = state.canCreateNewField ? ( {wrappedChildren} ) : ( wrappedChildren ); useEffect(() => { if (onRequestClose) { return addEventListener( importModalState.events, 'requestClose', onRequestClose, ); } return undefined; }, [onRequestClose]); useEffect(() => state.init(), []); const t = state.translate; const { modal: discardModal } = state.discardChangesModal; // The main layout + its discard-changes modal differ per device; everything // common (the field editor) is stacked alongside `child` in the single return. let child: React.ReactNode; if (isMobile) { child = ( <> state.discardChangesModal.afterClose()} > {t('cairo.import.discardChanges.title')} } content={ {t('cairo.import.discardChanges.description')} } onCloseButtonClick={() => discardModal.close()} stickyFooter footer={ } /> ); } else { child = ( <> ); } return ( <> {child} {state.canCreateNewField ? ( renderFieldEditor ? ( renderFieldEditor({ state }) ) : ( ) ) : null} ); } export const ImportButtonModalLayout = observer(_ImportButtonModalLayout);