feat: rename RICH_TEXT_V2 → RICH_TEXT in codebase (keep DB value) (#18628)

## Summary

- Renames the `FieldMetadataType` enum key from `RICH_TEXT_V2` to
`RICH_TEXT` across the entire codebase, while keeping the underlying
string value as `'RICH_TEXT_V2'` to maintain PostgreSQL database
compatibility
- Renames all related types, guards, hooks, components, and files from
`*RichTextV2*` / `*rich-text-v2*` to `*RichText*` / `*rich-text*` (e.g.
`FormRichTextV2FieldInput` → `FormRichTextFieldInput`,
`isFieldRichTextV2` → `isFieldRichText`)
- Updates generated files (GraphQL schema, SDK types) to use the new key
while preserving the `RICH_TEXT_V2` string value for DB/API layer
- Updates i18n locale files, test snapshots, and integration tests to
reflect the rename

## Context

The legacy `RICH_TEXT` (V1) field type was deprecated and migrated to
`TEXT` in a previous PR (#18623). With V1 gone, the `RICH_TEXT_V2`
naming is no longer necessary — `RICH_TEXT` is now the canonical name.
The DB enum value stays `'RICH_TEXT_V2'` to avoid confusion with the
just-deprecated V1 type and to prevent a database migration.

## Test plan

- [x] `twenty-server` typecheck passes
- [x] `twenty-front` typecheck passes (only pre-existing Apollo client
errors remain)
- [x] `twenty-server` lint passes
- [x] `twenty-front` lint passes
- [x] `twenty-shared` build passes
- [ ] CI passes


Made with [Cursor](https://cursor.com)
This commit is contained in:
Charles Bochet
2026-03-13 19:07:55 +01:00
committed by GitHub
parent 3054679411
commit d9eb317bb5
129 changed files with 452 additions and 401 deletions
@@ -40,7 +40,7 @@ export const COMPOSITE_FIELD_TYPE_SUB_FIELDS_NAMES = {
workspaceMemberId: 'workspaceMemberId',
context: 'context',
},
[FieldMetadataType.RICH_TEXT_V2]: {
[FieldMetadataType.RICH_TEXT]: {
blocknote: 'blocknote',
markdown: 'markdown',
},
@@ -18,4 +18,5 @@ export enum FeatureFlagKey {
IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED = 'IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED',
IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED = 'IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED',
IS_DRAFT_EMAIL_ENABLED = 'IS_DRAFT_EMAIL_ENABLED',
IS_RICH_TEXT_V1_MIGRATED = 'IS_RICH_TEXT_V1_MIGRATED',
}
@@ -15,7 +15,7 @@ export type FieldMetadataDefaultValueUuidFunction =
export type FieldMetadataDefaultValueNowFunction =
typeof fieldMetadataDefaultValueFunctionName.NOW;
export type FieldMetadataDefaultValueRichTextV2 = {
export type FieldMetadataDefaultValueRichText = {
blocknote: string | null;
markdown: string | null;
};
@@ -90,7 +90,7 @@ export type FieldMetadataDefaultValueMapping = {
[FieldMetadataType.SELECT]: string | null;
[FieldMetadataType.MULTI_SELECT]: string[] | null;
[FieldMetadataType.RAW_JSON]: object | null;
[FieldMetadataType.RICH_TEXT_V2]: FieldMetadataDefaultValueRichTextV2 | null;
[FieldMetadataType.RICH_TEXT]: FieldMetadataDefaultValueRichText | null;
[FieldMetadataType.ACTOR]: FieldMetadataDefaultActor | null;
[FieldMetadataType.ARRAY]: string[] | null;
};
@@ -19,7 +19,7 @@ export enum FieldMetadataType {
RATING = 'RATING',
RAW_JSON = 'RAW_JSON',
RELATION = 'RELATION',
RICH_TEXT_V2 = 'RICH_TEXT_V2',
RICH_TEXT = 'RICH_TEXT',
SELECT = 'SELECT',
TEXT = 'TEXT',
TS_VECTOR = 'TS_VECTOR',
@@ -146,13 +146,13 @@ export type FilesFilter = {
is?: IsFilter;
};
export type RichTextV2LeafFilter = {
export type RichTextLeafFilter = {
ilike?: string;
};
export type RichTextV2Filter = {
blocknote?: RichTextV2LeafFilter;
markdown?: RichTextV2LeafFilter;
export type RichTextFilter = {
blocknote?: RichTextLeafFilter;
markdown?: RichTextLeafFilter;
};
export type TSVectorFilter = {
@@ -176,7 +176,7 @@ export type LeafFilter =
| ArrayFilter
| RawJsonFilter
| FilesFilter
| RichTextV2Filter
| RichTextFilter
| TSVectorFilter
| undefined;
@@ -7,7 +7,7 @@ import { emailsCompositeType } from './emails.composite-type';
import { fullNameCompositeType } from './full-name.composite-type';
import { linksCompositeType } from './links.composite-type';
import { phonesCompositeType } from './phones.composite-type';
import { richTextV2CompositeType } from './rich-text-v2.composite-type';
import { richTextCompositeType } from './rich-text.composite-type';
export const compositeTypeDefinitions = new Map<
FieldMetadataType,
@@ -20,5 +20,5 @@ export const compositeTypeDefinitions = new Map<
[FieldMetadataType.ACTOR, actorCompositeType],
[FieldMetadataType.EMAILS, emailsCompositeType],
[FieldMetadataType.PHONES, phonesCompositeType],
[FieldMetadataType.RICH_TEXT_V2, richTextV2CompositeType],
[FieldMetadataType.RICH_TEXT, richTextCompositeType],
]);
@@ -2,8 +2,8 @@ import { z } from 'zod';
import { FieldMetadataType } from '../FieldMetadataType';
import { type CompositeType } from '../composite-types/composite-type.interface';
export const richTextV2CompositeType: CompositeType = {
type: FieldMetadataType.RICH_TEXT_V2,
export const richTextCompositeType: CompositeType = {
type: FieldMetadataType.RICH_TEXT,
properties: [
{
name: 'blocknote',
@@ -21,9 +21,9 @@ export const richTextV2CompositeType: CompositeType = {
};
// with import only markdown subfield is filled, then blocknote is undefined
export const richTextV2ValueSchema = z.object({
export const richTextValueSchema = z.object({
blocknote: z.string().nullable().optional(),
markdown: z.string().nullable(),
});
export type RichTextV2Metadata = z.infer<typeof richTextV2ValueSchema>;
export type RichTextMetadata = z.infer<typeof richTextValueSchema>;
+7 -7
View File
@@ -46,11 +46,11 @@ export type {
PhonesMetadata,
} from './composite-types/phones.composite-type';
export { phonesCompositeType } from './composite-types/phones.composite-type';
export type { RichTextV2Metadata } from './composite-types/rich-text-v2.composite-type';
export type { RichTextMetadata } from './composite-types/rich-text.composite-type';
export {
richTextV2CompositeType,
richTextV2ValueSchema,
} from './composite-types/rich-text-v2.composite-type';
richTextCompositeType,
richTextValueSchema,
} from './composite-types/rich-text.composite-type';
export type { CompositeFieldSubFieldName } from './CompositeFieldSubFieldNameType';
export type { ConfigVariableValue } from './ConfigVariableValue';
export { ConnectedAccountProvider } from './ConnectedAccountProvider';
@@ -71,7 +71,7 @@ export type {
FieldMetadataDefaultValueFunctionNames,
FieldMetadataDefaultValueUuidFunction,
FieldMetadataDefaultValueNowFunction,
FieldMetadataDefaultValueRichTextV2,
FieldMetadataDefaultValueRichText,
FieldMetadataDefaultValueCurrency,
FieldMetadataDefaultValueFullName,
FieldMetadataDefaultValueAddress,
@@ -217,8 +217,8 @@ export type {
ArrayFilter,
RawJsonFilter,
FilesFilter,
RichTextV2LeafFilter,
RichTextV2Filter,
RichTextLeafFilter,
RichTextFilter,
TSVectorFilter,
LeafFilter,
AndObjectRecordFilter,
@@ -2,7 +2,7 @@ import { FieldMetadataType } from '@/types';
import { isFieldMetadataTextKind } from '../isFieldMetadataTextKind';
describe('isFieldMetadataTextKind', () => {
it.each([FieldMetadataType.TEXT, FieldMetadataType.RICH_TEXT_V2])(
it.each([FieldMetadataType.TEXT, FieldMetadataType.RICH_TEXT])(
'should return true for %s',
(type) => {
expect(isFieldMetadataTextKind(type)).toBe(true);
@@ -2,7 +2,7 @@ import { FieldMetadataType } from '@/types';
const TEXT_FIELD_TYPES: FieldMetadataType[] = [
FieldMetadataType.TEXT,
FieldMetadataType.RICH_TEXT_V2,
FieldMetadataType.RICH_TEXT,
];
export const isFieldMetadataTextKind = (
@@ -24,7 +24,7 @@ export * from './utils/isMatchingFloatFilter';
export * from './utils/isMatchingMultiSelectFilter';
export * from './utils/isMatchingRatingFilter';
export * from './utils/isMatchingRawJsonFilter';
export * from './utils/isMatchingRichTextV2Filter';
export * from './utils/isMatchingRichTextFilter';
export * from './utils/isMatchingSelectFilter';
export * from './utils/isMatchingStringFilter';
export * from './utils/isMatchingTSVectorFilter';
@@ -1,11 +1,11 @@
import { isMatchingRichTextV2Filter } from '@/utils/filter/utils/isMatchingRichTextV2Filter';
import { isMatchingRichTextFilter } from '@/utils/filter/utils/isMatchingRichTextFilter';
describe('isMatchingRichTextV2Filter', () => {
describe('isMatchingRichTextFilter', () => {
describe('markdown ilike', () => {
it('should match with wildcard pattern', () => {
expect(
isMatchingRichTextV2Filter({
richTextV2Filter: { markdown: { ilike: '%hello%' } },
isMatchingRichTextFilter({
richTextFilter: { markdown: { ilike: '%hello%' } },
value: 'say hello world',
}),
).toBe(true);
@@ -13,8 +13,8 @@ describe('isMatchingRichTextV2Filter', () => {
it('should not match when pattern does not match', () => {
expect(
isMatchingRichTextV2Filter({
richTextV2Filter: { markdown: { ilike: '%goodbye%' } },
isMatchingRichTextFilter({
richTextFilter: { markdown: { ilike: '%goodbye%' } },
value: 'say hello world',
}),
).toBe(false);
@@ -22,8 +22,8 @@ describe('isMatchingRichTextV2Filter', () => {
it('should be case insensitive', () => {
expect(
isMatchingRichTextV2Filter({
richTextV2Filter: { markdown: { ilike: '%HELLO%' } },
isMatchingRichTextFilter({
richTextFilter: { markdown: { ilike: '%HELLO%' } },
value: 'say hello world',
}),
).toBe(true);
@@ -33,11 +33,11 @@ describe('isMatchingRichTextV2Filter', () => {
describe('default', () => {
it('should throw for unexpected filter', () => {
expect(() =>
isMatchingRichTextV2Filter({
richTextV2Filter: {} as any,
isMatchingRichTextFilter({
richTextFilter: {} as any,
value: 'test',
}),
).toThrow('Unexpected value for RICH_TEXT_V2 filter');
).toThrow('Unexpected value for RICH_TEXT filter');
});
});
});
@@ -0,0 +1,25 @@
import { type RichTextFilter } from '@/types';
import escapeRegExp from 'lodash.escaperegexp';
export const isMatchingRichTextFilter = ({
richTextFilter,
value,
}: {
richTextFilter: RichTextFilter;
value: string;
}) => {
switch (true) {
case richTextFilter.markdown !== undefined: {
const escapedPattern = escapeRegExp(richTextFilter.markdown.ilike);
const regexPattern = escapedPattern.replace(/%/g, '.*');
const regexCaseInsensitive = new RegExp(`^${regexPattern}$`, 'i');
return regexCaseInsensitive.test(value);
}
default: {
throw new Error(
`Unexpected value for RICH_TEXT filter : ${JSON.stringify(richTextFilter)}`,
);
}
}
};
@@ -1,25 +0,0 @@
import { type RichTextV2Filter } from '@/types';
import escapeRegExp from 'lodash.escaperegexp';
export const isMatchingRichTextV2Filter = ({
richTextV2Filter,
value,
}: {
richTextV2Filter: RichTextV2Filter;
value: string;
}) => {
switch (true) {
case richTextV2Filter.markdown !== undefined: {
const escapedPattern = escapeRegExp(richTextV2Filter.markdown.ilike);
const regexPattern = escapedPattern.replace(/%/g, '.*');
const regexCaseInsensitive = new RegExp(`^${regexPattern}$`, 'i');
return regexCaseInsensitive.test(value);
}
default: {
throw new Error(
`Unexpected value for RICH_TEXT_V2 filter : ${JSON.stringify(richTextV2Filter)}`,
);
}
}
};
+1 -1
View File
@@ -117,7 +117,7 @@ export { isMatchingFloatFilter } from './filter/utils/isMatchingFloatFilter';
export { isMatchingMultiSelectFilter } from './filter/utils/isMatchingMultiSelectFilter';
export { isMatchingRatingFilter } from './filter/utils/isMatchingRatingFilter';
export { isMatchingRawJsonFilter } from './filter/utils/isMatchingRawJsonFilter';
export { isMatchingRichTextV2Filter } from './filter/utils/isMatchingRichTextV2Filter';
export { isMatchingRichTextFilter } from './filter/utils/isMatchingRichTextFilter';
export { isMatchingSelectFilter } from './filter/utils/isMatchingSelectFilter';
export { isMatchingStringFilter } from './filter/utils/isMatchingStringFilter';
export { isMatchingTSVectorFilter } from './filter/utils/isMatchingTSVectorFilter';