Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiSuperDatePicker] Support restricted date range #8071

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions packages/eui/changelogs/upcoming/8071.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Added props `minDate` and `maxDate` on `EuiSuperDatePicker` to support restricting date range selections

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const superDatePickerPatternSource = require('!!raw-loader!./super_date_picker_p
import SuperDatePickerLocale from './super_date_picker_locale';
const superDatePickerLocaleSource = require('!!raw-loader!./super_date_picker_locale');

import SuperDatePickerRangeRestricted from './super_date_picker_range_restricted';
const superDatePickerRangeRestrictedSource = require('!!raw-loader!./super_date_picker_range_restricted');

const superDatePickerSnippet = `<EuiSuperDatePicker
onTimeChange={onTimeChange}
start="now-30m"
Expand Down Expand Up @@ -71,6 +74,15 @@ const superDatePickerLocaleSnippet = `<EuiSuperDatePicker
onTimeChange={onTimeChange}
/>`;

const superDatePickerRangeRestrictedSnippet = `<EuiSuperDatePicker
start="now-1h"
end="now-15m"
minDate={moment('10/01/2024')}
maxDate={moment('11/01/2024')}
dateFormat="MM DD, YYYY"
onTimeChange={onTimeChange}
/>`;

export const SuperDatePickerExample = {
title: 'Super date picker',
intro: (
Expand Down Expand Up @@ -391,5 +403,28 @@ if (!endMoment || !endMoment.isValid()) {
snippet: superDatePickerLocaleSnippet,
demo: <SuperDatePickerLocale />,
},
{
title: 'Restricted Range',
source: [
{
type: GuideSectionTypes.JS,
code: superDatePickerRangeRestrictedSource,
},
],
text: (
<>
<p>
To limit the range from which users can choose a date, you can use{' '}
<EuiCode>minDate</EuiCode> and <EuiCode>maxDate</EuiCode>. By
updating the date input values for <EuiCode>start</EuiCode> and{' '}
<EuiCode>end</EuiCode> users get immediate feedback on what range
values are allowed.
</p>
</>
),
props: { EuiSuperDatePicker },
snippet: superDatePickerRangeRestrictedSnippet,
demo: <SuperDatePickerRangeRestricted />,
},
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useState } from 'react';

import {
EuiSuperDatePicker,
OnTimeChangeProps,
} from '../../../../src/components';
import moment from 'moment';

export default () => {
const [start, setStart] = useState('now-30m');
const [end, setEnd] = useState('now');
const minDate = moment().subtract(1, 'M');
const maxDate = moment().add(1, 'M');

const onTimeChange = ({ start, end }: OnTimeChangeProps) => {
setStart(start);
setEnd(end);
};

return (
<EuiSuperDatePicker
start={start}
end={end}
minDate={minDate}
maxDate={maxDate}
onTimeChange={onTimeChange}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export interface EuiAbsoluteTabProps {
roundUp: boolean;
labelPrefix: string;
utcOffset?: number;
minDate?: Moment;
maxDate?: Moment;
}

export const EuiAbsoluteTab: FunctionComponent<EuiAbsoluteTabProps> = ({
Expand All @@ -55,6 +57,8 @@ export const EuiAbsoluteTab: FunctionComponent<EuiAbsoluteTabProps> = ({
locale,
roundUp,
utcOffset,
minDate,
maxDate,
labelPrefix,
}) => {
const styles = useEuiMemoizedStyles(euiAbsoluteTabDateFormStyles);
Expand Down Expand Up @@ -157,6 +161,8 @@ export const EuiAbsoluteTab: FunctionComponent<EuiAbsoluteTabProps> = ({
timeFormat={timeFormat}
locale={locale}
utcOffset={utcOffset}
minDate={minDate}
maxDate={maxDate}
/>
<EuiFlexGroup
component="form"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import React, {
MouseEventHandler,
} from 'react';
import classNames from 'classnames';
import { LocaleSpecifier } from 'moment'; // eslint-disable-line import/named
import { LocaleSpecifier, Moment } from 'moment'; // eslint-disable-line import/named

import { useEuiMemoizedStyles } from '../../../../services';
import { CommonProps } from '../../../common';
Expand Down Expand Up @@ -46,6 +46,8 @@ export interface EuiDatePopoverButtonProps {
timeFormat: string;
value: string;
utcOffset?: number;
minDate?: Moment;
maxDate?: Moment;
compressed?: boolean;
timeOptions: TimeOptions;
}
Expand All @@ -66,6 +68,8 @@ export const EuiDatePopoverButton: FunctionComponent<
locale,
dateFormat,
utcOffset,
minDate,
maxDate,
timeFormat,
isOpen,
onPopoverToggle,
Expand Down Expand Up @@ -150,6 +154,8 @@ export const EuiDatePopoverButton: FunctionComponent<
position={position}
utcOffset={utcOffset}
timeOptions={timeOptions}
minDate={minDate}
maxDate={maxDate}
/>
</EuiPopover>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import React, { FunctionComponent } from 'react';
import { LocaleSpecifier } from 'moment';
import { LocaleSpecifier, Moment } from 'moment';

import { useEuiMemoizedStyles } from '../../../../services';
import { useEuiPaddingCSS } from '../../../../global_styling';
Expand Down Expand Up @@ -37,6 +37,8 @@ export interface EuiDatePopoverContentProps {
locale?: LocaleSpecifier;
position: 'start' | 'end';
utcOffset?: number;
minDate?: Moment;
maxDate?: Moment;
timeOptions: TimeOptions;
}

Expand All @@ -53,6 +55,8 @@ export const EuiDatePopoverContent: FunctionComponent<
position,
utcOffset,
timeOptions,
minDate,
maxDate,
}) => {
const styles = useEuiMemoizedStyles(euiDatePopoverContentStyles);

Expand Down Expand Up @@ -101,6 +105,8 @@ export const EuiDatePopoverContent: FunctionComponent<
roundUp={roundUp}
labelPrefix={labelPrefix}
utcOffset={utcOffset}
minDate={minDate}
maxDate={maxDate}
/>
),
'data-test-subj': 'superDatePickerAbsoluteTab',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import React from 'react';
import moment from 'moment';
import type { Meta, StoryObj } from '@storybook/react';
import { expect } from '@storybook/test';
import { within } from '../../../../.storybook/test';
Expand Down Expand Up @@ -48,6 +49,8 @@ const meta: Meta<EuiSuperDatePickerProps> = {
isLoading: false,
isQuickSelectOnly: false,
commonlyUsedRanges: [{ start: 'now/d', end: 'now/d', label: 'Today' }],
maxDate: undefined,
minDate: undefined,
},
};
enableFunctionToggleControls(meta, ['onTimeChange']);
Expand Down Expand Up @@ -89,6 +92,28 @@ export const CustomQuickSelectPanel: Story = {
},
};

export const RestrictedRange: Story = {
parameters: {
controls: {
include: [
'dateFormat',
'start',
'end',
'minDate',
'maxDate',
'onTimeChange',
],
},
loki: {
chromeSelector: LOKI_SELECTORS.portal,
},
},
args: {
minDate: moment('10/01/2024'),
maxDate: moment('11/01/2024'),
},
};

function CustomPanel({ applyTime }: { applyTime?: ApplyTime }) {
function applyMyCustomTime() {
applyTime!({ start: 'now-30d', end: 'now+7d' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
EuiSuperDatePicker,
EuiSuperDatePickerProps,
} from './super_date_picker';
import moment from 'moment';

const noop = () => {};

Expand Down Expand Up @@ -396,5 +397,83 @@ describe('EuiSuperDatePicker', () => {
expect(startButton).toHaveTextContent('300 days ago');
});
});

describe('minDate', () => {
const props = {
onTimeChange: noop,
end: 'now',
};

it('is valid when the start value is set after the minDate', () => {
const { container } = render(
<EuiSuperDatePicker
{...props}
start="10/01/2024"
minDate={moment('10/01/2024')}
/>
);

const formWraper = container.querySelector(
'.euiFormControlLayout__childrenWrapper'
)!;

expect(formWraper.className).not.toContain('invalid');
});

it('is invalid when the start value is set before the minDate', () => {
const { container } = render(
<EuiSuperDatePicker
{...props}
start="09/30/2024"
minDate={moment('10/01/2024')}
/>
);

const formWraper = container.querySelector(
'.euiFormControlLayout__childrenWrapper'
)!;

expect(formWraper.className).toContain('invalid');
});
});

describe('maxDate', () => {
const props = {
onTimeChange: noop,
start: '10/01/2024',
};

it('is valid when the end value is set before the maxDate', () => {
const { container } = render(
<EuiSuperDatePicker
{...props}
end="10/31/2024"
maxDate={moment('11/01/2024')}
/>
);

const formWraper = container.querySelector(
'.euiFormControlLayout__childrenWrapper'
)!;

expect(formWraper.className).not.toContain('invalid');
});

it('is invalid when the end date exceeds the maxDate', () => {
const { container } = render(
<EuiSuperDatePicker
{...props}
end="11/02/2024"
maxDate={moment('11/01/2024')}
/>
);

const formWraper = container.querySelector(
'.euiFormControlLayout__childrenWrapper'
)!;

expect(formWraper.className).toContain('invalid');
});
});
});
});
Loading
Loading