forked from ddrilling/asb_cloud_front
График скорость проходки-интервал
This commit is contained in:
parent
f62b280ee5
commit
c119f22aa4
@ -1,15 +1,35 @@
|
|||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
|
import { DatePicker } from 'antd'
|
||||||
import notify from "../components/notify"
|
import notify from "../components/notify"
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { AnalyticsService } from "../services/api"
|
import { AnalyticsService } from '../services/api'
|
||||||
import { ChartDepthToInterval } from './charts/ChartDepthToInterval'
|
import { ChartDepthToInterval } from './charts/ChartDepthToInterval'
|
||||||
|
import { Select } from 'antd'
|
||||||
|
|
||||||
const line = {label: 'Данные по глубине скважины за период', y: 'intervalDepthProgress', x: 'intervalStartDate'}
|
const { Option } = Select
|
||||||
|
|
||||||
|
const timePeriodCollection = [
|
||||||
|
{ value: '60', label: '1 минута' },
|
||||||
|
{ value: '300', label: '5 минут' },
|
||||||
|
{ value: '600', label: '10 минут' },
|
||||||
|
{ value: '1800', label: '30 минут' },
|
||||||
|
{ value: '3600', label: '1 час' },
|
||||||
|
{ value: '21600', label: '6 часов' },
|
||||||
|
{ value: '43200', label: '12 часов' },
|
||||||
|
{ value: '86400', label: '24 часа' }
|
||||||
|
]
|
||||||
|
|
||||||
|
const { RangePicker } = DatePicker
|
||||||
|
|
||||||
|
const lines = [{ label: 'График скорость проходки-интервал', yAccessorName: "intervalDepthProgress", xAccessorName: "intervalStartDate", color: '#00f' }]
|
||||||
|
|
||||||
export function AnalysisDepthToInterval() {
|
export function AnalysisDepthToInterval() {
|
||||||
let { id } = useParams()
|
let { id } = useParams()
|
||||||
const [depthToIntervalData, setDepthToIntervalData] = useState([])
|
const [depthToIntervalData, setDepthToIntervalData] = useState([])
|
||||||
const [loader, setLoader] = useState(false)
|
const [loader, setLoader] = useState(false)
|
||||||
|
const [chartInterval, setChartInterval] = useState(600)
|
||||||
|
|
||||||
|
const children = timePeriodCollection.map((line) => <Option key={line.value}>{line.label}</Option>)
|
||||||
|
|
||||||
const handleReceiveDepthToIntervalData = (data) => {
|
const handleReceiveDepthToIntervalData = (data) => {
|
||||||
setDepthToIntervalData(data)
|
setDepthToIntervalData(data)
|
||||||
@ -17,7 +37,7 @@ export function AnalysisDepthToInterval() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoader(true)
|
setLoader(true)
|
||||||
AnalyticsService.getWellDepthToInterval(id)
|
AnalyticsService.getWellDepthToInterval(id, chartInterval)
|
||||||
.then(handleReceiveDepthToIntervalData)
|
.then(handleReceiveDepthToIntervalData)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
notify(`Не удалось получить данные для Анализа Глубина-День по скважине "${id}"`,
|
notify(`Не удалось получить данные для Анализа Глубина-День по скважине "${id}"`,
|
||||||
@ -25,13 +45,16 @@ export function AnalysisDepthToInterval() {
|
|||||||
console.log(error)
|
console.log(error)
|
||||||
})
|
})
|
||||||
.finally(setLoader(false))
|
.finally(setLoader(false))
|
||||||
}, [id])
|
}, [id, chartInterval])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Select defaultValue="600" onChange={setChartInterval}>
|
||||||
|
{children}
|
||||||
|
</Select>
|
||||||
<ChartDepthToInterval
|
<ChartDepthToInterval
|
||||||
data={depthToIntervalData}
|
data={depthToIntervalData}
|
||||||
line={line}
|
lines={lines}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,7 @@ Chart.register(TimeScale, LinearScale, LineController, LineElement, PointElement
|
|||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
aspectRatio: 1.45,
|
aspectRatio: 6,
|
||||||
animation: false,
|
animation: false,
|
||||||
tooltips: {
|
tooltips: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
@ -33,7 +33,7 @@ const defaultOptions = {
|
|||||||
scales: {
|
scales: {
|
||||||
x:{
|
x:{
|
||||||
type: 'time',
|
type: 'time',
|
||||||
reverse: true,
|
reverse: false,
|
||||||
time: {
|
time: {
|
||||||
stepSize: 20,
|
stepSize: 20,
|
||||||
displayFormats: {
|
displayFormats: {
|
||||||
@ -53,7 +53,7 @@ const defaultOptions = {
|
|||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
z: 1,
|
z: 1,
|
||||||
display : false,
|
display : true,
|
||||||
textStrokeColor : "#ffff",
|
textStrokeColor : "#ffff",
|
||||||
textStrokeWidth : 2,
|
textStrokeWidth : 2,
|
||||||
color:"#000",
|
color:"#000",
|
||||||
@ -78,18 +78,6 @@ const defaultOptions = {
|
|||||||
datalabels: {
|
datalabels: {
|
||||||
display: false,
|
display: false,
|
||||||
},
|
},
|
||||||
// zoom: {
|
|
||||||
// zoom: {
|
|
||||||
// wheel: {
|
|
||||||
// enabled: true,
|
|
||||||
// modifierKey: 'alt',
|
|
||||||
// },
|
|
||||||
// pinch: {
|
|
||||||
// enabled: true
|
|
||||||
// },
|
|
||||||
// mode: 'x',
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@ import { useEffect, useState } from 'react'
|
|||||||
import { ChartDepthToIntervalBase } from './ChartDepthToIntervalBase'
|
import { ChartDepthToIntervalBase } from './ChartDepthToIntervalBase'
|
||||||
import { CreateDataset } from './ChartTimeArchive'
|
import { CreateDataset } from './ChartTimeArchive'
|
||||||
|
|
||||||
export function ChartDepthToInterval({data, lines}) {
|
export const ChartDepthToInterval = ({ lines, data }) => {
|
||||||
const [depthToIntervalDataParams, setDepthToIntervalDataParams] = useState({data: {datasets: []}})
|
const [depthToIntervalDataParams, setDepthToIntervalDataParams] = useState({ data: { datasets: [] } })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if ((!lines)
|
if ((!lines)
|
||||||
@ -12,11 +12,11 @@ export function ChartDepthToInterval({data, lines}) {
|
|||||||
|
|
||||||
let newDatasets = lines.map(lineCfg => {
|
let newDatasets = lines.map(lineCfg => {
|
||||||
let datasets = CreateDataset(lineCfg)
|
let datasets = CreateDataset(lineCfg)
|
||||||
if(data.length !== 0)
|
if (data.length !== 0)
|
||||||
datasets.data = data.map(dataItem => {
|
datasets.data = data.map(dataItem => {
|
||||||
return {
|
return {
|
||||||
x: new Date(dataItem[lineCfg.x??'date']),
|
x: new Date(dataItem[lineCfg.xAccessorName ?? 'intervalStartDate']),
|
||||||
y: dataItem[lineCfg.y],
|
y: dataItem[lineCfg.yAccessorName ?? 'intervalDepthProgress'],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return datasets
|
return datasets
|
||||||
@ -29,9 +29,11 @@ export function ChartDepthToInterval({data, lines}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setDepthToIntervalDataParams(newParams)
|
setDepthToIntervalDataParams(newParams)
|
||||||
|
|
||||||
}, [data, lines])
|
}, [data, lines])
|
||||||
|
|
||||||
return (
|
return (<>
|
||||||
<ChartDepthToIntervalBase dataParams={depthToIntervalDataParams} />
|
<ChartDepthToIntervalBase dataParams={depthToIntervalDataParams} />
|
||||||
)
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
@ -1,37 +1,41 @@
|
|||||||
import {useEffect, useRef, useState} from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import {
|
import {
|
||||||
Chart,
|
Chart,
|
||||||
TimeScale,
|
TimeScale,
|
||||||
Legend,
|
Legend,
|
||||||
PointElement,
|
PointElement,
|
||||||
ChartData,
|
ChartData,
|
||||||
ChartTypeRegistry,
|
ChartTypeRegistry,
|
||||||
ChartOptions,
|
ChartOptions,
|
||||||
BarController,
|
BarController,
|
||||||
BarElement
|
BarElement,
|
||||||
|
TimeSeriesScale,
|
||||||
|
LinearScale,
|
||||||
|
LineController,
|
||||||
} from 'chart.js'
|
} from 'chart.js'
|
||||||
import 'chartjs-adapter-moment'
|
import 'chartjs-adapter-moment'
|
||||||
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
||||||
|
|
||||||
Chart.register(TimeScale, BarController, BarElement, PointElement, Legend, ChartDataLabels)
|
Chart.register(TimeScale, BarController, BarElement, PointElement, TimeSeriesScale, LineController, LinearScale, Legend, ChartDataLabels)
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
aspectRatio: 1.45,
|
aspectRatio: 4,
|
||||||
animation: false,
|
animation: false,
|
||||||
tooltips: {
|
tooltips: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label(tooltipItem:any) {
|
label(tooltipItem: any) {
|
||||||
return tooltipItem.yLabel;
|
return tooltipItem.yLabel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
|
events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'],
|
||||||
scales: {
|
scales: {
|
||||||
x:{
|
x: {
|
||||||
|
position: 'bottom',
|
||||||
type: 'time',
|
type: 'time',
|
||||||
reverse: true,
|
reverse: false,
|
||||||
time: {
|
time: {
|
||||||
stepSize: 20,
|
stepSize: 20,
|
||||||
displayFormats: {
|
displayFormats: {
|
||||||
@ -46,34 +50,33 @@ const defaultOptions = {
|
|||||||
year: 'yyyy.MM',
|
year: 'yyyy.MM',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
grid:{
|
grid: {
|
||||||
drawTicks: false,
|
drawTicks: false,
|
||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
z: 1,
|
z: 1,
|
||||||
display : false,
|
display: true,
|
||||||
textStrokeColor : "#ffff",
|
textStrokeColor: "#ffff",
|
||||||
textStrokeWidth : 2,
|
textStrokeWidth: 2,
|
||||||
color:"#000",
|
color: "#000",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
y: {
|
||||||
y:{
|
beginAtZero: true,
|
||||||
beginAtZero: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
elements:{
|
elements: {
|
||||||
point:{
|
point: {
|
||||||
radius:0,
|
radius: 0,
|
||||||
hoverRadius:5,
|
hoverRadius: 5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins:{
|
plugins: {
|
||||||
legend:{
|
legend: {
|
||||||
display: true,
|
display: true,
|
||||||
},
|
},
|
||||||
datalabels: {
|
datalabels: {
|
||||||
display: false,
|
display: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,39 +107,39 @@ export type TimeParams = {
|
|||||||
|
|
||||||
const linesPerInterval = 32
|
const linesPerInterval = 32
|
||||||
|
|
||||||
export const timeUnitByInterval = (intervalSec:number):String => {
|
export const timeUnitByInterval = (intervalSec: number): String => {
|
||||||
if(intervalSec <= 60)
|
if (intervalSec <= 60)
|
||||||
return 'millisecond'
|
return 'millisecond'
|
||||||
|
|
||||||
if(intervalSec <= 32*60)
|
if (intervalSec <= 32 * 60)
|
||||||
return 'second'
|
return 'second'
|
||||||
|
|
||||||
if(intervalSec <= 32*60*60)
|
if (intervalSec <= 32 * 60 * 60)
|
||||||
return 'minute'
|
return 'minute'
|
||||||
|
|
||||||
if(intervalSec <= 32*12*60*60)
|
if (intervalSec <= 32 * 12 * 60 * 60)
|
||||||
return 'hour'
|
return 'hour'
|
||||||
|
|
||||||
if(intervalSec <= 32*24*60*60)
|
if (intervalSec <= 32 * 24 * 60 * 60)
|
||||||
return 'day'
|
return 'day'
|
||||||
|
|
||||||
if(intervalSec <= 32*7*24*60*60)
|
if (intervalSec <= 32 * 7 * 24 * 60 * 60)
|
||||||
return 'week'
|
return 'week'
|
||||||
|
|
||||||
if(intervalSec <= 32*30.4375*24*60*60)
|
if (intervalSec <= 32 * 30.4375 * 24 * 60 * 60)
|
||||||
return 'month'
|
return 'month'
|
||||||
|
|
||||||
if(intervalSec <= 32*121.75*24*60*60)
|
if (intervalSec <= 32 * 121.75 * 24 * 60 * 60)
|
||||||
return 'quarter'
|
return 'quarter'
|
||||||
else
|
else
|
||||||
return 'year'
|
return 'year'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const timeParamsByInterval = (intervalSec:number) :TimeParams => {
|
export const timeParamsByInterval = (intervalSec: number): TimeParams => {
|
||||||
let stepSize = intervalSec
|
let stepSize = intervalSec
|
||||||
let unit = timeUnitByInterval(intervalSec)
|
let unit = timeUnitByInterval(intervalSec)
|
||||||
|
|
||||||
switch(unit){
|
switch (unit) {
|
||||||
case "millisecond":
|
case "millisecond":
|
||||||
stepSize *= 1000
|
stepSize *= 1000
|
||||||
break;
|
break;
|
||||||
@ -147,65 +150,65 @@ export const timeParamsByInterval = (intervalSec:number) :TimeParams => {
|
|||||||
stepSize /= 60
|
stepSize /= 60
|
||||||
break;
|
break;
|
||||||
case "hour":
|
case "hour":
|
||||||
stepSize /= 60*60
|
stepSize /= 60 * 60
|
||||||
break;
|
break;
|
||||||
case "day":
|
case "day":
|
||||||
stepSize /= 24*60*60
|
stepSize /= 24 * 60 * 60
|
||||||
break;
|
break;
|
||||||
case "week":
|
case "week":
|
||||||
stepSize /= 7*24*60*60
|
stepSize /= 7 * 24 * 60 * 60
|
||||||
break;
|
break;
|
||||||
case "month":
|
case "month":
|
||||||
stepSize /= 30*24*60*60
|
stepSize /= 30 * 24 * 60 * 60
|
||||||
break;
|
break;
|
||||||
case "quarter":
|
case "quarter":
|
||||||
stepSize /= 91*24*60*60
|
stepSize /= 91 * 24 * 60 * 60
|
||||||
break;
|
break;
|
||||||
case "year":
|
case "year":
|
||||||
stepSize /= 365.25*24*60*60
|
stepSize /= 365.25 * 24 * 60 * 60
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stepSize = Math.round(stepSize/linesPerInterval)
|
stepSize = Math.round(stepSize / linesPerInterval)
|
||||||
stepSize = stepSize > 0 ? stepSize : 1;
|
stepSize = stepSize > 0 ? stepSize : 1;
|
||||||
return {unit, stepSize}
|
return { unit, stepSize }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChartDepthToIntervalBase: React.FC<ChartTimeBaseProps> = ({options, dataParams}) => {
|
export const ChartDepthToIntervalBase: React.FC<ChartTimeBaseProps> = ({ options, dataParams }) => {
|
||||||
const chartRef = useRef<HTMLCanvasElement>(null)
|
const chartRef = useRef<HTMLCanvasElement>(null)
|
||||||
const [chart, setChart] = useState<any>()
|
const [chart, setChart] = useState<any>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if((chartRef.current)&&(!chart)) {
|
if ((chartRef.current) && (!chart)) {
|
||||||
let thisOptions = {}
|
let thisOptions = {}
|
||||||
Object.assign(thisOptions, defaultOptions, options)
|
Object.assign(thisOptions, defaultOptions, options)
|
||||||
|
|
||||||
let newChart = new Chart(chartRef.current, {
|
let newChart = new Chart(chartRef.current, {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
plugins: [ChartDataLabels],
|
plugins: [ChartDataLabels],
|
||||||
options: thisOptions,
|
options: thisOptions,
|
||||||
data: dataParams.data
|
data: dataParams.data
|
||||||
})
|
})
|
||||||
setChart(newChart)
|
setChart(newChart)
|
||||||
|
|
||||||
return () => chart?.destroy()
|
return () => chart?.destroy()
|
||||||
}
|
}
|
||||||
}, [chart, options, dataParams])
|
}, [chart, options, dataParams])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!chart)
|
if (!chart)
|
||||||
return
|
return
|
||||||
|
|
||||||
chart.data = dataParams.data
|
chart.data = dataParams.data
|
||||||
chart.options.aspectRatio = options?.aspectRatio
|
chart.options.aspectRatio = options?.aspectRatio
|
||||||
if (dataParams.xStart) {
|
if (dataParams.xStart) {
|
||||||
let interval = Number(dataParams.xInterval ?? 600)
|
let interval = Number(dataParams.xInterval ?? 600)
|
||||||
let start = new Date(dataParams.xStart)
|
let start = new Date(dataParams.xStart)
|
||||||
let end = new Date(dataParams.xStart)
|
let end = new Date(dataParams.xStart)
|
||||||
end.setSeconds(end.getSeconds() + interval)
|
end.setSeconds(end.getSeconds() + interval)
|
||||||
let {unit, stepSize} = timeParamsByInterval(interval)
|
let { unit, stepSize } = timeParamsByInterval(interval)
|
||||||
|
|
||||||
if(chart.options.scales?.x){
|
if (chart.options.scales?.x) {
|
||||||
chart.options.scales.x.max = end.getTime()
|
chart.options.scales.x.max = end.getTime()
|
||||||
chart.options.scales.x.min = start.getTime()
|
chart.options.scales.x.min = start.getTime()
|
||||||
chart.options.scales.x.ticks.display = dataParams.displayLabels ?? true
|
chart.options.scales.x.ticks.display = dataParams.displayLabels ?? true
|
||||||
@ -214,8 +217,11 @@ export const ChartDepthToIntervalBase: React.FC<ChartTimeBaseProps> = ({options,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chart.update()
|
chart.update()
|
||||||
}, [chart, dataParams, options])
|
}, [chart, dataParams, options])
|
||||||
|
|
||||||
return(<canvas ref={chartRef} />)
|
return (<canvas style={{
|
||||||
|
width: "100px",
|
||||||
|
height: "100px"
|
||||||
|
}} ref={chartRef} />)
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ export default function Analysis() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AnalysisDepthToDay />
|
<AnalysisDepthToDay />
|
||||||
|
<div style={{ marginTop: '100px' }}> </div>
|
||||||
<AnalysisDepthToInterval />
|
<AnalysisDepthToInterval />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,7 @@ import moment from 'moment'
|
|||||||
import notify from '../components/notify'
|
import notify from '../components/notify'
|
||||||
import LoaderPortal from '../components/LoaderPortal'
|
import LoaderPortal from '../components/LoaderPortal'
|
||||||
|
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker
|
||||||
|
|
||||||
const SaveObject = (key, obj) => {
|
const SaveObject = (key, obj) => {
|
||||||
let json = JSON.stringify(obj)
|
let json = JSON.stringify(obj)
|
||||||
|
@ -183,6 +183,17 @@ const columns = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const timePeriodCollection = [
|
||||||
|
{value: '60', label: '1 минута'},
|
||||||
|
{value: '300', label: '5 минут'},
|
||||||
|
{value: '600', label: '10 минут'},
|
||||||
|
{value: '1800', label: '30 минут'},
|
||||||
|
{value: '3600', label: '1 час'},
|
||||||
|
{value: '21600', label: '6 часов'},
|
||||||
|
{value: '43200', label: '12 часов'},
|
||||||
|
{value: '86400', label: '24 часа'}
|
||||||
|
]
|
||||||
|
|
||||||
export default function TelemetryView(props) {
|
export default function TelemetryView(props) {
|
||||||
let {id} = useParams()
|
let {id} = useParams()
|
||||||
const [saubData, setSaubData] = useState([])
|
const [saubData, setSaubData] = useState([])
|
||||||
@ -191,6 +202,8 @@ export default function TelemetryView(props) {
|
|||||||
|
|
||||||
const [loader, setLoader] = useState(false) // , setLoader
|
const [loader, setLoader] = useState(false) // , setLoader
|
||||||
|
|
||||||
|
const children = timePeriodCollection.map((line) => <Option key={line.value}>{line.label}</Option>)
|
||||||
|
|
||||||
const handleReceiveDataSaub = (data) => {
|
const handleReceiveDataSaub = (data) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setSaubData(data)
|
setSaubData(data)
|
||||||
@ -248,14 +261,7 @@ export default function TelemetryView(props) {
|
|||||||
<Col>
|
<Col>
|
||||||
Интервал:
|
Интервал:
|
||||||
<Select defaultValue="600" onChange={setChartInterval}>
|
<Select defaultValue="600" onChange={setChartInterval}>
|
||||||
<Option value='60'>1 минута</Option>
|
{children}
|
||||||
<Option value='300'>5 минут</Option>
|
|
||||||
<Option value='600'>10 минут</Option>
|
|
||||||
<Option value='1800'>30 минут</Option>
|
|
||||||
<Option value='3600'>1 час</Option>
|
|
||||||
<Option value='21600'>6 час</Option>
|
|
||||||
<Option value='43200'>12 часов</Option>
|
|
||||||
<Option value='86400'>1 день</Option>
|
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
<span style={{flexGrow: 1}}> </span>
|
<span style={{flexGrow: 1}}> </span>
|
||||||
|
Loading…
Reference in New Issue
Block a user