remove isRichTextV2Enabled feature flag (#10562)

This commit is contained in:
Etienne
2025-02-28 14:34:06 +01:00
committed by GitHub
parent ea1ac3708c
commit 2aa72de210
14 changed files with 31 additions and 135 deletions

View File

@ -2,11 +2,9 @@ import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions
import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { BlockNoteEditor } from '@blocknote/core';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
import { FeatureFlagKey } from '~/generated/graphql';
export const useExportNoteAction: ActionHookWithObjectMetadataItem = ({
objectMetadataItem,
@ -24,18 +22,12 @@ export const useExportNoteAction: ActionHookWithObjectMetadataItem = ({
const shouldBeRegistered =
isDefined(objectMetadataItem) && isDefined(selectedRecord) && isNoteOrTask;
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const onClick = async () => {
if (!shouldBeRegistered || !selectedRecord?.body) {
return;
}
const initialBody = isRichTextV2Enabled
? selectedRecord.bodyV2?.blocknote
: selectedRecord.body;
const initialBody = selectedRecord.bodyV2?.blocknote;
let parsedBody = [];
@ -45,7 +37,7 @@ export const useExportNoteAction: ActionHookWithObjectMetadataItem = ({
} catch (error) {
// eslint-disable-next-line no-console
console.warn(
`Failed to parse body for record ${recordId}, for rich text version ${isRichTextV2Enabled ? 'v2' : 'v1'}`,
`Failed to parse body for record ${recordId}, for rich text version 'v2'`,
);
// eslint-disable-next-line no-console
console.warn(initialBody);

View File

@ -50,10 +50,6 @@ export const ActivityRichTextEditor = ({
const cache = useApolloClient().cache;
const activity = activityInStore as Task | Note | null;
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
@ -73,14 +69,12 @@ export const ActivityRichTextEditor = ({
});
const persistBodyDebounced = useDebouncedCallback((blocknote: string) => {
const input = isRichTextV2Enabled
? {
bodyV2: {
blocknote,
markdown: null,
},
}
: { body: blocknote };
const input = {
bodyV2: {
blocknote,
markdown: null,
},
};
if (isDefined(activity)) {
upsertActivity({
@ -175,9 +169,7 @@ export const ActivityRichTextEditor = ({
};
const initialBody = useMemo(() => {
const blocknote = isRichTextV2Enabled
? activity?.bodyV2?.blocknote
: activity?.body;
const blocknote = activity?.bodyV2?.blocknote;
if (
isDefined(activity) &&
@ -192,7 +184,7 @@ export const ActivityRichTextEditor = ({
} catch (error) {
// eslint-disable-next-line no-console
console.warn(
`Failed to parse body for activity ${activityId}, for rich text version ${isRichTextV2Enabled ? 'v2' : 'v1'}`,
`Failed to parse body for activity ${activityId}, for rich text version 'v2'`,
);
// eslint-disable-next-line no-console
console.warn(blocknote);
@ -206,7 +198,7 @@ export const ActivityRichTextEditor = ({
}
return undefined;
}, [activity, isRichTextV2Enabled, activityId]);
}, [activity, activityId]);
const handleEditorBuiltInUploadFile = async (file: File) => {
const { attachmentAbsoluteURL } = await handleUploadAttachment(file);

View File

@ -7,20 +7,16 @@ export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatur
({
objectMetadataItems,
objectNameSingular,
isRichTextV2Enabled,
}: {
objectMetadataItems: ObjectMetadataItem[];
objectNameSingular: CoreObjectNameSingular;
isRichTextV2Enabled: boolean;
}) => {
const body = isRichTextV2Enabled
? {
bodyV2: {
markdown: true,
blocknote: true,
},
}
: { body: true };
const body = {
bodyV2: {
markdown: true,
blocknote: true,
},
};
return {
objectNameSingular: objectNameSingular,

View File

@ -12,8 +12,6 @@ import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGq
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated/graphql';
import { sortByAscString } from '~/utils/array/sortByAscString';
export const useActivities = <T extends Task | Note>({
@ -29,10 +27,6 @@ export const useActivities = <T extends Task | Note>({
activitiesOrderByVariables: RecordGqlOperationOrderBy;
skip?: boolean;
}) => {
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const { objectMetadataItems } = useObjectMetadataItems();
const { activityTargets, loadingActivityTargets } =
@ -70,7 +64,6 @@ export const useActivities = <T extends Task | Note>({
findActivitiesOperationSignatureFactory({
objectMetadataItems,
objectNameSingular,
isRichTextV2Enabled,
});
const { records: activities, loading: loadingActivities } =

View File

@ -13,9 +13,7 @@ import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordF
import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { isDefined } from 'twenty-shared';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
import { sortByAscString } from '~/utils/array/sortByAscString';
export const usePrepareFindManyActivitiesQuery = ({
@ -23,10 +21,6 @@ export const usePrepareFindManyActivitiesQuery = ({
}: {
activityObjectNameSingular: CoreObjectNameSingular;
}) => {
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const { objectMetadataItem: objectMetadataItemActivity } =
useObjectMetadataItem({
objectNameSingular: activityObjectNameSingular,
@ -120,7 +114,6 @@ export const usePrepareFindManyActivitiesQuery = ({
findActivitiesOperationSignatureFactory({
objectNameSingular: activityObjectNameSingular,
objectMetadataItems,
isRichTextV2Enabled,
});
upsertFindManyActivitiesInCache({

View File

@ -6,8 +6,6 @@ import { Note } from '@/activities/types/Note';
import { getActivityPreview } from '@/activities/utils/getActivityPreview';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFieldContext } from '@/object-record/hooks/useFieldContext';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
const StyledCard = styled.div<{ isSingleNote: boolean }>`
align-items: flex-start;
@ -73,12 +71,8 @@ export const NoteCard = ({
const openActivityRightDrawer = useOpenActivityRightDrawer({
objectNameSingular: CoreObjectNameSingular.Note,
});
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const body = getActivityPreview(
isRichTextV2Enabled ? (note?.bodyV2?.blocknote ?? null) : note?.body,
);
const body = getActivityPreview(note?.bodyV2?.blocknote ?? null);
const { FieldContextProvider: NoteTargetsContextProvider } = useFieldContext({
objectNameSingular: CoreObjectNameSingular.Note,

View File

@ -16,8 +16,6 @@ import { ActivityRow } from '@/activities/components/ActivityRow';
import { Task } from '@/activities/types/Task';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFieldContext } from '@/object-record/hooks/useFieldContext';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
import { useCompleteTask } from '../hooks/useCompleteTask';
const StyledTaskBody = styled.div`
@ -84,13 +82,7 @@ export const TaskRow = ({ task }: { task: Task }) => {
objectNameSingular: CoreObjectNameSingular.Task,
});
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const body = getActivitySummary(
isRichTextV2Enabled ? (task?.bodyV2?.blocknote ?? null) : task?.body,
);
const body = getActivitySummary(task?.bodyV2?.blocknote ?? null);
const { completeTask } = useCompleteTask(task);

View File

@ -4,9 +4,7 @@ import { IconForbid } from 'twenty-ui';
import { MatchColumnSelect } from '@/spreadsheet-import/components/MatchColumnSelect';
import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FieldMetadataType } from 'twenty-shared';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
import { Columns, ColumnType } from '../MatchColumnsStep';
const StyledContainer = styled.div`
@ -27,19 +25,12 @@ export const TemplateColumn = <T extends string>({
columnIndex,
onChange,
}: TemplateColumnProps<T>) => {
const isRichTextV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
);
const { fields } = useSpreadsheetImportInternal<T>();
const column = columns[columnIndex];
const isIgnored = column.type === ColumnType.ignored;
const fieldOptions = fields
.filter((field) =>
isRichTextV2Enabled
? field.fieldMetadataType !== FieldMetadataType.RICH_TEXT
: true,
)
.filter((field) => field.fieldMetadataType !== FieldMetadataType.RICH_TEXT)
.map(({ icon, label, key }) => {
const isSelected =
columns.findIndex((column) => {

View File

@ -12,7 +12,6 @@ import {
MaintainedWorkspacesMigrationCommandOptions,
MaintainedWorkspacesMigrationCommandRunner,
} from 'src/database/commands/migration-command/maintained-workspaces-migration-command.runner';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -174,8 +173,6 @@ export class MigrateRichTextFieldCommand extends MaintainedWorkspacesMigrationCo
workspaceId,
});
await this.enableRichTextV2FeatureFlag(workspaceId);
if (!this.options.dryRun) {
await this.workspaceMetadataVersionService.incrementMetadataVersion(
workspaceId,
@ -190,24 +187,6 @@ export class MigrateRichTextFieldCommand extends MaintainedWorkspacesMigrationCo
}
}
private async enableRichTextV2FeatureFlag(
workspaceId: string,
): Promise<void> {
if (!this.options.dryRun) {
await this.featureFlagRepository.upsert(
{
workspaceId,
key: FeatureFlagKey.IsRichTextV2Enabled,
value: true,
},
{
conflictPaths: ['workspaceId', 'key'],
skipUpdateIfNoValuesChanged: true,
},
);
}
}
private buildRichTextFieldStandardId(richTextField: FieldMetadataEntity) {
switch (true) {
case richTextField.standardId === TASK_STANDARD_FIELD_IDS.body: {

View File

@ -8,7 +8,6 @@ import {
MaintainedWorkspacesMigrationCommandOptions,
MaintainedWorkspacesMigrationCommandRunner,
} from 'src/database/commands/migration-command/maintained-workspaces-migration-command.runner';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@ -66,14 +65,6 @@ export class MigrateSearchVectorOnNoteAndTaskEntitiesCommand extends MaintainedW
`Running command for workspace ${workspaceId} ${index + 1}/${total}`,
);
await this.featureFlagRepository.findOneOrFail({
where: {
workspaceId,
key: FeatureFlagKey.IsRichTextV2Enabled,
value: true,
},
});
const noteObjectMetadata =
await this.objectMetadataRepository.findOneOrFail({
select: ['id'],

View File

@ -75,11 +75,6 @@ export const seedFeatureFlags = async (
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IsRichTextV2Enabled,
workspaceId: workspaceId,
value: true,
},
{
key: FeatureFlagKey.IsNewRelationEnabled,
workspaceId: workspaceId,

View File

@ -1,6 +1,5 @@
import { QueryResultGetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { FileService } from 'src/engine/core-modules/file/services/file.service';
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
@ -22,14 +21,7 @@ export class ActivityQueryResultGetterHandler
activity: TaskWorkspaceEntity | NoteWorkspaceEntity,
workspaceId: string,
): Promise<TaskWorkspaceEntity | NoteWorkspaceEntity> {
const isRichTextV2Enabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IsRichTextV2Enabled,
workspaceId,
);
const blocknoteJson = isRichTextV2Enabled
? activity.bodyV2?.blocknote
: activity.body;
const blocknoteJson = activity.bodyV2?.blocknote;
if (!activity.id || !blocknoteJson) {
return activity;
@ -44,7 +36,7 @@ export class ActivityQueryResultGetterHandler
// TODO: Remove this once we have removed the old rich text
// eslint-disable-next-line no-console
console.warn(
`Failed to parse body for activity ${activity.id} in workspace ${workspaceId}, for rich text version ${isRichTextV2Enabled ? 'v2' : 'v1'}`,
`Failed to parse body for activity ${activity.id} in workspace ${workspaceId}, for rich text version 'v2'`,
);
// eslint-disable-next-line no-console
console.warn(blocknoteJson);
@ -76,19 +68,12 @@ export class ActivityQueryResultGetterHandler
}),
);
if (isRichTextV2Enabled) {
return {
...activity,
bodyV2: {
blocknote: JSON.stringify(blocknoteWithSignedPayload),
markdown: activity.bodyV2?.markdown ?? null,
},
};
}
return {
...activity,
body: JSON.stringify(blocknoteWithSignedPayload),
bodyV2: {
blocknote: JSON.stringify(blocknoteWithSignedPayload),
markdown: activity.bodyV2?.markdown ?? null,
},
};
}
}

View File

@ -205,6 +205,10 @@ export class QueryRunnerArgsFactory {
}
case FieldMetadataType.NUMBER:
return [key, 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: {
const richTextV2Value = richTextV2ValueSchema.parse(value);

View File

@ -13,7 +13,6 @@ export enum FeatureFlagKey {
IsCustomDomainEnabled = 'IS_CUSTOM_DOMAIN_ENABLED',
IsApprovedAccessDomainsEnabled = 'IS_APPROVED_ACCESS_DOMAINS_ENABLED',
IsBillingPlansEnabled = 'IS_BILLING_PLANS_ENABLED',
IsRichTextV2Enabled = 'IS_RICH_TEXT_V2_ENABLED',
IsNewRelationEnabled = 'IS_NEW_RELATION_ENABLED',
IsPermissionsEnabled = 'IS_PERMISSIONS_ENABLED',
}