diff --git a/packages/react-material-ui/src/components/submodules/DrawerForm/index.tsx b/packages/react-material-ui/src/components/submodules/DrawerForm/index.tsx index db862d7e..a7ee8abd 100644 --- a/packages/react-material-ui/src/components/submodules/DrawerForm/index.tsx +++ b/packages/react-material-ui/src/components/submodules/DrawerForm/index.tsx @@ -1,8 +1,5 @@ -import React, { useState, PropsWithChildren, ReactNode } from 'react'; - -import type { RJSFSchema, UiSchema, CustomValidator } from '@rjsf/utils'; -import type { IChangeEvent, FormProps } from '@rjsf/core'; - +import React, { useState } from 'react'; +import type { IChangeEvent } from '@rjsf/core'; import { Box, Drawer, @@ -11,59 +8,16 @@ import { IconButton, Typography, } from '@mui/material'; -import ChevronLeft from '@mui/icons-material/ChevronLeft'; -import ChevronRight from '@mui/icons-material/ChevronRight'; import CloseIcon from '@mui/icons-material/Close'; import useDataProvider, { useQuery } from '@concepta/react-data-provider'; import validator from '@rjsf/validator-ajv6'; -import { SchemaForm, SchemaFormProps } from '../../../components/SchemaForm'; - +import { SchemaForm } from '../../../components/SchemaForm'; import { CustomTextFieldWidget } from '../../../styles/CustomWidgets'; +import { FormSubmoduleProps } from '../types/Form'; +import TableRowControls from '../TableRowControls'; -type Action = 'creation' | 'edit' | 'details' | null; - -type DrawerFormSubmoduleProps = PropsWithChildren< - Omit< - SchemaFormProps, - | 'schema' - | 'uiSchema' - | 'validator' - | 'onSubmit' - | 'noHtml5Validate' - | 'showErrorList' - | 'formData' - | 'readonly' - | 'customValidate' - > -> & { - queryResource: string; - title?: string; - formSchema?: RJSFSchema; - viewMode?: Action | null; - formUiSchema?: UiSchema; - formData?: Record | null; - submitButtonTitle?: string; - cancelButtonTitle?: string; - hideCancelButton?: boolean; - customFooterContent?: ReactNode; - onClose?: () => void; - customValidate?: CustomValidator; - widgets?: FormProps['widgets']; - onSuccess?: (data: unknown) => void; - onError?: (error: unknown) => void; - onDeleteSuccess?: (data: unknown) => void; - onDeleteError?: (error: unknown) => void; - onPrevious?: (data: unknown) => void; - onNext?: (data: unknown) => void; - isLoading?: boolean; - viewIndex?: number; - rowsPerPage?: number; - currentPage?: number; - pageCount?: number; -}; - -const DrawerFormSubmodule = (props: DrawerFormSubmoduleProps) => { +const DrawerFormSubmodule = (props: FormSubmoduleProps) => { const { queryResource, viewMode, @@ -87,11 +41,12 @@ const DrawerFormSubmodule = (props: DrawerFormSubmoduleProps) => { rowsPerPage, currentPage, pageCount, + isVisible, ...otherProps } = props; const [fieldValues, setFieldValues] = - useState(null); + useState(null); const { post, patch, del } = useDataProvider(); @@ -155,7 +110,7 @@ const DrawerFormSubmodule = (props: DrawerFormSubmoduleProps) => { }; return ( - + { } > {viewMode !== 'creation' && ( - - onPrevious(formData)} - disabled={isLoading || (currentPage === 1 && viewIndex === 1)} - > - - - - {isLoading ? '' : `Row ${viewIndex}/${rowsPerPage}`} - - onNext(formData)} - disabled={ - isLoading || - (currentPage === pageCount && viewIndex === rowsPerPage) - } - > - - - + onPrevious(formData)} + onNext={() => onNext(formData)} + /> )} {props.customFooterContent} diff --git a/packages/react-material-ui/src/components/submodules/Filter/index.tsx b/packages/react-material-ui/src/components/submodules/Filter/index.tsx index 89c6e847..1f102059 100644 --- a/packages/react-material-ui/src/components/submodules/Filter/index.tsx +++ b/packages/react-material-ui/src/components/submodules/Filter/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, ReactNode } from 'react'; import { Filter, FilterVariant, @@ -42,6 +42,7 @@ export type FilterCallback = (filter: FilterValues) => void; type Props = { orderableListCacheKey?: string; cacheApiPath?: string; + complementaryActions?: ReactNode; }; const FilterSubmodule = (props: Props) => { diff --git a/packages/react-material-ui/src/components/submodules/ModalForm/index.tsx b/packages/react-material-ui/src/components/submodules/ModalForm/index.tsx index 4224608a..1ebe9d60 100644 --- a/packages/react-material-ui/src/components/submodules/ModalForm/index.tsx +++ b/packages/react-material-ui/src/components/submodules/ModalForm/index.tsx @@ -1,7 +1,5 @@ -import React, { PropsWithChildren, ReactNode } from 'react'; - -import type { RJSFSchema, UiSchema, CustomValidator } from '@rjsf/utils'; -import type { IChangeEvent, FormProps } from '@rjsf/core'; +import React from 'react'; +import { IChangeEvent } from '@rjsf/core'; import { Box, Button, @@ -10,60 +8,17 @@ import { DialogTitle, DialogContent, IconButton, - Typography, } from '@mui/material'; -import ChevronLeft from '@mui/icons-material/ChevronLeft'; -import ChevronRight from '@mui/icons-material/ChevronRight'; import CloseIcon from '@mui/icons-material/Close'; import useDataProvider, { useQuery } from '@concepta/react-data-provider'; import validator from '@rjsf/validator-ajv6'; -import { SchemaForm, SchemaFormProps } from '../../../components/SchemaForm'; +import { SchemaForm } from '../../../components/SchemaForm'; import { CustomTextFieldWidget } from '../../../styles/CustomWidgets'; +import { FormSubmoduleProps } from '../types/Form'; +import TableRowControls from '../TableRowControls'; -type Action = 'creation' | 'edit' | 'details' | null; - -type ModalFormSubmoduleProps = PropsWithChildren< - Omit< - SchemaFormProps, - | 'schema' - | 'uiSchema' - | 'validator' - | 'onSubmit' - | 'noHtml5Validate' - | 'showErrorList' - | 'formData' - | 'readonly' - | 'customValidate' - > -> & { - title?: string; - queryResource: string; - formSchema?: RJSFSchema; - viewMode?: Action | null; - formUiSchema?: UiSchema; - formData?: Record | null; - submitButtonTitle?: string; - cancelButtonTitle?: string; - hideCancelButton?: boolean; - customFooterContent?: ReactNode; - onClose?: () => void; - customValidate?: CustomValidator; - widgets?: FormProps['widgets']; - onSuccess?: (data: unknown) => void; - onError?: (error: unknown) => void; - onDeleteSuccess?: (data: unknown) => void; - onDeleteError?: (error: unknown) => void; - onPrevious?: (data: unknown) => void; - onNext?: (data: unknown) => void; - isLoading?: boolean; - viewIndex?: number; - rowsPerPage?: number; - currentPage?: number; - pageCount?: number; -}; - -const ModalFormSubmodule = (props: ModalFormSubmoduleProps) => { +const ModalFormSubmodule = (props: FormSubmoduleProps) => { const { queryResource, viewMode, @@ -87,6 +42,7 @@ const ModalFormSubmodule = (props: ModalFormSubmoduleProps) => { rowsPerPage, currentPage, pageCount, + isVisible, ...otherProps } = props; @@ -150,7 +106,7 @@ const ModalFormSubmodule = (props: ModalFormSubmoduleProps) => { }; return ( - + {viewMode === 'creation' ? 'Add Data' @@ -189,92 +145,82 @@ const ModalFormSubmodule = (props: ModalFormSubmoduleProps) => { readonly={viewMode === 'details'} {...otherProps} > - <> - {children} + {children} + + {viewMode !== 'creation' && ( + onPrevious(formData)} + onNext={() => onNext(formData)} + /> + )} - {viewMode !== 'creation' && ( - - onPrevious(formData)} - disabled={ - isLoading || (currentPage === 1 && viewIndex === 1) - } - > - - - - {isLoading ? '' : `Row ${viewIndex}/${rowsPerPage}`} - - onNext(formData)} - disabled={ - isLoading || - (currentPage === pageCount && viewIndex === rowsPerPage) - } - > - - - + {props.customFooterContent} + {viewMode === 'creation' && !props.hideCancelButton && ( + + )} + {viewMode === 'edit' && !props.hideCancelButton && ( + + )} + {viewMode === 'details' && !props.hideCancelButton && ( + + )} + {viewMode !== 'details' && ( + )} - - {props.customFooterContent} - {viewMode === 'creation' && !props.hideCancelButton && ( - - )} - {viewMode === 'edit' && !props.hideCancelButton && ( - - )} - {viewMode === 'details' && !props.hideCancelButton && ( - - )} - {viewMode !== 'details' && ( - - )} - - + diff --git a/packages/react-material-ui/src/components/submodules/Table/index.tsx b/packages/react-material-ui/src/components/submodules/Table/index.tsx index 66ca9d2a..2324eede 100644 --- a/packages/react-material-ui/src/components/submodules/Table/index.tsx +++ b/packages/react-material-ui/src/components/submodules/Table/index.tsx @@ -278,45 +278,41 @@ const TableSubmodule = (props: TableSubmoduleProps) => { + {props.reordable !== false && ( + + )} + + {props.additionalFilterRowContent} + {!props.hideAddButton && ( + + )} + + + } /> )} - - - {props.reordable !== false && ( - - )} - - {props.additionalFilterRowContent} - {!props.hideAddButton && ( - - )} - - diff --git a/packages/react-material-ui/src/components/submodules/TableRowControls/index.tsx b/packages/react-material-ui/src/components/submodules/TableRowControls/index.tsx new file mode 100644 index 00000000..d06e905b --- /dev/null +++ b/packages/react-material-ui/src/components/submodules/TableRowControls/index.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { Box, IconButton, Typography, Skeleton } from '@mui/material'; +import ChevronLeft from '@mui/icons-material/ChevronLeft'; +import ChevronRight from '@mui/icons-material/ChevronRight'; + +type Props = { + isLoading: boolean; + currentIndex: number; + rowsPerPage: number; + isPreviousDisabled: boolean; + isNextDisabled: boolean; + onPrevious: () => void; + onNext: () => void; +}; + +const TableRowControls = (props: Props) => { + const { + isLoading, + currentIndex, + rowsPerPage, + isPreviousDisabled, + isNextDisabled, + onPrevious, + onNext, + } = props; + + return ( + + + + + + {isLoading ? ( + + ) : ( + `Row ${currentIndex}/${rowsPerPage}` + )} + + + + + + ); +}; + +export default TableRowControls; diff --git a/packages/react-material-ui/src/components/submodules/types/Form.ts b/packages/react-material-ui/src/components/submodules/types/Form.ts new file mode 100644 index 00000000..90f6a148 --- /dev/null +++ b/packages/react-material-ui/src/components/submodules/types/Form.ts @@ -0,0 +1,48 @@ +import { PropsWithChildren, ReactNode } from 'react'; +import { RJSFSchema, UiSchema, CustomValidator } from '@rjsf/utils'; +import { FormProps } from '@rjsf/core'; + +import { SchemaFormProps } from '../../../components/SchemaForm'; + +export type Action = 'creation' | 'edit' | 'details' | null; + +export type FormSubmoduleProps = PropsWithChildren< + Omit< + SchemaFormProps, + | 'schema' + | 'uiSchema' + | 'validator' + | 'onSubmit' + | 'noHtml5Validate' + | 'showErrorList' + | 'formData' + | 'readonly' + | 'customValidate' + > +> & { + isVisible: boolean; + queryResource: string; + title?: string; + formSchema?: RJSFSchema; + viewMode?: Action | null; + formUiSchema?: UiSchema; + formData?: Record | null; + submitButtonTitle?: string; + cancelButtonTitle?: string; + hideCancelButton?: boolean; + customFooterContent?: ReactNode; + onClose?: () => void; + customValidate?: CustomValidator; + widgets?: FormProps['widgets']; + onSuccess?: (data: unknown) => void; + onError?: (error: unknown) => void; + onDeleteSuccess?: (data: unknown) => void; + onDeleteError?: (error: unknown) => void; + onPrevious?: (data: unknown) => void; + onNext?: (data: unknown) => void; + isLoading?: boolean; + viewIndex?: number; + rowsPerPage?: number; + currentPage?: number; + pageCount?: number; +}; diff --git a/packages/react-material-ui/src/modules/crud/index.tsx b/packages/react-material-ui/src/modules/crud/index.tsx index bf098038..e7b59d95 100644 --- a/packages/react-material-ui/src/modules/crud/index.tsx +++ b/packages/react-material-ui/src/modules/crud/index.tsx @@ -89,6 +89,7 @@ const CrudModule = (props: ModuleProps) => { const [drawerViewMode, setDrawerViewMode] = useState(null); const [selectedRow, setSelectedRow] = useState(null); const [currentViewIndex, setCurrentViewIndex] = useState(0); + const [isFormVisible, setFormVisible] = useState(false); const useTableReturn = useTable(props.resource, { callbacks: { @@ -224,11 +225,13 @@ const CrudModule = (props: ModuleProps) => { setSelectedRow(payload.row); setDrawerViewMode(payload.action); setCurrentViewIndex(payload.index); + setFormVisible(true); }} onAddNew={() => { setSelectedRow(null); setDrawerViewMode('creation'); setCurrentViewIndex(0); + setFormVisible(true); }} hideAddButton={!props.createFormProps} hideEditButton={!props.editFormProps || props.hideEditButton} @@ -250,37 +253,26 @@ const CrudModule = (props: ModuleProps) => { {enhancedFormProps && ( { useTableReturn.refresh(); - - setSelectedRow(null); - setDrawerViewMode(null); - setCurrentViewIndex(0); - + setFormVisible(false); if (formOnSuccess) { formOnSuccess(data); } }} onDeleteSuccess={(data) => { useTableReturn.refresh(); - - setSelectedRow(null); - setDrawerViewMode(null); - setCurrentViewIndex(0); - + setFormVisible(false); if (formOnDeleteSuccess) { formOnDeleteSuccess(data); } }} - onClose={() => { - setSelectedRow(null); - setDrawerViewMode(null); - setCurrentViewIndex(0); - }} + onClose={() => setFormVisible(false)} onPrevious={() => changeCurrentFormData('previous')} onNext={() => changeCurrentFormData('next')} isLoading={isPending}