Skip to content

Commit

Permalink
feat: support localization in date filter (#5572)
Browse files Browse the repository at this point in the history
  • Loading branch information
sjaanus committed Dec 8, 2023
1 parent b6f1929 commit 166432b
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 19 deletions.
18 changes: 13 additions & 5 deletions frontend/src/component/common/FilterDateItem/FilterDateItem.tsx
Expand Up @@ -4,8 +4,10 @@ import { StyledPopover } from '../FilterItem/FilterItem.styles';
import { FilterItemChip } from '../FilterItem/FilterItemChip/FilterItemChip';
import { FilterItem } from '../FilterItem/FilterItem';
import { DateCalendar, LocalizationProvider } from '@mui/x-date-pickers';
import { parseISO, format } from 'date-fns';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { format } from 'date-fns';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { getLocalizedDateString } from '../util';

interface IFilterDateItemProps {
label: string;
Expand All @@ -24,7 +26,7 @@ export const FilterDateItem: FC<IFilterDateItemProps> = ({
}) => {
const ref = useRef<HTMLDivElement>(null);
const [anchorEl, setAnchorEl] = useState<HTMLDivElement | null>(null);
const [searchText, setSearchText] = useState('');
const { locationSettings } = useLocationSettings();

const onClick = () => {
setAnchorEl(ref.current);
Expand All @@ -34,18 +36,24 @@ export const FilterDateItem: FC<IFilterDateItemProps> = ({
setAnchorEl(null);
};

const selectedOptions = state ? state.values : [];
const selectedOptions = state
? [
getLocalizedDateString(
state.values[0],
locationSettings.locale,
) || '',
]
: [];
const selectedDate = state ? new Date(state.values[0]) : null;
const currentOperator = state ? state.operator : operators[0];

const onDelete = () => {
onChange(undefined);
onClose();
onChipClose();
};

const setValue = (value: Date | null) => {
const formattedValue = value ? format(value, 'MM/dd/yyyy') : '';
const formattedValue = value ? format(value, 'yyyy-MM-dd') : '';
onChange({ operator: currentOperator, values: [formattedValue] });
};

Expand Down
10 changes: 2 additions & 8 deletions frontend/src/component/common/Table/cells/DateCell/DateCell.tsx
@@ -1,21 +1,15 @@
import { VFC } from 'react';
import { useLocationSettings } from 'hooks/useLocationSettings';
import { formatDateYMD } from 'utils/formatDate';
import { parseISO } from 'date-fns';
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import { getLocalizedDateString } from '../../../util';

interface IDateCellProps {
value?: Date | string | null;
}

export const DateCell: VFC<IDateCellProps> = ({ value }) => {
const { locationSettings } = useLocationSettings();

const date = value
? value instanceof Date
? formatDateYMD(value, locationSettings.locale)
: formatDateYMD(parseISO(value), locationSettings.locale)
: undefined;
const date = getLocalizedDateString(value, locationSettings.locale);

return <TextCell lineClamp={1}>{date}</TextCell>;
};
15 changes: 14 additions & 1 deletion frontend/src/component/common/util.ts
Expand Up @@ -2,8 +2,9 @@ import { weightTypes } from 'constants/weightTypes';
import { IUiConfig } from 'interfaces/uiConfig';
import { INavigationMenuItem } from 'interfaces/route';
import { IFeatureVariant } from 'interfaces/featureToggle';
import { format, isValid } from 'date-fns';
import { format, isValid, parseISO } from 'date-fns';
import { IFeatureVariantEdit } from 'component/feature/FeatureView/FeatureVariants/FeatureEnvironmentVariants/EnvironmentVariantsModal/EnvironmentVariantsModal';
import { formatDateYMD } from '../../utils/formatDate';

/**
* Handle feature flags and configuration for different plans.
Expand Down Expand Up @@ -48,6 +49,18 @@ export const trim = (value: string): string => {
}
};

export const getLocalizedDateString = (
value: Date | string | null | undefined,
locale: string,
) => {
const date = value
? value instanceof Date
? formatDateYMD(value, locale)
: formatDateYMD(parseISO(value), locale)
: undefined;
return date;
};

export const parseDateValue = (value: string) => {
const date = new Date(value);
return `${format(date, 'yyyy-MM-dd')}T${format(date, 'HH:mm')}`;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/features/feature-search/feature.search.e2e.test.ts
Expand Up @@ -829,13 +829,13 @@ test('should search features by created date with operators', async () => {
createdAt: '2023-01-29T15:21:39.975Z',
});

const { body } = await filterFeaturesByCreated('IS_BEFORE:01/28/2023');
const { body } = await filterFeaturesByCreated('IS_BEFORE:2023-01-28');
expect(body).toMatchObject({
features: [{ name: 'my_feature_a' }],
});

const { body: afterBody } = await filterFeaturesByCreated(
'IS_ON_OR_AFTER:01/28/2023',
'IS_ON_OR_AFTER:2023-01-28',
);
expect(afterBody).toMatchObject({
features: [{ name: 'my_feature_b' }],
Expand All @@ -861,7 +861,7 @@ test('should filter features by combined operators', async () => {
const { body } = await filterFeaturesByOperators(
'IS_NOT:active',
'DO_NOT_INCLUDE:simple:my_tag',
'IS_BEFORE:01/28/2023',
'IS_BEFORE:2023-01-28',
);
expect(body).toMatchObject({
features: [{ name: 'my_feature_a' }],
Expand Down
4 changes: 2 additions & 2 deletions src/lib/openapi/spec/feature-search-query-parameters.ts
Expand Up @@ -137,8 +137,8 @@ export const featureSearchQueryParameters = [
name: 'createdAt',
schema: {
type: 'string',
example: 'IS_ON_OR_AFTER:28/01/2023',
pattern: '^(IS_BEFORE|IS_ON_OR_AFTER):\\d{2}\\/\\d{2}\\/\\d{4}$',
example: 'IS_ON_OR_AFTER:2023-01-28',
pattern: '^(IS_BEFORE|IS_ON_OR_AFTER):\\d{4}-\\d{2}-\\d{2}$',
},
description:
'The date the feature was created. The date can be specified with an operator. The supported operators are IS_BEFORE, IS_ON_OR_AFTER.',
Expand Down

0 comments on commit 166432b

Please sign in to comment.