import { Pagination, PaginationProps } from '@/components/Pagination'; import { FunctionField } from '@/components/ra-fields'; import { Datagrid, ListToolbar, ListToolbarProps } from '@/components/ra-lists'; import { DatagridProps } from '@/components/ra-lists/Datagrid/Datagrid'; import { useUuid } from '@/hooks'; import { CheckBox, CheckBoxOutlineBlankOutlined, Error } from '@mui/icons-material'; import { Button, Chip, Dialog, DialogActions, DialogContent, DialogContentProps, DialogProps, Stack } from '@mui/material'; import _ from 'lodash'; import { Identifier, ListBase, ListControllerProps, RaRecord, RecordRepresentation, WithListContext, useGetMany, useGetRecordRepresentation, useTranslate } from 'ra-core'; import { PropsWithChildren, useCallback } from 'react'; type RecordRepresentationType = (record: RaRecord) => string; type EntityFieldProps = { id: Identifier; onClick?: (record: RaRecord) => void; onDelete?: (record: RaRecord) => void; recordRepresentation?: RecordRepresentationType; resource: string; }; type EntityLookupDialogProps = PropsWithChildren<{ onCancel: () => void; onConfirm: (selectedIds: Identifier[]) => void; multiple: boolean; slotProps?: { dataGrid?: DatagridProps; dialog?: DialogProps; dialogContent?: DialogContentProps; list?: ListControllerProps; listToolbar?: Pick; pagination?: PaginationProps; }; }>; function EntityField(props: EntityFieldProps): JSX.Element | null { const { id, onClick: onClickCb, onDelete: onDeleteCb, recordRepresentation, resource } = props; const fallbackRecordRepresentation = useGetRecordRepresentation(resource); const { data, isLoading, error } = useGetMany(resource, { ids: [id] }); const record = _.find(data ?? [], { id }); const canDelete = !_.isNil(record) && _.isFunction(onDeleteCb); const onDelete = useCallback(() => { if (canDelete) { onDeleteCb(record); } }, [onDeleteCb, record, canDelete]); const canClick = !_.isNil(record) && _.isFunction(onClickCb); const onClick = useCallback(() => { if (canClick) { onClickCb(record); } }, [onClickCb, record, canClick]); if (isLoading) { return null; } else if (error || _.isNil(record)) { return ; } else { const label = _.isFunction(recordRepresentation) ? recordRepresentation(record) : fallbackRecordRepresentation(record); return ; } } function EntityLookupDialog(props: EntityLookupDialogProps): JSX.Element { const uuid = useUuid(); const t = useTranslate(); const { children, multiple, onCancel, onConfirm, slotProps } = props; const { dialogContent: dialogContentProps = {}, listToolbar: listToolbarProps = {}, pagination: paginationProps } = slotProps ?? {}; const listProps = _.chain(slotProps?.list) .defaults({ disableSyncWithLocation: true, emptyWhileLoading: true, exporter: false }) .value(); const hasListToolbar = !_.isNil(listToolbarProps.filters); const dialogProps = _.chain(slotProps?.dialog) .defaults({ disableEscapeKeyDown: true, fullWidth: true, keepMounted: false, open: false }) .value(); const dataGridProps = _.chain(slotProps?.dataGrid) .defaults({}) .extend({ bulkActionButtons: false, rowClick: 'toggleSelection' }) .value(); const updateSelection = useCallback( (selectedIds: Identifier[], id: Identifier): Identifier[] => { if (multiple) { return _.includes(selectedIds, id) ? _.without(selectedIds, id) : _.concat(selectedIds, id); } else { return _.includes(selectedIds, id) ? [] : [id]; } }, [multiple] ); return ( { return ( { onUnselectItems(); onCancel(); }} > {hasListToolbar ? : null} onSelect(updateSelection(selectedIds, id))}> _.includes(selectedIds, record.id) ? : } /> {children ?? ( } /> )} ); }} /> ); } export { EntityField, EntityLookupDialog }; export type { EntityFieldProps, EntityLookupDialogProps, RecordRepresentationType };