From a20048ff7f97e57465535de460a5f710e6230c20 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 8 Jan 2019 09:41:58 -0700 Subject: [PATCH] [EuiSuperDatePicker] add showRefreshOnly prop (#1412) * [EuiSuperDatePicker] add showRefreshOnly prop * showRefreshOnly design updates (#4) * rename showRefreshOnly to isAutoRefreshOnly, add description for prop * changelog --- CHANGELOG.md | 1 + .../views/date_picker/date_picker_example.js | 4 + .../views/date_picker/super_date_picker.js | 65 ++++++--- .../date_picker/_date_picker_range.scss | 4 + .../date_picker/date_picker_range.js | 4 + .../super_date_picker.test.js.snap | 2 + .../super_date_picker/pretty_interval.js | 27 ++++ .../super_date_picker/pretty_interval.test.js | 30 ++++ .../__snapshots__/quick_select.test.js.snap | 4 +- .../quick_select_popover.test.js.snap | 135 ++++++++++++++++++ .../quick_select_popover/quick_select.test.js | 2 +- .../quick_select_popover.js | 49 ++++--- .../quick_select_popover.test.js | 50 +++++++ .../super_date_picker/super_date_picker.js | 26 +++- 14 files changed, 364 insertions(+), 39 deletions(-) create mode 100644 src/components/date_picker/super_date_picker/pretty_interval.js create mode 100644 src/components/date_picker/super_date_picker/pretty_interval.test.js create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select_popover.test.js.snap create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index e174eeffec2..42301c7382e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - Added `onBlur` prop to `EuiComboBox` ([#1400](https://github.com/elastic/eui/pull/1400)) - Added `initialFocus` prop typedefs to `EuiModal` and `EuiPopover` ([#1410](https://github.com/elastic/eui/pull/1410)) - Updated `gisApp` icon ([#1413](https://github.com/elastic/eui/pull/1413)) +- Added `isAutoRefreshOnly` prop to `EuiSuperDatePicker` ([#1412](https://github.com/elastic/eui/pull/1412)) ## [`6.2.0`](https://github.com/elastic/eui/tree/v6.2.0) 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 59d6e087a31..7c8da550319 100644 --- a/src-docs/src/views/date_picker/date_picker_example.js +++ b/src-docs/src/views/date_picker/date_picker_example.js @@ -298,6 +298,10 @@ export const DatePickerExample = { to immediately invoke onTimeChange{' '} for all start and end changes.

+

+ Set isAutoRefreshOnly to true to limit the component to only display auto refresh content. + This is useful in cases where there is no time data but auto-refresh configuration is still desired. +

), 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 3c9154d47de..b9bd254b90f 100644 --- a/src-docs/src/views/date_picker/super_date_picker.js +++ b/src-docs/src/views/date_picker/super_date_picker.js @@ -15,6 +15,7 @@ export default class extends Component { recentlyUsedRanges: [], isLoading: false, showUpdateButton: true, + isAutoRefreshOnly: false, start: 'now-30m', end: 'now', } @@ -60,13 +61,55 @@ export default class extends Component { })); } + toggleShowRefreshOnly = () => { + this.setState(prevState => ({ + isAutoRefreshOnly: !prevState.isAutoRefreshOnly, + })); + } + + renderTimeRange = () => { + if (this.state.isAutoRefreshOnly) { + return null; + } + + return ( + + + + + + + + + ); + } + render() { return ( + +   + + @@ -80,24 +123,12 @@ export default class extends Component { onRefreshChange={this.onRefreshChange} recentlyUsedRanges={this.state.recentlyUsedRanges} showUpdateButton={this.state.showUpdateButton} + isAutoRefreshOnly={this.state.isAutoRefreshOnly} /> - - - - - - + + + {this.renderTimeRange()} ); } diff --git a/src/components/date_picker/_date_picker_range.scss b/src/components/date_picker/_date_picker_range.scss index a88f2331894..583562cd5a3 100644 --- a/src/components/date_picker/_date_picker_range.scss +++ b/src/components/date_picker/_date_picker_range.scss @@ -53,3 +53,7 @@ padding-right: $euiFormControlPadding / 2; } } + +.euiDatePickerRange--readOnly { + background: $euiFormBackgroundDisabledColor; +} diff --git a/src/components/date_picker/date_picker_range.js b/src/components/date_picker/date_picker_range.js index 8dc3b5e5fd0..b3e20b5e9a3 100644 --- a/src/components/date_picker/date_picker_range.js +++ b/src/components/date_picker/date_picker_range.js @@ -18,6 +18,7 @@ export const EuiDatePickerRange = ({ iconType, fullWidth, isCustom, + readOnly, ...rest }) => { @@ -25,6 +26,7 @@ export const EuiDatePickerRange = ({ 'euiDatePickerRange', { 'euiDatePickerRange--fullWidth': fullWidth, + 'euiDatePickerRange--readOnly': readOnly, }, className ); @@ -47,11 +49,13 @@ export const EuiDatePickerRange = ({ startControl = cloneElement(startDateControl, { showIcon: false, fullWidth: fullWidth, + readOnly: readOnly, }); endControl = cloneElement(endDateControl, { showIcon: false, fullWidth: fullWidth, + readOnly: readOnly, }); } diff --git a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap index ef2a7b9e8fd..47989b90535 100644 --- a/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap +++ b/src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap @@ -72,6 +72,7 @@ exports[`EuiSuperDatePicker is rendered 1`] = ` } dateFormat="MMM D, YYYY @ HH:mm:ss.SSS" end="now" + isAutoRefreshOnly={false} isPaused={true} recentlyUsedRanges={Array []} refreshInterval={0} @@ -204,6 +205,7 @@ exports[`EuiSuperDatePicker isLoading 1`] = ` } dateFormat="MMM D, YYYY @ HH:mm:ss.SSS" end="now" + isAutoRefreshOnly={false} isPaused={true} recentlyUsedRanges={Array []} refreshInterval={0} diff --git a/src/components/date_picker/super_date_picker/pretty_interval.js b/src/components/date_picker/super_date_picker/pretty_interval.js new file mode 100644 index 00000000000..fe8db73a50a --- /dev/null +++ b/src/components/date_picker/super_date_picker/pretty_interval.js @@ -0,0 +1,27 @@ + +const MS_IN_SECOND = 1000; +const MS_IN_MINUTE = 60 * MS_IN_SECOND; +const MS_IN_HOUR = 60 * MS_IN_MINUTE; +const MS_IN_DAY = 24 * MS_IN_HOUR; + +export function prettyInterval(isPaused, intervalInMs) { + if (isPaused || intervalInMs === 0) { + return 'Off'; + } else if (intervalInMs < MS_IN_MINUTE) { + const intervalInSeconds = Math.round(intervalInMs / MS_IN_SECOND); + const units = intervalInSeconds > 1 ? 'seconds' : 'second'; + return `${intervalInSeconds} ${units}`; + } else if (intervalInMs < MS_IN_HOUR) { + const intervalInMinutes = Math.round(intervalInMs / MS_IN_MINUTE); + const units = intervalInMinutes > 1 ? 'minutes' : 'minute'; + return `${intervalInMinutes} ${units}`; + } else if (intervalInMs < MS_IN_DAY) { + const intervalInHours = Math.round(intervalInMs / MS_IN_HOUR); + const units = intervalInHours > 1 ? 'hours' : 'hour'; + return `${intervalInHours} ${units}`; + } + + const intervalInDays = Math.round(intervalInMs / MS_IN_DAY); + const units = intervalInDays > 1 ? 'days' : 'day'; + return `${intervalInDays} ${units}`; +} diff --git a/src/components/date_picker/super_date_picker/pretty_interval.test.js b/src/components/date_picker/super_date_picker/pretty_interval.test.js new file mode 100644 index 00000000000..1eb067fdb92 --- /dev/null +++ b/src/components/date_picker/super_date_picker/pretty_interval.test.js @@ -0,0 +1,30 @@ + +import { prettyInterval } from './pretty_interval'; + +const IS_NOT_PAUSED = false; +const IS_PAUSED = true; + +test('Off', () => { + expect(prettyInterval(IS_NOT_PAUSED, 0)).toBe('Off'); + expect(prettyInterval(IS_PAUSED, 1000)).toBe('Off'); +}); + +test('seconds', () => { + expect(prettyInterval(IS_NOT_PAUSED, 1000)).toBe('1 second'); + expect(prettyInterval(IS_NOT_PAUSED, 15000)).toBe('15 seconds'); +}); + +test('minutes', () => { + expect(prettyInterval(IS_NOT_PAUSED, 60000)).toBe('1 minute'); + expect(prettyInterval(IS_NOT_PAUSED, 1800000)).toBe('30 minutes'); +}); + +test('hours', () => { + expect(prettyInterval(IS_NOT_PAUSED, 3600000)).toBe('1 hour'); + expect(prettyInterval(IS_NOT_PAUSED, 43200000)).toBe('12 hours'); +}); + +test('days', () => { + expect(prettyInterval(IS_NOT_PAUSED, 86400000)).toBe('1 day'); + expect(prettyInterval(IS_NOT_PAUSED, 86400000 * 2)).toBe('2 days'); +}); diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap index 12d0b8b97f2..37fcd8b38a8 100644 --- a/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap +++ b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`EuiSuperDatePicker is rendered 1`] = ` +exports[`EuiQuickSelect is rendered 1`] = ` `; -exports[`EuiSuperDatePicker prevQuickSelect 1`] = ` +exports[`EuiQuickSelect prevQuickSelect 1`] = ` + + + } + closePopover={[Function]} + hasArrow={true} + id="QuickSelectPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" +> +
+ + + + + + +
+ +`; + +exports[`EuiQuickSelectPopover isAutoRefreshOnly 1`] = ` + + + + } + closePopover={[Function]} + hasArrow={true} + id="QuickSelectPopover" + isOpen={false} + ownFocus={true} + panelPaddingSize="m" +> +
+ +
+
+`; diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js index 49733a1b676..3bceebb3a48 100644 --- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js +++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js @@ -11,7 +11,7 @@ const defaultProps = { start: 'now-15m', end: 'now', }; -describe('EuiSuperDatePicker', () => { +describe('EuiQuickSelect', () => { test('is rendered', () => { const component = shallow( { + if (this.props.isAutoRefreshOnly) { + return null; + } + + return ( + + + + + + ); + } + render() { const quickSelectButton = ( - + ); @@ -78,22 +105,7 @@ export class EuiQuickSelectPopover extends Component { className="euiQuickSelectPopover__content" data-test-subj="superDatePickerQuickMenu" > - - - + {this.renderDateTimeSections()} {}; + +const defaultProps = { + applyTime: noop, + applyRefreshInterval: noop, + start: 'now-15m', + end: 'now', + isPaused: true, + refreshInterval: 0, + commonlyUsedRanges: [ + { start: 'now/d', end: 'now/d', label: 'Today' }, + ], + dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', + recentlyUsedRanges: [ + { start: 'now/d', end: 'now/d', label: 'Today' }, + ], + isAutoRefreshOnly: false +}; + +describe('EuiQuickSelectPopover', () => { + test('is rendered', () => { + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); + }); + + test('isAutoRefreshOnly', () => { + const component = shallow( + + ); + + expect(component) + .toMatchSnapshot(); + }); +}); 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 4fc67449caf..444bc7dcf37 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 @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { commonlyUsedRangeShape, recentlyUsedRangeShape } from './types'; import { prettyDuration, showPrettyDuration } from './pretty_duration'; +import { prettyInterval } from './pretty_interval'; import dateMath from '@elastic/datemath'; @@ -59,6 +60,10 @@ export class EuiSuperDatePicker extends Component { * Set showUpdateButton to false to immediately invoke onTimeChange for all start and end changes. */ showUpdateButton: PropTypes.bool, + /** + * Set isAutoRefreshOnly to true to limit the component to only display auto refresh content. + */ + isAutoRefreshOnly: PropTypes.bool, } static defaultProps = { @@ -79,6 +84,7 @@ export class EuiSuperDatePicker extends Component { dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS', recentlyUsedRanges: [], showUpdateButton: true, + isAutoRefreshOnly: false, } static getDerivedStateFromProps(nextProps, prevState) { @@ -206,6 +212,23 @@ export class EuiSuperDatePicker extends Component { isInvalid, } = this.state; + if (this.props.isAutoRefreshOnly) { + return ( + } + endDateControl={
} + readOnly + > + + {prettyInterval(this.props.isPaused, this.props.refreshInterval)} + + + ); + } + if (this.state.showPrettyDuration) { return ( { - if (!this.props.showUpdateButton) { + if (!this.props.showUpdateButton || this.props.isAutoRefreshOnly) { return; } @@ -309,6 +332,7 @@ export class EuiSuperDatePicker extends Component { commonlyUsedRanges={this.props.commonlyUsedRanges} dateFormat={this.props.dateFormat} recentlyUsedRanges={this.props.recentlyUsedRanges} + isAutoRefreshOnly={this.props.isAutoRefreshOnly} /> ); return (