forked from ddrilling/asb_cloud_front
Переработана рекомендации уставок:
* Добавлена таблица с историей уставок * Добавлено окно просмотра уставки * Переработан стиль добавления уставки
This commit is contained in:
parent
4d0627a4fa
commit
ad8f01b186
113
src/pages/TelemetryView/SetpointSender.jsx
Normal file
113
src/pages/TelemetryView/SetpointSender.jsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { Select, Modal, Input, InputNumber } from 'antd'
|
||||||
|
import { SetpointsService } from '../../services/api'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import { makeNumericRender, EditableTable, makeNumericInput } from '../../components/Table'
|
||||||
|
import { PeriodPicker, defaultPeriod } from '../../components/PeriodPicker'
|
||||||
|
import { Grid, GridItem } from '../../components/Grid'
|
||||||
|
|
||||||
|
export const SetpointSender = ({ idWell, onClose, visible, setpointNames }) => {
|
||||||
|
const [expirePeriod, setExpirePeriod] = useState(defaultPeriod)
|
||||||
|
const [comment, setComment] = useState('')
|
||||||
|
const [setpoints, setSetpoints] = useState([])
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
const addingColumns = [
|
||||||
|
{
|
||||||
|
title: 'Наименование уставки',
|
||||||
|
dataIndex: 'name',
|
||||||
|
editable: true,
|
||||||
|
isRequired: true,
|
||||||
|
width: 200,
|
||||||
|
input: <Select options={setpointNames} />,
|
||||||
|
render: (val) => setpointNames.find((name) => name.value === val)?.label
|
||||||
|
}, {
|
||||||
|
title: 'Значение',
|
||||||
|
dataIndex: 'value',
|
||||||
|
editable: true,
|
||||||
|
isRequired: true,
|
||||||
|
width: 125,
|
||||||
|
input: <InputNumber style={{ width: '100%' }} formatter={value => `${value}`.replace(',', '.')}/>,
|
||||||
|
render: makeNumericRender(1),
|
||||||
|
align: 'right'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const onAdd = async (sp) => setSetpoints((prevSp) => {
|
||||||
|
sp.key = Date.now()
|
||||||
|
prevSp.push(sp)
|
||||||
|
return prevSp
|
||||||
|
})
|
||||||
|
|
||||||
|
const onEdit = async (sp) => setSetpoints((prevSp) => {
|
||||||
|
const idx = prevSp.findIndex((val) => val.key === sp.key)
|
||||||
|
prevSp[idx] = sp
|
||||||
|
return prevSp
|
||||||
|
})
|
||||||
|
|
||||||
|
const onDelete = async (sp) => setSetpoints((prevSp) => {
|
||||||
|
const idx = prevSp.findIndex((val) => val.key === sp.key)
|
||||||
|
prevSp.splice(idx, 1)
|
||||||
|
return prevSp
|
||||||
|
})
|
||||||
|
|
||||||
|
const onModalOk = () => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
const setpointsObject = setpoints.reduce((obj, sp) => (obj[sp.name] = sp.value, obj), {})
|
||||||
|
const request = {
|
||||||
|
uploadDate: new Date(),
|
||||||
|
obsolescenceSec: expirePeriod,
|
||||||
|
setpoints: setpointsObject,
|
||||||
|
comment: comment
|
||||||
|
}
|
||||||
|
await SetpointsService.insert(idWell, request)
|
||||||
|
onClose(true)
|
||||||
|
},
|
||||||
|
setIsLoading,
|
||||||
|
`Не удалось отправить уставки по скважине "${idWell}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
width={800}
|
||||||
|
title={'Рекомендовать уставки'}
|
||||||
|
visible={visible}
|
||||||
|
onCancel={onClose}
|
||||||
|
onOk={onModalOk}
|
||||||
|
okText={'Отправить'}
|
||||||
|
>
|
||||||
|
<LoaderPortal show={isLoading}>
|
||||||
|
<Grid>
|
||||||
|
<GridItem row={1} col={1}>Период актуальности рекомендаций:</GridItem>
|
||||||
|
<GridItem row={1} col={2}>
|
||||||
|
<PeriodPicker style={{ marginLeft: 'auto' }} onChange={setExpirePeriod} width={'100%'}/>
|
||||||
|
</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={2} col={1}>Комментарий:</GridItem>
|
||||||
|
<GridItem row={3} col={1} colSpan={3}>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={4}
|
||||||
|
onChange={(e) => setComment(e.target.value)}
|
||||||
|
value={comment}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={4} col={1} colSpan={3}>
|
||||||
|
<EditableTable
|
||||||
|
bordered
|
||||||
|
columns={addingColumns}
|
||||||
|
dataSource={setpoints}
|
||||||
|
onRowAdd={onAdd}
|
||||||
|
onRowEdit={onEdit}
|
||||||
|
onRowDelete={onDelete}
|
||||||
|
pagination={false}
|
||||||
|
style={{ margin: '10px 0' }}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</LoaderPortal>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
77
src/pages/TelemetryView/SetpointViewer.jsx
Normal file
77
src/pages/TelemetryView/SetpointViewer.jsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import moment from 'moment'
|
||||||
|
import { memo } from 'react'
|
||||||
|
import { Modal, Input } from 'antd'
|
||||||
|
import { Table } from '../../components/Table'
|
||||||
|
import { UserView } from '../../components/UserView'
|
||||||
|
import { Grid, GridItem } from '../../components/Grid'
|
||||||
|
import { periodToString } from '../../utils/datetime'
|
||||||
|
|
||||||
|
export const setpointStatus = {
|
||||||
|
0: 'Неизвестно',
|
||||||
|
1: 'Ожидает отправки',
|
||||||
|
2: 'Отправлено',
|
||||||
|
3: 'Принято оператором',
|
||||||
|
4: 'Отклонено оператором',
|
||||||
|
5: 'Устарело',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getSetpointStatus = (id) => {
|
||||||
|
if (!id || Object.keys(setpointStatus).every((idx) => Number(idx) !== id))
|
||||||
|
return setpointStatus[0]
|
||||||
|
return setpointStatus[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: 'Название', dataIndex: 'name' },
|
||||||
|
{ title: 'Значение', dataIndex: 'value' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export const SetpointViewer = memo(({ setpoint, visible, onClose, setpointNames }) => {
|
||||||
|
let date = moment(setpoint?.uploadDate).format('DD MMM YYYY, HH:mm:ss')
|
||||||
|
let setpoints = []
|
||||||
|
if (setpoint) {
|
||||||
|
setpoints = Object.keys(setpoint?.setpoints).map((name) => ({
|
||||||
|
name: setpointNames.find(spName => spName.value === name)?.label,
|
||||||
|
value: setpoint.setpoints[name]
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
width={800}
|
||||||
|
title={`Уставка от ${date}`}
|
||||||
|
onCancel={onClose}
|
||||||
|
visible={visible}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
<Grid>
|
||||||
|
<GridItem row={1} col={1}>Дата рекомендаций:</GridItem>
|
||||||
|
<GridItem row={1} col={2}>{date}</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={2} col={1}>Автор:</GridItem>
|
||||||
|
<GridItem row={2} col={2}><UserView user={setpoint?.author}/></GridItem>
|
||||||
|
|
||||||
|
<GridItem row={3} col={1}>Статус:</GridItem>
|
||||||
|
<GridItem row={3} col={2}>{getSetpointStatus(setpoint?.idState)}</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={4} col={1}>Период актуальности рекомендаций:</GridItem>
|
||||||
|
<GridItem row={4} col={2}>{periodToString(setpoint?.obsolescenceSec)}</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={5} col={1}>Комментарий:</GridItem>
|
||||||
|
<GridItem row={6} col={1} colSpan={3}>
|
||||||
|
<Input.TextArea rows={4} value={setpoint?.comment} readOnly />
|
||||||
|
</GridItem>
|
||||||
|
|
||||||
|
<GridItem row={7} col={1} colSpan={3}>
|
||||||
|
<Table
|
||||||
|
bordered
|
||||||
|
size={'small'}
|
||||||
|
dataSource={setpoints}
|
||||||
|
columns={columns}
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
})
|
@ -1,41 +1,25 @@
|
|||||||
import { Button, Input, Modal, Select } from 'antd'
|
import moment from 'moment'
|
||||||
import { useState } from 'react'
|
import { Button, Modal } from 'antd'
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
import { useState, useEffect } from 'react'
|
||||||
|
import { Table } from '../../components/Table'
|
||||||
|
import { UserView } from '../../components/UserView'
|
||||||
import LoaderPortal from '../../components/LoaderPortal'
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import PeriodPicker, { defaultPeriod } from '../../components/PeriodPicker'
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
import { EditableTable, makeNumericRender } from '../../components/Table'
|
import { makeStringCutter } from '../../utils/string'
|
||||||
import { SetpointsService } from '../../services/api'
|
import { SetpointsService } from '../../services/api'
|
||||||
|
import { SetpointSender } from './SetpointSender'
|
||||||
|
import { SetpointViewer, getSetpointStatus } from './SetpointViewer'
|
||||||
|
|
||||||
export const Setpoints = ({ idWell, ...other }) => {
|
export const Setpoints = ({ idWell, ...other }) => {
|
||||||
const [isModalShown, setIsModalShown] = useState(false)
|
const [isModalVisible, setIsModalVisible] = useState(false)
|
||||||
|
const [isSenderVisible, setIsSenderVisible] = useState(false)
|
||||||
|
const [isViewerVisible, setIsViewerVisible] = useState(false)
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const [isUploading, setIsUploading] = useState(false)
|
|
||||||
const [setpointNames, setSetpointNames] = useState([])
|
|
||||||
const [setpoints, setSetpoints] = useState([])
|
const [setpoints, setSetpoints] = useState([])
|
||||||
const [comment, setComment] = useState('')
|
const [selected, setSelected] = useState(null)
|
||||||
const [expirePeriod, setExpirePeriod] = useState(defaultPeriod)
|
const [setpointNames, setSetpointNames] = useState([])
|
||||||
|
|
||||||
const columns = [
|
useEffect(() => invokeWebApiWrapperAsync(
|
||||||
{
|
|
||||||
title: 'Наименование установки',
|
|
||||||
dataIndex: 'name',
|
|
||||||
editable: true,
|
|
||||||
isRequired: true,
|
|
||||||
width: 200,
|
|
||||||
input: <Select options={setpointNames} />,
|
|
||||||
render: (val) => setpointNames.find((name) => name.value === val)?.label
|
|
||||||
}, {
|
|
||||||
title: 'Значение',
|
|
||||||
dataIndex: 'value',
|
|
||||||
editable: true,
|
|
||||||
isRequired: true,
|
|
||||||
width: 125,
|
|
||||||
render: makeNumericRender(7),
|
|
||||||
align: 'right'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const onOpenClick = () => invokeWebApiWrapperAsync(
|
|
||||||
async () => {
|
async () => {
|
||||||
const names = await SetpointsService.getSetpointsNamesByIdWell(idWell)
|
const names = await SetpointsService.getSetpointsNamesByIdWell(idWell)
|
||||||
if (!names) throw Error('Setpoints not found')
|
if (!names) throw Error('Setpoints not found')
|
||||||
@ -44,84 +28,79 @@ export const Setpoints = ({ idWell, ...other }) => {
|
|||||||
value: spn.name,
|
value: spn.name,
|
||||||
tooltip: spn.comment
|
tooltip: spn.comment
|
||||||
})))
|
})))
|
||||||
setIsModalShown(true)
|
},
|
||||||
|
setIsLoading,
|
||||||
|
`Не удалось загрузить список имёт уставок по скважине "${idWell}"`
|
||||||
|
), [idWell])
|
||||||
|
|
||||||
|
const showMore = (id) => {
|
||||||
|
const selected = setpoints.find((sp) => sp.id === id)
|
||||||
|
setSelected(selected ?? {})
|
||||||
|
setIsViewerVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const historyColumns = [
|
||||||
|
{ title: 'Дата', dataIndex: 'uploadDate', render: item => moment(item).format('DD MMM YYYY, HH:mm:ss') },
|
||||||
|
{ title: 'Автор', dataIndex: 'author', render: (user) => <UserView user={user} /> },
|
||||||
|
{ title: 'Комментарий', dataIndex: 'comment', render: makeStringCutter() },
|
||||||
|
{ title: 'Статус', dataIndex: 'idState', render: (id) => getSetpointStatus(parseInt(id)) },
|
||||||
|
{ dataIndex: 'id', render: (id) => <Button onClick={() => showMore(id)}>Подробнее</Button> },
|
||||||
|
]
|
||||||
|
|
||||||
|
const updateTable = () => invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
const setpoints = await SetpointsService.getByIdWell(idWell)
|
||||||
|
setSetpoints(setpoints)
|
||||||
},
|
},
|
||||||
setIsLoading,
|
setIsLoading,
|
||||||
`Не удалось загрузить список для скважины "${idWell}"`
|
`Не удалось загрузить список для скважины "${idWell}"`
|
||||||
)
|
)
|
||||||
|
|
||||||
const onModalOk = () => invokeWebApiWrapperAsync(
|
useEffect(updateTable, [idWell])
|
||||||
async () => {
|
|
||||||
// eslint-disable-next-line no-sequences
|
|
||||||
const setpointsObject = setpoints.reduce((obj, sp) => (obj[sp.name] = sp.value, obj), {})
|
|
||||||
const request = {
|
|
||||||
uploadDate: new Date(),
|
|
||||||
obsolescenceSec: expirePeriod,
|
|
||||||
setpoints: setpointsObject,
|
|
||||||
comment: comment
|
|
||||||
}
|
|
||||||
await SetpointsService.insert(idWell, request)
|
|
||||||
setIsModalShown(false)
|
|
||||||
},
|
|
||||||
setIsUploading,
|
|
||||||
`Не удалось отправить рекомендации по скважине "${idWell}"`
|
|
||||||
)
|
|
||||||
|
|
||||||
const onAdd = async (setpoint) => setSetpoints((prevSetpoints) => {
|
const onSenderClose = (pushed) => {
|
||||||
setpoint.key = Date.now()
|
if (pushed) updateTable()
|
||||||
prevSetpoints.push(setpoint)
|
setIsSenderVisible(false)
|
||||||
return prevSetpoints
|
}
|
||||||
})
|
|
||||||
|
|
||||||
const onEdit = async (setpoint) => setSetpoints((prevSetpoints) => {
|
|
||||||
const idx = prevSetpoints.findIndex((val) => val.key === setpoint.key)
|
|
||||||
prevSetpoints[idx] = setpoint
|
|
||||||
return prevSetpoints
|
|
||||||
})
|
|
||||||
|
|
||||||
const onDelete = async (setpoint) => setSetpoints((prevSetpoints) => {
|
|
||||||
const idx = prevSetpoints.findIndex((val) => val.key === setpoint.key)
|
|
||||||
prevSetpoints.splice(idx, 1)
|
|
||||||
return prevSetpoints
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div {...other}>
|
<div {...other}>
|
||||||
<Button onClick={onOpenClick} loading={isLoading}>
|
<Button onClick={() => setIsModalVisible(true)} loading={isLoading}>
|
||||||
Рекомендовать установки
|
Рекомендованные уставки
|
||||||
</Button>
|
</Button>
|
||||||
<Modal
|
<Modal
|
||||||
width={800}
|
width={1200}
|
||||||
title={'Рекомендация установок'}
|
title={'Рекомендованные уставки'}
|
||||||
visible={isModalShown}
|
visible={isModalVisible}
|
||||||
onCancel={() => setIsModalShown(false)}
|
onCancel={() => setIsModalVisible(false)}
|
||||||
onOk={onModalOk}
|
footer={
|
||||||
okText={'Отправить'}
|
<Button onClick={() => setIsSenderVisible(true)}>
|
||||||
|
Рекомендовать
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<LoaderPortal show={isUploading}>
|
<LoaderPortal show={isLoading}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<Table
|
||||||
Период актуальности рекомендаций:
|
size={'small'}
|
||||||
<PeriodPicker onChange={setExpirePeriod} />
|
|
||||||
</div>
|
|
||||||
<EditableTable
|
|
||||||
bordered
|
bordered
|
||||||
columns={columns}
|
columns={historyColumns}
|
||||||
dataSource={setpoints}
|
dataSource={setpoints}
|
||||||
onRowAdd={onAdd}
|
|
||||||
onRowEdit={onEdit}
|
|
||||||
onRowDelete={onDelete}
|
|
||||||
pagination={false}
|
pagination={false}
|
||||||
style={{ margin: '10px 0' }}
|
|
||||||
/>
|
|
||||||
Комментарий:
|
|
||||||
<Input.TextArea
|
|
||||||
rows={4}
|
|
||||||
onChange={(e) => setComment(e.value)}
|
|
||||||
value={comment}
|
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</LoaderPortal>
|
</LoaderPortal>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<SetpointSender
|
||||||
|
idWell={idWell}
|
||||||
|
setpointNames={setpointNames}
|
||||||
|
visible={isSenderVisible}
|
||||||
|
onClose={onSenderClose}
|
||||||
|
/>
|
||||||
|
<SetpointViewer
|
||||||
|
setpointNames={setpointNames}
|
||||||
|
setpoint={selected}
|
||||||
|
visible={isViewerVisible}
|
||||||
|
onClose={() => setIsViewerVisible(false)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user