На странице Наработка добавлен сброс даты и выделение данных при наведении

This commit is contained in:
ts_salikhov 2022-10-05 14:20:39 +04:00
parent 74b309ee87
commit be7e76acf7
3 changed files with 68 additions and 27 deletions

View File

@ -11,6 +11,7 @@ const { RangePicker } = DatePicker
export type DateRangeWrapperProps = RangePickerSharedProps<Moment> & {
value?: RangeValue<Moment>,
isUTC?: boolean
allowClear?: boolean
}
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
showTime
allowClear={false}
allowClear={allowClear}
format={defaultFormat}
defaultValue={[
moment().subtract(1, 'days').startOf('day'),

View File

@ -7,7 +7,7 @@ import { useElementSize } from 'usehooks-ts'
import '@styles/d3.less'
type DataType = {
export type HorizontalChartDataType = {
name: string
percent: number
}
@ -15,16 +15,22 @@ type DataType = {
type D3HorizontalChartProps = {
width?: string
height?: string
data: DataType[]
data: HorizontalChartDataType[]
colors?: string[]
selected?: string | null
onMouseOver?: (e: MouseEvent, d: HorizontalChartDataType) => void
onMouseOut?: (e: MouseEvent, d: HorizontalChartDataType) => void
}
const D3HorizontalChart = memo((
export const D3HorizontalChart = memo((
{
width: givenWidth = '100%',
height: givenHeight = '100%',
selected,
data,
colors
colors,
onMouseOver,
onMouseOut,
}: D3HorizontalChartProps) => {
const [rootRef, { width, height }] = useElementSize()
@ -54,6 +60,7 @@ const D3HorizontalChart = memo((
const y = d3.scaleBand()
.domain(names)
.range([0, chartHeight])
.padding(0.25)
// axes
@ -113,16 +120,17 @@ const D3HorizontalChart = memo((
.attr('fill', (d, i) => colors ? colors[i] : 'black')
.attr('y', d => String(y(d.name)))
.attr('height', y.bandwidth())
.transition()
.duration(1000)
.ease(d3.easeLinear)
.attr('width', d => d.percent >= 0 ? x(d.percent) : 0)
.attr('stroke', d => selected && d.name === selected ? 'black' : '')
.attr('stroke-width', d => selected && d.name === selected ? '2' : '0')
.on('mouseover', onMouseOver ? onMouseOver : () => {})
.on('mouseout', onMouseOut ? onMouseOut : () => {})
})
return () => {
svg.remove()
}
}, [width, height, data])
}, [width, height, data, colors, selected, onMouseOver, onMouseOut])
return (
<LoaderPortal show={false} style={{width: givenWidth, height: givenHeight}}>

View File

@ -5,7 +5,7 @@ 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 { D3HorizontalChart, HorizontalChartDataType } from '@components/d3/D3HorizontalChart'
import { useWell } from '@asb/context'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { SubsystemOperationTimeService } from '@api'
@ -49,22 +49,50 @@ const tableColumns = [
<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'),
makeColumn('% использования', 'kUsage', { width: 200, render: val => makeNumericRender(2)(+val * 100) }),
makeColumn('Проходка, м', 'sumDepthInterval', { width: 200, render: makeNumericRender(2) }),
makeColumn('Время работы, ч', 'usedTimeHours', { width: 200, render: makeNumericRender(2) }),
makeColumn('Кол-во запусков', 'operationCount', { width: 200, render: makeNumericRender(0) }),
]
const OperationTime = memo(() => {
const [showLoader, setShowLoader] = useState(false)
const [data, setData] = useState<DataType[]>([])
const [selectedData, setSelectedData] = useState<DataType[]>([])
const [dateRange, setDateRange] = useState<Moment[]>([])
const [dateRange, setDateRange] = useState<Moment[] | null>([])
const [selected, setSelected] = useState<string | null>(null)
const [childrenData, setChildrenData] = useState<ReactNode[]>([])
const [well] = useWell()
const errorNotifyText = `Не удалось загрузить данные`
const onRow = useCallback((item: DataType) => {
const out = {
onMouseEnter: () => {
setSelected(item.subsystemName)
},
onMouseLeave: () => {
setSelected(null)
},
style: {}
}
if (item.subsystemName === selected) {
out.style = { background: '#FAFAFA', fontSize: '16px', fontWeight: '600' }
}
return out
}, [selected])
const onMouseOver = useCallback(function (e: MouseEvent, d: HorizontalChartDataType) {
setSelected(d.name)
}, [])
const onMouseOut = useCallback(function (e: MouseEvent, d: HorizontalChartDataType) {
setSelected(null)
}, [])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
@ -73,8 +101,8 @@ const OperationTime = memo(() => {
const responseData:DataType[] = arrayOrDefault(await SubsystemOperationTimeService.getStat(
well.id,
undefined,
dateRange[1] ? dateRange[0]?.toISOString() : undefined,
dateRange[1]?.toISOString(),
dateRange && dateRange[1] ? dateRange[0]?.toISOString() : undefined,
dateRange && dateRange[1] ? dateRange[1].toISOString() : undefined,
))
setData(responseData)
setSelectedData(responseData)
@ -124,25 +152,29 @@ const OperationTime = memo(() => {
</Col>
<Col span={6}>
<DateRangeWrapper
allowClear
allowEmpty={[true, true]}
onCalendarChange={(dateRange: any) => setDateRange(dateRange)}
value={[dateRange[0], dateRange[1]]}
value={[dateRange && dateRange[0], dateRange && dateRange[1]]}
/>
</Col>
</Row>
<div style={{width: '100%', height: '50vh'}}>
<D3HorizontalChart
data={selectedData.map(item => ({name: item.subsystemName, percent: item.kUsage * 100}))}
colors={subsystemColors}
selected={selected}
width={'100%'}
height={'50vh'}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
/>
</div>
<Table
size={'small'}
columns={tableColumns}
dataSource={selectedData.map((d, i) => ({...d, color: subsystemColors[i]}))}
scroll={{ y: '25vh', x: true }}
pagination={false}
onRow={onRow}
/>
</LoaderPortal>
)