asb_cloud_front/src/pages/DrillingProgram/index.jsx

193 lines
6.3 KiB
JavaScript
Executable File
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 { 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,
} = useMemo(() => data, [data])
const stateId = useMemo(() => idState ?? ID_STATE.Unknown, [idState])
const state = useMemo(() => STATE_STRING[stateId], [stateId])
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,
`Не удалось загрузить категории программы бурения`,
{ actionName: 'Загрузка категорий программы бурения', well }
), [well])
useEffect(() => {
updateData()
}, [updateData])
const onCategoryEdit = useCallback((catId) => {
setSelectedCategory(catId)
setEditorVisible(!!catId)
}, [])
const onCategoryHistory = useCallback((catId) => {
setSelectedCategory(catId)
setHistoryVisible(!!catId)
}, [])
const onEditorClosed = useCallback((needUpdate) => {
setEditorVisible(false)
if (needUpdate)
updateData()
}, [updateData])
const clearError = useCallback(() => invokeWebApiWrapperAsync(
async () => {
await DrillingProgramService.clearError(well.id)
await updateData()
},
setShowLoader,
`Не удалось сбросить ошибку формирования программы бурения`,
{ actionName: 'Сброс ошибки форматирования программы бурения', well }
), [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',
})