forked from ddrilling/asb_cloud_front
169 lines
6.5 KiB
JavaScript
Executable File
169 lines
6.5 KiB
JavaScript
Executable File
import { useState, useEffect, memo, useMemo, useCallback, useContext } from 'react'
|
||
import { Button, Form, Input, Popconfirm, Timeline } from 'antd'
|
||
import {
|
||
CheckSquareOutlined,
|
||
EditOutlined,
|
||
SaveOutlined,
|
||
PlusOutlined,
|
||
CloseCircleOutlined,
|
||
DeleteOutlined
|
||
} from '@ant-design/icons'
|
||
|
||
import { IdWellContext } from '@asb/context'
|
||
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 }))
|
||
|
||
const disabled = !hasPermission('Measure.edit')
|
||
|
||
export const MeasureTable = memo(({ 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 idWell = useContext(IdWellContext)
|
||
|
||
const [measuresForm] = Form.useForm()
|
||
|
||
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}"`,
|
||
'Удаление записи для скважины'
|
||
)
|
||
const editingDisabled = useMemo(() => disabled || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
|
||
const deleteDisabled = useMemo(() => !hasPermission('Measure.delete') || !!displayedValues?.isDefaultData, [displayedValues?.isDefaultData])
|
||
|
||
const editTable = useCallback((action) => {
|
||
setEditingActionName(action)
|
||
setIsTableEditing(true)
|
||
}, [])
|
||
|
||
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}"`,
|
||
'Добавление/изменение записи по скважине'
|
||
), [displayedValues?.id, displayedValues?.timestamp, editingActionName, group.idCategory, idWell, measuresForm, updateMeasuresFunc])
|
||
|
||
return (
|
||
<>
|
||
<h2>{group.title}</h2>
|
||
<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
|