forked from ddrilling/asb_cloud_front
Merge branch 'dev' into feature/sider-navigation-menu
This commit is contained in:
commit
530001d110
@ -11,6 +11,7 @@ const { RangePicker } = DatePicker
|
|||||||
export type DateRangeWrapperProps = RangePickerSharedProps<Moment> & {
|
export type DateRangeWrapperProps = RangePickerSharedProps<Moment> & {
|
||||||
value?: RangeValue<Moment>,
|
value?: RangeValue<Moment>,
|
||||||
isUTC?: boolean
|
isUTC?: boolean
|
||||||
|
allowClear?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizeDates = (value?: RangeValue<Moment>, isUTC?: boolean): RangeValue<Moment> => {
|
const normalizeDates = (value?: RangeValue<Moment>, isUTC?: boolean): RangeValue<Moment> => {
|
||||||
@ -21,10 +22,10 @@ const normalizeDates = (value?: RangeValue<Moment>, isUTC?: boolean): RangeValue
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DateRangeWrapper = memo<DateRangeWrapperProps>(({ value, isUTC, ...other }) => (
|
export const DateRangeWrapper = memo<DateRangeWrapperProps>(({ value, isUTC, allowClear = false, ...other }) => (
|
||||||
<RangePicker
|
<RangePicker
|
||||||
showTime
|
showTime
|
||||||
allowClear={false}
|
allowClear={allowClear}
|
||||||
format={defaultFormat}
|
format={defaultFormat}
|
||||||
defaultValue={[
|
defaultValue={[
|
||||||
moment().subtract(1, 'days').startOf('day'),
|
moment().subtract(1, 'days').startOf('day'),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { memo, useEffect, useMemo, useRef } from 'react'
|
import { memo, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||||
import { useElementSize } from 'usehooks-ts'
|
import { useElementSize } from 'usehooks-ts'
|
||||||
import { Property } from 'csstype'
|
import { Property } from 'csstype'
|
||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3'
|
||||||
@ -20,6 +20,7 @@ export type D3HorizontalChartProps = {
|
|||||||
height?: Property.Height
|
height?: Property.Height
|
||||||
data: PercentChartDataType[]
|
data: PercentChartDataType[]
|
||||||
offset?: Partial<ChartOffset>
|
offset?: Partial<ChartOffset>
|
||||||
|
afterDraw?: (d: d3.Selection<SVGRectElement, PercentChartDataType, SVGGElement, unknown>) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOffset = { top: 50, right: 100, bottom: 50, left: 100 }
|
const defaultOffset = { top: 50, right: 100, bottom: 50, left: 100 }
|
||||||
@ -29,13 +30,14 @@ export const D3HorizontalPercentChart = memo<D3HorizontalChartProps>(({
|
|||||||
height: givenHeight = '100%',
|
height: givenHeight = '100%',
|
||||||
offset: givenOffset,
|
offset: givenOffset,
|
||||||
data,
|
data,
|
||||||
|
afterDraw,
|
||||||
}) => {
|
}) => {
|
||||||
const offset = usePartialProps<ChartOffset>(givenOffset, defaultOffset)
|
const offset = usePartialProps<ChartOffset>(givenOffset, defaultOffset)
|
||||||
|
|
||||||
const [divRef, { width, height }] = useElementSize()
|
const [divRef, { width, height }] = useElementSize()
|
||||||
const rootRef = useRef<SVGGElement | null>(null)
|
const rootRef = useRef<SVGGElement | null>(null)
|
||||||
|
|
||||||
const root = useMemo(() => rootRef.current ? d3.select(rootRef.current) : null, [rootRef.current])
|
const root = useCallback(() => rootRef.current ? d3.select(rootRef.current) : null, [rootRef.current])
|
||||||
|
|
||||||
const inlineWidth = useMemo(() => width - offset.left - offset.right, [width])
|
const inlineWidth = useMemo(() => width - offset.left - offset.right, [width])
|
||||||
const inlineHeight = useMemo(() => height - offset.top - offset.bottom, [height])
|
const inlineHeight = useMemo(() => height - offset.top - offset.bottom, [height])
|
||||||
@ -44,42 +46,50 @@ export const D3HorizontalPercentChart = memo<D3HorizontalChartProps>(({
|
|||||||
const yScale = useMemo(() => d3.scaleBand().domain(data.map((d) => d.name)).range([0, inlineHeight]).padding(0.25), [data, inlineHeight])
|
const yScale = useMemo(() => d3.scaleBand().domain(data.map((d) => d.name)).range([0, inlineHeight]).padding(0.25), [data, inlineHeight])
|
||||||
|
|
||||||
useEffect(() => { /// Отрисовываем оси X сверху и снизу
|
useEffect(() => { /// Отрисовываем оси X сверху и снизу
|
||||||
if (width < 100 || height < 100 || !root) return
|
const r = root()
|
||||||
|
if (width < 100 || height < 100 || !r) return
|
||||||
const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).ticks(4).tickSize(-inlineHeight)
|
const xAxisTop = d3.axisTop(xScale).tickFormat((d) => `${d}%`).ticks(4).tickSize(-inlineHeight)
|
||||||
const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).ticks(4)
|
const xAxisBottom = d3.axisBottom(xScale).tickFormat((d) => `${d}%`).ticks(4)
|
||||||
|
|
||||||
root.selectChild<SVGGElement>('.axis.x.bottom').call(xAxisBottom)
|
r.selectChild<SVGGElement>('.axis.x.bottom').call(xAxisBottom)
|
||||||
root.selectChild<SVGGElement>('.axis.x.top').call(xAxisTop)
|
r.selectChild<SVGGElement>('.axis.x.top').call(xAxisTop)
|
||||||
.selectAll('.tick')
|
.selectAll('.tick')
|
||||||
.attr('class', 'tick grid-line')
|
.attr('class', 'tick grid-line')
|
||||||
}, [root, width, height, xScale, inlineHeight])
|
}, [root, width, height, xScale, inlineHeight])
|
||||||
|
|
||||||
useEffect(() => { /// Отрисовываем ось Y слева
|
useEffect(() => { /// Отрисовываем ось Y слева
|
||||||
if (width < 100 || height < 100 || !root) return
|
const r = root()
|
||||||
root.selectChild<SVGGElement>('.axis.y.left').call(d3.axisLeft(yScale))
|
if (width < 100 || height < 100 || !r) return
|
||||||
|
r.selectChild<SVGGElement>('.axis.y.left').call(d3.axisLeft(yScale))
|
||||||
}, [root, width, height, yScale])
|
}, [root, width, height, yScale])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (width < 100 || height < 100 || !root) return
|
const r = root()
|
||||||
|
if (width < 100 || height < 100 || !r) return
|
||||||
|
|
||||||
const delay = d3.transition().duration(500).ease(d3.easeLinear)
|
const delay = d3.transition().duration(500).ease(d3.easeLinear)
|
||||||
|
|
||||||
const rects = root.selectChild('.data').selectAll('rect').data(data)
|
const rects = r.selectChild('.data').selectAll('rect').data(data)
|
||||||
rects.enter().append('rect')
|
rects.enter().append('rect')
|
||||||
rects.exit().remove()
|
rects.exit().remove()
|
||||||
root.selectChild<SVGGElement>('.data')
|
|
||||||
.selectAll<SVGRectElement, PercentChartDataType>('rect')
|
const selectedRects = r.selectChild<SVGGElement>('.data')
|
||||||
.attr('fill', (d) => d.color || 'black')
|
.selectAll<SVGRectElement, PercentChartDataType>('rect')
|
||||||
.attr('y', (d) => yScale(d.name) ?? null)
|
|
||||||
.attr('height', yScale.bandwidth())
|
selectedRects.attr('fill', (d) => d.color || 'black')
|
||||||
.transition(delay)
|
.attr('y', (d) => yScale(d.name) ?? null)
|
||||||
.attr('width', (d) => xScale(d.percent))
|
.attr('height', yScale.bandwidth())
|
||||||
}, [data, width, height, root, yScale, xScale])
|
.transition(delay)
|
||||||
|
.attr('width', (d) => d.percent > 0 ? xScale(d.percent) : 0)
|
||||||
|
|
||||||
|
afterDraw?.(selectedRects)
|
||||||
|
|
||||||
|
}, [data, width, height, root, yScale, xScale, afterDraw])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoaderPortal show={false} style={{ width: givenWidth, height: givenHeight }}>
|
<LoaderPortal show={false} style={{ width: givenWidth, height: givenHeight }}>
|
||||||
<div ref={divRef} style={{ width: '100%', height: '100%' }}>
|
<div ref={divRef} style={{ width: '100%', height: '100%' }}>
|
||||||
<svg id={'d3-horizontal-chart'} width={'100%'} height={'100%'}>
|
<svg width={'100%'} height={'100%'}>
|
||||||
<g ref={rootRef} transform={`translate(${offset.left}, ${offset.top})`}>
|
<g ref={rootRef} transform={`translate(${offset.left}, ${offset.top})`}>
|
||||||
<g className={'axis x top'}></g>
|
<g className={'axis x top'}></g>
|
||||||
<g className={'axis x bottom'} transform={`translate(0, ${inlineHeight})`}></g>
|
<g className={'axis x bottom'} transform={`translate(0, ${inlineHeight})`}></g>
|
||||||
|
@ -61,6 +61,8 @@ export const DocumentsTemplate = ({ idCategory, well: givenWell, mimeTypes, head
|
|||||||
filterFileName,
|
filterFileName,
|
||||||
begin,
|
begin,
|
||||||
end,
|
end,
|
||||||
|
undefined,
|
||||||
|
false,
|
||||||
(page - 1) * pageSize,
|
(page - 1) * pageSize,
|
||||||
pageSize,
|
pageSize,
|
||||||
)
|
)
|
||||||
|
@ -74,7 +74,7 @@ export const CategoryHistory = ({ idCategory, visible, onClose }) => {
|
|||||||
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
|
const [begin, end] = range?.length > 1 ? [range[0].toISOString(), range[1].toISOString()] : [null, null]
|
||||||
const skip = (page - 1) * pageSize
|
const skip = (page - 1) * pageSize
|
||||||
|
|
||||||
const paginatedHistory = await FileService.getFilesInfo(well.caption, idCategory, companyName, fileName, begin, end, skip, pageSize)
|
const paginatedHistory = await FileService.getFilesInfo(well.caption, idCategory, companyName, fileName, begin, end, undefined, false, skip, pageSize)
|
||||||
setTotal(paginatedHistory?.count ?? 0)
|
setTotal(paginatedHistory?.count ?? 0)
|
||||||
setData(arrayOrDefault(paginatedHistory?.items))
|
setData(arrayOrDefault(paginatedHistory?.items))
|
||||||
},
|
},
|
||||||
|
@ -22,14 +22,14 @@ const subsystemColors = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const tableColumns = [
|
const tableColumns = [
|
||||||
makeColumn('Цвет', 'color', { width: 50, render: (backgroundColor) => (
|
makeColumn('Цвет', 'color', { width: 60, render: (backgroundColor) => (
|
||||||
<div className={'table_color'} style={{ backgroundColor }} />
|
<div className={'table_color'} style={{ backgroundColor }} />
|
||||||
)}),
|
)}),
|
||||||
makeTextColumn('Подсистема', 'subsystemName'),
|
makeTextColumn('Подсистема', 'subsystemName'),
|
||||||
makeNumericColumn('Использование, %', 'kUsage', undefined, undefined, val => (+val * 100).toFixed(2)),
|
makeNumericColumn('Использование, %', 'kUsage', undefined, undefined, val => (+val * 100).toFixed(2), 200),
|
||||||
makeNumericColumn('Проходка, м', 'sumDepthInterval'),
|
makeNumericColumn('Проходка, м', 'sumDepthInterval', undefined, undefined, undefined, 200),
|
||||||
makeNumericColumn('Время работы, ч', 'usedTimeHours'),
|
makeNumericColumn('Время работы, ч', 'usedTimeHours', undefined, undefined, undefined, 200),
|
||||||
makeNumericColumn('Кол-во запусков', 'operationCount', undefined, undefined, makeNumericRender(0)),
|
makeNumericColumn('Кол-во запусков', 'operationCount', undefined, undefined, makeNumericRender(0), 200),
|
||||||
]
|
]
|
||||||
|
|
||||||
// Выбор доступен только до текущей даты
|
// Выбор доступен только до текущей даты
|
||||||
@ -65,15 +65,15 @@ export const OperationTime = memo(() => {
|
|||||||
if (!well.id) return
|
if (!well.id) return
|
||||||
|
|
||||||
// Ограничение задаётся только если выбраны обе даты
|
// Ограничение задаётся только если выбраны обе даты
|
||||||
const startDate = dateRange[1] ? dateRange[0]?.toISOString() : undefined
|
const startDate = dateRange?.[1] ? dateRange[0]?.toISOString() : undefined
|
||||||
const endDate = dateRange[1]?.toISOString()
|
const endDate = dateRange?.[1] ? dateRange[1]?.toISOString() : undefined
|
||||||
|
|
||||||
const data = await SubsystemOperationTimeService.getStat(well.id, undefined, startDate, endDate)
|
const data = await SubsystemOperationTimeService.getStat(well.id, undefined, startDate, endDate)
|
||||||
// Выбираем цвета для подсистем (если цветов не хватает начинаем сначала)
|
// Выбираем цвета для подсистем (если цветов не хватает начинаем сначала)
|
||||||
const coloredData = arrayOrDefault(data).map((d, i) => ({ ...d, color: subsystemColors[i % subsystemColors.length] }))
|
const coloredData = arrayOrDefault(data).map((d, i) => ({ ...d, color: subsystemColors[i % subsystemColors.length] }))
|
||||||
|
|
||||||
setData(coloredData)
|
setData(coloredData)
|
||||||
setSelected(data.map((d) => d.idSubsystem)) // По-умолчанию выбираем все подсистемы
|
setSelected(data?.map((d) => d.idSubsystem)) // По-умолчанию выбираем все подсистемы
|
||||||
},
|
},
|
||||||
setShowLoader,
|
setShowLoader,
|
||||||
`Не удалось загрузить данные`,
|
`Не удалось загрузить данные`,
|
||||||
@ -95,6 +95,7 @@ export const OperationTime = memo(() => {
|
|||||||
value={selected}
|
value={selected}
|
||||||
/>
|
/>
|
||||||
<DateRangeWrapper
|
<DateRangeWrapper
|
||||||
|
allowClear
|
||||||
onCalendarChange={setDateRange}
|
onCalendarChange={setDateRange}
|
||||||
disabledDate={disabledDates}
|
disabledDate={disabledDates}
|
||||||
disabledTime={disabledTimes}
|
disabledTime={disabledTimes}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
.table_color {
|
.table_color {
|
||||||
padding: 5px 0;
|
padding: 5px 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user