[Requires "warm" cache flush (no immediate downtime before flush)] Migrate viewGroup.fieldMetadataId -> view.mainGroupByFieldMetadataId (1/3) (#16206)

In this PR (1/3)
- introduce view.mainGroupByFieldMetadataId as the new reference
determining which fieldMetadataId is used in a grouped view, in order to
deprecate viewGroup.fieldMetadataId which creates inconsistencies.
view.mainGroupByFieldMetadataId is now filled at every view creation,
though not in use yet.
- Introduce a command to backfill view.mainGroupByFieldMetadataId for
existing views + delete all viewGroup.fieldMetadataId with a
fieldMetadataId that is not view.mainGroupByFieldMetadataId. (It should
concern 37 active workspaces)
- Temporarily disable the option to change a grouped view's
fieldMetadataId as for now it creates inconsistencies. This feature can
be reintroduced when we have done the full migration.

In a next PR
- (2/3) use view.mainGroupByFieldMetadataId instead of
viewGroup.fieldMetadataId. In FE we may keep viewGroup.fieldMetadataId
as a state (TBD). View groups will now be created / deleted as a side
effect of view's mainGroupByFieldMetadataId update.
- (3/3) remove viewGroup.fieldMetadataId

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Marie
2025-12-02 16:31:07 +01:00
committed by GitHub
parent aa729a2a0a
commit 77409b6eb2
71 changed files with 484 additions and 99 deletions
@@ -23,6 +23,9 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = <
kanbanAggregateOperationViewIds:
fieldMetadataEntity.kanbanAggregateOperationViews.map(({ id }) => id),
calendarViewIds: fieldMetadataEntity.calendarViews.map(({ id }) => id),
mainGroupByFieldMetadataViewIds:
fieldMetadataEntity.mainGroupByFieldMetadataViews?.map(({ id }) => id) ??
[],
viewGroupIds: fieldMetadataEntity.viewGroups.map(({ id }) => id),
viewFieldIds: fieldMetadataEntity.viewFields.map(({ id }) => id),
viewFilterIds: fieldMetadataEntity.viewFilters.map(({ id }) => id),
@@ -26,6 +26,7 @@ export const getDefaultFlatFieldMetadata = ({
return {
calendarViewIds: [],
mainGroupByFieldMetadataViewIds: [],
viewFieldIds: [],
description: createFieldInput.description ?? null,
id: fieldMetadataId,
@@ -1,5 +1,5 @@
import { isDefined } from 'class-validator';
import { type EnumFieldMetadataType } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import {
@@ -63,7 +63,8 @@ export const recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate = ({
const flatViewGroupsToUpdate = updatedFieldMetadataOptions.flatMap(
({ from: fromOption, to: toOption }) =>
flatViewGroups.flatMap((flatViewGroup) =>
flatViewGroup.fieldValue === fromOption.value
flatViewGroup.fieldValue === fromOption.value &&
flatViewGroup.fieldMetadataId === fromFlatFieldMetadata.id
? { ...flatViewGroup, fieldValue: toOption.value }
: [],
),