mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Create SelectingTable, improve EditingTable functionality
This commit is contained in:
@@ -31,9 +31,14 @@ export const EditableTable = <T extends Editable<MRT_RowData>, ParentType extend
|
||||
// TODO: Using static index - need to use some id, probably sorting breaks this
|
||||
const rowClicked = (index: number | undefined) => {
|
||||
if (index === undefined) return
|
||||
const museums = [...editData[field]]
|
||||
museums[index].rowState = getNewState(state)
|
||||
setEditData({ ...editData, museums })
|
||||
const items = [...editData[field]]
|
||||
if (items[index].rowState === 'new') {
|
||||
items.splice(index, 1)
|
||||
setEditData({ ...editData, [field]: items })
|
||||
return
|
||||
}
|
||||
items[index].rowState = getNewState(state)
|
||||
setEditData({ ...editData, items })
|
||||
}
|
||||
|
||||
const getIcon = () => {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { MRT_ColumnDef, MRT_RowData } from 'material-react-table'
|
||||
import { EditingModal } from './FormComponents'
|
||||
import { TableView } from '@/components/TableView/TableView'
|
||||
import { useDetailContext } from '../hooks'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
export const SelectingTable = <T extends MRT_RowData, ParentType>({
|
||||
buttonText,
|
||||
data,
|
||||
columns,
|
||||
editingAction,
|
||||
fieldName,
|
||||
idFieldName,
|
||||
}: {
|
||||
buttonText: string
|
||||
data: T[]
|
||||
columns: MRT_ColumnDef<T>[]
|
||||
editingAction?: (object: T) => void
|
||||
fieldName: keyof ParentType
|
||||
idFieldName: keyof T
|
||||
}) => {
|
||||
const { editData, setEditData } = useDetailContext<ParentType>()
|
||||
|
||||
const selectedItems = editData[fieldName] as T[]
|
||||
|
||||
const defaultEditingAction = (newObject: T) => {
|
||||
if (selectedItems.find(item => item[idFieldName] === newObject[idFieldName])) return
|
||||
setEditData({ ...editData, [fieldName]: [...selectedItems, { ...newObject, rowState: 'new' }] })
|
||||
}
|
||||
|
||||
const idSet = useMemo(() => {
|
||||
return new Set(selectedItems.map(item => item[idFieldName] as T))
|
||||
}, [selectedItems, idFieldName])
|
||||
|
||||
const filteredMuseums = useMemo(() => {
|
||||
return data.filter(row => !idSet.has(row[idFieldName]))
|
||||
}, [data, idSet, idFieldName])
|
||||
|
||||
return (
|
||||
<EditingModal buttonText={buttonText}>
|
||||
<TableView<T>
|
||||
data={filteredMuseums}
|
||||
columns={columns}
|
||||
selectorFn={editingAction ?? defaultEditingAction}
|
||||
idFieldName={idFieldName}
|
||||
/>
|
||||
</EditingModal>
|
||||
)
|
||||
}
|
||||
@@ -1,63 +1,19 @@
|
||||
import { Editable, LocalityDetails, Museum } from '@/backendTypes'
|
||||
import { EditableTable } from '@/components/DetailView/common/EditableTable'
|
||||
import { EditingForm } from '@/components/DetailView/common/EditingForm'
|
||||
import { EditingModal, Grouped } from '@/components/DetailView/common/FormComponents'
|
||||
import { Grouped } from '@/components/DetailView/common/FormComponents'
|
||||
import { SelectingTable } from '@/components/DetailView/common/SelectingTable'
|
||||
import { useDetailContext } from '@/components/DetailView/hooks'
|
||||
import { TableView } from '@/components/TableView/TableView'
|
||||
import { useGetAllMuseumsQuery } from '@/redux/museumReducer'
|
||||
import { Box, CircularProgress } from '@mui/material'
|
||||
import { MRT_ColumnDef } from 'material-react-table'
|
||||
import { useState } from 'react'
|
||||
|
||||
const MuseumSelectingTable = () => {
|
||||
const { data, isError } = useGetAllMuseumsQuery()
|
||||
const [selected, setSelected] = useState<string[]>([])
|
||||
if (isError) return 'Error loading museums.'
|
||||
if (!data) return <CircularProgress />
|
||||
|
||||
const selectId = (id: string) => {
|
||||
const index = selected.indexOf(id)
|
||||
if (index < 0) {
|
||||
setSelected([...selected, id])
|
||||
} else {
|
||||
const newSelected = [...selected]
|
||||
newSelected.splice(index, 1)
|
||||
setSelected(newSelected)
|
||||
}
|
||||
}
|
||||
|
||||
const columns: MRT_ColumnDef<Museum>[] = [
|
||||
{
|
||||
accessorKey: 'museum',
|
||||
header: 'Code',
|
||||
},
|
||||
{
|
||||
accessorKey: 'institution',
|
||||
header: 'Museum',
|
||||
},
|
||||
{
|
||||
accessorKey: 'city',
|
||||
header: 'City',
|
||||
},
|
||||
{
|
||||
accessorKey: 'country',
|
||||
header: 'Country',
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<TableView<Museum>
|
||||
data={data}
|
||||
columns={columns}
|
||||
selectorFn={selectId}
|
||||
selectedList={selected}
|
||||
idFieldName="museum"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const MuseumTab = () => {
|
||||
const { editData, mode } = useDetailContext<LocalityDetails>()
|
||||
const { data: museumData, isError } = useGetAllMuseumsQuery()
|
||||
|
||||
if (isError) return 'Error loading museums.'
|
||||
if (!museumData) return <CircularProgress />
|
||||
|
||||
const columns: MRT_ColumnDef<Museum>[] = [
|
||||
{
|
||||
@@ -78,12 +34,6 @@ export const MuseumTab = () => {
|
||||
},
|
||||
]
|
||||
|
||||
const selectingTable = (
|
||||
<EditingModal buttonText="Add existing museum">
|
||||
<MuseumSelectingTable />
|
||||
</EditingModal>
|
||||
)
|
||||
|
||||
const formFields: { name: string; label: string; required?: boolean }[] = [
|
||||
{ name: 'code', label: 'Code', required: true },
|
||||
{ name: 'museum', label: 'Museum', required: true },
|
||||
@@ -94,19 +44,22 @@ export const MuseumTab = () => {
|
||||
{ name: 'country', label: 'Country', required: true },
|
||||
]
|
||||
|
||||
const editingModal = (
|
||||
<EditingForm<Museum, LocalityDetails>
|
||||
buttonText="Add new museum"
|
||||
formFields={formFields}
|
||||
arrayFieldName="museums"
|
||||
/>
|
||||
)
|
||||
|
||||
return (
|
||||
<Grouped title="Museums">
|
||||
{mode === 'edit' && (
|
||||
<Box display="flex" gap={1}>
|
||||
{editingModal} {selectingTable}
|
||||
<EditingForm<Museum, LocalityDetails>
|
||||
buttonText="Add new museum"
|
||||
formFields={formFields}
|
||||
arrayFieldName="museums"
|
||||
/>
|
||||
<SelectingTable<Museum, LocalityDetails>
|
||||
buttonText="Add existing museum"
|
||||
data={museumData}
|
||||
columns={columns}
|
||||
fieldName="museums"
|
||||
idFieldName="museum"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
<EditableTable<Editable<Museum>, LocalityDetails>
|
||||
|
||||
@@ -5,34 +5,29 @@ import { useNavigate } from 'react-router-dom'
|
||||
import ManageSearchIcon from '@mui/icons-material/ManageSearch'
|
||||
import PolicyIcon from '@mui/icons-material/Policy'
|
||||
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'
|
||||
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
|
||||
|
||||
export const ActionComponent = <T extends MRT_RowData>({
|
||||
row,
|
||||
idFieldName,
|
||||
selectorFn,
|
||||
selectedList,
|
||||
checkRowRestriction,
|
||||
url,
|
||||
selectorFn,
|
||||
}: {
|
||||
row: MRT_Row<T>
|
||||
idFieldName: keyof T
|
||||
selectorFn?: (id: string) => void
|
||||
selectedList?: string[]
|
||||
checkRowRestriction: ((row: T) => boolean) | undefined
|
||||
url: string | undefined
|
||||
selectorFn?: (id: T) => void
|
||||
}) => {
|
||||
const navigate = useNavigate()
|
||||
const id = row.original[idFieldName]
|
||||
const currentSelected = selectedList && selectedList.find(sel => sel === id)
|
||||
const getIconToShow = () => {
|
||||
if (currentSelected) return <CheckCircleOutlineIcon color="success" />
|
||||
if (selectorFn) return <AddCircleOutlineIcon />
|
||||
return <ManageSearchIcon />
|
||||
}
|
||||
const onClick = () => {
|
||||
if (selectorFn) {
|
||||
selectorFn(id)
|
||||
selectorFn(row.original)
|
||||
} else {
|
||||
navigate(`/${url}/${id}`)
|
||||
}
|
||||
|
||||
@@ -30,15 +30,13 @@ export const TableView = <T extends MRT_RowData>({
|
||||
idFieldName,
|
||||
checkRowRestriction,
|
||||
selectorFn,
|
||||
selectedList,
|
||||
url,
|
||||
}: {
|
||||
data: T[] | undefined
|
||||
columns: MRT_ColumnDef<T>[]
|
||||
idFieldName: keyof MRT_RowData
|
||||
idFieldName: keyof T
|
||||
checkRowRestriction?: (row: T) => boolean
|
||||
selectorFn?: (id: string) => void
|
||||
selectedList?: string[]
|
||||
selectorFn?: (id: T) => void
|
||||
url?: string
|
||||
}) => {
|
||||
const navigate = useNavigate()
|
||||
@@ -92,14 +90,7 @@ export const TableView = <T extends MRT_RowData>({
|
||||
}}
|
||||
onColumnFiltersChange={setColumnFilters}
|
||||
renderRowActions={({ row }) => (
|
||||
<ActionComponent
|
||||
row={row}
|
||||
idFieldName={idFieldName}
|
||||
selectorFn={selectorFn}
|
||||
selectedList={selectedList}
|
||||
checkRowRestriction={checkRowRestriction}
|
||||
url={url}
|
||||
/>
|
||||
<ActionComponent {...{ selectorFn, url, checkRowRestriction, row, idFieldName }} />
|
||||
)}
|
||||
displayColumnDefOptions={{ 'mrt-row-actions': { size: 50, header: '' } }}
|
||||
enableRowActions
|
||||
|
||||
Reference in New Issue
Block a user