import { Modal, Steps, Typography } from 'antd'; import { isEqual } from 'lodash'; import React, { useEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import { CreateScheduleStep } from '@app/ingestV2/source/builder/CreateScheduleStep'; import { DefineRecipeStep } from '@app/ingestV2/source/builder/DefineRecipeStep'; import { NameSourceStep } from '@app/ingestV2/source/builder/NameSourceStep'; import { SelectTemplateStep } from '@app/ingestV2/source/builder/SelectTemplateStep'; import sourcesJson from '@app/ingestV2/source/builder/sources.json'; import { SourceBuilderState, StepProps } from '@app/ingestV2/source/builder/types'; const StyledModal = styled(Modal)` && .ant-modal-content { border-radius: 16px; overflow: hidden; min-width: 400px; } `; const TitleContainer = styled.div` display: flex; justify-content: space-between; border-radius: 12px; `; const StepsContainer = styled.div` margin-right: 20px; margin-left: 20px; margin-bottom: 40px; `; /** * Mapping from the step type to the title for the step */ export enum IngestionSourceBuilderStepTitles { SELECT_TEMPLATE = 'Choose Data Source', DEFINE_RECIPE = 'Configure Connection', CREATE_SCHEDULE = 'Sync Schedule', NAME_SOURCE = 'Finish up', } /** * Mapping from the step type to the component implementing that step. */ export const IngestionSourceBuilderStepComponent = { SELECT_TEMPLATE: SelectTemplateStep, DEFINE_RECIPE: DefineRecipeStep, CREATE_SCHEDULE: CreateScheduleStep, NAME_SOURCE: NameSourceStep, }; /** * Steps of the Ingestion Source Builder flow. */ export enum IngestionSourceBuilderStep { SELECT_TEMPLATE = 'SELECT_TEMPLATE', DEFINE_RECIPE = 'DEFINE_RECIPE', CREATE_SCHEDULE = 'CREATE_SCHEDULE', NAME_SOURCE = 'NAME_SOURCE', } const modalBodyStyle = { padding: '16px 24px 16px 24px', backgroundColor: '#F6F6F6' }; type Props = { initialState?: SourceBuilderState; open: boolean; onSubmit?: (input: SourceBuilderState, resetState: () => void, shouldRun?: boolean) => void; onCancel?: () => void; }; export const IngestionSourceBuilderModal = ({ initialState, open, onSubmit, onCancel }: Props) => { const isEditing = initialState !== undefined; const titleText = isEditing ? 'Edit Data Source' : 'Connect Data Source'; const initialStep = isEditing ? IngestionSourceBuilderStep.DEFINE_RECIPE : IngestionSourceBuilderStep.SELECT_TEMPLATE; const [stepStack, setStepStack] = useState([initialStep]); const [ingestionBuilderState, setIngestionBuilderState] = useState({ schedule: { interval: '0 0 * * *', }, }); const ingestionSources = JSON.parse(JSON.stringify(sourcesJson)); // TODO: replace with call to server once we have access to dynamic list of sources // Reset the ingestion builder modal state when the modal is re-opened. const prevInitialState = useRef(initialState); useEffect(() => { if (!isEqual(prevInitialState.current, initialState)) { setIngestionBuilderState(initialState || {}); } prevInitialState.current = initialState; }, [initialState]); // Reset the step stack to the initial step when the modal is re-opened. useEffect(() => setStepStack([initialStep]), [initialStep]); const goTo = (step: IngestionSourceBuilderStep) => { setStepStack([...stepStack, step]); }; const prev = () => { setStepStack(stepStack.slice(0, -1)); }; const cancel = () => { onCancel?.(); }; const submit = (shouldRun?: boolean) => { onSubmit?.( ingestionBuilderState, () => { setStepStack([initialStep]); setIngestionBuilderState({}); }, shouldRun, ); }; const currentStep = stepStack[stepStack.length - 1]; const currentStepIndex = Object.values(IngestionSourceBuilderStep) .map((value, index) => ({ value, index, })) .filter((obj) => obj.value === currentStep)[0].index; const StepComponent: React.FC = IngestionSourceBuilderStepComponent[currentStep]; return ( {titleText} } style={{ top: 40 }} bodyStyle={modalBodyStyle} open={open} onCancel={onCancel} > {currentStepIndex > 0 ? ( {Object.keys(IngestionSourceBuilderStep).map((item) => ( ))} ) : null} 1 ? prev : undefined} submit={submit} cancel={cancel} ingestionSources={ingestionSources} /> ); };