asb_cloud_front/src/pages/Measure/MeasureTable.jsx

166 lines
6.4 KiB
React
Raw Normal View History

2022-03-18 19:40:52 +05:00
import { useState, useEffect, memo, useMemo, useCallback } from 'react'
import { Button, Form, Input, Popconfirm, Timeline } from 'antd'
import {
CheckSquareOutlined,
EditOutlined,
SaveOutlined,
PlusOutlined,
CloseCircleOutlined,
DeleteOutlined
} from '@ant-design/icons'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { hasPermission } from '@utils/permissions'
import { formatDate } from '@utils'
import { MeasureService } from '@api'
import { View } from './View'
import '@styles/index.css'
import '@styles/measure.css'
const createEditingColumns = (cols, renderDelegate) =>
cols.map(col => ({ render: renderDelegate, ...col }))
2022-03-18 19:40:52 +05:00
const disabled = !hasPermission('Measure.edit')
export const MeasureTable = memo(({ idWell, group, updateMeasuresFunc, additionalButtons }) => {
const [showLoader, setShowLoader] = useState(false)
const [displayedValues, setDisplayedValues] = useState({})
const [editingColumns, setEditingColumns] = useState(group.columns)
const [isTableEditing, setIsTableEditing] = useState(false)
const [editingActionName, setEditingActionName] = useState('')
const [measuresForm] = Form.useForm()
2021-10-06 13:57:04 +05:00
2022-03-18 19:40:52 +05:00
const data = useMemo(() => group?.values?.length > 0 ? group.values : [group?.defaultValue], [group?.defaultValue, group?.values])
useEffect(() => setDisplayedValues(data.at(-1)), [data])
useEffect(() => {
const switchableColumns = createEditingColumns(
group.columns,
isTableEditing ? () => <Input className={'w-100 measure-input'} /> : null
)
if(editingActionName === 'edit')
measuresForm.setFieldsValue(displayedValues?.data)
else if(editingActionName === 'add')
measuresForm.resetFields()
setEditingColumns(switchableColumns)
}, [isTableEditing, group.columns, editingActionName, displayedValues?.data, measuresForm])
const markMeasuresAsDeleted = async () => await invokeWebApiWrapperAsync(
async () => {
await MeasureService.markAsDelete(idWell, displayedValues.id)
updateMeasuresFunc()
},
setShowLoader,
`Не удалось удалить запись ${displayedValues.id} для скважины "${idWell}"`,
'Удаление записи для скважины'
)
2022-03-18 19:40:52 +05:00
const editingDisabled = useMemo(() => disabled || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
const deleteDisabled = useMemo(() => !hasPermission('Measure.delete') || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
2022-03-18 19:40:52 +05:00
const editTable = useCallback((action) => {
setEditingActionName(action)
setIsTableEditing(true)
2022-03-18 19:40:52 +05:00
}, [])
2021-08-28 22:32:13 +05:00
2022-03-18 19:40:52 +05:00
const handleSubmitMeasuresForm = useCallback(async (formData) => await invokeWebApiWrapperAsync(
async () => {
measuresForm.validateFields()
const measureParams = {
idWell: idWell,
idCategory: group.idCategory,
timestamp: new Date().toISOString(),
data: formData
}
if(editingActionName === 'add') {
await MeasureService.insert(idWell, measureParams)
} else if (editingActionName === 'edit') {
measureParams.id = displayedValues.id
measureParams.timestamp = displayedValues.timestamp
await MeasureService.update(idWell, measureParams)
}
setIsTableEditing(false)
updateMeasuresFunc()
},
setShowLoader,
`Не удалось добавить/изменить запись для скаважины "${idWell}"`,
'Добавление/изменение записи по скважине'
2022-03-18 19:40:52 +05:00
), [displayedValues?.id, displayedValues?.timestamp, editingActionName, group.idCategory, idWell, measuresForm, updateMeasuresFunc])
return (
<>
&nbsp;<h2>{group.title}</h2>&nbsp;
<div className={'d-flex'}>
<div className={'flex-direction-column'}>
<div className={'measure-buttons-container'}>
<div className={'w-300px mt-8px d-flex'} style={{ alignItems: 'stretch' }}>
{ isTableEditing ? (
<>
<Button key={'confirm'} className={'flex-1'} onClick={() => measuresForm.submit()}>
<SaveOutlined />
</Button>
<Button key={'decline'} className={'flex-1'} onClick={() => setIsTableEditing(false)}>
<CloseCircleOutlined />
</Button>
</>
) : (
<>
<Button key={'add'} className={'flex-1'} onClick={() => editTable('add')} disabled={disabled}>
<PlusOutlined />
</Button>
<Button key={'edit'} className={'flex-1'} onClick={() => editTable('edit')} disabled={editingDisabled}>
<EditOutlined />
</Button>
<Popconfirm style={{ flex: '1' }} title={'Удалить данные?'} onConfirm={markMeasuresAsDeleted} disabled={deleteDisabled}>
<Button key={'delete'} onClick={() => setEditingActionName('delete')} disabled={deleteDisabled}>
<DeleteOutlined style={{ margin:'auto 28px' }}/>
</Button>
</Popconfirm>
</>
)}
{additionalButtons?.(isTableEditing)}
</div>
</div>
<div className={'measure-dates mt-20px'}>
<Timeline className={'mt-12px ml-10px'}>
{data.map((item, index) => (
<Timeline.Item
key={index}
className={'measure-button'}
onClick={() => setDisplayedValues(item)}
dot={item?.id === displayedValues?.id && (
<CheckSquareOutlined className={'timeline-clock-icon'} />
)}
>
<span className={item?.id === displayedValues?.id ? 'selected-timeline' : undefined}>
{formatDate(item.timestamp) ?? 'Нет данных'}
</span>
</Timeline.Item>
))}
</Timeline>
</div>
</div>
<div className={'w-100'}>
<LoaderPortal show={showLoader}>
<Form form={measuresForm} onFinish={handleSubmitMeasuresForm}>
<View item={displayedValues?.data ?? {}} columns={editingColumns} />
</Form>
</LoaderPortal>
</div>
</div>
</>
)
})
export default MeasureTable