asb_cloud_front/src/components/Table/EditableTable.jsx
Фролов 7a7a4663c5 Remove padding from EditableCell.
Add types into otherColumsParams.
2021-08-30 15:11:21 +05:00

176 lines
5.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Form, Table, Button, Popconfirm } from "antd"
import { EditOutlined, SaveOutlined, PlusOutlined, CloseCircleOutlined, DeleteOutlined } from '@ant-design/icons'
import { useState, useEffect } from "react";
import { EditableCell } from './EditableCell'
const newRowKeyValue = 'newRow'
const tryAddKeys = (items) => {
if(!items?.length || !items[0])
return []
if(items[0].key)
return items
return items.map((item, index) => ({...item, key: item.key ?? item.id ?? index }))
}
export const EditableTable = ({
columns,
dataSource,
onChange, // Метод вызывается со всем dataSource с измененными элементами после любого действия
onRowAdd, // Метод вызывается с новой добавленной записью. Если метод не поределен, то кнопка добавления строки не показывается
onRowEdit,// Метод вызывается с новой отредактированной записью. Если метод не поределен, то кнопка редактирования строки не показывается
onRowDelete,// Метод вызывается с удаленной записью. Если метод не поределен, то кнопка удаления строки не показывается
...otherTableProps}) => {
const [form] = Form.useForm()
const [data, setData] = useState(tryAddKeys(dataSource))
const [editingKey, setEditingKey] = useState('')
useEffect(()=>{
setData(tryAddKeys(dataSource))
},[dataSource])
const isEditing = (record) => record?.key === editingKey
const edit = (record) => {
form.setFieldsValue({...record})
setEditingKey(record.key)
}
const cancel = () => {
if(editingKey === newRowKeyValue)
{
const newData = [...data]
const index = newData.findIndex((item) => newRowKeyValue === item.key)
newData.splice(index, 1)
setData(newData)
}
setEditingKey('')
}
const addNewRow = async () => {
let newRow = {
...form.initialValues,
key:newRowKeyValue
}
const newData = [newRow, ...data]
setData(newData)
edit(newRow)
}
const save = async (record) => {
try {
const row = await form.validateFields()
const newData = [...data]
const index = newData.findIndex((item) => record.key === item.key)
const item = newData[index]
const newItem = { ...item, ...row }
newData.splice(index, 1, newItem)
if(item.key === newRowKeyValue)
item.key = newRowKeyValue + newData.length
setEditingKey('')
setData(newData)
if (editingKey === newRowKeyValue)
onRowAdd(newItem)
else
onRowEdit(newItem)
if(onChange)
onChange(newData)
} catch (errInfo) {
console.log('Validate Failed:', errInfo)
}
}
const deleteRow = (record) =>{
const newData = [...data]
const index = newData.findIndex((item) => record.key === item.key)
newData.splice(index, 1)
setData(newData)
onRowDelete(record)
if(onChange)
onChange(newData)
}
const operationColumn = {
width: 82,
title: (!!onRowAdd) && <Button
onClick={addNewRow}
disabled={editingKey !== ''}
icon={<PlusOutlined/>}
/>,
dataIndex: 'operation',
render: (_, record) => {
const editable = isEditing(record)
return editable
?(<span>
<Button
onClick={() => save(record)}
icon={<SaveOutlined/>}/>
<Button
onClick={cancel}
icon={<CloseCircleOutlined/>}/>
</span>)
:(<span>
{onRowEdit&&<Button
disabled={editingKey !== ''}
onClick={() => edit(record)}
icon={<EditOutlined/>}/>}
{onRowDelete&&
<Popconfirm title="Удалить?" onConfirm={()=>deleteRow(record)}>
<Button icon={<DeleteOutlined/>}/>
</Popconfirm>}
</span>)
},
}
const handleColumn = (col) => {
if (col.children)
col.children = col.children.map(handleColumn)
if (!col.editable)
return col
return {
...col,
onCell: (record) => ({
editing: isEditing(record),
record,
dataIndex: col.dataIndex ?? col.key,
key: col.key ?? col.dataIndex,
input: col.input,
isRequired: col.isRequired,
title: col.title,
dataType: col.dataType,
formItemClass: col.formItemClass,
formItemRules: col.formItemRules,
initialValue: col.initialValue,
}),
}
}
const mergedColumns = [...columns.map(handleColumn), operationColumn]
return (
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
},
}}
columns={mergedColumns}
dataSource={data}
{...otherTableProps}
/>
</Form>
)
}