Polish Table Options (#11160)

* Clean up grid

* Polish threshold list

* Add empty state to table column options

* Improve appearance of custom time format

* Use clockface input within Draggable Column

* Use clockface input in table sidebar
pull/11185/head
alexpaxton 2019-01-16 15:33:34 -08:00 committed by GitHub
parent 2332f852e7
commit 6f2b3d9f25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 220 additions and 158 deletions

View File

@ -87,6 +87,7 @@
------------------------------------------------------------------------------
*/
.form--box {
width: 100%;
border-radius: $radius;
background-color: $g4-onyx;
padding: $ix-marg-b 11px;

View File

@ -2,7 +2,7 @@
import React, {SFC} from 'react'
// Components
import {Dropdown, ComponentStatus} from 'src/clockface'
import {Dropdown, ComponentStatus, DropdownMenuColors} from 'src/clockface'
// Types
import {ColorLabel} from 'src/types/colors'
@ -29,6 +29,7 @@ const ColorDropdown: SFC<Props> = props => {
onChange={onChoose}
status={status}
widthPixels={widthPixels}
menuColor={DropdownMenuColors.Onyx}
>
{colors.map(color => (
<Dropdown.Item id={color.name} key={color.name} value={color}>

View File

@ -5,8 +5,6 @@
@import 'src/style/modules';
$time-machine--controls-height: 62px;
.time-machine {
height: 100%;
@include no-user-select();
@ -38,22 +36,9 @@ $time-machine--controls-height: 62px;
flex: 0 0 100%;
}
.time-machine--controls {
height: $time-machine--controls-height;
width: 100%;
display: flex;
align-items: center;
padding: $ix-marg-c;
justify-content: space-between;
}
.time-machine--controls .slide-toggle {
margin-right: $ix-marg-b;
}
.time-machine--view {
position: absolute;
top: $time-machine--controls-height;
top: 0;
right: 0;
bottom: 0;
left: 0;

View File

@ -18,7 +18,7 @@
&.dragging {
border-radius: 4px;
opacity: 0.25;
opacity: 0.4;
@include gradient-h($c-pool, $c-star);
> * {

View File

@ -4,7 +4,7 @@ import HTML5Backend from 'react-dnd-html5-backend'
// Components
import DraggableColumn from 'src/shared/components/draggable_column/DraggableColumn'
import {Form} from 'src/clockface'
import {ComponentSize, EmptyState, Grid, Form} from 'src/clockface'
// Types
import {FieldOption} from 'src/types/v2/dashboards'
@ -18,30 +18,41 @@ interface Props {
class ColumnsOptions extends Component<Props> {
public render() {
const {columns, className} = this.props
const {className} = this.props
return (
<Form.Element label="Table Columns">
<div className={className}>
{columns.map((c, i) => this.getDraggableColumn(c, i))}
</div>
</Form.Element>
<Grid.Column>
<Form.Element label="Table Columns">
<div className={className}>{this.draggableColumns}</div>
</Form.Element>
</Grid.Column>
)
}
private getDraggableColumn(column: FieldOption, i: number): JSX.Element {
const {onMoveColumn, onUpdateColumn} = this.props
private get draggableColumns(): JSX.Element | JSX.Element[] {
const {columns, onMoveColumn, onUpdateColumn} = this.props
if (columns.length) {
return columns.map((column: FieldOption, i: number) => (
<DraggableColumn
key={column.internalName}
index={i}
id={column.internalName}
internalName={column.internalName}
displayName={column.displayName}
visible={column.visible}
onUpdateColumn={onUpdateColumn}
onMoveColumn={onMoveColumn}
/>
))
}
return (
<DraggableColumn
key={column.internalName}
index={i}
id={column.internalName}
internalName={column.internalName}
displayName={column.displayName}
visible={column.visible}
onUpdateColumn={onUpdateColumn}
onMoveColumn={onMoveColumn}
/>
<Form.Box>
<EmptyState size={ComponentSize.Small}>
<EmptyState.Text text="This query returned no columns" />
</EmptyState>
</Form.Box>
)
}
}

View File

@ -1,3 +1,4 @@
// Libraries
import React, {Component, ChangeEvent} from 'react'
import {findDOMNode} from 'react-dom'
import {
@ -11,9 +12,17 @@ import {
ConnectDropTarget,
ConnectDragPreview,
} from 'react-dnd'
// Components
import {Input, ComponentStatus} from 'src/clockface'
// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
// Types
import {LogsTableColumn} from 'src/types/logs'
// Constants
const columnType = 'column'
interface Props {
@ -123,7 +132,6 @@ export default class DraggableColumn extends Component<Props> {
displayName,
connectDragPreview,
connectDropTarget,
visible,
} = this.props
return connectDragPreview(
@ -134,21 +142,29 @@ export default class DraggableColumn extends Component<Props> {
{this.visibilityToggle}
<div className="customizable-field--name">{internalName}</div>
</div>
<input
className="form-control input-sm customizable-field--input"
type="text"
spellCheck={false}
<Input
customClass="customizable-field--input"
id="internalName"
value={displayName}
onChange={this.handleColumnRename}
placeholder={`Rename ${internalName}`}
disabled={!visible}
status={this.inputStatus}
/>
</div>
)
)
}
private get inputStatus(): ComponentStatus {
const {visible} = this.props
if (visible) {
return ComponentStatus.Default
}
return ComponentStatus.Disabled
}
private get dragHandle(): JSX.Element {
const {connectDragSource} = this.props

View File

@ -6,6 +6,7 @@ import _ from 'lodash'
import {ErrorHandling} from 'src/shared/decorators/errors'
import FancyScrollbar from 'src/shared/components/fancy_scrollbar/FancyScrollbar'
import TableSidebarItem from 'src/shared/components/tables/TableSidebarItem'
import {Input, IconFont} from 'src/clockface'
// Types
import {FluxTable} from 'src/types'
@ -34,12 +35,12 @@ export default class TableSidebar extends PureComponent<Props, State> {
<div className="time-machine-sidebar">
{!this.isDataEmpty && (
<div className="time-machine-sidebar--heading">
<input
type="text"
className="form-control input-xs time-machine-sidebar--filter"
<Input
icon={IconFont.Search}
onChange={this.handleSearch}
placeholder="Filter tables"
placeholder="Filter tables..."
value={searchTerm}
customClass="time-machine-sidebar--filter"
/>
</div>
)}

View File

@ -78,40 +78,48 @@ export class TableOptions extends Component<Props, {}> {
<>
<Grid.Column widthSM={Columns.Four}>
<h4 className="view-options--header">Table Formatting</h4>
{!!fieldOptions.length && (
<SortBy
selected={sortBy}
fieldOptions={fieldOptions}
onChange={this.handleChangeSortBy}
/>
)}
<TimeFormat
timeFormat={timeFormat}
onTimeFormatChange={onSetTimeFormat}
/>
{decimalPlaces && (
<DecimalPlacesOption
digits={decimalPlaces.digits}
isEnforced={decimalPlaces.isEnforced}
onDecimalPlacesChange={onSetDecimalPlaces}
/>
)}
<Grid>
<Grid.Row>
{!!fieldOptions.length && (
<SortBy
selected={sortBy}
fieldOptions={fieldOptions}
onChange={this.handleChangeSortBy}
/>
)}
<TimeFormat
timeFormat={timeFormat}
onTimeFormatChange={onSetTimeFormat}
/>
{decimalPlaces && (
<DecimalPlacesOption
digits={decimalPlaces.digits}
isEnforced={decimalPlaces.isEnforced}
onDecimalPlacesChange={onSetDecimalPlaces}
/>
)}
</Grid.Row>
</Grid>
</Grid.Column>
<Grid.Column widthSM={Columns.Four}>
<h4 className="view-options--header">Column Settings</h4>
<TimeAxis
verticalTimeAxis={verticalTimeAxis}
onToggleVerticalTimeAxis={this.handleToggleVerticalTimeAxis}
/>
<FixFirstColumn
fixed={fixFirstColumn}
onToggleFixFirstColumn={this.handleToggleFixFirstColumn}
/>
<ColumnOptions
columns={fieldOptions}
onMoveColumn={this.handleMoveColumn}
onUpdateColumn={this.handleUpdateColumn}
/>
<Grid>
<Grid.Row>
<TimeAxis
verticalTimeAxis={verticalTimeAxis}
onToggleVerticalTimeAxis={this.handleToggleVerticalTimeAxis}
/>
<FixFirstColumn
fixed={fixFirstColumn}
onToggleFixFirstColumn={this.handleToggleFixFirstColumn}
/>
<ColumnOptions
columns={fieldOptions}
onMoveColumn={this.handleMoveColumn}
onUpdateColumn={this.handleUpdateColumn}
/>
</Grid.Row>
</Grid>
</Grid.Column>
<Grid.Column widthSM={Columns.Four}>
<h4 className="view-options--header">Colorized Thresholds</h4>

View File

@ -2,7 +2,7 @@ import _ from 'lodash'
import React from 'react'
// Types
import {Dropdown, Form, DropdownMode} from 'src/clockface'
import {Grid, Dropdown, Form, DropdownMode} from 'src/clockface'
import {FieldOption} from 'src/types/v2/dashboards'
interface Props {
@ -13,25 +13,27 @@ interface Props {
const SortBy = ({fieldOptions, onChange, selected}: Props) => {
return (
<Form.Element label="Default Sort Field">
<Dropdown
selectedID={_.get(selected, 'internalName', null)}
customClass="dropdown-stretch"
onChange={onChange}
mode={DropdownMode.ActionList}
titleText="Choose a sort field"
>
{fieldOptions.map(field => (
<Dropdown.Item
key={field.internalName}
id={field.internalName}
value={field}
>
{field.displayName}
</Dropdown.Item>
))}
</Dropdown>
</Form.Element>
<Grid.Column>
<Form.Element label="Default Sort Field">
<Dropdown
selectedID={_.get(selected, 'internalName', null)}
customClass="dropdown-stretch"
onChange={onChange}
mode={DropdownMode.ActionList}
titleText="Choose a sort field"
>
{fieldOptions.map(field => (
<Dropdown.Item
key={field.internalName}
id={field.internalName}
value={field}
>
{field.displayName}
</Dropdown.Item>
))}
</Dropdown>
</Form.Element>
</Grid.Column>
)
}

View File

@ -8,6 +8,7 @@ import {
InputType,
ComponentStatus,
ButtonType,
ComponentSize,
} from 'src/clockface'
import ColorDropdown from 'src/shared/components/ColorDropdown'
@ -62,6 +63,7 @@ class Threshold extends PureComponent<Props, State> {
{isDeletable &&
!isBase && (
<Button
size={ComponentSize.ExtraSmall}
shape={ButtonShape.Square}
onClick={this.handleDelete}
icon={IconFont.Remove}

View File

@ -28,22 +28,22 @@
}
.threshold-item--label {
flex: 0 0 120px;
display: flex;
align-items: center;
justify-content: space-between;
height: 30px;
font-weight: 600;
font-size: 13px;
padding-left: 11px;
padding-left: $ix-marg-b;
padding-right: $ix-marg-a;
border-radius: 4px;
@include no-user-select();
width: 120px;
background-color: $g4-onyx;
color: $g11-sidewalk;
color: $g9-mountain;
&.threshold-item--label__editable {
color: $g16-pearl;
background-color: initial;
color: $g13-mist;
}
}

View File

@ -2,7 +2,7 @@
import React, {SFC} from 'react'
// Components
import {Radio, ButtonShape, Form} from 'src/clockface'
import {Grid, Radio, ButtonShape, Form} from 'src/clockface'
interface Props {
verticalTimeAxis: boolean
@ -10,28 +10,30 @@ interface Props {
}
const TimeAxis: SFC<Props> = ({verticalTimeAxis, onToggleVerticalTimeAxis}) => (
<Form.Element label="Time Axis">
<Radio shape={ButtonShape.StretchToFit}>
<Radio.Button
id="graph-time-axis--vertical"
value={true}
active={verticalTimeAxis}
onClick={onToggleVerticalTimeAxis}
titleText="Position time on the vertical table axis"
>
Vertical
</Radio.Button>
<Radio.Button
id="graph-time-axis--horizontal"
value={false}
active={!verticalTimeAxis}
onClick={onToggleVerticalTimeAxis}
titleText="Position time on the horizontal table axis"
>
Horizontal
</Radio.Button>
</Radio>
</Form.Element>
<Grid.Column>
<Form.Element label="Time Axis">
<Radio shape={ButtonShape.StretchToFit}>
<Radio.Button
id="graph-time-axis--vertical"
value={true}
active={verticalTimeAxis}
onClick={onToggleVerticalTimeAxis}
titleText="Position time on the vertical table axis"
>
Vertical
</Radio.Button>
<Radio.Button
id="graph-time-axis--horizontal"
value={false}
active={!verticalTimeAxis}
onClick={onToggleVerticalTimeAxis}
titleText="Position time on the horizontal table axis"
>
Horizontal
</Radio.Button>
</Radio>
</Form.Element>
</Grid.Column>
)
export default TimeAxis

View File

@ -0,0 +1,12 @@
/*
Time Format Styles
------------------------------------------------------------------------------
*/
@import 'src/style/modules';
.time-format--helper {
color: $g11-sidewalk;
margin: 0;
font-size: 13px;
}

View File

@ -1,8 +1,17 @@
import React, {PureComponent} from 'react'
// Components
import {Form, Grid, Input, InputType, Dropdown, Columns} from 'src/clockface'
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
import {
ComponentSpacer,
Stack,
Alignment,
Form,
Grid,
Input,
InputType,
Dropdown,
Columns,
} from 'src/clockface'
// Constants
import {DEFAULT_TIME_FORMAT} from 'src/shared/constants'
@ -12,6 +21,9 @@ import {
TIME_FORMAT_TOOLTIP_LINK,
} from 'src/dashboards/constants'
// Styles
import 'src/shared/components/view_options/options/TimeFormat.scss'
// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
@ -36,9 +48,9 @@ class TimeFormat extends PureComponent<Props, State> {
const {format} = this.state
return (
<Grid.Column widthXS={Columns.Twelve}>
<Form.Element label="Time Format" labelAddOn={this.timeFormatTooltip}>
<>
<Grid.Column widthSM={Columns.Six}>
<Form.Element label="Time Format">
<ComponentSpacer stackChildren={Stack.Rows} align={Alignment.Left}>
<Dropdown
selectedID={this.showCustom ? TIME_FORMAT_CUSTOM : format}
onChange={this.handleChooseFormat}
@ -50,18 +62,9 @@ class TimeFormat extends PureComponent<Props, State> {
</Dropdown.Item>
))}
</Dropdown>
{this.showCustom && (
<Input
type={InputType.Text}
spellCheck={false}
placeholder="Enter custom format..."
value={format}
data-test="custom-time-format"
customClass="custom-time-format"
onChange={this.handleChangeFormat}
/>
)}
</>
{this.customTimeInput}
{this.helpBox}
</ComponentSpacer>
</Form.Element>
</Grid.Column>
)
@ -74,21 +77,6 @@ class TimeFormat extends PureComponent<Props, State> {
return !formatOption || customFormat
}
private timeFormatTooltip = (): JSX.Element => {
const tipContent = `For information on formatting, see <br/><a href="#">${TIME_FORMAT_TOOLTIP_LINK}</a>`
if (this.showCustom) {
return (
<a href={TIME_FORMAT_TOOLTIP_LINK} target="_blank">
<QuestionMarkTooltip
tipID="Time Axis Format"
tipContent={tipContent}
/>
</a>
)
}
}
private get onTimeFormatChange() {
return this.props.onTimeFormatChange
}
@ -107,6 +95,39 @@ class TimeFormat extends PureComponent<Props, State> {
this.setState({format, customFormat: false})
}
}
private get customTimeInput(): JSX.Element {
const {format} = this.state
if (this.showCustom) {
return (
<Input
type={InputType.Text}
spellCheck={false}
placeholder="Enter custom format..."
value={format}
data-test="custom-time-format"
customClass="custom-time-format"
onChange={this.handleChangeFormat}
/>
)
}
}
private get helpBox(): JSX.Element {
if (this.showCustom) {
return (
<Form.Box>
<p className="time-format--helper">
For help with formatting time, see{' '}
<a href={TIME_FORMAT_TOOLTIP_LINK} target="_blank">
MomentJS Docs
</a>
</p>
</Form.Box>
)
}
}
}
export default TimeFormat