From 46e515436e616424757909e8c4d04368eca1a836 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Fri, 13 Mar 2026 17:25:40 +0100 Subject: [PATCH] Deprecate legacy RICH_TEXT field metadata type (#18623) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Removes the deprecated `RICH_TEXT` (V1) field metadata type from the codebase entirely - Adds a 1.20 upgrade command that migrates existing `RICH_TEXT` fields to `TEXT` in `core.fieldMetadata` - Cleans up ~70 files across `twenty-shared`, `twenty-server`, `twenty-front`, `twenty-sdk`, and `twenty-zapier` ## Context `RICH_TEXT` was a legacy field type that stored rich text as a single `text` column. It was already **read-only** — writes threw errors directing users to `RICH_TEXT_V2` instead. `RICH_TEXT_V2` is the current approach: a composite type with `blocknote` (editor JSON) and `markdown` subfields. Keeping the deprecated type added maintenance burden without any value. Since the underlying database column type for `RICH_TEXT` was already `text` (same as `TEXT`), the migration only needs to update the metadata — no data migration or column changes required. ## Changes ### Upgrade command (new) - `1-20-migrate-rich-text-to-text.command.ts` — runs `UPDATE core."fieldMetadata" SET "type" = 'TEXT' WHERE "type" = 'RICH_TEXT'` per workspace, with cache invalidation ### Enum & shared types - Removed `RICH_TEXT` from `FieldMetadataType` enum - Removed from `FieldMetadataDefaultValueMapping`, `isFieldMetadataTextKind` ### Server (~30 files) - Removed from type mapper (scalar, filter, order-by), data processors, input transformer, filter operators, zod schemas, column type mapping, searchable fields, RLS matching, OpenAPI schema, fake value generators - Removed from field creation flow and field metadata type validator - Updated dev seeder Pet `bio` field to `TEXT` - Cleaned up mocks, snapshots, integration tests ### Frontend (~25 files) - Deleted: `RichTextFieldDisplay`, `isFieldRichText`, `isFieldRichTextValue`, `useRichTextFieldDisplay` - Removed from `FieldDisplay`, `usePersistField`, `isFieldValueEmpty`, `isRecordMatchingFilter`, `generateEmptyFieldValue`, `isFieldCellSupported`, spreadsheet import, workflow fake values - Removed from settings types, field type configs, and field creation exclusion list - Updated tests, mocks, and stories ### SDK & Zapier - Removed from generated GraphQL schema and TypeScript types - Removed from Zapier `computeInputFields` --- .../src/generated-metadata/graphql.ts | 1 - .../filterSortableFieldMetadataItems.test.ts | 6 +- .../utils/isNonCompositeField.ts | 1 - .../ui/components/FieldDisplay.tsx | 4 - .../record-field/ui/hooks/usePersistField.ts | 7 -- .../components/RichTextFieldDisplay.tsx | 12 -- .../hooks/useRichTextFieldDisplay.ts | 37 ------ .../RichTextFieldInput.stories.tsx | 2 +- .../record-field/ui/types/FieldMetadata.ts | 9 +- .../ui/types/guards/assertFieldMetadata.ts | 17 ++- .../ui/types/guards/isFieldRichText.ts | 12 -- .../ui/types/guards/isFieldRichTextValue.ts | 12 -- .../ui/utils/isFieldValueEmpty.ts | 2 - .../utils/isRecordMatchingFilter.ts | 9 -- .../hooks/useBuildSpreadSheetImportFields.ts | 1 - .../buildRecordFromImportedStructuredRow.ts | 1 - ...ImportFilterAvailableFieldMetadataItems.ts | 8 +- .../utils/generateEmptyFieldValue.ts | 3 - .../utils/isFieldCellSupported.ts | 6 +- .../types/SettingsExcludedFieldType.ts | 2 +- .../__tests__/getSortIconForFieldType.test.ts | 9 -- .../__tests__/generateFakeValue.test.ts | 9 -- .../utils/generate/generateFakeValue.ts | 2 - .../constants/DefaultIconsByFieldType.ts | 1 - .../SettingsObjectNewFieldSelect.tsx | 1 - .../metadata/objects/mock-objects-metadata.ts | 2 +- .../clients/generated/metadata/schema.graphql | 1 - .../src/clients/generated/metadata/schema.ts | 3 +- .../1-20-migrate-rich-text-to-text.command.ts | 114 ++++++++++++++++++ .../1-20-upgrade-version-command.module.ts | 13 +- .../upgrade.command.ts | 3 + .../__mocks__/object-metadata-item.mock.ts | 15 --- .../data-arg-processor.service.spec.ts.snap | 2 - ...-inputs-by-field-metadata-type.constant.ts | 1 - ...-metadata-config-by-field-name.constant.ts | 5 - .../data-arg-processor.service.ts | 1 - .../filter-arg-processor.service.spec.ts.snap | 4 - ...-inputs-by-field-metadata-type.constant.ts | 4 - ...-inputs-by-field-metadata-type.constant.ts | 7 -- .../get-operators-for-field-type.util.ts | 1 - .../services/type-mapper.service.ts | 3 - .../utils/__tests__/components.utils.spec.ts | 12 -- .../utils/generate-random-field-value.util.ts | 1 - .../zod-schemas/field-filters.zod-schema.ts | 1 - .../record-properties.zod-schema.ts | 1 - .../record-input-transformer.service.ts | 4 - .../field-metadata-entity.test-type.ts | 15 --- .../__mocks__/pet-flat-fields.mock.ts | 2 +- ...t-field-metadata-type-validator.service.ts | 1 - .../flat-field-metadata.test-type.ts | 1 - ...-to-flat-field-metadatas-to-create.util.ts | 1 - ...rls-row-level-permission-predicate.util.ts | 9 -- ...ject-metadata-to-schema-properties.util.ts | 3 +- .../src/engine/utils/generate-fake-value.ts | 2 - .../pet-custom-field-seeds.constant.ts | 2 +- ...reate-standard-flat-skill-metadata.util.ts | 2 +- ...ts-vectors-column-expression.utils.spec.ts | 4 +- .../utils/is-searchable-field.util.ts | 1 - .../utils/is-text-column-type.util.ts | 7 +- .../test-object-gql-fields.constant.ts | 1 - ...-input-validation.integration-spec.ts.snap | 5 - ...e-input-by-field-metadata-type.constant.ts | 7 -- ...e-input-by-field-metadata-type.constant.ts | 2 +- ...reate-input-validation.integration-spec.ts | 71 ----------- .../types/field-metadata-type-to-test.ts | 1 - ...get-field-metadata-creation-inputs.util.ts | 6 - .../src/types/FieldMetadataDefaultValue.ts | 1 - .../src/types/FieldMetadataType.ts | 1 - .../__tests__/isFieldMetadataTextKind.test.ts | 13 +- .../fieldMetadata/isFieldMetadataTextKind.ts | 1 - .../src/utils/computeInputFields.ts | 2 - 71 files changed, 165 insertions(+), 368 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/RichTextFieldDisplay.tsx delete mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useRichTextFieldDisplay.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichText.ts delete mode 100644 packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichTextValue.ts create mode 100644 packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command.ts delete mode 100644 packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/rich-text-field-create-input-validation.integration-spec.ts.snap delete mode 100644 packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/rich-text-field-create-input-validation.integration-spec.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 7c9363df44b..c9022dc057f 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1825,7 +1825,6 @@ export enum FieldMetadataType { RATING = 'RATING', RAW_JSON = 'RAW_JSON', RELATION = 'RELATION', - RICH_TEXT = 'RICH_TEXT', RICH_TEXT_V2 = 'RICH_TEXT_V2', SELECT = 'SELECT', TEXT = 'TEXT', diff --git a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/filterSortableFieldMetadataItems.test.ts b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/filterSortableFieldMetadataItems.test.ts index 4e8686db661..94e7c35ccf4 100644 --- a/packages/twenty-front/src/modules/object-metadata/utils/__tests__/filterSortableFieldMetadataItems.test.ts +++ b/packages/twenty-front/src/modules/object-metadata/utils/__tests__/filterSortableFieldMetadataItems.test.ts @@ -96,12 +96,12 @@ describe('filterSortableFieldMetadataItems', () => { expect(filterSortableFieldMetadataItems(field)).toBe(false); }); - it('should NOT allow unsortable field types like RICH_TEXT', () => { + it('should NOT allow unsortable field types like RICH_TEXT_V2', () => { const field = { - type: FieldMetadataType.RICH_TEXT, + type: FieldMetadataType.RICH_TEXT_V2, isSystem: false, isActive: true, - name: 'richText', + name: 'richTextV2', }; expect(filterSortableFieldMetadataItems(field)).toBe(false); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts index 1b2af2422e0..45050684fa6 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/utils/isNonCompositeField.ts @@ -17,7 +17,6 @@ export const isNonCompositeField = (type: FieldType) => { FieldMetadataType.MULTI_SELECT, FieldMetadataType.POSITION, FieldMetadataType.RAW_JSON, - FieldMetadataType.RICH_TEXT, FieldMetadataType.ARRAY, ].includes(type as any); diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/components/FieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/components/FieldDisplay.tsx index 5a8499de8d5..1bccc73ab92 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/components/FieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/components/FieldDisplay.tsx @@ -10,7 +10,6 @@ import { LinksFieldDisplay } from '@/object-record/record-field/ui/meta-types/di import { PhonesFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/PhonesFieldDisplay'; import { RatingFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/RatingFieldDisplay'; import { RelationFromManyFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/RelationFromManyFieldDisplay'; -import { RichTextFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/RichTextFieldDisplay'; import { RichTextV2FieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/RichTextV2FieldDisplay'; import { isFieldIdentifierDisplay } from '@/object-record/record-field/ui/meta-types/display/utils/isFieldIdentifierDisplay'; import { isFieldActor } from '@/object-record/record-field/ui/types/guards/isFieldActor'; @@ -21,7 +20,6 @@ import { isFieldFiles } from '@/object-record/record-field/ui/types/guards/isFie import { isFieldLinks } from '@/object-record/record-field/ui/types/guards/isFieldLinks'; import { isFieldPhones } from '@/object-record/record-field/ui/types/guards/isFieldPhones'; import { isFieldRating } from '@/object-record/record-field/ui/types/guards/isFieldRating'; -import { isFieldRichText } from '@/object-record/record-field/ui/types/guards/isFieldRichText'; import { isFieldRichTextV2 } from '@/object-record/record-field/ui/types/guards/isFieldRichTextV2'; import { MorphRelationManyToOneFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/MorphRelationManyToOneFieldDisplay'; @@ -112,8 +110,6 @@ export const FieldDisplay = () => { ) : isFieldRating(fieldDefinition) ? ( - ) : isFieldRichText(fieldDefinition) ? ( - ) : isFieldRichTextV2(fieldDefinition) ? ( ) : isFieldActor(fieldDefinition) ? ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts index 29d3130e240..0fe2eb7f23c 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/hooks/usePersistField.ts @@ -49,9 +49,7 @@ import { isFieldRating } from '@/object-record/record-field/ui/types/guards/isFi import { isFieldRatingValue } from '@/object-record/record-field/ui/types/guards/isFieldRatingValue'; import { isFieldRelationManyToOne } from '@/object-record/record-field/ui/types/guards/isFieldRelationManyToOne'; import { isFieldRelationManyToOneValue } from '@/object-record/record-field/ui/types/guards/isFieldRelationManyToOneValue'; -import { isFieldRichText } from '@/object-record/record-field/ui/types/guards/isFieldRichText'; import { isFieldRichTextV2 } from '@/object-record/record-field/ui/types/guards/isFieldRichTextV2'; -import { isFieldRichTextValue } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValue'; import { isFieldRichTextV2Value } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValueV2'; import { isFieldText } from '@/object-record/record-field/ui/types/guards/isFieldText'; import { isFieldTextValue } from '@/object-record/record-field/ui/types/guards/isFieldTextValue'; @@ -145,10 +143,6 @@ export const usePersistField = ({ const fieldIsRawJson = isFieldRawJson(fieldDefinition) && isFieldRawJsonValue(valueToPersist); - const fieldIsRichText = - isFieldRichText(fieldDefinition) && - isFieldRichTextValue(valueToPersist); - const fieldIsRichTextV2 = isFieldRichTextV2(fieldDefinition) && isFieldRichTextV2Value(valueToPersist); @@ -185,7 +179,6 @@ export const usePersistField = ({ fieldIsRawJson || fieldIsArray || fieldIsFiles || - fieldIsRichText || fieldIsRichTextV2; if (isValuePersistable) { diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/RichTextFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/RichTextFieldDisplay.tsx deleted file mode 100644 index 479738da34c..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/display/components/RichTextFieldDisplay.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { useRichTextFieldDisplay } from '@/object-record/record-field/ui/meta-types/hooks/useRichTextFieldDisplay'; -import { getFirstNonEmptyLineOfRichText } from '@/blocknote-editor/utils/getFirstNonEmptyLineOfRichText'; - -export const RichTextFieldDisplay = () => { - const { fieldValue } = useRichTextFieldDisplay(); - - return ( -
- {getFirstNonEmptyLineOfRichText(fieldValue)} -
- ); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useRichTextFieldDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useRichTextFieldDisplay.ts deleted file mode 100644 index 7a8064f0b96..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/hooks/useRichTextFieldDisplay.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useContext } from 'react'; - -import { type FieldRichTextValue } from '@/object-record/record-field/ui/types/FieldMetadata'; -import { assertFieldMetadata } from '@/object-record/record-field/ui/types/guards/assertFieldMetadata'; -import { isFieldRichText } from '@/object-record/record-field/ui/types/guards/isFieldRichText'; -import { useRecordFieldValue } from '@/object-record/record-store/hooks/useRecordFieldValue'; -import type { PartialBlock } from '@blocknote/core'; -import { isDefined, parseJson } from 'twenty-shared/utils'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext'; - -export const useRichTextFieldDisplay = () => { - const { recordId, fieldDefinition } = useContext(FieldContext); - - assertFieldMetadata( - FieldMetadataType.RICH_TEXT, - isFieldRichText, - fieldDefinition, - ); - - const fieldName = fieldDefinition.metadata.fieldName; - - const fieldValue = useRecordFieldValue( - recordId, - fieldName, - fieldDefinition, - ); - - const fieldValueParsed = isDefined(fieldValue) - ? parseJson(fieldValue) - : null; - - return { - fieldDefinition, - fieldValue: fieldValueParsed, - }; -}; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/__stories__/RichTextFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/__stories__/RichTextFieldInput.stories.tsx index d1940f7f507..1134d3a7c7e 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/__stories__/RichTextFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/meta-types/input/components/__stories__/RichTextFieldInput.stories.tsx @@ -65,7 +65,7 @@ const RichTextFieldInputWithContext = () => { fieldDefinition: { fieldMetadataId: 'richText', label: 'Rich Text', - type: FieldMetadataType.RICH_TEXT, + type: FieldMetadataType.RICH_TEXT_V2, iconName: 'IconRichText', metadata: { fieldName: 'richText', diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/types/FieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/types/FieldMetadata.ts index f12819776e6..922b73b19a2 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/types/FieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/types/FieldMetadata.ts @@ -135,10 +135,6 @@ export type FieldRichTextV2Metadata = BaseFieldMetadata & { settings?: null; }; -export type FieldRichTextMetadata = BaseFieldMetadata & { - settings?: null; -}; - export type FieldPositionMetadata = BaseFieldMetadata & { settings?: null; }; @@ -229,8 +225,7 @@ export type FieldMetadata = | FieldArrayMetadata | FieldTsVectorMetadata | FieldRawJsonMetadata - | FieldRichTextV2Metadata - | FieldRichTextMetadata; + | FieldRichTextV2Metadata; export type FieldTextValue = string; export type FieldUUidValue = string; // TODO: can we replace with a template literal type, or maybe overkill ? @@ -289,8 +284,6 @@ export type FieldRichTextV2Value = { markdown: string | null; }; -export type FieldRichTextValue = null | string; - const FieldActorSourceSchema = z.union([ z.literal('API'), z.literal('IMPORT'), diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/assertFieldMetadata.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/assertFieldMetadata.ts index dc21e7f9e23..7afe1bfb716 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/assertFieldMetadata.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/assertFieldMetadata.ts @@ -24,7 +24,6 @@ import { type FieldRatingMetadata, type FieldRawJsonMetadata, type FieldRelationMetadata, - type FieldRichTextMetadata, type FieldRichTextV2Metadata, type FieldSelectMetadata, type FieldTextMetadata, @@ -77,15 +76,13 @@ type AssertFieldMetadataFunction = < ? FieldRawJsonMetadata : E extends 'RICH_TEXT_V2' ? FieldRichTextV2Metadata - : E extends 'RICH_TEXT' - ? FieldRichTextMetadata - : E extends 'ACTOR' - ? FieldActorMetadata - : E extends 'ARRAY' - ? FieldArrayMetadata - : E extends 'PHONES' - ? FieldPhonesMetadata - : never, + : E extends 'ACTOR' + ? FieldActorMetadata + : E extends 'ARRAY' + ? FieldArrayMetadata + : E extends 'PHONES' + ? FieldPhonesMetadata + : never, >( fieldType: E, fieldTypeGuard: ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichText.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichText.ts deleted file mode 100644 index 13fada8e50e..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichText.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { FieldMetadataType } from '~/generated-metadata/graphql'; - -import { type FieldDefinition } from '@/object-record/record-field/ui/types/FieldDefinition'; -import { - type FieldMetadata, - type FieldRichTextMetadata, -} from '@/object-record/record-field/ui/types/FieldMetadata'; - -export const isFieldRichText = ( - field: Pick, 'type'>, -): field is FieldDefinition => - field.type === FieldMetadataType.RICH_TEXT; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichTextValue.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichTextValue.ts deleted file mode 100644 index a7627f5a019..00000000000 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/types/guards/isFieldRichTextValue.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { z } from 'zod'; -import { type FieldRichTextValue } from '@/object-record/record-field/ui/types/FieldMetadata'; - -export const richTextSchema: z.ZodType = z.union([ - z.null(), - z.string(), -]); - -export const isFieldRichTextValue = ( - fieldValue: unknown, -): fieldValue is FieldRichTextValue => - richTextSchema.safeParse(fieldValue).success; diff --git a/packages/twenty-front/src/modules/object-record/record-field/ui/utils/isFieldValueEmpty.ts b/packages/twenty-front/src/modules/object-record/record-field/ui/utils/isFieldValueEmpty.ts index cc82fd129ea..a7fca56f654 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/ui/utils/isFieldValueEmpty.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/ui/utils/isFieldValueEmpty.ts @@ -32,7 +32,6 @@ import { isFieldPosition } from '@/object-record/record-field/ui/types/guards/is import { isFieldRating } from '@/object-record/record-field/ui/types/guards/isFieldRating'; import { isFieldRawJson } from '@/object-record/record-field/ui/types/guards/isFieldRawJson'; import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation'; -import { isFieldRichText } from '@/object-record/record-field/ui/types/guards/isFieldRichText'; import { isFieldRichTextV2 } from '@/object-record/record-field/ui/types/guards/isFieldRichTextV2'; import { isFieldRichTextV2Value } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValueV2'; import { isFieldSelect } from '@/object-record/record-field/ui/types/guards/isFieldSelect'; @@ -63,7 +62,6 @@ export const isFieldValueEmpty = ({ isFieldRating(fieldDefinition) || isFieldBoolean(fieldDefinition) || isFieldRawJson(fieldDefinition) || - isFieldRichText(fieldDefinition) || isFieldPosition(fieldDefinition) ) { return isValueEmpty(fieldValue); diff --git a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts index 5e54b8f89f4..72ba06ad493 100644 --- a/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-filter/utils/isRecordMatchingFilter.ts @@ -235,15 +235,6 @@ export const isRecordMatchingFilter = ({ value: record[filterKey], }); } - case FieldMetadataType.RICH_TEXT: { - // TODO: Implement a better rich text filter once it becomes a composite field - // See this issue for more context: https://github.com/twentyhq/twenty/issues/7613#issuecomment-2408944585 - // This should be tackled in Q4'24 - return isMatchingStringFilter({ - stringFilter: filterValue as StringFilter, - value: record[filterKey], - }); - } case FieldMetadataType.RICH_TEXT_V2: { return isMatchingRichTextV2Filter({ richTextV2Filter: filterValue as RichTextV2Filter, diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useBuildSpreadSheetImportFields.ts b/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useBuildSpreadSheetImportFields.ts index 9ddd335b34f..e66676373e0 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useBuildSpreadSheetImportFields.ts +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/hooks/useBuildSpreadSheetImportFields.ts @@ -91,7 +91,6 @@ export const useBuildSpreadsheetImportFields = () => { case FieldMetadataType.MORPH_RELATION: case FieldMetadataType.ACTOR: case FieldMetadataType.TS_VECTOR: - case FieldMetadataType.RICH_TEXT: return []; default: diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow.ts b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow.ts index a8e4243bbcd..628513d0a15 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow.ts +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow.ts @@ -377,7 +377,6 @@ export const buildRecordFromImportedStructuredRow = ({ case FieldMetadataType.FILES: case FieldMetadataType.MORPH_RELATION: case FieldMetadataType.POSITION: - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.TS_VECTOR: break; default: diff --git a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts index a767276c60f..9ba0ca95abf 100644 --- a/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts +++ b/packages/twenty-front/src/modules/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts @@ -13,11 +13,9 @@ export const spreadsheetImportFilterAvailableFieldMetadataItems = ( (!isHiddenSystemField(fieldMetadataItem) || fieldMetadataItem.name === 'id') && fieldMetadataItem.name !== 'deletedAt' && - (![ - FieldMetadataType.RELATION, - FieldMetadataType.RICH_TEXT, - FieldMetadataType.ACTOR, - ].includes(fieldMetadataItem.type) || + (![FieldMetadataType.RELATION, FieldMetadataType.ACTOR].includes( + fieldMetadataItem.type, + ) || fieldMetadataItem.relation?.type === RelationType.MANY_TO_ONE), ) .sort((fieldMetadataItemA, fieldMetadataItemB) => diff --git a/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts b/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts index 4fca3e84055..f50a22ee7db 100644 --- a/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts +++ b/packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts @@ -95,9 +95,6 @@ export const generateEmptyFieldValue = ({ case FieldMetadataType.RAW_JSON: { return null; } - case FieldMetadataType.RICH_TEXT: { - return null; - } case FieldMetadataType.RICH_TEXT_V2: { return { blocknote: null, diff --git a/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts b/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts index 5f79d7ed320..0a6b1131143 100644 --- a/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts +++ b/packages/twenty-front/src/modules/object-record/utils/isFieldCellSupported.ts @@ -9,11 +9,7 @@ export const isFieldCellSupported = ( fieldMetadataItem: FieldMetadataItem, objectMetadataItems: ObjectMetadataItem[], ) => { - if ( - [FieldMetadataType.POSITION, FieldMetadataType.RICH_TEXT].includes( - fieldMetadataItem.type, - ) - ) { + if (fieldMetadataItem.type === FieldMetadataType.POSITION) { return false; } diff --git a/packages/twenty-front/src/modules/settings/data-model/types/SettingsExcludedFieldType.ts b/packages/twenty-front/src/modules/settings/data-model/types/SettingsExcludedFieldType.ts index eed8f20ae9a..49204ec0533 100644 --- a/packages/twenty-front/src/modules/settings/data-model/types/SettingsExcludedFieldType.ts +++ b/packages/twenty-front/src/modules/settings/data-model/types/SettingsExcludedFieldType.ts @@ -3,5 +3,5 @@ import { type PickLiteral } from '~/types/PickLiteral'; export type SettingsExcludedFieldType = PickLiteral< FieldType, - 'POSITION' | 'TS_VECTOR' | 'RICH_TEXT' | 'RICH_TEXT_V2' | 'NUMERIC' + 'POSITION' | 'TS_VECTOR' | 'RICH_TEXT_V2' | 'NUMERIC' >; diff --git a/packages/twenty-front/src/modules/side-panel/pages/page-layout/utils/__tests__/getSortIconForFieldType.test.ts b/packages/twenty-front/src/modules/side-panel/pages/page-layout/utils/__tests__/getSortIconForFieldType.test.ts index db1429ad856..7a9fb9914ce 100644 --- a/packages/twenty-front/src/modules/side-panel/pages/page-layout/utils/__tests__/getSortIconForFieldType.test.ts +++ b/packages/twenty-front/src/modules/side-panel/pages/page-layout/utils/__tests__/getSortIconForFieldType.test.ts @@ -51,15 +51,6 @@ describe('getSortIconForFieldType', () => { ).toBe(IconSortDescendingLetters); }); - it('should return IconSortAscendingLetters for RICH_TEXT field ascending', () => { - expect( - getSortIconForFieldType({ - fieldType: FieldMetadataType.RICH_TEXT, - orderBy: GraphOrderBy.FIELD_ASC, - }), - ).toBe(IconSortAscendingLetters); - }); - it('should return IconSortAscendingLetters for RICH_TEXT_V2 field ascending', () => { expect( getSortIconForFieldType({ diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/__tests__/generateFakeValue.test.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/__tests__/generateFakeValue.test.ts index bf9b690fe24..6ba191820af 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/__tests__/generateFakeValue.test.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/__tests__/generateFakeValue.test.ts @@ -141,15 +141,6 @@ describe('generateFakeValue', () => { expect(result).toBeNull(); }); - it('should generate RICH_TEXT value', () => { - const result = generateFakeValue( - FieldMetadataType.RICH_TEXT, - 'FieldMetadataType', - ); - - expect(result).toBe('My rich text'); - }); - it('should generate UUID value', () => { const result = generateFakeValue( FieldMetadataType.UUID, diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/generateFakeValue.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/generateFakeValue.ts index 6fa9372b933..f5814891149 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/generateFakeValue.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/generate/generateFakeValue.ts @@ -68,8 +68,6 @@ const generateFieldMetadataTypeValue = ( return 'Tim Cook'; case FieldMetadataType.RAW_JSON: return null; - case FieldMetadataType.RICH_TEXT: - return 'My rich text'; case FieldMetadataType.UUID: return '123e4567-e89b-12d3-a456-426614174000'; default: diff --git a/packages/twenty-front/src/pages/settings/data-model/constants/DefaultIconsByFieldType.ts b/packages/twenty-front/src/pages/settings/data-model/constants/DefaultIconsByFieldType.ts index 89495e4f512..da6fb232fdd 100644 --- a/packages/twenty-front/src/pages/settings/data-model/constants/DefaultIconsByFieldType.ts +++ b/packages/twenty-front/src/pages/settings/data-model/constants/DefaultIconsByFieldType.ts @@ -24,7 +24,6 @@ export const DEFAULT_ICONS_BY_FIELD_TYPE: Record = { [FieldMetadataType.ACTOR]: 'IconUsers', [FieldMetadataType.NUMERIC]: 'IconUsers', [FieldMetadataType.POSITION]: 'IconUsers', - [FieldMetadataType.RICH_TEXT]: 'IconUsers', [FieldMetadataType.RICH_TEXT_V2]: 'IconUsers', [FieldMetadataType.TS_VECTOR]: 'IconUsers', }; diff --git a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx index 1545f1d63c7..7f9b47d45e2 100644 --- a/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/new-field/SettingsObjectNewFieldSelect.tsx @@ -47,7 +47,6 @@ export const SettingsObjectNewFieldSelect = () => { const excludedFieldTypes: FieldType[] = ( [ FieldMetadataType.NUMERIC, - FieldMetadataType.RICH_TEXT, FieldMetadataType.RICH_TEXT_V2, FieldMetadataType.ACTOR, FieldMetadataType.UUID, diff --git a/packages/twenty-front/src/testing/mock-data/generated/metadata/objects/mock-objects-metadata.ts b/packages/twenty-front/src/testing/mock-data/generated/metadata/objects/mock-objects-metadata.ts index 398973b8b42..50e494c5436 100644 --- a/packages/twenty-front/src/testing/mock-data/generated/metadata/objects/mock-objects-metadata.ts +++ b/packages/twenty-front/src/testing/mock-data/generated/metadata/objects/mock-objects-metadata.ts @@ -13456,7 +13456,7 @@ export const mockedStandardObjectMetadataQueryResult: ObjectMetadataItemsQuery = "__typename": "Field", "id": "7700d2ac-0643-44a2-acd0-f0bb446bc08c", "universalIdentifier": "107ed3e9-2ae0-43ef-a2d6-3f24bc54c2a5", - "type": "RICH_TEXT", + "type": "TEXT", "name": "bio", "label": "Bio", "description": "", diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql index 514a40c0bb7..ff433001db3 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql @@ -374,7 +374,6 @@ enum FieldMetadataType { RATING RAW_JSON RELATION - RICH_TEXT RICH_TEXT_V2 SELECT TEXT diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts index b3781806b16..db5025569c6 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts @@ -309,7 +309,7 @@ export interface Field { /** Type of the field */ -export type FieldMetadataType = 'ACTOR' | 'ADDRESS' | 'ARRAY' | 'BOOLEAN' | 'CURRENCY' | 'DATE' | 'DATE_TIME' | 'EMAILS' | 'FILES' | 'FULL_NAME' | 'LINKS' | 'MORPH_RELATION' | 'MULTI_SELECT' | 'NUMBER' | 'NUMERIC' | 'PHONES' | 'POSITION' | 'RATING' | 'RAW_JSON' | 'RELATION' | 'RICH_TEXT' | 'RICH_TEXT_V2' | 'SELECT' | 'TEXT' | 'TS_VECTOR' | 'UUID' +export type FieldMetadataType = 'ACTOR' | 'ADDRESS' | 'ARRAY' | 'BOOLEAN' | 'CURRENCY' | 'DATE' | 'DATE_TIME' | 'EMAILS' | 'FILES' | 'FULL_NAME' | 'LINKS' | 'MORPH_RELATION' | 'MULTI_SELECT' | 'NUMBER' | 'NUMERIC' | 'PHONES' | 'POSITION' | 'RATING' | 'RAW_JSON' | 'RELATION' | 'RICH_TEXT_V2' | 'SELECT' | 'TEXT' | 'TS_VECTOR' | 'UUID' export interface IndexField { id: Scalars['UUID'] @@ -8290,7 +8290,6 @@ export const enumFieldMetadataType = { RATING: 'RATING' as const, RAW_JSON: 'RAW_JSON' as const, RELATION: 'RELATION' as const, - RICH_TEXT: 'RICH_TEXT' as const, RICH_TEXT_V2: 'RICH_TEXT_V2' as const, SELECT: 'SELECT' as const, TEXT: 'TEXT' as const, diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command.ts new file mode 100644 index 00000000000..533b5368284 --- /dev/null +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command.ts @@ -0,0 +1,114 @@ +import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; + +import { Command } from 'nest-commander'; +import { DataSource, Repository } from 'typeorm'; + +import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; +import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner'; +import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util'; +import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util'; +import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; +import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; +import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service'; +import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; +import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type'; + +@Command({ + name: 'upgrade:1-20:migrate-rich-text-to-text', + description: + 'Migrate deprecated RICH_TEXT field metadata type to TEXT. The underlying column type is already text, so only the metadata needs updating.', +}) +export class MigrateRichTextToTextCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner { + constructor( + @InjectRepository(WorkspaceEntity) + protected readonly workspaceRepository: Repository, + @InjectDataSource() + private readonly coreDataSource: DataSource, + protected readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager, + protected readonly dataSourceService: DataSourceService, + private readonly workspaceCacheService: WorkspaceCacheService, + private readonly workspaceCacheStorageService: WorkspaceCacheStorageService, + private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, + ) { + super(workspaceRepository, twentyORMGlobalManager, dataSourceService); + } + + override async runOnWorkspace({ + workspaceId, + options, + }: RunOnWorkspaceArgs): Promise { + const dryRun = options?.dryRun ?? false; + + this.logger.log( + `${dryRun ? '[DRY RUN] ' : ''}Migrating RICH_TEXT fields to TEXT in workspace ${workspaceId}`, + ); + + if (dryRun) { + this.logger.log( + `[DRY RUN] Would update RICH_TEXT -> TEXT in core.fieldMetadata for workspace ${workspaceId}. Skipping.`, + ); + + return; + } + + const queryRunner = this.coreDataSource.createQueryRunner(); + + await queryRunner.connect(); + + try { + const result = await queryRunner.query( + `UPDATE core."fieldMetadata" + SET "type" = 'TEXT' + WHERE "workspaceId" = $1 + AND "type" = 'RICH_TEXT' + RETURNING "id"`, + [workspaceId], + ); + + const updatedCount = result.length; + + if (updatedCount > 0) { + this.logger.log( + `Migrated ${updatedCount} RICH_TEXT field(s) to TEXT in workspace ${workspaceId}`, + ); + await this.invalidateCaches(workspaceId); + } else { + this.logger.log( + `No RICH_TEXT fields found in workspace ${workspaceId}`, + ); + } + } finally { + await queryRunner.release(); + } + } + + private async invalidateCaches(workspaceId: string): Promise { + const modifiedMetadataNames = ['fieldMetadata'] as const; + + const cacheKeysToInvalidate: WorkspaceCacheKeyName[] = [ + ...new Set( + modifiedMetadataNames + .flatMap((name) => [name, ...getMetadataRelatedMetadataNames(name)]) + .map(getMetadataFlatEntityMapsKey), + ), + 'ORMEntityMetadatas', + ]; + + await this.workspaceCacheService.invalidateAndRecompute( + workspaceId, + cacheKeysToInvalidate, + ); + + await this.workspaceMetadataVersionService.incrementMetadataVersion( + workspaceId, + ); + + await this.workspaceCacheStorageService.flush(workspaceId); + + this.logger.log( + `Cache invalidated and metadata version incremented for workspace ${workspaceId}`, + ); + } +} diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module.ts index 4937d067fae..0d6d9438062 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/1-20/1-20-upgrade-version-command.module.ts @@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { BackfillCommandMenuItemsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-command-menu-items.command'; import { BackfillPageLayoutsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-page-layouts.command'; +import { MigrateRichTextToTextCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command'; import { ApplicationModule } from 'src/engine/core-modules/application/application.module'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -25,7 +26,15 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace WorkspaceMigrationModule, FeatureFlagModule, ], - providers: [BackfillCommandMenuItemsCommand, BackfillPageLayoutsCommand], - exports: [BackfillCommandMenuItemsCommand, BackfillPageLayoutsCommand], + providers: [ + BackfillCommandMenuItemsCommand, + BackfillPageLayoutsCommand, + MigrateRichTextToTextCommand, + ], + exports: [ + BackfillCommandMenuItemsCommand, + BackfillPageLayoutsCommand, + MigrateRichTextToTextCommand, + ], }) export class V1_20_UpgradeVersionCommandModule {} diff --git a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts index d94ab6383ec..2aa9306ab85 100644 --- a/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts +++ b/packages/twenty-server/src/database/commands/upgrade-version-command/upgrade.command.ts @@ -35,6 +35,7 @@ import { BackfillMissingStandardViewsCommand } from 'src/database/commands/upgra import { SeedServerIdCommand } from 'src/database/commands/upgrade-version-command/1-19/1-19-seed-server-id.command'; import { BackfillCommandMenuItemsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-command-menu-items.command'; import { BackfillPageLayoutsCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-backfill-page-layouts.command'; +import { MigrateRichTextToTextCommand } from 'src/database/commands/upgrade-version-command/1-20/1-20-migrate-rich-text-to-text.command'; import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service'; import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; @@ -87,6 +88,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { // 1.20 Commands protected readonly backfillCommandMenuItemsCommand: BackfillCommandMenuItemsCommand, protected readonly backfillPageLayoutsCommand: BackfillPageLayoutsCommand, + protected readonly migrateRichTextToTextCommand: MigrateRichTextToTextCommand, ) { super( workspaceRepository, @@ -133,6 +135,7 @@ export class UpgradeCommand extends UpgradeCommandRunner { ]; const commands_1200: VersionCommands = [ + this.migrateRichTextToTextCommand, this.backfillCommandMenuItemsCommand, this.backfillPageLayoutsCommand, ]; diff --git a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts index 888259737a1..386b22f43e0 100644 --- a/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts +++ b/packages/twenty-server/src/engine/api/__mocks__/object-metadata-item.mock.ts @@ -335,20 +335,6 @@ export const fieldRawJsonMock = getMockFieldMetadataEntity({ updatedAt: new Date(), }); -export const fieldRichTextMock = getMockFieldMetadataEntity({ - workspaceId, - objectMetadataId, - id: 'fieldRichTextId', - name: 'fieldRichText', - type: FieldMetadataType.RICH_TEXT, - label: 'Field Rich Text', - isNullable: true, - defaultValue: null, - isLabelSyncedWithName: true, - createdAt: new Date(), - updatedAt: new Date(), -}); - export const fieldActorMock = getMockFieldMetadataEntity({ workspaceId, objectMetadataId, @@ -436,7 +422,6 @@ const FIELDS_MOCK = [ fieldPositionMock, fieldAddressMock, fieldRawJsonMock, - fieldRichTextMock, fieldActorMock, fieldArrayMock, ]; diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/__snapshots__/data-arg-processor.service.spec.ts.snap b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/__snapshots__/data-arg-processor.service.spec.ts.snap index c8a12c80bd8..f3439ffcc79 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/__snapshots__/data-arg-processor.service.spec.ts.snap +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/__snapshots__/data-arg-processor.service.spec.ts.snap @@ -172,8 +172,6 @@ exports[`DataArgProcessorService failing inputs validation RELATION should throw exports[`DataArgProcessorService failing inputs validation RELATION should throw for invalid input #5: "non-uuid" 1`] = `"Invalid UUID value 'non-uuid' for field "manyToOneRelationFieldId""`; -exports[`DataArgProcessorService failing inputs validation RICH_TEXT should throw for invalid input #1: "test" 1`] = `"richTextField RICH_TEXT-typed field does not support write operations"`; - exports[`DataArgProcessorService failing inputs validation RICH_TEXT_V2 should throw for invalid input #1: "not-a-rich-text" 1`] = `"Invalid rich text v2 value 'not-a-rich-text' for field "richTextV2Field" - Should be an object"`; exports[`DataArgProcessorService failing inputs validation RICH_TEXT_V2 should throw for invalid input #2: 1 1`] = `"Invalid rich text v2 value 1 for field "richTextV2Field" - Should be an object"`; diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/failing-inputs-by-field-metadata-type.constant.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/failing-inputs-by-field-metadata-type.constant.ts index 25cc79a267d..851880c3cdc 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/failing-inputs-by-field-metadata-type.constant.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/failing-inputs-by-field-metadata-type.constant.ts @@ -96,7 +96,6 @@ export const failingInputsByFieldMetadataType: { { input: { booleanField: 'string' } }, { input: { booleanField: 1 } }, ], - [FieldMetadataType.RICH_TEXT]: [{ input: { richTextField: 'test' } }], [FieldMetadataType.ADDRESS]: [ { input: { addressField: 'not-an-address' } }, { input: { addressField: 1 } }, diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/field-metadata-config-by-field-name.constant.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/field-metadata-config-by-field-name.constant.ts index 991f7640a76..eaee5d51541 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/field-metadata-config-by-field-name.constant.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/__tests__/constants/field-metadata-config-by-field-name.constant.ts @@ -139,11 +139,6 @@ export const fieldMetadataConfigByFieldName: Record< type: FieldMetadataType.RICH_TEXT_V2, isNullable: true, }, - richTextField: { - name: 'richTextField', - type: FieldMetadataType.RICH_TEXT, - isNullable: true, - }, position: { name: 'position', type: FieldMetadataType.POSITION, diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service.ts index e67bbeecd6a..14337125e5e 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg-processor.service.ts @@ -312,7 +312,6 @@ export class DataArgProcessorService { return transformLinksValue(validatedValue); } - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.TS_VECTOR: throw new CommonQueryRunnerException( `${key} ${fieldMetadata.type}-typed field does not support write operations`, diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/__snapshots__/filter-arg-processor.service.spec.ts.snap b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/__snapshots__/filter-arg-processor.service.spec.ts.snap index e39c5af0952..9cfb69c4bf1 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/__snapshots__/filter-arg-processor.service.spec.ts.snap +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/__snapshots__/filter-arg-processor.service.spec.ts.snap @@ -140,10 +140,6 @@ exports[`FilterArgProcessorService failing filter inputs validation RELATION sho exports[`FilterArgProcessorService failing filter inputs validation RELATION should throw for invalid filter #3: {"manyToOneRelationFieldId":{}} 1`] = `"Filter for field "manyToOneRelationFieldId" must have exactly one operator"`; -exports[`FilterArgProcessorService failing filter inputs validation RICH_TEXT should throw for invalid filter #1: {"richTextField":{"invalidOperator":"test"}} 1`] = `"Operator "invalidOperator" is not valid for field "richTextField" of type RICH_TEXT - Allowed operators: eq, neq, gt, gte, lt, lte, in, is, like, ilike, startsWith, endsWith"`; - -exports[`FilterArgProcessorService failing filter inputs validation RICH_TEXT should throw for invalid filter #2: {"richTextField":{}} 1`] = `"Filter for field "richTextField" must have exactly one operator"`; - exports[`FilterArgProcessorService failing filter inputs validation RICH_TEXT_V2 should throw for invalid filter #1: {"richTextV2Field":{"invalidOperator":"test"}} 1`] = `"Sub field "invalidOperator" not found for composite type: RICH_TEXT_V2"`; exports[`FilterArgProcessorService failing filter inputs validation RICH_TEXT_V2 should throw for invalid filter #2: {"richTextV2Field":{"markdown":{"invalidOperator":"test"}}} 1`] = `"Operator "invalidOperator" is not valid for field "richTextV2Field.markdown" of type TEXT - Allowed operators: eq, neq, gt, gte, lt, lte, in, is, like, ilike, startsWith, endsWith"`; diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/failing-filter-inputs-by-field-metadata-type.constant.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/failing-filter-inputs-by-field-metadata-type.constant.ts index a825e794fdd..17fc987a6db 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/failing-filter-inputs-by-field-metadata-type.constant.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/failing-filter-inputs-by-field-metadata-type.constant.ts @@ -11,10 +11,6 @@ export const failingFilterInputsByFieldMetadataType: { { filter: { textField: { eq: 'test', neq: 'test' } } }, { filter: { textField: {} } }, ], - [FieldMetadataType.RICH_TEXT]: [ - { filter: { richTextField: { invalidOperator: 'test' } } }, - { filter: { richTextField: {} } }, - ], [FieldMetadataType.NUMBER]: [ { filter: { numberField: { eq: 'not-a-number' } } }, { filter: { numberField: { eq: {} } } }, diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/successful-filter-inputs-by-field-metadata-type.constant.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/successful-filter-inputs-by-field-metadata-type.constant.ts index 840128ce17b..2e5d73b2cab 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/successful-filter-inputs-by-field-metadata-type.constant.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/__tests__/constants/successful-filter-inputs-by-field-metadata-type.constant.ts @@ -21,13 +21,6 @@ export const successfulFilterInputsByFieldMetadataType: { { filter: { textField: { is: 'NOT_NULL' } } }, { filter: { textField: { eq: null } } }, ], - [FieldMetadataType.RICH_TEXT]: [ - { filter: { richTextField: { eq: 'test' } } }, - { filter: { richTextField: { like: '%test%' } } }, - { filter: { richTextField: { ilike: '%test%' } } }, - { filter: { richTextField: { is: 'NULL' } } }, - { filter: { richTextField: { is: 'NOT_NULL' } } }, - ], [FieldMetadataType.NUMBER]: [ { filter: { numberField: { eq: 1 } } }, { filter: { numberField: { neq: 1 } } }, diff --git a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/utils/get-operators-for-field-type.util.ts b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/utils/get-operators-for-field-type.util.ts index c13525dbc77..87c6de3b061 100644 --- a/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/utils/get-operators-for-field-type.util.ts +++ b/packages/twenty-server/src/engine/api/common/common-args-processors/filter-arg-processor/utils/get-operators-for-field-type.util.ts @@ -20,7 +20,6 @@ export const getOperatorsForFieldType = ( ): FilterOperator[] => { switch (fieldType) { case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: return STRING_FILTER_OPERATORS; case FieldMetadataType.NUMBER: diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts index 95e6abf04be..92119aacffe 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-schema-builder/services/type-mapper.service.ts @@ -74,7 +74,6 @@ export class TypeMapperService { [FieldMetadataType.POSITION, PositionScalarType], [FieldMetadataType.RAW_JSON, GraphQLJSON], [FieldMetadataType.ARRAY, StringArrayScalarType], - [FieldMetadataType.RICH_TEXT, GraphQLString], [FieldMetadataType.TS_VECTOR, TSVectorScalarType], ]); @@ -179,7 +178,6 @@ export class TypeMapperService { [FieldMetadataType.POSITION, FloatFilterType], [FieldMetadataType.FILES, RawJsonFilterType], [FieldMetadataType.RAW_JSON, RawJsonFilterType], - [FieldMetadataType.RICH_TEXT, StringFilterType], [FieldMetadataType.RICH_TEXT_V2, RichTextV2FilterType], [FieldMetadataType.ARRAY, ArrayFilterType], [FieldMetadataType.MULTI_SELECT, MultiSelectFilterType], @@ -209,7 +207,6 @@ export class TypeMapperService { [FieldMetadataType.POSITION, OrderByDirectionType], [FieldMetadataType.FILES, OrderByDirectionType], [FieldMetadataType.RAW_JSON, OrderByDirectionType], - [FieldMetadataType.RICH_TEXT, OrderByDirectionType], [FieldMetadataType.ARRAY, OrderByDirectionType], [FieldMetadataType.TS_VECTOR, OrderByDirectionType], // TODO: Add TSVectorOrderByType ]); diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts index c84304c15cd..ca960dfd9fe 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/__tests__/components.utils.spec.ts @@ -295,10 +295,6 @@ describe('computeSchemaComponents', () => { "format": "uuid", "type": "string", }, - "fieldRichText": { - "description": "Default field metadata entity description", - "type": "string", - }, "fieldSelect": { "description": "Default field metadata entity description", "enum": [ @@ -540,10 +536,6 @@ describe('computeSchemaComponents', () => { "format": "uuid", "type": "string", }, - "fieldRichText": { - "description": "Default field metadata entity description", - "type": "string", - }, "fieldSelect": { "description": "Default field metadata entity description", "enum": [ @@ -796,10 +788,6 @@ describe('computeSchemaComponents', () => { "format": "uuid", "type": "string", }, - "fieldRichText": { - "description": "Default field metadata entity description", - "type": "string", - }, "fieldSelect": { "description": "Default field metadata entity description", "enum": [ diff --git a/packages/twenty-server/src/engine/core-modules/open-api/utils/generate-random-field-value.util.ts b/packages/twenty-server/src/engine/core-modules/open-api/utils/generate-random-field-value.util.ts index d9dd8b25f3a..77f814f0470 100644 --- a/packages/twenty-server/src/engine/core-modules/open-api/utils/generate-random-field-value.util.ts +++ b/packages/twenty-server/src/engine/core-modules/open-api/utils/generate-random-field-value.util.ts @@ -124,7 +124,6 @@ export const generateRandomFieldValue = ({ return {}; } - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.RICH_TEXT_V2: { return ''; } diff --git a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/field-filters.zod-schema.ts b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/field-filters.zod-schema.ts index ac6709b9fd8..80cd15dd34c 100644 --- a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/field-filters.zod-schema.ts +++ b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/field-filters.zod-schema.ts @@ -28,7 +28,6 @@ export const generateFieldFilterZodSchema = ( .describe(`Filter by ${field.name} (UUID field)`); case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.RICH_TEXT_V2: return z .object({ diff --git a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts index 6db71031592..88aa687b140 100644 --- a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts +++ b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts @@ -37,7 +37,6 @@ const getFieldZodType = (field: FlatFieldMetadata): z.ZodTypeAny => { return z.string().uuidv4(); case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: return z.string(); case FieldMetadataType.DATE_TIME: diff --git a/packages/twenty-server/src/engine/core-modules/record-transformer/services/record-input-transformer.service.ts b/packages/twenty-server/src/engine/core-modules/record-transformer/services/record-input-transformer.service.ts index 1cd90b48c33..d24cba68297 100644 --- a/packages/twenty-server/src/engine/core-modules/record-transformer/services/record-input-transformer.service.ts +++ b/packages/twenty-server/src/engine/core-modules/record-transformer/services/record-input-transformer.service.ts @@ -78,10 +78,6 @@ export class RecordInputTransformerService { return value || null; case FieldMetadataType.NUMBER: return value === null ? null : Number(value); - case FieldMetadataType.RICH_TEXT: - throw new Error( - 'Rich text is not supported, please use RICH_TEXT_V2 instead', - ); case FieldMetadataType.RICH_TEXT_V2: return await transformRichTextV2Value(value); case FieldMetadataType.LINKS: diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/__tests__/field-metadata-entity.test-type.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/__tests__/field-metadata-entity.test-type.ts index 3e2735c6d83..41aa24e0222 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/__tests__/field-metadata-entity.test-type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/types/__tests__/field-metadata-entity.test-type.ts @@ -61,8 +61,6 @@ type PositionFieldMetadata = FieldMetadataEntity; type RawJsonFieldMetadata = FieldMetadataEntity; -type RichTextFieldMetadata = FieldMetadataEntity; - type ActorFieldMetadata = FieldMetadataEntity; type ArrayFieldMetadata = FieldMetadataEntity; @@ -93,7 +91,6 @@ type RelationAssertions = [ Expect>, Expect>, Expect>, - Expect>, Expect>, Expect>, Expect>, @@ -124,7 +121,6 @@ type SettingsAssertions = [ Expect>, Expect>, Expect>, - Expect>, Expect>, Expect>, Expect>, @@ -371,16 +367,6 @@ type DefaultValueAssertions = [ } > >, - Expect< - HasAllProperties< - RichTextFieldMetadata, - { - defaultValue: JsonbProperty< - FieldMetadataDefaultValueMapping[FieldMetadataType.RICH_TEXT] - >; - } - > - >, Expect< HasAllProperties< ActorFieldMetadata, @@ -484,7 +470,6 @@ type OptionsAssertions = [ Expect>, Expect>, Expect>, - Expect>, Expect>, Expect>, Expect>, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock.ts index 074b8b14299..44d4ef6270b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/__mocks__/pet-flat-fields.mock.ts @@ -742,7 +742,7 @@ export const PET_FLAT_FIELDS_MOCK = { bio: getFlatFieldMetadataMock({ id: 'fa0ec409-0f29-4b19-b304-31d1018a2344', objectMetadataId: 'd34e0f07-1b8c-4de0-938e-599cf05e1f7f', - type: FieldMetadataType.RICH_TEXT, + type: FieldMetadataType.TEXT, name: 'bio', label: 'Bio', defaultValue: null, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts index 0680ca9f12e..5aacc5cd238 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-type-validator.service.ts @@ -71,7 +71,6 @@ export class FlatFieldMetadataTypeValidatorService { PHONES: DEFAULT_NO_VALIDATION, POSITION: validatePositionFlatFieldMetadata, RAW_JSON: DEFAULT_NO_VALIDATION, - RICH_TEXT: DEFAULT_NO_VALIDATION, RICH_TEXT_V2: DEFAULT_NO_VALIDATION, TEXT: DEFAULT_NO_VALIDATION, TS_VECTOR: validateTsVectorFlatFieldMetadata, diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/__tests__/flat-field-metadata.test-type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/__tests__/flat-field-metadata.test-type.ts index 9efb0ce83d7..43612683f29 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/__tests__/flat-field-metadata.test-type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/types/__tests__/flat-field-metadata.test-type.ts @@ -105,7 +105,6 @@ const _assertion: Record = { // JSON/Array types rawJson: {} as FlatFieldMetadata, array: {} as FlatFieldMetadata, - richText: {} as FlatFieldMetadata, richTextV2: {} as FlatFieldMetadata, // Relation types diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts index 12597343933..7510eb22c2d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/from-create-field-input-to-flat-field-metadatas-to-create.util.ts @@ -183,7 +183,6 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({ case FieldMetadataType.POSITION: case FieldMetadataType.ADDRESS: case FieldMetadataType.RAW_JSON: - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.RICH_TEXT_V2: case FieldMetadataType.ACTOR: case FieldMetadataType.ARRAY: { diff --git a/packages/twenty-server/src/engine/twenty-orm/utils/is-record-matching-rls-row-level-permission-predicate.util.ts b/packages/twenty-server/src/engine/twenty-orm/utils/is-record-matching-rls-row-level-permission-predicate.util.ts index 0240cb32197..d0b355805e2 100644 --- a/packages/twenty-server/src/engine/twenty-orm/utils/is-record-matching-rls-row-level-permission-predicate.util.ts +++ b/packages/twenty-server/src/engine/twenty-orm/utils/is-record-matching-rls-row-level-permission-predicate.util.ts @@ -243,15 +243,6 @@ export const isRecordMatchingRLSRowLevelPermissionPredicate = ({ value: recordFieldValue, }); } - case FieldMetadataType.RICH_TEXT: { - // TODO: Implement a better rich text filter once it becomes a composite field - // See this issue for more context: https://github.com/twentyhq/twenty/issues/7613#issuecomment-2408944585 - // This should be tackled in Q4'24 - return isMatchingStringFilter({ - stringFilter: filterValue as StringFilter, - value: recordFieldValue, - }); - } case FieldMetadataType.RICH_TEXT_V2: { return isMatchingRichTextV2Filter({ richTextV2Filter: filterValue as RichTextV2Filter, diff --git a/packages/twenty-server/src/engine/utils/convert-object-metadata-to-schema-properties.util.ts b/packages/twenty-server/src/engine/utils/convert-object-metadata-to-schema-properties.util.ts index 04ac52ec5ac..7834d7e3e27 100644 --- a/packages/twenty-server/src/engine/utils/convert-object-metadata-to-schema-properties.util.ts +++ b/packages/twenty-server/src/engine/utils/convert-object-metadata-to-schema-properties.util.ts @@ -49,8 +49,7 @@ const getFieldProperties = (field: FieldMetadataEntity): SchemaObject => { case FieldMetadataType.UUID: { return { type: 'string', format: 'uuid' }; } - case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: { + case FieldMetadataType.TEXT: { return { type: 'string' }; } case FieldMetadataType.DATE_TIME: { diff --git a/packages/twenty-server/src/engine/utils/generate-fake-value.ts b/packages/twenty-server/src/engine/utils/generate-fake-value.ts index 78fdbba7017..306580a0447 100644 --- a/packages/twenty-server/src/engine/utils/generate-fake-value.ts +++ b/packages/twenty-server/src/engine/utils/generate-fake-value.ts @@ -68,8 +68,6 @@ const generateFieldMetadataTypeValue = ( return 'Tim Cook'; case FieldMetadataType.RAW_JSON: return null; - case FieldMetadataType.RICH_TEXT: - return 'My rich text'; case FieldMetadataType.UUID: return '123e4567-e89b-12d3-a456-426614174000'; default: diff --git a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/pet-custom-field-seeds.constant.ts b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/pet-custom-field-seeds.constant.ts index 44acfdcee30..a6cba24c56a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/pet-custom-field-seeds.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/pet-custom-field-seeds.constant.ts @@ -90,7 +90,7 @@ export const PET_CUSTOM_FIELD_SEEDS: FieldMetadataSeed[] = [ name: 'soundSwag', }, { - type: FieldMetadataType.RICH_TEXT, + type: FieldMetadataType.TEXT, label: 'Bio', name: 'bio', }, diff --git a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/skill-metadata/create-standard-flat-skill-metadata.util.ts b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/skill-metadata/create-standard-flat-skill-metadata.util.ts index af2f2149540..5a664e4441a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/skill-metadata/create-standard-flat-skill-metadata.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/twenty-standard-application/utils/skill-metadata/create-standard-flat-skill-metadata.util.ts @@ -367,7 +367,7 @@ You help users manage their workspace data model by creating, updating, and orga - **CURRENCY**: Monetary values - **RATING**: Star ratings - **RELATION**: Links to other objects -- **RICH_TEXT**: Formatted text content +- **RICH_TEXT_V2**: Formatted rich text content ## Best Practices diff --git a/packages/twenty-server/src/engine/workspace-manager/utils/__tests__/get-ts-vectors-column-expression.utils.spec.ts b/packages/twenty-server/src/engine/workspace-manager/utils/__tests__/get-ts-vectors-column-expression.utils.spec.ts index 336c73fa1c0..85ae0ccca60 100644 --- a/packages/twenty-server/src/engine/workspace-manager/utils/__tests__/get-ts-vectors-column-expression.utils.spec.ts +++ b/packages/twenty-server/src/engine/workspace-manager/utils/__tests__/get-ts-vectors-column-expression.utils.spec.ts @@ -50,9 +50,9 @@ describe('getTsVectorColumnExpressionFromFields', () => { ); }); - it('should handle rich text fields', () => { + it('should handle text fields', () => { const fields = [ - { name: 'body', type: FieldMetadataType.RICH_TEXT }, + { name: 'body', type: FieldMetadataType.TEXT }, ] as FieldTypeAndNameMetadata[]; const result = getTsVectorColumnExpressionFromFields(fields); diff --git a/packages/twenty-server/src/engine/workspace-manager/utils/is-searchable-field.util.ts b/packages/twenty-server/src/engine/workspace-manager/utils/is-searchable-field.util.ts index 579d03eb427..4acda18c43c 100644 --- a/packages/twenty-server/src/engine/workspace-manager/utils/is-searchable-field.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/utils/is-searchable-field.util.ts @@ -6,7 +6,6 @@ const SEARCHABLE_FIELD_TYPES = [ FieldMetadataType.ADDRESS, FieldMetadataType.LINKS, FieldMetadataType.PHONES, - FieldMetadataType.RICH_TEXT, FieldMetadataType.RICH_TEXT_V2, FieldMetadataType.UUID, ] as const; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/is-text-column-type.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/is-text-column-type.util.ts index a5c0a51bc3a..81de03e9d00 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/is-text-column-type.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration/workspace-migration-runner/utils/is-text-column-type.util.ts @@ -1,8 +1,11 @@ import { FieldMetadataType } from 'twenty-shared/types'; + +// 'RICH_TEXT' kept as a raw string for pre-upgrade workspaces that haven't +// yet run the 1.20 migrate-rich-text-to-text command. export const isTextColumnType = (type: FieldMetadataType) => { return ( type === FieldMetadataType.TEXT || - type === FieldMetadataType.RICH_TEXT || - type === FieldMetadataType.ARRAY + type === FieldMetadataType.ARRAY || + (type as string) === 'RICH_TEXT' ); }; diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/constants/test-object-gql-fields.constant.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/constants/test-object-gql-fields.constant.ts index f4fa775dbe7..cb8c8cd73ee 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/constants/test-object-gql-fields.constant.ts +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/constants/test-object-gql-fields.constant.ts @@ -53,7 +53,6 @@ export const TEST_OBJECT_GQL_FIELDS = ` } rawJsonField arrayField - richTextField richTextV2Field { blocknote markdown diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/rich-text-field-create-input-validation.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/rich-text-field-create-input-validation.integration-spec.ts.snap deleted file mode 100644 index 538f825bd48..00000000000 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/__snapshots__/rich-text-field-create-input-validation.integration-spec.ts.snap +++ /dev/null @@ -1,5 +0,0 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing - -exports[`Create input validation - RICH_TEXT Gql create input - failure RICH_TEXT - should fail with : {"richTextField":"test"} 1`] = `"richTextField RICH_TEXT-typed field does not support write operations"`; - -exports[`Create input validation - RICH_TEXT Rest create input - failure RICH_TEXT - should fail with : {"richTextField":"test"} 1`] = `"["richTextField RICH_TEXT-typed field does not support write operations"]"`; diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/failing-create-input-by-field-metadata-type.constant.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/failing-create-input-by-field-metadata-type.constant.ts index a386479cf74..da11ea7d21f 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/failing-create-input-by-field-metadata-type.constant.ts +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/failing-create-input-by-field-metadata-type.constant.ts @@ -138,13 +138,6 @@ export const failingCreateInputByFieldMetadataType: { }, }, ], - [FieldMetadataType.RICH_TEXT]: [ - { - input: { - richTextField: 'test', - }, - }, - ], [FieldMetadataType.ADDRESS]: [ { input: { diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/successful-create-input-by-field-metadata-type.constant.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/successful-create-input-by-field-metadata-type.constant.ts index 79f93b05902..62ff204d234 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/successful-create-input-by-field-metadata-type.constant.ts +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/constants/successful-create-input-by-field-metadata-type.constant.ts @@ -8,7 +8,7 @@ import { FieldMetadataType } from 'twenty-shared/types'; export const successfulCreateInputByFieldMetadataType: { [K in Exclude< FieldMetadataTypesToTestForCreateInputValidation, - FieldMetadataType.RICH_TEXT | FieldMetadataType.FILES // Done in files-field-sync.integration-spec.ts + FieldMetadataType.FILES // Done in files-field-sync.integration-spec.ts >]: { input: any; validateInput: (record: Record) => boolean; diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/rich-text-field-create-input-validation.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/rich-text-field-create-input-validation.integration-spec.ts deleted file mode 100644 index fc0c6c7ccca..00000000000 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/create-validation/rich-text-field-create-input-validation.integration-spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { failingCreateInputByFieldMetadataType } from 'test/integration/graphql/suites/inputs-validation/create-validation/constants/failing-create-input-by-field-metadata-type.constant'; -import { expectGqlCreateInputValidationError } from 'test/integration/graphql/suites/inputs-validation/create-validation/utils/expect-gql-create-input-validation-error.util'; -import { expectRestCreateInputValidationError } from 'test/integration/graphql/suites/inputs-validation/create-validation/utils/expect-rest-create-input-validation-error.util'; -import { destroyManyObjectsMetadata } from 'test/integration/graphql/suites/inputs-validation/utils/destroy-many-objects-metadata'; -import { setupTestObjectsWithAllFieldTypes } from 'test/integration/graphql/suites/inputs-validation/utils/setup-test-objects-with-all-field-types.util'; -import { FieldMetadataType } from 'twenty-shared/types'; - -const FIELD_METADATA_TYPE = FieldMetadataType.RICH_TEXT; - -const failingTestCases = - failingCreateInputByFieldMetadataType[FIELD_METADATA_TYPE]; - -describe(`Create input validation - ${FIELD_METADATA_TYPE}`, () => { - let objectMetadataId: string; - let objectMetadataSingularName: string; - let objectMetadataPluralName: string; - let targetObjectMetadata1Id: string; - let targetObjectMetadata2Id: string; - - beforeAll(async () => { - const setupTest = await setupTestObjectsWithAllFieldTypes(); - - objectMetadataId = setupTest.objectMetadataId; - objectMetadataSingularName = setupTest.objectMetadataSingularName; - objectMetadataPluralName = setupTest.objectMetadataPluralName; - targetObjectMetadata1Id = setupTest.targetObjectMetadata1Id; - targetObjectMetadata2Id = setupTest.targetObjectMetadata2Id; - }); - - afterAll(async () => { - await destroyManyObjectsMetadata([ - objectMetadataId, - targetObjectMetadata1Id, - targetObjectMetadata2Id, - ]); - }); - - describe('Gql create input - failure', () => { - it.each( - failingTestCases.map((testCase) => ({ - ...testCase, - stringifiedInput: JSON.stringify(testCase.input), - })), - )( - `${FIELD_METADATA_TYPE} - should fail with : $stringifiedInput`, - async ({ input }) => { - await expectGqlCreateInputValidationError( - objectMetadataSingularName, - input, - ); - }, - ); - }); - - describe('Rest create input - failure', () => { - it.each( - failingTestCases.map((testCase) => ({ - ...testCase, - stringifiedInput: JSON.stringify(testCase.input), - })), - )( - `${FIELD_METADATA_TYPE} - should fail with : $stringifiedInput`, - async ({ input }) => { - await expectRestCreateInputValidationError( - objectMetadataPluralName, - input, - ); - }, - ); - }); -}); diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/types/field-metadata-type-to-test.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/types/field-metadata-type-to-test.ts index 4933083e113..498e8d3dcb4 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/types/field-metadata-type-to-test.ts +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/types/field-metadata-type-to-test.ts @@ -2,7 +2,6 @@ import { type FieldMetadataType } from 'twenty-shared/types'; type FieldMetadataTypesNotTestedForFilterInputValidation = | 'TS_VECTOR' - | 'RICH_TEXT' | 'POSITION' | 'ACTOR' | 'NUMERIC' diff --git a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/utils/get-field-metadata-creation-inputs.util.ts b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/utils/get-field-metadata-creation-inputs.util.ts index 713a52f98da..ae00a7f5a8b 100644 --- a/packages/twenty-server/test/integration/graphql/suites/inputs-validation/utils/get-field-metadata-creation-inputs.util.ts +++ b/packages/twenty-server/test/integration/graphql/suites/inputs-validation/utils/get-field-metadata-creation-inputs.util.ts @@ -37,12 +37,6 @@ export const getFieldMetadataCreationInputs = ( 'ACTOR' | 'POSITION' >]: FieldMetadataCreationInput | FieldMetadataCreationInput[]; } = { - [FieldMetadataType.RICH_TEXT]: { - name: 'richTextField', - label: 'richTextField', - type: FieldMetadataType.RICH_TEXT, - objectMetadataId, - }, [FieldMetadataType.RICH_TEXT_V2]: { name: 'richTextV2Field', label: 'richTextV2Field', diff --git a/packages/twenty-shared/src/types/FieldMetadataDefaultValue.ts b/packages/twenty-shared/src/types/FieldMetadataDefaultValue.ts index cf7d0a5feca..65e015b3301 100644 --- a/packages/twenty-shared/src/types/FieldMetadataDefaultValue.ts +++ b/packages/twenty-shared/src/types/FieldMetadataDefaultValue.ts @@ -90,7 +90,6 @@ export type FieldMetadataDefaultValueMapping = { [FieldMetadataType.SELECT]: string | null; [FieldMetadataType.MULTI_SELECT]: string[] | null; [FieldMetadataType.RAW_JSON]: object | null; - [FieldMetadataType.RICH_TEXT]: string | null; [FieldMetadataType.RICH_TEXT_V2]: FieldMetadataDefaultValueRichTextV2 | null; [FieldMetadataType.ACTOR]: FieldMetadataDefaultActor | null; [FieldMetadataType.ARRAY]: string[] | null; diff --git a/packages/twenty-shared/src/types/FieldMetadataType.ts b/packages/twenty-shared/src/types/FieldMetadataType.ts index dbd839aa9e7..14ede6386bf 100644 --- a/packages/twenty-shared/src/types/FieldMetadataType.ts +++ b/packages/twenty-shared/src/types/FieldMetadataType.ts @@ -19,7 +19,6 @@ export enum FieldMetadataType { RATING = 'RATING', RAW_JSON = 'RAW_JSON', RELATION = 'RELATION', - RICH_TEXT = 'RICH_TEXT', RICH_TEXT_V2 = 'RICH_TEXT_V2', SELECT = 'SELECT', TEXT = 'TEXT', diff --git a/packages/twenty-shared/src/utils/fieldMetadata/__tests__/isFieldMetadataTextKind.test.ts b/packages/twenty-shared/src/utils/fieldMetadata/__tests__/isFieldMetadataTextKind.test.ts index 47837389e36..b948510098e 100644 --- a/packages/twenty-shared/src/utils/fieldMetadata/__tests__/isFieldMetadataTextKind.test.ts +++ b/packages/twenty-shared/src/utils/fieldMetadata/__tests__/isFieldMetadataTextKind.test.ts @@ -2,13 +2,12 @@ import { FieldMetadataType } from '@/types'; import { isFieldMetadataTextKind } from '../isFieldMetadataTextKind'; describe('isFieldMetadataTextKind', () => { - it.each([ - FieldMetadataType.TEXT, - FieldMetadataType.RICH_TEXT, - FieldMetadataType.RICH_TEXT_V2, - ])('should return true for %s', (type) => { - expect(isFieldMetadataTextKind(type)).toBe(true); - }); + it.each([FieldMetadataType.TEXT, FieldMetadataType.RICH_TEXT_V2])( + 'should return true for %s', + (type) => { + expect(isFieldMetadataTextKind(type)).toBe(true); + }, + ); it.each([FieldMetadataType.NUMBER, FieldMetadataType.SELECT])( 'should return false for %s', diff --git a/packages/twenty-shared/src/utils/fieldMetadata/isFieldMetadataTextKind.ts b/packages/twenty-shared/src/utils/fieldMetadata/isFieldMetadataTextKind.ts index 7790a59dfa7..7440a079ee3 100644 --- a/packages/twenty-shared/src/utils/fieldMetadata/isFieldMetadataTextKind.ts +++ b/packages/twenty-shared/src/utils/fieldMetadata/isFieldMetadataTextKind.ts @@ -2,7 +2,6 @@ import { FieldMetadataType } from '@/types'; const TEXT_FIELD_TYPES: FieldMetadataType[] = [ FieldMetadataType.TEXT, - FieldMetadataType.RICH_TEXT, FieldMetadataType.RICH_TEXT_V2, ]; diff --git a/packages/twenty-zapier/src/utils/computeInputFields.ts b/packages/twenty-zapier/src/utils/computeInputFields.ts index e06ccf80b3e..bb409cd28be 100644 --- a/packages/twenty-zapier/src/utils/computeInputFields.ts +++ b/packages/twenty-zapier/src/utils/computeInputFields.ts @@ -15,7 +15,6 @@ const getTypeFromFieldMetadataType = ( switch (fieldMetadataType) { case FieldMetadataType.UUID: case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.ARRAY: case FieldMetadataType.RATING: return 'string'; @@ -242,7 +241,6 @@ export const computeInputFields = ( break; case FieldMetadataType.UUID: case FieldMetadataType.TEXT: - case FieldMetadataType.RICH_TEXT: case FieldMetadataType.DATE_TIME: case FieldMetadataType.DATE: case FieldMetadataType.BOOLEAN: