Add more types to tablegraph

chore/tables-to-TS
ebb-tide 2018-05-10 16:30:11 -07:00
parent 867f8b343a
commit 1876c91bdc
3 changed files with 102 additions and 56 deletions

View File

@ -4,8 +4,15 @@ import {map, reduce, filter} from 'fast.js'
import {CELL_HORIZONTAL_PADDING} from 'src/shared/constants/tableGraph'
import {DEFAULT_TIME_FIELD, DEFAULT_TIME_FORMAT} from 'src/dashboards/constants'
import {
DbData,
Sort,
FieldOption,
TableOptions,
DecimalPlaces,
} from 'src/types/dashboard'
const calculateTimeColumnWidth = timeFormat => {
const calculateTimeColumnWidth = (timeFormat: string): number => {
// Force usage of longest format names for ideal measurement
timeFormat = _.replace(timeFormat, 'MMMM', 'September')
timeFormat = _.replace(timeFormat, 'dddd', 'Wednesday')
@ -22,17 +29,21 @@ const calculateTimeColumnWidth = timeFormat => {
return width + CELL_HORIZONTAL_PADDING
}
interface ColumnWidths {
totalWidths: number
widths: {[x: string]: number}
}
const updateMaxWidths = (
row,
maxColumnWidths,
topRow,
isTopRow,
fieldOptions,
timeFormatWidth,
verticalTimeAxis,
decimalPlaces
) => {
return reduce(
row: DbData[],
maxColumnWidths: ColumnWidths,
topRow: DbData[],
isTopRow: boolean,
fieldOptions: FieldOption[],
timeFormatWidth: number,
verticalTimeAxis: boolean,
decimalPlaces: DecimalPlaces
): ColumnWidths => {
const maxWidths = reduce(
row,
(acc, col, c) => {
const isLabel =
@ -79,14 +90,22 @@ const updateMaxWidths = (
},
{...maxColumnWidths}
)
return maxWidths
}
export const computeFieldOptions = (existingFieldOptions, sortedLabels) => {
interface SortedLabel {
label: string
responseIndex: number
seriesIndex: number
}
export const computeFieldOptions = (
existingFieldOptions: FieldOption[],
sortedLabels: SortedLabel[]
): FieldOption[] => {
const timeField =
existingFieldOptions.find(f => f.internalName === 'time') ||
DEFAULT_TIME_FIELD
let astNames = [timeField]
sortedLabels.forEach(({label}) => {
const field = {
internalName: label,
@ -108,12 +127,12 @@ export const computeFieldOptions = (existingFieldOptions, sortedLabels) => {
}
export const calculateColumnWidths = (
data,
fieldOptions,
timeFormat,
verticalTimeAxis,
decimalPlaces
) => {
data: DbData[][],
fieldOptions: FieldOption[],
timeFormat: string,
verticalTimeAxis: boolean,
decimalPlaces: DecimalPlaces
): ColumnWidths => {
const timeFormatWidth = calculateTimeColumnWidth(
timeFormat === '' ? DEFAULT_TIME_FORMAT : timeFormat
)
@ -135,7 +154,10 @@ export const calculateColumnWidths = (
)
}
export const filterTableColumns = (data, fieldOptions) => {
export const filterTableColumns = (
data: DbData[][],
fieldOptions: FieldOption[]
): DbData[][] => {
const visibility = {}
const filteredData = map(data, (row, i) => {
return filter(row, (col, j) => {
@ -151,7 +173,10 @@ export const filterTableColumns = (data, fieldOptions) => {
return filteredData[0].length ? filteredData : [[]]
}
export const orderTableColumns = (data, fieldOptions) => {
export const orderTableColumns = (
data: DbData[][],
fieldOptions: FieldOption[]
): DbData[][] => {
const fieldsSortOrder = fieldOptions.map(fieldOption => {
return _.findIndex(data[0], dataLabel => {
return dataLabel === fieldOption.internalName
@ -164,14 +189,20 @@ export const orderTableColumns = (data, fieldOptions) => {
return orderedData[0].length ? orderedData : [[]]
}
interface TransformTableDataReturnType {
transformedData: DbData[][]
sortedTimeVals: number[]
columnWidths: ColumnWidths
totalWidths: number
}
export const transformTableData = (
data,
sort,
fieldOptions,
tableOptions,
timeFormat,
decimalPlaces
) => {
data: DbData[][],
sort: Sort,
fieldOptions: FieldOption[],
tableOptions: TableOptions,
timeFormat: string,
decimalPlaces: DecimalPlaces
): TransformTableDataReturnType => {
const {verticalTimeAxis} = tableOptions
const sortIndex = _.indexOf(data[0], sort.field)
const sortedData = [

View File

@ -35,7 +35,7 @@ import {
FieldOption,
DecimalPlaces,
Sort,
dbData,
DbData,
} from 'src/types/dashboard'
interface Props {
@ -52,19 +52,24 @@ interface Props {
}
interface State {
data: dbData[][]
transformedData: dbData[][]
data: DbData[][]
transformedData: DbData[][]
sortedTimeVals: number[]
sortedLabels: string[]
hoveredColumnIndex: number
hoveredRowIndex: number
timeColumnWidth: number
sort: Sort
columnWidths: {}
columnWidths: ColumnWidths
totalColumnWidths: number
isTimeVisible: boolean
}
interface ColumnWidths {
totalWidths: number
widths: {[x: string]: number}
}
@ErrorHandling
class TableGraph extends Component<Props, State> {
private gridContainer: HTMLDivElement
@ -84,7 +89,7 @@ class TableGraph extends Component<Props, State> {
hoveredColumnIndex: NULL_ARRAY_INDEX,
hoveredRowIndex: NULL_ARRAY_INDEX,
sort: {field: sortField, direction: DEFAULT_SORT_DIRECTION},
columnWidths: {},
columnWidths: {totalWidths: 0, widths: {}},
totalColumnWidths: 0,
isTimeVisible: true,
timeColumnWidth: 0,
@ -119,7 +124,7 @@ class TableGraph extends Component<Props, State> {
const tableWidth = _.get(this, ['gridContainer', 'clientWidth'], 0)
const tableHeight = _.get(this, ['gridContainer', 'clientHeight'], 0)
const {scrollToColumn, scrollToRow} = this.calcScrollToColRow()
const {scrollToColumn, scrollToRow} = this.scrollToColRow
return (
<div
className="table-graph-container"
@ -306,7 +311,7 @@ class TableGraph extends Component<Props, State> {
}
}
private handleUpdateFieldOptions = fieldOptions => {
private handleUpdateFieldOptions = (fieldOptions: FieldOption[]): void => {
const {isInCEO} = this.props
if (!isInCEO) {
return
@ -314,7 +319,10 @@ class TableGraph extends Component<Props, State> {
this.props.handleUpdateFieldOptions(fieldOptions)
}
private calcScrollToColRow = () => {
private get scrollToColRow(): {
scrollToRow: number | null
scrollToColumn: number | null
} {
const {data, sortedTimeVals, hoveredColumnIndex, isTimeVisible} = this.state
const {hoverTime, tableOptions} = this.props
const hoveringThisTable = hoveredColumnIndex !== NULL_ARRAY_INDEX
@ -325,7 +333,7 @@ class TableGraph extends Component<Props, State> {
hoveringThisTable ||
!isTimeVisible
) {
return {scrollToColumn: undefined, scrollToRow: undefined}
return {scrollToColumn: null, scrollToRow: null}
}
const firstDiff = Math.abs(Number(hoverTime) - sortedTimeVals[1]) // sortedTimeVals[0] is "time"
@ -342,12 +350,15 @@ class TableGraph extends Component<Props, State> {
)
const {verticalTimeAxis} = tableOptions
const scrollToColumn = verticalTimeAxis ? undefined : hoverTimeFound.index
const scrollToRow = verticalTimeAxis ? hoverTimeFound.index : undefined
const scrollToColumn = verticalTimeAxis ? null : hoverTimeFound.index
const scrollToRow = verticalTimeAxis ? hoverTimeFound.index : null
return {scrollToRow, scrollToColumn}
}
private handleHover = (columnIndex, rowIndex) => () => {
private handleHover = (
columnIndex: number,
rowIndex: number
): (() => void) => (): void => {
const {
handleSetHoverTime,
tableOptions: {verticalTimeAxis},
@ -368,7 +379,7 @@ class TableGraph extends Component<Props, State> {
})
}
private handleMouseLeave = () => {
private handleMouseLeave = (): void => {
if (this.props.handleSetHoverTime) {
this.props.handleSetHoverTime(NULL_HOVER_TIME)
this.setState({
@ -378,7 +389,7 @@ class TableGraph extends Component<Props, State> {
}
}
private handleClickFieldName = clickedFieldName => () => {
private handleClickFieldName = (clickedFieldName: string) => (): void => {
const {tableOptions, fieldOptions, timeFormat, decimalPlaces} = this.props
const {data, sort} = this.state
@ -405,7 +416,9 @@ class TableGraph extends Component<Props, State> {
})
}
private calculateColumnWidth = columnSizerWidth => column => {
private calculateColumnWidth = (columnSizerWidth: number) => (column: {
index: number
}): number => {
const {index} = column
const {
tableOptions: {fixFirstColumn},
@ -435,20 +448,19 @@ class TableGraph extends Component<Props, State> {
}
private createCellContents = (
cellData,
fieldName,
isTimeData,
isFieldName,
isNumerical
) => {
cellData: DbData,
fieldName: DbData,
isTimeData: boolean,
isFieldName: boolean
): string => {
const {timeFormat, decimalPlaces} = this.props
if (isTimeData) {
return `${moment(cellData).format(timeFormat)}`
}
if (isFieldName) {
return fieldName
if (typeof cellData === 'string' && isFieldName) {
return `${fieldName}`
}
if (isNumerical && decimalPlaces.isEnforced) {
if (typeof cellData === 'number' && decimalPlaces.isEnforced) {
return cellData.toFixed(decimalPlaces.digits)
}
return `${cellData}`
@ -543,8 +555,7 @@ class TableGraph extends Component<Props, State> {
cellData,
fieldName,
isTimeData,
isFieldName,
isNumerical
isFieldName
)
return (
@ -552,7 +563,11 @@ class TableGraph extends Component<Props, State> {
key={key}
style={cellStyle}
className={cellClass}
onClick={isFieldName ? this.handleClickFieldName(cellData) : null}
onClick={
isFieldName && typeof cellData === 'string'
? this.handleClickFieldName(cellData)
: null
}
onMouseOver={_.throttle(this.handleHover(columnIndex, rowIndex), 100)}
title={cellContents}
>

View File

@ -10,7 +10,7 @@ interface Axis {
scale: string
}
export type dbData = string | number | null | undefined
export type DbData = string | number | null | undefined
export interface FieldOption {
internalName: string