From b8bc8caf4ee740bc498b39f76d89b3ca836ff621 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Tue, 4 Dec 2018 10:59:10 -0700
Subject: [PATCH 01/37] super date picker component
---
.../views/date_picker/date_picker_example.js | 19 ++
.../views/date_picker/super_date_picker.js | 33 ++
src/components/date_picker/_index.scss | 1 +
src/components/date_picker/index.js | 4 +
.../super_date_picker/_super_date_picker.scss | 95 ++++++
.../super_date_picker/absolute_form.js | 89 +++++
.../super_date_picker/date_button.js | 165 +++++++++
.../super_date_picker/quick_select_popover.js | 319 ++++++++++++++++++
.../super_date_picker/super_date_picker.js | 194 +++++++++++
src/components/index.js | 1 +
10 files changed, 920 insertions(+)
create mode 100644 src-docs/src/views/date_picker/super_date_picker.js
create mode 100644 src/components/date_picker/super_date_picker/_super_date_picker.scss
create mode 100644 src/components/date_picker/super_date_picker/absolute_form.js
create mode 100644 src/components/date_picker/super_date_picker/date_button.js
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover.js
create mode 100644 src/components/date_picker/super_date_picker/super_date_picker.js
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 38dcff6a3f9..7235470eee8 100644
--- a/src-docs/src/views/date_picker/date_picker_example.js
+++ b/src-docs/src/views/date_picker/date_picker_example.js
@@ -58,6 +58,10 @@ import Utc from './utc';
const utcSource = require('!!raw-loader!./utc');
const utcHtml = renderToHtml(Utc);
+import SuperDatePicker from './super_date_picker';
+const superDatePickerSource = require('!!raw-loader!./super_date_picker');
+const superDatePickerHtml = renderToHtml(SuperDatePicker);
+
import GlobalDatePicker from './global_date_picker';
const globalDatePickerSource = require('!!raw-loader!./global_date_picker');
const globalDatePickerHtml = renderToHtml(GlobalDatePicker);
@@ -265,6 +269,21 @@ export const DatePickerExample = {
),
demo: ,
+ }, {
+ title: 'Super date picker',
+ source: [{
+ type: GuideSectionTypes.JS,
+ code: superDatePickerSource,
+ }, {
+ type: GuideSectionTypes.HTML,
+ code: superDatePickerHtml,
+ }],
+ text: (
+
+ Super date picker
+
+ ),
+ demo: ,
}, {
title: 'Global date picker',
source: [{
diff --git a/src-docs/src/views/date_picker/super_date_picker.js b/src-docs/src/views/date_picker/super_date_picker.js
new file mode 100644
index 00000000000..5352288f53f
--- /dev/null
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -0,0 +1,33 @@
+
+import React, { Component } from 'react';
+
+import {
+ EuiSuperDatePicker,
+} from '../../../../src/components';
+
+export default class extends Component {
+
+ state = {}
+
+ onTimeChange = ({ from, to }) => {
+ this.setState({ from, to });
+ }
+
+ onRefreshChange = ({ isPaused, refreshInterval }) => {
+ this.setState({ isPaused, refreshInterval });
+ }
+
+ render() {
+
+ return (
+
+ );
+ }
+}
diff --git a/src/components/date_picker/_index.scss b/src/components/date_picker/_index.scss
index 65219322767..cc5927780e8 100644
--- a/src/components/date_picker/_index.scss
+++ b/src/components/date_picker/_index.scss
@@ -1,3 +1,4 @@
// Uses some form mixins
@import 'date_picker';
@import 'date_picker_range';
+@import 'super_date_picker/super_date_picker';
diff --git a/src/components/date_picker/index.js b/src/components/date_picker/index.js
index eb720402eec..c7087098446 100644
--- a/src/components/date_picker/index.js
+++ b/src/components/date_picker/index.js
@@ -5,3 +5,7 @@ export {
export {
EuiDatePickerRange,
} from './date_picker_range';
+
+export {
+ EuiSuperDatePicker,
+} from './super_date_picker/super_date_picker';
diff --git a/src/components/date_picker/super_date_picker/_super_date_picker.scss b/src/components/date_picker/super_date_picker/_super_date_picker.scss
new file mode 100644
index 00000000000..b8b48560225
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/_super_date_picker.scss
@@ -0,0 +1,95 @@
+// sass-lint:disable no-important
+.euiSuperDatePicker__quickSelectButton {
+ // Override prepend border since button already lives inside another prepend
+ border-right: none !important;
+
+ .euiSuperDatePicker__quickSelectButtonText {
+ // Override specificity from universal and sibiling selectors
+ margin-right: $euiSizeXS !important;
+ }
+}
+
+.euiSuperDatePicker.euiFormControlLayout {
+ max-width: 480px;
+
+ > .euiFormControlLayout__childrenWrapper {
+ flex: 1 1 100%;
+ overflow: hidden;
+
+ > .euiDatePickerRange {
+ max-width: none;
+ width: auto;
+
+ // sass-lint:disable nesting-depth
+ .euiPopover__anchor {
+ display: block;
+ }
+ }
+ }
+}
+
+.euiSuperDatePicker__dateButton {
+ @include euiFormControlText;
+ display: block;
+ width: 100%;
+ padding: 0 $euiSizeS;
+ line-height: $euiFormControlHeight - 2px;
+ height: $euiFormControlHeight - 2px;
+ word-break: break-all;
+ transition: background $euiAnimSpeedFast ease-in;
+
+ $backgroundColor: tintOrShade($euiColorSuccess, 90%, 70%);
+ $textColor: makeHighContrastColor($euiColorSuccess, $backgroundColor);
+
+ &-isSelected,
+ &-needsUpdating,
+ &:hover,
+ &:focus {
+ background-color: $backgroundColor;
+ }
+
+ &-needsUpdating {
+ color: $textColor;
+ }
+
+ &-isInvalid {
+ $backgroundColor: tintOrShade($euiColorDanger, 90%, 70%);
+ $textColor: makeHighContrastColor($euiColorDanger, $backgroundColor);
+ background-color: $backgroundColor;
+ color: $textColor;
+ }
+
+ .euiFormControlLayout__prepend {
+ border: none;
+ }
+}
+
+.euiSuperDatePicker__dateButton--start {
+ text-align: right;
+}
+
+.euiSuperDatePicker__dateButton--end {
+ text-align: left;
+}
+
+.euiSuperDatePicker__updateButton {
+ // Just wide enough for all 3 states
+ min-width: $euiButtonMinWidth + ($euiSizeXS * 1.5);
+}
+
+.euiSuperDatePicker__popoverSection {
+ @include euiScrollBar;
+ max-height: $euiSizeM * 11;
+ overflow: hidden;
+ overflow-y: auto;
+}
+
+@include euiBreakpoint('xs', 's') {
+ .euiSuperDatePicker__updateButton {
+ min-width: 0;
+
+ .euiSuperDatePicker__updateButtonText {
+ display: none;
+ }
+ }
+}
diff --git a/src/components/date_picker/super_date_picker/absolute_form.js b/src/components/date_picker/super_date_picker/absolute_form.js
new file mode 100644
index 00000000000..90497289357
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/absolute_form.js
@@ -0,0 +1,89 @@
+
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+
+import moment from 'moment';
+
+import dateMath from '@kbn/datemath';
+
+import {
+ EuiDatePicker,
+ EuiFieldText,
+ EuiFormRow,
+} from '@elastic/eui';
+
+const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
+
+const toMoment = (value, roundUp) => {
+ const valueAsMoment = dateMath.parse(value, { roundUp });
+ return {
+ value: valueAsMoment,
+ textInputValue: valueAsMoment.format(INPUT_DATE_FORMAT)
+ };
+};
+
+export class AbsoluteForm extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ ...toMoment(this.props.value, this.props.roundUp),
+ isTextInvalid: false,
+ };
+ }
+
+ static getDerivedStateFromProps = (nextProps) => {
+ return {
+ ...toMoment(nextProps.value, nextProps.roundUp),
+ isTextInvalid: false,
+ };
+ }
+
+ handleChange = (date) => {
+ this.props.onChange(date.toISOString());
+ }
+
+ handleTextChange = (evt) => {
+ const date = moment(evt.target.value, INPUT_DATE_FORMAT, true);
+ if (date.isValid()) {
+ this.props.onChange(date.toISOString());
+ }
+
+ this.setState({
+ textInputValue: evt.target.value,
+ isTextInvalid: !date.isValid()
+ });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+AbsoluteForm.propTypes = {
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ roundUp: PropTypes.bool.isRequired,
+};
diff --git a/src/components/date_picker/super_date_picker/date_button.js b/src/components/date_picker/super_date_picker/date_button.js
new file mode 100644
index 00000000000..0c8d7aded15
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_button.js
@@ -0,0 +1,165 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import chrome from 'ui/chrome';
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import { AbsoluteForm } from './absolute_form';
+import { RelativeForm } from './relative_form';
+
+import {
+ EuiPopover,
+ EuiTabbedContent,
+ EuiText,
+} from '@elastic/eui';
+
+import { formatTimeString } from '../pretty_duration';
+import {
+ getTimeMode,
+ TIME_MODES,
+ toAbsoluteString,
+ toRelativeString,
+} from '../lib/time_modes';
+
+export class DateButton extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ isOpen: false,
+ };
+ }
+
+ onTabClick = (selectedTab) => {
+ const {
+ value,
+ roundUp
+ } = this.props;
+
+ switch(selectedTab.id) {
+ case TIME_MODES.ABSOLUTE:
+ this.props.onChange(toAbsoluteString(value, roundUp));
+ break;
+ case TIME_MODES.RELATIVE:
+ this.props.onChange(toRelativeString(value));
+ break;
+ case TIME_MODES.NOW:
+ this.props.onChange('now');
+ break;
+ }
+ };
+
+ closePopover = () => {
+ this.setState({ isOpen: false });
+ }
+
+ togglePopover = () => {
+ this.setState((prevState) => ({
+ isOpen: !prevState.isOpen,
+ }));
+ }
+
+ renderTabs = () => {
+ return [
+ {
+ id: TIME_MODES.ABSOLUTE,
+ name: 'Absolute',
+ content: (
+
+ ),
+ },
+ {
+ id: TIME_MODES.RELATIVE,
+ name: 'Relative',
+ content: (
+
+ ),
+ },
+ {
+ id: TIME_MODES.NOW,
+ name: 'Now',
+ content: (
+
+ ),
+ }
+ ];
+ }
+
+ render() {
+ const input = (
+
+ {formatTimeString(this.props.value, chrome.getUiSettingsClient().get('dateFormat'))}
+
+ );
+
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+DateButton.propTypes = {
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ roundUp: PropTypes.bool,
+};
+
+DateButton.defaultProps = {
+ roundUp: false,
+};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover.js
new file mode 100644
index 00000000000..ed4926d7dc3
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover.js
@@ -0,0 +1,319 @@
+import _ from 'lodash';
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+
+/*import { timeUnits } from '../time_units';
+import { timeHistory } from '../../timefilter/time_history';
+import { prettyDuration } from '../pretty_duration';
+import { RefreshIntervalForm } from './refresh_interval_form';*/
+
+import {
+ EuiButtonEmpty,
+ EuiButton,
+ EuiButtonIcon,
+} from '../../button';
+
+import {
+ EuiFlexGrid,
+ EuiFlexGroup,
+ EuiFlexItem,
+} from '../../flex';
+
+import {
+ EuiIcon,
+} from '../../icon';
+
+import {
+ EuiPopover,
+} from '../../popover';
+
+import {
+ EuiTitle,
+} from '../../title';
+
+import {
+ EuiSpacer,
+} from '../../spacer';
+
+import {
+ EuiFormRow,
+ EuiSelect,
+ EuiFieldNumber,
+} from '../../form';
+
+import {
+ EuiText,
+} from '../../text';
+
+import {
+ EuiHorizontalRule,
+} from '../../horizontal_rule';
+
+import {
+ EuiLink,
+} from '../../link';
+
+const LAST = 'last';
+const NEXT = 'next';
+
+const timeTenseOptions = [
+ { value: LAST, text: 'Last' },
+ { value: NEXT, text: 'Next' },
+];
+/*const timeUnitsOptions = Object.keys(timeUnits).map(key => {
+ return { value: key, text: `${timeUnits[key]}s` };
+});*/
+
+export class QuickSelectPopover extends Component {
+
+ state = {
+ isOpen: false,
+ timeTense: LAST,
+ timeValue: 15,
+ timeUnits: 'm',
+ }
+
+ closePopover = () => {
+ this.setState({ isOpen: false });
+ }
+
+ togglePopover = () => {
+ this.setState((prevState) => ({
+ isOpen: !prevState.isOpen
+ }));
+ }
+
+ onTimeTenseChange = (evt) => {
+ this.setState({
+ timeTense: evt.target.value,
+ });
+ }
+
+ onTimeValueChange = (evt) => {
+ const sanitizedValue = parseInt(evt.target.value, 10);
+ this.setState({
+ timeValue: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ });
+ }
+
+ onTimeUnitsChange = (evt) => {
+ this.setState({
+ timeUnits: evt.target.value,
+ });
+ }
+
+ applyQuickSelect = () => {
+ const {
+ timeTense,
+ timeValue,
+ timeUnits,
+ } = this.state;
+
+ if (timeTense === NEXT) {
+ this.setTime({
+ from: 'now',
+ to: `now+${timeValue}${timeUnits}`
+ });
+ return;
+ }
+
+ this.setTime({
+ from: `now-${timeValue}${timeUnits}`,
+ to: 'now'
+ });
+ }
+
+ setTime = ({ from, to }) => {
+ this.props.setTime({
+ from: from,
+ to: to
+ });
+ this.closePopover();
+ }
+
+ applyTime = ({ from, to }) => {
+ this.props.applyTime({
+ from: from,
+ to: to
+ });
+ this.closePopover();
+ }
+
+ renderTimeNavigation = () => {
+ return (
+
+
+
+
+ );
+ }
+
+ renderQuickSelect = () => {
+ return (
+
+ Quick select
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply
+
+
+
+
+
+ );
+ }
+
+ renderCommonlyUsed = () => {
+ const commonlyUsed = chrome.getUiSettingsClient().get('timepicker:quickRanges');
+ const sections = _.groupBy(commonlyUsed, 'section');
+
+ const renderSectionItems = (section) => {
+ return section.map(({ from, to, display }) => {
+ const applyTime = () => {
+ this.applyTime({ from, to });
+ };
+ return (
+
+ {display}
+
+ );
+ });
+ };
+
+ return (
+
+ Commonly used
+
+
+ {Object.keys(sections).map((key, index) => {
+ const isLastSection = Object.keys(sections).length - 1 === index;
+ const sectionSpacer = isLastSection
+ ? undefined
+ : ( );
+ return (
+
+
+ {renderSectionItems(sections[key])}
+
+ {sectionSpacer}
+
+ );
+ })}
+
+
+ );
+ }
+
+ renderRecentlyUsed = () => {
+ const links = timeHistory.get().map(({ from, to }) => {
+ const applyTime = () => {
+ this.applyTime({ from, to });
+ };
+ const display = prettyDuration(from, to, (...args) => chrome.getUiSettingsClient().get(...args));
+ return (
+
+ {display}
+
+ );
+ });
+
+ return (
+
+ Recently used date ranges
+
+
+
+ {links}
+
+
+
+ );
+ }
+
+ render() {
+ const quickSelectButton = (
+
+
+
+ );
+
+ return (
+
+
+ Quick select
+
+
+ );
+ }
+}
+
+QuickSelectPopover.propTypes = {
+ applyTime: PropTypes.func.isRequired,
+ setTime: PropTypes.func.isRequired,
+ setRefresh: PropTypes.func.isRequired,
+ isPaused: PropTypes.bool.isRequired,
+ refreshInterval: PropTypes.number,
+};
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
new file mode 100644
index 00000000000..6dd22207426
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/super_date_picker.js
@@ -0,0 +1,194 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import moment from 'moment';
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+
+/*import dateMath from '@kbn/datemath';*/
+
+import { QuickSelectPopover } from './quick_select_popover';
+//import { TimeInput } from './time_input';
+
+import {
+ EuiFormControlLayout,
+} from '../../form';
+
+import {
+ EuiText,
+} from '../../text';
+
+import {
+ EuiButton,
+} from '../../button';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+} from '../../flex';
+
+/*import { prettyDuration } from '../pretty_duration';
+import { timeNavigation } from '../time_navigation';
+import { calculateBounds } from 'ui/timefilter/get_time';*/
+
+export class EuiSuperDatePicker extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ from: this.props.from,
+ to: this.props.to,
+ isInvalid: false,
+ hasChanged: false,
+ isEditMode: false,
+ };
+ }
+
+ static getDerivedStateFromProps = (nextProps) => {
+ return {
+ from: nextProps.from,
+ to: nextProps.to,
+ isInvalid: false,
+ hasChanged: false,
+ isEditMode: false,
+ };
+ }
+
+ setTime = ({ from, to }) => {
+ // TODO validation once dateMath is an npm artifact
+ /*const fromMoment = dateMath.parse(from);
+ const toMoment = dateMath.parse(to, { roundUp: true });
+ const isInvalid = fromMoment.isAfter(toMoment);
+ if (isInvalid) {
+ this.lastToast = toastNotifications.addDanger({
+ title: `Invalid time range`,
+ text: `From must occur before To`,
+ });
+ }*/
+
+ this.setState({
+ from,
+ to,
+ isInvalid: false,
+ hasChanged: true,
+ });
+ }
+
+ setFrom = (from) => {
+ this.setTime({ from, to: this.state.to });
+ }
+
+ setTo = (to) => {
+ this.setTime({ from: this.state.from, to });
+ }
+
+ /*getBounds = () => {
+ return calculateBounds({ from: this.state.from, to: this.state.to });
+ }
+
+ stepForward = () => {
+ this.setTime(timeNavigation.stepForward(this.getBounds()));
+ }
+
+ stepBackward = () => {
+ this.setTime(timeNavigation.stepBackward(this.getBounds()));
+ }*/
+
+ applyTime = () => {
+ this.props.onTimeChange(this.state.from, this.state.to);
+ }
+
+ applyQuickTime = ({ from, to }) => {
+ this.props.onTimeChange(from, to);
+ }
+
+ renderDateRange = () => {
+ return;
+ }
+
+ renderUpdateButton = () => {
+ const color = this.state.hasChanged ? 'secondary' : 'primary';
+ const icon = this.state.hasChanged ? 'kqlFunction' : 'refresh';
+ let text = this.state.hasChanged ? 'Update' : 'Refresh';
+
+ return (
+
+ {text}
+
+ );
+ }
+
+ render() {
+ const quickSelect = (
+
+ );
+ return (
+
+
+
+
+ {this.renderDateRange()}
+
+
+
+
+ {this.renderUpdateButton()}
+
+
+
+ );
+ }
+}
+
+EuiSuperDatePicker.propTypes = {
+ from: PropTypes.string,
+ to: PropTypes.string,
+ onTimeChange: PropTypes.func.isRequired,
+ isPaused: PropTypes.bool,
+ refreshInterval: PropTypes.number,
+ onRefreshChange: PropTypes.func.isRequired,
+};
+
+EuiSuperDatePicker.defaultProps = {
+ from: 'now-15m',
+ to: 'now',
+ isPaused: true,
+ refreshInterval: 0,
+};
+
diff --git a/src/components/index.js b/src/components/index.js
index c09b340e33d..c724b6ced32 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -72,6 +72,7 @@ export {
export {
EuiDatePicker,
EuiDatePickerRange,
+ EuiSuperDatePicker,
} from './date_picker';
export {
From fcf1d8ffb71c91396b3bf52a24b5f4a0310ab48b Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Tue, 4 Dec 2018 12:10:07 -0700
Subject: [PATCH 02/37] quick select
---
package.json | 1 +
.../quick_select_popover/quick_select.js | 141 +++++++++++++++++
.../quick_select_popover.js | 145 ++----------------
.../super_date_picker/super_date_picker.js | 18 +--
.../super_date_picker/time_units.js | 11 ++
yarn.lock | 15 +-
6 files changed, 188 insertions(+), 143 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
rename src/components/date_picker/super_date_picker/{ => quick_select_popover}/quick_select_popover.js (58%)
create mode 100644 src/components/date_picker/super_date_picker/time_units.js
diff --git a/package.json b/package.json
index 6d28ba8a366..c6f62723c1c 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"url": "https://github.com/elastic/eui.git"
},
"dependencies": {
+ "@elastic/datemath": "5.0.0",
"classnames": "^2.2.5",
"core-js": "^2.5.1",
"focus-trap-react": "^3.0.4",
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
new file mode 100644
index 00000000000..4f80f2ca6f1
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -0,0 +1,141 @@
+
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+
+import { EuiButton, EuiButtonIcon } from '../../../button';
+import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
+import { EuiTitle } from '../../../title';
+import { EuiSpacer } from '../../../spacer';
+import { EuiFormRow, EuiSelect, EuiFieldNumber } from '../../../form';
+import { EuiToolTip } from '../../../tool_tip';
+
+import { timeUnits } from '../time_units';
+
+const LAST = 'last';
+const NEXT = 'next';
+
+const timeTenseOptions = [
+ { value: LAST, text: 'Last' },
+ { value: NEXT, text: 'Next' },
+];
+const timeUnitsOptions = Object.keys(timeUnits).map(key => {
+ return { value: key, text: `${timeUnits[key]}s` };
+});
+
+export class QuickSelect extends Component {
+ state = {
+ timeTense: LAST,
+ timeValue: 15,
+ timeUnits: 'm',
+ }
+
+ onTimeTenseChange = (evt) => {
+ this.setState({
+ timeTense: evt.target.value,
+ });
+ }
+
+ onTimeValueChange = (evt) => {
+ const sanitizedValue = parseInt(evt.target.value, 10);
+ this.setState({
+ timeValue: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ });
+ }
+
+ onTimeUnitsChange = (evt) => {
+ this.setState({
+ timeUnits: evt.target.value,
+ });
+ }
+
+ applyQuickSelect = () => {
+ const {
+ timeTense,
+ timeValue,
+ timeUnits,
+ } = this.state;
+
+ if (timeTense === NEXT) {
+ this.props.applyTime({
+ from: 'now',
+ to: `now+${timeValue}${timeUnits}`
+ });
+ return;
+ }
+
+ this.props.applyTime({
+ from: `now-${timeValue}${timeUnits}`,
+ to: 'now'
+ });
+ }
+
+ render() {
+ return (
+
+
+
+ Quick select
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply
+
+
+
+
+
+ );
+ }
+}
+
+QuickSelect.propTypes = {
+ applyTime: PropTypes.func.isRequired,
+};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
similarity index 58%
rename from src/components/date_picker/super_date_picker/quick_select_popover.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index ed4926d7dc3..6fa7142dfe0 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -2,7 +2,7 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
-/*import { timeUnits } from '../time_units';
+/*
import { timeHistory } from '../../timefilter/time_history';
import { prettyDuration } from '../pretty_duration';
import { RefreshIntervalForm } from './refresh_interval_form';*/
@@ -11,66 +11,48 @@ import {
EuiButtonEmpty,
EuiButton,
EuiButtonIcon,
-} from '../../button';
+} from '../../../button';
import {
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
-} from '../../flex';
+} from '../../../flex';
import {
EuiIcon,
-} from '../../icon';
+} from '../../../icon';
import {
EuiPopover,
-} from '../../popover';
+} from '../../../popover';
import {
EuiTitle,
-} from '../../title';
+} from '../../../title';
import {
EuiSpacer,
-} from '../../spacer';
-
-import {
- EuiFormRow,
- EuiSelect,
- EuiFieldNumber,
-} from '../../form';
+} from '../../../spacer';
import {
EuiText,
-} from '../../text';
+} from '../../../text';
import {
EuiHorizontalRule,
-} from '../../horizontal_rule';
+} from '../../../horizontal_rule';
import {
EuiLink,
-} from '../../link';
-
-const LAST = 'last';
-const NEXT = 'next';
+} from '../../../link';
-const timeTenseOptions = [
- { value: LAST, text: 'Last' },
- { value: NEXT, text: 'Next' },
-];
-/*const timeUnitsOptions = Object.keys(timeUnits).map(key => {
- return { value: key, text: `${timeUnits[key]}s` };
-});*/
+import { QuickSelect } from './quick_select';
export class QuickSelectPopover extends Component {
state = {
isOpen: false,
- timeTense: LAST,
- timeValue: 15,
- timeUnits: 'm',
}
closePopover = () => {
@@ -83,54 +65,6 @@ export class QuickSelectPopover extends Component {
}));
}
- onTimeTenseChange = (evt) => {
- this.setState({
- timeTense: evt.target.value,
- });
- }
-
- onTimeValueChange = (evt) => {
- const sanitizedValue = parseInt(evt.target.value, 10);
- this.setState({
- timeValue: isNaN(sanitizedValue) ? '' : sanitizedValue,
- });
- }
-
- onTimeUnitsChange = (evt) => {
- this.setState({
- timeUnits: evt.target.value,
- });
- }
-
- applyQuickSelect = () => {
- const {
- timeTense,
- timeValue,
- timeUnits,
- } = this.state;
-
- if (timeTense === NEXT) {
- this.setTime({
- from: 'now',
- to: `now+${timeValue}${timeUnits}`
- });
- return;
- }
-
- this.setTime({
- from: `now-${timeValue}${timeUnits}`,
- to: 'now'
- });
- }
-
- setTime = ({ from, to }) => {
- this.props.setTime({
- from: from,
- to: to
- });
- this.closePopover();
- }
-
applyTime = ({ from, to }) => {
this.props.applyTime({
from: from,
@@ -156,57 +90,6 @@ export class QuickSelectPopover extends Component {
);
}
- renderQuickSelect = () => {
- return (
-
- Quick select
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Apply
-
-
-
-
-
- );
- }
-
renderCommonlyUsed = () => {
const commonlyUsed = chrome.getUiSettingsClient().get('timepicker:quickRanges');
const sections = _.groupBy(commonlyUsed, 'section');
@@ -303,7 +186,10 @@ export class QuickSelectPopover extends Component {
ownFocus
>
- Quick select
+
+
);
@@ -312,7 +198,6 @@ export class QuickSelectPopover extends Component {
QuickSelectPopover.propTypes = {
applyTime: PropTypes.func.isRequired,
- setTime: PropTypes.func.isRequired,
setRefresh: PropTypes.func.isRequired,
isPaused: PropTypes.bool.isRequired,
refreshInterval: PropTypes.number,
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 6dd22207426..ed261cf4cc5 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
@@ -21,9 +21,9 @@ import moment from 'moment';
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
-/*import dateMath from '@kbn/datemath';*/
+import dateMath from '@elastic/datemath';
-import { QuickSelectPopover } from './quick_select_popover';
+import { QuickSelectPopover } from './quick_select_popover/quick_select_popover';
//import { TimeInput } from './time_input';
import {
@@ -66,27 +66,22 @@ export class EuiSuperDatePicker extends Component {
from: nextProps.from,
to: nextProps.to,
isInvalid: false,
+ errorMessage: undefined,
hasChanged: false,
isEditMode: false,
};
}
setTime = ({ from, to }) => {
- // TODO validation once dateMath is an npm artifact
- /*const fromMoment = dateMath.parse(from);
+ const fromMoment = dateMath.parse(from);
const toMoment = dateMath.parse(to, { roundUp: true });
const isInvalid = fromMoment.isAfter(toMoment);
- if (isInvalid) {
- this.lastToast = toastNotifications.addDanger({
- title: `Invalid time range`,
- text: `From must occur before To`,
- });
- }*/
this.setState({
from,
to,
isInvalid: false,
+ errorMessage: isInvalid ? 'Invalid time range, "from" must occur before "to"' : undefined,
hasChanged: true,
});
}
@@ -146,8 +141,7 @@ export class EuiSuperDatePicker extends Component {
render() {
const quickSelect = (
Date: Tue, 4 Dec 2018 12:39:06 -0700
Subject: [PATCH 03/37] commonly used ranges
---
.../quick_select_popover/commonly_used.js | 53 +++++++++++++++++++
.../quick_select_popover.js | 50 ++---------------
.../date_picker/super_date_picker/types.js | 7 +++
3 files changed, 65 insertions(+), 45 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
create mode 100644 src/components/date_picker/super_date_picker/types.js
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
new file mode 100644
index 00000000000..b5c0f93364c
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
@@ -0,0 +1,53 @@
+
+import PropTypes from 'prop-types';
+import React, { Fragment } from 'react';
+import { commonlyUsedRange } from '../types';
+
+import { EuiFlexGrid, EuiFlexItem } from '../../../flex';
+import { EuiTitle } from '../../../title';
+import { EuiSpacer } from '../../../spacer';
+import { EuiLink } from '../../../link';
+import { EuiText } from '../../../text';
+
+export function CommonlyUsed({ commonlyUsedRanges, applyTime }) {
+ const links = commonlyUsedRanges.map(({ from, to, label }) => {
+ const applyCommonlyUsedTime = () => {
+ applyTime({ from, to });
+ };
+ return (
+
+ {label}
+
+ );
+ });
+
+ return (
+
+ Commonly used
+
+
+
+ {links}
+
+
+
+ );
+}
+
+CommonlyUsed.propTypes = {
+ commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRange),
+ applyTime: PropTypes.func.isRequired,
+};
+
+CommonlyUsed.defaultProps = {
+ commonlyUsedRanges: [
+ { from: 'now/d', to: 'now/d', label: 'Today' },
+ { from: 'now-1d/d', to: 'now-1d/d', label: 'Yesterday' },
+ { from: 'now/w', to: 'now/w', label: 'This week' },
+ { from: 'now/w', to: 'now', label: 'Week to date' },
+ { from: 'now/M', to: 'now/M', label: 'This month' },
+ { from: 'now/M', to: 'now', label: 'Month to date' },
+ { from: 'now/y', to: 'now/y', label: 'This year' },
+ { from: 'now/y', to: 'now', label: 'Year to date' },
+ ]
+};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 6fa7142dfe0..8e37bf3ea39 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -48,6 +48,7 @@ import {
} from '../../../link';
import { QuickSelect } from './quick_select';
+import { CommonlyUsed } from './commonly_used';
export class QuickSelectPopover extends Component {
@@ -90,51 +91,6 @@ export class QuickSelectPopover extends Component {
);
}
- renderCommonlyUsed = () => {
- const commonlyUsed = chrome.getUiSettingsClient().get('timepicker:quickRanges');
- const sections = _.groupBy(commonlyUsed, 'section');
-
- const renderSectionItems = (section) => {
- return section.map(({ from, to, display }) => {
- const applyTime = () => {
- this.applyTime({ from, to });
- };
- return (
-
- {display}
-
- );
- });
- };
-
- return (
-
- Commonly used
-
-
- {Object.keys(sections).map((key, index) => {
- const isLastSection = Object.keys(sections).length - 1 === index;
- const sectionSpacer = isLastSection
- ? undefined
- : ( );
- return (
-
-
- {renderSectionItems(sections[key])}
-
- {sectionSpacer}
-
- );
- })}
-
-
- );
- }
-
renderRecentlyUsed = () => {
const links = timeHistory.get().map(({ from, to }) => {
const applyTime = () => {
@@ -190,6 +146,10 @@ export class QuickSelectPopover extends Component {
applyTime={this.applyTime}
/>
+
+
);
diff --git a/src/components/date_picker/super_date_picker/types.js b/src/components/date_picker/super_date_picker/types.js
new file mode 100644
index 00000000000..22a38b4892f
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/types.js
@@ -0,0 +1,7 @@
+import PropTypes from 'prop-types';
+
+export const commonlyUsedRange = PropTypes.shape({
+ from: PropTypes.string.isRequired,
+ to: PropTypes.string.isRequired,
+ label: PropTypes.string.isRequired,
+});
From d42a1b17dc9e51fbabc349abf8bb04b9409078d4 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Tue, 4 Dec 2018 14:54:48 -0700
Subject: [PATCH 04/37] recently used
---
package.json | 1 +
.../views/date_picker/super_date_picker.js | 16 ++++--
.../super_date_picker/pretty_duration.js | 53 +++++++++++++++++++
.../super_date_picker/pretty_duration.test.js | 44 +++++++++++++++
.../quick_select_popover/commonly_used.js | 23 ++------
.../quick_select_popover.js | 45 ++++++----------
.../quick_select_popover/recently_used.js | 53 +++++++++++++++++++
.../super_date_picker/super_date_picker.js | 26 +++++++--
.../date_picker/super_date_picker/types.js | 7 ++-
yarn.lock | 9 +++-
10 files changed, 222 insertions(+), 55 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/pretty_duration.js
create mode 100644 src/components/date_picker/super_date_picker/pretty_duration.test.js
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
diff --git a/package.json b/package.json
index c6f62723c1c..f2b636f72f3 100644
--- a/package.json
+++ b/package.json
@@ -121,6 +121,7 @@
"markdown-it": "8.4.1",
"mocha": "^5.0.4",
"moment": "^2.20.1",
+ "moment-timezone": "^0.5.14",
"node-sass": "^4.9.3",
"nodegit": "^0.23.0",
"npm-run": "^4.1.2",
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 5352288f53f..4c7daae0cf5 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -7,10 +7,20 @@ import {
export default class extends Component {
- state = {}
+ state = {
+ recentlyUsedRanges: []
+ }
onTimeChange = ({ from, to }) => {
- this.setState({ from, to });
+ this.setState((prevState) => {
+ const recentlyUsedRanges = [...prevState.recentlyUsedRanges];
+ recentlyUsedRanges.push({ from, to });
+ return {
+ from,
+ to,
+ recentlyUsedRanges: recentlyUsedRanges.length > 10 ? recentlyUsedRanges.slice(0, 9) : recentlyUsedRanges,
+ };
+ });
}
onRefreshChange = ({ isPaused, refreshInterval }) => {
@@ -18,7 +28,6 @@ export default class extends Component {
}
render() {
-
return (
);
}
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
new file mode 100644
index 00000000000..6db1be99af5
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -0,0 +1,53 @@
+
+import dateMath from '@elastic/datemath';
+import moment from 'moment';
+import { timeUnits } from './time_units';
+
+const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.sssZ';
+
+function cantLookup(timeFrom, timeTo, dateFormat) {
+ const displayFrom = formatTimeString(timeFrom, dateFormat);
+ const displayTo = formatTimeString(timeTo, dateFormat, true);
+ return `${displayFrom} to ${displayTo}`;
+}
+
+function getRangeKey(from, to) {
+ return `${from} to ${to}`;
+}
+
+export function formatTimeString(timeString, dateFormat, roundUp = false) {
+ const timeAsMoment = moment(timeString, ISO_FORMAT, true);
+ if (timeAsMoment.isValid()) {
+ console.log('ISO_FORMAT', timeAsMoment.format(ISO_FORMAT));
+ return timeAsMoment.format(dateFormat);
+ }
+
+ if (timeString === 'now') {
+ return 'now';
+ }
+
+ const tryParse = dateMath.parse(timeString, { roundUp: roundUp });
+ return moment.isMoment(tryParse) ? '~ ' + tryParse.fromNow() : timeString;
+}
+
+export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
+ const matchingQuickRange = quickRanges.find(({ from: quickFrom, to: quickTo }) => {
+ return timeFrom === quickFrom && timeTo === quickTo;
+ });
+ if (matchingQuickRange) {
+ return matchingQuickRange.label;
+ }
+
+ const fromParts = timeFrom.split('-');
+ if (timeTo === 'now' && fromParts[0] === 'now' && fromParts[1]) {
+ const rounded = fromParts[1].split('/');
+ let text = `Last ${rounded[0]}`;
+ if (rounded[1]) {
+ const timeUnit = timeUnits[rounded[1]] ? timeUnits[rounded[1]] : rounded[1];
+ text = `${text} rounded to the ${timeUnit}`;
+ }
+ return text;
+ }
+
+ return cantLookup(timeFrom, timeTo, dateFormat);
+}
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
new file mode 100644
index 00000000000..9e4ea99c506
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -0,0 +1,44 @@
+
+import moment from 'moment-timezone';
+import { prettyDuration } from './pretty_duration';
+
+moment.tz.setDefault('UTC');
+const dateFormat = 'MMMM Do YYYY, HH:mm:ss.SSS';
+const quickRanges = [
+ {
+ from: 'now-15m',
+ to: 'now',
+ label: 'quick range 15 minutes custom display',
+ }
+];
+
+test('quick range', () => {
+ const timeFrom = 'now-15m';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('quick range 15 minutes custom display');
+});
+
+test('last', () => {
+ const timeFrom = 'now-1M';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M');
+});
+
+test('last that is rounded', () => {
+ const timeFrom = 'now-1M/w';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M rounded to the week');
+});
+
+test('from is in past', () => {
+ const timeFrom = 'now-17m';
+ const timeTo = 'now-15m';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('~ 17 minutes ago to ~ 15 minutes ago');
+});
+
+// TODO figure out timezone to get this working
+//test('absolute dates', () => {
+// const timeFrom = '2018-01-17T18:57:57.149Z';
+// const timeTo = '2018-01-17T20:00:00.000Z';
+// expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('January 17th 2018, 18:57:57.149 to January 17th 2018, 20:00:00.000');
+//});
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
index b5c0f93364c..724f52c8c1e 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React, { Fragment } from 'react';
-import { commonlyUsedRange } from '../types';
+import { commonlyUsedRangeShape } from '../types';
import { EuiFlexGrid, EuiFlexItem } from '../../../flex';
import { EuiTitle } from '../../../title';
@@ -9,14 +9,14 @@ import { EuiSpacer } from '../../../spacer';
import { EuiLink } from '../../../link';
import { EuiText } from '../../../text';
-export function CommonlyUsed({ commonlyUsedRanges, applyTime }) {
+export function CommonlyUsed({ applyTime, commonlyUsedRanges }) {
const links = commonlyUsedRanges.map(({ from, to, label }) => {
- const applyCommonlyUsedTime = () => {
+ const applyCommonlyUsed = () => {
applyTime({ from, to });
};
return (
- {label}
+ {label}
);
});
@@ -35,19 +35,6 @@ export function CommonlyUsed({ commonlyUsedRanges, applyTime }) {
}
CommonlyUsed.propTypes = {
- commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRange),
applyTime: PropTypes.func.isRequired,
-};
-
-CommonlyUsed.defaultProps = {
- commonlyUsedRanges: [
- { from: 'now/d', to: 'now/d', label: 'Today' },
- { from: 'now-1d/d', to: 'now-1d/d', label: 'Yesterday' },
- { from: 'now/w', to: 'now/w', label: 'This week' },
- { from: 'now/w', to: 'now', label: 'Week to date' },
- { from: 'now/M', to: 'now/M', label: 'This month' },
- { from: 'now/M', to: 'now', label: 'Month to date' },
- { from: 'now/y', to: 'now/y', label: 'This year' },
- { from: 'now/y', to: 'now', label: 'Year to date' },
- ]
+ commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 8e37bf3ea39..0ac12fd2ade 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -1,10 +1,10 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
+import { commonlyUsedRangeShape, recentlyUsedRangeShape } from '../types';
/*
import { timeHistory } from '../../timefilter/time_history';
-import { prettyDuration } from '../pretty_duration';
import { RefreshIntervalForm } from './refresh_interval_form';*/
import {
@@ -49,6 +49,7 @@ import {
import { QuickSelect } from './quick_select';
import { CommonlyUsed } from './commonly_used';
+import { RecentlyUsed } from './recently_used';
export class QuickSelectPopover extends Component {
@@ -68,8 +69,8 @@ export class QuickSelectPopover extends Component {
applyTime = ({ from, to }) => {
this.props.applyTime({
- from: from,
- to: to
+ from,
+ to,
});
this.closePopover();
}
@@ -91,32 +92,6 @@ export class QuickSelectPopover extends Component {
);
}
- renderRecentlyUsed = () => {
- const links = timeHistory.get().map(({ from, to }) => {
- const applyTime = () => {
- this.applyTime({ from, to });
- };
- const display = prettyDuration(from, to, (...args) => chrome.getUiSettingsClient().get(...args));
- return (
-
- {display}
-
- );
- });
-
- return (
-
- Recently used date ranges
-
-
-
- {links}
-
-
-
- );
- }
-
render() {
const quickSelectButton = (
+
+
@@ -161,4 +145,7 @@ QuickSelectPopover.propTypes = {
setRefresh: PropTypes.func.isRequired,
isPaused: PropTypes.bool.isRequired,
refreshInterval: PropTypes.number,
+ commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
+ dateFormat: PropTypes.string.isRequired,
+ recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape).isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
new file mode 100644
index 00000000000..cb5837b1a4b
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
@@ -0,0 +1,53 @@
+
+import PropTypes from 'prop-types';
+import React, { Fragment } from 'react';
+import { commonlyUsedRangeShape, recentlyUsedRangeShape } from '../types';
+import { prettyDuration } from '../pretty_duration';
+
+import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
+import { EuiTitle } from '../../../title';
+import { EuiSpacer } from '../../../spacer';
+import { EuiLink } from '../../../link';
+import { EuiText } from '../../../text';
+
+export function RecentlyUsed({ applyTime, commonlyUsedRanges, dateFormat, recentlyUsedRanges }) {
+ if (recentlyUsedRanges.length === 0) {
+ return null;
+ }
+
+ const links = recentlyUsedRanges.map(({ from, to }) => {
+ const applyRecentlyUsed = () => {
+ applyTime({ from, to });
+ };
+ return (
+
+
+ {prettyDuration(from, to, commonlyUsedRanges, dateFormat)}
+
+
+ );
+ });
+
+ return (
+
+ Recently used date ranges
+
+
+
+ {links}
+
+
+
+ );
+}
+
+RecentlyUsed.propTypes = {
+ applyTime: PropTypes.func.isRequired,
+ commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
+ dateFormat: PropTypes.string.isRequired,
+ recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape),
+};
+
+RecentlyUsed.defaultProps = {
+ recentlyUsedRanges: []
+};
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 ed261cf4cc5..a5ed2f53501 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
@@ -20,6 +20,7 @@
import moment from 'moment';
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
+import { commonlyUsedRangeShape, recentlyUsedRangeShape } from './types';
import dateMath from '@elastic/datemath';
@@ -107,11 +108,11 @@ export class EuiSuperDatePicker extends Component {
}*/
applyTime = () => {
- this.props.onTimeChange(this.state.from, this.state.to);
+ this.props.onTimeChange({ from: this.state.from, to: this.state.to });
}
applyQuickTime = ({ from, to }) => {
- this.props.onTimeChange(from, to);
+ this.props.onTimeChange({ from, to });
}
renderDateRange = () => {
@@ -144,9 +145,12 @@ export class EuiSuperDatePicker extends Component {
applyTime={this.applyQuickTime}
stepForward={this.stepForward}
stepBackward={this.stepBackward}
- setRefresh={this.props.setRefresh}
+ setRefresh={this.props.onRefreshChange}
isPaused={this.props.isPaused}
refreshInterval={this.props.refreshInterval}
+ commonlyUsedRanges={this.props.commonlyUsedRanges}
+ dateFormat={this.props.dateFormat}
+ recentlyUsedRanges={this.props.recentlyUsedRanges}
/>
);
return (
@@ -177,6 +181,10 @@ EuiSuperDatePicker.propTypes = {
isPaused: PropTypes.bool,
refreshInterval: PropTypes.number,
onRefreshChange: PropTypes.func.isRequired,
+
+ commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape),
+ dateFormat: PropTypes.string,
+ recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape),
};
EuiSuperDatePicker.defaultProps = {
@@ -184,5 +192,17 @@ EuiSuperDatePicker.defaultProps = {
to: 'now',
isPaused: true,
refreshInterval: 0,
+ commonlyUsedRanges: [
+ { from: 'now/d', to: 'now/d', label: 'Today' },
+ { from: 'now-1d/d', to: 'now-1d/d', label: 'Yesterday' },
+ { from: 'now/w', to: 'now/w', label: 'This week' },
+ { from: 'now/w', to: 'now', label: 'Week to date' },
+ { from: 'now/M', to: 'now/M', label: 'This month' },
+ { from: 'now/M', to: 'now', label: 'Month to date' },
+ { from: 'now/y', to: 'now/y', label: 'This year' },
+ { from: 'now/y', to: 'now', label: 'Year to date' },
+ ],
+ dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
+ recentlyUsedRanges: [],
};
diff --git a/src/components/date_picker/super_date_picker/types.js b/src/components/date_picker/super_date_picker/types.js
index 22a38b4892f..78e4c817a16 100644
--- a/src/components/date_picker/super_date_picker/types.js
+++ b/src/components/date_picker/super_date_picker/types.js
@@ -1,7 +1,12 @@
import PropTypes from 'prop-types';
-export const commonlyUsedRange = PropTypes.shape({
+export const commonlyUsedRangeShape = PropTypes.shape({
from: PropTypes.string.isRequired,
to: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
});
+
+export const recentlyUsedRangeShape = PropTypes.shape({
+ from: PropTypes.string.isRequired,
+ to: PropTypes.string.isRequired,
+});
diff --git a/yarn.lock b/yarn.lock
index 811e03dc147..fbcaf50f73f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8801,12 +8801,19 @@ mocha@^5.0.0, mocha@^5.0.4:
mkdirp "0.5.1"
supports-color "4.4.0"
+moment-timezone@^0.5.14:
+ version "0.5.23"
+ resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463"
+ integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==
+ dependencies:
+ moment ">= 2.9.0"
+
moment@2.x.x:
version "2.21.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
integrity sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==
-moment@^2.13.0:
+"moment@>= 2.9.0", moment@^2.13.0:
version "2.22.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
From 325168f44e552ab0744c589db91fd089fa0dbf1e Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Wed, 5 Dec 2018 06:55:41 -0700
Subject: [PATCH 05/37] cleanup quick_select_popover
---
.../views/date_picker/super_date_picker.js | 5 +-
.../super_date_picker/pretty_duration.js | 10 ++--
.../quick_select_popover/commonly_used.js | 2 +
.../quick_select_popover/quick_select.js | 2 +
.../quick_select_popover.js | 58 +------------------
.../quick_select_popover/recently_used.js | 2 +
6 files changed, 18 insertions(+), 61 deletions(-)
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 4c7daae0cf5..6bad16ceea6 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -13,7 +13,10 @@ export default class extends Component {
onTimeChange = ({ from, to }) => {
this.setState((prevState) => {
- const recentlyUsedRanges = [...prevState.recentlyUsedRanges];
+ const recentlyUsedRanges = prevState.recentlyUsedRanges.filter(recentlyUsedRange => {
+ const isDuplicate = recentlyUsedRange.from === from && recentlyUsedRange.to === to;
+ return !isDuplicate;
+ });
recentlyUsedRanges.push({ from, to });
return {
from,
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index 6db1be99af5..836b1d03af7 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -11,10 +11,6 @@ function cantLookup(timeFrom, timeTo, dateFormat) {
return `${displayFrom} to ${displayTo}`;
}
-function getRangeKey(from, to) {
- return `${from} to ${to}`;
-}
-
export function formatTimeString(timeString, dateFormat, roundUp = false) {
const timeAsMoment = moment(timeString, ISO_FORMAT, true);
if (timeAsMoment.isValid()) {
@@ -27,7 +23,11 @@ export function formatTimeString(timeString, dateFormat, roundUp = false) {
}
const tryParse = dateMath.parse(timeString, { roundUp: roundUp });
- return moment.isMoment(tryParse) ? '~ ' + tryParse.fromNow() : timeString;
+ if (moment.isMoment(tryParse)) {
+ return `~ ${tryParse.fromNow()}`;
+ }
+
+ return timeString;
}
export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
index 724f52c8c1e..64ae8961180 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
@@ -8,6 +8,7 @@ import { EuiTitle } from '../../../title';
import { EuiSpacer } from '../../../spacer';
import { EuiLink } from '../../../link';
import { EuiText } from '../../../text';
+import { EuiHorizontalRule } from '../../../horizontal_rule';
export function CommonlyUsed({ applyTime, commonlyUsedRanges }) {
const links = commonlyUsedRanges.map(({ from, to, label }) => {
@@ -30,6 +31,7 @@ export function CommonlyUsed({ applyTime, commonlyUsedRanges }) {
{links}
+
);
}
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index 4f80f2ca6f1..878ca227d67 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -8,6 +8,7 @@ import { EuiTitle } from '../../../title';
import { EuiSpacer } from '../../../spacer';
import { EuiFormRow, EuiSelect, EuiFieldNumber } from '../../../form';
import { EuiToolTip } from '../../../tool_tip';
+import { EuiHorizontalRule } from '../../../horizontal_rule';
import { timeUnits } from '../time_units';
@@ -131,6 +132,7 @@ export class QuickSelect extends Component {
+
);
}
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 0ac12fd2ade..d22071ed59b 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -1,24 +1,12 @@
-import _ from 'lodash';
+
import PropTypes from 'prop-types';
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import { commonlyUsedRangeShape, recentlyUsedRangeShape } from '../types';
-/*
-import { timeHistory } from '../../timefilter/time_history';
-import { RefreshIntervalForm } from './refresh_interval_form';*/
-
import {
EuiButtonEmpty,
- EuiButton,
- EuiButtonIcon,
} from '../../../button';
-import {
- EuiFlexGrid,
- EuiFlexGroup,
- EuiFlexItem,
-} from '../../../flex';
-
import {
EuiIcon,
} from '../../../icon';
@@ -27,26 +15,6 @@ import {
EuiPopover,
} from '../../../popover';
-import {
- EuiTitle,
-} from '../../../title';
-
-import {
- EuiSpacer,
-} from '../../../spacer';
-
-import {
- EuiText,
-} from '../../../text';
-
-import {
- EuiHorizontalRule,
-} from '../../../horizontal_rule';
-
-import {
- EuiLink,
-} from '../../../link';
-
import { QuickSelect } from './quick_select';
import { CommonlyUsed } from './commonly_used';
import { RecentlyUsed } from './recently_used';
@@ -75,23 +43,6 @@ export class QuickSelectPopover extends Component {
this.closePopover();
}
- renderTimeNavigation = () => {
- return (
-
-
-
-
- );
- }
-
render() {
const quickSelectButton = (
-
+
);
@@ -121,19 +72,16 @@ export class QuickSelectPopover extends Component {
applyTime={this.applyTime}
commonlyUsedRanges={this.props.commonlyUsedRanges}
/>
-
-
-
);
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
index cb5837b1a4b..419d86eb24a 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/recently_used.js
@@ -9,6 +9,7 @@ import { EuiTitle } from '../../../title';
import { EuiSpacer } from '../../../spacer';
import { EuiLink } from '../../../link';
import { EuiText } from '../../../text';
+import { EuiHorizontalRule } from '../../../horizontal_rule';
export function RecentlyUsed({ applyTime, commonlyUsedRanges, dateFormat, recentlyUsedRanges }) {
if (recentlyUsedRanges.length === 0) {
@@ -37,6 +38,7 @@ export function RecentlyUsed({ applyTime, commonlyUsedRanges, dateFormat, recent
{links}
+
);
}
From 0aa79ef62d938a713fd660542e636934b047d7bc Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Wed, 5 Dec 2018 10:43:25 -0700
Subject: [PATCH 06/37] refresh interval
---
.../views/date_picker/super_date_picker.js | 7 +-
.../quick_select_popover.js | 10 +-
.../quick_select_popover/refresh_interval.js | 137 ++++++++++++++++++
.../super_date_picker/super_date_picker.js | 2 +-
4 files changed, 152 insertions(+), 4 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
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 6bad16ceea6..6bf6ad66c7c 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -27,7 +27,12 @@ export default class extends Component {
}
onRefreshChange = ({ isPaused, refreshInterval }) => {
- this.setState({ isPaused, refreshInterval });
+ this.setState((prevState) => {
+ return {
+ isPaused: isPaused == null ? prevState.isPaused : isPaused,
+ refreshInterval: refreshInterval == null ? prevState.refreshInterval : refreshInterval,
+ };
+ });
}
render() {
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index d22071ed59b..65c67586286 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -18,6 +18,7 @@ import {
import { QuickSelect } from './quick_select';
import { CommonlyUsed } from './commonly_used';
import { RecentlyUsed } from './recently_used';
+import { RefreshInterval } from './refresh_interval';
export class QuickSelectPopover extends Component {
@@ -82,6 +83,11 @@ export class QuickSelectPopover extends Component {
dateFormat={this.props.dateFormat}
recentlyUsedRanges={this.props.recentlyUsedRanges}
/>
+
);
@@ -90,9 +96,9 @@ export class QuickSelectPopover extends Component {
QuickSelectPopover.propTypes = {
applyTime: PropTypes.func.isRequired,
- setRefresh: PropTypes.func.isRequired,
+ applyRefreshInterval: PropTypes.func.isRequired,
isPaused: PropTypes.bool.isRequired,
- refreshInterval: PropTypes.number,
+ refreshInterval: PropTypes.number.isRequired,
commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
dateFormat: PropTypes.string.isRequired,
recentlyUsedRanges: PropTypes.arrayOf(recentlyUsedRangeShape).isRequired,
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
new file mode 100644
index 00000000000..32bf457a9ae
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
@@ -0,0 +1,137 @@
+import PropTypes from 'prop-types';
+import React, { Component, Fragment } from 'react';
+import { timeUnits } from '../time_units';
+
+import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
+import { EuiTitle } from '../../../title';
+import { EuiSpacer } from '../../../spacer';
+import { EuiFormRow, EuiSelect, EuiFieldNumber } from '../../../form';
+import { EuiButton } from '../../../button';
+
+const refreshUnitsOptions = Object.keys(timeUnits)
+ .filter(timeUnit => {
+ return timeUnit === 'h' || timeUnit === 'm';
+ })
+ .map(timeUnit => {
+ return { value: timeUnit, text: `${timeUnits[timeUnit]}s` };
+ });
+
+const MILLISECONDS_IN_MINUTE = 1000 * 60;
+const MILLISECONDS_IN_HOUR = MILLISECONDS_IN_MINUTE * 60;
+
+function convertMilliseconds(milliseconds) {
+ if (milliseconds > MILLISECONDS_IN_HOUR) {
+ return {
+ units: 'h',
+ value: milliseconds / MILLISECONDS_IN_HOUR
+ };
+ }
+
+ return {
+ units: 'm',
+ value: milliseconds / MILLISECONDS_IN_MINUTE
+ };
+}
+
+export class RefreshInterval extends Component {
+ constructor(props) {
+ super(props);
+
+ const { value, units } = convertMilliseconds(this.props.refreshInterval);
+ this.state = {
+ value,
+ units,
+ };
+ }
+
+ static getDerivedStateFromProps = (nextProps) => {
+ const { value, units } = convertMilliseconds(nextProps.refreshInterval);
+ return {
+ value,
+ units,
+ };
+ }
+
+ onValueChange = (evt) => {
+ const sanitizedValue = parseInt(evt.target.value, 10);
+ this.setState({
+ value: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ }, this.applyRefreshInterval);
+ };
+
+ onUnitsChange = (evt) => {
+ this.setState({
+ units: evt.target.value,
+ }, this.applyRefreshInterval);
+ }
+
+ applyRefreshInterval = () => {
+ if (this.state.value === '') {
+ return;
+ }
+
+ const valueInMilliSeconds = this.state.units === 'h'
+ ? this.state.value * MILLISECONDS_IN_HOUR
+ : this.state.value * MILLISECONDS_IN_MINUTE;
+
+ this.props.applyRefreshInterval({
+ refreshInterval: valueInMilliSeconds,
+ isPaused: valueInMilliSeconds <= 0 ? true : this.props.isPaused,
+ });
+ }
+
+ toogleRefresh = () => {
+ this.props.applyRefreshInterval({
+ isPaused: !this.props.isPaused
+ });
+ }
+
+ render() {
+ return (
+
+ Refresh every
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {this.props.isPaused ? 'Start' : 'Stop'}
+
+
+
+
+
+ );
+ }
+}
+
+RefreshInterval.propTypes = {
+ applyRefreshInterval: PropTypes.func.isRequired,
+ isPaused: PropTypes.bool.isRequired,
+ refreshInterval: PropTypes.number.isRequired,
+};
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 a5ed2f53501..25a1e5db608 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
@@ -145,7 +145,7 @@ export class EuiSuperDatePicker extends Component {
applyTime={this.applyQuickTime}
stepForward={this.stepForward}
stepBackward={this.stepBackward}
- setRefresh={this.props.onRefreshChange}
+ applyRefreshInterval={this.props.onRefreshChange}
isPaused={this.props.isPaused}
refreshInterval={this.props.refreshInterval}
commonlyUsedRanges={this.props.commonlyUsedRanges}
From f0c95440c2cb9f7db0330e3b8ec3fd85f2938355 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Wed, 5 Dec 2018 12:29:28 -0700
Subject: [PATCH 07/37] show date range
---
.../super_date_picker/date_button.js | 182 +++++-------------
.../super_date_picker/super_date_picker.js | 90 +++++++--
2 files changed, 122 insertions(+), 150 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/date_button.js b/src/components/date_picker/super_date_picker/date_button.js
index 0c8d7aded15..a4237972b0a 100644
--- a/src/components/date_picker/super_date_picker/date_button.js
+++ b/src/components/date_picker/super_date_picker/date_button.js
@@ -1,127 +1,77 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import chrome from 'ui/chrome';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
-import { AbsoluteForm } from './absolute_form';
-import { RelativeForm } from './relative_form';
-
-import {
- EuiPopover,
- EuiTabbedContent,
- EuiText,
-} from '@elastic/eui';
+import classNames from 'classnames';
-import { formatTimeString } from '../pretty_duration';
-import {
- getTimeMode,
- TIME_MODES,
- toAbsoluteString,
- toRelativeString,
-} from '../lib/time_modes';
+import { EuiPopover } from '../../popover';
export class DateButton extends Component {
+ static propTypes = {
+ position: PropTypes.oneOf(['start', 'end']),
+ isInvalid: PropTypes.bool,
+ needsUpdating: PropTypes.bool,
+ buttonOnly: PropTypes.bool,
+ value: PropTypes.string.isRequired,
+ }
- constructor(props) {
- super(props);
+ state = {
+ isOpen: false,
+ }
- this.state = {
+ togglePopover = () => {
+ this.setState((prevState) => {
+ return { isOpen: !prevState.isOpen };
+ });
+ }
+
+ closePopover = () => {
+ this.setState({
isOpen: false,
- };
+ });
}
- onTabClick = (selectedTab) => {
+ render() {
const {
+ position,
+ isInvalid,
+ needsUpdating,
value,
- roundUp
+ buttonProps,
+ buttonOnly,
+ ...rest
} = this.props;
- switch(selectedTab.id) {
- case TIME_MODES.ABSOLUTE:
- this.props.onChange(toAbsoluteString(value, roundUp));
- break;
- case TIME_MODES.RELATIVE:
- this.props.onChange(toRelativeString(value));
- break;
- case TIME_MODES.NOW:
- this.props.onChange('now');
- break;
- }
- };
-
- closePopover = () => {
- this.setState({ isOpen: false });
- }
-
- togglePopover = () => {
- this.setState((prevState) => ({
- isOpen: !prevState.isOpen,
- }));
- }
-
- renderTabs = () => {
- return [
- {
- id: TIME_MODES.ABSOLUTE,
- name: 'Absolute',
- content: (
-
- ),
- },
+ const classes = classNames([
+ 'euiSuperDatePicker__dateButton',
+ `euiSuperDatePicker__dateButton--${position}`,
{
- id: TIME_MODES.RELATIVE,
- name: 'Relative',
- content: (
-
- ),
- },
- {
- id: TIME_MODES.NOW,
- name: 'Now',
- content: (
-
- ),
+ 'euiSuperDatePicker__dateButton-isSelected': this.state.isOpen,
+ 'euiSuperDatePicker__dateButton-isInvalid': isInvalid,
+ 'euiSuperDatePicker__dateButton-needsUpdating': needsUpdating
}
- ];
- }
+ ]);
- render() {
- const input = (
+ let title = value;
+ if (isInvalid) {
+ title = `Invalid date: ${title}`;
+ } else if (needsUpdating) {
+ title = `Update needed: ${title}`;
+ }
+
+ const button = (
- {formatTimeString(this.props.value, chrome.getUiSettingsClient().get('dateFormat'))}
+ {value}
);
+ if (buttonOnly) {
+ return button;
+ }
+
return (
-
-
-
-
+ Date selection popover
);
}
}
-
-DateButton.propTypes = {
- value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- roundUp: PropTypes.bool,
-};
-
-DateButton.defaultProps = {
- roundUp: false,
-};
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 25a1e5db608..1765c637f2b 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
@@ -21,28 +21,18 @@ import moment from 'moment';
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import { commonlyUsedRangeShape, recentlyUsedRangeShape } from './types';
+import { prettyDuration } from './pretty_duration';
import dateMath from '@elastic/datemath';
import { QuickSelectPopover } from './quick_select_popover/quick_select_popover';
-//import { TimeInput } from './time_input';
+import { DateButton } from './date_button';
-import {
- EuiFormControlLayout,
-} from '../../form';
-
-import {
- EuiText,
-} from '../../text';
-
-import {
- EuiButton,
-} from '../../button';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
-} from '../../flex';
+import { EuiDatePickerRange } from '../date_picker_range';
+import { EuiFormControlLayout } from '../../form';
+import { EuiText } from '../../text';
+import { EuiButton, EuiButtonEmpty } from '../../button';
+import { EuiFlexGroup, EuiFlexItem } from '../../flex';
/*import { prettyDuration } from '../pretty_duration';
import { timeNavigation } from '../time_navigation';
@@ -115,8 +105,66 @@ export class EuiSuperDatePicker extends Component {
this.props.onTimeChange({ from, to });
}
- renderDateRange = () => {
- return;
+ toggleEditMode = () => {
+ this.setState({ isEditMode: true });
+ }
+
+ renderDatePickerRange = () => {
+ const {
+ from,
+ to,
+ hasChanged,
+ isInvalid,
+ } = this.state;
+
+ let prettyDurationDateRange;
+ if (!this.state.isEditMode) {
+ prettyDurationDateRange = (
+
+
+
+ Show dates
+
+
+ );
+ }
+
+ // Why isn't prettyDurationDateRange just returned and instead passed as a child to EuiDatePickerRange?
+ // Need classes provided by EuiDatePickerRange for consistent view and
+ // EuiDatePickerRange does not render startDateControl of endDateControl when children are provided.
+ return (
+
+ }
+ endDateControl={
+
+ }
+ >
+ {prettyDurationDateRange}
+
+ );
}
renderUpdateButton = () => {
@@ -158,10 +206,10 @@ export class EuiSuperDatePicker extends Component {
- {this.renderDateRange()}
+ {this.renderDatePickerRange()}
From e823450f787278962a7b827e43e4c272bcf1bea9 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Wed, 5 Dec 2018 15:30:07 -0700
Subject: [PATCH 08/37] relative date parsing
---
.../{ => date_popover}/date_button.js | 14 ++-
.../date_popover/date_input.js | 75 +++++++++++
.../date_popover/date_modes.js | 30 +++++
.../date_popover/relative_options.js | 18 +++
.../date_popover/relative_utils.js | 61 +++++++++
.../date_popover/relative_utils.test.js | 119 ++++++++++++++++++
.../super_date_picker/super_date_picker.js | 9 +-
7 files changed, 321 insertions(+), 5 deletions(-)
rename src/components/date_picker/super_date_picker/{ => date_popover}/date_button.js (82%)
create mode 100644 src/components/date_picker/super_date_picker/date_popover/date_input.js
create mode 100644 src/components/date_picker/super_date_picker/date_popover/date_modes.js
create mode 100644 src/components/date_picker/super_date_picker/date_popover/relative_options.js
create mode 100644 src/components/date_picker/super_date_picker/date_popover/relative_utils.js
create mode 100644 src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js
diff --git a/src/components/date_picker/super_date_picker/date_button.js b/src/components/date_picker/super_date_picker/date_popover/date_button.js
similarity index 82%
rename from src/components/date_picker/super_date_picker/date_button.js
rename to src/components/date_picker/super_date_picker/date_popover/date_button.js
index a4237972b0a..d5b5078b46a 100644
--- a/src/components/date_picker/super_date_picker/date_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_button.js
@@ -2,7 +2,9 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import classNames from 'classnames';
-import { EuiPopover } from '../../popover';
+import { EuiPopover } from '../../../popover';
+
+import { DateInput } from './date_input';
export class DateButton extends Component {
static propTypes = {
@@ -11,6 +13,8 @@ export class DateButton extends Component {
needsUpdating: PropTypes.bool,
buttonOnly: PropTypes.bool,
value: PropTypes.string.isRequired,
+ onChange: PropTypes.func,
+ roundUp: PropTypes.bool,
}
state = {
@@ -37,6 +41,8 @@ export class DateButton extends Component {
value,
buttonProps,
buttonOnly,
+ roundUp, // eslint-disable-line no-unused-vars
+ onChange, // eslint-disable-line no-unused-vars
...rest
} = this.props;
@@ -82,7 +88,11 @@ export class DateButton extends Component {
ownFocus
{...rest}
>
- Date selection popover
+
);
}
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_input.js b/src/components/date_picker/super_date_picker/date_popover/date_input.js
new file mode 100644
index 00000000000..5ee1fa1680b
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/date_input.js
@@ -0,0 +1,75 @@
+
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import { EuiTabbedContent } from '../../../tabs';
+
+import {
+ getDateMode,
+ DATE_MODES,
+ toAbsoluteString,
+ toRelativeString,
+} from './date_modes';
+
+export function DateInput({ value, roundUp, onChange }) {
+
+ const onTabClick = (selectedTab) => {
+ switch(selectedTab.id) {
+ case DATE_MODES.ABSOLUTE:
+ onChange(toAbsoluteString(value, roundUp));
+ break;
+ case DATE_MODES.RELATIVE:
+ onChange(toRelativeString(value));
+ break;
+ case DATE_MODES.NOW:
+ onChange('now');
+ break;
+ }
+ };
+
+ const renderTabs = () => {
+ return [
+ {
+ id: DATE_MODES.ABSOLUTE,
+ name: 'Absolute',
+ content: (
+ absolute: {value}
+ ),
+ },
+ {
+ id: DATE_MODES.RELATIVE,
+ name: 'Relative',
+ content: (
+ relative: {value}
+ ),
+ },
+ {
+ id: DATE_MODES.NOW,
+ name: 'Now',
+ content: (
+ now: {value}
+ ),
+ }
+ ];
+ };
+
+ return (
+
+ );
+}
+
+DateInput.propTypes = {
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+ roundUp: PropTypes.bool,
+};
+
+DateInput.defaultProps = {
+ roundUp: false,
+};
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_modes.js b/src/components/date_picker/super_date_picker/date_popover/date_modes.js
new file mode 100644
index 00000000000..5ab95e6b22a
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/date_modes.js
@@ -0,0 +1,30 @@
+
+import dateMath from '@elastic/datemath';
+import { parseRelativeParts, toRelativeStringFromParts } from './relative_utils';
+
+export const DATE_MODES = {
+ ABSOLUTE: 'absolute',
+ RELATIVE: 'relative',
+ NOW: 'now',
+};
+
+export function getDateMode(value) {
+ if (value === 'now') {
+ return DATE_MODES.NOW;
+ }
+
+ if (value.includes('now')) {
+ return DATE_MODES.RELATIVE;
+ }
+
+ return DATE_MODES.absolute;
+}
+
+export function toAbsoluteString(value, roundUp) {
+ return dateMath.parse(value, { roundUp }).toISOString();
+}
+
+
+export function toRelativeString(value) {
+ return toRelativeStringFromParts(parseRelativeParts(value));
+}
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_options.js b/src/components/date_picker/super_date_picker/date_popover/relative_options.js
new file mode 100644
index 00000000000..43045a13a03
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_options.js
@@ -0,0 +1,18 @@
+
+export const relativeOptions = [
+ { text: 'Seconds ago', value: 's' },
+ { text: 'Minutes ago', value: 'm' },
+ { text: 'Hours ago', value: 'h' },
+ { text: 'Days ago', value: 'd' },
+ { text: 'Weeks ago', value: 'w' },
+ { text: 'Months ago', value: 'M' },
+ { text: 'Years ago', value: 'y' },
+
+ { text: 'Seconds from now', value: 's+' },
+ { text: 'Minutes from now', value: 'm+' },
+ { text: 'Hours from now', value: 'h+' },
+ { text: 'Days from now', value: 'd+' },
+ { text: 'Weeks from now', value: 'w+' },
+ { text: 'Months from now', value: 'M+' },
+ { text: 'Years from now', value: 'y+' },
+];
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_utils.js b/src/components/date_picker/super_date_picker/date_popover/relative_utils.js
new file mode 100644
index 00000000000..c77fc35de07
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_utils.js
@@ -0,0 +1,61 @@
+
+import dateMath from '@elastic/datemath';
+import moment from 'moment';
+import _ from 'lodash';
+import { relativeOptions } from './relative_options';
+
+export function parseRelativeParts(value) {
+ const matches = _.isString(value) && value.match(/now(([\-\+])([0-9]+)([smhdwMy])(\/[smhdwMy])?)?/);
+
+ const isNow = matches && !matches[1];
+ const operator = matches && matches[2];
+ const count = matches && matches[3];
+ const unit = matches && matches[4];
+ const roundBy = matches && matches[5];
+
+ if (isNow) {
+ return { count: 0, unit: 's', round: false };
+ }
+
+ if (count && unit) {
+ return {
+ count: parseInt(count, 10),
+ unit: operator === '+' ? `${unit}+` : unit,
+ round: roundBy ? true : false,
+ };
+ }
+
+ const results = { count: 0, unit: 's', round: false };
+ const duration = moment.duration(moment().diff(dateMath.parse(value)));
+ const units = _.pluck(_.clone(relativeOptions).reverse(), 'value')
+ .filter(s => /^[smhdwMy]$/.test(s));
+ let unitOp = '';
+ for (let i = 0; i < units.length; i++) {
+ const as = duration.as(units[i]);
+ if (as < 0) unitOp = '+';
+ if (Math.abs(as) > 1) {
+ results.count = Math.round(Math.abs(as));
+ results.unit = units[i] + unitOp;
+ results.round = false;
+ break;
+ }
+ }
+ return results;
+}
+
+export function toRelativeStringFromParts(relativeParts) {
+ const count = _.get(relativeParts, `count`, 0);
+ const round = _.get(relativeParts, `round`, false);
+
+ if (count === 0 && !round) {
+ return 'now';
+ }
+
+ const matches = _.get(relativeParts, `unit`, 's').match(/([smhdwMy])(\+)?/);
+ const unit = matches[1];
+ const operator = matches && matches[2] ? matches[2] : '-';
+
+ let result = `now${operator}${count}${unit}`;
+ result += (round ? `/${unit}` : '');
+ return result;
+}
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js b/src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js
new file mode 100644
index 00000000000..8df1dbf074f
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js
@@ -0,0 +1,119 @@
+
+import { parseRelativeParts, toRelativeStringFromParts } from './relative_utils';
+import moment from 'moment';
+
+describe('parseRelativeParts', () => {
+ describe('relative', () => {
+ it('should parse now', () => {
+ const out = parseRelativeParts('now');
+ expect(out).toEqual({
+ count: 0,
+ unit: 's',
+ round: false
+ });
+ });
+
+ it('should parse now-2h', () => {
+ const out = parseRelativeParts('now-2h');
+ expect(out).toEqual({
+ count: 2,
+ unit: 'h',
+ round: false
+ });
+ });
+
+ it('should parse now-2h/h', () => {
+ const out = parseRelativeParts('now-2h/h');
+ expect(out).toEqual({
+ count: 2,
+ unit: 'h',
+ round: true
+ });
+ });
+
+ it('should parse now+10m/m', () => {
+ const out = parseRelativeParts('now+10m/m');
+ expect(out).toEqual({
+ count: 10,
+ unit: 'm+',
+ round: true
+ });
+ });
+ });
+
+ describe('absolute', () => {
+ it('should parse now', () => {
+ const out = parseRelativeParts(moment().toDate().toISOString());
+ expect(out).toEqual({
+ count: 0,
+ unit: 's',
+ round: false
+ });
+ });
+
+ it('should parse 3 months ago', () => {
+ const out = parseRelativeParts(moment().subtract(3, 'M').toDate().toISOString());
+ expect(out).toEqual({
+ count: 3,
+ unit: 'M',
+ round: false
+ });
+ });
+
+ it('should parse 15 minutes ago', () => {
+ const out = parseRelativeParts(moment().subtract(15, 'm').toDate().toISOString());
+ expect(out).toEqual({
+ count: 15,
+ unit: 'm',
+ round: false
+ });
+ });
+
+ it('should parse 2 hours from now', () => {
+ const out = parseRelativeParts(moment().add(2, 'h').toDate().toISOString());
+ expect(out).toEqual({
+ count: 2,
+ unit: 'h+',
+ round: false
+ });
+ });
+ });
+});
+
+describe('toRelativeStringFromParts', () => {
+ it('should convert parts to now', () => {
+ const out = toRelativeStringFromParts({
+ count: 0,
+ unit: 's',
+ round: false
+ });
+ expect(out).toEqual('now');
+ });
+
+ it('should convert parts to now-2h', () => {
+ const out = toRelativeStringFromParts({
+ count: 2,
+ unit: 'h',
+ round: false
+ });
+ expect(out).toEqual('now-2h');
+ });
+
+ it('should convert parts to now-2h/h', () => {
+ const out = toRelativeStringFromParts({
+ count: 2,
+ unit: 'h',
+ round: true
+ });
+ expect(out).toEqual('now-2h/h');
+ });
+
+ it('should convert parts to now+10m/m', () => {
+ const out = toRelativeStringFromParts({
+ count: 10,
+ unit: 'm+',
+ round: true
+ });
+ expect(out).toEqual('now+10m/m');
+ });
+});
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 1765c637f2b..f1a7fb5c999 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
@@ -26,7 +26,7 @@ import { prettyDuration } from './pretty_duration';
import dateMath from '@elastic/datemath';
import { QuickSelectPopover } from './quick_select_popover/quick_select_popover';
-import { DateButton } from './date_button';
+import { DateButton } from './date_popover/date_button';
import { EuiDatePickerRange } from '../date_picker_range';
import { EuiFormControlLayout } from '../../form';
@@ -147,18 +147,21 @@ export class EuiSuperDatePicker extends Component {
isCustom
startDateControl={
}
endDateControl={
}
>
From c8f3339601a4fefd8abfda991fb6c7fc024237d0 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 09:02:05 -0700
Subject: [PATCH 09/37] clean up date_popover
---
.../super_date_picker/_super_date_picker.scss | 4 +-
...{date_button.js => date_popover_button.js} | 27 ++++++-------
...{date_input.js => date_popover_content.js} | 14 +++----
.../super_date_picker/super_date_picker.js | 39 +++++++++----------
4 files changed, 39 insertions(+), 45 deletions(-)
rename src/components/date_picker/super_date_picker/date_popover/{date_button.js => date_popover_button.js} (76%)
rename src/components/date_picker/super_date_picker/date_popover/{date_input.js => date_popover_content.js} (78%)
diff --git a/src/components/date_picker/super_date_picker/_super_date_picker.scss b/src/components/date_picker/super_date_picker/_super_date_picker.scss
index b8b48560225..16bdde5cf33 100644
--- a/src/components/date_picker/super_date_picker/_super_date_picker.scss
+++ b/src/components/date_picker/super_date_picker/_super_date_picker.scss
@@ -28,7 +28,7 @@
}
}
-.euiSuperDatePicker__dateButton {
+.euiSuperDatePicker__dateText {
@include euiFormControlText;
display: block;
width: 100%;
@@ -37,7 +37,9 @@
height: $euiFormControlHeight - 2px;
word-break: break-all;
transition: background $euiAnimSpeedFast ease-in;
+}
+.euiSuperDatePicker__dateButton {
$backgroundColor: tintOrShade($euiColorSuccess, 90%, 70%);
$textColor: makeHighContrastColor($euiColorSuccess, $backgroundColor);
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
similarity index 76%
rename from src/components/date_picker/super_date_picker/date_popover/date_button.js
rename to src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index d5b5078b46a..2c2388bf7aa 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -4,16 +4,15 @@ import classNames from 'classnames';
import { EuiPopover } from '../../../popover';
-import { DateInput } from './date_input';
+import { DatePopoverContent } from './date_popover_content';
-export class DateButton extends Component {
+export class DatePopoverButton extends Component {
static propTypes = {
position: PropTypes.oneOf(['start', 'end']),
isInvalid: PropTypes.bool,
needsUpdating: PropTypes.bool,
- buttonOnly: PropTypes.bool,
value: PropTypes.string.isRequired,
- onChange: PropTypes.func,
+ onValueChange: PropTypes.func,
roundUp: PropTypes.bool,
}
@@ -40,13 +39,13 @@ export class DateButton extends Component {
needsUpdating,
value,
buttonProps,
- buttonOnly,
- roundUp, // eslint-disable-line no-unused-vars
- onChange, // eslint-disable-line no-unused-vars
+ roundUp,
+ onValueChange,
...rest
} = this.props;
const classes = classNames([
+ 'euiSuperDatePicker__dateText',
'euiSuperDatePicker__dateButton',
`euiSuperDatePicker__dateButton--${position}`,
{
@@ -65,7 +64,7 @@ export class DateButton extends Component {
const button = (
);
- if (buttonOnly) {
- return button;
- }
-
return (
-
);
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_input.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
similarity index 78%
rename from src/components/date_picker/super_date_picker/date_popover/date_input.js
rename to src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
index 5ee1fa1680b..34a15197a00 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_input.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
@@ -11,18 +11,18 @@ import {
toRelativeString,
} from './date_modes';
-export function DateInput({ value, roundUp, onChange }) {
+export function DatePopoverContent({ value, roundUp, onValueChange }) {
const onTabClick = (selectedTab) => {
switch(selectedTab.id) {
case DATE_MODES.ABSOLUTE:
- onChange(toAbsoluteString(value, roundUp));
+ onValueChange(toAbsoluteString(value, roundUp));
break;
case DATE_MODES.RELATIVE:
- onChange(toRelativeString(value));
+ onValueChange(toRelativeString(value));
break;
case DATE_MODES.NOW:
- onChange('now');
+ onValueChange('now');
break;
}
};
@@ -64,12 +64,12 @@ export function DateInput({ value, roundUp, onChange }) {
);
}
-DateInput.propTypes = {
+DatePopoverContent.propTypes = {
value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
+ onValueChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool,
};
-DateInput.defaultProps = {
+DatePopoverContent.defaultProps = {
roundUp: false,
};
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 f1a7fb5c999..34b87307a06 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
@@ -26,7 +26,7 @@ import { prettyDuration } from './pretty_duration';
import dateMath from '@elastic/datemath';
import { QuickSelectPopover } from './quick_select_popover/quick_select_popover';
-import { DateButton } from './date_popover/date_button';
+import { DatePopoverButton } from './date_popover/date_popover_button';
import { EuiDatePickerRange } from '../date_picker_range';
import { EuiFormControlLayout } from '../../form';
@@ -117,56 +117,53 @@ export class EuiSuperDatePicker extends Component {
isInvalid,
} = this.state;
- let prettyDurationDateRange;
if (!this.state.isEditMode) {
- prettyDurationDateRange = (
-
-
+ return (
+ }
+ endDateControl={
}
+ >
+
+ {prettyDuration(from, to, this.props.commonlyUsedRanges, this.props.dateFormat)}
+
Show dates
-
+
);
}
- // Why isn't prettyDurationDateRange just returned and instead passed as a child to EuiDatePickerRange?
- // Need classes provided by EuiDatePickerRange for consistent view and
- // EuiDatePickerRange does not render startDateControl of endDateControl when children are provided.
return (
}
endDateControl={
-
}
- >
- {prettyDurationDateRange}
-
+ />
);
}
From 08fad42db32d4ba54c5b9197da9f66221bc9698b Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 10:39:20 -0700
Subject: [PATCH 10/37] relative
---
.../date_popover/date_popover_button.js | 9 +-
.../date_popover/date_popover_content.js | 27 +++--
.../date_popover/relative.js | 105 ++++++++++++++++++
.../super_date_picker/super_date_picker.js | 6 +-
4 files changed, 135 insertions(+), 12 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/date_popover/relative.js
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index 2c2388bf7aa..f0ee4276bda 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -12,7 +12,8 @@ export class DatePopoverButton extends Component {
isInvalid: PropTypes.bool,
needsUpdating: PropTypes.bool,
value: PropTypes.string.isRequired,
- onValueChange: PropTypes.func,
+ onChange: PropTypes.func,
+ dateFormat: PropTypes.string.isRequired,
roundUp: PropTypes.bool,
}
@@ -40,7 +41,8 @@ export class DatePopoverButton extends Component {
value,
buttonProps,
roundUp,
- onValueChange,
+ onChange,
+ dateFormat,
...rest
} = this.props;
@@ -86,7 +88,8 @@ export class DatePopoverButton extends Component {
);
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
index 34a15197a00..e18c404dc1d 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
@@ -3,6 +3,9 @@ import PropTypes from 'prop-types';
import React from 'react';
import { EuiTabbedContent } from '../../../tabs';
+import { EuiText } from '../../../text';
+
+import { Relative } from './relative';
import {
getDateMode,
@@ -11,18 +14,18 @@ import {
toRelativeString,
} from './date_modes';
-export function DatePopoverContent({ value, roundUp, onValueChange }) {
+export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
const onTabClick = (selectedTab) => {
switch(selectedTab.id) {
case DATE_MODES.ABSOLUTE:
- onValueChange(toAbsoluteString(value, roundUp));
+ onChange(toAbsoluteString(value, roundUp));
break;
case DATE_MODES.RELATIVE:
- onValueChange(toRelativeString(value));
+ onChange(toRelativeString(value));
break;
case DATE_MODES.NOW:
- onValueChange('now');
+ onChange('now');
break;
}
};
@@ -40,14 +43,23 @@ export function DatePopoverContent({ value, roundUp, onValueChange }) {
id: DATE_MODES.RELATIVE,
name: 'Relative',
content: (
- relative: {value}
+
),
},
{
id: DATE_MODES.NOW,
name: 'Now',
content: (
- now: {value}
+
+
+ Setting the time to "Now" means that on every refresh
+ this time will be set to the time of the refresh.
+
+
),
}
];
@@ -66,8 +78,9 @@ export function DatePopoverContent({ value, roundUp, onValueChange }) {
DatePopoverContent.propTypes = {
value: PropTypes.string.isRequired,
- onValueChange: PropTypes.func.isRequired,
+ onChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool,
+ dateFormat: PropTypes.string.isRequired,
};
DatePopoverContent.defaultProps = {
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative.js b/src/components/date_picker/super_date_picker/date_popover/relative.js
new file mode 100644
index 00000000000..51cbce86698
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/date_popover/relative.js
@@ -0,0 +1,105 @@
+
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import dateMath from '@elastic/datemath';
+
+import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
+import {
+ EuiForm,
+ EuiFormRow,
+ EuiSelect,
+ EuiFieldNumber,
+ EuiFieldText,
+ EuiSwitch
+} from '../../../form';
+
+import { timeUnits } from '../time_units';
+import { relativeOptions } from './relative_options';
+import { parseRelativeParts, toRelativeStringFromParts } from './relative_utils';
+
+export class Relative extends Component {
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ ...parseRelativeParts(this.props.value),
+ };
+ }
+
+ static getDerivedStateFromProps = (nextProps) => {
+ return {
+ ...parseRelativeParts(nextProps.value),
+ };
+ }
+
+ onCountChange = (evt) => {
+ const sanitizedValue = parseInt(evt.target.value, 10);
+ this.setState({
+ count: isNaN(sanitizedValue) ? '' : sanitizedValue,
+ }, this.handleChange);
+ }
+
+ onUnitChange = (evt) => {
+ this.setState({
+ unit: evt.target.value,
+ }, this.handleChange);
+ }
+
+ onRoundChange = (evt) => {
+ this.setState({
+ round: evt.target.checked,
+ }, this.handleChange);
+ };
+
+ handleChange = () => {
+ if (this.state.count === '') {
+ return;
+ }
+ this.props.onChange(toRelativeStringFromParts(this.state));
+ }
+
+ render() {
+ const formatedValue = dateMath.parse(this.props.value).format(this.props.dateFormat);
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+Relative.propTypes = {
+ dateFormat: PropTypes.string.isRequired,
+ value: PropTypes.string.isRequired,
+ onChange: PropTypes.func.isRequired,
+};
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 34b87307a06..8e6396aea16 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
@@ -149,8 +149,9 @@ export class EuiSuperDatePicker extends Component {
position="start"
needsUpdating={hasChanged}
isInvalid={isInvalid}
- onValueChange={this.setFrom}
+ onChange={this.setFrom}
value={from}
+ dateFormat={this.props.dateFormat}
/>
}
endDateControl={
@@ -158,8 +159,9 @@ export class EuiSuperDatePicker extends Component {
position="end"
needsUpdating={hasChanged}
isInvalid={isInvalid}
- onValueChange={this.setTo}
+ onChange={this.setTo}
value={to}
+ dateFormat={this.props.dateFormat}
roundUp
/>
}
From 4ee30fcd7dbff37077a0681e7fa6529a9b8a352d Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 12:26:41 -0700
Subject: [PATCH 11/37] absolute tab
---
.../absolute_tab.js} | 25 ++++++++-----------
.../date_popover/date_popover_button.js | 3 ++-
.../date_popover/date_popover_content.js | 12 ++++++---
.../{relative.js => relative_tab.js} | 4 +--
.../super_date_picker/pretty_duration.js | 1 -
.../super_date_picker/super_date_picker.js | 17 +++++--------
6 files changed, 30 insertions(+), 32 deletions(-)
rename src/components/date_picker/super_date_picker/{absolute_form.js => date_popover/absolute_tab.js} (81%)
rename src/components/date_picker/super_date_picker/date_popover/{relative.js => relative_tab.js} (97%)
diff --git a/src/components/date_picker/super_date_picker/absolute_form.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
similarity index 81%
rename from src/components/date_picker/super_date_picker/absolute_form.js
rename to src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
index 90497289357..4cf60865a91 100644
--- a/src/components/date_picker/super_date_picker/absolute_form.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
@@ -1,28 +1,24 @@
-
import PropTypes from 'prop-types';
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import moment from 'moment';
-import dateMath from '@kbn/datemath';
-
-import {
- EuiDatePicker,
- EuiFieldText,
- EuiFormRow,
-} from '@elastic/eui';
+import dateMath from '@elastic/datemath';
const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
+import { EuiDatePicker } from '../../date_picker';
+import { EuiFormRow, EuiFieldText } from '../../../form';
+
const toMoment = (value, roundUp) => {
const valueAsMoment = dateMath.parse(value, { roundUp });
return {
- value: valueAsMoment,
+ valueAsMoment,
textInputValue: valueAsMoment.format(INPUT_DATE_FORMAT)
};
};
-export class AbsoluteForm extends Component {
+export class AbsoluteTab extends Component {
constructor(props) {
super(props);
@@ -58,7 +54,7 @@ export class AbsoluteForm extends Component {
render() {
return (
-
+
-
+
);
}
}
-AbsoluteForm.propTypes = {
+AbsoluteTab.propTypes = {
+ dateFormat: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
roundUp: PropTypes.bool.isRequired,
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index f0ee4276bda..e5bbfe33f2a 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -4,6 +4,7 @@ import classNames from 'classnames';
import { EuiPopover } from '../../../popover';
+import { formatTimeString } from '../pretty_duration';
import { DatePopoverContent } from './date_popover_content';
export class DatePopoverButton extends Component {
@@ -71,7 +72,7 @@ export class DatePopoverButton extends Component {
title={title}
{...buttonProps}
>
- {value}
+ {formatTimeString(value, dateFormat)}
);
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
index e18c404dc1d..b16ad706c57 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
@@ -5,7 +5,8 @@ import React from 'react';
import { EuiTabbedContent } from '../../../tabs';
import { EuiText } from '../../../text';
-import { Relative } from './relative';
+import { AbsoluteTab } from './absolute_tab';
+import { RelativeTab } from './relative_tab';
import {
getDateMode,
@@ -36,14 +37,19 @@ export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
id: DATE_MODES.ABSOLUTE,
name: 'Absolute',
content: (
- absolute: {value}
+
),
},
{
id: DATE_MODES.RELATIVE,
name: 'Relative',
content: (
-
+ onClick={this.toggleEditMode}
+ >
Show dates
@@ -170,21 +169,17 @@ export class EuiSuperDatePicker extends Component {
}
renderUpdateButton = () => {
- const color = this.state.hasChanged ? 'secondary' : 'primary';
- const icon = this.state.hasChanged ? 'kqlFunction' : 'refresh';
- let text = this.state.hasChanged ? 'Update' : 'Refresh';
-
return (
- {text}
+ {this.state.hasChanged ? 'Update' : 'Refresh'}
);
}
From 9734df44a5b670bca3e8096bc0ffe98c09f04ec4 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 12:44:01 -0700
Subject: [PATCH 12/37] implement step forward and step backward
---
.../quick_select_popover/quick_select.js | 41 ++++++++++++++++++-
.../quick_select_popover.js | 5 ++-
.../super_date_picker/super_date_picker.js | 22 ++--------
3 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index 878ca227d67..d57e1b5d885 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -1,6 +1,8 @@
import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
+import moment from 'moment';
+import dateMath from '@elastic/datemath';
import { EuiButton, EuiButtonIcon } from '../../../button';
import { EuiFlexGroup, EuiFlexItem } from '../../../flex';
@@ -70,6 +72,31 @@ export class QuickSelect extends Component {
});
}
+ getBounds = () => {
+ return {
+ min: dateMath.parse(this.props.from),
+ max: dateMath.parse(this.props.to, { roundUp: true }),
+ };
+ }
+
+ stepForward = () => {
+ const { min, max } = this.getBounds();
+ const diff = max.diff(min);
+ this.props.applyTime({
+ from: moment(max).add(1, 'ms').toISOString(),
+ to: moment(max).add(diff + 1, 'ms').toISOString(),
+ });
+ }
+
+ stepBackward = () => {
+ const { min, max } = this.getBounds();
+ const diff = max.diff(min);
+ this.props.applyTime({
+ from: moment(min).subtract(diff + 1, 'ms').toISOString(),
+ to: moment(min).subtract(1, 'ms').toISOString(),
+ });
+ }
+
render() {
return (
@@ -79,12 +106,20 @@ export class QuickSelect extends Component {
-
+
-
+
@@ -140,4 +175,6 @@ export class QuickSelect extends Component {
QuickSelect.propTypes = {
applyTime: PropTypes.func.isRequired,
+ from: PropTypes.string.isRequired,
+ to: PropTypes.string.isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 65c67586286..55b891ef339 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -71,7 +71,8 @@ export class QuickSelectPopover extends Component {
{
- return calculateBounds({ from: this.state.from, to: this.state.to });
- }
-
- stepForward = () => {
- this.setTime(timeNavigation.stepForward(this.getBounds()));
- }
-
- stepBackward = () => {
- this.setTime(timeNavigation.stepBackward(this.getBounds()));
- }*/
-
applyTime = () => {
this.props.onTimeChange({ from: this.state.from, to: this.state.to });
}
@@ -188,8 +172,8 @@ export class EuiSuperDatePicker extends Component {
const quickSelect = (
Date: Thu, 6 Dec 2018 13:52:52 -0700
Subject: [PATCH 13/37] add data-test-subjs needed for existing kibana
functional tests
---
.../super_date_picker/date_popover/absolute_tab.js | 1 +
.../super_date_picker/date_popover/date_popover_button.js | 1 +
.../super_date_picker/date_popover/date_popover_content.js | 3 +++
.../quick_select_popover/commonly_used.js | 7 ++++++-
.../quick_select_popover/quick_select_popover.js | 6 +++++-
.../quick_select_popover/refresh_interval.js | 3 +++
.../date_picker/super_date_picker/super_date_picker.js | 2 ++
7 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
index 4cf60865a91..cabf2b4dfd9 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
@@ -71,6 +71,7 @@ export class AbsoluteTab extends Component {
isInvalid={this.state.isTextInvalid}
value={this.state.textInputValue}
onChange={this.handleTextChange}
+ data-test-subj={`superDatePickerAbsoluteDateInput`}
/>
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index e5bbfe33f2a..83b933ae9c0 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -70,6 +70,7 @@ export class DatePopoverButton extends Component {
onClick={this.togglePopover}
className={classes}
title={title}
+ data-test-subj={`superDatePicker${this.props.position}DatePopoverButton`}
{...buttonProps}
>
{formatTimeString(value, dateFormat)}
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
index b16ad706c57..f38660dbda1 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
@@ -44,6 +44,7 @@ export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
roundUp={roundUp}
/>
),
+ 'data-test-subj': 'superDatePickerAbsoluteTab',
},
{
id: DATE_MODES.RELATIVE,
@@ -55,6 +56,7 @@ export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
onChange={onChange}
/>
),
+ 'data-test-subj': 'superDatePickerRelativeTab',
},
{
id: DATE_MODES.NOW,
@@ -67,6 +69,7 @@ export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
),
+ 'data-test-subj': 'superDatePickerNowTab',
}
];
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
index 64ae8961180..f7330ab6861 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
@@ -17,7 +17,12 @@ export function CommonlyUsed({ applyTime, commonlyUsedRanges }) {
};
return (
- {label}
+
+ {label}
+
);
});
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 55b891ef339..88ceadf2d9c 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -54,6 +54,7 @@ export class QuickSelectPopover extends Component {
size="xs"
iconType="arrowDown"
iconSide="right"
+ data-test-subj="superDatePickerToggleQuickMenuButton"
>
@@ -68,7 +69,10 @@ export class QuickSelectPopover extends Component {
anchorPosition="downLeft"
ownFocus
>
-
+
@@ -108,6 +109,7 @@ export class RefreshInterval extends Component {
value={this.state.units}
options={refreshUnitsOptions}
onChange={this.onUnitsChange}
+ data-test-subj="superDatePickerRefreshIntervalUnitsSelect"
/>
@@ -119,6 +121,7 @@ export class RefreshInterval extends Component {
onClick={this.toogleRefresh}
style={{ minWidth: 90 }}
disabled={this.state.value === '' || this.state.value <= 0}
+ data-test-subj="superDatePickerToggleRefreshButton"
>
{this.props.isPaused ? 'Start' : 'Stop'}
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 7d314431de8..a17d6857e33 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
@@ -115,6 +115,7 @@ export class EuiSuperDatePicker extends Component {
size="xs"
style={{ flexGrow: 0 }}
onClick={this.toggleEditMode}
+ data-test-subj="superDatePickerShowDatesButton"
>
Show dates
@@ -162,6 +163,7 @@ export class EuiSuperDatePicker extends Component {
textProps={{ className: 'euiSuperDatePicker__updateButtonText' }}
disabled={this.state.isInvalid}
onClick={this.applyTime}
+ data-test-subj="superDatePickerApplyTimeButton"
>
{this.state.hasChanged ? 'Update' : 'Refresh'}
From 78583b66094d1b6492931dcd05a56470a3cb6794 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 14:07:05 -0700
Subject: [PATCH 14/37] remove global date picker pattern, add comments about
EuiSuperDatePicker props
---
src-docs/src/theme_dark.scss | 1 -
src-docs/src/theme_k6_dark.scss | 1 -
src-docs/src/theme_k6_light.scss | 1 -
src-docs/src/theme_light.scss | 1 -
.../date_picker/_global_date_picker.scss | 97 ---
.../views/date_picker/date_picker_example.js | 27 +-
.../views/date_picker/global_date_picker.js | 566 ------------------
.../super_date_picker/super_date_picker.js | 19 +
8 files changed, 21 insertions(+), 692 deletions(-)
delete mode 100644 src-docs/src/views/date_picker/_global_date_picker.scss
delete mode 100644 src-docs/src/views/date_picker/global_date_picker.js
diff --git a/src-docs/src/theme_dark.scss b/src-docs/src/theme_dark.scss
index 97d4ef0207c..f09a1aede5c 100644
--- a/src-docs/src/theme_dark.scss
+++ b/src-docs/src/theme_dark.scss
@@ -1,4 +1,3 @@
@import '../../src/theme_dark';
@import './components/guide_components';
@import './views/header/global_filter_group';
-@import './views/date_picker/global_date_picker';
diff --git a/src-docs/src/theme_k6_dark.scss b/src-docs/src/theme_k6_dark.scss
index a3738416b1d..99e708a00f1 100644
--- a/src-docs/src/theme_k6_dark.scss
+++ b/src-docs/src/theme_k6_dark.scss
@@ -1,4 +1,3 @@
@import '../../src/theme_k6_dark';
@import './components/guide_components';
@import './views/header/global_filter_group';
-@import './views/date_picker/global_date_picker';
diff --git a/src-docs/src/theme_k6_light.scss b/src-docs/src/theme_k6_light.scss
index 6fe9d55fe4b..544617f335d 100644
--- a/src-docs/src/theme_k6_light.scss
+++ b/src-docs/src/theme_k6_light.scss
@@ -1,4 +1,3 @@
@import '../../src/theme_k6_light';
@import './components/guide_components';
@import './views/header/global_filter_group';
-@import './views/date_picker/global_date_picker';
diff --git a/src-docs/src/theme_light.scss b/src-docs/src/theme_light.scss
index bd607c9114f..782fc422f63 100644
--- a/src-docs/src/theme_light.scss
+++ b/src-docs/src/theme_light.scss
@@ -1,4 +1,3 @@
@import '../../src/theme_light';
@import './components/guide_components';
@import './views/header/global_filter_group';
-@import './views/date_picker/global_date_picker';
diff --git a/src-docs/src/views/date_picker/_global_date_picker.scss b/src-docs/src/views/date_picker/_global_date_picker.scss
deleted file mode 100644
index d522ce46bcb..00000000000
--- a/src-docs/src/views/date_picker/_global_date_picker.scss
+++ /dev/null
@@ -1,97 +0,0 @@
-//// GLOBAL Date picker
-
-// sass-lint:disable no-important
-.euiGlobalDatePicker__quickSelectButton {
- // Override prepend border since button already lives inside another prepend
- border-right: none !important;
-
- .euiGlobalDatePicker__quickSelectButtonText {
- // Override specificity from universal and sibiling selectors
- margin-right: $euiSizeXS !important;
- }
-}
-
-.euiGlobalDatePicker.euiFormControlLayout {
- max-width: 480px;
-
- > .euiFormControlLayout__childrenWrapper {
- flex: 1 1 100%;
- overflow: hidden;
-
- > .euiDatePickerRange {
- max-width: none;
- width: auto;
-
- // sass-lint:disable nesting-depth
- .euiPopover__anchor {
- display: block;
- }
- }
- }
-}
-
-.euiGlobalDatePicker__dateButton {
- @include euiFormControlText;
- display: block;
- width: 100%;
- padding: 0 $euiSizeS;
- line-height: $euiFormControlHeight - 2px;
- height: $euiFormControlHeight - 2px;
- word-break: break-all;
- transition: background $euiAnimSpeedFast ease-in;
-
- $backgroundColor: tintOrShade($euiColorSuccess, 90%, 70%);
- $textColor: makeHighContrastColor($euiColorSuccess, $backgroundColor);
-
- &-isSelected,
- &-needsUpdating,
- &:hover,
- &:focus {
- background-color: $backgroundColor;
- }
-
- &-needsUpdating {
- color: $textColor;
- }
-
- &-isInvalid {
- $backgroundColor: tintOrShade($euiColorDanger, 90%, 70%);
- $textColor: makeHighContrastColor($euiColorDanger, $backgroundColor);
- background-color: $backgroundColor;
- color: $textColor;
- }
-
- .euiFormControlLayout__prepend {
- border: none;
- }
-}
-
-.euiGlobalDatePicker__dateButton--start {
- text-align: right;
-}
-
-.euiGlobalDatePicker__dateButton--end {
- text-align: left;
-}
-
-.euiGlobalDatePicker__updateButton {
- // Just wide enough for all 3 states
- min-width: $euiButtonMinWidth + ($euiSizeXS * 1.5);
-}
-
-.euiGlobalDatePicker__popoverSection {
- @include euiScrollBar;
- max-height: $euiSizeM * 11;
- overflow: hidden;
- overflow-y: auto;
-}
-
-@include euiBreakpoint('xs', 's') {
- .euiGlobalDatePicker__updateButton {
- min-width: 0;
-
- .euiGlobalDatePicker__updateButtonText {
- display: none;
- }
- }
-}
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 7235470eee8..94c6ea9078d 100644
--- a/src-docs/src/views/date_picker/date_picker_example.js
+++ b/src-docs/src/views/date_picker/date_picker_example.js
@@ -11,7 +11,7 @@ import {
EuiLink,
EuiDatePicker,
EuiDatePickerRange,
- EuiCallOut,
+ EuiSuperDatePicker,
} from '../../../../src/components';
import DatePicker from './date_picker';
@@ -62,10 +62,6 @@ import SuperDatePicker from './super_date_picker';
const superDatePickerSource = require('!!raw-loader!./super_date_picker');
const superDatePickerHtml = renderToHtml(SuperDatePicker);
-import GlobalDatePicker from './global_date_picker';
-const globalDatePickerSource = require('!!raw-loader!./global_date_picker');
-const globalDatePickerHtml = renderToHtml(GlobalDatePicker);
-
export const DatePickerExample = {
title: 'DatePicker',
sections: [{
@@ -284,25 +280,6 @@ export const DatePickerExample = {
),
demo:
,
- }, {
- title: 'Global date picker',
- source: [{
- type: GuideSectionTypes.JS,
- code: globalDatePickerSource,
- }, {
- type: GuideSectionTypes.HTML,
- code: globalDatePickerHtml,
- }],
- text: (
-
-
-
- This documents a visual pattern for the eventual replacement of Kibana's
- global date/time picker. It uses all EUI components with some custom styles.
-
-
-
- ),
- demo:
,
+ props: { EuiSuperDatePicker },
}],
};
diff --git a/src-docs/src/views/date_picker/global_date_picker.js b/src-docs/src/views/date_picker/global_date_picker.js
deleted file mode 100644
index 13930214175..00000000000
--- a/src-docs/src/views/date_picker/global_date_picker.js
+++ /dev/null
@@ -1,566 +0,0 @@
-
-import React, {
- Component, Fragment,
-} from 'react';
-import PropTypes from 'prop-types';
-
-import moment from 'moment';
-import classNames from 'classnames';
-
-import {
- EuiDatePicker,
- EuiDatePickerRange,
- EuiFormControlLayout,
- EuiButtonEmpty,
- EuiIcon,
- EuiLink, EuiTitle, EuiFlexGrid, EuiFlexItem,
- EuiPopover,
- EuiSpacer,
- EuiText,
- EuiHorizontalRule,
- EuiFlexGroup,
- EuiFormRow,
- EuiSelect,
- EuiFieldNumber,
- EuiButton,
- EuiTabbedContent,
- EuiForm,
- EuiSwitch,
- EuiToolTip,
- EuiFieldText,
- EuiButtonIcon,
-} from '../../../../src/components';
-
-const commonDates = [
- 'Today', 'Yesterday', 'This week', 'Week to date', 'This month', 'Month to date', 'This year', 'Year to date',
-];
-
-const relativeSelectOptions = [
- { text: 'Seconds ago', value: 'string:s' },
- { text: 'Minutes ago', value: 'string:m' },
- { text: 'Hours ago', value: 'string:h' },
- { text: 'Days ago', value: 'string:d' },
- { text: 'Weeks ago', value: 'string:w' },
- { text: 'Months ago', value: 'string:M' },
- { text: 'Years ago', value: 'string:y' },
- { text: 'Seconds from now', value: 'string:s+' },
- { text: 'Minutes from now', value: 'string:m+' },
- { text: 'Hours from now', value: 'string:h+' },
- { text: 'Days from now', value: 'string:d+' },
- { text: 'Weeks from now', value: 'string:w+' },
- { text: 'Months from now', value: 'string:M+' },
- { text: 'Years from now', value: 'string:y+' },
-];
-
-class GlobalDatePopover extends Component {
- constructor(props) {
- super(props);
-
- this.tabs = [{
- id: 'absolute',
- name: 'Absolute',
- content: (
-
-
-
-
-
-
- ),
- }, {
- id: 'relative',
- name: 'Relative',
- content: (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ),
- }, {
- id: 'now',
- name: 'Now',
- content: (
-
-
- Setting the time to "Now" means that on every refresh
- this time will be set to the time of the refresh.
-
-
- ),
- }];
-
- this.state = {
- selectedTab: this.tabs[0],
- };
- }
-
- onTabClick = (selectedTab) => {
- this.setState({ selectedTab });
- };
-
- render() {
- return (
-
- );
- }
-}
-
-// eslint-disable-next-line react/no-multi-comp
-class GlobalDateButton extends Component {
- static propTypes = {
- position: PropTypes.oneOf(['start', 'end']),
- isInvalid: PropTypes.bool,
- needsUpdating: PropTypes.bool,
- buttonOnly: PropTypes.bool,
- date: PropTypes.string,
- }
-
- constructor(props) {
- super(props);
-
- this.state = {
- isPopoverOpen: false,
- };
- }
-
- togglePopover = () => {
- this.setState({
- isPopoverOpen: !this.state.isPopoverOpen,
- });
- }
-
- closePopover = () => {
- this.setState({
- isPopoverOpen: false,
- });
- }
-
- render() {
- const {
- position,
- isInvalid,
- needsUpdating,
- date,
- buttonProps,
- buttonOnly,
- ...rest
- } = this.props;
-
- const {
- isPopoverOpen,
- } = this.state;
-
- const classes = classNames([
- 'euiGlobalDatePicker__dateButton',
- `euiGlobalDatePicker__dateButton--${position}`,
- {
- 'euiGlobalDatePicker__dateButton-isSelected': isPopoverOpen,
- 'euiGlobalDatePicker__dateButton-isInvalid': isInvalid,
- 'euiGlobalDatePicker__dateButton-needsUpdating': needsUpdating
- }
- ]);
-
- let title = date;
- if (isInvalid) {
- title = `Invalid date: ${title}`;
- } else if (needsUpdating) {
- title = `Update needed: ${title}`;
- }
-
- const button = (
-
- {date}
-
- );
-
- return buttonOnly ? button : (
-
-
-
- );
- }
-}
-
-// eslint-disable-next-line react/no-multi-comp
-export default class extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- startDate: moment().format('MMM DD YYYY h:mm:ss.SSS'),
- endDate: moment().add(11, 'd').format('MMM DD YYYY hh:mm:ss.SSS'),
- isPopoverOpen: false,
- showPrettyFormat: false,
- showNeedsUpdate: false,
- isUpdating: false,
- timerIsOn: false,
- recentlyUsed: [
- ['11/25/2017 00:00 AM', '11/25/2017 11:59 PM'],
- ['3 hours ago', '4 minutes ago'],
- 'Last 6 months',
- ['06/11/2017 06:11 AM', '06/11/2017 06:11 PM'],
- ],
- };
- }
-
- setTootipRef = node => (this.tooltip = node);
-
- showTooltip = () => this.tooltip.showToolTip();
- hideTooltip = () => this.tooltip.hideToolTip();
-
- togglePopover = (e) => {
- // HACK TODO:
- // this works because react listens to all events at the
- // document level, and you need to interact with the native
- // event's propagation to short-circuit outside click handler
- // see also: https://stackoverflow.com/a/24421834
- e.nativeEvent.stopImmediatePropagation();
-
- this.setState(prevState => ({
- isPopoverOpen: !prevState.isPopoverOpen,
- }));
- }
-
- togglePrettyFormat = () => {
- this.setState(prevState => ({
- showPrettyFormat: !prevState.showPrettyFormat,
- }));
- }
-
- toggleNeedsUpdate = () => {
- this.setState(prevState => {
-
- if (!prevState.showNeedsUpdate) {
- clearTimeout(this.tooltipTimeout);
- this.showTooltip();
- this.tooltipTimeout = setTimeout(() => {
- this.hideTooltip();
- }, 10000);
- }
-
- return ({
- showNeedsUpdate: !prevState.showNeedsUpdate,
- });
- });
- }
-
- closePopover = () => {
- this.setState({
- isPopoverOpen: false,
- });
- }
-
- toggleTimer = () => {
- this.setState(prevState => ({
- timerIsOn: !prevState.timerIsOn,
- }));
- }
-
- toggleIsUpdating = () => {
- this.setState(prevState => ({
- isUpdating: !prevState.isUpdating,
- }));
- }
-
-
- render() {
- const quickSelectButton = (
-
-
-
- );
-
- const commonlyUsed = this.renderCommonlyUsed(commonDates);
- const recentlyUsed = this.renderRecentlyUsed(this.state.recentlyUsed);
-
- const quickSelectPopover = (
-
-
- {this.renderQuickSelect()}
-
- {commonlyUsed}
-
- {recentlyUsed}
-
- {this.renderTimer()}
-
-
- );
-
- return (
-
-
-
-
-
-
-
-
-
-
- }
- endDateControl={
-
- }
- >
- {this.state.showPrettyFormat &&
-
-
- Show dates
-
- }
-
-
-
-
- {this.renderUpdateButton()}
-
-
-
- );
- }
-
- renderUpdateButton = () => {
- const color = this.state.showNeedsUpdate ? 'secondary' : 'primary';
- const icon = this.state.showNeedsUpdate ? 'kqlFunction' : 'refresh';
- let text = this.state.showNeedsUpdate ? 'Update' : 'Refresh';
-
- if (this.state.isUpdating) {
- text = 'Updating';
- }
-
- return (
-
-
- {text}
-
-
- );
- }
-
- renderQuickSelect = () => {
- const firstOptions = [
- { value: 'last', text: 'Last' },
- { value: 'previous', text: 'Previous' },
- ];
-
- const lastOptions = [
- { value: 'seconds', text: 'seconds' },
- { value: 'minutes', text: 'minutes' },
- { value: 'hours', text: 'hours' },
- { value: 'days', text: 'days' },
- { value: 'weeks', text: 'weeks' },
- { value: 'months', text: 'months' },
- { value: 'years', text: 'years' },
- ];
-
- return (
-
-
-
- Quick select
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Apply
-
-
-
-
- );
- }
-
- renderCommonlyUsed = (commonDates) => {
- const links = commonDates.map((date) => {
- return (
-
{date}
- );
- });
-
- return (
-
- Commonly used
-
-
-
- {links}
-
-
-
- );
- }
-
- renderRecentlyUsed = (recentDates) => {
- const links = recentDates.map((date) => {
- let dateRange;
- if (typeof date !== 'string') {
- dateRange = `${date[0]} – ${date[1]}`;
- }
-
- return (
-
{dateRange || date}
- );
- });
-
- return (
-
- Recently used date ranges
-
-
-
- {links}
-
-
-
- );
- }
-
- renderTimer = () => {
- const lastOptions = [
- { value: 'minutes', text: 'minutes' },
- { value: 'hours', text: 'hours' },
- ];
-
- return (
-
- Refresh every
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {this.state.timerIsOn ? 'Stop' : 'Start'}
-
-
-
-
-
- );
- }
-
-}
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 a17d6857e33..6b2c20d36ae 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
@@ -206,15 +206,34 @@ export class EuiSuperDatePicker extends Component {
}
EuiSuperDatePicker.propTypes = {
+ /**
+ * String as either datemath (e.g.: now, now-15m, now-15m/m) or
+ * absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ'
+ */
from: 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'
+ */
to: PropTypes.string,
onTimeChange: PropTypes.func.isRequired,
isPaused: PropTypes.bool,
+ /**
+ * Refresh interval in milliseconds
+ */
refreshInterval: PropTypes.number,
onRefreshChange: PropTypes.func.isRequired,
+ /**
+ * 'from' and 'to' 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,
+ /**
+ * 'from' and 'to' 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),
};
From c2fd0e8c1dccd1df05a9c93f6f830c793a830c56 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 14:11:40 -0700
Subject: [PATCH 15/37] change log
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 37ad1815de2..d70ec37dce9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)
-No public interface changes since `5.3.0`.
+- Added `EuiSuperDatePicker` component ([#1351](https://github.com/elastic/eui/pull/1351))
## [`5.3.0`](https://github.com/elastic/eui/tree/v5.3.0)
From 3e69d699dcb053339303fc4be128df4456e2ba4e Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 6 Dec 2018 14:21:25 -0700
Subject: [PATCH 16/37] remove kibana file header
---
.../super_date_picker/super_date_picker.js | 18 ------------------
1 file changed, 18 deletions(-)
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 6b2c20d36ae..3cc4ee7f51a 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
@@ -1,21 +1,3 @@
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
From 48294f59ad34b9f6eb2603b1a285ecea92855c97 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 09:49:47 -0700
Subject: [PATCH 17/37] only show pretty duration for commonly used ranges and
relative to now, now to now isInvalid, recenlty selected in reverse order
---
.../views/date_picker/super_date_picker.js | 2 +-
.../{date_popover => }/date_modes.js | 0
.../date_popover/date_popover_content.js | 2 +-
.../date_popover/relative_tab.js | 4 +-
.../super_date_picker/pretty_duration.js | 14 ++++
.../super_date_picker/pretty_duration.test.js | 76 ++++++++++++-------
.../{date_popover => }/relative_options.js | 0
.../{date_popover => }/relative_utils.js | 0
.../{date_popover => }/relative_utils.test.js | 0
.../super_date_picker/super_date_picker.js | 38 ++++++----
10 files changed, 92 insertions(+), 44 deletions(-)
rename src/components/date_picker/super_date_picker/{date_popover => }/date_modes.js (100%)
rename src/components/date_picker/super_date_picker/{date_popover => }/relative_options.js (100%)
rename src/components/date_picker/super_date_picker/{date_popover => }/relative_utils.js (100%)
rename src/components/date_picker/super_date_picker/{date_popover => }/relative_utils.test.js (100%)
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 6bf6ad66c7c..71458f619cd 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -17,7 +17,7 @@ export default class extends Component {
const isDuplicate = recentlyUsedRange.from === from && recentlyUsedRange.to === to;
return !isDuplicate;
});
- recentlyUsedRanges.push({ from, to });
+ recentlyUsedRanges.unshift({ from, to });
return {
from,
to,
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_modes.js b/src/components/date_picker/super_date_picker/date_modes.js
similarity index 100%
rename from src/components/date_picker/super_date_picker/date_popover/date_modes.js
rename to src/components/date_picker/super_date_picker/date_modes.js
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
index f38660dbda1..df2b5b88c26 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_content.js
@@ -13,7 +13,7 @@ import {
DATE_MODES,
toAbsoluteString,
toRelativeString,
-} from './date_modes';
+} from '../date_modes';
export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
index ad616a7f27c..3d001845a48 100644
--- a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
@@ -14,8 +14,8 @@ import {
} from '../../../form';
import { timeUnits } from '../time_units';
-import { relativeOptions } from './relative_options';
-import { parseRelativeParts, toRelativeStringFromParts } from './relative_utils';
+import { relativeOptions } from '../relative_options';
+import { parseRelativeParts, toRelativeStringFromParts } from '../relative_utils';
export class RelativeTab extends Component {
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index 2f3fbb9e6af..cd2680db477 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -2,6 +2,7 @@
import dateMath from '@elastic/datemath';
import moment from 'moment';
import { timeUnits } from './time_units';
+import { getDateMode, DATE_MODES } from './date_modes';
const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.sssZ';
@@ -50,3 +51,16 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
return cantLookup(timeFrom, timeTo, dateFormat);
}
+
+export function showPrettyDuration(timeFrom, timeTo, quickRanges = []) {
+ const matchingQuickRange = quickRanges.find(({ from: quickFrom, to: quickTo }) => {
+ return timeFrom === quickFrom && timeTo === quickTo;
+ });
+ if (matchingQuickRange) {
+ return true;
+ }
+
+ const fromDateMode = getDateMode(timeFrom);
+ const toDateMode = getDateMode(timeTo);
+ return fromDateMode === DATE_MODES.RELATIVE && toDateMode === DATE_MODES.NOW;
+}
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
index 9e4ea99c506..af960f18f3f 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.test.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -1,6 +1,6 @@
import moment from 'moment-timezone';
-import { prettyDuration } from './pretty_duration';
+import { prettyDuration, showPrettyDuration } from './pretty_duration';
moment.tz.setDefault('UTC');
const dateFormat = 'MMMM Do YYYY, HH:mm:ss.SSS';
@@ -12,33 +12,57 @@ const quickRanges = [
}
];
-test('quick range', () => {
- const timeFrom = 'now-15m';
- const timeTo = 'now';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('quick range 15 minutes custom display');
-});
+describe('prettyDuration', () => {
+ test('quick range', () => {
+ const timeFrom = 'now-15m';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('quick range 15 minutes custom display');
+ });
-test('last', () => {
- const timeFrom = 'now-1M';
- const timeTo = 'now';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M');
-});
+ test('last', () => {
+ const timeFrom = 'now-1M';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M');
+ });
-test('last that is rounded', () => {
- const timeFrom = 'now-1M/w';
- const timeTo = 'now';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M rounded to the week');
-});
+ test('last that is rounded', () => {
+ const timeFrom = 'now-1M/w';
+ const timeTo = 'now';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M rounded to the week');
+ });
-test('from is in past', () => {
- const timeFrom = 'now-17m';
- const timeTo = 'now-15m';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('~ 17 minutes ago to ~ 15 minutes ago');
+ test('from is in past', () => {
+ const timeFrom = 'now-17m';
+ const timeTo = 'now-15m';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('~ 17 minutes ago to ~ 15 minutes ago');
+ });
+
+ // TODO figure out timezone to get this working
+ //test('absolute dates', () => {
+ // const timeFrom = '2018-01-17T18:57:57.149Z';
+ // const timeTo = '2018-01-17T20:00:00.000Z';
+ // expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('January 17th 2018, 18:57:57.149 to January 17th 2018, 20:00:00.000');
+ //});
});
-// TODO figure out timezone to get this working
-//test('absolute dates', () => {
-// const timeFrom = '2018-01-17T18:57:57.149Z';
-// const timeTo = '2018-01-17T20:00:00.000Z';
-// expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('January 17th 2018, 18:57:57.149 to January 17th 2018, 20:00:00.000');
-//});
+describe('showPrettyDuration', () => {
+ test('should show pretty duration for quick range', () => {
+ expect(showPrettyDuration('now-15m', 'now', quickRanges)).toBe(true);
+ });
+
+ test('should show pretty duration for relative to now', () => {
+ expect(showPrettyDuration('now-17m', 'now', quickRanges)).toBe(true);
+ });
+
+ test('should not show pretty duration for relative to relative', () => {
+ expect(showPrettyDuration('now-17m', 'now-3m', quickRanges)).toBe(false);
+ });
+
+ test('should not show pretty duration for absolute to absolute', () => {
+ expect(showPrettyDuration('2018-01-17T18:57:57.149Z', '2018-01-17T20:00:00.000Z', quickRanges)).toBe(false);
+ });
+
+ test('should not show pretty duration for absolute to now', () => {
+ expect(showPrettyDuration('2018-01-17T18:57:57.149Z', 'now', quickRanges)).toBe(false);
+ });
+});
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_options.js b/src/components/date_picker/super_date_picker/relative_options.js
similarity index 100%
rename from src/components/date_picker/super_date_picker/date_popover/relative_options.js
rename to src/components/date_picker/super_date_picker/relative_options.js
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_utils.js b/src/components/date_picker/super_date_picker/relative_utils.js
similarity index 100%
rename from src/components/date_picker/super_date_picker/date_popover/relative_utils.js
rename to src/components/date_picker/super_date_picker/relative_utils.js
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js b/src/components/date_picker/super_date_picker/relative_utils.test.js
similarity index 100%
rename from src/components/date_picker/super_date_picker/date_popover/relative_utils.test.js
rename to src/components/date_picker/super_date_picker/relative_utils.test.js
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 3cc4ee7f51a..94892e92b3c 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
@@ -2,7 +2,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { commonlyUsedRangeShape, recentlyUsedRangeShape } from './types';
-import { prettyDuration } from './pretty_duration';
+import { prettyDuration, showPrettyDuration } from './pretty_duration';
import dateMath from '@elastic/datemath';
@@ -19,36 +19,46 @@ export class EuiSuperDatePicker extends Component {
constructor(props) {
super(props);
+ const {
+ from,
+ to,
+ commonlyUsedRanges
+ } = this.props;
+
this.state = {
- from: this.props.from,
- to: this.props.to,
+ from,
+ to,
isInvalid: false,
hasChanged: false,
- isEditMode: false,
+ showPrettyDuration: showPrettyDuration(from, to, commonlyUsedRanges),
};
}
static getDerivedStateFromProps = (nextProps) => {
+ const {
+ from,
+ to,
+ commonlyUsedRanges
+ } = nextProps;
+
return {
- from: nextProps.from,
- to: nextProps.to,
+ from,
+ to,
isInvalid: false,
- errorMessage: undefined,
hasChanged: false,
- isEditMode: false,
+ showPrettyDuration: showPrettyDuration(from, to, commonlyUsedRanges),
};
}
setTime = ({ from, to }) => {
const fromMoment = dateMath.parse(from);
const toMoment = dateMath.parse(to, { roundUp: true });
- const isInvalid = fromMoment.isAfter(toMoment);
+ const isInvalid = (from === 'now' && to === 'now') || fromMoment.isAfter(toMoment);
this.setState({
from,
to,
isInvalid,
- errorMessage: isInvalid ? 'Invalid time range, "from" must occur before "to"' : undefined,
hasChanged: true,
});
}
@@ -69,8 +79,8 @@ export class EuiSuperDatePicker extends Component {
this.props.onTimeChange({ from, to });
}
- toggleEditMode = () => {
- this.setState({ isEditMode: true });
+ hidePrettyDuration = () => {
+ this.setState({ showPrettyDuration: false });
}
renderDatePickerRange = () => {
@@ -81,7 +91,7 @@ export class EuiSuperDatePicker extends Component {
isInvalid,
} = this.state;
- if (!this.state.isEditMode) {
+ if (this.state.showPrettyDuration) {
return (
Show dates
From ebd53922c1bfbb8652c2404ab85aedb6d87ca66c Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 11:13:19 -0700
Subject: [PATCH 18/37] use full time unit name in pretty duration
---
.../super_date_picker/pretty_duration.js | 28 ++++++++++++-------
.../super_date_picker/pretty_duration.test.js | 6 ++--
.../super_date_picker/relative_utils.js | 15 ++++++----
.../super_date_picker/relative_utils.test.js | 6 ++--
.../super_date_picker/time_units.js | 1 -
5 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index cd2680db477..8ac5c060436 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -3,6 +3,7 @@ import dateMath from '@elastic/datemath';
import moment from 'moment';
import { timeUnits } from './time_units';
import { getDateMode, DATE_MODES } from './date_modes';
+import { parseRelativeParts } from './relative_utils';
const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.sssZ';
@@ -12,6 +13,12 @@ function cantLookup(timeFrom, timeTo, dateFormat) {
return `${displayFrom} to ${displayTo}`;
}
+function isRelativeToNow(timeFrom, timeTo) {
+ const fromDateMode = getDateMode(timeFrom);
+ const toDateMode = getDateMode(timeTo);
+ return fromDateMode === DATE_MODES.RELATIVE && toDateMode === DATE_MODES.NOW;
+}
+
export function formatTimeString(timeString, dateFormat, roundUp = false) {
const timeAsMoment = moment(timeString, ISO_FORMAT, true);
if (timeAsMoment.isValid()) {
@@ -38,13 +45,16 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
return matchingQuickRange.label;
}
- const fromParts = timeFrom.split('-');
- if (timeTo === 'now' && fromParts[0] === 'now' && fromParts[1]) {
- const rounded = fromParts[1].split('/');
- let text = `Last ${rounded[0]}`;
- if (rounded[1]) {
- const timeUnit = timeUnits[rounded[1]] ? timeUnits[rounded[1]] : rounded[1];
- text = `${text} rounded to the ${timeUnit}`;
+ if (isRelativeToNow(timeFrom, timeTo)) {
+ const relativeParts = parseRelativeParts(timeFrom);
+ let countTimeUnit = timeUnits[relativeParts.unit.substring(0, 1)];
+ if (relativeParts.count > 1) {
+ countTimeUnit += 's';
+ }
+ let text = `Last ${relativeParts.count} ${countTimeUnit}`;
+ if (relativeParts.round) {
+ const roundTimeUnit = timeUnits[relativeParts.roundUnit] ? timeUnits[relativeParts.roundUnit] : relativeParts.roundUnit;
+ text += ` rounded to the ${roundTimeUnit}`;
}
return text;
}
@@ -60,7 +70,5 @@ export function showPrettyDuration(timeFrom, timeTo, quickRanges = []) {
return true;
}
- const fromDateMode = getDateMode(timeFrom);
- const toDateMode = getDateMode(timeTo);
- return fromDateMode === DATE_MODES.RELATIVE && toDateMode === DATE_MODES.NOW;
+ return isRelativeToNow(timeFrom, timeTo);
}
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
index af960f18f3f..c1e6560f4f4 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.test.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -20,15 +20,15 @@ describe('prettyDuration', () => {
});
test('last', () => {
- const timeFrom = 'now-1M';
+ const timeFrom = 'now-16m';
const timeTo = 'now';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M');
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 16 minutes');
});
test('last that is rounded', () => {
const timeFrom = 'now-1M/w';
const timeTo = 'now';
- expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1M rounded to the week');
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1 month rounded to the week');
});
test('from is in past', () => {
diff --git a/src/components/date_picker/super_date_picker/relative_utils.js b/src/components/date_picker/super_date_picker/relative_utils.js
index c77fc35de07..096d6a65243 100644
--- a/src/components/date_picker/super_date_picker/relative_utils.js
+++ b/src/components/date_picker/super_date_picker/relative_utils.js
@@ -4,6 +4,8 @@ import moment from 'moment';
import _ from 'lodash';
import { relativeOptions } from './relative_options';
+const ROUND_DELIMETER = '/';
+
export function parseRelativeParts(value) {
const matches = _.isString(value) && value.match(/now(([\-\+])([0-9]+)([smhdwMy])(\/[smhdwMy])?)?/);
@@ -18,10 +20,12 @@ export function parseRelativeParts(value) {
}
if (count && unit) {
+ const isRounded = roundBy ? true : false;
return {
count: parseInt(count, 10),
unit: operator === '+' ? `${unit}+` : unit,
- round: roundBy ? true : false,
+ round: isRounded,
+ roundUnit: isRounded ? roundBy.replace(ROUND_DELIMETER, '') : undefined,
};
}
@@ -45,17 +49,16 @@ export function parseRelativeParts(value) {
export function toRelativeStringFromParts(relativeParts) {
const count = _.get(relativeParts, `count`, 0);
- const round = _.get(relativeParts, `round`, false);
+ const isRounded = _.get(relativeParts, `round`, false);
- if (count === 0 && !round) {
+ if (count === 0 && !isRounded) {
return 'now';
}
const matches = _.get(relativeParts, `unit`, 's').match(/([smhdwMy])(\+)?/);
const unit = matches[1];
const operator = matches && matches[2] ? matches[2] : '-';
+ const round = isRounded ? `${ROUND_DELIMETER}${unit}` : '';
- let result = `now${operator}${count}${unit}`;
- result += (round ? `/${unit}` : '');
- return result;
+ return `now${operator}${count}${unit}${round}`;
}
diff --git a/src/components/date_picker/super_date_picker/relative_utils.test.js b/src/components/date_picker/super_date_picker/relative_utils.test.js
index 8df1dbf074f..43fe7b048c9 100644
--- a/src/components/date_picker/super_date_picker/relative_utils.test.js
+++ b/src/components/date_picker/super_date_picker/relative_utils.test.js
@@ -27,7 +27,8 @@ describe('parseRelativeParts', () => {
expect(out).toEqual({
count: 2,
unit: 'h',
- round: true
+ round: true,
+ roundUnit: 'h',
});
});
@@ -36,7 +37,8 @@ describe('parseRelativeParts', () => {
expect(out).toEqual({
count: 10,
unit: 'm+',
- round: true
+ round: true,
+ roundUnit: 'm',
});
});
});
diff --git a/src/components/date_picker/super_date_picker/time_units.js b/src/components/date_picker/super_date_picker/time_units.js
index ce19b67f2b4..3ad61fca541 100644
--- a/src/components/date_picker/super_date_picker/time_units.js
+++ b/src/components/date_picker/super_date_picker/time_units.js
@@ -8,4 +8,3 @@ export const timeUnits = {
M: 'month',
y: 'year'
};
-
From 3a4aac096d3992f603afabd20c7a733d70236026 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 12:07:20 -0700
Subject: [PATCH 19/37] pass roundUp to formatTimeString to ensure date button
display is accurate, make onRefreshChange prop optional
---
.../super_date_picker/date_popover/date_popover_button.js | 2 +-
.../quick_select_popover/quick_select_popover.js | 2 +-
.../quick_select_popover/refresh_interval.js | 6 +++++-
.../date_picker/super_date_picker/super_date_picker.js | 5 ++++-
4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index 83b933ae9c0..3a05d99b516 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -73,7 +73,7 @@ export class DatePopoverButton extends Component {
data-test-subj={`superDatePicker${this.props.position}DatePopoverButton`}
{...buttonProps}
>
- {formatTimeString(value, dateFormat)}
+ {formatTimeString(value, dateFormat, roundUp)}
);
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 88ceadf2d9c..9f2d44d4d37 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -103,7 +103,7 @@ QuickSelectPopover.propTypes = {
applyTime: PropTypes.func.isRequired,
from: PropTypes.string.isRequired,
to: PropTypes.string.isRequired,
- applyRefreshInterval: PropTypes.func.isRequired,
+ applyRefreshInterval: PropTypes.func,
isPaused: PropTypes.bool.isRequired,
refreshInterval: PropTypes.number.isRequired,
commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
index d665947099b..9483c9584e0 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
@@ -87,6 +87,10 @@ export class RefreshInterval extends Component {
}
render() {
+ if (!this.props.applyRefreshInterval) {
+ return null;
+ }
+
return (
Refresh every
@@ -134,7 +138,7 @@ export class RefreshInterval extends Component {
}
RefreshInterval.propTypes = {
- applyRefreshInterval: PropTypes.func.isRequired,
+ applyRefreshInterval: PropTypes.func,
isPaused: PropTypes.bool.isRequired,
refreshInterval: PropTypes.number.isRequired,
};
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 94892e92b3c..ab40c48e716 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
@@ -214,7 +214,10 @@ EuiSuperDatePicker.propTypes = {
* Refresh interval in milliseconds
*/
refreshInterval: PropTypes.number,
- onRefreshChange: PropTypes.func.isRequired,
+ /**
+ * Supply onRefreshChange to show refresh interval form in quick select popover
+ */
+ onRefreshChange: PropTypes.func,
/**
* 'from' and 'to' must be string as either datemath (e.g.: now, now-15m, now-15m/m) or
From db09dc22f0d5b3d442c107d00df92f7184d02448 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 12:22:53 -0700
Subject: [PATCH 20/37] index files for super_date_picker and prefix
subcomponents with 'Eui'
---
src/components/date_picker/_index.scss | 2 +-
src/components/date_picker/index.js | 2 +-
.../date_picker/super_date_picker/_index.scss | 1 +
.../date_popover/absolute_tab.js | 4 ++--
.../date_popover/date_popover_button.js | 6 +++---
.../date_popover/date_popover_content.js | 14 ++++++-------
.../date_popover/relative_tab.js | 4 ++--
.../date_picker/super_date_picker/index.js | 3 +++
.../quick_select_popover/commonly_used.js | 4 ++--
.../quick_select_popover/quick_select.js | 4 ++--
.../quick_select_popover.js | 20 +++++++++----------
.../quick_select_popover/recently_used.js | 6 +++---
.../quick_select_popover/refresh_interval.js | 4 ++--
.../super_date_picker/super_date_picker.js | 10 +++++-----
14 files changed, 44 insertions(+), 40 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/_index.scss
create mode 100644 src/components/date_picker/super_date_picker/index.js
diff --git a/src/components/date_picker/_index.scss b/src/components/date_picker/_index.scss
index cc5927780e8..6ae886348b2 100644
--- a/src/components/date_picker/_index.scss
+++ b/src/components/date_picker/_index.scss
@@ -1,4 +1,4 @@
// Uses some form mixins
@import 'date_picker';
@import 'date_picker_range';
-@import 'super_date_picker/super_date_picker';
+@import 'super_date_picker/index';
diff --git a/src/components/date_picker/index.js b/src/components/date_picker/index.js
index c7087098446..00f6c0b638a 100644
--- a/src/components/date_picker/index.js
+++ b/src/components/date_picker/index.js
@@ -8,4 +8,4 @@ export {
export {
EuiSuperDatePicker,
-} from './super_date_picker/super_date_picker';
+} from './super_date_picker';
diff --git a/src/components/date_picker/super_date_picker/_index.scss b/src/components/date_picker/super_date_picker/_index.scss
new file mode 100644
index 00000000000..6382670c4bf
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/_index.scss
@@ -0,0 +1 @@
+@import 'super_date_picker';
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
index cabf2b4dfd9..58813254191 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
@@ -18,7 +18,7 @@ const toMoment = (value, roundUp) => {
};
};
-export class AbsoluteTab extends Component {
+export class EuiAbsoluteTab extends Component {
constructor(props) {
super(props);
@@ -79,7 +79,7 @@ export class AbsoluteTab extends Component {
}
}
-AbsoluteTab.propTypes = {
+EuiAbsoluteTab.propTypes = {
dateFormat: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index 3a05d99b516..e3dd142d427 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -5,9 +5,9 @@ import classNames from 'classnames';
import { EuiPopover } from '../../../popover';
import { formatTimeString } from '../pretty_duration';
-import { DatePopoverContent } from './date_popover_content';
+import { EuiDatePopoverContent } from './date_popover_content';
-export class DatePopoverButton extends Component {
+export class EuiDatePopoverButton extends Component {
static propTypes = {
position: PropTypes.oneOf(['start', 'end']),
isInvalid: PropTypes.bool,
@@ -87,7 +87,7 @@ export class DatePopoverButton extends Component {
ownFocus
{...rest}
>
- {
switch(selectedTab.id) {
@@ -37,7 +37,7 @@ export function DatePopoverContent({ value, roundUp, onChange, dateFormat }) {
id: DATE_MODES.ABSOLUTE,
name: 'Absolute',
content: (
- {
const applyCommonlyUsed = () => {
applyTime({ from, to });
@@ -41,7 +41,7 @@ export function CommonlyUsed({ applyTime, commonlyUsedRanges }) {
);
}
-CommonlyUsed.propTypes = {
+EuiCommonlyUsed.propTypes = {
applyTime: PropTypes.func.isRequired,
commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index d57e1b5d885..52d58dc56e9 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -25,7 +25,7 @@ const timeUnitsOptions = Object.keys(timeUnits).map(key => {
return { value: key, text: `${timeUnits[key]}s` };
});
-export class QuickSelect extends Component {
+export class EuiQuickSelect extends Component {
state = {
timeTense: LAST,
timeValue: 15,
@@ -173,7 +173,7 @@ export class QuickSelect extends Component {
}
}
-QuickSelect.propTypes = {
+EuiQuickSelect.propTypes = {
applyTime: PropTypes.func.isRequired,
from: PropTypes.string.isRequired,
to: PropTypes.string.isRequired,
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 9f2d44d4d37..78fbc4c3f77 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -15,12 +15,12 @@ import {
EuiPopover,
} from '../../../popover';
-import { QuickSelect } from './quick_select';
-import { CommonlyUsed } from './commonly_used';
-import { RecentlyUsed } from './recently_used';
-import { RefreshInterval } from './refresh_interval';
+import { EuiQuickSelect } from './quick_select';
+import { EuiCommonlyUsed } from './commonly_used';
+import { EuiRecentlyUsed } from './recently_used';
+import { EuiRefreshInterval } from './refresh_interval';
-export class QuickSelectPopover extends Component {
+export class EuiQuickSelectPopover extends Component {
state = {
isOpen: false,
@@ -73,22 +73,22 @@ export class QuickSelectPopover extends Component {
style={{ width: 400, maxWidth: '100%' }}
data-test-subj="superDatePickerQuickMenu"
>
-
-
-
-
}
endDateControl={
-
Date: Fri, 7 Dec 2018 12:50:25 -0700
Subject: [PATCH 21/37] add isLoading prop to EuiSuperDatePicker
---
.../views/date_picker/super_date_picker.js | 17 +-
.../super_date_picker.test.js.snap | 272 ++++++++++++++++++
.../super_date_picker/super_date_picker.js | 12 +-
.../super_date_picker.test.js | 33 +++
4 files changed, 329 insertions(+), 5 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/__snapshots__/super_date_picker.test.js.snap
create mode 100644 src/components/date_picker/super_date_picker/super_date_picker.test.js
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 71458f619cd..908b8cb43ae 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -8,7 +8,8 @@ import {
export default class extends Component {
state = {
- recentlyUsedRanges: []
+ recentlyUsedRanges: [],
+ isLoading: false,
}
onTimeChange = ({ from, to }) => {
@@ -22,8 +23,19 @@ export default class extends Component {
from,
to,
recentlyUsedRanges: recentlyUsedRanges.length > 10 ? recentlyUsedRanges.slice(0, 9) : recentlyUsedRanges,
+ isLoading: true,
};
- });
+ }, this.startLoading);
+ }
+
+ startLoading = () => {
+ setTimeout(
+ this.stopLoading,
+ 1000);
+ }
+
+ stopLoading = () => {
+ this.setState({ isLoading: false });
}
onRefreshChange = ({ isPaused, refreshInterval }) => {
@@ -38,6 +50,7 @@ export default class extends Component {
render() {
return (
+
+
+ }
+ >
+ }
+ iconType={false}
+ isCustom={true}
+ startDateControl={
}
+ >
+
+ Last 15 minutes
+
+
+ Show dates
+
+
+
+
+
+
+ Refresh
+
+
+
+`;
+
+exports[`EuiSuperDatePicker isLoading 1`] = `
+
+
+
+ }
+ >
+ }
+ iconType={false}
+ isCustom={true}
+ startDateControl={
}
+ >
+
+ Last 15 minutes
+
+
+ Show dates
+
+
+
+
+
+
+ Updating
+
+
+
+`;
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 e2c8f5f4bce..c0713139ddc 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
@@ -146,18 +146,23 @@ export class EuiSuperDatePicker extends Component {
}
renderUpdateButton = () => {
+ let buttonText = 'Refresh';
+ if (this.state.hasChanged || this.props.isLoading) {
+ buttonText = this.props.isLoading ? 'Updating' : 'Update';
+ }
return (
- {this.state.hasChanged ? 'Update' : 'Refresh'}
+ {buttonText}
);
}
@@ -198,6 +203,7 @@ export class EuiSuperDatePicker extends Component {
}
EuiSuperDatePicker.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'
diff --git a/src/components/date_picker/super_date_picker/super_date_picker.test.js b/src/components/date_picker/super_date_picker/super_date_picker.test.js
new file mode 100644
index 00000000000..22af2b5f6ba
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/super_date_picker.test.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import {
+ EuiSuperDatePicker,
+} from './super_date_picker';
+
+const noop = () => {}
+
+describe('EuiSuperDatePicker', () => {
+ test('is rendered', () => {
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+
+ test('isLoading', () => {
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+});
From e440d6d7b9820b6f18bdce0effcb1e2ceefca1d4 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 12:58:52 -0700
Subject: [PATCH 22/37] add props documenation for callback functions
---
.../date_picker/super_date_picker/super_date_picker.js | 4 ++++
.../date_picker/super_date_picker/super_date_picker.test.js | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
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 c0713139ddc..1a0ce6cc02e 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
@@ -214,6 +214,9 @@ EuiSuperDatePicker.propTypes = {
* absolute date in the format 'YYYY-MM-DDTHH:mm:ss.sssZ'
*/
to: PropTypes.string,
+ /**
+ * Callback for when the time changes. Called with { from, to }
+ */
onTimeChange: PropTypes.func.isRequired,
isPaused: PropTypes.bool,
/**
@@ -221,6 +224,7 @@ EuiSuperDatePicker.propTypes = {
*/
refreshInterval: PropTypes.number,
/**
+ * Callback for when the time changes. Called with { isPaused, refreshInterval }
* Supply onRefreshChange to show refresh interval form in quick select popover
*/
onRefreshChange: PropTypes.func,
diff --git a/src/components/date_picker/super_date_picker/super_date_picker.test.js b/src/components/date_picker/super_date_picker/super_date_picker.test.js
index 22af2b5f6ba..5fa4f20e4ed 100644
--- a/src/components/date_picker/super_date_picker/super_date_picker.test.js
+++ b/src/components/date_picker/super_date_picker/super_date_picker.test.js
@@ -5,7 +5,7 @@ import {
EuiSuperDatePicker,
} from './super_date_picker';
-const noop = () => {}
+const noop = () => {};
describe('EuiSuperDatePicker', () => {
test('is rendered', () => {
From a45a277263e5d084cb6a0e66c04674c748c2184d Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 13:19:57 -0700
Subject: [PATCH 23/37] show 'next' relative ranges as pretty duration
---
.../super_date_picker/pretty_duration.js | 25 ++++++++++++-------
.../super_date_picker/pretty_duration.test.js | 12 ++++++++-
.../super_date_picker/super_date_picker.js | 4 +--
.../super_date_picker/time_units.js | 10 ++++++++
4 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index 8ac5c060436..0a0564ef657 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -1,7 +1,7 @@
import dateMath from '@elastic/datemath';
import moment from 'moment';
-import { timeUnits } from './time_units';
+import { timeUnits, timeUnitsPlural } from './time_units';
import { getDateMode, DATE_MODES } from './date_modes';
import { parseRelativeParts } from './relative_utils';
@@ -16,7 +16,9 @@ function cantLookup(timeFrom, timeTo, dateFormat) {
function isRelativeToNow(timeFrom, timeTo) {
const fromDateMode = getDateMode(timeFrom);
const toDateMode = getDateMode(timeTo);
- return fromDateMode === DATE_MODES.RELATIVE && toDateMode === DATE_MODES.NOW;
+ const isLast = fromDateMode === DATE_MODES.RELATIVE && toDateMode === DATE_MODES.NOW;
+ const isNext = fromDateMode === DATE_MODES.NOW && toDateMode === DATE_MODES.RELATIVE;
+ return isLast || isNext;
}
export function formatTimeString(timeString, dateFormat, roundUp = false) {
@@ -46,15 +48,20 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
}
if (isRelativeToNow(timeFrom, timeTo)) {
- const relativeParts = parseRelativeParts(timeFrom);
- let countTimeUnit = timeUnits[relativeParts.unit.substring(0, 1)];
- if (relativeParts.count > 1) {
- countTimeUnit += 's';
+ let timeTense;
+ let relativeParts;
+ if (getDateMode(timeTo) === DATE_MODES.NOW) {
+ timeTense = 'Last';
+ relativeParts = parseRelativeParts(timeFrom);
+ } else {
+ timeTense = 'Next';
+ relativeParts = parseRelativeParts(timeTo);
}
- let text = `Last ${relativeParts.count} ${countTimeUnit}`;
+ const countTimeUnit = relativeParts.unit.substring(0, 1);
+ const countTimeUnitFullName = relativeParts.count > 1 ? timeUnitsPlural[countTimeUnit] : timeUnits[countTimeUnit];
+ let text = `${timeTense} ${relativeParts.count} ${countTimeUnitFullName}`;
if (relativeParts.round) {
- const roundTimeUnit = timeUnits[relativeParts.roundUnit] ? timeUnits[relativeParts.roundUnit] : relativeParts.roundUnit;
- text += ` rounded to the ${roundTimeUnit}`;
+ text += ` rounded to the ${timeUnits[relativeParts.roundUnit]}`;
}
return text;
}
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
index c1e6560f4f4..af80a8e2734 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.test.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -31,6 +31,12 @@ describe('prettyDuration', () => {
expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Last 1 month rounded to the week');
});
+ test('next', () => {
+ const timeFrom = 'now';
+ const timeTo = 'now+16m';
+ expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('Next 16 minutes');
+ });
+
test('from is in past', () => {
const timeFrom = 'now-17m';
const timeTo = 'now-15m';
@@ -50,10 +56,14 @@ describe('showPrettyDuration', () => {
expect(showPrettyDuration('now-15m', 'now', quickRanges)).toBe(true);
});
- test('should show pretty duration for relative to now', () => {
+ test('should show pretty duration for last', () => {
expect(showPrettyDuration('now-17m', 'now', quickRanges)).toBe(true);
});
+ test('should show pretty duration for next', () => {
+ expect(showPrettyDuration('now', 'now+17m', quickRanges)).toBe(true);
+ });
+
test('should not show pretty duration for relative to relative', () => {
expect(showPrettyDuration('now-17m', 'now-3m', quickRanges)).toBe(false);
});
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 1a0ce6cc02e..78643a361fb 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
@@ -224,8 +224,8 @@ EuiSuperDatePicker.propTypes = {
*/
refreshInterval: PropTypes.number,
/**
- * Callback for when the time changes. Called with { isPaused, refreshInterval }
- * Supply onRefreshChange to show refresh interval form in quick select popover
+ * 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,
diff --git a/src/components/date_picker/super_date_picker/time_units.js b/src/components/date_picker/super_date_picker/time_units.js
index 3ad61fca541..73766803588 100644
--- a/src/components/date_picker/super_date_picker/time_units.js
+++ b/src/components/date_picker/super_date_picker/time_units.js
@@ -8,3 +8,13 @@ export const timeUnits = {
M: 'month',
y: 'year'
};
+
+export const timeUnitsPlural = {
+ s: 'seconds',
+ m: 'minutes',
+ h: 'hours',
+ d: 'days',
+ w: 'weeks',
+ M: 'months',
+ y: 'years'
+};
From 2ef51714221191d9a8eef2320d1245c2cf780fc1 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 7 Dec 2018 14:11:02 -0700
Subject: [PATCH 24/37] rename from and to -> start and end
---
.../views/date_picker/super_date_picker.js | 14 +--
.../super_date_picker.test.js.snap | 72 +++++++-------
.../super_date_picker/pretty_duration.js | 4 +-
.../super_date_picker/pretty_duration.test.js | 4 +-
.../quick_select_popover/commonly_used.js | 4 +-
.../quick_select_popover/quick_select.js | 24 ++---
.../quick_select_popover.js | 14 +--
.../quick_select_popover/recently_used.js | 8 +-
.../super_date_picker/super_date_picker.js | 94 +++++++++----------
.../date_picker/super_date_picker/types.js | 8 +-
10 files changed, 123 insertions(+), 123 deletions(-)
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 908b8cb43ae..47c0347522a 100644
--- a/src-docs/src/views/date_picker/super_date_picker.js
+++ b/src-docs/src/views/date_picker/super_date_picker.js
@@ -12,16 +12,16 @@ export default class extends Component {
isLoading: false,
}
- onTimeChange = ({ from, to }) => {
+ onTimeChange = ({ start, end }) => {
this.setState((prevState) => {
const recentlyUsedRanges = prevState.recentlyUsedRanges.filter(recentlyUsedRange => {
- const isDuplicate = recentlyUsedRange.from === from && recentlyUsedRange.to === to;
+ const isDuplicate = recentlyUsedRange.start === start && recentlyUsedRange.end === end;
return !isDuplicate;
});
- recentlyUsedRanges.unshift({ from, to });
+ recentlyUsedRanges.unshift({ start, end });
return {
- from,
- to,
+ start,
+ end,
recentlyUsedRanges: recentlyUsedRanges.length > 10 ? recentlyUsedRanges.slice(0, 9) : recentlyUsedRanges,
isLoading: true,
};
@@ -51,8 +51,8 @@ export default class extends Component {
return (
}
>
@@ -164,53 +164,53 @@ exports[`EuiSuperDatePicker isLoading 1`] = `
commonlyUsedRanges={
Array [
Object {
- "from": "now/d",
+ "end": "now/d",
"label": "Today",
- "to": "now/d",
+ "start": "now/d",
},
Object {
- "from": "now-1d/d",
+ "end": "now-1d/d",
"label": "Yesterday",
- "to": "now-1d/d",
+ "start": "now-1d/d",
},
Object {
- "from": "now/w",
+ "end": "now/w",
"label": "This week",
- "to": "now/w",
+ "start": "now/w",
},
Object {
- "from": "now/w",
+ "end": "now",
"label": "Week to date",
- "to": "now",
+ "start": "now/w",
},
Object {
- "from": "now/M",
+ "end": "now/M",
"label": "This month",
- "to": "now/M",
+ "start": "now/M",
},
Object {
- "from": "now/M",
+ "end": "now",
"label": "Month to date",
- "to": "now",
+ "start": "now/M",
},
Object {
- "from": "now/y",
+ "end": "now/y",
"label": "This year",
- "to": "now/y",
+ "start": "now/y",
},
Object {
- "from": "now/y",
+ "end": "now",
"label": "Year to date",
- "to": "now",
+ "start": "now/y",
},
]
}
dateFormat="MMM D, YYYY @ HH:mm:ss.SSS"
- from="now-15m"
+ end="now"
isPaused={true}
recentlyUsedRanges={Array []}
refreshInterval={0}
- to="now"
+ start="now-15m"
/>
}
>
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index 0a0564ef657..ed357c1841b 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -40,7 +40,7 @@ export function formatTimeString(timeString, dateFormat, roundUp = false) {
}
export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
- const matchingQuickRange = quickRanges.find(({ from: quickFrom, to: quickTo }) => {
+ const matchingQuickRange = quickRanges.find(({ start: quickFrom, end: quickTo }) => {
return timeFrom === quickFrom && timeTo === quickTo;
});
if (matchingQuickRange) {
@@ -70,7 +70,7 @@ export function prettyDuration(timeFrom, timeTo, quickRanges = [], dateFormat) {
}
export function showPrettyDuration(timeFrom, timeTo, quickRanges = []) {
- const matchingQuickRange = quickRanges.find(({ from: quickFrom, to: quickTo }) => {
+ const matchingQuickRange = quickRanges.find(({ start: quickFrom, end: quickTo }) => {
return timeFrom === quickFrom && timeTo === quickTo;
});
if (matchingQuickRange) {
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
index af80a8e2734..5f240a6e8bf 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.test.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -6,8 +6,8 @@ moment.tz.setDefault('UTC');
const dateFormat = 'MMMM Do YYYY, HH:mm:ss.SSS';
const quickRanges = [
{
- from: 'now-15m',
- to: 'now',
+ start: 'now-15m',
+ end: 'now',
label: 'quick range 15 minutes custom display',
}
];
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
index 5e6aa8c464d..b7a1822fa88 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
@@ -11,9 +11,9 @@ import { EuiText } from '../../../text';
import { EuiHorizontalRule } from '../../../horizontal_rule';
export function EuiCommonlyUsed({ applyTime, commonlyUsedRanges }) {
- const links = commonlyUsedRanges.map(({ from, to, label }) => {
+ const links = commonlyUsedRanges.map(({ start, end, label }) => {
const applyCommonlyUsed = () => {
- applyTime({ from, to });
+ applyTime({ start, end });
};
return (
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index 52d58dc56e9..ff291604e7c 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -60,22 +60,22 @@ export class EuiQuickSelect extends Component {
if (timeTense === NEXT) {
this.props.applyTime({
- from: 'now',
- to: `now+${timeValue}${timeUnits}`
+ start: 'now',
+ end: `now+${timeValue}${timeUnits}`
});
return;
}
this.props.applyTime({
- from: `now-${timeValue}${timeUnits}`,
- to: 'now'
+ start: `now-${timeValue}${timeUnits}`,
+ end: 'now'
});
}
getBounds = () => {
return {
- min: dateMath.parse(this.props.from),
- max: dateMath.parse(this.props.to, { roundUp: true }),
+ min: dateMath.parse(this.props.start),
+ max: dateMath.parse(this.props.end, { roundUp: true }),
};
}
@@ -83,8 +83,8 @@ export class EuiQuickSelect extends Component {
const { min, max } = this.getBounds();
const diff = max.diff(min);
this.props.applyTime({
- from: moment(max).add(1, 'ms').toISOString(),
- to: moment(max).add(diff + 1, 'ms').toISOString(),
+ start: moment(max).add(1, 'ms').toISOString(),
+ end: moment(max).add(diff + 1, 'ms').toISOString(),
});
}
@@ -92,8 +92,8 @@ export class EuiQuickSelect extends Component {
const { min, max } = this.getBounds();
const diff = max.diff(min);
this.props.applyTime({
- from: moment(min).subtract(diff + 1, 'ms').toISOString(),
- to: moment(min).subtract(1, 'ms').toISOString(),
+ start: moment(min).subtract(diff + 1, 'ms').toISOString(),
+ end: moment(min).subtract(1, 'ms').toISOString(),
});
}
@@ -175,6 +175,6 @@ export class EuiQuickSelect extends Component {
EuiQuickSelect.propTypes = {
applyTime: PropTypes.func.isRequired,
- from: PropTypes.string.isRequired,
- to: PropTypes.string.isRequired,
+ start: PropTypes.string.isRequired,
+ end: PropTypes.string.isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 78fbc4c3f77..b0500d122a7 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -36,10 +36,10 @@ export class EuiQuickSelectPopover extends Component {
}));
}
- applyTime = ({ from, to }) => {
+ applyTime = ({ start, end }) => {
this.props.applyTime({
- from,
- to,
+ start,
+ end,
});
this.closePopover();
}
@@ -75,8 +75,8 @@ export class EuiQuickSelectPopover extends Component {
>
{
+ const links = recentlyUsedRanges.map(({ start, end }) => {
const applyRecentlyUsed = () => {
- applyTime({ from, to });
+ applyTime({ start, end });
};
return (
-
+
- {prettyDuration(from, to, commonlyUsedRanges, dateFormat)}
+ {prettyDuration(start, end, commonlyUsedRanges, dateFormat)}
);
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 78643a361fb..7ce4ec8f25b 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
@@ -20,63 +20,63 @@ export class EuiSuperDatePicker extends Component {
super(props);
const {
- from,
- to,
+ start,
+ end,
commonlyUsedRanges
} = this.props;
this.state = {
- from,
- to,
+ start,
+ end,
isInvalid: false,
hasChanged: false,
- showPrettyDuration: showPrettyDuration(from, to, commonlyUsedRanges),
+ showPrettyDuration: showPrettyDuration(start, end, commonlyUsedRanges),
};
}
static getDerivedStateFromProps = (nextProps) => {
const {
- from,
- to,
+ start,
+ end,
commonlyUsedRanges
} = nextProps;
return {
- from,
- to,
+ start,
+ end,
isInvalid: false,
hasChanged: false,
- showPrettyDuration: showPrettyDuration(from, to, commonlyUsedRanges),
+ showPrettyDuration: showPrettyDuration(start, end, commonlyUsedRanges),
};
}
- setTime = ({ from, to }) => {
- const fromMoment = dateMath.parse(from);
- const toMoment = dateMath.parse(to, { roundUp: true });
- const isInvalid = (from === 'now' && to === 'now') || fromMoment.isAfter(toMoment);
+ setTime = ({ start, end }) => {
+ const startMoment = dateMath.parse(start);
+ const endMoment = dateMath.parse(end, { roundUp: true });
+ const isInvalid = (start === 'now' && end === 'now') || startMoment.isAfter(endMoment);
this.setState({
- from,
- to,
+ start,
+ end,
isInvalid,
hasChanged: true,
});
}
- setFrom = (from) => {
- this.setTime({ from, to: this.state.to });
+ setStart = (start) => {
+ this.setTime({ start, end: this.state.end });
}
- setTo = (to) => {
- this.setTime({ from: this.state.from, to });
+ setEnd = (end) => {
+ this.setTime({ start: this.state.start, end });
}
applyTime = () => {
- this.props.onTimeChange({ from: this.state.from, to: this.state.to });
+ this.props.onTimeChange({ start: this.state.start, end: this.state.end });
}
- applyQuickTime = ({ from, to }) => {
- this.props.onTimeChange({ from, to });
+ applyQuickTime = ({ start, end }) => {
+ this.props.onTimeChange({ start, end });
}
hidePrettyDuration = () => {
@@ -85,8 +85,8 @@ export class EuiSuperDatePicker extends Component {
renderDatePickerRange = () => {
const {
- from,
- to,
+ start,
+ end,
hasChanged,
isInvalid,
} = this.state;
@@ -101,7 +101,7 @@ export class EuiSuperDatePicker extends Component {
endDateControl={
}
>
- {prettyDuration(from, to, this.props.commonlyUsedRanges, this.props.dateFormat)}
+ {prettyDuration(start, end, this.props.commonlyUsedRanges, this.props.dateFormat)}
}
@@ -135,8 +135,8 @@ export class EuiSuperDatePicker extends Component {
position="end"
needsUpdating={hasChanged}
isInvalid={isInvalid}
- onChange={this.setTo}
- value={to}
+ onChange={this.setEnd}
+ value={end}
dateFormat={this.props.dateFormat}
roundUp
/>
@@ -171,8 +171,8 @@ export class EuiSuperDatePicker extends Component {
const quickSelect = (
Date: Fri, 7 Dec 2018 14:31:03 -0700
Subject: [PATCH 25/37] store previous quick select state
---
.../__snapshots__/quick_select.test.js.snap | 433 ++++++++++++++++++
.../quick_select_popover/quick_select.js | 26 +-
.../quick_select_popover/quick_select.test.js | 41 ++
.../quick_select_popover.js | 6 +-
4 files changed, 498 insertions(+), 8 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap
create mode 100644 src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js
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
new file mode 100644
index 00000000000..95e30574a8e
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/__snapshots__/quick_select.test.js.snap
@@ -0,0 +1,433 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`EuiSuperDatePicker is rendered 1`] = `
+
+
+
+
+
+ Quick select
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply
+
+
+
+
+
+
+`;
+
+exports[`EuiSuperDatePicker prevQuickSelect 1`] = `
+
+
+
+
+
+ Quick select
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Apply
+
+
+
+
+
+
+`;
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index ff291604e7c..f1957bee2a9 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -26,10 +26,15 @@ const timeUnitsOptions = Object.keys(timeUnits).map(key => {
});
export class EuiQuickSelect extends Component {
- state = {
- timeTense: LAST,
- timeValue: 15,
- timeUnits: 'm',
+ constructor(props) {
+ super(props);
+
+ const { timeTense, timeValue, timeUnits } = this.props.prevQuickSelect;
+ this.state = {
+ timeTense: timeTense ? timeTense : LAST,
+ timeValue: timeValue ? timeValue : 15,
+ timeUnits: timeUnits ? timeUnits : 'm',
+ };
}
onTimeTenseChange = (evt) => {
@@ -61,14 +66,16 @@ export class EuiQuickSelect extends Component {
if (timeTense === NEXT) {
this.props.applyTime({
start: 'now',
- end: `now+${timeValue}${timeUnits}`
+ end: `now+${timeValue}${timeUnits}`,
+ quickSelect: { ...this.state },
});
return;
}
this.props.applyTime({
start: `now-${timeValue}${timeUnits}`,
- end: 'now'
+ end: 'now',
+ quickSelect: { ...this.state },
});
}
@@ -160,7 +167,7 @@ export class EuiQuickSelect extends Component {
size="s"
onClick={this.applyQuickSelect}
style={{ minWidth: 0 }}
- disabled={this.state.timeValue === ''}
+ disabled={this.state.timeValue === '' || this.state.timeValue <= 0}
>
Apply
@@ -177,4 +184,9 @@ EuiQuickSelect.propTypes = {
applyTime: PropTypes.func.isRequired,
start: PropTypes.string.isRequired,
end: PropTypes.string.isRequired,
+ prevQuickSelect: PropTypes.object,
+};
+
+EuiQuickSelect.defaultProps = {
+ prevQuickSelect: {},
};
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
new file mode 100644
index 00000000000..49733a1b676
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.test.js
@@ -0,0 +1,41 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+
+import {
+ EuiQuickSelect,
+} from './quick_select';
+
+const noop = () => {};
+const defaultProps = {
+ applyTime: noop,
+ start: 'now-15m',
+ end: 'now',
+};
+describe('EuiSuperDatePicker', () => {
+ test('is rendered', () => {
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+
+ test('prevQuickSelect', () => {
+ const component = shallow(
+
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+});
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index b0500d122a7..6d45ec93001 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -36,11 +36,14 @@ export class EuiQuickSelectPopover extends Component {
}));
}
- applyTime = ({ start, end }) => {
+ applyTime = ({ start, end, quickSelect }) => {
this.props.applyTime({
start,
end,
});
+ if (quickSelect) {
+ this.setState({ prevQuickSelect: quickSelect });
+ }
this.closePopover();
}
@@ -77,6 +80,7 @@ export class EuiQuickSelectPopover extends Component {
applyTime={this.applyTime}
start={this.props.start}
end={this.props.end}
+ prevQuickSelect={this.state.prevQuickSelect}
/>
Date: Sun, 9 Dec 2018 09:44:28 -0700
Subject: [PATCH 26/37] snapshot updates
---
.../super_date_picker.test.js.snap | 80 +++++++++++--------
.../date_popover/date_popover_button.js | 2 +-
.../super_date_picker/super_date_picker.js | 30 ++++---
3 files changed, 64 insertions(+), 48 deletions(-)
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 6b2aeb6591d..cf18215a325 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
@@ -113,24 +113,29 @@ exports[`EuiSuperDatePicker is rendered 1`] = `
component="div"
grow={false}
>
-
- Refresh
-
+
+ Refresh
+
+
`;
@@ -248,25 +253,30 @@ exports[`EuiSuperDatePicker isLoading 1`] = `
component="div"
grow={false}
>
-
- Updating
-
+
+ Updating
+
+
`;
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index e3dd142d427..2463b8343b5 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -82,7 +82,7 @@ export class EuiDatePopoverButton extends Component {
button={button}
isOpen={this.state.isOpen}
closePopover={this.closePopover}
- anchorPosition="downRight"
+ anchorPosition={this.props.position === 'start' ? 'downLeft' : 'downRight'}
panelPaddingSize="none"
ownFocus
{...rest}
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 7ce4ec8f25b..0d29fc507aa 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
@@ -13,6 +13,7 @@ import { EuiDatePickerRange } from '../date_picker_range';
import { EuiFormControlLayout } from '../../form';
import { EuiButton, EuiButtonEmpty } from '../../button';
import { EuiFlexGroup, EuiFlexItem } from '../../flex';
+import { EuiToolTip } from '../../tool_tip';
export class EuiSuperDatePicker extends Component {
@@ -151,19 +152,24 @@ export class EuiSuperDatePicker extends Component {
buttonText = this.props.isLoading ? 'Updating' : 'Update';
}
return (
-
- {buttonText}
-
+
+ {buttonText}
+
+
);
}
From 0b447b4ea8a0638df8dce275e50d8cad92fdb378 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Sun, 9 Dec 2018 09:48:49 -0700
Subject: [PATCH 27/37] keep quick select popover open on next / previous time
window arrow
---
.../super_date_picker/quick_select_popover/quick_select.js | 2 ++
.../quick_select_popover/quick_select_popover.js | 6 ++++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
index f1957bee2a9..3d06c1dfa9b 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select.js
@@ -92,6 +92,7 @@ export class EuiQuickSelect extends Component {
this.props.applyTime({
start: moment(max).add(1, 'ms').toISOString(),
end: moment(max).add(diff + 1, 'ms').toISOString(),
+ keepPopoverOpen: true,
});
}
@@ -101,6 +102,7 @@ export class EuiQuickSelect extends Component {
this.props.applyTime({
start: moment(min).subtract(diff + 1, 'ms').toISOString(),
end: moment(min).subtract(1, 'ms').toISOString(),
+ keepPopoverOpen: true,
});
}
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 6d45ec93001..9c0fc7234fb 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -36,7 +36,7 @@ export class EuiQuickSelectPopover extends Component {
}));
}
- applyTime = ({ start, end, quickSelect }) => {
+ applyTime = ({ start, end, quickSelect, keepPopoverOpen = false }) => {
this.props.applyTime({
start,
end,
@@ -44,7 +44,9 @@ export class EuiQuickSelectPopover extends Component {
if (quickSelect) {
this.setState({ prevQuickSelect: quickSelect });
}
- this.closePopover();
+ if (!keepPopoverOpen) {
+ this.closePopover();
+ }
}
render() {
From b4a0f21ee0bd171c2b9ddbca020eebdd0da08a37 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Mon, 10 Dec 2018 12:17:51 -0700
Subject: [PATCH 28/37] make pretty duration clickable, add paragraph to
example
---
.../views/date_picker/date_picker_example.js | 6 ++-
.../super_date_picker.test.js.snap | 40 +++++++++++++++++--
.../super_date_picker/super_date_picker.js | 9 ++++-
3 files changed, 48 insertions(+), 7 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 1dfa0787cd7..b326f755eaa 100644
--- a/src-docs/src/views/date_picker/date_picker_example.js
+++ b/src-docs/src/views/date_picker/date_picker_example.js
@@ -276,7 +276,11 @@ export const DatePickerExample = {
}],
text: (
- Super date picker
+
+ start and end date times are passed as strings
+ 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
+
),
demo: ,
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 cf18215a325..5147c25d067 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
@@ -86,11 +86,27 @@ exports[`EuiSuperDatePicker is rendered 1`] = `
isCustom={true}
startDateControl={
}
>
-
Last 15 minutes
-
+
}
>
-
Last 15 minutes
-
+
}
endDateControl={
}
>
-
+
{prettyDuration(start, end, this.props.commonlyUsedRanges, this.props.dateFormat)}
-
+
Date: Mon, 10 Dec 2018 13:56:35 -0700
Subject: [PATCH 29/37] show tooltip when time changes
---
.../super_date_picker/super_date_picker.js | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
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 287213362e2..aa0f5e18fdc 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
@@ -51,17 +51,35 @@ export class EuiSuperDatePicker extends Component {
};
}
+ setTootipRef = node => (this.tooltip = node);
+
+ showTooltip = () => this.tooltip.showToolTip();
+ hideTooltip = () => this.tooltip.hideToolTip();
+
setTime = ({ start, end }) => {
const startMoment = dateMath.parse(start);
const endMoment = dateMath.parse(end, { roundUp: true });
const isInvalid = (start === 'now' && end === 'now') || startMoment.isAfter(endMoment);
+ if (this.tooltipTimeout) {
+ clearTimeout(this.tooltipTimeout);
+ this.hideTooltip();
+ this.tooltipTimeout === null;
+ }
+
this.setState({
start,
end,
isInvalid,
hasChanged: true,
});
+
+ if (!isInvalid) {
+ this.showTooltip();
+ this.tooltipTimeout = setTimeout(() => {
+ this.hideTooltip();
+ }, 2000);
+ }
}
setStart = (start) => {
@@ -158,6 +176,7 @@ export class EuiSuperDatePicker extends Component {
}
return (
From 0a0c770dfba7787f9e3769d286efa8a11a88b3d9 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Tue, 11 Dec 2018 08:47:50 -0700
Subject: [PATCH 30/37] allow setting relative unit when value is zero
---
.../super_date_picker/date_popover/relative_tab.js | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
index 29231beee03..085f41e5a27 100644
--- a/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/relative_tab.js
@@ -28,8 +28,14 @@ export class EuiRelativeTab extends Component {
}
static getDerivedStateFromProps = (nextProps) => {
+ const relativeParts = parseRelativeParts(nextProps.value);
+ // parseRelativeParts will always return unit of 's' when the count is zero
+ // Do not override state.unit when count is zero to allow users to set the unit when count is zero
+ if (relativeParts.count === 0) {
+ delete relativeParts.unit;
+ }
return {
- ...parseRelativeParts(nextProps.value),
+ ...relativeParts,
};
}
From 7f74ef757ce252e4000e5d292ff9c194b5dd7d47 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 13 Dec 2018 08:39:54 -0700
Subject: [PATCH 31/37] updates from chandlerprall review
---
.../super_date_picker/date_popover/absolute_tab.js | 13 +++----------
.../date_popover/date_popover_button.js | 2 +-
...ommonly_used.js => commonly_used_time_ranges.js} | 4 ++--
.../quick_select_popover/quick_select_popover.js | 4 ++--
.../quick_select_popover/refresh_interval.js | 9 +--------
.../super_date_picker/relative_options.js | 9 +++++++++
.../date_picker/super_date_picker/relative_utils.js | 10 ++++------
.../super_date_picker/super_date_picker.js | 2 +-
8 files changed, 23 insertions(+), 30 deletions(-)
rename src/components/date_picker/super_date_picker/quick_select_popover/{commonly_used.js => commonly_used_time_ranges.js} (91%)
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
index 58813254191..929bdd72bc8 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
@@ -5,11 +5,11 @@ import moment from 'moment';
import dateMath from '@elastic/datemath';
-const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
-
import { EuiDatePicker } from '../../date_picker';
import { EuiFormRow, EuiFieldText } from '../../../form';
+const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
+
const toMoment = (value, roundUp) => {
const valueAsMoment = dateMath.parse(value, { roundUp });
return {
@@ -20,14 +20,7 @@ const toMoment = (value, roundUp) => {
export class EuiAbsoluteTab extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- ...toMoment(this.props.value, this.props.roundUp),
- isTextInvalid: false,
- };
- }
+ state = {}
static getDerivedStateFromProps = (nextProps) => {
return {
diff --git a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
index 2463b8343b5..6619aa81333 100644
--- a/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
+++ b/src/components/date_picker/super_date_picker/date_popover/date_popover_button.js
@@ -13,7 +13,7 @@ export class EuiDatePopoverButton extends Component {
isInvalid: PropTypes.bool,
needsUpdating: PropTypes.bool,
value: PropTypes.string.isRequired,
- onChange: PropTypes.func,
+ onChange: PropTypes.func.isRequired,
dateFormat: PropTypes.string.isRequired,
roundUp: PropTypes.bool,
}
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.js
similarity index 91%
rename from src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
rename to src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.js
index b7a1822fa88..a80774719e4 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/commonly_used_time_ranges.js
@@ -10,7 +10,7 @@ import { EuiLink } from '../../../link';
import { EuiText } from '../../../text';
import { EuiHorizontalRule } from '../../../horizontal_rule';
-export function EuiCommonlyUsed({ applyTime, commonlyUsedRanges }) {
+export function EuiCommonlyUsedTimeRanges({ applyTime, commonlyUsedRanges }) {
const links = commonlyUsedRanges.map(({ start, end, label }) => {
const applyCommonlyUsed = () => {
applyTime({ start, end });
@@ -41,7 +41,7 @@ export function EuiCommonlyUsed({ applyTime, commonlyUsedRanges }) {
);
}
-EuiCommonlyUsed.propTypes = {
+EuiCommonlyUsedTimeRanges.propTypes = {
applyTime: PropTypes.func.isRequired,
commonlyUsedRanges: PropTypes.arrayOf(commonlyUsedRangeShape).isRequired,
};
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
index 9c0fc7234fb..889f5ba3f34 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/quick_select_popover.js
@@ -16,7 +16,7 @@ import {
} from '../../../popover';
import { EuiQuickSelect } from './quick_select';
-import { EuiCommonlyUsed } from './commonly_used';
+import { EuiCommonlyUsedTimeRanges } from './commonly_used_time_ranges';
import { EuiRecentlyUsed } from './recently_used';
import { EuiRefreshInterval } from './refresh_interval';
@@ -84,7 +84,7 @@ export class EuiQuickSelectPopover extends Component {
end={this.props.end}
prevQuickSelect={this.state.prevQuickSelect}
/>
-
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
index 096f1c0f881..8c0ecc1d1d1 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
@@ -34,15 +34,8 @@ function convertMilliseconds(milliseconds) {
}
export class EuiRefreshInterval extends Component {
- constructor(props) {
- super(props);
- const { value, units } = convertMilliseconds(this.props.refreshInterval);
- this.state = {
- value,
- units,
- };
- }
+ state = {}
static getDerivedStateFromProps = (nextProps) => {
const { value, units } = convertMilliseconds(nextProps.refreshInterval);
diff --git a/src/components/date_picker/super_date_picker/relative_options.js b/src/components/date_picker/super_date_picker/relative_options.js
index 43045a13a03..677191356cf 100644
--- a/src/components/date_picker/super_date_picker/relative_options.js
+++ b/src/components/date_picker/super_date_picker/relative_options.js
@@ -16,3 +16,12 @@ export const relativeOptions = [
{ text: 'Months from now', value: 'M+' },
{ text: 'Years from now', value: 'y+' },
];
+
+export const relativeUnitsFromLargestToSmallest = relativeOptions
+ .filter(({ value }) => {
+ return !value.includes('+');
+ })
+ .map(({ value }) => {
+ return value;
+ })
+ .reverse();
diff --git a/src/components/date_picker/super_date_picker/relative_utils.js b/src/components/date_picker/super_date_picker/relative_utils.js
index 096d6a65243..4732080fe1b 100644
--- a/src/components/date_picker/super_date_picker/relative_utils.js
+++ b/src/components/date_picker/super_date_picker/relative_utils.js
@@ -2,7 +2,7 @@
import dateMath from '@elastic/datemath';
import moment from 'moment';
import _ from 'lodash';
-import { relativeOptions } from './relative_options';
+import { relativeUnitsFromLargestToSmallest } from './relative_options';
const ROUND_DELIMETER = '/';
@@ -31,15 +31,13 @@ export function parseRelativeParts(value) {
const results = { count: 0, unit: 's', round: false };
const duration = moment.duration(moment().diff(dateMath.parse(value)));
- const units = _.pluck(_.clone(relativeOptions).reverse(), 'value')
- .filter(s => /^[smhdwMy]$/.test(s));
let unitOp = '';
- for (let i = 0; i < units.length; i++) {
- const as = duration.as(units[i]);
+ for (let i = 0; i < relativeUnitsFromLargestToSmallest.length; i++) {
+ const as = duration.as(relativeUnitsFromLargestToSmallest[i]);
if (as < 0) unitOp = '+';
if (Math.abs(as) > 1) {
results.count = Math.round(Math.abs(as));
- results.unit = units[i] + unitOp;
+ results.unit = relativeUnitsFromLargestToSmallest[i] + unitOp;
results.round = false;
break;
}
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 aa0f5e18fdc..e331f1a7483 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
@@ -64,7 +64,7 @@ export class EuiSuperDatePicker extends Component {
if (this.tooltipTimeout) {
clearTimeout(this.tooltipTimeout);
this.hideTooltip();
- this.tooltipTimeout === null;
+ this.tooltipTimeout = null;
}
this.setState({
From 759ecda31baeef1e9f9e0bd43abccf9e9f861581 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Thu, 13 Dec 2018 09:50:35 -0700
Subject: [PATCH 32/37] remove moment-timezone dependency, not needed
---
package.json | 1 -
.../super_date_picker/pretty_duration.test.js | 9 ---------
2 files changed, 10 deletions(-)
diff --git a/package.json b/package.json
index 1a4f458b73a..1c4ba11e774 100644
--- a/package.json
+++ b/package.json
@@ -122,7 +122,6 @@
"markdown-it": "8.4.1",
"mocha": "^5.0.4",
"moment": "^2.20.1",
- "moment-timezone": "^0.5.14",
"node-sass": "^4.9.3",
"nodegit": "^0.23.0",
"npm-run": "^4.1.2",
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.test.js b/src/components/date_picker/super_date_picker/pretty_duration.test.js
index 5f240a6e8bf..3f0124eea17 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.test.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.test.js
@@ -1,8 +1,6 @@
-import moment from 'moment-timezone';
import { prettyDuration, showPrettyDuration } from './pretty_duration';
-moment.tz.setDefault('UTC');
const dateFormat = 'MMMM Do YYYY, HH:mm:ss.SSS';
const quickRanges = [
{
@@ -42,13 +40,6 @@ describe('prettyDuration', () => {
const timeTo = 'now-15m';
expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('~ 17 minutes ago to ~ 15 minutes ago');
});
-
- // TODO figure out timezone to get this working
- //test('absolute dates', () => {
- // const timeFrom = '2018-01-17T18:57:57.149Z';
- // const timeTo = '2018-01-17T20:00:00.000Z';
- // expect(prettyDuration(timeFrom, timeTo, quickRanges, dateFormat)).toBe('January 17th 2018, 18:57:57.149 to January 17th 2018, 20:00:00.000');
- //});
});
describe('showPrettyDuration', () => {
From b6bfe054e597d55776db77e87ef4aa7f491826f5 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 14 Dec 2018 14:29:50 -0700
Subject: [PATCH 33/37] remove getDerivedStateFromProps from
EuiSuperDatePicker, EuiAbsoluteTab, EuiRefreshInterval, and EuiRelativeTab
---
.../date_popover/absolute_tab.js | 35 ++++++++++---------
.../date_popover/relative_tab.js | 12 -------
.../date_picker/super_date_picker/index.js | 8 +++--
.../super_date_picker/pretty_duration.js | 2 +-
.../quick_select_popover/refresh_interval.js | 8 ++---
.../super_date_picker/super_date_picker.js | 16 ---------
.../wrapped_super_date_picker.js | 20 +++++++++++
7 files changed, 48 insertions(+), 53 deletions(-)
create mode 100644 src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
diff --git a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
index 929bdd72bc8..cd3c78fe4d4 100644
--- a/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
+++ b/src/components/date_picker/super_date_picker/date_popover/absolute_tab.js
@@ -10,39 +10,40 @@ import { EuiFormRow, EuiFieldText } from '../../../form';
const INPUT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss.SSS';
-const toMoment = (value, roundUp) => {
- const valueAsMoment = dateMath.parse(value, { roundUp });
- return {
- valueAsMoment,
- textInputValue: valueAsMoment.format(INPUT_DATE_FORMAT)
- };
-};
-
export class EuiAbsoluteTab extends Component {
- state = {}
+ constructor(props) {
+ super(props);
- static getDerivedStateFromProps = (nextProps) => {
- return {
- ...toMoment(nextProps.value, nextProps.roundUp),
+ const valueAsMoment = dateMath.parse(props.value, { roundUp: props.roundUp });
+ this.state = {
+ valueAsMoment,
+ textInputValue: valueAsMoment.format(INPUT_DATE_FORMAT),
isTextInvalid: false,
};
}
handleChange = (date) => {
this.props.onChange(date.toISOString());
+ this.setState({
+ valueAsMoment: date,
+ textInputValue: date.format(INPUT_DATE_FORMAT),
+ isTextInvalid: false,
+ });
}
handleTextChange = (evt) => {
const date = moment(evt.target.value, INPUT_DATE_FORMAT, true);
+ const updatedState = {
+ textInputValue: evt.target.value,
+ isTextInvalid: !date.isValid()
+ };
if (date.isValid()) {
this.props.onChange(date.toISOString());
+ updatedState.valueAsMoment = date;
}
- this.setState({
- textInputValue: evt.target.value,
- isTextInvalid: !date.isValid()
- });
+ this.setState(updatedState);
}
render() {
@@ -52,7 +53,7 @@ export class EuiAbsoluteTab extends Component {
inline
showTimeSelect
shadow={false}
- selected={this.state.value}
+ selected={this.state.valueAsMoment}
onChange={this.handleChange}
/>
{
- const relativeParts = parseRelativeParts(nextProps.value);
- // parseRelativeParts will always return unit of 's' when the count is zero
- // Do not override state.unit when count is zero to allow users to set the unit when count is zero
- if (relativeParts.count === 0) {
- delete relativeParts.unit;
- }
- return {
- ...relativeParts,
- };
- }
-
onCountChange = (evt) => {
const sanitizedValue = parseInt(evt.target.value, 10);
this.setState({
diff --git a/src/components/date_picker/super_date_picker/index.js b/src/components/date_picker/super_date_picker/index.js
index 35eb266d870..beb571ca393 100644
--- a/src/components/date_picker/super_date_picker/index.js
+++ b/src/components/date_picker/super_date_picker/index.js
@@ -1,3 +1,5 @@
-export {
- EuiSuperDatePicker,
-} from './super_date_picker';
+import {
+ WrappedEuiSuperDatePicker,
+} from './wrapped_super_date_picker';
+
+export { WrappedEuiSuperDatePicker as EuiSuperDatePicker };
diff --git a/src/components/date_picker/super_date_picker/pretty_duration.js b/src/components/date_picker/super_date_picker/pretty_duration.js
index ed357c1841b..feb9fe2ff58 100644
--- a/src/components/date_picker/super_date_picker/pretty_duration.js
+++ b/src/components/date_picker/super_date_picker/pretty_duration.js
@@ -5,7 +5,7 @@ import { timeUnits, timeUnitsPlural } from './time_units';
import { getDateMode, DATE_MODES } from './date_modes';
import { parseRelativeParts } from './relative_utils';
-const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.sssZ';
+const ISO_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
function cantLookup(timeFrom, timeTo, dateFormat) {
const displayFrom = formatTimeString(timeFrom, dateFormat);
diff --git a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
index 8c0ecc1d1d1..59f741b060c 100644
--- a/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
+++ b/src/components/date_picker/super_date_picker/quick_select_popover/refresh_interval.js
@@ -35,11 +35,11 @@ function convertMilliseconds(milliseconds) {
export class EuiRefreshInterval extends Component {
- state = {}
+ constructor(props) {
+ super(props);
- static getDerivedStateFromProps = (nextProps) => {
- const { value, units } = convertMilliseconds(nextProps.refreshInterval);
- return {
+ const { value, units } = convertMilliseconds(props.refreshInterval);
+ this.state = {
value,
units,
};
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 e331f1a7483..1ac6ceb7c69 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
@@ -35,22 +35,6 @@ export class EuiSuperDatePicker extends Component {
};
}
- static getDerivedStateFromProps = (nextProps) => {
- const {
- start,
- end,
- commonlyUsedRanges
- } = nextProps;
-
- return {
- start,
- end,
- isInvalid: false,
- hasChanged: false,
- showPrettyDuration: showPrettyDuration(start, end, commonlyUsedRanges),
- };
- }
-
setTootipRef = node => (this.tooltip = node);
showTooltip = () => this.tooltip.showToolTip();
diff --git a/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js b/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
new file mode 100644
index 00000000000..f9bbbaad52e
--- /dev/null
+++ b/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
@@ -0,0 +1,20 @@
+import React from 'react';
+import { EuiSuperDatePicker } from './super_date_picker';
+
+// 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 (
+
+ );
+}
+
+WrappedEuiSuperDatePicker.defaultProps = {
+ start: 'now-15m',
+ end: 'now',
+};
From 97bc8726f83d2a125ccd78ff45a65d407aac6e72 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 14 Dec 2018 14:33:56 -0700
Subject: [PATCH 34/37] move changelog message under master section
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index df6a2f43c83..f334039e324 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
## [`master`](https://github.com/elastic/eui/tree/master)
- Added `DisambiguateSet` and `ExclusiveUnion` utility types ([#1368](https://github.com/elastic/eui/pull/1368))
+- Added `EuiSuperDatePicker` component ([#1351](https://github.com/elastic/eui/pull/1351))
**Bug fixes**
@@ -40,7 +41,6 @@
- Convert `EuiIcon` to TypeScript ([#1355](https://github.com/elastic/eui/pull/1355))
- Add support for `aria-label`, `aria-labelledby` and `aria-describedby` to `EuiCodeEditor` ([#1354](https://github.com/elastic/eui/pull/1354))
-- Added `EuiSuperDatePicker` component ([#1351](https://github.com/elastic/eui/pull/1351))
**Bug fixes**
From df7fc4f3938539b52eefbfb8993c00fd6d6eeb87 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 14 Dec 2018 15:01:19 -0700
Subject: [PATCH 35/37] moved prop types to Wrapped component so they are
usable in docs
---
.../date_picker/super_date_picker/index.js | 2 +-
.../super_date_picker/super_date_picker.js | 132 ++++++++++--------
.../wrapped_super_date_picker.js | 20 ---
3 files changed, 75 insertions(+), 79 deletions(-)
delete mode 100644 src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
diff --git a/src/components/date_picker/super_date_picker/index.js b/src/components/date_picker/super_date_picker/index.js
index beb571ca393..183a5d85800 100644
--- a/src/components/date_picker/super_date_picker/index.js
+++ b/src/components/date_picker/super_date_picker/index.js
@@ -1,5 +1,5 @@
import {
WrappedEuiSuperDatePicker,
-} from './wrapped_super_date_picker';
+} 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 1ac6ceb7c69..9b12ebc371f 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,6 +15,78 @@ import { EuiButton, EuiButtonEmpty } 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 (
+
+ );
+}
+
+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),
+};
+
+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: [],
+};
+
export class EuiSuperDatePicker extends Component {
constructor(props) {
@@ -216,62 +288,6 @@ export class EuiSuperDatePicker extends Component {
}
}
-EuiSuperDatePicker.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),
-};
-
-EuiSuperDatePicker.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: [],
-};
+EuiSuperDatePicker.propTypes = WrappedEuiSuperDatePicker.propTypes;
+EuiSuperDatePicker.defaultProps = WrappedEuiSuperDatePicker.defaultProps;
diff --git a/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js b/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
deleted file mode 100644
index f9bbbaad52e..00000000000
--- a/src/components/date_picker/super_date_picker/wrapped_super_date_picker.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import { EuiSuperDatePicker } from './super_date_picker';
-
-// 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 (
-
- );
-}
-
-WrappedEuiSuperDatePicker.defaultProps = {
- start: 'now-15m',
- end: 'now',
-};
From 88236cb41d1722f7564c9cfed23272bd7fc7d4d8 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 14 Dec 2018 15:19:55 -0700
Subject: [PATCH 36/37] check component is mounted for show and hide tooltip
---
.../super_date_picker/super_date_picker.js | 22 +++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
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 9b12ebc371f..97756ccd20b 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
@@ -107,10 +107,28 @@ export class EuiSuperDatePicker extends Component {
};
}
+ componentWillUnmount() {
+ this._isMounted = false;
+ }
+
+ componentDidMount() {
+ this._isMounted = true;
+ }
+
setTootipRef = node => (this.tooltip = node);
- showTooltip = () => this.tooltip.showToolTip();
- hideTooltip = () => this.tooltip.hideToolTip();
+ showTooltip = () => {
+ if (!this._isMounted) {
+ return;
+ }
+ this.tooltip.showToolTip();
+ }
+ hideTooltip = () => {
+ if (!this._isMounted) {
+ return;
+ }
+ this.tooltip.hideToolTip();
+ }
setTime = ({ start, end }) => {
const startMoment = dateMath.parse(start);
From 95100c9c53232bf4b49e24cf192690cb630f12b2 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Fri, 14 Dec 2018 17:09:51 -0700
Subject: [PATCH 37/37] update to datemath dependency with moment as peer
---
package.json | 3 ++-
yarn.lock | 21 ++++-----------------
2 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/package.json b/package.json
index c30bf4912e5..75d156b0970 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,6 @@
"url": "https://github.com/elastic/eui.git"
},
"dependencies": {
- "@elastic/datemath": "5.0.0",
"@types/numeral": "^0.0.25",
"classnames": "^2.2.5",
"core-js": "^2.5.1",
@@ -70,6 +69,7 @@
"@babel/preset-env": "^7.1.0",
"@babel/preset-react": "^7.0.0",
"@babel/preset-typescript": "^7.1.0",
+ "@elastic/datemath": "^5.0.2",
"@elastic/eslint-config-kibana": "^0.15.0",
"@types/classnames": "^2.2.6",
"@types/enzyme": "^3.1.13",
@@ -171,6 +171,7 @@
"yo": "^2.0.0"
},
"peerDependencies": {
+ "@elastic/datemath": "^5.0.2",
"moment": "^2.13.0",
"prop-types": "^15.5.0",
"react": "^16.3",
diff --git a/yarn.lock b/yarn.lock
index 8be47d609d4..28e52972457 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -780,12 +780,11 @@
lodash "^4.17.10"
to-fast-properties "^2.0.0"
-"@elastic/datemath@5.0.0":
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/@elastic/datemath/-/datemath-5.0.0.tgz#62900ddbdc1c98b2af824073be462c769c582a34"
- integrity sha512-csUO6qyWK0LKrX9V8WUnZZ2BBy0pB1nf8nNKw+KQz+PbKQeCr30jtk+2+z/u4DWMCQKODa5V5E8C8f9eNmkD9Q==
+"@elastic/datemath@^5.0.2":
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/@elastic/datemath/-/datemath-5.0.2.tgz#1e62fe7137acd6ebcde9a794ef22b91820c9e6cf"
+ integrity sha512-MYU7KedGPMYu3ljgrO3tY8I8rD73lvBCltd78k5avDIv/6gMbuhKXsMhkEPbb9angs9hR/2ADk0QcGbVxUBXUw==
dependencies:
- moment "^2.13.0"
tslib "^1.9.3"
"@elastic/eslint-config-kibana@^0.15.0":
@@ -8813,23 +8812,11 @@ mocha@^5.0.0, mocha@^5.0.4:
mkdirp "0.5.1"
supports-color "4.4.0"
-moment-timezone@^0.5.14:
- version "0.5.23"
- resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463"
- integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==
- dependencies:
- moment ">= 2.9.0"
-
moment@2.x.x:
version "2.21.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
integrity sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==
-"moment@>= 2.9.0", moment@^2.13.0:
- version "2.22.2"
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
- integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
-
moment@^2.20.1:
version "2.20.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"