diff --git a/ui/src/shared/components/TableGraph.js b/ui/src/shared/components/TableGraph.js index 511c93bdf..c22030010 100644 --- a/ui/src/shared/components/TableGraph.js +++ b/ui/src/shared/components/TableGraph.js @@ -14,8 +14,12 @@ import { NULL_HOVER_TIME, TIME_FORMAT_DEFAULT, TIME_COLUMN_DEFAULT, + ASCENDING, + DESCENDING, FIX_FIRST_COLUMN_DEFAULT, } from 'src/shared/constants/tableGraph' +const DEFAULT_SORT = ASCENDING + import {generateThresholdsListHexs} from 'shared/constants/colorOperations' class TableGraph extends Component { @@ -26,21 +30,50 @@ class TableGraph extends Component { unzippedData: [[]], hoveredColumnIndex: NULL_COLUMN_INDEX, hoveredRowIndex: NULL_ROW_INDEX, - sortByColumnIndex: -1, + sortByColumnIndex: NULL_COLUMN_INDEX, + clickToSortFieldIndex: NULL_COLUMN_INDEX, + clicktoSortDirection: DEFAULT_SORT, } } componentWillReceiveProps(nextProps) { - const {data, unzippedData} = timeSeriesToTableGraph(nextProps.data) - - const {tableOptions: {sortBy: {internalName}}} = nextProps - const sortByColumnIndex = _.indexOf(data[0], internalName) - - const sortedData = _.sortBy(_.drop(data, 1), sortByColumnIndex) - this.setState({ - data: [data[0], ...sortedData], - unzippedData, + const {data} = timeSeriesToTableGraph(nextProps.data) + const { + clickToSortFieldIndex, + clicktoSortDirection, sortByColumnIndex, + } = this.state + const {tableOptions: {sortBy: {internalName}}} = nextProps + if ( + sortByColumnIndex === NULL_COLUMN_INDEX || + _.get(this.props, ['tableOptions', 'sortBy', 'internalName'], '') !== + internalName + ) { + const newSortByColumnIndex = _.indexOf(data[0], internalName) + const sortedData = [ + data[0], + ..._.orderBy(_.drop(data, 1), newSortByColumnIndex, [DEFAULT_SORT]), + ] + this.setState({ + data: sortedData, + unzippedData: _.unzip(sortedData), + sortByColumnIndex: newSortByColumnIndex, + clickToSortFieldIndex: NULL_COLUMN_INDEX, + clicktoSortDirection: DEFAULT_SORT, + }) + return + } + + const clicked = clickToSortFieldIndex !== NULL_COLUMN_INDEX + const sortIndex = clicked ? clickToSortFieldIndex : sortByColumnIndex + const direction = clicked ? clicktoSortDirection : DEFAULT_SORT + const sortedData = [ + data[0], + ..._.orderBy(_.drop(data, 1), sortIndex, [direction]), + ] + this.setState({ + data: sortedData, + unzippedData: _.unzip(sortedData), }) } @@ -81,14 +114,44 @@ class TableGraph extends Component { } } - cellRenderer = ({columnIndex, rowIndex, key, style, parent}) => { - const {colors, tableOptions} = this.props + handleClickFieldName = (columnIndex, rowIndex) => () => { + const {tableOptions} = this.props + const {clickToSortFieldIndex, clicktoSortDirection, data} = this.state + const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true) + const newIndex = verticalTimeAxis ? columnIndex : rowIndex + + if (clickToSortFieldIndex === newIndex) { + const direction = + clicktoSortDirection === ASCENDING ? DESCENDING : ASCENDING + const sortedData = [ + data[0], + ..._.orderBy(_.drop(data, 1), clickToSortFieldIndex, [direction]), + ] + this.setState({ + data: sortedData, + unzippedData: _.unzip(sortedData), + clicktoSortDirection: direction, + }) + return + } + + const sortedData = [ + data[0], + ..._.orderBy(_.drop(data, 1), clickToSortFieldIndex, [DEFAULT_SORT]), + ] + this.setState({ + data: sortedData, + unzippedData: _.unzip(sortedData), + clickToSortFieldIndex: newIndex, + clicktoSortDirection: DEFAULT_SORT, + }) + } + + cellRenderer = ({columnIndex, rowIndex, key, parent, style}) => { const {hoveredColumnIndex, hoveredRowIndex} = this.state - - const data = _.get(tableOptions, 'verticalTimeAxis', true) - ? this.state.data - : this.state.unzippedData - + const {tableOptions, colors} = this.props + const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true) + const data = verticalTimeAxis ? this.state.data : this.state.unzippedData const timeFormat = _.get(tableOptions, 'timeFormat', TIME_FORMAT_DEFAULT) const columnNames = _.get(tableOptions, 'columnNames', [ TIME_COLUMN_DEFAULT, @@ -101,9 +164,10 @@ class TableGraph extends Component { const isFixedRow = rowIndex === 0 && columnIndex > 0 const isFixedColumn = fixFirstColumn && rowIndex > 0 && columnIndex === 0 - const isTimeData = tableOptions.verticalTimeAxis + const isTimeData = verticalTimeAxis ? rowIndex > 0 && columnIndex === 0 : isFixedRow + const isFieldName = verticalTimeAxis ? rowIndex === 0 : columnIndex === 0 const isFixedCorner = rowIndex === 0 && columnIndex === 0 const dataIsNumerical = _.isNumber(data[rowIndex][columnIndex]) const isHighlightedRow = @@ -135,6 +199,7 @@ class TableGraph extends Component { 'table-graph-cell__highlight-row': isHighlightedRow, 'table-graph-cell__highlight-column': isHighlightedColumn, 'table-graph-cell__numerical': dataIsNumerical, + 'table-graph-cell__isFieldName': isFieldName, }) const cellData = data[rowIndex][columnIndex] @@ -153,6 +218,9 @@ class TableGraph extends Component { key={key} style={cellStyle} className={cellClass} + onClick={ + isFieldName ? this.handleClickFieldName(columnIndex, rowIndex) : null + } onMouseOver={this.handleHover(columnIndex, rowIndex)} title={cellContents} alt={cellContents} @@ -163,11 +231,15 @@ class TableGraph extends Component { } render() { - const {sortByColumnIndex, hoveredColumnIndex, hoveredRowIndex} = this.state + const { + sortByColumnIndex, + clickToSortFieldIndex, + clicktoSortDirection, + hoveredColumnIndex, + hoveredRowIndex, + } = this.state const {hoverTime, tableOptions, colors} = this.props - const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true) - const data = verticalTimeAxis ? this.state.data : this.state.unzippedData const columnCount = _.get(data, ['0', 'length'], 0) @@ -175,8 +247,8 @@ class TableGraph extends Component { const COLUMN_MIN_WIDTH = 98 const COLUMN_MAX_WIDTH = 500 const ROW_HEIGHT = 30 - const tableWidth = this.gridContainer ? this.gridContainer.clientWidth : 0 - const tableHeight = this.gridContainer ? this.gridContainer.clientHeight : 0 + const tableWidth = _.get(this, ['gridContainer', 'clientWidth'], 0) + const tableHeight = _.get(this, ['gridContainer', 'clientHeight'], 0) const hoverTimeIndex = hoveredRowIndex === NULL_ROW_INDEX ? this.calcHoverTimeIndex(data, hoverTime, verticalTimeAxis) @@ -226,6 +298,8 @@ class TableGraph extends Component { scrollToColumn={scrollToColumn} verticalTimeAxis={verticalTimeAxis} sortByColumnIndex={sortByColumnIndex} + clickToSortFieldIndex={clickToSortFieldIndex} + clicktoSortDirection={clicktoSortDirection} cellRenderer={this.cellRenderer} hoveredColumnIndex={hoveredColumnIndex} hoveredRowIndex={hoveredRowIndex} diff --git a/ui/src/shared/constants/tableGraph.js b/ui/src/shared/constants/tableGraph.js index 2f3c9d944..460a9de92 100644 --- a/ui/src/shared/constants/tableGraph.js +++ b/ui/src/shared/constants/tableGraph.js @@ -8,6 +8,8 @@ export const TIME_FORMAT_CUSTOM = 'Custom' export const TIME_COLUMN_DEFAULT = {internalName: 'time', displayName: ''} +export const ASCENDING = 'asc' +export const DESCENDING = 'desc' export const FIX_FIRST_COLUMN_DEFAULT = true export const FORMAT_OPTIONS = [ diff --git a/ui/src/style/components/table-graph.scss b/ui/src/style/components/table-graph.scss index 21c952480..1a217e1bf 100644 --- a/ui/src/style/components/table-graph.scss +++ b/ui/src/style/components/table-graph.scss @@ -67,6 +67,18 @@ border-color: $g20-white; &:after {visibility: hidden;} } + &__isFieldName:hover { + cursor: pointer; + } + &__isFieldName:before { + font-family: 'icomoon'; + content: "\e902"; + font-size: 17px; + } + &__isSortedUp { + } + &__isSortedDown { + } } .ReactVirtualized__Grid { diff --git a/ui/src/utils/timeSeriesToDygraph.js b/ui/src/utils/timeSeriesToDygraph.js index b5d18c3cc..89873d5eb 100644 --- a/ui/src/utils/timeSeriesToDygraph.js +++ b/ui/src/utils/timeSeriesToDygraph.js @@ -178,11 +178,8 @@ export const timeSeriesToTableGraph = raw => { const tableData = map(sortedTimeSeries, ({time, values}) => [time, ...values]) const data = tableData.length ? [labels, ...tableData] : [[]] - const unzippedData = _.unzip(data) - return { - data, - unzippedData, - } + + return {data} } export default timeSeriesToDygraph