import { find } from 'lodash' import classNames from 'classnames' import React, { useCallback, useEffect, useState } from 'react' import { arrayMove } from 'react-sortable-hoc' import { useAsyncEffect } from 'use-async-effect' import { SortableContainer, SortableElement } from 'react-sortable-hoc' import { SchemaFeedback, ISchemaFeedbackProps } from './SchemaFeedback' import { SchemaPreview } from './SchemaPreview' import { SchemaField } from './SchemaField' import * as helpers from '../helpers' import { IDict } from '../common' export interface ISchemaProps { source?: string | File schema: IDict | File onSave: any oldIndex?: number newIndex?: number onSchemaChange?: (schema: any, error: any) => void disablePreview: boolean disableSave?: boolean } export function Schema(props: ISchemaProps) { const [tab, setTab] = useState('edit' as 'edit' | 'preview') const [error, setError] = useState(null as null | Error) const [loading, setLoading] = useState(false) const [columns, setColumns] = useState([] as IDict[]) const [metadata, setMetadata] = useState({} as IDict) const [feedback] = useState({} as ISchemaFeedbackProps['feedback']) // Mount useAsyncEffect(async () => { try { setLoading(false) const { columns, metadata } = await helpers.importSchema(props.source, props.schema) setLoading(false) setColumns(columns) setMetadata(metadata) } catch (error) { // @ts-ignore setError(error) setLoading(false) } }, []) const memoizedExportSchema = useCallback( () => helpers.exportSchema(columns, metadata), [columns, metadata] ) useEffect(() => { if (props.onSchemaChange) { const schema = memoizedExportSchema() props.onSchemaChange(schema, error) } }, [columns, metadata, error]) // Save const saveSchema = () => { if (props.onSave) { const schema = memoizedExportSchema() props.onSave(schema, error) } } // Feedback Reset const resetFeedback = () => {} // Add Field const addField = () => { setColumns([...columns, helpers.createColumn(columns.length)]) } // Remove Field const removeField = (id: number): void => { const newColumns = columns.filter((column) => column.id !== id) setColumns([...newColumns]) } // Update Field const updateField = (id: number, name: string, value: any): void => { const column = find(columns, (column) => column.id === id) if (column) { column.field[name] = value setColumns([...columns]) } } // Move Field const moveField = (props: { oldIndex: number; newIndex: number }) => { setColumns([...arrayMove(columns, props.oldIndex, props.newIndex)]) } const showTabNumber = !props.disablePreview && !props.disableSave return (
{/* Tab navigation */}
{/* Feedback */} {/* Tab contents */} {!loading && !error && (
{/* Edit */} {tab === 'edit' && (
{/* List fields */} {/* Add field */}
)} {/* Preview */} {tab === 'preview' && (
)}
)}
) } // Internal const SortableFields = SortableContainer( (props: { columns: IDict[]; metadata: IDict; removeField: any; updateField: any }) => ( ) ) const SortableField = SortableElement( (props: { column: IDict; metadata: IDict; removeField: any; updateField: any }) => (
  • ) )