forked from ddrilling/asb_cloud_front
Добавлен шаблон новой программы бурения
This commit is contained in:
parent
65ac977cab
commit
9de6400e78
@ -1,168 +1,236 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { memo, useState } from 'react'
|
||||||
import { FileExcelOutlined } from '@ant-design/icons'
|
import { Button, Tooltip, Layout } from 'antd'
|
||||||
import { Popconfirm, Button, Tooltip, Typography } from 'antd'
|
import { CommentOutlined, FileWordOutlined, TableOutlined, UploadOutlined } from '@ant-design/icons'
|
||||||
|
|
||||||
import { Flex } from '@components/Grid'
|
import { Flex } from '@components/Grid'
|
||||||
|
import { UserView } from '@components/views'
|
||||||
import LoaderPortal from '@components/LoaderPortal'
|
import LoaderPortal from '@components/LoaderPortal'
|
||||||
import { MarkView, UserView } from '@components/views'
|
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||||
import { invokeWebApiWrapperAsync, download, formatBytes } from '@components/factory'
|
import { arrayOrDefault, formatDate } from '@utils'
|
||||||
import { DrillingProgramService, WellService } from '@api'
|
import { hasPermission } from '@utils/permissions'
|
||||||
|
import { DrillingProgramService } from '@api'
|
||||||
|
|
||||||
import DocumentsTemplate from '@pages/Documents/DocumentsTemplate'
|
const testCategories = [
|
||||||
|
|
||||||
const idFileCategoryDrillingProgramItems = 13
|
|
||||||
const { Text } = Typography
|
|
||||||
|
|
||||||
export const DrillingProgram = ({ idWell }) => {
|
|
||||||
const [downloadButtonEnabled, selDownloadButtonEnabled] = useState(false)
|
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
|
||||||
const [tooltip, setTooltip] = useState('нет файлов для формирования')
|
|
||||||
const [wellLabel, setWellLabel] = useState(`${idWell}`)
|
|
||||||
const [childKey, setChildKey] = useState()
|
|
||||||
const [lastUpdatedFile, setLastUpdatedFile] = useState()
|
|
||||||
|
|
||||||
useEffect(() => invokeWebApiWrapperAsync(
|
|
||||||
async () => {
|
|
||||||
const well = await WellService.get(idWell)
|
|
||||||
setWellLabel(well.caption ?? `${idWell}`)
|
|
||||||
},
|
|
||||||
setShowLoader,
|
|
||||||
`Не удалось загрузить название скважины "${idWell}"`,
|
|
||||||
'Получить название скважины'
|
|
||||||
), [idWell])
|
|
||||||
|
|
||||||
const downloadProgram = () => invokeWebApiWrapperAsync(
|
|
||||||
async () => await download(`/api/well/${idWell}/drillingProgram`),
|
|
||||||
setShowLoader,
|
|
||||||
`Не удалось загрузить программу бурения для скважины "${idWell}"`,
|
|
||||||
'Получить программу бурения'
|
|
||||||
)
|
|
||||||
|
|
||||||
const openProgramPreview = () => invokeWebApiWrapperAsync(
|
|
||||||
async() => {
|
|
||||||
const filWebUrl = await DrillingProgramService.getOrCreateSharedUrl(idWell)
|
|
||||||
if(filWebUrl && filWebUrl.length > 0)
|
|
||||||
window.open(filWebUrl, '_blank')
|
|
||||||
else
|
|
||||||
throw new Error('Сервер вернул плохую ссылку')
|
|
||||||
},
|
|
||||||
setShowLoader,
|
|
||||||
'Не удалось создать быстрый просмотр программы',
|
|
||||||
'Создать быстрый просмотр программы'
|
|
||||||
)
|
|
||||||
|
|
||||||
const filesUpdated = (files) => {
|
|
||||||
if (!files || files.length === 0) {
|
|
||||||
setTooltip('Нет файлов для формирования программы')
|
|
||||||
selDownloadButtonEnabled(false)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const isAllFilesAreExcel = files.every(fileInfo => fileInfo?.name.toLowerCase().endsWith('.xlsx'))
|
|
||||||
const isAnyFileMarked = files.some(file => file?.fileMarks.some(m => m?.idMarkType === 1 && !m?.isDeleted))
|
|
||||||
|
|
||||||
if (isAllFilesAreExcel && isAnyFileMarked) {
|
|
||||||
setTooltip('Программа доступна для скачивания')
|
|
||||||
selDownloadButtonEnabled(true)
|
|
||||||
} else {
|
|
||||||
setTooltip('Список файлов содержит недопустимые типы файлов')
|
|
||||||
}
|
|
||||||
const last = files.reduce((pre, cur) => pre.uploadDate > cur.uploadDate ? pre : cur)
|
|
||||||
setLastUpdatedFile(last)
|
|
||||||
}
|
|
||||||
|
|
||||||
const customColumns = [
|
|
||||||
{
|
{
|
||||||
title: 'Метки',
|
caption: 'Задание от геологов',
|
||||||
key: 'fileMarks',
|
status: 1,
|
||||||
render: (_, record) => renderMarksColumn(record?.id, record?.fileMarks)
|
file: {
|
||||||
|
name: 'Документ 1.xlsx',
|
||||||
|
author: { login: 'Человек 9', company: { caption: 'Компания 9' } },
|
||||||
|
size: '123 кБ',
|
||||||
|
uploadDate: '2022-01-01T00:00:00',
|
||||||
},
|
},
|
||||||
]
|
lastApprove: '2022-01-01T00:00:00',
|
||||||
|
lastReject: '2022-01-01T00:00:00',
|
||||||
const renderMarksColumn=(idFile, marks)=>{
|
approved: [{
|
||||||
const validMarks = marks?.filter(m => !(m?.isDeleted))
|
user: { login: 'Человек 2', company: { caption: 'Компания 2' }},
|
||||||
if(validMarks?.length)
|
comment: 'Комментарий',
|
||||||
return validMarks.map(mark => <MarkView mark = {mark} onDelete={() => deleteMark(mark.id)}/>)
|
}],
|
||||||
|
undecided: [{ login: 'Человек 3', company: { caption: 'Компания 1' }}],
|
||||||
return (
|
rejected: [],
|
||||||
<Popconfirm title={'Согласовать файл?'} onConfirm={() => addMarkToFile(idFile)}>
|
}, {
|
||||||
<Button type={'link'}>Согласовать</Button>
|
caption: 'Профиль ствола скважины (ННБ)',
|
||||||
</Popconfirm>
|
status: 1,
|
||||||
)
|
file: {
|
||||||
|
name: 'Документ 1.xlsx',
|
||||||
|
author: { login: 'Человек 9', company: { caption: 'Компания 9' }},
|
||||||
|
size: '123 кБ',
|
||||||
|
uploadDate: '2022-01-01T00:00:00',
|
||||||
|
},
|
||||||
|
lastApprove: '2022-01-01T00:00:00',
|
||||||
|
lastReject: '2022-01-01T00:00:00',
|
||||||
|
approved: [{
|
||||||
|
user: { login: 'Человек 2', company: { caption: 'Компания 2' }},
|
||||||
|
comment: 'Комментарий 3',
|
||||||
|
}],
|
||||||
|
undecided: [
|
||||||
|
{ login: 'Человек 3', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 4', company: { caption: 'Компания 2' }},
|
||||||
|
],
|
||||||
|
rejected: [{
|
||||||
|
user: { login: 'Человек 1', company: { caption: 'Компания 1' }},
|
||||||
|
comment: 'Комментарий 2',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
caption: 'Технологические расчёты ННБ',
|
||||||
|
status: 0,
|
||||||
|
file: {
|
||||||
|
name: 'Документ 1.xlsx',
|
||||||
|
author: { login: 'Человек 9', company: { caption: 'Компания 9' }},
|
||||||
|
size: '123 кБ',
|
||||||
|
uploadDate: '2022-01-01T00:00:00',
|
||||||
|
},
|
||||||
|
lastApprove: '2022-01-01T00:00:00',
|
||||||
|
lastReject: '2022-01-01T00:00:00',
|
||||||
|
approved: [],
|
||||||
|
undecided: [
|
||||||
|
{ login: 'Человек 2', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 3', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 4', company: { caption: 'Компания 2' }},
|
||||||
|
],
|
||||||
|
rejected: [{
|
||||||
|
user: { login: 'Человек 1', company: { caption: 'Компания 1' }},
|
||||||
|
comment: 'Комментарий 2',
|
||||||
|
}],
|
||||||
|
}, {
|
||||||
|
caption: 'ГГД',
|
||||||
|
status: 0,
|
||||||
|
file: {
|
||||||
|
name: 'Документ 1.xlsx',
|
||||||
|
author: { login: 'Человек 9', company: { caption: 'Компания 9' }},
|
||||||
|
size: '123 кБ',
|
||||||
|
uploadDate: '2022-01-01T00:00:00',
|
||||||
|
},
|
||||||
|
lastApprove: '2022-01-01T00:00:00',
|
||||||
|
lastReject: '2022-01-01T00:00:00',
|
||||||
|
approved: [],
|
||||||
|
undecided: [
|
||||||
|
{ login: 'Человек 2', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 3', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 4', company: { caption: 'Компания 2' }},
|
||||||
|
{ login: 'Человек 2', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 3', company: { caption: 'Компания 1' }},
|
||||||
|
{ login: 'Человек 4', company: { caption: 'Компания 2' }},
|
||||||
|
],
|
||||||
|
rejected: [{
|
||||||
|
user: { login: 'Человек 1', company: { caption: 'Компания 1' }},
|
||||||
|
comment: 'Комментарий 2',
|
||||||
|
}],
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const addMarkToFile = async (idFile) => {
|
const testProgram = {
|
||||||
const mark = {
|
name: 'Документ 1.xlsx',
|
||||||
idFile: idFile,
|
size: '123 кБ',
|
||||||
idMarkType: 1,
|
uploadDate: '2022-01-01T00:00:00',
|
||||||
isDeleted: false,
|
}
|
||||||
comment: '',
|
|
||||||
}
|
|
||||||
await DrillingProgramService.createFileMark(idWell, mark)
|
|
||||||
selDownloadButtonEnabled(true)
|
|
||||||
setChildKey(Date.now())
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteMark = async (idMark) => {
|
export const DrillingProgram = memo(({ idWell }) => {
|
||||||
await DrillingProgramService.deleteFileMark(idWell, idMark)
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
setChildKey(Date.now())
|
const [categories, setCategories] = useState(testCategories)
|
||||||
}
|
const [program, setProgram] = useState(testProgram)
|
||||||
|
|
||||||
const downloadButton = (
|
const updateData = async () => await invokeWebApiWrapperAsync(
|
||||||
<div>
|
async () => {
|
||||||
<span>Программа бурения</span>
|
const categories = arrayOrDefault(await DrillingProgramService.getCategories(idWell))
|
||||||
<Flex>
|
const program = await DrillingProgramService.getProgram(idWell)
|
||||||
<Tooltip title={tooltip}>
|
setCategories(categories)
|
||||||
<Button
|
setProgram(program)
|
||||||
type={'primary'}
|
},
|
||||||
onClick={downloadProgram}
|
setShowLoader,
|
||||||
disabled={!downloadButtonEnabled}
|
`Не удалось загрузить название скважины "${idWell}"`
|
||||||
>
|
|
||||||
Сформировать и скачать
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip title={'Просмотреть через GoogleDrive'}>
|
|
||||||
<Popconfirm
|
|
||||||
title={'Загрузить файл на GoogleDrive для просмотра?'}
|
|
||||||
onConfirm={openProgramPreview}
|
|
||||||
disabled={!downloadButtonEnabled}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type={'link'}
|
|
||||||
disabled={!downloadButtonEnabled}
|
|
||||||
>
|
|
||||||
<FileExcelOutlined />
|
|
||||||
Программа бурения {wellLabel}.xlsx
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const lastUpdatedFileView = lastUpdatedFile &&
|
// useEffect(() => updateCategories(), [idWell])
|
||||||
<Text>
|
|
||||||
<b>Последнее изменние:</b>
|
const onApprove = (category) => () => invokeWebApiWrapperAsync(
|
||||||
'{lastUpdatedFile.name}'
|
async () => {
|
||||||
[{formatBytes(lastUpdatedFile.size)}]
|
await DrillingProgramService.approve(idWell, category)
|
||||||
загружен: {new Date(lastUpdatedFile.uploadDate).toLocaleString()}
|
await updateData()
|
||||||
автор: <UserView user={lastUpdatedFile.author}/>
|
},
|
||||||
</Text>
|
setShowLoader,
|
||||||
|
`Не удалось согласовать документ для скважины "${idWell}"!`
|
||||||
|
)
|
||||||
|
|
||||||
|
const onReject = (category) => () => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
await DrillingProgramService.reject(idWell, category)
|
||||||
|
await updateData()
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
`Не удалось согласовать документ для скважины "${idWell}"!`
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoaderPortal show={showLoader}>
|
<LoaderPortal show={showLoader}>
|
||||||
<DocumentsTemplate
|
<Layout>
|
||||||
key={childKey}
|
{program && (
|
||||||
idWell={idWell}
|
<div style={{ border: '1px solid #BEBEBE' }}>
|
||||||
accept={'.xlsx'}
|
<div style={{ padding: '5px 10px', backgroundColor: '#F3F3F3', borderBottom: '1px solid #BEBEBE' }}>Программа бурения</div>
|
||||||
onChange={filesUpdated}
|
<Flex style={{ justifyContent: 'flex-start', alignItems: 'center', backgroundColor: 'white' }}>
|
||||||
headerChild={downloadButton}
|
<Button type={'link'} icon={<FileWordOutlined />} style={{ marginLeft: '10px' }}>{program.name}</Button>
|
||||||
customColumns={customColumns}
|
<div style={{ margin: '10px' }}>Размер: {program.size}</div>
|
||||||
beforeTable={lastUpdatedFileView}
|
<div style={{ margin: '10px' }}>Загружен: {formatDate(program.uploadDate)}</div>
|
||||||
idCategory={idFileCategoryDrillingProgramItems}
|
</Flex>
|
||||||
/>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{categories.map((category) => category && (
|
||||||
|
<div key={category.caption} style={{ border: '1px solid #BEBEBE', marginTop: '10px' }}>
|
||||||
|
<Flex style={{ width: '100%', borderBottom: '1px solid #BEBEBE' }}>
|
||||||
|
<div style={{ padding: '5px 10px', backgroundColor: '#F3F3F3', flex: 5, borderRight: '1px solid #BEBEBE' }}>{category.caption}</div>
|
||||||
|
<div style={{ padding: '5px 10px', backgroundColor: '#F3F3F3', flex: 7 }}>Согласованты</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex>
|
||||||
|
<Flex style={{ padding: '5px 10px', backgroundColor: 'white', alignItems: 'stretch', flex: 5, borderRight: '1px solid #BEBEBE' }}>
|
||||||
|
<Flex style={{ flex: 10, flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||||
|
<Button type={'link'} icon={<FileWordOutlined />}>{category.file.name}</Button>
|
||||||
|
<div style={{ marginLeft: '15px' }}>Автор: <UserView user={category.file.author}/></div>
|
||||||
|
<div style={{ marginLeft: '15px' }}>Размер: {category.file.size}</div>
|
||||||
|
<div style={{ marginLeft: '15px' }}>Загружен: {formatDate(category.file.uploadDate)}</div>
|
||||||
|
</Flex>
|
||||||
|
<Flex style={{ flexDirection: 'column', flex: 2 }}>
|
||||||
|
<Button icon={<UploadOutlined />} style={{ margin: '5px 0 10px 0' }} title={'Загрузить'}>Загрузить</Button>
|
||||||
|
<Button icon={<TableOutlined />} disabled={!category.file} title={'История'}>История</Button>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex style={{ padding: '5px 10px', backgroundColor: 'white', alignItems: 'stretch', flex: 7 }}>
|
||||||
|
<div style={{ display: 'flex', flexWrap: 'wrap', flex: 6 }}>
|
||||||
|
{category.undecided.map((user, i) => (
|
||||||
|
<span key={i} style={{ margin: '5px 10px' }}>
|
||||||
|
<UserView user={user} />
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Flex style={{ flex: 3, margin: '0 5px', flexDirection: 'column' }}>
|
||||||
|
{category.status === 0 && hasPermission() && (
|
||||||
|
<Button style={{ margin: '5px 0'}} onClick={onApprove(category)}>Согласовать</Button>
|
||||||
|
)}
|
||||||
|
<Flex style={{ flexDirection: 'column', padding: '10px', backgroundColor: '#EFFEEF', border: '1px solid #1FB448', flexGrow: 1 }}>
|
||||||
|
<Flex style={{ justifyContent: 'space-between' }}>
|
||||||
|
<span style={{ fontWeight: 800 }}>Согласовано</span>
|
||||||
|
<span>{formatDate(category.lastApprove)}</span>
|
||||||
|
</Flex>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column-reverse', alignItems: 'stretch', flexGrow: 1 }}>
|
||||||
|
{category.approved?.map(({ comment, user }, i) => (
|
||||||
|
<div key={`${i}`} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<UserView user={user} />
|
||||||
|
<Tooltip placement={'left'} title={comment}>
|
||||||
|
<CommentOutlined />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
<Flex style={{ flex: 3, marginLeft: '0 5px', flexDirection: 'column' }}>
|
||||||
|
{category.status === 0 && hasPermission() && (
|
||||||
|
<Button style={{ margin: '5px 0' }} onClick={onReject(category)}>Отклонить</Button>
|
||||||
|
)}
|
||||||
|
<Flex style={{ flexDirection: 'column', padding: '10px', backgroundColor: '#FEF2EF', border: '1px solid #B4661F', flexGrow: 1 }}>
|
||||||
|
<Flex style={{ justifyContent: 'space-between' }}>
|
||||||
|
<span style={{ fontWeight: 800 }}>Отклонено</span>
|
||||||
|
<span>{formatDate(category.lastReject)}</span>
|
||||||
|
</Flex>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column-reverse', alignItems: 'stretch', flexGrow: 1 }}>
|
||||||
|
{category.rejected?.map(({ comment, user }, i) => (
|
||||||
|
<div key={`${i}`} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
<UserView user={user} />
|
||||||
|
<Tooltip placement={'left'} title={comment}>
|
||||||
|
<CommentOutlined />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</Layout>
|
||||||
</LoaderPortal>
|
</LoaderPortal>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
export default DrillingProgram
|
export default DrillingProgram
|
||||||
|
Loading…
Reference in New Issue
Block a user