import { FileField } from '@/components/ra-fields'; import { LabeledInput } from '@/components/ra-inputs/LabeledInput'; import { styled } from '@mui/material/styles'; import { get } from 'lodash'; import React, { useMemo } from 'react'; import { FileInput as RaFileInput, FileInputProps as RaFileInputProps, useRecordContext } from 'react-admin'; import { useWatch } from 'react-hook-form'; const StyledFileInput = styled(RaFileInput, { slot: 'root' })(({ theme }) => ({ '& .previews': {}, '& .previews>div': { marginTop: theme.spacing(1), padding: theme.spacing(1.5), border: `1px solid ${theme.palette.divider}`, borderRadius: theme.shape.borderRadius, '& button': { float: 'right', placeItems: 'flex-end', verticalAlign: 'middle' }, '&:hover': { backgroundColor: theme.palette.action.hover }, '& .MuiLink-root': { fontSize: theme.typography.body1.fontSize } } })); /** * FileInput is designed to be used as single input. It does not support multiple files and * can be used only for base64 encoded files using applica framework. * * @example * // If you hav an object class with @File annotation, you can map it to a FileInput: * ... * * * The component will handle create and delete operations related to the source field associated * in conjuction with Applica Framework backend API services. * */ function FileInput({ children = , title, ...props }: FileInputProps): JSX.Element { const file = useWatch({ name: props.source }); const record = useRecordContext(props); const { source } = props; // Base64 files are persisted with a simple string that contains the temporary filename. // Applica Framework add a suffix to the temporary filename that is the original filename. // With a little trick we try (because we are not sure that this is true) to get the original filename. const filename = useMemo(() => { if (file && file?.title) { return file?.title; } const filename = get(record, source); if (filename) { const parts = filename.split('__'); return parts.length > 0 ? parts[parts.length - 1] : filename; } return filename; }, [record, source, file]); return ( // @ts-ignore {/* @ts-ignore */} { /** @ts-ignore */ React.cloneElement(children, { // @ts-ignore ...children.props, title: title || source, source, record: { ...record, [source]: file?.title || get(record, source), [`_${source}`]: file?.src || get(record, `_${source}`), [title || source]: filename } }) } ); } type FileInputProps = { source: string; title?: string; children?: React.ReactNode; } & RaFileInputProps; export { FileInput }; export type { FileInputProps };