From 0d7b09b0f6cc333dfdc981cfbd4b14d93bb158b5 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Wed, 5 Dec 2018 15:35:18 +0100 Subject: [PATCH 1/3] add basic button group component, using the the same label style as is remove not used code cleanup --- .../ToggleButtonGroup/ToggleButton.tsx | 33 +++++++++++++ .../ToggleButtonGroup/ToggleButtonGroup.tsx | 46 +++++++++++++++++++ public/sass/_grafana.scss | 1 + .../sass/components/_toggle_button_group.scss | 27 +++++++++++ 4 files changed, 107 insertions(+) create mode 100644 public/app/core/components/ToggleButtonGroup/ToggleButton.tsx create mode 100644 public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx create mode 100644 public/sass/components/_toggle_button_group.scss diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx new file mode 100644 index 00000000000..2fdf324ac44 --- /dev/null +++ b/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx @@ -0,0 +1,33 @@ +import React, { PureComponent } from 'react'; + +interface ToggleButtonProps { + onChange?: (value) => void; + selected?: boolean; + value: any; + classNames?: string; +} +interface ToggleButtonState {} + +export default class ToggleButton extends PureComponent { + static defaultProps = { + classNames: '', + }; + + handleChange = () => { + const { onChange, value } = this.props; + if (onChange) { + onChange(value); + } + }; + + render() { + const { children, selected, classNames } = this.props; + const btnClassName = `btn ${classNames} ${selected ? 'active' : ''}`; + + return ( + + ); + } +} diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx new file mode 100644 index 00000000000..b3063004ebd --- /dev/null +++ b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx @@ -0,0 +1,46 @@ +import React, { PureComponent, ReactElement } from 'react'; + +interface ToggleButtonGroupProps { + onChange: (value) => void; + value?: any; + label?: string; +} + +export default class ToggleButtonGroup extends PureComponent { + getValues() { + const { children } = this.props; + return React.Children.toArray(children).map(c => c['props'].value); + } + + handleToggle(toggleValue) { + const { value, onChange } = this.props; + if (value && value === toggleValue) { + return; + } + onChange(toggleValue); + } + + render() { + const { children, value, label } = this.props; + const values = this.getValues(); + const selectedValue = value || values[0]; + + const childClones = React.Children.map(children, (child: ReactElement) => { + const { value: buttonValue } = child.props; + + return React.cloneElement(child, { + selected: buttonValue === selectedValue, + onChange: this.handleToggle.bind(this), + }); + }); + + return ( +
+
+ {label && } + {childClones} +
+
+ ); + } +} diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index e4c7a9c59e1..b53b69a9c74 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -101,6 +101,7 @@ @import 'components/delete_button'; @import 'components/add_data_source.scss'; @import 'components/page_loader'; +@import 'components/toggle_button_group'; // PAGES @import 'pages/login'; diff --git a/public/sass/components/_toggle_button_group.scss b/public/sass/components/_toggle_button_group.scss new file mode 100644 index 00000000000..5107c18f1a7 --- /dev/null +++ b/public/sass/components/_toggle_button_group.scss @@ -0,0 +1,27 @@ +.toggle-button-group { + display: flex; + + .gf-form-label { + background-color: $input-label-bg; + } + + .btn { + @include buttonBackground($input-bg, $input-bg); + &.active { + background-color: lighten($input-label-bg, 5%); + color: $link-color; + &:hover { + cursor: default; + } + } + } + + &:first-child { + border-radius: 2px 0 0 2px; + margin: 0; + } + &:last-child { + border-radius: 0 2px 2px 0; + margin-left: 0 !important; + } +} From 6f8293af4ea9173e23795b380c935d241cc4fed5 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Wed, 5 Dec 2018 16:27:14 +0100 Subject: [PATCH 2/3] sort of a hacky way to figure if the small variation should be used for the label improve light theme look use new toggle button group in logs stop propagation on click event clean up styles improve support for small when a label is present refactoring - move toggle button to the group file. turn it into a stateless component improve support for light theme rename dedupe to dedup use radius variable --- .../ToggleButtonGroup/ToggleButton.tsx | 33 ----------------- .../ToggleButtonGroup/ToggleButtonGroup.tsx | 36 +++++++++++++++++-- public/app/features/explore/Logs.tsx | 32 +++++------------ .../sass/components/_toggle_button_group.scss | 32 +++++++++++------ 4 files changed, 62 insertions(+), 71 deletions(-) delete mode 100644 public/app/core/components/ToggleButtonGroup/ToggleButton.tsx diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx deleted file mode 100644 index 2fdf324ac44..00000000000 --- a/public/app/core/components/ToggleButtonGroup/ToggleButton.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React, { PureComponent } from 'react'; - -interface ToggleButtonProps { - onChange?: (value) => void; - selected?: boolean; - value: any; - classNames?: string; -} -interface ToggleButtonState {} - -export default class ToggleButton extends PureComponent { - static defaultProps = { - classNames: '', - }; - - handleChange = () => { - const { onChange, value } = this.props; - if (onChange) { - onChange(value); - } - }; - - render() { - const { children, selected, classNames } = this.props; - const btnClassName = `btn ${classNames} ${selected ? 'active' : ''}`; - - return ( - - ); - } -} diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx index b3063004ebd..91b7f1538c9 100644 --- a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx +++ b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx @@ -1,4 +1,4 @@ -import React, { PureComponent, ReactElement } from 'react'; +import React, { SFC, ReactNode, PureComponent, ReactElement } from 'react'; interface ToggleButtonGroupProps { onChange: (value) => void; @@ -9,7 +9,12 @@ interface ToggleButtonGroupProps { export default class ToggleButtonGroup extends PureComponent { getValues() { const { children } = this.props; - return React.Children.toArray(children).map(c => c['props'].value); + return React.Children.toArray(children).map((c: ReactElement) => c.props.value); + } + + smallChildren() { + const { children } = this.props; + return React.Children.toArray(children).every((c: ReactElement) => c.props.className.includes('small')); } handleToggle(toggleValue) { @@ -24,6 +29,7 @@ export default class ToggleButtonGroup extends PureComponent) => { const { value: buttonValue } = child.props; @@ -37,10 +43,34 @@ export default class ToggleButtonGroup extends PureComponent
- {label && } + {label && } {childClones}
); } } + +interface ToggleButtonProps { + onChange?: (value) => void; + selected?: boolean; + value: any; + className?: string; + children: ReactNode; +} + +export const ToggleButton: SFC = ({ children, selected, className = '', value, onChange }) => { + const handleChange = event => { + event.stopPropagation(); + if (onChange) { + onChange(value); + } + }; + + const btnClassName = `btn ${className} ${selected ? 'active' : ''}`; + return ( + + ); +}; diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index 3a584cd5664..f7704cf340a 100644 --- a/public/app/features/explore/Logs.tsx +++ b/public/app/features/explore/Logs.tsx @@ -16,6 +16,7 @@ import { } from 'app/core/logs_model'; import { findHighlightChunksInText } from 'app/core/utils/text'; import { Switch } from 'app/core/components/Switch/Switch'; +import ToggleButtonGroup, { ToggleButton } from 'app/core/components/ToggleButtonGroup/ToggleButtonGroup'; import Graph from './Graph'; import LogLabels from './LogLabels'; @@ -304,30 +305,13 @@ export default class Logs extends PureComponent { - this.onChangeDedup(LogsDedupStrategy.none)} - small - /> - this.onChangeDedup(LogsDedupStrategy.exact)} - small - /> - this.onChangeDedup(LogsDedupStrategy.numbers)} - small - /> - this.onChangeDedup(LogsDedupStrategy.signature)} - small - /> + + {Object.keys(LogsDedupStrategy).map((dedupType, i) => ( + + {dedupType} + + ))} + {hasData && meta && (
diff --git a/public/sass/components/_toggle_button_group.scss b/public/sass/components/_toggle_button_group.scss index 5107c18f1a7..ed701a489a9 100644 --- a/public/sass/components/_toggle_button_group.scss +++ b/public/sass/components/_toggle_button_group.scss @@ -3,25 +3,35 @@ .gf-form-label { background-color: $input-label-bg; + &:first-child { + border-radius: $border-radius 0 0 $border-radius; + margin: 0; + } + &.small { + padding: ($input-padding-y / 2) ($input-padding-x / 2); + font-size: $font-size-xs; + } } .btn { - @include buttonBackground($input-bg, $input-bg); + background-color: $typeahead-selected-bg; + border-radius: 0; + color: $text-color; &.active { - background-color: lighten($input-label-bg, 5%); - color: $link-color; + background-color: $input-bg; &:hover { cursor: default; } } - } - &:first-child { - border-radius: 2px 0 0 2px; - margin: 0; - } - &:last-child { - border-radius: 0 2px 2px 0; - margin-left: 0 !important; + &:first-child { + border-radius: $border-radius 0 0 $border-radius; + margin: 0; + } + + &:last-child { + border-radius: 0 $border-radius $border-radius 0; + margin-left: 0; + } } } From b74c0997738f0b9f11caa57e7e52cd2f40bcc886 Mon Sep 17 00:00:00 2001 From: Erik Sundell Date: Thu, 6 Dec 2018 14:54:26 +0100 Subject: [PATCH 3/3] use render props instead of cloneElement --- .../ToggleButtonGroup/ToggleButtonGroup.tsx | 14 +++-------- public/app/features/explore/Logs.tsx | 25 +++++++++++++------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx index 91b7f1538c9..1e9ae4732df 100644 --- a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx +++ b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx @@ -4,6 +4,7 @@ interface ToggleButtonGroupProps { onChange: (value) => void; value?: any; label?: string; + render: (props) => void; } export default class ToggleButtonGroup extends PureComponent { @@ -26,25 +27,16 @@ export default class ToggleButtonGroup extends PureComponent) => { - const { value: buttonValue } = child.props; - - return React.cloneElement(child, { - selected: buttonValue === selectedValue, - onChange: this.handleToggle.bind(this), - }); - }); - return (
{label && } - {childClones} + {this.props.render({ selectedValue, onChange: this.handleToggle.bind(this) })}
); diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index f7704cf340a..cc4dcbdcc5c 100644 --- a/public/app/features/explore/Logs.tsx +++ b/public/app/features/explore/Logs.tsx @@ -305,13 +305,24 @@ export default class Logs extends PureComponent { - - {Object.keys(LogsDedupStrategy).map((dedupType, i) => ( - - {dedupType} - - ))} - + + Object.keys(LogsDedupStrategy).map((dedupType, i) => ( + + {dedupType} + + )) + } + /> {hasData && meta && (