asb_cloud_front/src/pages/DrillingProgram/index.jsx

191 lines
6.1 KiB
React
Raw Normal View History

import { Button, Layout } from 'antd'
import {
AuditOutlined,
CheckOutlined,
CloseOutlined,
FileWordOutlined,
LoadingOutlined,
ReloadOutlined,
WarningOutlined,
} from '@ant-design/icons'
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { useWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils'
import { DrillingProgramService } from '@api'
import CategoryAdder from './CategoryAdder'
import CategoryRender from './CategoryRender'
import CategoryEditor from './CategoryEditor'
import CategoryHistory from './CategoryHistory'
import '@styles/drilling_program.less'
const ID_STATE = {
NotInitialized: 0,
Approving: 1,
Creating: 2,
Ready: 3,
Error: 4,
Unknown: -1,
}
const STATE_STRING = {
[ID_STATE.NotInitialized]: { icon: CloseOutlined, text: 'Не настроена' },
[ID_STATE.Approving]: { icon: AuditOutlined, text: 'Согласовывается' },
[ID_STATE.Creating]: { icon: LoadingOutlined, text: 'Формируется' },
[ID_STATE.Ready]: { icon: CheckOutlined, text: 'Сформирована' },
[ID_STATE.Error]: { icon: WarningOutlined, text: 'Ошибка формирования' },
[ID_STATE.Unknown]: { icon: WarningOutlined, text: 'Неизвестно' },
}
const DrillingProgram = memo(() => {
const [selectedCategory, setSelectedCategory] = useState()
const [historyVisible, setHistoryVisible] = useState(false)
const [editorVisible, setEditorVisible] = useState(false)
const [showLoader, setShowLoader] = useState(false)
const [categories, setCategories] = useState([])
const [data, setData] = useState({})
const [well] = useWell()
const {
idState,
permissionToEdit,
parts,
program,
error,
2022-03-18 19:40:52 +05:00
} = useMemo(() => data, [data])
const stateId = useMemo(() => idState ?? ID_STATE.Unknown, [idState])
const state = useMemo(() => STATE_STRING[stateId], [stateId])
2022-03-18 19:40:52 +05:00
const StateIcon = useMemo(() => state.icon, [state?.icon])
const updateData = useCallback(async () => await invokeWebApiWrapperAsync(
async () => {
const data = await DrillingProgramService.getState(well.id)
const categories = arrayOrDefault(await DrillingProgramService.getCategories(well.id))
setData(data)
setCategories(categories.filter(cat => {
if (cat?.id && (cat.name || cat.shortName))
if (data.parts?.findIndex((val) => val.idFileCategory === cat.id) < 0)
return true
return false
}))
},
setShowLoader,
`Не удалось загрузить название скважины "${well.caption}"`
), [well])
useEffect(() => {
updateData()
}, [updateData])
2022-03-18 19:40:52 +05:00
const onCategoryEdit = useCallback((catId) => {
setSelectedCategory(catId)
setEditorVisible(!!catId)
2022-03-18 19:40:52 +05:00
}, [])
2022-03-18 19:40:52 +05:00
const onCategoryHistory = useCallback((catId) => {
setSelectedCategory(catId)
setHistoryVisible(!!catId)
2022-03-18 19:40:52 +05:00
}, [])
const onEditorClosed = useCallback((needUpdate) => {
setEditorVisible(false)
if (needUpdate)
updateData()
}, [updateData])
const clearError = useCallback(() => invokeWebApiWrapperAsync(
async () => {
await DrillingProgramService.clearError(well.id)
await updateData()
},
setShowLoader,
`Не удалось сбросить ошибку формирования программы бурения для скважины ${well.caption}`
), [well])
return (
<LoaderPortal show={showLoader}>
<Layout style={{ backgroundColor: 'white' }}>
<div className={'drilling_program'}>
<div className={'program_header'}>
<h3>Программа бурения</h3>
{permissionToEdit && (
<div>
<CategoryAdder categories={categories} onUpdate={updateData} />
</div>
)}
</div>
<div className={'program_content'}>
{stateId === ID_STATE.Ready ? (
<>
<Button
type={'link'}
icon={<FileWordOutlined />}
style={{ marginLeft: '10px' }}
onClick={() => downloadFile(program)}
>
{program?.name}
</Button>
<div className={'m-10'}>Размер: {formatBytes(program?.size)}</div>
<div className={'m-10'}>Сформирован: {formatDate(program?.uploadDate)}</div>
</>
) : stateId === ID_STATE.Error ? (
<>
<h3 className={'program_status error'}>
<StateIcon className={'m-10'} />
{error?.message ?? state.text}
</h3>
<Button onClick={clearError} icon={<ReloadOutlined />}>
Сбросить статус ошибки
</Button>
</>
) : (
<h3 className={'program_status'}>
<StateIcon className={'m-10'} />
{state.text}
</h3>
)}
</div>
</div>
{parts?.map?.((part, idx) => part && (
<CategoryRender
key={`${idx}`}
partData={part}
onEdit={permissionToEdit && onCategoryEdit}
onUpdate={updateData}
onHistory={onCategoryHistory}
/>
))}
{permissionToEdit && (
<>
<CategoryEditor
visible={editorVisible}
onClosed={onEditorClosed}
category={parts?.find((part) => part.idFileCategory === selectedCategory) ?? {}}
/>
</>
)}
<CategoryHistory
idCategory={selectedCategory}
onClose={() => setHistoryVisible(false)}
visible={historyVisible}
/>
</Layout>
</LoaderPortal>
)
})
export default wrapPrivateComponent(DrillingProgram, {
requirements: [ 'DrillingProgram.get' ],
title: 'Программа бурения',
route: 'drillingProgram',
})