Добавлен tooltip для графика операций время-день

This commit is contained in:
goodmice 2022-08-09 11:54:06 +05:00
parent 5511c06410
commit fc6646eb80
5 changed files with 82 additions and 9 deletions

View File

@ -8,7 +8,7 @@ import '@styles/detected_operations.less'
const displayNumber = makeDisplayValue({ fixed: 2 })
const makeTooltipRender = (category) => ([{ data: [data] }]) => (
export const makeTooltipRender = (category) => ([{ data: [data] }]) => (
<div className={'detected-operations-tooltip'}>
<span className={'tooltip-label'}>{data.operationCategory?.name}</span>
<span className={'tooltip-label'}>{formatDate(data.dateStart, undefined, 'DD.MM.YYYY')}</span>
@ -21,12 +21,12 @@ const makeTooltipRender = (category) => ([{ data: [data] }]) => (
<GridItem row={2} col={3}>{displayNumber(data.depthEnd)} м</GridItem>
</Grid>
<Grid style={{ marginTop: 0 }}>
<GridItem row={1} col={1}>{category?.name ?? 'Ключ'}:</GridItem>
<GridItem row={1} col={1}>{category?.keyValueName ?? 'Ключ'}:</GridItem>
<GridItem row={1} col={2}>{displayNumber(data.value)}</GridItem>
<GridItem row={1} col={3}>{category?.unit ?? '----'}</GridItem>
<GridItem row={1} col={3}>{category?.keyValueUnits ?? '----'}</GridItem>
<GridItem row={2} col={1}>Цель:</GridItem>
<GridItem row={2} col={2}>{displayNumber(data.operationValue?.targetValue)}</GridItem>
<GridItem row={2} col={3}>{category?.unit ?? '----'}</GridItem>
<GridItem row={2} col={3}>{category?.keyValueUnits ?? '----'}</GridItem>
</Grid>
</div>
)

View File

@ -70,7 +70,11 @@ const Operations = memo(() => {
invokeWebApiWrapperAsync(
async () => {
const categories = arrayOrDefault(await DetectedOperationService.getCategories())
setCategories(categories.map(({ id, name }) => ({ value: id, label: name })))
setCategories(categories.map((category) => ({
...category,
value: category.id,
label: category.name,
})))
},
setIsLoading,
'Не удалось загрзуить категории операций'

View File

@ -11,8 +11,13 @@ import { DetectedOperationService } from '@api'
import { unique } from '@utils/filters'
import { formatDate } from '@utils'
import { makeTooltipRender } from '@pages/Telemetry/Operations/OperationsChart'
import { makeGetColor } from '.'
import '@styles/d3.less'
import '@styles/tvd.less'
import '@styles/detected_operations.less'
const defaultOffset = { left: 40, right: 20, top: 20, bottom: 20 }
const zeroDate = moment('2000-01-01 00:00:00')
@ -42,10 +47,13 @@ export const TLChart = memo(({
backgroundColor = '#0000',
barHeight = 15,
offset = defaultOffset,
tooltipSize = { width: 200, height: 220 },
}) => {
const [isLoading, setIsLoading] = useState(false)
const [svgRef, setSvgRef] = useState()
const [data, setData] = useState()
const [selected, setSelected] = useState()
const [tooltipPos, setTooltipPos] = useState({ x: 0, y: 0 })
const getColor = useMemo(() => makeGetColor(data?.map((row) => row.idCategory).filter(unique)), [data])
@ -124,22 +132,54 @@ export const TLChart = memo(({
.attr('width', (d) => xAxis(d.endTime) - xAxis(d.startTime))
.attr('height', barHeight)
.attr('fill', (d) => getColor(d.idCategory))
.on('mouseover', (e, data) => {
d3.select(svgRef).select('.chart-area')
.selectAll('rect')
.filter((d) => d.idCategory === data.idCategory)
.attr('stroke-width', '2px')
const rect = e.target.getBoundingClientRect()
setTooltipPos({ x: rect.x, y: rect.y })
setSelected(data)
})
.on('mouseout', (e, data) => {
d3.select(svgRef).select('.chart-area')
.selectAll('rect')
.filter((d) => d.idCategory === data.idCategory)
.attr('stroke-width', '0')
setSelected(null)
})
}, [svgRef, xAxis, yAxis, data, getColor])
const tooltipStyle = useMemo(() => {
return {
...tooltipSize,
left: tooltipPos.x - tooltipSize.width - 8,
top: tooltipPos.y - tooltipSize.height / 2 + barHeight / 2,
}
}, [tooltipPos, tooltipSize, barHeight])
return (
<div className={'tvd-right'} ref={rootRef}>
<LoaderPortal show={isLoading} style={{ width: '100%', flexGrow: 1 }}>
<LoaderPortal show={isLoading} className={'asb-d3-chart'}>
{selected && (
<div className={'tl-op-tooltip'} style={tooltipStyle}>
<div className={'tooltip right'}>
{makeTooltipRender(selected.operationCategory)([{ data: [selected] }])}
</div>
</div>
)}
{data ? (
<svg ref={setSvgRef} width={'100%'} height={'100%'}>
<svg className={'tl-op-chart'} ref={setSvgRef} width={'100%'} height={'100%'}>
<g className={'axis x'} transform={`translate(${offset.left}, ${offset.top})`} />
<g className={'axis y'} transform={`translate(${offset.left}, ${offset.top + barHeight})`} />
<g className={'chart-area'} transform={`translate(${offset.left}, ${offset.top + barHeight})`} stroke={'none'} />
<g className={'chart-area'} transform={`translate(${offset.left}, ${offset.top + barHeight})`} stroke={'red'} strokeWidth={'0'} />
<rect
x={offset.left}
y={offset.top}
width={Math.max(width - offset.left - offset.right, 0)}
height={Math.max(height - offset.top - offset.bottom, 0)}
fill={backgroundColor}
pointerEvents={'none'}
/>
</svg>
) : (

View File

@ -41,7 +41,7 @@
&.bottom {
margin-top: 0;
margin-bottom: @arrow-size;
&::after {
border-top-color: @bg-color;
@ -51,6 +51,24 @@
}
}
&.left {
margin-left: @arrow-size;
&::after {
border-right-color: @bg-color;
top: 50%;
right: 100%;
}
}
&.right {
margin-right: @arrow-size;
&::after {
border-left-color: @bg-color;
top: 50%;
left: 100%;
}
}
& .tooltip-content {
overflow: hidden;
width: 100%;

View File

@ -86,6 +86,17 @@
justify-content: center;
}
.tl-op-tooltip {
position: absolute;
pointer-events: none;
}
.tl-op-chart {
& .chart-area > rect {
transition: stroke-width .25s ease-in-out;
}
}
.tl-pie {
display: flex;
flex-direction: column;