forked from ddrilling/asb_cloud_front
Merge remote-tracking branch 'origin/dev' into DrillingModesPage
This commit is contained in:
commit
f9271b0f46
@ -32,7 +32,7 @@
|
|||||||
"react_test": "react-scripts test",
|
"react_test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
},
|
},
|
||||||
"proxy": "http://192.168.1.70:5000",
|
"proxy": "http://192.168.1.58:5000",
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"react-app",
|
"react-app",
|
||||||
|
7
src/components/ErrorFetch.js
Normal file
7
src/components/ErrorFetch.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export class ErrorFetch extends Error {
|
||||||
|
constructor(status, message) {
|
||||||
|
super(message);
|
||||||
|
this.name = "ErrorFetch"
|
||||||
|
this.status = status
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import { ReactNode } from 'react'
|
import { ReactNode } from 'react'
|
||||||
|
import { makeNumericSorter, makeStringSorter} from './sorters'
|
||||||
|
export { makeDateSorter, makeNumericSorter, makeStringSorter} from './sorters'
|
||||||
export { Table } from 'antd'
|
export { Table } from 'antd'
|
||||||
export { EditableTable } from './EditableTable'
|
export { EditableTable } from './EditableTable'
|
||||||
export { DatePickerWrapper } from './DatePickerWrapper'
|
export { DatePickerWrapper } from './DatePickerWrapper'
|
||||||
@ -7,10 +9,28 @@ export { SelectFromDictionary } from './SelectFromDictionary'
|
|||||||
export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/
|
export const RegExpIsFloat = /^[-+]?\d+\.?\d*$/
|
||||||
export const formatDate='YYYY.MM.DD HH:mm'
|
export const formatDate='YYYY.MM.DD HH:mm'
|
||||||
|
|
||||||
export const numericColumnOptions = {
|
export const makeNumericRender = (fixed?:number) => (value: any, row: object): ReactNode => {
|
||||||
|
const placeholder = '-'
|
||||||
|
let val = placeholder
|
||||||
|
if((value !== null) ||
|
||||||
|
(value !== undefined) ||
|
||||||
|
Number.isNaN(value) ||
|
||||||
|
!Number.isFinite(value)){
|
||||||
|
val = !!fixed
|
||||||
|
? (+value).toFixed(fixed)
|
||||||
|
: (+value).toPrecision(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<div className='text-align-r-container'>
|
||||||
|
<span>{val}</span>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const makeNumericColumnOptions = (fixed?:number, sorterKey?:string ) => ({
|
||||||
editable: true,
|
editable: true,
|
||||||
initialValue: 0,
|
initialValue: 0,
|
||||||
width:100,
|
width:100,
|
||||||
|
sorter: sorterKey? makeNumericSorter(sorterKey) : null,
|
||||||
formItemRules: [
|
formItemRules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@ -18,7 +38,8 @@ export const numericColumnOptions = {
|
|||||||
pattern: RegExpIsFloat,
|
pattern: RegExpIsFloat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
render: makeNumericRender(fixed),
|
||||||
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
other - объект с дополнительными свойствами колонки
|
other - объект с дополнительными свойствами колонки
|
||||||
@ -78,41 +99,6 @@ export const makeColumnsPlanFact = (title:string | ReactNode, key:string|string[
|
|||||||
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
|
export const makeFilterTextMatch = (key: string | number) => (filterValue: string | number, dataItem: any) =>
|
||||||
dataItem[key] === filterValue
|
dataItem[key] === filterValue
|
||||||
|
|
||||||
export const makeNumericSorter = (key: string) => (a: any, b: any) => a[key] - b[key]
|
|
||||||
|
|
||||||
export const makeStringSorter = (key: string) => (a: any, b: any) =>
|
|
||||||
{
|
|
||||||
if(a == null && b == null)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if(a == null)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if(b == null)
|
|
||||||
return -1
|
|
||||||
|
|
||||||
let aValue = a[key]
|
|
||||||
let bValue = b[key]
|
|
||||||
|
|
||||||
for (let i = 0; i < a.length; i++) {
|
|
||||||
if (isNaN(aValue.charCodeAt(i)) || (aValue.charCodeAt(i) > bValue.charCodeAt(i)))
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if (aValue.charCodeAt(i) > bValue.charCodeAt(i))
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
export const makeDateSorter = (key: string) => (a: any, b: any) => {
|
|
||||||
const date = new Date(a[key])
|
|
||||||
|
|
||||||
if(Number.isNaN(date.getTime()))
|
|
||||||
throw new Error('Date column contains not date formatted string(s)')
|
|
||||||
|
|
||||||
return date.getTime() - new Date(b[key]).getTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
export const makeGroupColumn = (title: string, children: object[]) => ({
|
export const makeGroupColumn = (title: string, children: object[]) => ({
|
||||||
title: title,
|
title: title,
|
||||||
children: children,
|
children: children,
|
||||||
@ -135,17 +121,6 @@ export const makeTextColumn = (
|
|||||||
...other
|
...other
|
||||||
})
|
})
|
||||||
|
|
||||||
export const defaultNumericRender = (value: any, row: object) => {
|
|
||||||
const placeholder = '-'
|
|
||||||
if((value === null) ||
|
|
||||||
(value === undefined) ||
|
|
||||||
Number.isNaN(value) ||
|
|
||||||
!Number.isFinite(value))
|
|
||||||
return placeholder
|
|
||||||
|
|
||||||
return (+value).toPrecision(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const makeNumericColumn = (title: string, dataIndex: string,
|
export const makeNumericColumn = (title: string, dataIndex: string,
|
||||||
filters: object[], filterDelegate: (key: string | number) => any,
|
filters: object[], filterDelegate: (key: string | number) => any,
|
||||||
renderDelegate: (_: any, row: object) => any, width: string, other?: columnPropsOther) => ({
|
renderDelegate: (_: any, row: object) => any, width: string, other?: columnPropsOther) => ({
|
||||||
@ -156,7 +131,7 @@ export const makeNumericColumn = (title: string, dataIndex: string,
|
|||||||
onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
|
onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
|
||||||
sorter: makeNumericSorter(dataIndex),
|
sorter: makeNumericSorter(dataIndex),
|
||||||
width: width,
|
width: width,
|
||||||
render: renderDelegate??defaultNumericRender,
|
render: renderDelegate??makeNumericRender(),
|
||||||
align: 'right',
|
align: 'right',
|
||||||
...other
|
...other
|
||||||
})
|
})
|
33
src/components/Table/sorters.ts
Normal file
33
src/components/Table/sorters.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
export const makeNumericSorter = (key: string) => (a: any, b: any) => a[key] - b[key];
|
||||||
|
|
||||||
|
export const makeStringSorter = (key: string) => (a: any, b: any) => {
|
||||||
|
if (a == null && b == null)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (a == null)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (b == null)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
let aValue = a[key];
|
||||||
|
let bValue = b[key];
|
||||||
|
|
||||||
|
for (let i = 0; i < a.length; i++) {
|
||||||
|
if (isNaN(aValue.charCodeAt(i)) || (aValue.charCodeAt(i) > bValue.charCodeAt(i)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (aValue.charCodeAt(i) > bValue.charCodeAt(i))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const makeDateSorter = (key: string) => (a: any, b: any) => {
|
||||||
|
const date = new Date(a[key]);
|
||||||
|
|
||||||
|
if (Number.isNaN(date.getTime()))
|
||||||
|
throw new Error('Date column contains not date formatted string(s)');
|
||||||
|
|
||||||
|
return date.getTime() - new Date(b[key]).getTime();
|
||||||
|
};
|
@ -2,19 +2,35 @@ import { Upload, Button } from 'antd'
|
|||||||
import { UploadOutlined } from '@ant-design/icons'
|
import { UploadOutlined } from '@ant-design/icons'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { upload } from './factory'
|
import { upload } from './factory'
|
||||||
|
import { ErrorFetch } from './ErrorFetch'
|
||||||
|
|
||||||
export default function UploadForm({url, accept, onUploadStart, onUploadComplete, onUploadError}) {
|
export const UploadForm = ({url, accept, style, formData, onUploadStart, onUploadSuccess, onUploadComplete, onUploadError}) => {
|
||||||
const [fileList, setfileList] = useState([])
|
const [fileList, setfileList] = useState([])
|
||||||
|
|
||||||
const handleFileSend = async (values) => {
|
const handleFileSend = async () => {
|
||||||
if(onUploadStart)
|
if(onUploadStart)
|
||||||
onUploadStart()
|
onUploadStart()
|
||||||
try {
|
try {
|
||||||
const formData = new FormData()
|
const formDataLocal = new FormData()
|
||||||
fileList.forEach((val) => {
|
fileList.forEach((val) => {
|
||||||
formData.append("files", val.originFileObj);
|
formDataLocal.append("files", val.originFileObj)
|
||||||
});
|
})
|
||||||
await upload(url, formData)
|
|
||||||
|
if(formData)
|
||||||
|
for(var propName in formData)
|
||||||
|
formDataLocal.append(propName, formData[propName])
|
||||||
|
|
||||||
|
const response = await upload(url, formDataLocal)
|
||||||
|
if(!response.ok)
|
||||||
|
{
|
||||||
|
const errorText = await response.text()
|
||||||
|
const error = new ErrorFetch(response.status, errorText)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(onUploadSuccess)
|
||||||
|
onUploadSuccess()
|
||||||
|
}
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
if(onUploadError)
|
if(onUploadError)
|
||||||
onUploadError(error)
|
onUploadError(error)
|
||||||
@ -27,7 +43,7 @@ export default function UploadForm({url, accept, onUploadStart, onUploadComplete
|
|||||||
|
|
||||||
const isSendButtonEnabled = fileList.length > 0
|
const isSendButtonEnabled = fileList.length > 0
|
||||||
return(
|
return(
|
||||||
<div style={{display: 'flex'}}>
|
<div style={{display: 'flex', ...style}}>
|
||||||
<Upload
|
<Upload
|
||||||
name ="file"
|
name ="file"
|
||||||
fileList={fileList}
|
fileList={fileList}
|
||||||
|
@ -18,7 +18,7 @@ export const UserView = ({user}) => {
|
|||||||
<GridItem row={2} col={1}>
|
<GridItem row={2} col={1}>
|
||||||
Фамилия:
|
Фамилия:
|
||||||
</GridItem>
|
</GridItem>
|
||||||
<GridItem row={3} col={2}>
|
<GridItem row={2} col={2}>
|
||||||
{user?.surname}
|
{user?.surname}
|
||||||
</GridItem>
|
</GridItem>
|
||||||
<GridItem row={3} col={1}>
|
<GridItem row={3} col={1}>
|
||||||
|
@ -81,13 +81,14 @@ export const download = async (url:string, fileName?:string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const upload = async (url:string, formData: FormData) => {
|
export const upload = async (url:string, formData: FormData) => {
|
||||||
await fetch(url, {
|
let response = await fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'Bearer ' + localStorage['token']
|
Authorization: 'Bearer ' + localStorage['token']
|
||||||
},
|
},
|
||||||
method: 'Post',
|
method: 'Post',
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
export const downloadFile = async (fileInfo: FileInfoDto) => {
|
export const downloadFile = async (fileInfo: FileInfoDto) => {
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
Tooltip} from 'antd'
|
Tooltip} from 'antd'
|
||||||
import { DataService } from '../services/api'
|
import { TelemetryDataSaubService } from '../services/api'
|
||||||
import {generateUUID} from '../services/UidGenerator'
|
import {generateUUID} from '../services/UidGenerator'
|
||||||
import { ArchiveColumn } from '../components/ArchiveColumn'
|
import { ArchiveColumn } from '../components/ArchiveColumn'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
@ -94,7 +94,7 @@ export default function Archive({idWell}) {
|
|||||||
let startDate = rangeDate[0].toISOString()
|
let startDate = rangeDate[0].toISOString()
|
||||||
|
|
||||||
setLoader(true)
|
setLoader(true)
|
||||||
DataService.getData(idWell, startDate, interval, 2048)
|
TelemetryDataSaubService.getData(idWell, startDate, interval, 2048)
|
||||||
.then(handleReceiveDataSaub)
|
.then(handleReceiveDataSaub)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
notify(`Не удалось загрузить данные по скважине (${idWell}) c ${rangeDate[0]} по ${rangeDate[1]}`, 'error')
|
notify(`Не удалось загрузить данные по скважине (${idWell}) c ${rangeDate[0]} по ${rangeDate[1]}`, 'error')
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
makeNumericColumnPlanFact
|
makeNumericColumnPlanFact
|
||||||
} from "../../components/Table";
|
} from "../../components/Table";
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
||||||
import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
|
import ChartTvD from '../WellOperations/ChartTvD';
|
||||||
import WellOperationsTable from './WellOperationsTable'
|
import WellOperationsTable from './WellOperationsTable'
|
||||||
import {
|
import {
|
||||||
calcAndUpdateStatsBySections,
|
calcAndUpdateStatsBySections,
|
||||||
@ -249,10 +249,10 @@ export default function ClusterSections({ clusterData }) {
|
|||||||
width={1500}
|
width={1500}
|
||||||
footer={null}
|
footer={null}
|
||||||
>
|
>
|
||||||
<ChartDepthToDay
|
<ChartTvD
|
||||||
dataPlan={tvdDataPlan}
|
dataPlan={tvdDataPlan}
|
||||||
dataFact={tvdDataFact}
|
dataFact={tvdDataFact}
|
||||||
dataForecast={tvdDataForecast} />
|
dataPredict={tvdDataForecast} />
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -6,12 +6,11 @@ import {
|
|||||||
makeTextColumn,
|
makeTextColumn,
|
||||||
makeGroupColumn,
|
makeGroupColumn,
|
||||||
makeColumn,
|
makeColumn,
|
||||||
makeNumericColumnPlanFact,
|
makeDateSorter,
|
||||||
makeDateSorter
|
makeNumericColumnPlanFact} from "../../components/Table";
|
||||||
} from "../../components/Table";
|
|
||||||
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
|
import { calcAndUpdateStatsBySections, makeFilterMinMaxFunction } from "./functions";
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
||||||
import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
|
import ChartTvD from '../WellOperations/ChartTvD';
|
||||||
import WellOperationsTable from './WellOperationsTable'
|
import WellOperationsTable from './WellOperationsTable'
|
||||||
import { getOperations } from "./functions";
|
import { getOperations } from "./functions";
|
||||||
|
|
||||||
@ -206,10 +205,10 @@ useEffect(() => {
|
|||||||
width={1500}
|
width={1500}
|
||||||
footer={null}
|
footer={null}
|
||||||
>
|
>
|
||||||
<ChartDepthToDay
|
<ChartTvD
|
||||||
dataPlan={tvdDataPlan}
|
dataPlan={tvdDataPlan}
|
||||||
dataFact={tvdDataFact}
|
dataFact={tvdDataFact}
|
||||||
dataForecast={tvdDataForecast}
|
dataPredict={tvdDataForecast}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
@ -6,17 +6,24 @@ const minPrefix = "isMin"
|
|||||||
export const getOperations = async (idWell) => {
|
export const getOperations = async (idWell) => {
|
||||||
const ops = await WellOperationStatService.getTvd(idWell);
|
const ops = await WellOperationStatService.getTvd(idWell);
|
||||||
|
|
||||||
const planData = ops.map(el => {
|
const convert = wellOperationDto =>
|
||||||
return {key: el.plan?.id, depth: el.plan?.wellDepth, date: el.plan?.startDate}
|
({
|
||||||
}).filter(el => el.key)
|
key: wellOperationDto?.id,
|
||||||
|
depth: wellOperationDto?.depthStart,
|
||||||
|
date: wellOperationDto?.dateStart
|
||||||
|
})
|
||||||
|
|
||||||
const factData = ops.map(el => {
|
const planData = ops
|
||||||
return {key: el.fact?.id, depth: el.fact?.wellDepth, date: el.fact?.startDate}
|
.map(item => convert(item.plan))
|
||||||
}).filter(el => el.key)
|
.filter(el => el.key)
|
||||||
|
|
||||||
const predictData = ops.map(el => {
|
const factData = ops
|
||||||
return {key: el.predict?.id, depth: el.predict?.wellDepth, date: el.predict?.startDate}
|
.map(item => convert(item.fact))
|
||||||
}).filter(el => el.key)
|
.filter(el => el.key)
|
||||||
|
|
||||||
|
const predictData = ops
|
||||||
|
.map(item => convert(item.predict))
|
||||||
|
.filter(el => el.key)
|
||||||
|
|
||||||
return { operations: ops, plan: planData, fact: factData, predict: predictData }
|
return { operations: ops, plan: planData, fact: factData, predict: predictData }
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
formatBytes,
|
formatBytes,
|
||||||
} from "../../components/factory"
|
} from "../../components/factory"
|
||||||
import { EditableTable, makePaginationObject } from "../../components/Table"
|
import { EditableTable, makePaginationObject } from "../../components/Table"
|
||||||
import UploadForm from "../../components/UploadForm"
|
import {UploadForm} from "../../components/UploadForm"
|
||||||
import LoaderPortal from "../../components/LoaderPortal"
|
import LoaderPortal from "../../components/LoaderPortal"
|
||||||
import {UserView} from '../../components/UserView'
|
import {UserView} from '../../components/UserView'
|
||||||
import {CompanyView} from '../../components/CompanyView'
|
import {CompanyView} from '../../components/CompanyView'
|
||||||
|
@ -1,54 +1,198 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Table, Button, Modal } from 'antd'
|
import { Button, Form, Input, Popconfirm, Timeline } from 'antd'
|
||||||
import { HourglassOutlined } from '@ant-design/icons'
|
import moment from 'moment'
|
||||||
|
import { CheckSquareOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
SaveOutlined,
|
||||||
|
PlusOutlined,
|
||||||
|
CloseCircleOutlined,
|
||||||
|
DeleteOutlined } from '@ant-design/icons'
|
||||||
|
import { View } from './View'
|
||||||
import LoaderPortal from '../../components/LoaderPortal'
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
|
||||||
import { MeasureService } from '../../services/api'
|
import { MeasureService } from '../../services/api'
|
||||||
import { Editor } from './Editor'
|
import '../../styles/index.css'
|
||||||
|
import '../../styles/measure.css'
|
||||||
|
|
||||||
export const MeasureTable = ({idWell, idCategory, title, columns}) => {
|
const format='YYYY.MM.DD HH:mm'
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
|
||||||
const [showEditor, setShowEditor] = useState(false)
|
|
||||||
const [lastData, setLastData] = useState({})
|
|
||||||
|
|
||||||
const update = ()=>invokeWebApiWrapperAsync(async()=>{
|
export const MeasureTable = ({idWell, idCategory, title, columns, values, updateMeasuresFunc}) => {
|
||||||
const data = await MeasureService.getLast(idWell, idCategory)
|
|
||||||
setLastData(data)
|
const [showLoader, setShowLoader] = useState(false);
|
||||||
|
const [displayedValues, setDisplayedValues] = useState({});
|
||||||
|
const [editingColumns, setEditingColumns] = useState(columns);
|
||||||
|
const [isTableEditing, setIsTableEditing] = useState(false);
|
||||||
|
const [editingActionName, setEditingActionName] = useState('');
|
||||||
|
|
||||||
|
const [measuresForm] = Form.useForm();
|
||||||
|
|
||||||
|
const createEditingColumns = (cols, renderDelegate) =>
|
||||||
|
cols.map(col =>
|
||||||
|
({ render: renderDelegate,
|
||||||
|
...col
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const defaultValuesToDisplay = values[values.length-1]
|
||||||
|
|
||||||
|
setDisplayedValues(defaultValuesToDisplay)
|
||||||
|
}, [values])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let switchableColumns = []
|
||||||
|
|
||||||
|
isTableEditing
|
||||||
|
? switchableColumns = createEditingColumns(columns, () => <Input className='w-100 measure-input' />)
|
||||||
|
: switchableColumns = createEditingColumns(columns, null)
|
||||||
|
|
||||||
|
if(editingActionName === 'edit')
|
||||||
|
measuresForm.setFieldsValue(displayedValues?.data);
|
||||||
|
else if(editingActionName === 'add')
|
||||||
|
measuresForm.resetFields()
|
||||||
|
|
||||||
|
setEditingColumns(switchableColumns)
|
||||||
|
}, [isTableEditing, columns, editingActionName, displayedValues?.data, measuresForm])
|
||||||
|
|
||||||
|
const markMeasuresAsDeleted = async () => {
|
||||||
|
setShowLoader(true)
|
||||||
|
await MeasureService.markAsDelete(idWell, displayedValues.id)
|
||||||
|
updateMeasuresFunc()
|
||||||
|
setShowLoader(false)
|
||||||
}
|
}
|
||||||
, setShowLoader
|
|
||||||
, "не удалось загрузить")
|
|
||||||
|
|
||||||
useEffect(update, [idWell, idCategory])
|
const checkIsDataDefault = () =>
|
||||||
|
displayedValues?.isDefaultData ? true : false
|
||||||
|
|
||||||
const timestamp = lastData ? new Date(lastData?.timestamp).toLocaleString() : '-'
|
const crudButtons =
|
||||||
|
<div className='w-300px mt-8px'>
|
||||||
return <LoaderPortal show={showLoader}>
|
|
||||||
<h3>{title}</h3>
|
|
||||||
<span>Дата: {timestamp}</span>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowEditor(true)}
|
key='add'
|
||||||
icon={<HourglassOutlined/>}>История</Button>
|
className='w-33'
|
||||||
<Table
|
onClick={() => {
|
||||||
style={{marginTop:16}}
|
setEditingActionName('add')
|
||||||
bordered
|
setIsTableEditing(true)
|
||||||
dataSource = {[lastData?.data]}
|
}}
|
||||||
columns = {columns}
|
|
||||||
scroll={{ x: 400, y: 600 }}/>
|
|
||||||
<Modal
|
|
||||||
title={title}
|
|
||||||
centered
|
|
||||||
visible={showEditor}
|
|
||||||
onOk={() => setShowEditor(false)}
|
|
||||||
onCancel={() => setShowEditor(false)}
|
|
||||||
width="95%"
|
|
||||||
footer={null}
|
|
||||||
>
|
>
|
||||||
<Editor
|
<PlusOutlined />
|
||||||
idWell={idWell}
|
</Button>
|
||||||
idCategory={idCategory}
|
<Button
|
||||||
columns = {columns}
|
key='edit'
|
||||||
onUpdate={update}/>
|
className='w-33'
|
||||||
</Modal>
|
onClick={() => {
|
||||||
|
setEditingActionName('edit')
|
||||||
|
setIsTableEditing(true)
|
||||||
|
}}
|
||||||
|
disabled={checkIsDataDefault()}
|
||||||
|
>
|
||||||
|
<EditOutlined />
|
||||||
|
</Button>
|
||||||
|
<Popconfirm
|
||||||
|
title="Удалить данные?"
|
||||||
|
onConfirm={() => markMeasuresAsDeleted()}
|
||||||
|
disabled={checkIsDataDefault()}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
key='delete'
|
||||||
|
onClick={() => {
|
||||||
|
setEditingActionName('delete')
|
||||||
|
}}
|
||||||
|
disabled={checkIsDataDefault()}
|
||||||
|
>
|
||||||
|
<DeleteOutlined style={{margin:'auto 28px'}}/>
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
const confirmButtons =
|
||||||
|
<div className='w-300px mt-8px'>
|
||||||
|
<div className='d-flex'>
|
||||||
|
<Button
|
||||||
|
key='confirm'
|
||||||
|
className='w-50'
|
||||||
|
onClick={() => { measuresForm.submit() }}
|
||||||
|
>
|
||||||
|
<SaveOutlined />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
key='decline'
|
||||||
|
className='w-50'
|
||||||
|
onClick={()=> setIsTableEditing(false)}
|
||||||
|
>
|
||||||
|
<CloseCircleOutlined />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
let handleSubmitMeasuresForm = async (formData) => {
|
||||||
|
measuresForm.validateFields()
|
||||||
|
|
||||||
|
const measureParams = {
|
||||||
|
idWell: idWell,
|
||||||
|
idCategory: idCategory,
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
data: formData
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowLoader(true)
|
||||||
|
|
||||||
|
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(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
|
||||||
|
<h2>{title}</h2>
|
||||||
|
|
||||||
|
<div className='d-flex'>
|
||||||
|
<div className='flex-direction-column'>
|
||||||
|
<div className='measure-buttons-container'>
|
||||||
|
{isTableEditing
|
||||||
|
? confirmButtons
|
||||||
|
: crudButtons
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='measure-dates mt-20px'>
|
||||||
|
<Timeline className='mt-12px ml-10px'>
|
||||||
|
{values.map((item, index) =>
|
||||||
|
<Timeline.Item
|
||||||
|
key={index}
|
||||||
|
className='measure-button'
|
||||||
|
onClick={() => setDisplayedValues(item)}
|
||||||
|
dot={item?.id === displayedValues?.id
|
||||||
|
? <CheckSquareOutlined className="timeline-clock-icon" />
|
||||||
|
: null}
|
||||||
|
>
|
||||||
|
<span className={item?.id === displayedValues?.id ? 'selected-timeline' : ''}>
|
||||||
|
{item.timestamp ? moment.utc(item.timestamp).local().format(format) : 'Нет данных'}
|
||||||
|
</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>
|
</LoaderPortal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
}
|
}
|
@ -1,48 +1,40 @@
|
|||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { Button, Modal, Timeline } from 'antd'
|
import { Table, Button, Modal } from 'antd'
|
||||||
import moment from 'moment'
|
|
||||||
import { HourglassOutlined } from '@ant-design/icons'
|
import { HourglassOutlined } from '@ant-design/icons'
|
||||||
import LoaderPortal from '../../components/LoaderPortal'
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
import { MeasureService } from '../../services/api'
|
import { MeasureService } from '../../services/api'
|
||||||
import { Editor } from './Editor'
|
import { Editor } from './Editor'
|
||||||
import TimelineItem from 'antd/lib/timeline/TimelineItem'
|
|
||||||
//import { View } from './View'
|
|
||||||
|
|
||||||
const format='YYYY.MM.DD HH:mm'
|
export const MeasureTable = ({idWell, idCategory, title, columns}) => {
|
||||||
|
|
||||||
export const MeasureTable2 = ({idWell, idCategory, title, columns}) => {
|
|
||||||
const [showLoader, setShowLoader] = useState(false)
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
const [showEditor, setShowEditor] = useState(false)
|
const [showEditor, setShowEditor] = useState(false)
|
||||||
const [history, setHistory] = useState([])
|
const [lastData, setLastData] = useState({})
|
||||||
|
|
||||||
const update = () => invokeWebApiWrapperAsync(async()=>{
|
const update = ()=>invokeWebApiWrapperAsync(async()=>{
|
||||||
const data = await MeasureService.getHisory(idWell, idCategory)
|
const data = await MeasureService.getLast(idWell, idCategory)
|
||||||
const story = data?.map( i=> ({
|
setLastData(data)
|
||||||
id: i.id,
|
|
||||||
idWell: i.idWell,
|
|
||||||
idCategory: i.idCategory,
|
|
||||||
timestamp: moment.utc(i.timestamp).local().format(format),
|
|
||||||
...i.data}))
|
|
||||||
setHistory(story??[])
|
|
||||||
}
|
}
|
||||||
, setShowLoader
|
, setShowLoader
|
||||||
, "не удалось загрузить")
|
, "не удалось загрузить")
|
||||||
|
|
||||||
useEffect(update, [idWell, idCategory])
|
useEffect(update, [idWell, idCategory])
|
||||||
|
|
||||||
|
const timestamp = lastData ? new Date(lastData?.timestamp).toLocaleString() : '-'
|
||||||
|
|
||||||
return <LoaderPortal show={showLoader}>
|
return <LoaderPortal show={showLoader}>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
|
<span>Дата: {timestamp}</span>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setShowEditor(true)}
|
onClick={() => setShowEditor(true)}
|
||||||
icon={<HourglassOutlined/>}>История</Button>
|
icon={<HourglassOutlined/>}>История</Button>
|
||||||
<Timeline>
|
<Table
|
||||||
{history.map(item=><TimelineItem value={item}>{item.timestamp}</TimelineItem>)}
|
style={{marginTop:16}}
|
||||||
</Timeline>
|
bordered
|
||||||
{/* <View
|
dataSource = {[lastData?.data]}
|
||||||
item = {lastData?.data}
|
columns = {columns}
|
||||||
columns = {columns}/> */}
|
scroll={{ x: 400, y: 600 }}/>
|
||||||
<Modal
|
<Modal
|
||||||
title={title}
|
title={title}
|
||||||
centered
|
centered
|
@ -1,38 +1,62 @@
|
|||||||
import { Empty } from 'antd';
|
import { Empty, Form } from 'antd';
|
||||||
import {Grid, GridItem} from '../../components/Grid'
|
import {Grid, GridItem} from '../../components/Grid'
|
||||||
|
import '../../styles/index.css'
|
||||||
|
|
||||||
|
const renderSwitchableColumn = (column, itm) => {
|
||||||
|
if(column.render) {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
key={column.dataIndex}
|
||||||
|
name={column.dataIndex}
|
||||||
|
style={{margin: 0}}
|
||||||
|
//rules={column.formItemRules}
|
||||||
|
>
|
||||||
|
{column.render(itm[column.dataIndex])}
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <p key={column.title} className='m-5px'>{itm[column.dataIndex]}</p>
|
||||||
|
}
|
||||||
|
|
||||||
export const View = ({columns, item}) => {
|
export const View = ({columns, item}) => {
|
||||||
if (!item || !columns?.length)
|
if (!item || !columns?.length)
|
||||||
return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
|
return <Empty key='empty' image={Empty.PRESENTED_IMAGE_SIMPLE}/>
|
||||||
|
|
||||||
const colsCount = 3
|
const colsCount = 3
|
||||||
const viewItems = columns.map( (column, i) => {
|
const viewItems = columns.map( (column, i) => {
|
||||||
const row = Math.floor(i / colsCount) + 1
|
const row = Math.floor(i / colsCount) + 1
|
||||||
const colb = i % colsCount
|
const colb = i % colsCount
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<GridItem
|
<GridItem
|
||||||
|
key={column.dataIndex}
|
||||||
row={row}
|
row={row}
|
||||||
col={colb*2 + 1}
|
col={colb*2 + 1}
|
||||||
background='#00000005'
|
style={{border:'1px solid lightgrey'}}
|
||||||
border='1px solid #FFFE'
|
|
||||||
>
|
>
|
||||||
{column.title}
|
{column.title}
|
||||||
|
|
||||||
</GridItem>
|
</GridItem>
|
||||||
|
|
||||||
<GridItem
|
<GridItem
|
||||||
|
key={column.title}
|
||||||
row={row}
|
row={row}
|
||||||
col={colb*2 + 2}
|
col={colb*2 + 2}
|
||||||
border='1px solid rgba(0, 0, 0, 0.05)'
|
style={{border:'1px solid lightgrey',
|
||||||
justifyContect='right'
|
justifyContent:'right',
|
||||||
marginRight='16px'
|
marginRight:'16px',
|
||||||
fontWeight='bold'
|
fontWeight:'bold',
|
||||||
textAlign='right'>
|
textAlign:'right',
|
||||||
{column.render ? column.render(item[column.dataIndex]) : item[column.dataIndex]}
|
padding: 0}}
|
||||||
|
>
|
||||||
|
{renderSwitchableColumn(column, item)}
|
||||||
</GridItem>
|
</GridItem>
|
||||||
</>
|
</>
|
||||||
})
|
})
|
||||||
|
|
||||||
return <Grid>
|
return <>
|
||||||
|
<Grid>
|
||||||
{viewItems}
|
{viewItems}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
</>
|
||||||
}
|
}
|
@ -42,4 +42,10 @@ export const numericColumnOptions = {
|
|||||||
export const textColumnOptions = {
|
export const textColumnOptions = {
|
||||||
editable:true,
|
editable:true,
|
||||||
input:<TextArea/>,
|
input:<TextArea/>,
|
||||||
width:'20rem'}
|
width:'20rem',
|
||||||
|
formItemRules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: `Введите текст`
|
||||||
|
},
|
||||||
|
],}
|
@ -1,39 +0,0 @@
|
|||||||
import {makeColumn} from '../../components/Table'
|
|
||||||
import {v, numericColumnOptions, textColumnOptions} from './columnsCommon'
|
|
||||||
|
|
||||||
export const columnsMudDiagram = [
|
|
||||||
makeColumn(v('N пробы'), 'probeNumber', numericColumnOptions),
|
|
||||||
makeColumn(v('Глубина отбора пробы'), 'probeExtractionDepth', numericColumnOptions),
|
|
||||||
{
|
|
||||||
title: 'Литология',
|
|
||||||
key: 'lithology',
|
|
||||||
children: [
|
|
||||||
makeColumn(v('Песчаник (%)'), 'sandstone', numericColumnOptions),
|
|
||||||
makeColumn(v('Алевролит (%)'), 'siltstone', numericColumnOptions),
|
|
||||||
makeColumn(v('Аргиллит (%)'), 'argillit', numericColumnOptions),
|
|
||||||
makeColumn(v('Аргиллит бит. (%)'), 'brokenArgillit', numericColumnOptions),
|
|
||||||
makeColumn(v('Уголь (%)'), 'coal', numericColumnOptions),
|
|
||||||
makeColumn(v('Песок (%)'), 'sand', numericColumnOptions),
|
|
||||||
makeColumn(v('Глина (%)'), 'clay', numericColumnOptions),
|
|
||||||
makeColumn(v('Известняк (%)'), 'camstone', numericColumnOptions),
|
|
||||||
makeColumn(v('Цемент (%)'), 'cement', numericColumnOptions),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
makeColumn('Краткое описание', 'summary', textColumnOptions),
|
|
||||||
makeColumn(v('ЛБА бурового раствора'), 'drillingMud', numericColumnOptions),
|
|
||||||
makeColumn(v('ЛБА (шлама)'), 'sludge', numericColumnOptions),
|
|
||||||
{
|
|
||||||
title: 'Газопоказания',
|
|
||||||
key: 'gasIndications',
|
|
||||||
children: [
|
|
||||||
makeColumn(v('Сумма УВ мах. (абс%)'), 'maxSum', numericColumnOptions),
|
|
||||||
makeColumn(v('С1 метан (отн%)'), 'methane', numericColumnOptions),
|
|
||||||
makeColumn(v('С2 этан (отн%)'), 'ethane', numericColumnOptions),
|
|
||||||
makeColumn(v('С3 пропан (отн%)'), 'propane', numericColumnOptions),
|
|
||||||
makeColumn(v('С4 бутан (отн%)'), 'butane', numericColumnOptions),
|
|
||||||
makeColumn(v('С5 пентан (отн%)'), 'pentane', numericColumnOptions),
|
|
||||||
]
|
|
||||||
},
|
|
||||||
makeColumn(v('Мех. скорость'), 'mechanicalSpeed', numericColumnOptions),
|
|
||||||
makeColumn('Предварительное заключение о насыщении по ГК', 'preliminaryConclusion', textColumnOptions),
|
|
||||||
]
|
|
@ -31,3 +31,40 @@ export const columnsDrillingFluid = [
|
|||||||
makeColumn(v("Смазка, %"), "grease",numericColumnOptions),
|
makeColumn(v("Смазка, %"), "grease",numericColumnOptions),
|
||||||
makeColumn(v("Карбонат кальция, кг/м³"), "calciumCarbonate",numericColumnOptions),
|
makeColumn(v("Карбонат кальция, кг/м³"), "calciumCarbonate",numericColumnOptions),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const drillingFluidDefaultData = {
|
||||||
|
idWell: 0,
|
||||||
|
key: 'drillingFluidDefaultData',
|
||||||
|
idCategory: 0,
|
||||||
|
isDefaultData: true,
|
||||||
|
data: {
|
||||||
|
"name": 0,
|
||||||
|
"temperature": 0,
|
||||||
|
"density": 0,
|
||||||
|
"conditionalViscosity": 0,
|
||||||
|
"r300": 0,
|
||||||
|
"r600": 0,
|
||||||
|
"r3r6": 0,
|
||||||
|
"dnsDpa": 0,
|
||||||
|
"plasticViscocity": 0,
|
||||||
|
"snsDpa": 0,
|
||||||
|
"r3r649С": 0,
|
||||||
|
"dns49Cdpa": 0,
|
||||||
|
"plasticViscocity49c": 0,
|
||||||
|
"sns49Cdpa": 0,
|
||||||
|
"mbt": 0,
|
||||||
|
"sand": 0,
|
||||||
|
"filtering": 0,
|
||||||
|
"crust": 0,
|
||||||
|
"ktk": 0,
|
||||||
|
"ph": 0,
|
||||||
|
"hardness": 0,
|
||||||
|
"chlorides": 0,
|
||||||
|
"pf": 0,
|
||||||
|
"mf": 0,
|
||||||
|
"pm": 0,
|
||||||
|
"fluidSolidPhase": 0,
|
||||||
|
"grease": 0,
|
||||||
|
"calciumCarbonate": 0
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,64 @@
|
|||||||
import { columnsMudDiagram} from './columnsMudDiagram'
|
import { useState, useEffect } from 'react'
|
||||||
import { columnsDrillingFluid} from './columnsDrillingFluid'
|
import { columnsMudDiagram} from './mudDiagramData'
|
||||||
import { columnsNnb } from './columnsNnb'
|
import { mudDiagramDefaultData} from './mudDiagramData'
|
||||||
|
import { columnsDrillingFluid} from './drillingFluidData'
|
||||||
|
import { drillingFluidDefaultData} from './drillingFluidData'
|
||||||
|
import { columnsNnb } from './nnbData'
|
||||||
|
import { nnbDefaultData } from './nnbData'
|
||||||
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
|
import { MeasureService } from '../../services/api'
|
||||||
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import { MeasureTable } from './MeasureTable'
|
import { MeasureTable } from './MeasureTable'
|
||||||
//import { MeasureTable2 } from './MeasureTable2'
|
|
||||||
|
|
||||||
export default function Measure({idWell}){
|
export default function Measure({idWell}){
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
const [fluidValues, setFluidValues] = useState([])
|
||||||
|
const [mudValues, setMudValues] = useState([])
|
||||||
|
const [nnbValues, setNnbValues] = useState([])
|
||||||
|
const [isMeasuresUpdating, setIsMeasuresUpdating] = useState(false)
|
||||||
|
|
||||||
|
const updateCurrentValues = () => invokeWebApiWrapperAsync(async()=>{
|
||||||
|
const measures = await MeasureService.getHisory(idWell)
|
||||||
|
setIsMeasuresUpdating(false)
|
||||||
|
|
||||||
|
const fluids = measures.filter(el => el.idCategory === 1)
|
||||||
|
setFluidValues(fluids.length ? fluids : [drillingFluidDefaultData])
|
||||||
|
const muds = measures.filter(el => el.idCategory === 2)
|
||||||
|
setMudValues(muds.length ? muds : [mudDiagramDefaultData])
|
||||||
|
const nnbs = measures.filter(el => el.idCategory === 3)
|
||||||
|
setNnbValues(nnbs.length ? nnbs : [nnbDefaultData])
|
||||||
|
}
|
||||||
|
,setShowLoader
|
||||||
|
,`Не удалось загрузить последние данные по скважине ${idWell}`)
|
||||||
|
|
||||||
|
useEffect(updateCurrentValues, [idWell, isMeasuresUpdating])
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
<MeasureTable
|
<MeasureTable
|
||||||
idWell={idWell}
|
idWell={idWell}
|
||||||
idCategory={1}
|
idCategory={1}
|
||||||
title='Замер бурового раствора'
|
title='Замер бурового раствора'
|
||||||
columns={columnsDrillingFluid}/>
|
columns={columnsDrillingFluid}
|
||||||
|
values={fluidValues}
|
||||||
|
updateMeasuresFunc = {() => setIsMeasuresUpdating(true)}
|
||||||
|
/>
|
||||||
<MeasureTable
|
<MeasureTable
|
||||||
idWell={idWell}
|
idWell={idWell}
|
||||||
idCategory={2}
|
idCategory={2}
|
||||||
title='Шламограмма'
|
title='Шламограмма'
|
||||||
columns={columnsMudDiagram}/>
|
columns={columnsMudDiagram}
|
||||||
|
values={mudValues}
|
||||||
|
updateMeasuresFunc = {() => setIsMeasuresUpdating(true)}
|
||||||
|
/>
|
||||||
<MeasureTable
|
<MeasureTable
|
||||||
idWell={idWell}
|
idWell={idWell}
|
||||||
idCategory={3}
|
idCategory={3}
|
||||||
title='ННБ'
|
title='ННБ'
|
||||||
columns={columnsNnb}/>
|
columns={columnsNnb}
|
||||||
|
values={nnbValues}
|
||||||
|
updateMeasuresFunc = {() => setIsMeasuresUpdating(true)}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
58
src/pages/Measure/mudDiagramData.js
Normal file
58
src/pages/Measure/mudDiagramData.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import {makeColumn} from '../../components/Table'
|
||||||
|
import {v, numericColumnOptions, textColumnOptions} from './columnsCommon'
|
||||||
|
|
||||||
|
export const columnsMudDiagram = [
|
||||||
|
makeColumn(v('N пробы'), 'probeNumber', numericColumnOptions),
|
||||||
|
makeColumn(v('Глубина отбора пробы'), 'probeExtractionDepth', numericColumnOptions),
|
||||||
|
makeColumn(v('Песчаник (%)'), 'sandstone', numericColumnOptions),
|
||||||
|
makeColumn(v('Алевролит (%)'), 'siltstone', numericColumnOptions),
|
||||||
|
makeColumn(v('Аргиллит (%)'), 'argillit', numericColumnOptions),
|
||||||
|
makeColumn(v('Аргиллит бит. (%)'), 'brokenArgillit', numericColumnOptions),
|
||||||
|
makeColumn(v('Уголь (%)'), 'coal', numericColumnOptions),
|
||||||
|
makeColumn(v('Песок (%)'), 'sand', numericColumnOptions),
|
||||||
|
makeColumn(v('Глина (%)'), 'clay', numericColumnOptions),
|
||||||
|
makeColumn(v('Известняк (%)'), 'camstone', numericColumnOptions),
|
||||||
|
makeColumn(v('Цемент (%)'), 'cement', numericColumnOptions),
|
||||||
|
makeColumn('Краткое описание', 'summary', textColumnOptions),
|
||||||
|
makeColumn(v('ЛБА бурового раствора'), 'drillingMud', numericColumnOptions),
|
||||||
|
makeColumn(v('ЛБА (шлама)'), 'sludge', numericColumnOptions),
|
||||||
|
makeColumn(v('Сумма УВ мах. (абс%)'), 'maxSum', numericColumnOptions),
|
||||||
|
makeColumn(v('С1 метан (отн%)'), 'methane', numericColumnOptions),
|
||||||
|
makeColumn(v('С2 этан (отн%)'), 'ethane', numericColumnOptions),
|
||||||
|
makeColumn(v('С3 пропан (отн%)'), 'propane', numericColumnOptions),
|
||||||
|
makeColumn(v('С4 бутан (отн%)'), 'butane', numericColumnOptions),
|
||||||
|
makeColumn(v('С5 пентан (отн%)'), 'pentane', numericColumnOptions),
|
||||||
|
makeColumn(v('Мех. скорость'), 'mechanicalSpeed', numericColumnOptions),
|
||||||
|
makeColumn('Предварительное заключение о насыщении по ГК', 'preliminaryConclusion', textColumnOptions),
|
||||||
|
]
|
||||||
|
|
||||||
|
export const mudDiagramDefaultData = {
|
||||||
|
idWell: 0,
|
||||||
|
key: 'mudDiagramDefaultData',
|
||||||
|
idCategory: 0,
|
||||||
|
isDefaultData: true,
|
||||||
|
data: {
|
||||||
|
"probeNumber": 0,
|
||||||
|
"probeExtractionDepth": 0,
|
||||||
|
"sandstone": 0,
|
||||||
|
"siltstone": 0,
|
||||||
|
"argillit": 0,
|
||||||
|
"brokenArgillit": 0,
|
||||||
|
"coal": 0,
|
||||||
|
"sand": 0,
|
||||||
|
"clay": 0,
|
||||||
|
"camstone": 0,
|
||||||
|
"cement": 0,
|
||||||
|
"summary": '-',
|
||||||
|
"drillingMud": 0,
|
||||||
|
"sludge": 0,
|
||||||
|
"maxSum": 0,
|
||||||
|
"methane": 0,
|
||||||
|
"ethane": 0,
|
||||||
|
"propane": 0,
|
||||||
|
"butane": 0,
|
||||||
|
"pentane": 0,
|
||||||
|
"mechanicalSpeed": 0,
|
||||||
|
"preliminaryConclusion": '-'
|
||||||
|
}
|
||||||
|
}
|
@ -20,3 +20,29 @@ export const columnsNnb = [
|
|||||||
makeColumn(v('Разница вертикальных глубин\nмежду планом и фактом'), 'depthPlanFactDifference', numericColumnOptions),
|
makeColumn(v('Разница вертикальных глубин\nмежду планом и фактом'), 'depthPlanFactDifference', numericColumnOptions),
|
||||||
makeColumn(v('Расстояние в пространстве\nмежду планом и фактом'), 'distancePlanFactDifference', numericColumnOptions),
|
makeColumn(v('Расстояние в пространстве\nмежду планом и фактом'), 'distancePlanFactDifference', numericColumnOptions),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const nnbDefaultData = {
|
||||||
|
idWell: 0,
|
||||||
|
key: 'nnbDefaultData',
|
||||||
|
idCategory: 0,
|
||||||
|
isDefaultData: true,
|
||||||
|
data: {
|
||||||
|
"depth": 0,
|
||||||
|
"zenithAngle": 0,
|
||||||
|
"magneticAzimuth": 0,
|
||||||
|
"trueAzimuth": 0,
|
||||||
|
"directAzimuth": 0,
|
||||||
|
"verticalDepth": 0,
|
||||||
|
"absoluteMark": 0,
|
||||||
|
"localNorthOffset": 0,
|
||||||
|
"localEastOffset": 0,
|
||||||
|
"outFallOffset": 0,
|
||||||
|
"offsetAzimuth": 0,
|
||||||
|
"areaIntensity": '-',
|
||||||
|
"offsetStopAngle": 0,
|
||||||
|
"zenithIntensity": 0,
|
||||||
|
"comment": '-',
|
||||||
|
"depthPlanFactDifference": 0,
|
||||||
|
"distancePlanFactDifference": 0
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
import { Table, makeDateSorter, makeNumericSorter, formatDate} from "../../components/Table"
|
import { Table, formatDate, makeDateSorter, makeNumericSorter} from "../../components/Table"
|
||||||
import { Button, Tooltip } from "antd"
|
import { Button, Tooltip } from "antd"
|
||||||
import { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons'
|
import { FilePdfOutlined, FileTextOutlined} from '@ant-design/icons'
|
||||||
import { ReportService } from "../../services/api"
|
import { ReportService } from "../../services/api"
|
||||||
|
@ -46,7 +46,7 @@ export default function Well() {
|
|||||||
<Link to={`${rootPath}/report`}>Рапорт</Link>
|
<Link to={`${rootPath}/report`}>Рапорт</Link>
|
||||||
</PrivateMenuItem>
|
</PrivateMenuItem>
|
||||||
<PrivateMenuItem key="operations" icon={<FolderOutlined />}>
|
<PrivateMenuItem key="operations" icon={<FolderOutlined />}>
|
||||||
<Link to={`${rootPath}/operations/plan`}>Операции по скважине</Link>
|
<Link to={`${rootPath}/operations`}>Операции по скважине</Link>
|
||||||
</PrivateMenuItem>
|
</PrivateMenuItem>
|
||||||
<PrivateMenuItem key="archive" icon={<DatabaseOutlined />}>
|
<PrivateMenuItem key="archive" icon={<DatabaseOutlined />}>
|
||||||
<Link to={`${rootPath}/archive`}>Архив</Link>
|
<Link to={`${rootPath}/archive`}>Архив</Link>
|
||||||
@ -89,7 +89,7 @@ export default function Well() {
|
|||||||
<Route path="/well/:idWell/report">
|
<Route path="/well/:idWell/report">
|
||||||
<Report idWell={idWell} />
|
<Report idWell={idWell} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/well/:idWell/operations/:tab">
|
<Route path="/well/:idWell/operations">
|
||||||
<WellOperations idWell={idWell} />
|
<WellOperations idWell={idWell} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/well/:idWell/archive">
|
<Route path="/well/:idWell/archive">
|
||||||
|
@ -97,7 +97,7 @@ const makeDataset = (data, label, color, width=1.5, dash) => ({
|
|||||||
borderDash: dash,
|
borderDash: dash,
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
|
export default function ChartTvD({dataPlan, dataFact, dataPredict}) {
|
||||||
const chartRef = useRef(null)
|
const chartRef = useRef(null)
|
||||||
const [chart, setChart] = useState()
|
const [chart, setChart] = useState()
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
|
|||||||
let data = {
|
let data = {
|
||||||
datasets: [
|
datasets: [
|
||||||
makeDataset(dataFact, 'Факт', '#0A0'),
|
makeDataset(dataFact, 'Факт', '#0A0'),
|
||||||
makeDataset(dataForecast, 'Прогноз', 'purple', 1, [7,3]),
|
makeDataset(dataPredict, 'Прогноз', 'purple', 1, [7,3]),
|
||||||
makeDataset(dataPlan, 'План', '#C004', 4),
|
makeDataset(dataPlan, 'План', '#C004', 4),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ export default function ChartDepthToDay({dataPlan, dataFact, dataForecast}) {
|
|||||||
chart.data = data
|
chart.data = data
|
||||||
chart.update()
|
chart.update()
|
||||||
}
|
}
|
||||||
}, [chart, dataPlan, dataFact, dataForecast])
|
}, [chart, dataPlan, dataFact, dataPredict])
|
||||||
|
|
||||||
return (<canvas ref={chartRef} />)
|
return (<canvas ref={chartRef} />)
|
||||||
}
|
}
|
54
src/pages/WellOperations/ImportExportBar.jsx
Normal file
54
src/pages/WellOperations/ImportExportBar.jsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Button, Tooltip, Modal } from "antd";
|
||||||
|
import {useState} from 'react'
|
||||||
|
import { FileOutlined, ImportOutlined, ExportOutlined } from '@ant-design/icons'
|
||||||
|
import { download } from '../../components/factory'
|
||||||
|
import { ImportOperations } from './ImportOperations'
|
||||||
|
|
||||||
|
const style = {margin:4}
|
||||||
|
|
||||||
|
export const ImportExportBar = ({idWell, onImported}) =>{
|
||||||
|
const [isImportModalVisible, setIsImportModalVisible] = useState(false)
|
||||||
|
|
||||||
|
const downloadTemplate = async () => download(`/api/well/${idWell}/wellOperations/tamplate`)
|
||||||
|
const downloadExport = async () => download(`/api/well/${idWell}/wellOperations/export`)
|
||||||
|
|
||||||
|
const onDone = () => {
|
||||||
|
setIsImportModalVisible(false)
|
||||||
|
if(onImported)
|
||||||
|
onImported()
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<Tooltip title = "Импорт - загрузить файл с операциями на сервер">
|
||||||
|
<Button
|
||||||
|
icon={<ImportOutlined/>}
|
||||||
|
style={style}
|
||||||
|
onClick={_=>setIsImportModalVisible(true)}/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip title = "Экспорт - скачать файл с операциями по скважине">
|
||||||
|
<Button
|
||||||
|
icon={<ExportOutlined/>}
|
||||||
|
style={style}
|
||||||
|
onClick={downloadExport}/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip title = "Скачать шаблон">
|
||||||
|
<Button
|
||||||
|
icon={<FileOutlined/>}
|
||||||
|
style={style}
|
||||||
|
onClick={downloadTemplate}/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title='Импорт'
|
||||||
|
visible={isImportModalVisible}
|
||||||
|
onCancel={_=>setIsImportModalVisible(false)}
|
||||||
|
|
||||||
|
footer={null}>
|
||||||
|
<ImportOperations
|
||||||
|
idWell={idWell}
|
||||||
|
onDone={onDone}/>
|
||||||
|
</Modal >
|
||||||
|
</>
|
||||||
|
}
|
41
src/pages/WellOperations/ImportOperations.jsx
Normal file
41
src/pages/WellOperations/ImportOperations.jsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import {Switch} from 'antd'
|
||||||
|
import {useState} from 'react'
|
||||||
|
import { ErrorFetch } from '../../components/ErrorFetch'
|
||||||
|
import {UploadForm} from '../../components/UploadForm'
|
||||||
|
|
||||||
|
export const ImportOperations = ({idWell, onDone}) =>{
|
||||||
|
const [deleteBeforeImport, setDeleteBeforeImport] = useState(false)
|
||||||
|
const [errorText, setErrorText] = useState('')
|
||||||
|
|
||||||
|
const url = `/api/well/${idWell}/wellOperations/import`
|
||||||
|
|
||||||
|
const onUploadSuccess = () => {
|
||||||
|
setErrorText('')
|
||||||
|
if(onDone)
|
||||||
|
onDone()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUploadError = (error) => {
|
||||||
|
if(error instanceof ErrorFetch && error.status === 400)
|
||||||
|
setErrorText(`Не удалось импортировать.\n ${error?.message}`)
|
||||||
|
else
|
||||||
|
setErrorText(`Не удалось импортировать.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUrl = () => deleteBeforeImport
|
||||||
|
? url + '/1'
|
||||||
|
: url + '/0'
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
<p>Загрузить файл excel с операциями на сервер</p>
|
||||||
|
<span>Очистить список операций перед импортом </span>
|
||||||
|
<Switch onChange={setDeleteBeforeImport} checked={deleteBeforeImport}/>
|
||||||
|
<UploadForm
|
||||||
|
url={getUrl()}
|
||||||
|
style={{marginTop:'24px'}}
|
||||||
|
onUploadSuccess={onUploadSuccess}
|
||||||
|
onUploadError={onUploadError}
|
||||||
|
/>
|
||||||
|
<span style={{color:'red', fontWeight:'bold'}}>{errorText}</span>
|
||||||
|
</div>
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import ChartDepthToDay from '../../components/charts/ChartDepthToDay';
|
import ChartTvD from './ChartTvD';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
import { invokeWebApiWrapperAsync } from '../../components/factory';
|
||||||
import { getOperations } from '../Cluster/functions';
|
import { getOperations } from '../Cluster/functions';
|
||||||
@ -7,18 +7,15 @@ import { getOperations } from '../Cluster/functions';
|
|||||||
export const Tvd = ({ idWell }) => {
|
export const Tvd = ({ idWell }) => {
|
||||||
const [dataPlan, setDataPlan] = useState([]);
|
const [dataPlan, setDataPlan] = useState([]);
|
||||||
const [dataFact, setDataFact] = useState([]);
|
const [dataFact, setDataFact] = useState([]);
|
||||||
const [dataForecast, setDataForecast] = useState([]);
|
const [dataPredict, setDataPredict] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
invokeWebApiWrapperAsync(
|
invokeWebApiWrapperAsync(
|
||||||
async () => {
|
async () => {
|
||||||
const operations = await getOperations(idWell);
|
const operations = await getOperations(idWell);
|
||||||
|
|
||||||
setDataPlan(operations.plan)
|
setDataPlan(operations.plan)
|
||||||
|
|
||||||
setDataFact(operations.fact)
|
setDataFact(operations.fact)
|
||||||
|
setDataPredict(operations.predict)
|
||||||
setDataForecast(operations.predict)
|
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
`Не удалось загрузить операции по скважине "${idWell}"`,
|
`Не удалось загрузить операции по скважине "${idWell}"`,
|
||||||
@ -29,10 +26,10 @@ export const Tvd = ({ idWell }) => {
|
|||||||
<div className="container">
|
<div className="container">
|
||||||
<div>
|
<div>
|
||||||
<h2 className={'mt-20px'}>График Глубина-день</h2>
|
<h2 className={'mt-20px'}>График Глубина-день</h2>
|
||||||
<ChartDepthToDay
|
<ChartTvD
|
||||||
dataPlan={dataPlan}
|
dataPlan={dataPlan}
|
||||||
dataFact={dataFact}
|
dataFact={dataFact}
|
||||||
dataForecast={dataForecast} />
|
dataPredict={dataPredict} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -6,10 +6,8 @@ import {
|
|||||||
DatePickerWrapper,
|
DatePickerWrapper,
|
||||||
SelectFromDictionary,
|
SelectFromDictionary,
|
||||||
makeColumn,
|
makeColumn,
|
||||||
numericColumnOptions,
|
|
||||||
makeNumericSorter,
|
|
||||||
makeDateSorter,
|
makeDateSorter,
|
||||||
defaultNumericRender } from "../../components/Table"
|
makeNumericColumnOptions} from "../../components/Table"
|
||||||
import LoaderPortal from '../../components/LoaderPortal'
|
import LoaderPortal from '../../components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
import { invokeWebApiWrapperAsync } from '../../components/factory'
|
||||||
import { WellOperationService} from '../../services/api'
|
import { WellOperationService} from '../../services/api'
|
||||||
@ -20,20 +18,6 @@ const { TextArea } = Input;
|
|||||||
const basePageSize = 160;
|
const basePageSize = 160;
|
||||||
const format='YYYY.MM.DD HH:mm'
|
const format='YYYY.MM.DD HH:mm'
|
||||||
|
|
||||||
const numericSortColumnOptions = {
|
|
||||||
...numericColumnOptions,
|
|
||||||
sorter: makeNumericSorter('wellDepth'),
|
|
||||||
render:(value) =>
|
|
||||||
<div className='text-align-r-container'>
|
|
||||||
<span>{value}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
const durationFormattedColumnOptions = {
|
|
||||||
...numericColumnOptions,
|
|
||||||
render: defaultNumericRender
|
|
||||||
}
|
|
||||||
|
|
||||||
export const WellOperationsEditor = ({idWell, idType}) => {
|
export const WellOperationsEditor = ({idWell, idType}) => {
|
||||||
const [pageNumAndPageSize, setPageNumAndPageSize] = useState({current:1, pageSize:basePageSize})
|
const [pageNumAndPageSize, setPageNumAndPageSize] = useState({current:1, pageSize:basePageSize})
|
||||||
const [paginationTotal, setPaginationTotal] = useState(0)
|
const [paginationTotal, setPaginationTotal] = useState(0)
|
||||||
@ -81,19 +65,20 @@ export const WellOperationsEditor = ({idWell, idType}) => {
|
|||||||
render:(_, record)=>getByKeyOrReturnKey(dictionaryOperationCategory, record.idCategory)
|
render:(_, record)=>getByKeyOrReturnKey(dictionaryOperationCategory, record.idCategory)
|
||||||
}),
|
}),
|
||||||
makeColumn('Доп. инфо','categoryInfo', {editable:true, width:300, input:<TextArea/>}),
|
makeColumn('Доп. инфо','categoryInfo', {editable:true, width:300, input:<TextArea/>}),
|
||||||
makeColumn('Глубина забоя','wellDepth', numericSortColumnOptions),
|
makeColumn('Глубина забоя на начало','depthStart', makeNumericColumnOptions(2, 'depthStart')),
|
||||||
makeColumn('Время начала','startDate', {
|
makeColumn('Глубина забоя при завершении','depthEnd', makeNumericColumnOptions(2, 'depthEnd')),
|
||||||
|
makeColumn('Время начала','dateStart', {
|
||||||
editable:true,
|
editable:true,
|
||||||
width:200,
|
width:200,
|
||||||
input:<DatePickerWrapper/>,
|
input:<DatePickerWrapper/>,
|
||||||
initialValue:moment().format(),
|
initialValue:moment().format(),
|
||||||
sorter: makeDateSorter('startDate'),
|
sorter: makeDateSorter('dateStart'),
|
||||||
render:(_, record) =>
|
render:(_, record) =>
|
||||||
<div className={'text-align-r-container'}>
|
<div className={'text-align-r-container'}>
|
||||||
<span>{moment.utc(record.startDate).local().format(format)}</span>
|
<span>{moment.utc(record.dateStart).local().format(format)}</span>
|
||||||
</div>
|
</div>
|
||||||
}),
|
}),
|
||||||
makeColumn('Часы','durationHours', durationFormattedColumnOptions),
|
makeColumn('Часы','durationHours', makeNumericColumnOptions(2, 'durationHours')),
|
||||||
makeColumn('Комментарий','comment', {editable:true, input:<TextArea/>}),
|
makeColumn('Комментарий','comment', {editable:true, input:<TextArea/>}),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
import {Layout, Menu} from "antd";
|
import {Layout, Menu} from "antd";
|
||||||
import {Switch, Link, Route, Redirect, useParams} from "react-router-dom";
|
import {Switch, Link, Route, Redirect, useParams, useHistory} from "react-router-dom";
|
||||||
import { FolderOutlined } from "@ant-design/icons";
|
import { FolderOutlined } from "@ant-design/icons";
|
||||||
import { WellOperationsEditor } from './WellOperationsEditor'
|
import { WellOperationsEditor } from './WellOperationsEditor'
|
||||||
import { WellSectionsStat } from './WellSectionsStat'
|
import { WellSectionsStat } from './WellSectionsStat'
|
||||||
import { Tvd } from './Tvd'
|
import { Tvd } from './Tvd'
|
||||||
import { WellOpeationsModes } from './WellOpeationsModes'
|
import { ImportExportBar } from "./ImportExportBar";
|
||||||
|
|
||||||
const { Content } = Layout
|
const { Content } = Layout
|
||||||
|
|
||||||
export default function WellOperations({idWell}) {
|
export default function WellOperations({idWell}) {
|
||||||
let {tab} = useParams()
|
let {tab} = useParams()
|
||||||
|
let history = useHistory()
|
||||||
const rootPath = `/well/${idWell}/operations`;
|
const rootPath = `/well/${idWell}/operations`;
|
||||||
|
|
||||||
|
const onImported = () => {
|
||||||
|
history.push(`${rootPath}`)
|
||||||
|
}
|
||||||
|
|
||||||
return(<>
|
return(<>
|
||||||
<Menu
|
<Menu
|
||||||
mode="horizontal"
|
mode="horizontal"
|
||||||
@ -33,6 +38,7 @@ export default function WellOperations({idWell}) {
|
|||||||
<Menu.Item key={'modes'} icon={<FolderOutlined />}>
|
<Menu.Item key={'modes'} icon={<FolderOutlined />}>
|
||||||
<Link to={`${rootPath}/modes`}>Режимы</Link>
|
<Link to={`${rootPath}/modes`}>Режимы</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<ImportExportBar idWell={idWell} onImported={onImported}/>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Content className="site-layout-background">
|
<Content className="site-layout-background">
|
||||||
@ -53,7 +59,7 @@ export default function WellOperations({idWell}) {
|
|||||||
<WellOpeationsModes idWell={idWell}/>
|
<WellOpeationsModes idWell={idWell}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path={rootPath}>
|
<Route path={rootPath}>
|
||||||
<Redirect to={`${rootPath}/tvd`}/>
|
<Redirect to={`${rootPath}/plan`}/>
|
||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -20,7 +20,7 @@ export type DrillParamsDto = {
|
|||||||
topDriveSpeedMin?: number;
|
topDriveSpeedMin?: number;
|
||||||
topDriveSpeedAvg?: number;
|
topDriveSpeedAvg?: number;
|
||||||
topDriveSpeedMax?: number;
|
topDriveSpeedMax?: number;
|
||||||
flowMin?: number;
|
consumptionMin?: number;
|
||||||
flowAvg?: number;
|
consumptionAvg?: number;
|
||||||
flowMax?: number;
|
consumptionMax?: number;
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,8 @@ export class AdminTelemetryService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async mergeTelemetries(
|
public static async mergeTelemetries(
|
||||||
requestBody?: Array<number>,
|
requestBody?: Array<number>,
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: `/merge`,
|
path: `/merge`,
|
||||||
|
@ -15,10 +15,10 @@ export class DrillParamsService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async getDefaultDrillParams(
|
public static async getDefaultDrillParams(
|
||||||
idWell?: number,
|
idWell?: number,
|
||||||
startDepth?: number,
|
startDepth?: number,
|
||||||
endDepth?: number,
|
endDepth?: number,
|
||||||
): Promise<DrillParamsDto> {
|
): Promise<DrillParamsDto> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: `/drillParams/idWell/autoParams`,
|
path: `/drillParams/idWell/autoParams`,
|
||||||
@ -39,9 +39,9 @@ export class DrillParamsService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async saveDrillParams(
|
public static async saveDrillParams(
|
||||||
idWell?: number,
|
idWell?: number,
|
||||||
requestBody?: DrillParamsDto,
|
requestBody?: DrillParamsDto,
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: `/drillParams/idWell`,
|
path: `/drillParams/idWell`,
|
||||||
|
@ -154,10 +154,10 @@ export class WellOperationService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async import(
|
public static async import(
|
||||||
idWell: number,
|
idWell: number,
|
||||||
options: number,
|
options: number,
|
||||||
requestBody?: any,
|
requestBody?: any,
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
path: `/api/well/${idWell}/wellOperations/import/${options}`,
|
path: `/api/well/${idWell}/wellOperations/import/${options}`,
|
||||||
@ -173,8 +173,8 @@ export class WellOperationService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async export(
|
public static async export(
|
||||||
idWell: number,
|
idWell: number,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: `/api/well/${idWell}/wellOperations/export`,
|
path: `/api/well/${idWell}/wellOperations/export`,
|
||||||
@ -189,8 +189,8 @@ export class WellOperationService {
|
|||||||
* @throws ApiError
|
* @throws ApiError
|
||||||
*/
|
*/
|
||||||
public static async getTamplate(
|
public static async getTamplate(
|
||||||
idWell: string,
|
idWell: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const result = await __request({
|
const result = await __request({
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
path: `/api/well/${idWell}/wellOperations/tamplate`,
|
path: `/api/well/${idWell}/wellOperations/tamplate`,
|
||||||
|
@ -11,6 +11,10 @@ body {
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-direction-column {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.d-inline {
|
.d-inline {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
@ -19,10 +23,30 @@ body {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-15 {
|
||||||
|
width: 15%
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-33 {
|
||||||
|
width: 33%
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-50 {
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
.w-100 {
|
.w-100 {
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.m-0 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-8px {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-20px {
|
.mt-20px {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
@ -35,6 +59,10 @@ body {
|
|||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ml-10px {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.ml-30px {
|
.ml-30px {
|
||||||
margin-left: 30px;
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
|
36
src/styles/measure.css
Normal file
36
src/styles/measure.css
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
input.measure-input {
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-300px {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.measure-buttons-container {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.measure-dates {
|
||||||
|
height: 160px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.measure-button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-timeline {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.m-5px {
|
||||||
|
margin: 5px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12px {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-10px {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user