From 9a2bc96e2a8fbe0ece9cd0b45ddaa0fc53a58b24 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 28 Dec 2018 09:25:39 -0700 Subject: [PATCH 1/5] [EuiSuperDatePicker] add showApplyButton prop --- .../views/date_picker/date_picker_example.js | 17 ++++++ .../views/date_picker/super_date_picker.js | 61 +++++++++++++++---- .../super_date_picker/super_date_picker.js | 14 +++++ 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src-docs/src/views/date_picker/date_picker_example.js b/src-docs/src/views/date_picker/date_picker_example.js index b326f755eaa..a38003d8bd5 100644 --- a/src-docs/src/views/date_picker/date_picker_example.js +++ b/src-docs/src/views/date_picker/date_picker_example.js @@ -281,6 +281,23 @@ export const DatePickerExample = { in either datemath format (e.g.: now, now-15m, now-15m/m) or as absolute date in the format YYYY-MM-DDTHH:mm:ss.sssZ

+

+ onTimeChange will be immediately invoked when{' '} + start and end change from interactions with{' '} + Quick select, Commonly used, or Recently used date ranges{' '} + since these interactions set both start and end in a single event. +

+

+ onTimeChange will not be invoked when + start and end change from interactions with{' '} + Absolute, Relative, and Now tabs.{' '} + onTimeChange will be invoked when the user clicks the Update button. + This gives users the ability to set both start and end{' '} + before triggering onTimeChange. + Set showApplyButton to false{' '} + to immediately invoke onTimeChange{' '} + for all start and end changes. +

), demo: , diff --git a/src-docs/src/views/date_picker/super_date_picker.js b/src-docs/src/views/date_picker/super_date_picker.js index 47c0347522a..b228d687c68 100644 --- a/src-docs/src/views/date_picker/super_date_picker.js +++ b/src-docs/src/views/date_picker/super_date_picker.js @@ -1,8 +1,12 @@ -import React, { Component } from 'react'; +import React, { Component, Fragment } from 'react'; import { EuiSuperDatePicker, + EuiSwitch, + EuiSpacer, + EuiFormRow, + EuiFieldText, } from '../../../../src/components'; export default class extends Component { @@ -10,6 +14,9 @@ export default class extends Component { state = { recentlyUsedRanges: [], isLoading: false, + showApplyButton: true, + start: 'now-30m', + end: 'now', } onTimeChange = ({ start, end }) => { @@ -47,18 +54,50 @@ export default class extends Component { }); } + toggleShowApplyButton = () => { + this.setState(prevState => ({ + showApplyButton: !prevState.showApplyButton, + })); + } + render() { return ( - + + + + + + + + + + + + ); } } diff --git a/src/components/date_picker/super_date_picker/super_date_picker.js b/src/components/date_picker/super_date_picker/super_date_picker.js index 641eb0d8bce..7989dc67d61 100644 --- a/src/components/date_picker/super_date_picker/super_date_picker.js +++ b/src/components/date_picker/super_date_picker/super_date_picker.js @@ -66,6 +66,10 @@ WrappedEuiSuperDatePicker.propTypes = { * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' */ recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape), + /** + * Set showApplyButton to false to immediately invoke onTimeChange for all start and end changes. + */ + showApplyButton: PropTypes.bool, }; WrappedEuiSuperDatePicker.defaultProps = { @@ -85,6 +89,7 @@ WrappedEuiSuperDatePicker.defaultProps = { ], dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', recentlyUsedRanges: [], + showApplyButton: true, }; export class EuiSuperDatePicker extends Component { @@ -149,6 +154,11 @@ export class EuiSuperDatePicker extends Component { }); if (!isInvalid) { + if (!this.props.showApplyButton) { + this.props.onTimeChange({ start, end }); + return; + } + this.showTooltip(); this.tooltipTimeout = setTimeout(() => { this.hideTooltip(); @@ -236,6 +246,10 @@ export class EuiSuperDatePicker extends Component { } renderUpdateButton = () => { + if (!this.props.showApplyButton) { + return; + } + let buttonText = 'Refresh'; if (this.state.hasChanged || this.props.isLoading) { buttonText = this.props.isLoading ? 'Updating' : 'Update'; From 646801b635976f9e7723a6d12da7d362843ff70b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 1 Jan 2019 18:09:48 -0700 Subject: [PATCH 2/5] use getDerivedStateFromProps instead of key so component does not get remounted which causes the popovers to close unexpectedly --- .../date_picker/super_date_picker/index.js | 6 +- .../super_date_picker/super_date_picker.js | 172 +++++++++--------- 2 files changed, 92 insertions(+), 86 deletions(-) diff --git a/src/components/date_picker/super_date_picker/index.js b/src/components/date_picker/super_date_picker/index.js index 183a5d85800..35eb266d870 100644 --- a/src/components/date_picker/super_date_picker/index.js +++ b/src/components/date_picker/super_date_picker/index.js @@ -1,5 +1,3 @@ -import { - WrappedEuiSuperDatePicker, +export { + EuiSuperDatePicker, } from './super_date_picker'; - -export { WrappedEuiSuperDatePicker as EuiSuperDatePicker }; diff --git a/src/components/date_picker/super_date_picker/super_date_picker.js b/src/components/date_picker/super_date_picker/super_date_picker.js index 7989dc67d61..fa7bd347864 100644 --- a/src/components/date_picker/super_date_picker/super_date_picker.js +++ b/src/components/date_picker/super_date_picker/super_date_picker.js @@ -15,84 +15,89 @@ import { EuiButton } from '../../button'; import { EuiFlexGroup, EuiFlexItem } from '../../flex'; import { EuiToolTip } from '../../tool_tip'; -// EuiSuperDatePicker has state that needs to be reset when start or end change. -// Instead of using getDerivedStateFromProps, this wrapper adds a key to the component. -// When a key changes, React will create a new component instance rather than update the current one -// https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#recommendation-fully-uncontrolled-component-with-a-key -export function WrappedEuiSuperDatePicker(props) { - return ( - - ); -} +export class EuiSuperDatePicker extends Component { -WrappedEuiSuperDatePicker.propTypes = { - isLoading: PropTypes.bool, - /** - * String as either datemath (e.g.: now, now-15m, now-15m/m) or - * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' - */ - start: PropTypes.string, - /** - * String as either datemath (e.g.: now, now-15m, now-15m/m) or - * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' - */ - end: PropTypes.string, - /** - * Callback for when the time changes. Called with { start, end } - */ - onTimeChange: PropTypes.func.isRequired, - isPaused: PropTypes.bool, - /** - * Refresh interval in milliseconds - */ - refreshInterval: PropTypes.number, - /** - * Callback for when the refresh interval changes. Called with { isPaused, refreshInterval } - * Supply onRefreshChange to show refresh interval inputs in quick select popover - */ - onRefreshChange: PropTypes.func, - - /** - * 'start' and 'end' must be string as either datemath (e.g.: now, now-15m, now-15m/m) or - * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' - */ - commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape), - dateFormat: PropTypes.string, - /** - * 'start' and 'end' must be string as either datemath (e.g.: now, now-15m, now-15m/m) or - * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' - */ - recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape), - /** - * Set showApplyButton to false to immediately invoke onTimeChange for all start and end changes. - */ - showApplyButton: PropTypes.bool, -}; - -WrappedEuiSuperDatePicker.defaultProps = { - start: 'now-15m', - end: 'now', - isPaused: true, - refreshInterval: 0, - commonlyUsedRanges: [ - { start: 'now/d', end: 'now/d', label: 'Today' }, - { start: 'now-1d/d', end: 'now-1d/d', label: 'Yesterday' }, - { start: 'now/w', end: 'now/w', label: 'This week' }, - { start: 'now/w', end: 'now', label: 'Week to date' }, - { start: 'now/M', end: 'now/M', label: 'This month' }, - { start: 'now/M', end: 'now', label: 'Month to date' }, - { start: 'now/y', end: 'now/y', label: 'This year' }, - { start: 'now/y', end: 'now', label: 'Year to date' }, - ], - dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', - recentlyUsedRanges: [], - showApplyButton: true, -}; + static propTypes = { + isLoading: PropTypes.bool, + /** + * String as either datemath (e.g.: now, now-15m, now-15m/m) or + * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' + */ + start: PropTypes.string, + /** + * String as either datemath (e.g.: now, now-15m, now-15m/m) or + * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' + */ + end: PropTypes.string, + /** + * Callback for when the time changes. Called with { start, end } + */ + onTimeChange: PropTypes.func.isRequired, + isPaused: PropTypes.bool, + /** + * Refresh interval in milliseconds + */ + refreshInterval: PropTypes.number, + /** + * Callback for when the refresh interval changes. Called with { isPaused, refreshInterval } + * Supply onRefreshChange to show refresh interval inputs in quick select popover + */ + onRefreshChange: PropTypes.func, + + /** + * 'start' and 'end' must be string as either datemath (e.g.: now, now-15m, now-15m/m) or + * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' + */ + commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape), + dateFormat: PropTypes.string, + /** + * 'start' and 'end' must be string as either datemath (e.g.: now, now-15m, now-15m/m) or + * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ' + */ + recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape), + /** + * Set showApplyButton to false to immediately invoke onTimeChange for all start and end changes. + */ + showApplyButton: PropTypes.bool, + } -export class EuiSuperDatePicker extends Component { + static defaultProps = { + start: 'now-15m', + end: 'now', + isPaused: true, + refreshInterval: 0, + commonlyUsedRanges: [ + { start: 'now/d', end: 'now/d', label: 'Today' }, + { start: 'now-1d/d', end: 'now-1d/d', label: 'Yesterday' }, + { start: 'now/w', end: 'now/w', label: 'This week' }, + { start: 'now/w', end: 'now', label: 'Week to date' }, + { start: 'now/M', end: 'now/M', label: 'This month' }, + { start: 'now/M', end: 'now', label: 'Month to date' }, + { start: 'now/y', end: 'now/y', label: 'This year' }, + { start: 'now/y', end: 'now', label: 'Year to date' }, + ], + dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', + recentlyUsedRanges: [], + showApplyButton: true, + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.start !== prevState.prevProps.start + || nextProps.end !== prevState.prevProps.end) { + return { + prevProps: { + start: nextProps.start, + end: nextProps.end, + }, + start: nextProps.start, + end: nextProps.end, + isInvalid: false, + hasChanged: false, + }; + } + + return null; + } constructor(props) { super(props); @@ -104,6 +109,10 @@ export class EuiSuperDatePicker extends Component { } = this.props; this.state = { + prevProps: { + start: props.start, + end: props.end, + }, start, end, isInvalid: false, @@ -123,13 +132,13 @@ export class EuiSuperDatePicker extends Component { setTootipRef = node => (this.tooltip = node); showTooltip = () => { - if (!this._isMounted) { + if (!this._isMounted || !this.tooltip) { return; } this.tooltip.showToolTip(); } hideTooltip = () => { - if (!this._isMounted) { + if (!this._isMounted || !this.tooltip) { return; } this.tooltip.hideToolTip(); @@ -179,6 +188,9 @@ export class EuiSuperDatePicker extends Component { } applyQuickTime = ({ start, end }) => { + this.setState({ + showPrettyDuration: showPrettyDuration(start, end, this.props.commonlyUsedRanges), + }); this.props.onTimeChange({ start, end }); } @@ -319,7 +331,3 @@ export class EuiSuperDatePicker extends Component { ); } } - -EuiSuperDatePicker.propTypes = WrappedEuiSuperDatePicker.propTypes; -EuiSuperDatePicker.defaultProps = WrappedEuiSuperDatePicker.defaultProps; - From a611182b932e60b6214f0aede63dc01d389b9895 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 2 Jan 2019 10:57:24 -0700 Subject: [PATCH 3/5] update changelog --- CHANGELOG.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7991ef14db..1b830ef583b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `6.0.1`. +- Added `showApplyButton` prop to `EuiSuperDatePicker` ([#1399](https://github.com/elastic/eui/pull/1399)) -## [`6.0.1`](https://github.com/elastic/eui/tree/v6.0.1) +## [`6.0.1`](https://github.com/elastic/eui/tree/v6.0.1) **Bug fixes** @@ -21,7 +21,6 @@ No public interface changes since `6.0.1`. - Only style anchor tags in `EuiText` that have no class attribute ([#1373](https://github.com/elastic/eui/pull/1373)) - Fixed some EUI services' TS definitions ([#1380](https://github.com/elastic/eui/pull/1380)) -- `EuiColorPicker` align color picker popup with color selector when page is scrolled ([#1397](https://github.com/elastic/eui/pull/1397)) **Breaking changes** From c2626aa664ebc5e67ac31e20ed30ce7367250dff Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 2 Jan 2019 11:50:43 -0700 Subject: [PATCH 4/5] rename showApplyButton to showUpdateButton, move fields in example to under super date picker --- .../views/date_picker/date_picker_example.js | 2 +- .../views/date_picker/super_date_picker.js | 41 ++++++++++--------- .../super_date_picker/super_date_picker.js | 10 ++--- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src-docs/src/views/date_picker/date_picker_example.js b/src-docs/src/views/date_picker/date_picker_example.js index a38003d8bd5..59d6e087a31 100644 --- a/src-docs/src/views/date_picker/date_picker_example.js +++ b/src-docs/src/views/date_picker/date_picker_example.js @@ -294,7 +294,7 @@ export const DatePickerExample = { onTimeChange will be invoked when the user clicks the Update button. This gives users the ability to set both start and end{' '} before triggering onTimeChange. - Set showApplyButton to false{' '} + Set showUpdateButton to false{' '} to immediately invoke onTimeChange{' '} for all start and end changes.

diff --git a/src-docs/src/views/date_picker/super_date_picker.js b/src-docs/src/views/date_picker/super_date_picker.js index b228d687c68..3c9154d47de 100644 --- a/src-docs/src/views/date_picker/super_date_picker.js +++ b/src-docs/src/views/date_picker/super_date_picker.js @@ -14,7 +14,7 @@ export default class extends Component { state = { recentlyUsedRanges: [], isLoading: false, - showApplyButton: true, + showUpdateButton: true, start: 'now-30m', end: 'now', } @@ -56,33 +56,17 @@ export default class extends Component { toggleShowApplyButton = () => { this.setState(prevState => ({ - showApplyButton: !prevState.showApplyButton, + showUpdateButton: !prevState.showUpdateButton, })); } render() { return ( - - - - - - @@ -95,8 +79,25 @@ export default class extends Component { refreshInterval={this.state.refreshInterval} onRefreshChange={this.onRefreshChange} recentlyUsedRanges={this.state.recentlyUsedRanges} - showApplyButton={this.state.showApplyButton} + showUpdateButton={this.state.showUpdateButton} /> + + + + + + + ); } diff --git a/src/components/date_picker/super_date_picker/super_date_picker.js b/src/components/date_picker/super_date_picker/super_date_picker.js index fa7bd347864..4fc67449caf 100644 --- a/src/components/date_picker/super_date_picker/super_date_picker.js +++ b/src/components/date_picker/super_date_picker/super_date_picker.js @@ -56,9 +56,9 @@ export class EuiSuperDatePicker extends Component { */ recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape), /** - * Set showApplyButton to false to immediately invoke onTimeChange for all start and end changes. + * Set showUpdateButton to false to immediately invoke onTimeChange for all start and end changes. */ - showApplyButton: PropTypes.bool, + showUpdateButton: PropTypes.bool, } static defaultProps = { @@ -78,7 +78,7 @@ export class EuiSuperDatePicker extends Component { ], dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', recentlyUsedRanges: [], - showApplyButton: true, + showUpdateButton: true, } static getDerivedStateFromProps(nextProps, prevState) { @@ -163,7 +163,7 @@ export class EuiSuperDatePicker extends Component { }); if (!isInvalid) { - if (!this.props.showApplyButton) { + if (!this.props.showUpdateButton) { this.props.onTimeChange({ start, end }); return; } @@ -258,7 +258,7 @@ export class EuiSuperDatePicker extends Component { } renderUpdateButton = () => { - if (!this.props.showApplyButton) { + if (!this.props.showUpdateButton) { return; } From 4073859f855d4cac5751f684fbe5d3efc8dfc202 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 2 Jan 2019 13:45:34 -0700 Subject: [PATCH 5/5] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b830ef583b..40a01830db2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -- Added `showApplyButton` prop to `EuiSuperDatePicker` ([#1399](https://github.com/elastic/eui/pull/1399)) +- Added `showUpdateButton` prop to `EuiSuperDatePicker` ([#1399](https://github.com/elastic/eui/pull/1399)) ## [`6.0.1`](https://github.com/elastic/eui/tree/v6.0.1)