Merge pull request #4193 from influxdata/enhancements/refactor-tablegraph
Refactor table graph and multi grid to remove unused functionalitypull/4208/head
commit
ff2ce4f8d5
|
@ -91,10 +91,10 @@ const updateMaxWidths = (
|
||||||
|
|
||||||
const currentWidth = useTimeWidth
|
const currentWidth = useTimeWidth
|
||||||
? timeFormatWidth
|
? timeFormatWidth
|
||||||
: calculateSize(colValue, {
|
: calculateSize(colValue.toString().trim(), {
|
||||||
font: isLabel ? '"Roboto"' : '"RobotoMono", monospace',
|
font: isLabel ? '"Roboto"' : '"RobotoMono", monospace',
|
||||||
fontSize: '13px',
|
fontSize: '12px',
|
||||||
fontWeight: 'bold',
|
fontWeight: '500',
|
||||||
}).width + CELL_HORIZONTAL_PADDING
|
}).width + CELL_HORIZONTAL_PADDING
|
||||||
|
|
||||||
const {widths: Widths} = maxColumnWidths
|
const {widths: Widths} = maxColumnWidths
|
||||||
|
@ -151,6 +151,7 @@ export const calculateColumnWidths = (
|
||||||
const timeFormatWidth = calculateTimeColumnWidth(
|
const timeFormatWidth = calculateTimeColumnWidth(
|
||||||
timeFormat === '' ? DEFAULT_TIME_FORMAT : timeFormat
|
timeFormat === '' ? DEFAULT_TIME_FORMAT : timeFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
return fastReduce<TimeSeriesValue[], ColumnWidths>(
|
return fastReduce<TimeSeriesValue[], ColumnWidths>(
|
||||||
data,
|
data,
|
||||||
(acc: ColumnWidths, row: TimeSeriesValue[], r: number) => {
|
(acc: ColumnWidths, row: TimeSeriesValue[], r: number) => {
|
||||||
|
|
|
@ -74,6 +74,7 @@ class Layout extends Component<Props> {
|
||||||
) : (
|
) : (
|
||||||
<RefreshingGraph
|
<RefreshingGraph
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
|
timeFormat={cell.timeFormat}
|
||||||
axes={cell.axes}
|
axes={cell.axes}
|
||||||
type={cell.type}
|
type={cell.type}
|
||||||
inView={cell.inView}
|
inView={cell.inView}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import CellMeasurerCacheDecorator from './CellMeasurerCacheDecorator'
|
import _ from 'lodash'
|
||||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||||
import {Grid} from 'react-virtualized'
|
import {Grid, AutoSizer} from 'react-virtualized'
|
||||||
|
|
||||||
const SCROLLBAR_SIZE_BUFFER = 20
|
const SCROLLBAR_SIZE_BUFFER = 20
|
||||||
|
const ROW_HEIGHT = 30
|
||||||
|
|
||||||
type HeightWidthFunction = (arg: {index: number}) => number
|
type HeightWidthFunction = (arg: {index: number}) => number
|
||||||
|
|
||||||
export interface PropsMultiGrid {
|
export interface PropsMultiGrid {
|
||||||
|
@ -14,24 +16,16 @@ export interface PropsMultiGrid {
|
||||||
classNameBottomRightGrid?: string
|
classNameBottomRightGrid?: string
|
||||||
classNameTopLeftGrid?: string
|
classNameTopLeftGrid?: string
|
||||||
classNameTopRightGrid?: string
|
classNameTopRightGrid?: string
|
||||||
enableFixedColumnScroll?: boolean
|
|
||||||
enableFixedRowScroll?: boolean
|
|
||||||
fixedColumnCount?: number
|
fixedColumnCount?: number
|
||||||
fixedRowCount?: number
|
fixedRowCount?: number
|
||||||
style?: object
|
scrollToRow?: number
|
||||||
styleBottomLeftGrid?: object
|
scrollToColumn?: number
|
||||||
styleBottomRightGrid?: object
|
|
||||||
styleTopLeftGrid?: object
|
|
||||||
styleTopRightGrid?: object
|
|
||||||
scrollTop?: number
|
|
||||||
scrollLeft?: number
|
|
||||||
rowCount?: number
|
rowCount?: number
|
||||||
rowHeight?: number | HeightWidthFunction
|
rowHeight?: number | HeightWidthFunction
|
||||||
columnWidth?: number | HeightWidthFunction
|
columnWidth?: number | HeightWidthFunction
|
||||||
onScroll?: (arg: object) => {}
|
onScroll?: (arg: object) => {}
|
||||||
onSectionRendered?: () => {}
|
|
||||||
cellRenderer?: (arg: object) => JSX.Element
|
cellRenderer?: (arg: object) => JSX.Element
|
||||||
[key: string]: any // MultiGrid can accept any prop, and will rerender if they change
|
onMount?: (mg: MultiGrid) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -42,83 +36,32 @@ interface State {
|
||||||
showVerticalScrollbar: boolean
|
showVerticalScrollbar: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders 1, 2, or 4 Grids depending on configuration.
|
|
||||||
* A main (body) Grid will always be rendered.
|
|
||||||
* Optionally, 1-2 Grids for sticky header rows will also be rendered.
|
|
||||||
* If no sticky columns, only 1 sticky header Grid will be rendered.
|
|
||||||
* If sticky columns, 2 sticky header Grids will be rendered.
|
|
||||||
*/
|
|
||||||
class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
public static defaultProps = {
|
public static defaultProps = {
|
||||||
classNameBottomLeftGrid: '',
|
classNameBottomLeftGrid: '',
|
||||||
classNameBottomRightGrid: '',
|
classNameBottomRightGrid: '',
|
||||||
classNameTopLeftGrid: '',
|
classNameTopLeftGrid: '',
|
||||||
classNameTopRightGrid: '',
|
classNameTopRightGrid: '',
|
||||||
enableFixedColumnScroll: false,
|
|
||||||
enableFixedRowScroll: false,
|
|
||||||
fixedColumnCount: 0,
|
fixedColumnCount: 0,
|
||||||
fixedRowCount: 0,
|
fixedRowCount: 0,
|
||||||
scrollToColumn: -1,
|
scrollToColumn: -1,
|
||||||
scrollToRow: -1,
|
scrollToRow: -1,
|
||||||
style: {},
|
|
||||||
styleBottomLeftGrid: {},
|
styleBottomLeftGrid: {},
|
||||||
styleBottomRightGrid: {},
|
styleBottomRightGrid: {},
|
||||||
styleTopLeftGrid: {},
|
styleTopLeftGrid: {},
|
||||||
styleTopRightGrid: {},
|
styleTopRightGrid: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
public static getDerivedStateFromProps(
|
|
||||||
nextProps: PropsMultiGrid,
|
|
||||||
prevState: State
|
|
||||||
) {
|
|
||||||
if (
|
|
||||||
nextProps.scrollLeft !== prevState.scrollLeft ||
|
|
||||||
nextProps.scrollTop !== prevState.scrollTop
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
scrollLeft:
|
|
||||||
nextProps.scrollLeft != null && nextProps.scrollLeft >= 0
|
|
||||||
? nextProps.scrollLeft
|
|
||||||
: prevState.scrollLeft,
|
|
||||||
scrollTop:
|
|
||||||
nextProps.scrollTop != null && nextProps.scrollTop >= 0
|
|
||||||
? nextProps.scrollTop
|
|
||||||
: prevState.scrollTop,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private deferredInvalidateColumnIndex: number = 0
|
|
||||||
private deferredInvalidateRowIndex: number = 0
|
|
||||||
private bottomLeftGrid: Grid
|
private bottomLeftGrid: Grid
|
||||||
private bottomRightGrid: Grid
|
private bottomRightGrid: Grid
|
||||||
private topLeftGrid: Grid
|
private topLeftGrid: Grid
|
||||||
private topRightGrid: Grid
|
private topRightGrid: Grid
|
||||||
private deferredMeasurementCacheBottomLeftGrid: CellMeasurerCacheDecorator
|
|
||||||
private deferredMeasurementCacheBottomRightGrid: CellMeasurerCacheDecorator
|
|
||||||
private deferredMeasurementCacheTopRightGrid: CellMeasurerCacheDecorator
|
|
||||||
private leftGridWidth: number | null = 0
|
private leftGridWidth: number | null = 0
|
||||||
private topGridHeight: number | null = 0
|
private topGridHeight: number | null = 0
|
||||||
private lastRenderedColumnWidth: number | HeightWidthFunction
|
|
||||||
private lastRenderedFixedColumnCount: number = 0
|
|
||||||
private lastRenderedFixedRowCount: number = 0
|
|
||||||
private lastRenderedRowHeight: number | HeightWidthFunction
|
|
||||||
private bottomRightGridStyle: object | null
|
|
||||||
private topRightGridStyle: object | null
|
private topRightGridStyle: object | null
|
||||||
private lastRenderedStyle: object | null
|
|
||||||
private lastRenderedHeight: number = 0
|
|
||||||
private lastRenderedWidth: number = 0
|
|
||||||
private containerTopStyle: object | null
|
private containerTopStyle: object | null
|
||||||
private containerBottomStyle: object | null
|
private containerBottomStyle: object | null
|
||||||
private containerOuterStyle: object | null
|
private containerOuterStyle: object | null
|
||||||
private lastRenderedStyleBottomLeftGrid: object | null
|
|
||||||
private lastRenderedStyleBottomRightGrid: object | null
|
|
||||||
private lastRenderedStyleTopLeftGrid: object | null
|
|
||||||
private lastRenderedStyleTopRightGrid: object | null
|
|
||||||
private bottomLeftGridStyle: object | null
|
|
||||||
private topLeftGridStyle: object | null
|
private topLeftGridStyle: object | null
|
||||||
|
|
||||||
constructor(props: PropsMultiGrid, context) {
|
constructor(props: PropsMultiGrid, context) {
|
||||||
|
@ -131,82 +74,6 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
showHorizontalScrollbar: false,
|
showHorizontalScrollbar: false,
|
||||||
showVerticalScrollbar: false,
|
showVerticalScrollbar: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
const {deferredMeasurementCache, fixedColumnCount, fixedRowCount} = props
|
|
||||||
|
|
||||||
this.maybeCalculateCachedStyles(true)
|
|
||||||
|
|
||||||
if (deferredMeasurementCache) {
|
|
||||||
this.deferredMeasurementCacheBottomLeftGrid =
|
|
||||||
fixedRowCount > 0
|
|
||||||
? new CellMeasurerCacheDecorator({
|
|
||||||
cellMeasurerCache: deferredMeasurementCache,
|
|
||||||
columnIndexOffset: 0,
|
|
||||||
rowIndexOffset: fixedRowCount,
|
|
||||||
})
|
|
||||||
: deferredMeasurementCache
|
|
||||||
|
|
||||||
this.deferredMeasurementCacheBottomRightGrid =
|
|
||||||
fixedColumnCount > 0 || fixedRowCount > 0
|
|
||||||
? new CellMeasurerCacheDecorator({
|
|
||||||
cellMeasurerCache: deferredMeasurementCache,
|
|
||||||
columnIndexOffset: fixedColumnCount,
|
|
||||||
rowIndexOffset: fixedRowCount,
|
|
||||||
})
|
|
||||||
: deferredMeasurementCache
|
|
||||||
|
|
||||||
this.deferredMeasurementCacheTopRightGrid =
|
|
||||||
fixedColumnCount > 0
|
|
||||||
? new CellMeasurerCacheDecorator({
|
|
||||||
cellMeasurerCache: deferredMeasurementCache,
|
|
||||||
columnIndexOffset: fixedColumnCount,
|
|
||||||
rowIndexOffset: 0,
|
|
||||||
})
|
|
||||||
: deferredMeasurementCache
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public forceUpdateGrids() {
|
|
||||||
if (this.bottomLeftGrid) {
|
|
||||||
this.bottomLeftGrid.forceUpdate()
|
|
||||||
}
|
|
||||||
if (this.bottomRightGrid) {
|
|
||||||
this.bottomRightGrid.forceUpdate()
|
|
||||||
}
|
|
||||||
if (this.topLeftGrid) {
|
|
||||||
this.topLeftGrid.forceUpdate()
|
|
||||||
}
|
|
||||||
if (this.topRightGrid) {
|
|
||||||
this.topRightGrid.forceUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** See Grid#invalidateCellSizeAfterRender */
|
|
||||||
public invalidateCellSizeAfterRender({columnIndex = 0, rowIndex = 0} = {}) {
|
|
||||||
this.deferredInvalidateColumnIndex =
|
|
||||||
typeof this.deferredInvalidateColumnIndex === 'number'
|
|
||||||
? Math.min(this.deferredInvalidateColumnIndex, columnIndex)
|
|
||||||
: columnIndex
|
|
||||||
this.deferredInvalidateRowIndex =
|
|
||||||
typeof this.deferredInvalidateRowIndex === 'number'
|
|
||||||
? Math.min(this.deferredInvalidateRowIndex, rowIndex)
|
|
||||||
: rowIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
/** See Grid#measureAllCells */
|
|
||||||
public measureAllCells() {
|
|
||||||
if (this.bottomLeftGrid) {
|
|
||||||
this.bottomLeftGrid.measureAllCells()
|
|
||||||
}
|
|
||||||
if (this.bottomRightGrid) {
|
|
||||||
this.bottomRightGrid.measureAllCells()
|
|
||||||
}
|
|
||||||
if (this.topLeftGrid) {
|
|
||||||
this.topLeftGrid.measureAllCells()
|
|
||||||
}
|
|
||||||
if (this.topRightGrid) {
|
|
||||||
this.topRightGrid.measureAllCells()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public recomputeGridSize({columnIndex = 0, rowIndex = 0} = {}) {
|
public recomputeGridSize({columnIndex = 0, rowIndex = 0} = {}) {
|
||||||
|
@ -248,50 +115,20 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
const {scrollLeft, scrollTop} = this.props
|
if (this.props.onMount) {
|
||||||
|
this.props.onMount(this)
|
||||||
if (scrollLeft > 0 || scrollTop > 0) {
|
|
||||||
const newState: Partial<State> = {}
|
|
||||||
|
|
||||||
if (scrollLeft > 0) {
|
|
||||||
newState.scrollLeft = scrollLeft
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollTop > 0) {
|
|
||||||
newState.scrollTop = scrollTop
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({...this.state, ...newState})
|
|
||||||
}
|
}
|
||||||
this.handleInvalidatedGridSize()
|
|
||||||
}
|
|
||||||
|
|
||||||
public componentDidUpdate() {
|
|
||||||
this.handleInvalidatedGridSize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {
|
const {onScroll, ...rest} = this.props
|
||||||
onScroll,
|
|
||||||
scrollLeft: scrollLeftProp, // eslint-disable-line no-unused-vars
|
|
||||||
onSectionRendered,
|
|
||||||
scrollToRow,
|
|
||||||
scrollToColumn,
|
|
||||||
scrollTop: scrollTopProp, // eslint-disable-line no-unused-vars
|
|
||||||
...rest
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
this.prepareForRender()
|
this.prepareForRender()
|
||||||
|
|
||||||
// Don't render any of our Grids if there are no cells.
|
|
||||||
// This mirrors what Grid does,
|
|
||||||
// And prevents us from recording inaccurage measurements when used with CellMeasurer.
|
|
||||||
if (this.props.width === 0 || this.props.height === 0) {
|
if (this.props.width === 0 || this.props.height === 0) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// scrollTop and scrollLeft props are explicitly filtered out and ignored
|
|
||||||
|
|
||||||
const {scrollLeft, scrollTop} = this.state
|
const {scrollLeft, scrollTop} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -313,10 +150,7 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
{this.renderBottomRightGrid({
|
{this.renderBottomRightGrid({
|
||||||
...rest,
|
...rest,
|
||||||
onScroll,
|
onScroll,
|
||||||
onSectionRendered,
|
|
||||||
scrollLeft,
|
scrollLeft,
|
||||||
scrollToColumn,
|
|
||||||
scrollToRow,
|
|
||||||
scrollTop,
|
scrollTop,
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
@ -340,20 +174,15 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
} else {
|
} else {
|
||||||
return cellRenderer({
|
return cellRenderer({
|
||||||
...rest,
|
...rest,
|
||||||
|
style: {
|
||||||
|
...rest.style,
|
||||||
|
},
|
||||||
parent: this,
|
parent: this,
|
||||||
rowIndex: rowIndex + fixedRowCount,
|
rowIndex: rowIndex + fixedRowCount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getBottomGridHeight(props: PropsMultiGrid) {
|
|
||||||
const {height} = props
|
|
||||||
|
|
||||||
const topGridHeight = this.getTopGridHeight(props)
|
|
||||||
|
|
||||||
return height - topGridHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
private getLeftGridWidth(props: PropsMultiGrid) {
|
private getLeftGridWidth(props: PropsMultiGrid) {
|
||||||
const {fixedColumnCount, columnWidth} = props
|
const {fixedColumnCount, columnWidth} = props
|
||||||
|
|
||||||
|
@ -376,11 +205,7 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
|
|
||||||
private getRightGridWidth(props: PropsMultiGrid) {
|
private getRightGridWidth(props: PropsMultiGrid) {
|
||||||
const {width} = props
|
const {width} = props
|
||||||
|
return width - this.getLeftGridWidth(props)
|
||||||
const leftGridWidth = this.getLeftGridWidth(props)
|
|
||||||
const result = width - leftGridWidth
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTopGridHeight(props: PropsMultiGrid) {
|
private getTopGridHeight(props: PropsMultiGrid) {
|
||||||
|
@ -404,59 +229,72 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScrollbarsScroll = (e: React.MouseEvent<JSX.Element>) => {
|
private onScrollbarsScroll = (e: React.MouseEvent<JSX.Element>) => {
|
||||||
const {target} = e
|
const {scrollTop} = e.target as HTMLElement
|
||||||
this.onScroll(target)
|
const {scrollLeft} = this.state
|
||||||
|
|
||||||
|
this.onScroll({scrollTop, scrollLeft})
|
||||||
|
}
|
||||||
|
|
||||||
|
private onGridScroll = ({scrollLeft}) => {
|
||||||
|
const {scrollTop} = this.state
|
||||||
|
|
||||||
|
this.onScroll({scrollTop, scrollLeft})
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScroll = scrollInfo => {
|
private onScroll = scrollInfo => {
|
||||||
const {scrollLeft, scrollTop} = scrollInfo
|
|
||||||
this.setState({
|
|
||||||
scrollLeft,
|
|
||||||
scrollTop,
|
|
||||||
})
|
|
||||||
|
|
||||||
const {onScroll} = this.props
|
const {onScroll} = this.props
|
||||||
|
const {scrollLeft, scrollTop} = scrollInfo
|
||||||
|
|
||||||
|
this.setState({scrollLeft, scrollTop})
|
||||||
|
|
||||||
if (onScroll) {
|
if (onScroll) {
|
||||||
onScroll(scrollInfo)
|
onScroll(scrollInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onScrollLeft = scrollInfo => {
|
|
||||||
const {scrollLeft} = scrollInfo
|
|
||||||
this.onScroll({
|
|
||||||
scrollLeft,
|
|
||||||
scrollTop: this.state.scrollTop,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderBottomLeftGrid(props) {
|
private renderBottomLeftGrid(props) {
|
||||||
const {fixedColumnCount, fixedRowCount, rowCount} = props
|
const {fixedColumnCount, fixedRowCount, rowCount, columnWidth} = props
|
||||||
|
|
||||||
if (!fixedColumnCount) {
|
if (!fixedColumnCount) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const width = this.getLeftGridWidth(props)
|
const calculatedRowCount = Math.max(rowCount - fixedRowCount, 0)
|
||||||
const height = this.getBottomGridHeight(props)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Grid
|
<AutoSizer>
|
||||||
{...props}
|
{({width, height}) => (
|
||||||
cellRenderer={this.cellRendererBottomLeftGrid}
|
<FancyScrollbar
|
||||||
className={this.props.classNameBottomLeftGrid}
|
style={{
|
||||||
columnCount={fixedColumnCount}
|
width,
|
||||||
deferredMeasurementCache={this.deferredMeasurementCacheBottomLeftGrid}
|
height: this.props.height - ROW_HEIGHT,
|
||||||
onScroll={this.onScroll}
|
}}
|
||||||
height={height}
|
autoHide={true}
|
||||||
ref={this.bottomLeftGridRef}
|
scrollTop={this.state.scrollTop}
|
||||||
rowCount={Math.max(0, rowCount - fixedRowCount)}
|
scrollLeft={this.state.scrollLeft}
|
||||||
rowHeight={this.rowHeightBottomGrid}
|
setScrollTop={this.onScrollbarsScroll}
|
||||||
style={{
|
>
|
||||||
...this.bottomLeftGridStyle,
|
<Grid
|
||||||
}}
|
{...props}
|
||||||
tabIndex={null}
|
cellRenderer={this.cellRendererBottomLeftGrid}
|
||||||
width={width}
|
className={this.props.classNameBottomLeftGrid}
|
||||||
/>
|
columnCount={fixedColumnCount}
|
||||||
|
height={height}
|
||||||
|
ref={this.bottomLeftGridRef}
|
||||||
|
rowCount={calculatedRowCount}
|
||||||
|
rowHeight={ROW_HEIGHT}
|
||||||
|
columnWidth={columnWidth}
|
||||||
|
style={{
|
||||||
|
overflowY: 'hidden',
|
||||||
|
height: calculatedRowCount * ROW_HEIGHT,
|
||||||
|
position: 'absolute',
|
||||||
|
}}
|
||||||
|
tabIndex={null}
|
||||||
|
width={width}
|
||||||
|
/>
|
||||||
|
</FancyScrollbar>
|
||||||
|
)}
|
||||||
|
</AutoSizer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,46 +304,51 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
fixedColumnCount,
|
fixedColumnCount,
|
||||||
fixedRowCount,
|
fixedRowCount,
|
||||||
rowCount,
|
rowCount,
|
||||||
scrollToColumn,
|
|
||||||
scrollToRow,
|
scrollToRow,
|
||||||
|
scrollLeft,
|
||||||
|
scrollTop,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
const width = this.getRightGridWidth(props)
|
const calculatedRowCount = Math.max(0, rowCount - fixedRowCount)
|
||||||
const height = this.getBottomGridHeight(props)
|
|
||||||
|
const leftWidth = this.getLeftGridWidth(props)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FancyScrollbar
|
<AutoSizer>
|
||||||
style={{...this.bottomRightGridStyle, width, height}}
|
{({width, height}) => (
|
||||||
autoHide={true}
|
<FancyScrollbar
|
||||||
scrollTop={this.state.scrollTop}
|
style={{
|
||||||
scrollLeft={this.state.scrollLeft}
|
marginLeft: leftWidth,
|
||||||
setScrollTop={this.onScrollbarsScroll}
|
width: this.props.width - leftWidth,
|
||||||
>
|
height: this.props.height - ROW_HEIGHT,
|
||||||
<Grid
|
}}
|
||||||
{...props}
|
autoHide={true}
|
||||||
cellRenderer={this.cellRendererBottomRightGrid}
|
scrollTop={scrollTop}
|
||||||
className={this.props.classNameBottomRightGrid}
|
scrollLeft={scrollLeft}
|
||||||
columnCount={Math.max(0, columnCount - fixedColumnCount)}
|
setScrollTop={this.onScrollbarsScroll}
|
||||||
columnWidth={this.columnWidthRightGrid}
|
>
|
||||||
deferredMeasurementCache={
|
<Grid
|
||||||
this.deferredMeasurementCacheBottomRightGrid
|
{..._.omit(props, ['scrollToColumn'])}
|
||||||
}
|
cellRenderer={this.cellRendererBottomRightGrid}
|
||||||
height={height}
|
className={this.props.classNameBottomRightGrid}
|
||||||
ref={this.bottomRightGridRef}
|
columnCount={Math.max(0, columnCount - fixedColumnCount)}
|
||||||
rowCount={Math.max(0, rowCount - fixedRowCount)}
|
columnWidth={this.columnWidthRightGrid}
|
||||||
rowHeight={this.rowHeightBottomGrid}
|
overscanRowCount={100}
|
||||||
onScroll={this.onScroll}
|
height={height}
|
||||||
scrollToColumn={scrollToColumn - fixedColumnCount}
|
ref={this.bottomRightGridRef}
|
||||||
scrollToRow={scrollToRow - fixedRowCount}
|
onScroll={this.onGridScroll}
|
||||||
style={{
|
rowCount={calculatedRowCount}
|
||||||
...this.bottomRightGridStyle,
|
rowHeight={ROW_HEIGHT}
|
||||||
overflowX: false,
|
scrollToRow={scrollToRow - fixedRowCount}
|
||||||
overflowY: true,
|
style={{
|
||||||
left: 0,
|
overflowY: 'hidden',
|
||||||
}}
|
height: calculatedRowCount * ROW_HEIGHT + SCROLLBAR_SIZE_BUFFER,
|
||||||
width={width}
|
}}
|
||||||
/>
|
width={width - leftWidth}
|
||||||
</FancyScrollbar>
|
/>
|
||||||
|
</FancyScrollbar>
|
||||||
|
)}
|
||||||
|
</AutoSizer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,13 +375,7 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderTopRightGrid(props) {
|
private renderTopRightGrid(props) {
|
||||||
const {
|
const {columnCount, fixedColumnCount, fixedRowCount, scrollLeft} = props
|
||||||
columnCount,
|
|
||||||
enableFixedRowScroll,
|
|
||||||
fixedColumnCount,
|
|
||||||
fixedRowCount,
|
|
||||||
scrollLeft,
|
|
||||||
} = props
|
|
||||||
|
|
||||||
if (!fixedRowCount) {
|
if (!fixedRowCount) {
|
||||||
return null
|
return null
|
||||||
|
@ -554,9 +391,8 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
className={this.props.classNameTopRightGrid}
|
className={this.props.classNameTopRightGrid}
|
||||||
columnCount={Math.max(0, columnCount - fixedColumnCount)}
|
columnCount={Math.max(0, columnCount - fixedColumnCount)}
|
||||||
columnWidth={this.columnWidthRightGrid}
|
columnWidth={this.columnWidthRightGrid}
|
||||||
deferredMeasurementCache={this.deferredMeasurementCacheTopRightGrid}
|
|
||||||
height={height}
|
height={height}
|
||||||
onScroll={enableFixedRowScroll ? this.onScrollLeft : undefined}
|
onScroll={this.onGridScroll}
|
||||||
ref={this.topRightGridRef}
|
ref={this.topRightGridRef}
|
||||||
rowCount={fixedRowCount}
|
rowCount={fixedRowCount}
|
||||||
scrollLeft={scrollLeft}
|
scrollLeft={scrollLeft}
|
||||||
|
@ -567,23 +403,6 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private rowHeightBottomGrid = ({index}) => {
|
|
||||||
const {fixedRowCount, rowCount, rowHeight} = this.props
|
|
||||||
const {scrollbarSize, showVerticalScrollbar} = this.state
|
|
||||||
|
|
||||||
// An extra cell is added to the count
|
|
||||||
// This gives the smaller Grid extra room for offset,
|
|
||||||
// In case the main (bottom right) Grid has a scrollbar
|
|
||||||
// If no scrollbar, the extra space is overflow:hidden anyway
|
|
||||||
if (showVerticalScrollbar && index === rowCount - fixedRowCount) {
|
|
||||||
return scrollbarSize
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeof rowHeight === 'function'
|
|
||||||
? rowHeight({index: index + fixedRowCount})
|
|
||||||
: rowHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
private topLeftGridRef = ref => {
|
private topLeftGridRef = ref => {
|
||||||
this.topLeftGrid = ref
|
this.topLeftGrid = ref
|
||||||
}
|
}
|
||||||
|
@ -597,43 +416,17 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
* This method recalculates styles only when specific props change.
|
* This method recalculates styles only when specific props change.
|
||||||
*/
|
*/
|
||||||
private maybeCalculateCachedStyles(resetAll) {
|
private maybeCalculateCachedStyles(resetAll) {
|
||||||
const {
|
const {height, width} = this.props
|
||||||
columnWidth,
|
|
||||||
height,
|
|
||||||
fixedColumnCount,
|
|
||||||
fixedRowCount,
|
|
||||||
rowHeight,
|
|
||||||
style,
|
|
||||||
styleBottomLeftGrid,
|
|
||||||
styleBottomRightGrid,
|
|
||||||
styleTopLeftGrid,
|
|
||||||
styleTopRightGrid,
|
|
||||||
width,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
const sizeChange =
|
if (resetAll) {
|
||||||
resetAll ||
|
|
||||||
height !== this.lastRenderedHeight ||
|
|
||||||
width !== this.lastRenderedWidth
|
|
||||||
const leftSizeChange =
|
|
||||||
resetAll ||
|
|
||||||
columnWidth !== this.lastRenderedColumnWidth ||
|
|
||||||
fixedColumnCount !== this.lastRenderedFixedColumnCount
|
|
||||||
const topSizeChange =
|
|
||||||
resetAll ||
|
|
||||||
fixedRowCount !== this.lastRenderedFixedRowCount ||
|
|
||||||
rowHeight !== this.lastRenderedRowHeight
|
|
||||||
|
|
||||||
if (resetAll || sizeChange || style !== this.lastRenderedStyle) {
|
|
||||||
this.containerOuterStyle = {
|
this.containerOuterStyle = {
|
||||||
height,
|
height,
|
||||||
overflow: 'visible', // Let :focus outline show through
|
overflow: 'visible', // Let :focus outline show through
|
||||||
width,
|
width,
|
||||||
...style,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resetAll || sizeChange || topSizeChange) {
|
if (resetAll) {
|
||||||
this.containerTopStyle = {
|
this.containerTopStyle = {
|
||||||
height: this.getTopGridHeight(this.props),
|
height: this.getTopGridHeight(this.props),
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
@ -648,68 +441,25 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (resetAll) {
|
||||||
resetAll ||
|
|
||||||
styleBottomLeftGrid !== this.lastRenderedStyleBottomLeftGrid
|
|
||||||
) {
|
|
||||||
this.bottomLeftGridStyle = {
|
|
||||||
left: 0,
|
|
||||||
overflowY: 'hidden',
|
|
||||||
overflowX: 'hidden',
|
|
||||||
position: 'absolute',
|
|
||||||
...styleBottomLeftGrid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
resetAll ||
|
|
||||||
leftSizeChange ||
|
|
||||||
styleBottomRightGrid !== this.lastRenderedStyleBottomRightGrid
|
|
||||||
) {
|
|
||||||
this.bottomRightGridStyle = {
|
|
||||||
left: this.getLeftGridWidth(this.props),
|
|
||||||
position: 'absolute',
|
|
||||||
...styleBottomRightGrid,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resetAll || styleTopLeftGrid !== this.lastRenderedStyleTopLeftGrid) {
|
|
||||||
this.topLeftGridStyle = {
|
this.topLeftGridStyle = {
|
||||||
left: 0,
|
left: 0,
|
||||||
overflowX: 'hidden',
|
overflowX: 'hidden',
|
||||||
overflowY: 'hidden',
|
overflowY: 'hidden',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
...styleTopLeftGrid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (resetAll) {
|
||||||
resetAll ||
|
|
||||||
leftSizeChange ||
|
|
||||||
styleTopRightGrid !== this.lastRenderedStyleTopRightGrid
|
|
||||||
) {
|
|
||||||
this.topRightGridStyle = {
|
this.topRightGridStyle = {
|
||||||
left: this.getLeftGridWidth(this.props),
|
left: this.getLeftGridWidth(this.props),
|
||||||
overflowX: 'hidden',
|
overflowX: 'hidden',
|
||||||
overflowY: 'hidden',
|
overflowY: 'hidden',
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
...styleTopRightGrid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.lastRenderedColumnWidth = columnWidth
|
|
||||||
this.lastRenderedFixedColumnCount = fixedColumnCount
|
|
||||||
this.lastRenderedFixedRowCount = fixedRowCount
|
|
||||||
this.lastRenderedHeight = height
|
|
||||||
this.lastRenderedRowHeight = rowHeight
|
|
||||||
this.lastRenderedStyle = style
|
|
||||||
this.lastRenderedStyleBottomLeftGrid = styleBottomLeftGrid
|
|
||||||
this.lastRenderedStyleBottomRightGrid = styleBottomRightGrid
|
|
||||||
this.lastRenderedStyleTopLeftGrid = styleTopLeftGrid
|
|
||||||
this.lastRenderedStyleTopRightGrid = styleTopRightGrid
|
|
||||||
this.lastRenderedWidth = width
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bottomLeftGridRef = ref => {
|
private bottomLeftGridRef = ref => {
|
||||||
|
@ -765,48 +515,13 @@ class MultiGrid extends React.PureComponent<PropsMultiGrid, State> {
|
||||||
return scrollbarSize
|
return scrollbarSize
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeof columnWidth === 'function'
|
return _.isFunction(columnWidth)
|
||||||
? columnWidth({index: index + fixedColumnCount})
|
? columnWidth({index: index + fixedColumnCount})
|
||||||
: columnWidth
|
: columnWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleInvalidatedGridSize() {
|
|
||||||
if (typeof this.deferredInvalidateColumnIndex === 'number') {
|
|
||||||
const columnIndex = this.deferredInvalidateColumnIndex
|
|
||||||
const rowIndex = this.deferredInvalidateRowIndex
|
|
||||||
|
|
||||||
this.deferredInvalidateColumnIndex = null
|
|
||||||
this.deferredInvalidateRowIndex = null
|
|
||||||
|
|
||||||
this.recomputeGridSize({
|
|
||||||
columnIndex,
|
|
||||||
rowIndex,
|
|
||||||
})
|
|
||||||
this.forceUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private prepareForRender() {
|
private prepareForRender() {
|
||||||
if (
|
|
||||||
this.lastRenderedColumnWidth !== this.props.columnWidth ||
|
|
||||||
this.lastRenderedFixedColumnCount !== this.props.fixedColumnCount
|
|
||||||
) {
|
|
||||||
this.leftGridWidth = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
this.lastRenderedFixedRowCount !== this.props.fixedRowCount ||
|
|
||||||
this.lastRenderedRowHeight !== this.props.rowHeight
|
|
||||||
) {
|
|
||||||
this.topGridHeight = null
|
|
||||||
}
|
|
||||||
|
|
||||||
this.maybeCalculateCachedStyles(false)
|
this.maybeCalculateCachedStyles(false)
|
||||||
|
|
||||||
this.lastRenderedColumnWidth = this.props.columnWidth
|
|
||||||
this.lastRenderedFixedColumnCount = this.props.fixedColumnCount
|
|
||||||
this.lastRenderedFixedRowCount = this.props.fixedRowCount
|
|
||||||
this.lastRenderedRowHeight = this.props.rowHeight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,12 @@ import React, {Component} from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import {connect} from 'react-redux'
|
import {connect} from 'react-redux'
|
||||||
|
|
||||||
import {ColumnSizer, SizedColumnProps} from 'react-virtualized'
|
|
||||||
import {MultiGrid, PropsMultiGrid} from 'src/shared/components/MultiGrid'
|
|
||||||
import {bindActionCreators} from 'redux'
|
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
|
import {ColumnSizer, SizedColumnProps, AutoSizer} from 'react-virtualized'
|
||||||
|
import {MultiGrid, PropsMultiGrid} from 'src/shared/components/MultiGrid'
|
||||||
|
import {bindActionCreators} from 'redux'
|
||||||
import {fastReduce} from 'src/utils/fast'
|
import {fastReduce} from 'src/utils/fast'
|
||||||
|
|
||||||
import {timeSeriesToTableGraph} from 'src/utils/timeSeriesTransformers'
|
import {timeSeriesToTableGraph} from 'src/utils/timeSeriesTransformers'
|
||||||
import {
|
import {
|
||||||
computeFieldOptions,
|
computeFieldOptions,
|
||||||
|
@ -28,7 +26,6 @@ import {
|
||||||
} from 'src/shared/constants/tableGraph'
|
} from 'src/shared/constants/tableGraph'
|
||||||
import {generateThresholdsListHexs} from 'src/shared/constants/colorOperations'
|
import {generateThresholdsListHexs} from 'src/shared/constants/colorOperations'
|
||||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||||
|
|
||||||
import {TimeSeriesServerResponse, TimeSeriesValue} from 'src/types/series'
|
import {TimeSeriesServerResponse, TimeSeriesValue} from 'src/types/series'
|
||||||
import {ColorString} from 'src/types/colors'
|
import {ColorString} from 'src/types/colors'
|
||||||
import {
|
import {
|
||||||
|
@ -38,6 +35,9 @@ import {
|
||||||
Sort,
|
Sort,
|
||||||
} from 'src/types/dashboards'
|
} from 'src/types/dashboards'
|
||||||
|
|
||||||
|
const COLUMN_MIN_WIDTH = 100
|
||||||
|
const ROW_HEIGHT = 30
|
||||||
|
|
||||||
interface Label {
|
interface Label {
|
||||||
label: string
|
label: string
|
||||||
seriesIndex: number
|
seriesIndex: number
|
||||||
|
@ -49,7 +49,7 @@ interface CellRendererProps {
|
||||||
rowIndex: number
|
rowIndex: number
|
||||||
key: string
|
key: string
|
||||||
parent: React.Component<PropsMultiGrid>
|
parent: React.Component<PropsMultiGrid>
|
||||||
style: {[x: string]: any}
|
style: React.CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
@ -77,11 +77,14 @@ interface State {
|
||||||
columnWidths: {[x: string]: number}
|
columnWidths: {[x: string]: number}
|
||||||
totalColumnWidths: number
|
totalColumnWidths: number
|
||||||
isTimeVisible: boolean
|
isTimeVisible: boolean
|
||||||
|
shouldResize: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@ErrorHandling
|
@ErrorHandling
|
||||||
class TableGraph extends Component<Props, State> {
|
class TableGraph extends Component<Props, State> {
|
||||||
private gridContainer: HTMLDivElement
|
private gridContainer: HTMLDivElement
|
||||||
|
private multiGrid?: MultiGrid
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
|
@ -91,6 +94,7 @@ class TableGraph extends Component<Props, State> {
|
||||||
DEFAULT_TIME_FIELD.internalName
|
DEFAULT_TIME_FIELD.internalName
|
||||||
)
|
)
|
||||||
this.state = {
|
this.state = {
|
||||||
|
shouldResize: false,
|
||||||
data: [[]],
|
data: [[]],
|
||||||
transformedData: [[]],
|
transformedData: [[]],
|
||||||
sortedTimeVals: [],
|
sortedTimeVals: [],
|
||||||
|
@ -106,34 +110,13 @@ class TableGraph extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {
|
const {transformedData} = this.state
|
||||||
hoveredColumnIndex,
|
|
||||||
hoveredRowIndex,
|
|
||||||
timeColumnWidth,
|
|
||||||
sort,
|
|
||||||
transformedData,
|
|
||||||
} = this.state
|
|
||||||
|
|
||||||
const {
|
|
||||||
hoverTime,
|
|
||||||
tableOptions,
|
|
||||||
colors,
|
|
||||||
fieldOptions,
|
|
||||||
timeFormat,
|
|
||||||
decimalPlaces,
|
|
||||||
} = this.props
|
|
||||||
const {fixFirstColumn = DEFAULT_FIX_FIRST_COLUMN} = tableOptions
|
|
||||||
const columnCount = _.get(transformedData, ['0', 'length'], 0)
|
const columnCount = _.get(transformedData, ['0', 'length'], 0)
|
||||||
const rowCount = columnCount === 0 ? 0 : transformedData.length
|
const rowCount = columnCount === 0 ? 0 : transformedData.length
|
||||||
const COLUMN_MIN_WIDTH = 100
|
const fixedColumnCount = this.fixFirstColumn && columnCount > 1 ? 1 : 0
|
||||||
const COLUMN_MAX_WIDTH = 1000
|
|
||||||
const ROW_HEIGHT = 30
|
|
||||||
|
|
||||||
const fixedColumnCount = fixFirstColumn && columnCount > 1 ? 1 : undefined
|
|
||||||
|
|
||||||
const tableWidth = _.get(this, ['gridContainer', 'clientWidth'], 0)
|
|
||||||
const tableHeight = _.get(this, ['gridContainer', 'clientHeight'], 0)
|
|
||||||
const {scrollToColumn, scrollToRow} = this.scrollToColRow
|
const {scrollToColumn, scrollToRow} = this.scrollToColRow
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="table-graph-container"
|
className="table-graph-container"
|
||||||
|
@ -141,48 +124,64 @@ class TableGraph extends Component<Props, State> {
|
||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
>
|
>
|
||||||
{rowCount > 0 && (
|
{rowCount > 0 && (
|
||||||
<ColumnSizer
|
<AutoSizer>
|
||||||
columnCount={columnCount}
|
{({width, height}) => (
|
||||||
columnMaxWidth={COLUMN_MAX_WIDTH}
|
<ColumnSizer
|
||||||
columnMinWidth={COLUMN_MIN_WIDTH}
|
columnCount={this.computedColumnCount}
|
||||||
width={tableWidth}
|
columnMinWidth={COLUMN_MIN_WIDTH}
|
||||||
>
|
width={width}
|
||||||
{({columnWidth, registerChild}: SizedColumnProps) => (
|
>
|
||||||
<MultiGrid
|
{({
|
||||||
ref={registerChild}
|
adjustedWidth,
|
||||||
columnCount={columnCount}
|
columnWidth,
|
||||||
columnWidth={this.calculateColumnWidth(columnWidth)}
|
registerChild,
|
||||||
rowCount={rowCount}
|
}: SizedColumnProps) => (
|
||||||
rowHeight={ROW_HEIGHT}
|
<MultiGrid
|
||||||
height={tableHeight}
|
onMount={this.handleMultiGridMount}
|
||||||
width={tableWidth}
|
ref={registerChild}
|
||||||
fixedColumnCount={fixedColumnCount}
|
columnCount={columnCount}
|
||||||
fixedRowCount={1}
|
columnWidth={this.calculateColumnWidth(columnWidth)}
|
||||||
enableFixedColumnScroll={true}
|
scrollToRow={scrollToRow}
|
||||||
enableFixedRowScroll={true}
|
scrollToColumn={scrollToColumn}
|
||||||
scrollToRow={scrollToRow}
|
rowCount={rowCount}
|
||||||
scrollToColumn={scrollToColumn}
|
rowHeight={ROW_HEIGHT}
|
||||||
sort={sort}
|
height={height}
|
||||||
cellRenderer={this.cellRenderer}
|
width={adjustedWidth}
|
||||||
hoveredColumnIndex={hoveredColumnIndex}
|
fixedColumnCount={fixedColumnCount}
|
||||||
hoveredRowIndex={hoveredRowIndex}
|
fixedRowCount={1}
|
||||||
hoverTime={hoverTime}
|
cellRenderer={this.cellRenderer}
|
||||||
colors={colors}
|
classNameBottomRightGrid="table-graph--scroll-window"
|
||||||
fieldOptions={fieldOptions}
|
/>
|
||||||
tableOptions={tableOptions}
|
)}
|
||||||
timeFormat={timeFormat}
|
</ColumnSizer>
|
||||||
decimalPlaces={decimalPlaces}
|
|
||||||
timeColumnWidth={timeColumnWidth}
|
|
||||||
classNameBottomRightGrid="table-graph--scroll-window"
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</ColumnSizer>
|
</AutoSizer>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public handleMultiGridMount = (ref: MultiGrid) => {
|
||||||
|
this.multiGrid = ref
|
||||||
|
ref.forceUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
public componentWillUnmount() {
|
||||||
|
window.removeEventListener('resize', this.handleResize)
|
||||||
|
}
|
||||||
|
|
||||||
|
public get timeField() {
|
||||||
|
const {fieldOptions} = this.props
|
||||||
|
|
||||||
|
return _.find(
|
||||||
|
fieldOptions,
|
||||||
|
f => f.internalName === DEFAULT_TIME_FIELD.internalName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
public componentDidMount() {
|
public componentDidMount() {
|
||||||
|
window.addEventListener('resize', this.handleResize)
|
||||||
|
|
||||||
const sortField: string = _.get(
|
const sortField: string = _.get(
|
||||||
this.props,
|
this.props,
|
||||||
['tableOptions', 'sortBy', 'internalName'],
|
['tableOptions', 'sortBy', 'internalName'],
|
||||||
|
@ -199,12 +198,10 @@ class TableGraph extends Component<Props, State> {
|
||||||
} = this.props
|
} = this.props
|
||||||
const result = timeSeriesToTableGraph(data)
|
const result = timeSeriesToTableGraph(data)
|
||||||
const sortedLabels = result.sortedLabels
|
const sortedLabels = result.sortedLabels
|
||||||
|
|
||||||
const computedFieldOptions = computeFieldOptions(fieldOptions, sortedLabels)
|
const computedFieldOptions = computeFieldOptions(fieldOptions, sortedLabels)
|
||||||
|
|
||||||
if (!_.isEqual(computedFieldOptions, fieldOptions)) {
|
this.handleUpdateFieldOptions(computedFieldOptions)
|
||||||
this.handleUpdateFieldOptions(computedFieldOptions)
|
|
||||||
}
|
|
||||||
const {transformedData, sortedTimeVals, columnWidths} = transformTableData(
|
const {transformedData, sortedTimeVals, columnWidths} = transformTableData(
|
||||||
result.data,
|
result.data,
|
||||||
sort,
|
sort,
|
||||||
|
@ -214,67 +211,65 @@ class TableGraph extends Component<Props, State> {
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
)
|
)
|
||||||
|
|
||||||
const timeField = _.find(
|
const isTimeVisible = _.get(this.timeField, 'visible', true)
|
||||||
fieldOptions,
|
|
||||||
f => f.internalName === DEFAULT_TIME_FIELD.internalName
|
|
||||||
)
|
|
||||||
const isTimeVisible = _.get(timeField, 'visible', this.state.isTimeVisible)
|
|
||||||
|
|
||||||
this.setState({
|
this.setState(
|
||||||
transformedData,
|
{
|
||||||
sortedTimeVals,
|
transformedData,
|
||||||
columnWidths: columnWidths.widths,
|
sortedTimeVals,
|
||||||
data: result.data,
|
columnWidths: columnWidths.widths,
|
||||||
sortedLabels,
|
data: result.data,
|
||||||
totalColumnWidths: columnWidths.totalWidths,
|
sortedLabels,
|
||||||
hoveredColumnIndex: NULL_ARRAY_INDEX,
|
totalColumnWidths: columnWidths.totalWidths,
|
||||||
hoveredRowIndex: NULL_ARRAY_INDEX,
|
hoveredColumnIndex: NULL_ARRAY_INDEX,
|
||||||
sort,
|
hoveredRowIndex: NULL_ARRAY_INDEX,
|
||||||
isTimeVisible,
|
sort,
|
||||||
})
|
isTimeVisible,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
this.forceUpdate()
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentWillReceiveProps(nextProps: Props) {
|
public componentWillReceiveProps(nextProps: Props) {
|
||||||
const updatedProps = _.keys(nextProps).filter(
|
const {sort} = this.state
|
||||||
k => !_.isEqual(this.props[k], nextProps[k])
|
|
||||||
)
|
|
||||||
const {tableOptions, fieldOptions, timeFormat, decimalPlaces} = nextProps
|
|
||||||
|
|
||||||
let result = {}
|
let result = {}
|
||||||
|
if (this.hasDataChanged(nextProps.data)) {
|
||||||
if (_.includes(updatedProps, 'data')) {
|
|
||||||
result = timeSeriesToTableGraph(nextProps.data)
|
result = timeSeriesToTableGraph(nextProps.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = _.get(result, 'data', this.state.data)
|
const data = _.get(result, 'data', this.state.data)
|
||||||
const sortedLabels = _.get(result, 'sortedLabels', this.state.sortedLabels)
|
|
||||||
|
|
||||||
const computedFieldOptions = computeFieldOptions(fieldOptions, sortedLabels)
|
|
||||||
|
|
||||||
if (_.includes(updatedProps, 'data')) {
|
|
||||||
this.handleUpdateFieldOptions(computedFieldOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_.isEmpty(data[0])) {
|
if (_.isEmpty(data[0])) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const {sort} = this.state
|
const updatedProps = _.keys(_.omit(nextProps, 'data')).filter(
|
||||||
const internalName = _.get(
|
k => !_.isEqual(this.props[k], nextProps[k])
|
||||||
nextProps,
|
|
||||||
['tableOptions', 'sortBy', 'internalName'],
|
|
||||||
''
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const {tableOptions, fieldOptions, timeFormat, decimalPlaces} = nextProps
|
||||||
|
const sortedLabels = _.get(result, 'sortedLabels', this.state.sortedLabels)
|
||||||
|
const computedFieldOptions = computeFieldOptions(fieldOptions, sortedLabels)
|
||||||
|
|
||||||
|
if (this.hasDataChanged(nextProps.data)) {
|
||||||
|
this.handleUpdateFieldOptions(computedFieldOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalName = _.get(tableOptions, 'sortBy.internalName', '')
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!_.get(this.props, ['tableOptions', 'sortBy', 'internalName'], '') ===
|
_.get(this.props, 'tableOptions.sortBy.internalName', '') !== internalName
|
||||||
internalName
|
|
||||||
) {
|
) {
|
||||||
sort.direction = DEFAULT_SORT_DIRECTION
|
sort.direction = DEFAULT_SORT_DIRECTION
|
||||||
sort.field = internalName
|
sort.field = internalName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
_.includes(updatedProps, 'data') ||
|
this.hasDataChanged(nextProps.data) ||
|
||||||
_.includes(updatedProps, 'tableOptions') ||
|
_.includes(updatedProps, 'tableOptions') ||
|
||||||
_.includes(updatedProps, 'fieldOptions') ||
|
_.includes(updatedProps, 'fieldOptions') ||
|
||||||
_.includes(updatedProps, 'timeFormat')
|
_.includes(updatedProps, 'timeFormat')
|
||||||
|
@ -310,33 +305,75 @@ class TableGraph extends Component<Props, State> {
|
||||||
columnWidths: columnWidths.widths,
|
columnWidths: columnWidths.widths,
|
||||||
totalColumnWidths: columnWidths.totalWidths,
|
totalColumnWidths: columnWidths.totalWidths,
|
||||||
isTimeVisible,
|
isTimeVisible,
|
||||||
|
shouldResize: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleUpdateFieldOptions = (fieldOptions: FieldOption[]): void => {
|
public componentDidUpdate() {
|
||||||
const {isInCEO} = this.props
|
if (this.state.shouldResize) {
|
||||||
if (!isInCEO) {
|
if (this.multiGrid) {
|
||||||
return
|
this.multiGrid.recomputeGridSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({shouldResize: false})
|
||||||
}
|
}
|
||||||
this.props.handleUpdateFieldOptions(fieldOptions)
|
}
|
||||||
|
|
||||||
|
private hasDataChanged(data): boolean {
|
||||||
|
const newUUID = _.get(data, '0.response.uuid', null)
|
||||||
|
const oldUUID = _.get(this.props.data, '0.response.uuid', null)
|
||||||
|
|
||||||
|
return newUUID !== oldUUID
|
||||||
|
}
|
||||||
|
|
||||||
|
private get fixFirstColumn(): boolean {
|
||||||
|
const {tableOptions} = this.props
|
||||||
|
const {fixFirstColumn = DEFAULT_FIX_FIRST_COLUMN} = tableOptions
|
||||||
|
return fixFirstColumn
|
||||||
|
}
|
||||||
|
|
||||||
|
private get columnCount(): number {
|
||||||
|
const {transformedData} = this.state
|
||||||
|
return _.get(transformedData, ['0', 'length'], 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private get computedColumnCount(): number {
|
||||||
|
if (this.fixFirstColumn) {
|
||||||
|
return this.columnCount - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.columnCount
|
||||||
|
}
|
||||||
|
|
||||||
|
private get tableWidth(): number {
|
||||||
|
const tableWidth = _.get(this, ['gridContainer', 'clientWidth'], 0)
|
||||||
|
|
||||||
|
return tableWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleUpdateFieldOptions = (fieldOptions: FieldOption[]): void => {
|
||||||
|
const {isInCEO, handleUpdateFieldOptions} = this.props
|
||||||
|
if (isInCEO) {
|
||||||
|
handleUpdateFieldOptions(fieldOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private get isEmpty(): boolean {
|
||||||
|
const {data} = this.state
|
||||||
|
return _.isEmpty(data[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
private get scrollToColRow(): {
|
private get scrollToColRow(): {
|
||||||
scrollToRow: number | null
|
scrollToRow: number | null
|
||||||
scrollToColumn: number | null
|
scrollToColumn: number | null
|
||||||
} {
|
} {
|
||||||
const {data, sortedTimeVals, hoveredColumnIndex, isTimeVisible} = this.state
|
const {sortedTimeVals, hoveredColumnIndex, isTimeVisible} = this.state
|
||||||
const {hoverTime, tableOptions} = this.props
|
const {hoverTime} = this.props
|
||||||
const hoveringThisTable = hoveredColumnIndex !== NULL_ARRAY_INDEX
|
const hoveringThisTable = hoveredColumnIndex !== NULL_ARRAY_INDEX
|
||||||
const notHovering = hoverTime === NULL_HOVER_TIME
|
const notHovering = hoverTime === NULL_HOVER_TIME
|
||||||
if (
|
if (this.isEmpty || notHovering || hoveringThisTable || !isTimeVisible) {
|
||||||
_.isEmpty(data[0]) ||
|
return {scrollToColumn: 0, scrollToRow: -1}
|
||||||
notHovering ||
|
|
||||||
hoveringThisTable ||
|
|
||||||
!isTimeVisible
|
|
||||||
) {
|
|
||||||
return {scrollToColumn: null, scrollToRow: null}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstDiff = Math.abs(Number(hoverTime) - Number(sortedTimeVals[1])) // sortedTimeVals[0] is "time"
|
const firstDiff = Math.abs(Number(hoverTime) - Number(sortedTimeVals[1])) // sortedTimeVals[0] is "time"
|
||||||
|
@ -355,33 +392,35 @@ class TableGraph extends Component<Props, State> {
|
||||||
{index: 1, diff: firstDiff}
|
{index: 1, diff: firstDiff}
|
||||||
)
|
)
|
||||||
|
|
||||||
const {verticalTimeAxis} = tableOptions
|
const scrollToColumn = this.isVerticalTimeAxis ? -1 : hoverTimeFound.index
|
||||||
const scrollToColumn = verticalTimeAxis ? null : hoverTimeFound.index
|
const scrollToRow = this.isVerticalTimeAxis ? hoverTimeFound.index : null
|
||||||
const scrollToRow = verticalTimeAxis ? hoverTimeFound.index : null
|
|
||||||
return {scrollToRow, scrollToColumn}
|
return {scrollToRow, scrollToColumn}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleHover = (
|
private get isVerticalTimeAxis(): boolean {
|
||||||
columnIndex: number,
|
return _.get(
|
||||||
rowIndex: number
|
this.props,
|
||||||
): (() => void) => (): void => {
|
'tableOptions.verticalTimeAxis',
|
||||||
const {
|
DEFAULT_VERTICAL_TIME_AXIS
|
||||||
handleSetHoverTime,
|
)
|
||||||
tableOptions: {verticalTimeAxis},
|
}
|
||||||
} = this.props
|
|
||||||
|
private handleHover = (e: React.MouseEvent<HTMLElement>) => {
|
||||||
|
const {dataset} = e.target as HTMLElement
|
||||||
|
const {handleSetHoverTime} = this.props
|
||||||
const {sortedTimeVals, isTimeVisible} = this.state
|
const {sortedTimeVals, isTimeVisible} = this.state
|
||||||
if (verticalTimeAxis && rowIndex === 0) {
|
if (this.isVerticalTimeAxis && +dataset.rowIndex === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (handleSetHoverTime && isTimeVisible) {
|
if (handleSetHoverTime && isTimeVisible) {
|
||||||
const hoverTime = verticalTimeAxis
|
const hoverTime = this.isVerticalTimeAxis
|
||||||
? sortedTimeVals[rowIndex]
|
? sortedTimeVals[dataset.rowIndex]
|
||||||
: sortedTimeVals[columnIndex]
|
: sortedTimeVals[dataset.columnIndex]
|
||||||
handleSetHoverTime(hoverTime.toString())
|
handleSetHoverTime(_.defaultTo(hoverTime, '').toString())
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
hoveredColumnIndex: columnIndex,
|
hoveredColumnIndex: +dataset.columnIndex,
|
||||||
hoveredRowIndex: rowIndex,
|
hoveredRowIndex: +dataset.rowIndex,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,31 +465,28 @@ class TableGraph extends Component<Props, State> {
|
||||||
index: number
|
index: number
|
||||||
}): number => {
|
}): number => {
|
||||||
const {index} = column
|
const {index} = column
|
||||||
const {
|
|
||||||
tableOptions: {fixFirstColumn},
|
|
||||||
} = this.props
|
|
||||||
const {transformedData, columnWidths, totalColumnWidths} = this.state
|
const {transformedData, columnWidths, totalColumnWidths} = this.state
|
||||||
const columnCount = _.get(transformedData, ['0', 'length'], 0)
|
|
||||||
const columnLabel = transformedData[0][index]
|
const columnLabel = transformedData[0][index]
|
||||||
|
|
||||||
let adjustedColumnSizerWidth = columnWidths[columnLabel]
|
const original = columnWidths[columnLabel]
|
||||||
|
|
||||||
const tableWidth = _.get(this, ['gridContainer', 'clientWidth'], 0)
|
if (this.fixFirstColumn && index === 0) {
|
||||||
if (tableWidth > totalColumnWidths) {
|
return original
|
||||||
if (columnCount === 1) {
|
|
||||||
return columnSizerWidth
|
|
||||||
}
|
|
||||||
const difference = tableWidth - totalColumnWidths
|
|
||||||
const distributeOver =
|
|
||||||
fixFirstColumn && columnCount > 1 ? columnCount - 1 : columnCount
|
|
||||||
const increment = difference / distributeOver
|
|
||||||
adjustedColumnSizerWidth =
|
|
||||||
fixFirstColumn && index === 0
|
|
||||||
? columnWidths[columnLabel]
|
|
||||||
: columnWidths[columnLabel] + increment
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return adjustedColumnSizerWidth
|
if (this.tableWidth <= totalColumnWidths) {
|
||||||
|
return original
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.columnCount <= 1) {
|
||||||
|
return columnSizerWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
const difference = this.tableWidth - totalColumnWidths
|
||||||
|
const increment = difference / this.computedColumnCount
|
||||||
|
|
||||||
|
return original + increment
|
||||||
}
|
}
|
||||||
|
|
||||||
private createCellContents = (
|
private createCellContents = (
|
||||||
|
@ -460,16 +496,34 @@ class TableGraph extends Component<Props, State> {
|
||||||
isFieldName: boolean
|
isFieldName: boolean
|
||||||
): string => {
|
): string => {
|
||||||
const {timeFormat, decimalPlaces} = this.props
|
const {timeFormat, decimalPlaces} = this.props
|
||||||
|
|
||||||
if (isTimeData) {
|
if (isTimeData) {
|
||||||
return `${moment(cellData).format(timeFormat)}`
|
return moment(cellData).format(timeFormat)
|
||||||
}
|
}
|
||||||
if (typeof cellData === 'string' && isFieldName) {
|
if (_.isString(cellData) && isFieldName) {
|
||||||
return `${fieldName}`
|
return _.defaultTo(fieldName, '').toString()
|
||||||
}
|
}
|
||||||
if (typeof cellData === 'number' && decimalPlaces.isEnforced) {
|
if (
|
||||||
|
_.isNumber(cellData) &&
|
||||||
|
decimalPlaces.isEnforced &&
|
||||||
|
decimalPlaces.digits < 100
|
||||||
|
) {
|
||||||
return cellData.toFixed(decimalPlaces.digits)
|
return cellData.toFixed(decimalPlaces.digits)
|
||||||
}
|
}
|
||||||
return `${cellData}`
|
|
||||||
|
return _.defaultTo(cellData, '').toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleResize = () => {
|
||||||
|
this.forceUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private get timeFieldIndex(): number {
|
||||||
|
const {fieldOptions = [DEFAULT_TIME_FIELD]} = this.props
|
||||||
|
|
||||||
|
return fieldOptions.findIndex(
|
||||||
|
({internalName}) => internalName === DEFAULT_TIME_FIELD.internalName
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private cellRenderer = ({
|
private cellRenderer = ({
|
||||||
|
@ -487,43 +541,24 @@ class TableGraph extends Component<Props, State> {
|
||||||
isTimeVisible,
|
isTimeVisible,
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
const {
|
const {fieldOptions = [DEFAULT_TIME_FIELD], colors} = this.props
|
||||||
fieldOptions = [DEFAULT_TIME_FIELD],
|
|
||||||
tableOptions,
|
|
||||||
colors,
|
|
||||||
} = this.props
|
|
||||||
|
|
||||||
const {
|
|
||||||
verticalTimeAxis = DEFAULT_VERTICAL_TIME_AXIS,
|
|
||||||
fixFirstColumn = DEFAULT_FIX_FIRST_COLUMN,
|
|
||||||
} = tableOptions
|
|
||||||
|
|
||||||
const cellData = transformedData[rowIndex][columnIndex]
|
const cellData = transformedData[rowIndex][columnIndex]
|
||||||
|
const isSorted = sort.field === cellData
|
||||||
const timeFieldIndex = fieldOptions.findIndex(
|
const isAscending = sort.direction === ASCENDING
|
||||||
field => field.internalName === DEFAULT_TIME_FIELD.internalName
|
const isFirstRow = rowIndex === 0
|
||||||
)
|
const isFirstCol = columnIndex === 0
|
||||||
|
const isFixedRow = isFirstRow && !isFirstCol
|
||||||
const isFixedRow = rowIndex === 0 && columnIndex > 0
|
const isFixedColumn = this.fixFirstColumn && !isFirstRow && isFirstCol
|
||||||
const isFixedColumn = fixFirstColumn && rowIndex > 0 && columnIndex === 0
|
|
||||||
const isTimeData =
|
const isTimeData =
|
||||||
isTimeVisible &&
|
isTimeVisible &&
|
||||||
(verticalTimeAxis
|
(this.isVerticalTimeAxis
|
||||||
? rowIndex !== 0 && columnIndex === timeFieldIndex
|
? !isFirstRow && columnIndex === this.timeFieldIndex
|
||||||
: rowIndex === timeFieldIndex && columnIndex !== 0)
|
: rowIndex === this.timeFieldIndex && isFirstCol)
|
||||||
const isFieldName = verticalTimeAxis ? rowIndex === 0 : columnIndex === 0
|
const isFieldName = this.isVerticalTimeAxis ? isFirstRow : isFirstCol
|
||||||
const isFixedCorner = rowIndex === 0 && columnIndex === 0
|
const isFixedCorner = isFirstRow && isFirstCol
|
||||||
const isNumerical = _.isNumber(cellData)
|
const isNumerical = _.isNumber(cellData)
|
||||||
|
|
||||||
const isHighlightedRow =
|
let cellStyle: React.CSSProperties = style //tslint:disable-line
|
||||||
rowIndex === parent.props.scrollToRow ||
|
|
||||||
(rowIndex === hoveredRowIndex && hoveredRowIndex !== 0)
|
|
||||||
const isHighlightedColumn =
|
|
||||||
columnIndex === parent.props.scrollToColumn ||
|
|
||||||
(columnIndex === hoveredColumnIndex && hoveredColumnIndex !== 0)
|
|
||||||
|
|
||||||
let cellStyle = style
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!isFixedRow &&
|
!isFixedRow &&
|
||||||
!isFixedColumn &&
|
!isFixedColumn &&
|
||||||
|
@ -531,21 +566,19 @@ class TableGraph extends Component<Props, State> {
|
||||||
!isTimeData &&
|
!isTimeData &&
|
||||||
isNumerical
|
isNumerical
|
||||||
) {
|
) {
|
||||||
const {bgColor, textColor} = generateThresholdsListHexs({
|
const thresholdData = {colors, lastValue: cellData, cellType: 'table'}
|
||||||
colors,
|
const {bgColor, textColor} = generateThresholdsListHexs(thresholdData)
|
||||||
lastValue: cellData,
|
|
||||||
cellType: 'table',
|
|
||||||
})
|
|
||||||
|
|
||||||
cellStyle = {
|
cellStyle = {
|
||||||
...style,
|
...cellStyle,
|
||||||
backgroundColor: bgColor,
|
backgroundColor: bgColor,
|
||||||
color: textColor,
|
color: textColor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const foundField =
|
const foundField =
|
||||||
isFieldName && fieldOptions.find(field => field.internalName === cellData)
|
isFieldName &&
|
||||||
|
fieldOptions.find(({internalName}) => internalName === cellData)
|
||||||
const fieldName =
|
const fieldName =
|
||||||
foundField && (foundField.displayName || foundField.internalName)
|
foundField && (foundField.displayName || foundField.internalName)
|
||||||
|
|
||||||
|
@ -553,14 +586,15 @@ class TableGraph extends Component<Props, State> {
|
||||||
'table-graph-cell__fixed-row': isFixedRow,
|
'table-graph-cell__fixed-row': isFixedRow,
|
||||||
'table-graph-cell__fixed-column': isFixedColumn,
|
'table-graph-cell__fixed-column': isFixedColumn,
|
||||||
'table-graph-cell__fixed-corner': isFixedCorner,
|
'table-graph-cell__fixed-corner': isFixedCorner,
|
||||||
'table-graph-cell__highlight-row': isHighlightedRow,
|
'table-graph-cell__highlight-row':
|
||||||
'table-graph-cell__highlight-column': isHighlightedColumn,
|
rowIndex === parent.props.scrollToRow ||
|
||||||
|
(rowIndex === hoveredRowIndex && hoveredRowIndex > 0),
|
||||||
|
'table-graph-cell__highlight-column':
|
||||||
|
columnIndex === hoveredColumnIndex && hoveredColumnIndex > 0,
|
||||||
'table-graph-cell__numerical': isNumerical,
|
'table-graph-cell__numerical': isNumerical,
|
||||||
'table-graph-cell__field-name': isFieldName,
|
'table-graph-cell__field-name': isFieldName,
|
||||||
'table-graph-cell__sort-asc':
|
'table-graph-cell__sort-asc': isFieldName && isSorted && isAscending,
|
||||||
isFieldName && sort.field === cellData && sort.direction === ASCENDING,
|
'table-graph-cell__sort-desc': isFieldName && isSorted && !isAscending,
|
||||||
'table-graph-cell__sort-desc':
|
|
||||||
isFieldName && sort.field === cellData && sort.direction === DESCENDING,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const cellContents = this.createCellContents(
|
const cellContents = this.createCellContents(
|
||||||
|
@ -576,11 +610,13 @@ class TableGraph extends Component<Props, State> {
|
||||||
style={cellStyle}
|
style={cellStyle}
|
||||||
className={cellClass}
|
className={cellClass}
|
||||||
onClick={
|
onClick={
|
||||||
isFieldName && typeof cellData === 'string'
|
isFieldName && _.isString(cellData)
|
||||||
? this.handleClickFieldName(cellData)
|
? this.handleClickFieldName(cellData)
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
onMouseOver={_.throttle(this.handleHover(columnIndex, rowIndex), 100)}
|
data-column-index={columnIndex}
|
||||||
|
data-row-index={rowIndex}
|
||||||
|
onMouseOver={this.handleHover}
|
||||||
title={cellContents}
|
title={cellContents}
|
||||||
>
|
>
|
||||||
{cellContents}
|
{cellContents}
|
||||||
|
|
Loading…
Reference in New Issue