forked from ddrilling/asb_cloud_front
Merge branch 'dev' of bitbucket.org:autodrilling/asb_cloud_front into dev
This commit is contained in:
commit
01f499b85d
@ -12,7 +12,6 @@ export {
|
|||||||
makeNumericColumnPlanFact,
|
makeNumericColumnPlanFact,
|
||||||
makeNumericStartEnd,
|
makeNumericStartEnd,
|
||||||
makeNumericMinMax,
|
makeNumericMinMax,
|
||||||
makeNumericAvgRange
|
|
||||||
} from './numeric'
|
} from './numeric'
|
||||||
export { makeColumnsPlanFact } from './plan_fact'
|
export { makeColumnsPlanFact } from './plan_fact'
|
||||||
export { makeSelectColumn } from './select'
|
export { makeSelectColumn } from './select'
|
||||||
|
@ -94,18 +94,4 @@ export const makeNumericMinMax = (
|
|||||||
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max')),
|
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max')),
|
||||||
])
|
])
|
||||||
|
|
||||||
export const makeNumericAvgRange = (
|
|
||||||
title: ReactNode,
|
|
||||||
dataIndex: string,
|
|
||||||
fixed: number,
|
|
||||||
filters: object[],
|
|
||||||
filterDelegate: (key: string | number) => any,
|
|
||||||
renderDelegate: (_: any, row: object) => any,
|
|
||||||
width: string
|
|
||||||
) => makeGroupColumn(title, [
|
|
||||||
makeNumericColumn('мин', dataIndex + 'Min', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Min')),
|
|
||||||
makeNumericColumn('сред', dataIndex + 'Avg', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Avg')),
|
|
||||||
makeNumericColumn('макс', dataIndex + 'Max', filters, filterDelegate, renderDelegate, width, makeNumericColumnOptions(fixed, dataIndex + 'Max'))
|
|
||||||
])
|
|
||||||
|
|
||||||
export default makeNumericColumn
|
export default makeNumericColumn
|
||||||
|
@ -20,7 +20,6 @@ export {
|
|||||||
makeNumericColumnPlanFact,
|
makeNumericColumnPlanFact,
|
||||||
makeNumericStartEnd,
|
makeNumericStartEnd,
|
||||||
makeNumericMinMax,
|
makeNumericMinMax,
|
||||||
makeNumericAvgRange,
|
|
||||||
makeSelectColumn,
|
makeSelectColumn,
|
||||||
makeTagColumn,
|
makeTagColumn,
|
||||||
makeTagInput,
|
makeTagInput,
|
||||||
|
@ -7,6 +7,9 @@ import { DataType } from './Columns'
|
|||||||
export const makeNumericSorter = <T extends unknown>(key: keyof DataType<T>) =>
|
export const makeNumericSorter = <T extends unknown>(key: keyof DataType<T>) =>
|
||||||
(a: DataType<T>, b: DataType<T>) => Number(a[key]) - Number(b[key])
|
(a: DataType<T>, b: DataType<T>) => Number(a[key]) - Number(b[key])
|
||||||
|
|
||||||
|
export const makeNumericObjSorter = (key: [string, string]) =>
|
||||||
|
(a: DataType, b: DataType) => Number(a[key[0]][key[1]]) - Number(b[key[0]][key[1]])
|
||||||
|
|
||||||
export const makeStringSorter = <T extends unknown>(key: keyof DataType<T>) => (a?: DataType<T> | null, b?: DataType<T> | null) => {
|
export const makeStringSorter = <T extends unknown>(key: keyof DataType<T>) => (a?: DataType<T> | null, b?: DataType<T> | null) => {
|
||||||
if (!a && !b) return 0
|
if (!a && !b) return 0
|
||||||
if (!a) return 1
|
if (!a) return 1
|
||||||
|
149
src/components/d3/D3HorizontalChart.tsx
Normal file
149
src/components/d3/D3HorizontalChart.tsx
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import React, { memo, useEffect } from 'react'
|
||||||
|
import * as d3 from 'd3'
|
||||||
|
|
||||||
|
import LoaderPortal from '@components/LoaderPortal'
|
||||||
|
import { useElementSize } from 'usehooks-ts'
|
||||||
|
|
||||||
|
|
||||||
|
import '@styles/d3.less'
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
name: string
|
||||||
|
percent: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type D3HorizontalChartProps = {
|
||||||
|
width?: string
|
||||||
|
height?: string
|
||||||
|
data: DataType[]
|
||||||
|
colors?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const D3HorizontalChart = memo((
|
||||||
|
{
|
||||||
|
width: givenWidth = '100%',
|
||||||
|
height: givenHeight = '100%',
|
||||||
|
data,
|
||||||
|
colors
|
||||||
|
}: D3HorizontalChartProps) => {
|
||||||
|
|
||||||
|
const [rootRef, { width, height }] = useElementSize()
|
||||||
|
|
||||||
|
const margin = { top: 50, right: 100, bottom: 50, left: 100 }
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (width < 100 || height < 100) return
|
||||||
|
const _width = width - margin.left - margin.right
|
||||||
|
const _height = height - margin.top - margin.bottom
|
||||||
|
|
||||||
|
const svg = d3.select('#d3-horizontal-chart')
|
||||||
|
.attr('width', '100%')
|
||||||
|
.attr('height', '100%')
|
||||||
|
.append('g')
|
||||||
|
.attr('transform', `translate(${margin.left},${margin.top})`)
|
||||||
|
|
||||||
|
const percents = ['percents']
|
||||||
|
const names = data.map(d => d.name)
|
||||||
|
|
||||||
|
const stackedData = d3.stack()
|
||||||
|
//@ts-ignore
|
||||||
|
.keys(percents)(data)
|
||||||
|
|
||||||
|
const xMax = 100
|
||||||
|
|
||||||
|
// scales
|
||||||
|
|
||||||
|
const x = d3.scaleLinear()
|
||||||
|
.domain([0, xMax])
|
||||||
|
.range([0, _width])
|
||||||
|
|
||||||
|
const y = d3.scaleBand()
|
||||||
|
.domain(names)
|
||||||
|
.range([0, _height])
|
||||||
|
.padding(0.25)
|
||||||
|
|
||||||
|
// axes
|
||||||
|
|
||||||
|
const xAxisTop = d3.axisTop(x)
|
||||||
|
.tickValues([0, 25, 50, 75, 100])
|
||||||
|
.tickFormat(d => d + '%')
|
||||||
|
|
||||||
|
const xAxisBottom = d3.axisBottom(x)
|
||||||
|
.tickValues([0, 25, 50, 75, 100])
|
||||||
|
.tickFormat(d => d + '%')
|
||||||
|
|
||||||
|
const yAxisLeft = d3.axisLeft(y)
|
||||||
|
|
||||||
|
const gridlines = d3.axisBottom(x)
|
||||||
|
.tickValues([0, 25, 50, 75, 100])
|
||||||
|
.tickFormat(d => '')
|
||||||
|
.tickSize(_height)
|
||||||
|
|
||||||
|
const yAxisRight = d3.axisRight(y)
|
||||||
|
.ticks(0)
|
||||||
|
.tickValues([])
|
||||||
|
.tickFormat(d => '')
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', `translate(0,0)`)
|
||||||
|
.attr("class", "grid-line")
|
||||||
|
.call(g => g.select('.domain').remove())
|
||||||
|
.call(gridlines)
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', `translate(0,0)`)
|
||||||
|
.call(xAxisTop)
|
||||||
|
|
||||||
|
svg.append("g")
|
||||||
|
.call(yAxisLeft)
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', `translate(0,${_height})`)
|
||||||
|
.call(xAxisBottom)
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', `translate(${_width},0)`)
|
||||||
|
.call(yAxisRight)
|
||||||
|
|
||||||
|
const layers = svg.append('g')
|
||||||
|
.selectAll('g')
|
||||||
|
.data(stackedData)
|
||||||
|
.join('g')
|
||||||
|
|
||||||
|
// transition for bars
|
||||||
|
const duration = 1000
|
||||||
|
const t = d3.transition()
|
||||||
|
.duration(duration)
|
||||||
|
.ease(d3.easeLinear)
|
||||||
|
|
||||||
|
layers.each(function() {
|
||||||
|
d3.select(this)
|
||||||
|
.selectAll('rect')
|
||||||
|
//@ts-ignore
|
||||||
|
.data(d => d)
|
||||||
|
.join('rect')
|
||||||
|
.attr('fill', (d, i) => colors ? colors[i] : 'black')
|
||||||
|
//@ts-ignore
|
||||||
|
.attr('y', d => y(d.data.name))
|
||||||
|
.attr('height', y.bandwidth())
|
||||||
|
//@ts-ignore
|
||||||
|
.transition(t)
|
||||||
|
//@ts-ignore
|
||||||
|
.attr('width', d => x(d.data.percent))
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
svg.selectAll("g").selectAll("*").remove()
|
||||||
|
}
|
||||||
|
}, [width, height, data])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={false} style={{width: givenWidth, height: givenHeight}}>
|
||||||
|
<div ref={rootRef} style={{width: '100%', height: '100%'}}>
|
||||||
|
<svg id={'d3-horizontal-chart'}></svg>
|
||||||
|
</div>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default D3HorizontalChart
|
153
src/pages/Telemetry/OperationTime/index.tsx
Normal file
153
src/pages/Telemetry/OperationTime/index.tsx
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import React, { ReactNode, useEffect, useState } from 'react'
|
||||||
|
import { Col, Row, Select } from 'antd'
|
||||||
|
import { Moment } from 'moment'
|
||||||
|
|
||||||
|
import { DateRangeWrapper, makeColumn, makeNumericRender, Table } from '@components/Table'
|
||||||
|
import LoaderPortal from '@components/LoaderPortal'
|
||||||
|
import { arrayOrDefault, wrapPrivateComponent } from '@utils'
|
||||||
|
import D3HorizontalChart from '@components/d3/D3HorizontalChart'
|
||||||
|
import { useWell } from '@asb/context'
|
||||||
|
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||||
|
import { SubsystemOperationTimeService } from '@api'
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
type DataType = {
|
||||||
|
idSubsystem: number
|
||||||
|
subsystemName: string
|
||||||
|
usedTimeHours: number
|
||||||
|
kUsage: number
|
||||||
|
sumDepthInterval: number
|
||||||
|
operationCount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const subsystemColors = [
|
||||||
|
'#1abc9c',
|
||||||
|
'#16a085',
|
||||||
|
'#2ecc71',
|
||||||
|
'#27ae60',
|
||||||
|
'#3498db',
|
||||||
|
'#2980b9',
|
||||||
|
'#9b59b6',
|
||||||
|
'#8e44ad',
|
||||||
|
'#34495e',
|
||||||
|
'#2c3e50',
|
||||||
|
'#f1c40f',
|
||||||
|
'#f39c12',
|
||||||
|
'#e67e22',
|
||||||
|
'#d35400',
|
||||||
|
'#e74c3c',
|
||||||
|
'#c0392b',
|
||||||
|
'#ecf0f1',
|
||||||
|
'#bdc3c7',
|
||||||
|
'#95a5a6',
|
||||||
|
'#7f8c8d',
|
||||||
|
]
|
||||||
|
|
||||||
|
const tableColumns = [
|
||||||
|
makeColumn('Цвет', 'color', { width: 50, render: (color) => (
|
||||||
|
<div style={{ backgroundColor: color, padding: '5px 0' }} />
|
||||||
|
) }),
|
||||||
|
makeColumn('Подсистема', 'subsystemName'),
|
||||||
|
makeColumn('% использования', 'kUsage', { render: val => (+val * 100).toFixed(2) }),
|
||||||
|
makeColumn('Проходка, м', 'sumDepthInterval', {render: makeNumericRender(2)}),
|
||||||
|
makeColumn('Время работы, ч', 'usedTimeHours', {render: makeNumericRender(2)}),
|
||||||
|
makeColumn('Кол-во запусков', 'operationCount'),
|
||||||
|
]
|
||||||
|
|
||||||
|
const OperationTime = () => {
|
||||||
|
const [showLoader, setShowLoader] = useState(false)
|
||||||
|
const [data, setData] = useState<DataType[]>([])
|
||||||
|
const [dateRange, setDateRange] = useState<Moment[]>([])
|
||||||
|
const [childrenData, setChildrenData] = useState<ReactNode[]>([])
|
||||||
|
const [well] = useWell()
|
||||||
|
|
||||||
|
const errorNotifyText = `Не удалось загрузить данные`
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
invokeWebApiWrapperAsync(
|
||||||
|
async () => {
|
||||||
|
if (!well.id) return
|
||||||
|
try {
|
||||||
|
setData(arrayOrDefault(await SubsystemOperationTimeService.getStat(
|
||||||
|
well.id,
|
||||||
|
undefined,
|
||||||
|
dateRange[1] ? dateRange[0]?.toISOString() : undefined,
|
||||||
|
dateRange[1]?.toISOString(),
|
||||||
|
)))
|
||||||
|
} catch(e) {
|
||||||
|
setData([])
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setShowLoader,
|
||||||
|
errorNotifyText,
|
||||||
|
{ actionName: 'Получение данных по скважине', well }
|
||||||
|
)
|
||||||
|
}, [dateRange])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setChildrenData(data.map((item) => (
|
||||||
|
<Option key={item.subsystemName}>
|
||||||
|
{item.subsystemName}
|
||||||
|
</Option>
|
||||||
|
)))
|
||||||
|
}, [data])
|
||||||
|
|
||||||
|
const selectChange = (value: string[]) => {
|
||||||
|
|
||||||
|
setData(data.reduce((previousValue: DataType[], currentValue) => {
|
||||||
|
if (value.includes(currentValue.subsystemName)) {
|
||||||
|
previousValue.push(currentValue)
|
||||||
|
}
|
||||||
|
return previousValue
|
||||||
|
}, []))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoaderPortal show={showLoader}>
|
||||||
|
<h3 className={'filter-group-heading'}>Фильтр подсистем</h3>
|
||||||
|
<Row align={'middle'} justify={'space-between'} wrap={false} style={{ backgroundColor: 'white' }}>
|
||||||
|
<Col span={18}>
|
||||||
|
<Select
|
||||||
|
mode="multiple"
|
||||||
|
defaultValue={data.map(d => d.subsystemName)}
|
||||||
|
onChange={selectChange}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
>
|
||||||
|
{childrenData}
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<DateRangeWrapper
|
||||||
|
onCalendarChange={(dateRange: any) => setDateRange(dateRange)}
|
||||||
|
value={[dateRange[0], dateRange[1]]}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<div style={{width: '100%', height: '50vh'}}>
|
||||||
|
<D3HorizontalChart
|
||||||
|
data={data.map(item => ({name: item.subsystemName, percent: item.kUsage * 100}))}
|
||||||
|
colors={subsystemColors}
|
||||||
|
width={'100%'}
|
||||||
|
height={'50vh'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
size={'small'}
|
||||||
|
columns={tableColumns}
|
||||||
|
dataSource={data.map((d, i) => ({...d, color: subsystemColors[i]}))}
|
||||||
|
scroll={{ y: '25vh', x: true }}
|
||||||
|
pagination={false}
|
||||||
|
/>
|
||||||
|
</LoaderPortal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default wrapPrivateComponent(OperationTime, {
|
||||||
|
requirements: [],
|
||||||
|
title: 'Наработка',
|
||||||
|
route: 'operation_time',
|
||||||
|
})
|
@ -12,6 +12,7 @@ import Messages from './Messages'
|
|||||||
import Operations from './Operations'
|
import Operations from './Operations'
|
||||||
import DashboardNNB from './DashboardNNB'
|
import DashboardNNB from './DashboardNNB'
|
||||||
import TelemetryView from './TelemetryView'
|
import TelemetryView from './TelemetryView'
|
||||||
|
import OperationTime from './OperationTime'
|
||||||
|
|
||||||
import '@styles/index.css'
|
import '@styles/index.css'
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ const Telemetry = memo(() => {
|
|||||||
<PrivateMenu.Link content={Archive} icon={<DatabaseOutlined />} />
|
<PrivateMenu.Link content={Archive} icon={<DatabaseOutlined />} />
|
||||||
<PrivateMenu.Link content={DashboardNNB} />
|
<PrivateMenu.Link content={DashboardNNB} />
|
||||||
<PrivateMenu.Link content={Operations} />
|
<PrivateMenu.Link content={Operations} />
|
||||||
|
<PrivateMenu.Link content={OperationTime} />
|
||||||
</PrivateMenu>
|
</PrivateMenu>
|
||||||
|
|
||||||
<Layout>
|
<Layout>
|
||||||
@ -43,6 +45,7 @@ const Telemetry = memo(() => {
|
|||||||
<Route path={Archive.route} element={<Archive />} />
|
<Route path={Archive.route} element={<Archive />} />
|
||||||
<Route path={DashboardNNB.route} element={<DashboardNNB />} />
|
<Route path={DashboardNNB.route} element={<DashboardNNB />} />
|
||||||
<Route path={Operations.route} element={<Operations />} />
|
<Route path={Operations.route} element={<Operations />} />
|
||||||
|
<Route path={OperationTime.route} element={<OperationTime />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
@ -1,17 +1,87 @@
|
|||||||
import { useState, useEffect, useCallback, memo, useMemo } from 'react'
|
import { useState, useEffect, useCallback, memo, useMemo } from 'react'
|
||||||
|
import { InputNumber } from 'antd'
|
||||||
|
|
||||||
import { useWell } from '@asb/context'
|
import { useWell } from '@asb/context'
|
||||||
import {
|
import {
|
||||||
EditableTable,
|
EditableTable,
|
||||||
makeSelectColumn,
|
makeSelectColumn,
|
||||||
makeNumericAvgRange,
|
makeGroupColumn,
|
||||||
|
makeNumericRender,
|
||||||
makeNumericSorter,
|
makeNumericSorter,
|
||||||
|
RegExpIsFloat,
|
||||||
} from '@components/Table'
|
} from '@components/Table'
|
||||||
import LoaderPortal from '@components/LoaderPortal'
|
import LoaderPortal from '@components/LoaderPortal'
|
||||||
import { invokeWebApiWrapperAsync } from '@components/factory'
|
import { invokeWebApiWrapperAsync } from '@components/factory'
|
||||||
import { DrillParamsService, WellOperationService } from '@api'
|
import { DrillParamsService, WellOperationService } from '@api'
|
||||||
import { arrayOrDefault } from '@utils'
|
import { arrayOrDefault } from '@utils'
|
||||||
|
|
||||||
|
import { makeNumericObjSorter } from '@components/Table/sorters'
|
||||||
|
|
||||||
|
const makeNumericObjRender = (fixed, columnKey) => (value, obj) => {
|
||||||
|
let val = '-'
|
||||||
|
const isSelected = obj && columnKey && obj[columnKey[0]] ? obj[columnKey[0]][columnKey[1]] : false
|
||||||
|
|
||||||
|
if ((value ?? null) !== null && Number.isFinite(+value)) {
|
||||||
|
val = (fixed ?? null) !== null
|
||||||
|
? (+value).toFixed(fixed)
|
||||||
|
: (+value).toPrecision(5)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`text-align-r-container ${isSelected ? 'color-pale-green' : ''}`}>
|
||||||
|
<span>{val}</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeNumericColumnOptionsWithColor = (fixed, sorterKey, columnKey) => ({
|
||||||
|
editable: true,
|
||||||
|
initialValue: 0,
|
||||||
|
width: 100,
|
||||||
|
sorter: sorterKey ? makeNumericObjSorter(sorterKey) : undefined,
|
||||||
|
formItemRules: [{
|
||||||
|
required: true,
|
||||||
|
message: 'Введите число',
|
||||||
|
pattern: RegExpIsFloat,
|
||||||
|
}],
|
||||||
|
render: makeNumericObjRender(fixed, columnKey),
|
||||||
|
})
|
||||||
|
|
||||||
|
const makeNumericObjColumn = (
|
||||||
|
title,
|
||||||
|
dataIndex,
|
||||||
|
filters,
|
||||||
|
filterDelegate,
|
||||||
|
renderDelegate,
|
||||||
|
width,
|
||||||
|
other
|
||||||
|
) => ({
|
||||||
|
title: title,
|
||||||
|
dataIndex: dataIndex,
|
||||||
|
key: dataIndex,
|
||||||
|
filters: filters,
|
||||||
|
onFilter: filterDelegate ? filterDelegate(dataIndex) : null,
|
||||||
|
sorter: makeNumericObjSorter(dataIndex),
|
||||||
|
width: width,
|
||||||
|
input: <InputNumber style={{ width: '100%' }}/>,
|
||||||
|
render: renderDelegate ?? makeNumericRender(),
|
||||||
|
align: 'right',
|
||||||
|
...other
|
||||||
|
})
|
||||||
|
|
||||||
|
const makeNumericAvgRange = (
|
||||||
|
title,
|
||||||
|
dataIndex,
|
||||||
|
fixed,
|
||||||
|
filters,
|
||||||
|
filterDelegate,
|
||||||
|
renderDelegate,
|
||||||
|
width
|
||||||
|
) => makeGroupColumn(title, [
|
||||||
|
makeNumericObjColumn('мин', [dataIndex, 'min'], filters, filterDelegate, renderDelegate, width, makeNumericColumnOptionsWithColor(fixed, [dataIndex, 'min'], [dataIndex, 'isMin'])),
|
||||||
|
makeNumericObjColumn('сред', [dataIndex, 'avg'], filters, filterDelegate, renderDelegate, width, makeNumericColumnOptionsWithColor(fixed, [dataIndex, 'avg'])),
|
||||||
|
makeNumericObjColumn('макс', [dataIndex, 'max'], filters, filterDelegate, renderDelegate, width, makeNumericColumnOptionsWithColor(fixed, [dataIndex, 'max'], [dataIndex, 'isMax']))
|
||||||
|
])
|
||||||
|
|
||||||
export const getColumns = async (idWell) => {
|
export const getColumns = async (idWell) => {
|
||||||
let sectionTypes = await WellOperationService.getSectionTypes(idWell)
|
let sectionTypes = await WellOperationService.getSectionTypes(idWell)
|
||||||
|
@ -116,6 +116,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid-line line {
|
||||||
|
stroke: #ddd;
|
||||||
|
stroke-dasharray: 4
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1800px) {
|
@media (max-width: 1800px) {
|
||||||
.asb-d3-chart .adaptive-tooltip {
|
.asb-d3-chart .adaptive-tooltip {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
@ -141,4 +141,16 @@ code {
|
|||||||
.download-link {
|
.download-link {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
padding: 4px 15px;
|
padding: 4px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-cell:has(.color-pale-green) {
|
||||||
|
background-color: #98fb98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-table-tbody > tr > td.ant-table-cell-row-hover:has( > div.color-pale-green) {
|
||||||
|
background: #98fb98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-pale-green {
|
||||||
|
background-color: #98fb98;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user