From 30164a1e9b6778fc5c44bde3e221c72d60764af7 Mon Sep 17 00:00:00 2001 From: ebb-tide Date: Wed, 9 May 2018 13:25:11 -0700 Subject: [PATCH] Convert TableGraph to TS --- ui/package.json | 2 + .../constants/{index.js => index.ts} | 0 .../shared/components/MultiGrid/MultiGrid.tsx | 16 +- .../{TableGraph.js => TableGraph.tsx} | 194 ++++++++++-------- ...{colorOperations.js => colorOperations.ts} | 20 +- .../{tableGraph.js => tableGraph.ts} | 0 ...nsformers.js => timeSeriesTransformers.ts} | 9 +- ui/yarn.lock | 13 +- 8 files changed, 147 insertions(+), 107 deletions(-) rename ui/src/dashboards/constants/{index.js => index.ts} (100%) rename ui/src/shared/components/{TableGraph.js => TableGraph.tsx} (78%) rename ui/src/shared/constants/{colorOperations.js => colorOperations.ts} (88%) rename ui/src/shared/constants/{tableGraph.js => tableGraph.ts} (100%) rename ui/src/utils/{timeSeriesTransformers.js => timeSeriesTransformers.ts} (81%) diff --git a/ui/package.json b/ui/package.json index 0fa63f482a..dd28024768 100644 --- a/ui/package.json +++ b/ui/package.json @@ -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", diff --git a/ui/src/dashboards/constants/index.js b/ui/src/dashboards/constants/index.ts similarity index 100% rename from ui/src/dashboards/constants/index.js rename to ui/src/dashboards/constants/index.ts diff --git a/ui/src/shared/components/MultiGrid/MultiGrid.tsx b/ui/src/shared/components/MultiGrid/MultiGrid.tsx index 585012026a..8770739055 100644 --- a/ui/src/shared/components/MultiGrid/MultiGrid.tsx +++ b/ui/src/shared/components/MultiGrid/MultiGrid.tsx @@ -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 { 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 diff --git a/ui/src/shared/components/TableGraph.js b/ui/src/shared/components/TableGraph.tsx similarity index 78% rename from ui/src/shared/components/TableGraph.js rename to ui/src/shared/components/TableGraph.tsx index cc5326ec70..a43bda6ec9 100644 --- a/ui/src/shared/components/TableGraph.js +++ b/ui/src/shared/components/TableGraph.tsx @@ -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 { + private multiGridRef: React.RefObject + private gridContainer: React.Ref + constructor(props) { super(props) @@ -40,6 +95,7 @@ class TableGraph extends Component { ['tableOptions', 'sortBy', 'internalName'], DEFAULT_TIME_FIELD.internalName ) + this.multiGridRef = React.createRef() 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 (
(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}) => ( - 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 ( + + ) + }} )}
) } } -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), diff --git a/ui/src/shared/constants/colorOperations.js b/ui/src/shared/constants/colorOperations.ts similarity index 88% rename from ui/src/shared/constants/colorOperations.js rename to ui/src/shared/constants/colorOperations.ts index 6e7cf74d1f..82b7fedb66 100644 --- a/ui/src/shared/constants/colorOperations.js +++ b/ui/src/shared/constants/colorOperations.ts @@ -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} } diff --git a/ui/src/shared/constants/tableGraph.js b/ui/src/shared/constants/tableGraph.ts similarity index 100% rename from ui/src/shared/constants/tableGraph.js rename to ui/src/shared/constants/tableGraph.ts diff --git a/ui/src/utils/timeSeriesTransformers.js b/ui/src/utils/timeSeriesTransformers.ts similarity index 81% rename from ui/src/utils/timeSeriesTransformers.js rename to ui/src/utils/timeSeriesTransformers.ts index 2481db533d..a094ad326a 100644 --- a/ui/src/utils/timeSeriesTransformers.js +++ b/ui/src/utils/timeSeriesTransformers.ts @@ -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, diff --git a/ui/yarn.lock b/ui/yarn.lock index 8b3d253a90..b4b7792b01 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -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"