Convert TableGraph to TS

pull/10616/head
ebb-tide 2018-05-09 13:25:11 -07:00
parent eb73b090cd
commit 30164a1e9b
8 changed files with 147 additions and 107 deletions

View File

@ -119,6 +119,8 @@
"webpack-dev-server": "^2.11.1"
},
"dependencies": {
"@types/chroma-js": "^1.3.4",
"@types/react-virtualized": "^9.18.3",
"axios": "^0.13.1",
"bignumber.js": "^4.0.2",
"calculate-size": "^1.1.1",

View File

@ -4,8 +4,11 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import {Grid} from 'react-virtualized'
const SCROLLBAR_SIZE_BUFFER = 20
type HeightWidthFunction = (arg: {index: number}) => {} | number
interface Props {
width: number
height: number
columnCount?: number
classNameBottomLeftGrid?: string
classNameBottomRightGrid?: string
@ -23,15 +26,12 @@ interface Props {
scrollTop?: number
scrollLeft?: number
rowCount?: number
rowHeight?: (arg: {index: number}) => {} | number
columnWidth?: (arg: object) => {} | number
rowHeight?: number | HeightWidthFunction
columnWidth?: number | HeightWidthFunction
onScroll?: (arg: object) => {}
width: number
height: number
scrollToRow?: () => {}
onSectionRendered?: () => {}
scrollToColumn?: () => {}
cellRenderer?: (arg: object) => JSX.Element
[key: string]: any // MultiGrid can accept any prop, and will rerender if they change
}
interface State {
@ -99,10 +99,10 @@ class MultiGrid extends React.PureComponent<Props, State> {
private deferredMeasurementCacheTopRightGrid: CellMeasurerCacheDecorator
private leftGridWidth: number | null = 0
private topGridHeight: number | null = 0
private lastRenderedColumnWidth: (arg: object) => {} | number
private lastRenderedColumnWidth: number | HeightWidthFunction
private lastRenderedFixedColumnCount: number = 0
private lastRenderedFixedRowCount: number = 0
private lastRenderedRowHeight: (arg: {index: number}) => {} | number
private lastRenderedRowHeight: number | HeightWidthFunction
private bottomRightGridStyle: object | null
private topRightGridStyle: object | null
private lastRenderedStyle: object | null

View File

@ -1,5 +1,4 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import React, {PureComponent} from 'react'
import _ from 'lodash'
import classnames from 'classnames'
import {connect} from 'react-redux'
@ -26,12 +25,68 @@ import {
DEFAULT_VERTICAL_TIME_AXIS,
DEFAULT_SORT_DIRECTION,
} from 'src/shared/constants/tableGraph'
import {generateThresholdsListHexs} from 'shared/constants/colorOperations'
import {colorsStringSchema} from 'shared/schemas'
import {generateThresholdsListHexs} from 'src/shared/constants/colorOperations'
import {ErrorHandling} from 'src/shared/decorators/errors'
import {TimeSeriesServerResponse} from 'src/types/series'
import {ColorString} from 'src/types/colors'
type dbData = string | number | null
interface TableOptions {
verticalTimeAxis: boolean
sortBy: FieldOption
wrapping?: string
fixFirstColumn: boolean
}
interface DecimalPlaces {
isEnforced: boolean
digits: number
}
interface FieldOption {
internalName: string
displayName: string
visible: boolean
}
interface Sort {
field: string
direction: string
}
interface Props {
data: TimeSeriesServerResponse
tableOptions: TableOptions
timeFormat: string
decimalPlaces: DecimalPlaces
fieldOptions: FieldOption[]
hoverTime: string
handleUpdateFieldOptions: (fieldOptions: FieldOption[]) => void
handleSetHoverTime: (hovertime: string) => void
colors: ColorString
isInCEO: boolean
}
interface State {
data: dbData[][]
transformedData: dbData[][]
sortedTimeVals: number[]
sortedLabels: string[]
hoveredColumnIndex: number
hoveredRowIndex: number
timeColumnWidth: number
sort: Sort
columnWidths: {}
totalColumnWidths: number
isTimeVisible: boolean
}
@ErrorHandling
class TableGraph extends Component {
class TableGraph extends PureComponent<Props, State> {
private multiGridRef: React.RefObject<MultiGrid>
private gridContainer: React.Ref<HTMLDivElement>
constructor(props) {
super(props)
@ -40,6 +95,7 @@ class TableGraph extends Component {
['tableOptions', 'sortBy', 'internalName'],
DEFAULT_TIME_FIELD.internalName
)
this.multiGridRef = React.createRef<MultiGrid>()
this.state = {
data: [[]],
@ -51,11 +107,11 @@ class TableGraph extends Component {
sort: {field: sortField, direction: DEFAULT_SORT_DIRECTION},
columnWidths: {},
totalColumnWidths: 0,
timeColumnWidth: 0,
isTimeVisible: true,
}
}
componentDidMount() {
public componentDidMount() {
const sortField = _.get(
this.props,
['tableOptions', 'sortBy', 'internalName'],
@ -112,7 +168,7 @@ class TableGraph extends Component {
})
}
handleUpdateFieldOptions = fieldOptions => {
public handleUpdateFieldOptions = fieldOptions => {
const {isInCEO} = this.props
if (!isInCEO) {
return
@ -120,7 +176,7 @@ class TableGraph extends Component {
this.props.handleUpdateFieldOptions(fieldOptions)
}
componentWillReceiveProps(nextProps) {
public componentWillReceiveProps(nextProps) {
const updatedProps = _.keys(nextProps).filter(
k => !_.isEqual(this.props[k], nextProps[k])
)
@ -201,7 +257,7 @@ class TableGraph extends Component {
}
}
calcScrollToColRow = () => {
public calcScrollToColRow = () => {
const {data, sortedTimeVals, hoveredColumnIndex, isTimeVisible} = this.state
const {hoverTime, tableOptions} = this.props
const hoveringThisTable = hoveredColumnIndex !== NULL_ARRAY_INDEX
@ -215,11 +271,11 @@ class TableGraph extends Component {
return {scrollToColumn: undefined, scrollToRow: undefined}
}
const firstDiff = Math.abs(hoverTime - sortedTimeVals[1]) // sortedTimeVals[0] is "time"
const firstDiff = Math.abs(Number(hoverTime) - sortedTimeVals[1]) // sortedTimeVals[0] is "time"
const hoverTimeFound = reduce(
sortedTimeVals,
(acc, currentTime, index) => {
const thisDiff = Math.abs(hoverTime - currentTime)
const thisDiff = Math.abs(Number(hoverTime) - currentTime)
if (thisDiff < acc.diff) {
return {index, diff: thisDiff}
}
@ -234,7 +290,7 @@ class TableGraph extends Component {
return {scrollToRow, scrollToColumn}
}
handleHover = (columnIndex, rowIndex) => () => {
public handleHover = (columnIndex, rowIndex) => () => {
const {
handleSetHoverTime,
tableOptions: {verticalTimeAxis},
@ -255,7 +311,7 @@ class TableGraph extends Component {
})
}
handleMouseLeave = () => {
public handleMouseLeave = () => {
if (this.props.handleSetHoverTime) {
this.props.handleSetHoverTime(NULL_HOVER_TIME)
this.setState({
@ -265,7 +321,7 @@ class TableGraph extends Component {
}
}
handleClickFieldName = clickedFieldName => () => {
public handleClickFieldName = clickedFieldName => () => {
const {tableOptions, fieldOptions, timeFormat, decimalPlaces} = this.props
const {data, sort} = this.state
@ -292,7 +348,7 @@ class TableGraph extends Component {
})
}
calculateColumnWidth = columnSizerWidth => column => {
public calculateColumnWidth = columnSizerWidth => column => {
const {index} = column
const {
tableOptions: {fixFirstColumn},
@ -321,7 +377,7 @@ class TableGraph extends Component {
return adjustedColumnSizerWidth
}
createCellContents = (
public createCellContents = (
cellData,
fieldName,
isTimeData,
@ -341,7 +397,7 @@ class TableGraph extends Component {
return `${cellData}`
}
cellRenderer = ({columnIndex, rowIndex, key, parent, style}) => {
public cellRenderer = ({columnIndex, rowIndex, key, parent, style}) => {
const {
hoveredColumnIndex,
hoveredRowIndex,
@ -448,12 +504,7 @@ class TableGraph extends Component {
)
}
getMultiGridRef = (r, registerChild) => {
this.multiGridRef = r
return registerChild(r)
}
render() {
public render() {
const {
hoveredColumnIndex,
hoveredRowIndex,
@ -484,7 +535,7 @@ class TableGraph extends Component {
return (
<div
className="table-graph-container"
ref={gridContainer => (this.gridContainer = gridContainer)}
ref={this.gridContainer}
onMouseLeave={this.handleMouseLeave}
>
{rowCount > 0 && (
@ -494,73 +545,44 @@ class TableGraph extends Component {
columnMinWidth={COLUMN_MIN_WIDTH}
width={tableWidth}
>
{({columnWidth, registerChild}) => (
<MultiGrid
ref={r => this.getMultiGridRef(r, registerChild)}
columnCount={columnCount}
columnWidth={this.calculateColumnWidth(columnWidth)}
rowCount={rowCount}
rowHeight={ROW_HEIGHT}
height={tableHeight}
width={tableWidth}
fixedColumnCount={fixedColumnCount}
fixedRowCount={1}
enableFixedColumnScroll={true}
enableFixedRowScroll={true}
scrollToRow={scrollToRow}
scrollToColumn={scrollToColumn}
sort={sort}
cellRenderer={this.cellRenderer}
hoveredColumnIndex={hoveredColumnIndex}
hoveredRowIndex={hoveredRowIndex}
hoverTime={hoverTime}
colors={colors}
fieldOptions={fieldOptions}
tableOptions={tableOptions}
timeFormat={timeFormat}
decimalPlaces={decimalPlaces}
timeColumnWidth={timeColumnWidth}
classNameBottomRightGrid="table-graph--scroll-window"
/>
)}
{({columnWidth, registerChild}) => {
registerChild(this.multiGridRef)
return (
<MultiGrid
ref={this.multiGridRef}
columnCount={columnCount}
columnWidth={this.calculateColumnWidth(columnWidth)}
rowCount={rowCount}
rowHeight={ROW_HEIGHT}
height={tableHeight}
width={tableWidth}
fixedColumnCount={fixedColumnCount}
fixedRowCount={1}
enableFixedColumnScroll={true}
enableFixedRowScroll={true}
scrollToRow={scrollToRow}
scrollToColumn={scrollToColumn}
cellRenderer={this.cellRenderer}
sort={sort}
hoveredColumnIndex={hoveredColumnIndex}
hoveredRowIndex={hoveredRowIndex}
hoverTime={hoverTime}
colors={colors}
fieldOptions={fieldOptions}
tableOptions={tableOptions}
timeFormat={timeFormat}
decimalPlaces={decimalPlaces}
timeColumnWidth={timeColumnWidth}
classNameBottomRightGrid="table-graph--scroll-window"
/>
)
}}
</ColumnSizer>
)}
</div>
)
}
}
const {arrayOf, bool, number, shape, string, func} = PropTypes
TableGraph.propTypes = {
data: arrayOf(shape()),
tableOptions: shape({
verticalTimeAxis: bool.isRequired,
sortBy: shape({
internalName: string.isRequired,
displayName: string.isRequired,
visible: bool.isRequired,
}).isRequired,
wrapping: string.isRequired,
fixFirstColumn: bool.isRequired,
}),
timeFormat: string.isRequired,
decimalPlaces: shape({
isEnforced: bool.isRequired,
digits: number.isRequired,
}).isRequired,
fieldOptions: arrayOf(
shape({
internalName: string.isRequired,
displayName: string.isRequired,
visible: bool.isRequired,
})
).isRequired,
hoverTime: string,
handleUpdateFieldOptions: func,
handleSetHoverTime: func,
colors: colorsStringSchema,
isInCEO: bool,
}
const mapDispatchToProps = dispatch => ({
handleUpdateFieldOptions: bindActionCreators(updateFieldOptions, dispatch),

View File

@ -5,7 +5,7 @@ import {
THRESHOLD_COLORS,
THRESHOLD_TYPE_BASE,
THRESHOLD_TYPE_TEXT,
} from 'shared/constants/thresholds'
} from 'src/shared/constants/thresholds'
import {
CELL_TYPE_LINE,
@ -48,6 +48,8 @@ export const generateThresholdsListHexs = ({
cellType === CELL_TYPE_TABLE ? '#BEC2CC' : THRESHOLD_COLORS[11].hex,
}
const lastValueNumber = Number(lastValue) || 0
let bgColor
let textColor
if (!colors.length) {
return defaultColoring
@ -85,16 +87,14 @@ export const generateThresholdsListHexs = ({
colors,
lastValueNumber
)
const bgColor = null
const textColor = nearestCrossedThreshold.hex
return {bgColor, textColor}
return {bgColor: null, textColor: nearestCrossedThreshold.hex}
}
// When there is only a base color and it's applued to the background
if (colors.length === 1) {
const bgColor = baseColor.hex
const textColor = getLegibleTextColor(bgColor)
bgColor = baseColor.hex
textColor = getLegibleTextColor(bgColor)
return {bgColor, textColor}
}
@ -106,16 +106,16 @@ export const generateThresholdsListHexs = ({
lastValueNumber
)
const bgColor = nearestCrossedThreshold
bgColor = nearestCrossedThreshold
? nearestCrossedThreshold.hex
: baseColor.hex
const textColor = getLegibleTextColor(bgColor)
textColor = getLegibleTextColor(bgColor)
return {bgColor, textColor}
}
// If all else fails, use safe default
const bgColor = null
const textColor = baseColor.hex
bgColor = null
textColor = baseColor.hex
return {bgColor, textColor}
}

View File

@ -1,7 +1,12 @@
import {map, reduce} from 'fast.js'
import {groupByTimeSeriesTransform} from 'src/utils/groupByTimeSeriesTransform'
export const timeSeriesToDygraph = (raw = [], isInDataExplorer) => {
import {TimeSeriesServerResponse} from 'src/types/series'
export const timeSeriesToDygraph = (
raw: TimeSeriesServerResponse,
isInDataExplorer: boolean
) => {
const isTable = false
const {sortedLabels, sortedTimeSeries} = groupByTimeSeriesTransform(
raw,
@ -31,7 +36,7 @@ export const timeSeriesToDygraph = (raw = [], isInDataExplorer) => {
}
}
export const timeSeriesToTableGraph = raw => {
export const timeSeriesToTableGraph = (raw: TimeSeriesServerResponse) => {
const isTable = true
const {sortedLabels, sortedTimeSeries} = groupByTimeSeriesTransform(
raw,

View File

@ -24,6 +24,10 @@
version "0.22.7"
resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.7.tgz#4a92eafedfb2b9f4437d3a4410006d81114c66ce"
"@types/chroma-js@^1.3.4":
version "1.3.4"
resolved "https://registry.yarnpkg.com/@types/chroma-js/-/chroma-js-1.3.4.tgz#ef6d73041992544f492c5baad96468791ec45af5"
"@types/codemirror@^0.0.56":
version "0.0.56"
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.56.tgz#1fcf68df0d0a49791d843dadda7d94891ac88669"
@ -61,7 +65,7 @@
version "9.6.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.6.tgz#439b91f9caf3983cad2eef1e11f6bedcbf9431d2"
"@types/prop-types@^15.5.2":
"@types/prop-types@*", "@types/prop-types@^15.5.2":
version "15.5.2"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.2.tgz#3c6b8dceb2906cc87fe4358e809f9d20c8d59be1"
@ -84,6 +88,13 @@
"@types/history" "^3"
"@types/react" "*"
"@types/react-virtualized@^9.18.3":
version "9.18.3"
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.18.3.tgz#777b3c28bd2b972d0a402f2f9d11bacef550be1c"
dependencies:
"@types/prop-types" "*"
"@types/react" "*"
"@types/react@*", "@types/react@^16.0.38":
version "16.3.12"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.3.12.tgz#68d9146f3e9797e38ffbf22f7ed1dde91a2cfd2e"