connect tableOptions field visibility toggle to tableGraph
parent
9d550a7997
commit
e7f89b6322
|
@ -12,7 +12,7 @@ interface Props {
|
||||||
internalName: string
|
internalName: string
|
||||||
displayName: string
|
displayName: string
|
||||||
visible: boolean
|
visible: boolean
|
||||||
onColumnRename: (column: Column) => void
|
onColumnUpdate: (column: Column) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
class GraphOptionsCustomizableColumn extends PureComponent<Props, {}> {
|
class GraphOptionsCustomizableColumn extends PureComponent<Props, {}> {
|
||||||
|
@ -24,26 +24,26 @@ class GraphOptionsCustomizableColumn extends PureComponent<Props, {}> {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleColumnRename(rename: string) {
|
handleColumnRename(rename: string) {
|
||||||
const {onColumnRename, internalName, visible} = this.props
|
const {onColumnUpdate, internalName, visible} = this.props
|
||||||
onColumnRename({internalName, displayName: rename, visible})
|
onColumnUpdate({internalName, displayName: rename, visible})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleToggleVisible() {
|
handleToggleVisible() {
|
||||||
const {onColumnRename, internalName, displayName, visible} = this.props
|
const {onColumnUpdate, internalName, displayName, visible} = this.props
|
||||||
onColumnRename({internalName, displayName, visible: !visible})
|
onColumnUpdate({internalName, displayName, visible: !visible})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {internalName, displayName, visible} = this.props
|
const {internalName, displayName, visible} = this.props
|
||||||
console.log('VISIBLE:', visible)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="column-controls--section">
|
<div className="column-controls--section">
|
||||||
<div
|
<div
|
||||||
className="column-controls--label"
|
className={
|
||||||
onClick={this.handleToggleVisible}
|
visible ? 'column-controls--label' : 'column-controls--label-hidden'
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<span className="icon eye" />
|
<span className="icon eye" onClick={this.handleToggleVisible} />
|
||||||
{internalName}
|
{internalName}
|
||||||
</div>
|
</div>
|
||||||
<InputClickToEdit
|
<InputClickToEdit
|
||||||
|
@ -52,6 +52,7 @@ class GraphOptionsCustomizableColumn extends PureComponent<Props, {}> {
|
||||||
onBlur={this.handleColumnRename}
|
onBlur={this.handleColumnRename}
|
||||||
placeholder="Rename..."
|
placeholder="Rename..."
|
||||||
appearAsNormalInput={true}
|
appearAsNormalInput={true}
|
||||||
|
disabled={!visible}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,12 +11,12 @@ type Column = {
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
columns: Column[]
|
columns: Column[]
|
||||||
onColumnRename: (column: Column) => void
|
onColumnUpdate: (column: Column) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const GraphOptionsCustomizeColumns: SFC<Props> = ({
|
const GraphOptionsCustomizeColumns: SFC<Props> = ({
|
||||||
columns,
|
columns,
|
||||||
onColumnRename,
|
onColumnUpdate,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="graph-options-group">
|
<div className="graph-options-group">
|
||||||
|
@ -28,7 +28,7 @@ const GraphOptionsCustomizeColumns: SFC<Props> = ({
|
||||||
internalName={col.internalName}
|
internalName={col.internalName}
|
||||||
displayName={col.displayName}
|
displayName={col.displayName}
|
||||||
visible={col.visible}
|
visible={col.visible}
|
||||||
onColumnRename={onColumnRename}
|
onColumnUpdate={onColumnUpdate}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {updateTableOptions} from 'src/dashboards/actions/cellEditorOverlay'
|
||||||
type TableColumn = {
|
type TableColumn = {
|
||||||
internalName: string
|
internalName: string
|
||||||
displayName: string
|
displayName: string
|
||||||
|
visible: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
|
@ -74,7 +75,7 @@ export class TableOptions extends PureComponent<Props, {}> {
|
||||||
const existing = this.columnNames.find(
|
const existing = this.columnNames.find(
|
||||||
c => c.internalName === internalName
|
c => c.internalName === internalName
|
||||||
)
|
)
|
||||||
return existing || {internalName, displayName: ''}
|
return existing || {internalName, displayName: '', visible: true}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -92,7 +93,11 @@ export class TableOptions extends PureComponent<Props, {}> {
|
||||||
|
|
||||||
handleChooseSortBy = option => {
|
handleChooseSortBy = option => {
|
||||||
const {tableOptions, handleUpdateTableOptions} = this.props
|
const {tableOptions, handleUpdateTableOptions} = this.props
|
||||||
const sortBy = {displayName: option.text, internalName: option.key}
|
const sortBy = {
|
||||||
|
displayName: option.text,
|
||||||
|
internalName: option.key,
|
||||||
|
visible: true,
|
||||||
|
}
|
||||||
|
|
||||||
handleUpdateTableOptions({...tableOptions, sortBy})
|
handleUpdateTableOptions({...tableOptions, sortBy})
|
||||||
}
|
}
|
||||||
|
@ -115,7 +120,7 @@ export class TableOptions extends PureComponent<Props, {}> {
|
||||||
handleUpdateTableOptions({...tableOptions, fixFirstColumn})
|
handleUpdateTableOptions({...tableOptions, fixFirstColumn})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleColumnRename = column => {
|
handleColumnUpdate = column => {
|
||||||
const {handleUpdateTableOptions, tableOptions} = this.props
|
const {handleUpdateTableOptions, tableOptions} = this.props
|
||||||
const {columnNames} = tableOptions
|
const {columnNames} = tableOptions
|
||||||
const updatedColumns = columnNames.map(
|
const updatedColumns = columnNames.map(
|
||||||
|
@ -173,7 +178,7 @@ export class TableOptions extends PureComponent<Props, {}> {
|
||||||
</div>
|
</div>
|
||||||
<GraphOptionsCustomizeColumns
|
<GraphOptionsCustomizeColumns
|
||||||
columns={columns}
|
columns={columns}
|
||||||
onColumnRename={this.handleColumnRename}
|
onColumnUpdate={this.handleColumnUpdate}
|
||||||
/>
|
/>
|
||||||
<ThresholdsList showListHeading={true} onResetFocus={onResetFocus} />
|
<ThresholdsList showListHeading={true} onResetFocus={onResetFocus} />
|
||||||
<div className="form-group-wrapper graph-options-group">
|
<div className="form-group-wrapper graph-options-group">
|
||||||
|
|
|
@ -24,26 +24,56 @@ class TableGraph extends Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
data: [[]],
|
data: [[]],
|
||||||
unzippedData: [[]],
|
unzippedData: [[]],
|
||||||
|
visibleData: [[]],
|
||||||
hoveredColumnIndex: NULL_COLUMN_INDEX,
|
hoveredColumnIndex: NULL_COLUMN_INDEX,
|
||||||
hoveredRowIndex: NULL_ROW_INDEX,
|
hoveredRowIndex: NULL_ROW_INDEX,
|
||||||
sortByColumnIndex: -1,
|
sortByColumnIndex: -1,
|
||||||
|
invisibleFieldIndices: [],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
const {data, unzippedData} = timeSeriesToTableGraph(nextProps.data)
|
const {data, unzippedData} = timeSeriesToTableGraph(nextProps.data)
|
||||||
|
|
||||||
const {tableOptions: {sortBy: {internalName}}} = nextProps
|
const {
|
||||||
|
tableOptions: {sortBy: {internalName}, columnNames, verticalTimeAxis},
|
||||||
|
} = nextProps
|
||||||
const sortByColumnIndex = _.indexOf(data[0], internalName)
|
const sortByColumnIndex = _.indexOf(data[0], internalName)
|
||||||
|
|
||||||
const sortedData = _.sortBy(_.drop(data, 1), sortByColumnIndex)
|
const sortedData = [
|
||||||
|
data[0],
|
||||||
|
..._.sortBy(_.drop(data, 1), sortByColumnIndex),
|
||||||
|
]
|
||||||
|
|
||||||
|
if (verticalTimeAxis) {
|
||||||
|
const visibleColumns = {}
|
||||||
|
const filteredData = sortedData.map((row, i) => {
|
||||||
|
return row.filter((col, j) => {
|
||||||
|
if (i === 0) {
|
||||||
|
const foundColumn = columnNames.find(
|
||||||
|
column => column.internalName === col
|
||||||
|
)
|
||||||
|
visibleColumns[j] = foundColumn && foundColumn.visible
|
||||||
|
}
|
||||||
|
return visibleColumns[j]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const visibleData = filteredData[0].length ? filteredData : [[]]
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
data: [data[0], ...sortedData],
|
data: sortedData,
|
||||||
|
visibleData,
|
||||||
unzippedData,
|
unzippedData,
|
||||||
sortByColumnIndex,
|
sortByColumnIndex,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this._data = [[]]
|
||||||
|
this._visibleData = [[]]
|
||||||
|
}
|
||||||
|
|
||||||
calcHoverTimeIndex = (data, hoverTime, verticalTimeAxis) => {
|
calcHoverTimeIndex = (data, hoverTime, verticalTimeAxis) => {
|
||||||
if (isEmpty(data) || hoverTime === NULL_HOVER_TIME) {
|
if (isEmpty(data) || hoverTime === NULL_HOVER_TIME) {
|
||||||
return undefined
|
return undefined
|
||||||
|
@ -101,11 +131,17 @@ class TableGraph extends Component {
|
||||||
FIX_FIRST_COLUMN_DEFAULT
|
FIX_FIRST_COLUMN_DEFAULT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const timeField = columnNames.find(
|
||||||
|
column => column.internalName === TIME_COLUMN_DEFAULT.internalName
|
||||||
|
)
|
||||||
|
|
||||||
const isFixedRow = rowIndex === 0 && columnIndex > 0
|
const isFixedRow = rowIndex === 0 && columnIndex > 0
|
||||||
const isFixedColumn = fixFirstColumn && rowIndex > 0 && columnIndex === 0
|
const isFixedColumn = fixFirstColumn && rowIndex > 0 && columnIndex === 0
|
||||||
const isTimeData = tableOptions.verticalTimeAxis
|
const isTimeData =
|
||||||
? rowIndex > 0 && columnIndex === 0
|
timeField.visible &&
|
||||||
: isFixedRow
|
(tableOptions.verticalTimeAxis
|
||||||
|
? rowIndex > 0 && columnIndex === 0
|
||||||
|
: isFixedRow)
|
||||||
const isFixedCorner = rowIndex === 0 && columnIndex === 0
|
const isFixedCorner = rowIndex === 0 && columnIndex === 0
|
||||||
const isLastRow = rowIndex === rowCount - 1
|
const isLastRow = rowIndex === rowCount - 1
|
||||||
const isLastColumn = columnIndex === columnCount - 1
|
const isLastColumn = columnIndex === columnCount - 1
|
||||||
|
@ -168,7 +204,9 @@ class TableGraph extends Component {
|
||||||
|
|
||||||
const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true)
|
const verticalTimeAxis = _.get(tableOptions, 'verticalTimeAxis', true)
|
||||||
|
|
||||||
const data = verticalTimeAxis ? this.state.data : this.state.unzippedData
|
const data = verticalTimeAxis
|
||||||
|
? this.state.visibleData
|
||||||
|
: this.state.unzippedData
|
||||||
|
|
||||||
const columnCount = _.get(data, ['0', 'length'], 0)
|
const columnCount = _.get(data, ['0', 'length'], 0)
|
||||||
const rowCount = data.length
|
const rowCount = data.length
|
||||||
|
@ -193,7 +231,7 @@ class TableGraph extends Component {
|
||||||
ref={gridContainer => (this.gridContainer = gridContainer)}
|
ref={gridContainer => (this.gridContainer = gridContainer)}
|
||||||
onMouseOut={this.handleMouseOut}
|
onMouseOut={this.handleMouseOut}
|
||||||
>
|
>
|
||||||
{!isEmpty(data) &&
|
{!isEmpty(visibleData) &&
|
||||||
<MultiGrid
|
<MultiGrid
|
||||||
columnCount={columnCount}
|
columnCount={columnCount}
|
||||||
columnWidth={COLUMN_WIDTH}
|
columnWidth={COLUMN_WIDTH}
|
||||||
|
|
|
@ -257,17 +257,30 @@ button.btn.btn-primary.btn-sm.gauge-controls--add-threshold {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.column-controls--label {
|
.column-controls--label, .column-controls--label-hidden {
|
||||||
@extend %gauge-controls-label-styles;
|
@extend %gauge-controls-label-styles;
|
||||||
color: $g16-pearl;
|
color: $g16-pearl;
|
||||||
background-color: $g4-onyx;
|
background-color: $g4-onyx;
|
||||||
flex: 2 0 0;
|
flex: 2 0 0;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
padding-right: 5px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.column-controls--label-hidden {
|
||||||
|
color: $g0-obsidian;
|
||||||
}
|
}
|
||||||
.column-controls-input {
|
.column-controls-input {
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Cell Editor Overlay - Single-Stat Controls
|
Cell Editor Overlay - Single-Stat Controls
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
|
@ -9,7 +9,8 @@ const setup = (override = {}) => {
|
||||||
const props = {
|
const props = {
|
||||||
internalName: '',
|
internalName: '',
|
||||||
displayName: '',
|
displayName: '',
|
||||||
onColumnRename: () => {},
|
visible: true,
|
||||||
|
onColumnUpdate: () => {},
|
||||||
...override,
|
...override,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,17 +43,17 @@ describe('Dashboards.Components.GraphOptionsCustomizableColumn', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('instance methods', () => {
|
describe('instance methods', () => {
|
||||||
describe('#handleColumnRename', () => {
|
describe('#handleColumnUpdate', () => {
|
||||||
it('calls onColumnRename once', () => {
|
it('calls onColumnUpdate once', () => {
|
||||||
const onColumnRename = jest.fn()
|
const onColumnUpdate = jest.fn()
|
||||||
const internalName = 'test'
|
const internalName = 'test'
|
||||||
const {instance} = setup({onColumnRename, internalName})
|
const {instance} = setup({onColumnUpdate, internalName})
|
||||||
const rename = 'TEST'
|
const rename = 'TEST'
|
||||||
|
|
||||||
instance.handleColumnRename(rename)
|
instance.handleColumnRename(rename)
|
||||||
|
|
||||||
expect(onColumnRename).toHaveBeenCalledTimes(1)
|
expect(onColumnUpdate).toHaveBeenCalledTimes(1)
|
||||||
expect(onColumnRename).toHaveBeenCalledWith({
|
expect(onColumnUpdate).toHaveBeenCalledWith({
|
||||||
internalName,
|
internalName,
|
||||||
displayName: rename,
|
displayName: rename,
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {shallow} from 'enzyme'
|
||||||
const setup = (override = {}) => {
|
const setup = (override = {}) => {
|
||||||
const props = {
|
const props = {
|
||||||
columns: [],
|
columns: [],
|
||||||
onColumnRename: () => {},
|
onColumnUpdate: () => {},
|
||||||
...override,
|
...override,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue