Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save Markdown and BlockNote in RICH_TEXT fields (#7613) #9279

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

eliasylonen
Copy link
Contributor

@eliasylonen eliasylonen commented Dec 30, 2024

  1. Make RICH_TEXT field composite: instead of saving only BlockNote also save a lossy copy of the value in Markdown format.
  2. Let user choose between BlockNote and Markdown when importing a field from a CSV.

Fixes #7613
Fixes #7444

Copy link

github-actions bot commented Dec 30, 2024

TODOs/FIXMEs:

  • // TODO: Can these be null?: packages/twenty-front/src/modules/object-record/record-field/types/FieldMetadata.ts
  • // TODO: Check later if and how this works: packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts
  • // TODO: Check later if and how this works: packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts

Generated by 🚫 dangerJS against 73dfe30

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

This PR transforms RICH_TEXT fields into composite fields that store both BlockNote and Markdown formats, enabling dual-format storage and format choice during CSV imports.

  • Adds new rich-text.composite-type.ts defining the composite structure with nullable blocknote and markdown TEXT fields
  • Modifies search functionality in task/note entities to use bodyBlocknote instead of body, with a TODO to verify search behavior
  • Moves RICH_TEXT handling from basicColumnActionFactory to compositeColumnActionFactory for database migrations
  • Updates OpenAPI schema and Zapier integration to handle RICH_TEXT as a composite field with both formats
  • Needs proper example values in SettingsCompositeFieldTypeConfigs.ts (currently marked as TODO)

22 file(s) reviewed, 11 comment(s)
Edit PR Review Bot Settings | Greptile

Comment on lines +4 to +7
export const richTextSchema: z.ZodType<FieldRichTextValue> = z.object({
blocknote: z.string().nullable(),
markdown: z.string().nullable(),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: consider adding validation to ensure at least one of blocknote or markdown is non-null to prevent empty objects

Comment on lines +193 to +194
blocknote: 'TODO', // TODO
markdown: 'TODO',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: example values are marked as TODO and need to be properly defined with realistic sample data

label: 'Rich Text',
Icon: IllustrationIconText,
subFields: ['blocknote', 'markdown'],
filterableSubFields: [],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: consider adding 'markdown' to filterableSubFields to enable searching/filtering by content

@@ -21,7 +21,7 @@ export class ActivityQueryResultGetterHandler
return activity;
}

const body: RichTextBody = JSON.parse(activity.body);
const body: RichTextBody = JSON.parse(activity.body.blocknote);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: add try/catch around JSON.parse to handle invalid JSON gracefully

Comment on lines 164 to 165
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: missing return type for undefined case - could cause runtime issues if field type is not handled

Comment on lines +23 to +26
export type RichTextMetadata = {
blocknote: string;
markdown: string;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: both fields are defined as required in the type but marked as not required in the composite type definition above. This inconsistency could cause runtime issues

Comment on lines 38 to 46
export class FieldMetadataDefaultValueRichText {
@ValidateIf((_object, value) => value !== null)
@IsString()
value: string | null;
@ValidateIf((object, value) => value !== null)
@IsQuotedString()
blocknote: string | null;

@ValidateIf((object, value) => value !== null)
@IsQuotedString()
markdown: string | null;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Both blocknote and markdown fields can be null simultaneously. Consider adding validation to ensure at least one format is provided.

@@ -37,7 +38,7 @@ const BODY_FIELD_NAME = 'body';

export const SEARCH_FIELDS_FOR_TASK: FieldTypeAndNameMetadata[] = [
{ name: TITLE_FIELD_NAME, type: FieldMetadataType.TEXT },
{ name: BODY_FIELD_NAME, type: FieldMetadataType.RICH_TEXT },
{ name: `${BODY_FIELD_NAME}Blocknote`, type: FieldMetadataType.RICH_TEXT }, // TODO: Check later if and how this works
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: search field using 'bodyBlocknote' may break full-text search for existing tasks since the field name changed from 'body' to 'bodyBlocknote'

@@ -35,7 +36,7 @@ const BODY_FIELD_NAME = 'body';

export const SEARCH_FIELDS_FOR_NOTES: FieldTypeAndNameMetadata[] = [
{ name: TITLE_FIELD_NAME, type: FieldMetadataType.TEXT },
{ name: BODY_FIELD_NAME, type: FieldMetadataType.RICH_TEXT },
{ name: `${BODY_FIELD_NAME}Blocknote`, type: FieldMetadataType.RICH_TEXT }, // TODO: Check later if and how this works
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: search field name change from 'body' to 'bodyBlocknote' may break existing search functionality if not properly migrated

Comment on lines +232 to +234
name: 'blocknote',
label: 'Blocknote',
description: 'Blocknote',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: inconsistent casing between 'blocknote' and 'BlockNote' in label/description

@lucasbordeau
Copy link
Contributor

@eliasylonen Could you link the original issue ?
@FelixMalfait Should we re-activate the field input in this PR also ?

@FelixMalfait
Copy link
Member

@lucasbordeau I edited the description to add the related issues. I think we should create a separate issue for the input in table views as this PR is going to be quite big already (it's still wip). Would you mind creating it if you can point to the right direction? I'm not sure what has been done/is left to be done

@lucasbordeau
Copy link
Contributor

Could we use deprecated instead of old ?

@lucasbordeau
Copy link
Contributor

Shouldn't we add the type RICH_TEXT next to the RICH_TEXT_OLD/DEPRECATED ?

@eliasylonen
Copy link
Contributor Author

@lucasbordeau Yes 👍 will do!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
4 participants