Date field format display (#11384)

## Introduction

This PR enables functionality discussed in [Layout Date
Formatting](https://github.com/twentyhq/core-team-issues/issues/97).

### TLDR;
It enables greater control of date formatting at the object's field
level by upgrading all DATE and DATE_TIME fields' settings from:

```ts
{
    displayAsRelativeDate: boolean
}
```

to:

```ts

type FieldDateDisplayFormat = 'full_date' | 'relative_date' | 'date' | 'time' | 'year' | 'custom'

{
    displayFormat: FieldDateDisplayFormat
}
```

PR also includes an upgrade command that will update any existing DATE
and DATE_TIME fields to the new settings value

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Félix Malfait <felix@twenty.com>
Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
oliver
2025-04-18 01:00:02 -06:00
committed by GitHub
parent dd0ea2366f
commit 53042cc9dc
33 changed files with 690 additions and 250 deletions

View File

@ -10,13 +10,13 @@ import { PERCENT_AGGREGATE_OPERATION_OPTIONS } from '@/object-record/record-tabl
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { t } from '@lingui/core/macro';
import isEmpty from 'lodash.isempty';
import { FIELD_FOR_TOTAL_COUNT_AGGREGATE_OPERATION } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { formatAmount } from '~/utils/format/formatAmount';
import { formatNumber } from '~/utils/format/number';
import { formatDateString } from '~/utils/string/formatDateString';
import { formatDateTimeString } from '~/utils/string/formatDateTimeString';
import { FIELD_FOR_TOTAL_COUNT_AGGREGATE_OPERATION } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
export const computeAggregateValueAndLabel = ({
data,
@ -63,7 +63,7 @@ export const computeAggregateValueAndLabel = ({
let value;
const displayAsRelativeDate = field?.settings?.displayAsRelativeDate;
const dateFieldSettings = field?.settings;
if (
COUNT_AGGREGATE_OPERATION_OPTIONS.includes(
@ -101,10 +101,10 @@ export const computeAggregateValueAndLabel = ({
value = aggregateValue as string;
value = formatDateTimeString({
value,
displayAsRelativeDate,
timeZone,
dateFormat,
timeFormat,
dateFieldSettings,
});
break;
}
@ -113,9 +113,9 @@ export const computeAggregateValueAndLabel = ({
value = aggregateValue as string;
value = formatDateString({
value,
displayAsRelativeDate,
timeZone,
dateFormat,
dateFieldSettings,
});
break;
}

View File

@ -4,13 +4,9 @@ import { DateDisplay } from '@/ui/field/display/components/DateDisplay';
export const DateFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useDateFieldDisplay();
const displayAsRelativeDate =
fieldDefinition.metadata?.settings?.displayAsRelativeDate;
const dateFieldSettings = fieldDefinition.metadata?.settings;
return (
<DateDisplay
value={fieldValue}
displayAsRelativeDate={displayAsRelativeDate}
/>
<DateDisplay value={fieldValue} dateFieldSettings={dateFieldSettings} />
);
};

View File

@ -4,13 +4,9 @@ import { DateTimeDisplay } from '@/ui/field/display/components/DateTimeDisplay';
export const DateTimeFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useDateTimeFieldDisplay();
const displayAsRelativeDate =
fieldDefinition.metadata?.settings?.displayAsRelativeDate;
const dateFieldSettings = fieldDefinition.metadata?.settings;
return (
<DateTimeDisplay
value={fieldValue}
displayAsRelativeDate={displayAsRelativeDate}
/>
<DateTimeDisplay value={fieldValue} dateFieldSettings={dateFieldSettings} />
);
};

View File

@ -28,18 +28,32 @@ export type FieldTextMetadata = BaseFieldMetadata & {
};
};
export enum FieldDateDisplayFormat {
RELATIVE = 'RELATIVE',
USER_SETTINGS = 'USER_SETTINGS',
CUSTOM = 'CUSTOM',
}
export type FieldDateMetadataSettings =
| {
displayFormat?: FieldDateDisplayFormat.CUSTOM;
customUnicodeDateFormat: string;
}
| {
displayFormat?: Exclude<
FieldDateDisplayFormat,
FieldDateDisplayFormat.CUSTOM
>;
};
export type FieldDateTimeMetadata = BaseFieldMetadata & {
placeHolder: string;
settings?: {
displayAsRelativeDate?: boolean;
};
settings?: FieldDateMetadataSettings;
};
export type FieldDateMetadata = BaseFieldMetadata & {
placeHolder: string;
settings?: {
displayAsRelativeDate?: boolean;
};
settings?: FieldDateMetadataSettings;
};
export type FieldNumberVariant = 'number' | 'percentage';

View File

@ -0,0 +1,6 @@
import { FieldDateDisplayFormat } from '../FieldMetadata';
export const isDateFieldCustomDisplayFormat = (
displayFormat: FieldDateDisplayFormat,
): displayFormat is FieldDateDisplayFormat =>
displayFormat === FieldDateDisplayFormat.CUSTOM;

View File

@ -233,7 +233,7 @@ describe('useRecordData', () => {
relationType: undefined,
targetFieldMetadataName: '',
settings: {
displayAsRelativeDate: true,
displayFormat: 'RELATIVE',
},
},
position: 10,