Skip to content

Commit

Permalink
[EuiSuperDatePicker] Support restricted date range (#8071)
Browse files Browse the repository at this point in the history
  • Loading branch information
mgadewoll authored and tkajtoch committed Oct 14, 2024
1 parent 3735b63 commit 6426b05
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 8 deletions.
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

0 comments on commit 6426b05

Please sign in to comment.