Field deactivation side effect views calendar kanban viewFields (#15180)
# Introduction
Handling both:
- field deactivation side effect on view fields, view filters and views
- field deactivation side effect on view that targets it as
`kanbanAggregateFieldMetadataId`
- field deactivation side effect on view that targets it as
`calendarFieldMetadataId`
## Coverage
added coverage
```ts
PASS test/integration/metadata/suites/field-metadata/kanban-aggregate-field-deactivation-deletes-views.integration-spec.ts (13.132 s)
kanban-aggregate-field-deactivation-nullifies-kanban-properties
✓ should nullify kanban properties when field used as kanbanAggregateOperationFieldMetadataId is deactivated (3923 ms)
✓ should not modify views when field not used as kanbanAggregateOperationFieldMetadataId is deactivated (2958 ms)
✓ should nullify kanban properties on multiple views when they all use the same field as kanbanAggregateOperationFieldMetadataId (2542 ms)
✓ should nullify kanban properties when views have different aggregate operations on same field (3380 ms)
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 13.154 s
```
```ts
PASS test/integration/metadata/suites/field-metadata/view-group-field-deactivation-deletes-views.integration-spec.ts (12.639 s)
view-group-field-deactivation-deletes-views
✓ should delete view when field used in view group is deactivated (3469 ms)
✓ should not delete view when field not used in view group is deactivated (3109 ms)
✓ should delete multiple views when they all use the same field in view groups (2741 ms)
✓ should handle deactivation when view has multiple view groups with different fields (3008 ms)
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
Snapshots: 0 total
Time: 12.664 s
```
```ts
PASS test/integration/metadata/suites/field-metadata/calendar-field-deactivation-deletes-views.integration-spec.ts (14.579 s)
calendar-field-deactivation-deletes-views
✓ should delete view when field used as calendarFieldMetadataId is deactivated (3388 ms)
✓ should not delete view when field not used as calendarFieldMetadataId is deactivated (2438 ms)
✓ should delete multiple views when they all use the same field as calendarFieldMetadataId (2635 ms)
✓ should handle deactivation when views have different calendar layouts on same field (3195 ms)
✓ should delete calendar view but not other view types when calendar field is deactivated (2682 ms)
Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 14.601 s, estimated 15 s
```
## View soft deletion
We decided to remove the soft deletion grain on all the views, in this
PR context we've only removed soft deleted validation requirement on any
view entities
## Conclusion
close https://github.com/twentyhq/core-team-issues/issues/1754
This commit is contained in:
+10
@@ -29,6 +29,7 @@ import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permis
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
|
||||
@Entity('fieldMetadata')
|
||||
@Check(
|
||||
@@ -200,4 +201,13 @@ export class FieldMetadataEntity<
|
||||
|
||||
@OneToMany(() => ViewGroupEntity, (viewGroup) => viewGroup.fieldMetadata)
|
||||
viewGroups: Relation<ViewGroupEntity[]>;
|
||||
|
||||
@OneToMany(
|
||||
() => ViewEntity,
|
||||
(view) => view.kanbanAggregateOperationFieldMetadata,
|
||||
)
|
||||
kanbanAggregateOperationViews: Relation<ViewEntity[]>;
|
||||
|
||||
@OneToMany(() => ViewEntity, (view) => view.calendarFieldMetadata)
|
||||
calendarViews: Relation<ViewEntity[]>;
|
||||
}
|
||||
|
||||
+20
@@ -144,6 +144,7 @@ export class FieldMetadataServiceV2 {
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
} = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
@@ -154,6 +155,7 @@ export class FieldMetadataServiceV2 {
|
||||
'flatViewFilterMaps',
|
||||
'flatViewGroupMaps',
|
||||
'flatViewMaps',
|
||||
'flatViewFieldMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
@@ -165,6 +167,8 @@ export class FieldMetadataServiceV2 {
|
||||
updateFieldInput,
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
});
|
||||
|
||||
if (inputTranspilationResult.status === 'fail') {
|
||||
@@ -181,6 +185,9 @@ export class FieldMetadataServiceV2 {
|
||||
flatViewGroupsToUpdate,
|
||||
flatViewFiltersToDelete,
|
||||
flatViewFiltersToUpdate,
|
||||
flatViewFieldsToDelete,
|
||||
flatViewsToUpdate,
|
||||
flatViewsToDelete,
|
||||
} = inputTranspilationResult.result;
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -215,6 +222,18 @@ export class FieldMetadataServiceV2 {
|
||||
flatEntityToDelete: flatViewGroupsToDelete,
|
||||
flatEntityToUpdate: flatViewGroupsToUpdate,
|
||||
}),
|
||||
flatViewMaps: computeFlatEntityMapsFromTo({
|
||||
flatEntityMaps: existingFlatViewMaps,
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: flatViewsToDelete,
|
||||
flatEntityToUpdate: flatViewsToUpdate,
|
||||
}),
|
||||
flatViewFieldMaps: computeFlatEntityMapsFromTo({
|
||||
flatEntityMaps: existingFlatViewFieldMaps,
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: flatViewFieldsToDelete,
|
||||
flatEntityToUpdate: [],
|
||||
}),
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
@@ -222,6 +241,7 @@ export class FieldMetadataServiceV2 {
|
||||
index: true,
|
||||
viewGroup: true,
|
||||
viewFilter: true,
|
||||
view: true,
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
|
||||
-15
@@ -365,21 +365,6 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
if (fieldMetadataInput.isActive === false) {
|
||||
const viewsRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace(
|
||||
fieldMetadataInput.workspaceId,
|
||||
'view',
|
||||
{
|
||||
shouldBypassPermissionChecks: true,
|
||||
},
|
||||
);
|
||||
|
||||
await viewsRepository.delete({
|
||||
kanbanFieldMetadataId: id,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
updatedFieldMetadata.isActive &&
|
||||
isSelectOrMultiSelectFieldMetadata(updatedFieldMetadata) &&
|
||||
|
||||
+20
-30
@@ -3,64 +3,54 @@ import { type ExtractPropertiesThatEndsWithId } from 'twenty-shared/types';
|
||||
import { type AllMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-metadata-name.type';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
|
||||
type PropertyNameToRelationName<T extends string> = T extends `${infer Name}Id`
|
||||
? Name
|
||||
: never;
|
||||
|
||||
type ExtractEntityRelations<TEntity extends MetadataEntity<AllMetadataName>> = {
|
||||
[K in ExtractPropertiesThatEndsWithId<
|
||||
TEntity,
|
||||
'id' | 'workspaceId'
|
||||
> as PropertyNameToRelationName<K>]: K;
|
||||
[K in ExtractPropertiesThatEndsWithId<TEntity, 'id' | 'workspaceId'>]: K;
|
||||
};
|
||||
|
||||
type MetadataRelatedMetadataNames<T extends AllMetadataName> = Extract<
|
||||
keyof ExtractEntityRelations<MetadataEntity<T>>,
|
||||
AllMetadataName
|
||||
>;
|
||||
type MetadataRelatedMetadataNames<T extends AllMetadataName> =
|
||||
keyof ExtractEntityRelations<MetadataEntity<T>>;
|
||||
|
||||
type MetadataNameAndRelations = {
|
||||
[T in AllMetadataName]: MetadataRelatedMetadataNames<T> extends never
|
||||
? Record<string, never>
|
||||
: Record<MetadataRelatedMetadataNames<T>, string> & {
|
||||
[K in Exclude<
|
||||
AllMetadataName,
|
||||
MetadataRelatedMetadataNames<T>
|
||||
>]?: string;
|
||||
: {
|
||||
[P in MetadataRelatedMetadataNames<T>]?: AllMetadataName;
|
||||
};
|
||||
};
|
||||
|
||||
export const ALL_METADATA_NAME_MANY_TO_ONE_RELATIONS = {
|
||||
export const ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY = {
|
||||
fieldMetadata: {
|
||||
objectMetadata: 'objectMetadataId',
|
||||
objectMetadataId: 'objectMetadata',
|
||||
},
|
||||
objectMetadata: {},
|
||||
view: {
|
||||
objectMetadata: 'objectMetadataId',
|
||||
kanbanAggregateOperationFieldMetadataId: 'fieldMetadata',
|
||||
calendarFieldMetadataId: 'fieldMetadata',
|
||||
objectMetadataId: 'objectMetadata',
|
||||
},
|
||||
viewField: {
|
||||
view: 'viewId',
|
||||
fieldMetadata: 'fieldMetadataId',
|
||||
viewId: 'view',
|
||||
fieldMetadataId: 'fieldMetadata',
|
||||
},
|
||||
viewGroup: {
|
||||
view: 'viewId',
|
||||
fieldMetadata: 'fieldMetadataId',
|
||||
viewId: 'view',
|
||||
fieldMetadataId: 'fieldMetadata',
|
||||
},
|
||||
index: {
|
||||
objectMetadata: 'objectMetadataId',
|
||||
objectMetadataId: 'objectMetadata',
|
||||
},
|
||||
serverlessFunction: {},
|
||||
cronTrigger: {
|
||||
serverlessFunction: 'serverlessFunctionId',
|
||||
serverlessFunctionId: 'serverlessFunction',
|
||||
},
|
||||
databaseEventTrigger: {
|
||||
serverlessFunction: 'serverlessFunctionId',
|
||||
serverlessFunctionId: 'serverlessFunction',
|
||||
},
|
||||
routeTrigger: {
|
||||
serverlessFunction: 'serverlessFunctionId',
|
||||
serverlessFunctionId: 'serverlessFunction',
|
||||
},
|
||||
viewFilter: {
|
||||
view: 'viewId',
|
||||
fieldMetadata: 'fieldMetadataId',
|
||||
viewId: 'view',
|
||||
fieldMetadataId: 'fieldMetadata',
|
||||
},
|
||||
} as const satisfies MetadataNameAndRelations;
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
fieldMetadata: true,
|
||||
},
|
||||
view: {
|
||||
fieldMetadata: true,
|
||||
objectMetadata: true,
|
||||
},
|
||||
viewField: {
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { type ALL_METADATA_NAME_MANY_TO_ONE_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant';
|
||||
import { type ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant';
|
||||
import { type AllMetadataName } from 'src/engine/metadata-modules/flat-entity/types/all-metadata-name.type';
|
||||
|
||||
export type MetadataManyToOneRelatedMetadataNames<T extends AllMetadataName> =
|
||||
Extract<
|
||||
keyof (typeof ALL_METADATA_NAME_MANY_TO_ONE_RELATIONS)[T],
|
||||
(typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T][keyof (typeof ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY)[T]],
|
||||
AllMetadataName
|
||||
>;
|
||||
|
||||
+3
-2
@@ -1,4 +1,4 @@
|
||||
import { ALL_METADATA_NAME_MANY_TO_ONE_RELATIONS } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant';
|
||||
import { ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY } from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-many-to-one-relations.constant';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
@@ -32,8 +32,9 @@ export const addFlatEntityToFlatEntityAndRelatedEntityMapsOrThrow = <
|
||||
flatEntityMaps: initialFlatEntityAndRelatedMaps[flatEntityMapsKey],
|
||||
});
|
||||
|
||||
// TODO refactor
|
||||
const manyToOneRelatedMetadataName = Object.entries(
|
||||
ALL_METADATA_NAME_MANY_TO_ONE_RELATIONS[metadataName],
|
||||
ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY[metadataName],
|
||||
);
|
||||
|
||||
return manyToOneRelatedMetadataName.reduce(
|
||||
|
||||
+2
@@ -19,8 +19,10 @@ export const getFlatFieldMetadataMock = <T extends FieldMetadataType>(
|
||||
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
viewFieldIds: [],
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
|
||||
+2
@@ -32,9 +32,11 @@ export const getRelationTargetFlatFieldMetadataMock = ({
|
||||
const createdAt = '2024-01-01T00:00:00.000Z' as unknown as Date;
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
viewFieldIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
description: 'default flat field metadata description',
|
||||
|
||||
+8
@@ -105,6 +105,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"flatFieldMetadatas": [
|
||||
{
|
||||
"applicationId": null,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
"description": "new field description",
|
||||
@@ -117,6 +118,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": null,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "newFieldLabel",
|
||||
"morphId": Any<String>,
|
||||
"name": "newFieldPets",
|
||||
@@ -139,6 +141,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
"description": null,
|
||||
@@ -151,6 +154,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": null,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "Pet",
|
||||
"morphId": null,
|
||||
"name": "pet",
|
||||
@@ -175,6 +179,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
"description": "new field description",
|
||||
@@ -187,6 +192,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": null,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "newFieldLabel",
|
||||
"morphId": Any<String>,
|
||||
"name": "newFieldCompanies",
|
||||
@@ -209,6 +215,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
"description": null,
|
||||
@@ -221,6 +228,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isSystem": false,
|
||||
"isUIReadOnly": false,
|
||||
"isUnique": null,
|
||||
"kanbanAggregateOperationViewIds": [],
|
||||
"label": "Company",
|
||||
"morphId": null,
|
||||
"name": "company",
|
||||
|
||||
+13
-1
@@ -48,9 +48,21 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceFlatMapC
|
||||
viewGroups: {
|
||||
id: true,
|
||||
},
|
||||
kanbanAggregateOperationViews: {
|
||||
id: true,
|
||||
},
|
||||
calendarViews: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
withDeleted: true,
|
||||
relations: ['viewFields', 'viewFilters', 'viewGroups'],
|
||||
relations: [
|
||||
'viewFields',
|
||||
'viewFilters',
|
||||
'viewGroups',
|
||||
'kanbanAggregateOperationViews',
|
||||
'calendarViews',
|
||||
],
|
||||
});
|
||||
|
||||
return fieldMetadatas.reduce(
|
||||
|
||||
+4
@@ -12,6 +12,8 @@ export const FIELD_METADATA_RELATION_PROPERTIES = [
|
||||
'application',
|
||||
'viewFilters',
|
||||
'viewGroups',
|
||||
'kanbanAggregateOperationViews',
|
||||
'calendarViews',
|
||||
] as const satisfies (keyof FieldMetadataEntity)[];
|
||||
|
||||
export type FieldMetadataEntityRelationProperties =
|
||||
@@ -23,4 +25,6 @@ export type FlatFieldMetadata<T extends FieldMetadataType = FieldMetadataType> =
|
||||
viewFieldIds: string[];
|
||||
viewFilterIds: string[];
|
||||
viewGroupIds: string[];
|
||||
kanbanAggregateOperationViewIds: string[];
|
||||
calendarViewIds: string[];
|
||||
};
|
||||
|
||||
+3
@@ -20,6 +20,9 @@ export const fromFieldMetadataEntityToFlatFieldMetadata = <
|
||||
|
||||
return {
|
||||
...fieldMetadataWithoutRelations,
|
||||
kanbanAggregateOperationViewIds:
|
||||
fieldMetadataEntity.kanbanAggregateOperationViews.map(({ id }) => id),
|
||||
calendarViewIds: fieldMetadataEntity.calendarViews.map(({ id }) => id),
|
||||
viewGroupIds: fieldMetadataEntity.viewGroups.map(({ id }) => id),
|
||||
viewFieldIds: fieldMetadataEntity.viewFields.map(({ id }) => id),
|
||||
viewFilterIds: fieldMetadataEntity.viewFilters.map(({ id }) => id),
|
||||
|
||||
+26
-8
@@ -19,6 +19,7 @@ import { type FieldInputTranspilationResult } from 'src/engine/metadata-modules/
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { computeFlatFieldMetadataRelatedFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/compute-flat-field-metadata-related-flat-field-metadata.util';
|
||||
import {
|
||||
FLAT_FIELD_METADATA_UPDATE_EMPTY_SIDE_EFFECTS,
|
||||
type FlatFieldMetadataUpdateSideEffects,
|
||||
handleFlatFieldMetadataUpdateSideEffect,
|
||||
} from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-flat-field-metadata-update-side-effect.util';
|
||||
@@ -34,6 +35,8 @@ type FromUpdateFieldInputToFlatFieldMetadataArgs = {
|
||||
| 'flatFieldMetadataMaps'
|
||||
| 'flatViewFilterMaps'
|
||||
| 'flatViewGroupMaps'
|
||||
| 'flatViewMaps'
|
||||
| 'flatViewFieldMaps'
|
||||
>;
|
||||
|
||||
type FlatFieldMetadataAndIndexToUpdate = {
|
||||
@@ -46,6 +49,8 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
updateFieldInput: rawUpdateFieldInput,
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
}: FromUpdateFieldInputToFlatFieldMetadataArgs): FieldInputTranspilationResult<FlatFieldMetadataAndIndexToUpdate> => {
|
||||
const updateFieldInputInformalProperties =
|
||||
extractAndSanitizeObjectStringFields(rawUpdateFieldInput, [
|
||||
@@ -114,6 +119,8 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
return {
|
||||
status: 'success',
|
||||
result: {
|
||||
flatViewsToUpdate: [],
|
||||
flatViewsToDelete: [],
|
||||
flatViewGroupsToCreate: [],
|
||||
flatViewGroupsToDelete: [],
|
||||
flatViewGroupsToUpdate: [],
|
||||
@@ -123,6 +130,7 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
flatIndexMetadatasToCreate: [],
|
||||
flatViewFiltersToDelete: [],
|
||||
flatViewFiltersToUpdate: [],
|
||||
flatViewFieldsToDelete: [],
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -152,15 +160,8 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
];
|
||||
|
||||
const initialAccumulator: FlatFieldMetadataAndIndexToUpdate = {
|
||||
...structuredClone(FLAT_FIELD_METADATA_UPDATE_EMPTY_SIDE_EFFECTS),
|
||||
flatFieldMetadatasToUpdate: [],
|
||||
flatIndexMetadatasToUpdate: [],
|
||||
flatViewFiltersToDelete: [],
|
||||
flatViewFiltersToUpdate: [],
|
||||
flatViewGroupsToCreate: [],
|
||||
flatViewGroupsToDelete: [],
|
||||
flatIndexMetadatasToCreate: [],
|
||||
flatIndexMetadatasToDelete: [],
|
||||
flatViewGroupsToUpdate: [],
|
||||
};
|
||||
|
||||
updatedEditableFieldProperties.options = !isDefined(
|
||||
@@ -190,6 +191,9 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
flatViewFiltersToUpdate,
|
||||
flatIndexMetadatasToCreate,
|
||||
flatIndexMetadatasToDelete,
|
||||
flatViewsToDelete,
|
||||
flatViewFieldsToDelete,
|
||||
flatViewsToUpdate,
|
||||
} = handleFlatFieldMetadataUpdateSideEffect({
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
@@ -198,6 +202,8 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
flatFieldMetadataMaps,
|
||||
flatIndexMaps,
|
||||
toFlatFieldMetadata,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -237,6 +243,18 @@ export const fromUpdateFieldInputToFlatFieldMetadata = ({
|
||||
...accumulator.flatIndexMetadatasToCreate,
|
||||
...flatIndexMetadatasToCreate,
|
||||
],
|
||||
flatViewsToDelete: [
|
||||
...accumulator.flatViewsToDelete,
|
||||
...flatViewsToDelete,
|
||||
],
|
||||
flatViewFieldsToDelete: [
|
||||
...accumulator.flatViewFieldsToDelete,
|
||||
...flatViewFieldsToDelete,
|
||||
],
|
||||
flatViewsToUpdate: [
|
||||
...accumulator.flatViewsToUpdate,
|
||||
...flatViewsToUpdate,
|
||||
],
|
||||
};
|
||||
},
|
||||
initialAccumulator,
|
||||
|
||||
+2
@@ -23,6 +23,7 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
const createdAt = new Date();
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
viewFieldIds: [],
|
||||
description: createFieldInput.description ?? null,
|
||||
id: fieldMetadataId,
|
||||
@@ -57,5 +58,6 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
applicationId: null,
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
} as const satisfies FlatFieldMetadata;
|
||||
};
|
||||
|
||||
+1
-9
@@ -2,7 +2,6 @@ import { type EnumFieldMetadataType, type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util';
|
||||
import {
|
||||
type FlatViewFiltersToDeleteAndUpdate,
|
||||
recomputeViewFiltersOnFlatFieldMetadataOptionsUpdate,
|
||||
@@ -15,7 +14,7 @@ import {
|
||||
import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type';
|
||||
|
||||
type HandleEnumFlatFieldMetadataOptionsUpdateSideEffectsArgs = FromTo<
|
||||
FlatFieldMetadata,
|
||||
FlatFieldMetadata<EnumFieldMetadataType>,
|
||||
'flatFieldMetadata'
|
||||
> &
|
||||
Pick<AllFlatEntityMaps, 'flatViewFilterMaps' | 'flatViewGroupMaps'>;
|
||||
@@ -42,13 +41,6 @@ export const handleEnumFlatFieldMetadataUpdateSideEffects = ({
|
||||
EMPTY_ENUM_FIELD_METADATA_SIDE_EFFECT_RESULT,
|
||||
);
|
||||
|
||||
if (
|
||||
!isEnumFlatFieldMetadata(toFlatFieldMetadata) ||
|
||||
!isEnumFlatFieldMetadata(fromFlatFieldMetadata)
|
||||
) {
|
||||
return sideEffectResult;
|
||||
}
|
||||
|
||||
if (
|
||||
JSON.stringify(fromFlatFieldMetadata.options) !==
|
||||
JSON.stringify(toFlatFieldMetadata.options)
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { reduceFlatViewGroupsByViewId } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-id.util';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
type HandleFlatFieldMetadataDeactivationSideEffectsArgs = FromTo<
|
||||
FlatFieldMetadata,
|
||||
'flatFieldMetadata'
|
||||
> &
|
||||
Pick<
|
||||
AllFlatEntityMaps,
|
||||
| 'flatViewMaps'
|
||||
| 'flatViewFilterMaps'
|
||||
| 'flatViewFieldMaps'
|
||||
| 'flatViewGroupMaps'
|
||||
>;
|
||||
|
||||
export type FieldMetadataDeactivationSideEffect = {
|
||||
flatViewsToDelete: FlatView[];
|
||||
flatViewsToUpdate: FlatView[];
|
||||
flatViewFieldsToDelete: FlatViewField[];
|
||||
flatViewFiltersToDelete: FlatViewFilter[];
|
||||
};
|
||||
|
||||
export const handleFieldMetadataDeactivationSideEffects = ({
|
||||
flatViewMaps,
|
||||
fromFlatFieldMetadata,
|
||||
flatViewFieldMaps,
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
}: HandleFlatFieldMetadataDeactivationSideEffectsArgs): FieldMetadataDeactivationSideEffect => {
|
||||
const flatViewFiltersToDelete = findManyFlatEntityByIdInFlatEntityMapsOrThrow(
|
||||
{
|
||||
flatEntityIds: fromFlatFieldMetadata.viewFilterIds,
|
||||
flatEntityMaps: flatViewFilterMaps,
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFieldsToDelete = findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityIds: fromFlatFieldMetadata.viewFieldIds,
|
||||
flatEntityMaps: flatViewFieldMaps,
|
||||
});
|
||||
|
||||
const flatViewGroups = findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityIds: fromFlatFieldMetadata.viewGroupIds,
|
||||
flatEntityMaps: flatViewGroupMaps,
|
||||
});
|
||||
|
||||
const { flatViewGroupRecordByViewId } = reduceFlatViewGroupsByViewId({
|
||||
flatViewGroups,
|
||||
});
|
||||
|
||||
// Note: We assume a view only has view groups related to one field
|
||||
const viewIdsToDelete = [
|
||||
...new Set([
|
||||
...Object.keys(flatViewGroupRecordByViewId),
|
||||
...fromFlatFieldMetadata.calendarViewIds,
|
||||
]),
|
||||
];
|
||||
|
||||
const flatViewsToDelete = findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityIds: viewIdsToDelete,
|
||||
flatEntityMaps: flatViewMaps,
|
||||
});
|
||||
|
||||
const viewIdsToUpdate =
|
||||
fromFlatFieldMetadata.kanbanAggregateOperationViewIds.filter(
|
||||
(viewId) => !viewIdsToDelete.includes(viewId),
|
||||
);
|
||||
const flatViewsToUpdate = findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityIds: viewIdsToUpdate,
|
||||
flatEntityMaps: flatViewMaps,
|
||||
}).map((flatView) => ({
|
||||
...flatView,
|
||||
kanbanAggregateOperation: null,
|
||||
kanbanAggregateOperationFieldMetadataId: null,
|
||||
}));
|
||||
|
||||
return {
|
||||
flatViewsToUpdate,
|
||||
flatViewsToDelete,
|
||||
flatViewFieldsToDelete,
|
||||
flatViewFiltersToDelete,
|
||||
};
|
||||
};
|
||||
+87
-23
@@ -3,17 +3,23 @@ import { type FromTo } from 'twenty-shared/types';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { handleEnumFlatFieldMetadataUpdateSideEffects } from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-enum-flat-field-metadata-update-side-effects.util';
|
||||
import {
|
||||
type FieldMetadataDeactivationSideEffect,
|
||||
handleFieldMetadataDeactivationSideEffects,
|
||||
} from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-field-metadata-deactivation-side-effects.util';
|
||||
import {
|
||||
type FieldMetadataUpdateIndexSideEffect,
|
||||
handleIndexChangesDuringFieldUpdate,
|
||||
} from 'src/engine/metadata-modules/flat-field-metadata/utils/handle-index-changes-during-field-update.util';
|
||||
import { isEnumFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-enum-flat-field-metadata.util';
|
||||
import { type FlatViewFiltersToDeleteAndUpdate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-filters-on-flat-field-metadata-options-update.util';
|
||||
import { type FlatViewGroupsToDeleteUpdateAndCreate } from 'src/engine/metadata-modules/flat-field-metadata/utils/recompute-view-groups-on-flat-field-metadata-options-update.util';
|
||||
|
||||
export type FlatFieldMetadataUpdateSideEffects =
|
||||
FlatViewFiltersToDeleteAndUpdate &
|
||||
FlatViewGroupsToDeleteUpdateAndCreate &
|
||||
FieldMetadataUpdateIndexSideEffect;
|
||||
FieldMetadataUpdateIndexSideEffect &
|
||||
FieldMetadataDeactivationSideEffect;
|
||||
|
||||
type HandleFlatFieldMetadataUpdateSideEffectArgs = FromTo<
|
||||
FlatFieldMetadata,
|
||||
@@ -26,8 +32,25 @@ type HandleFlatFieldMetadataUpdateSideEffectArgs = FromTo<
|
||||
| 'flatFieldMetadataMaps'
|
||||
| 'flatViewFilterMaps'
|
||||
| 'flatViewGroupMaps'
|
||||
| 'flatViewMaps'
|
||||
| 'flatViewFieldMaps'
|
||||
>;
|
||||
|
||||
export const FLAT_FIELD_METADATA_UPDATE_EMPTY_SIDE_EFFECTS: FlatFieldMetadataUpdateSideEffects =
|
||||
{
|
||||
flatIndexMetadatasToUpdate: [],
|
||||
flatViewFiltersToDelete: [],
|
||||
flatViewFiltersToUpdate: [],
|
||||
flatViewGroupsToCreate: [],
|
||||
flatViewGroupsToDelete: [],
|
||||
flatIndexMetadatasToDelete: [],
|
||||
flatIndexMetadatasToCreate: [],
|
||||
flatViewGroupsToUpdate: [],
|
||||
flatViewsToDelete: [],
|
||||
flatViewFieldsToDelete: [],
|
||||
flatViewsToUpdate: [],
|
||||
};
|
||||
|
||||
export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
@@ -36,19 +59,59 @@ export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
flatFieldMetadataMaps,
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
flatViewFieldMaps,
|
||||
}: HandleFlatFieldMetadataUpdateSideEffectArgs): FlatFieldMetadataUpdateSideEffects => {
|
||||
const {
|
||||
flatViewFiltersToDelete,
|
||||
flatViewFiltersToUpdate,
|
||||
flatViewGroupsToCreate,
|
||||
flatViewGroupsToDelete,
|
||||
flatViewGroupsToUpdate,
|
||||
} = handleEnumFlatFieldMetadataUpdateSideEffects({
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
});
|
||||
const sideEffectResult = structuredClone(
|
||||
FLAT_FIELD_METADATA_UPDATE_EMPTY_SIDE_EFFECTS,
|
||||
);
|
||||
|
||||
const isDeactivation =
|
||||
fromFlatFieldMetadata.isActive === true &&
|
||||
toFlatFieldMetadata.isActive === false;
|
||||
|
||||
if (isDeactivation) {
|
||||
const {
|
||||
flatViewsToDelete,
|
||||
flatViewFieldsToDelete,
|
||||
flatViewFiltersToDelete,
|
||||
flatViewsToUpdate,
|
||||
} = handleFieldMetadataDeactivationSideEffects({
|
||||
flatViewMaps,
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
flatViewFieldMaps,
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
});
|
||||
|
||||
sideEffectResult.flatViewsToUpdate.push(...flatViewsToUpdate);
|
||||
sideEffectResult.flatViewsToDelete.push(...flatViewsToDelete);
|
||||
sideEffectResult.flatViewFieldsToDelete.push(...flatViewFieldsToDelete);
|
||||
sideEffectResult.flatViewFiltersToDelete.push(...flatViewFiltersToDelete);
|
||||
} else if (
|
||||
isEnumFlatFieldMetadata(toFlatFieldMetadata) &&
|
||||
isEnumFlatFieldMetadata(fromFlatFieldMetadata)
|
||||
) {
|
||||
const {
|
||||
flatViewFiltersToDelete,
|
||||
flatViewFiltersToUpdate,
|
||||
flatViewGroupsToCreate,
|
||||
flatViewGroupsToDelete,
|
||||
flatViewGroupsToUpdate,
|
||||
} = handleEnumFlatFieldMetadataUpdateSideEffects({
|
||||
flatViewFilterMaps,
|
||||
flatViewGroupMaps,
|
||||
fromFlatFieldMetadata,
|
||||
toFlatFieldMetadata,
|
||||
});
|
||||
|
||||
sideEffectResult.flatViewFiltersToUpdate.push(...flatViewFiltersToUpdate);
|
||||
sideEffectResult.flatViewGroupsToCreate.push(...flatViewGroupsToCreate);
|
||||
sideEffectResult.flatViewGroupsToDelete.push(...flatViewGroupsToDelete);
|
||||
sideEffectResult.flatViewGroupsToUpdate.push(...flatViewGroupsToUpdate);
|
||||
sideEffectResult.flatViewFiltersToDelete.push(...flatViewFiltersToDelete);
|
||||
}
|
||||
|
||||
const {
|
||||
flatIndexMetadatasToUpdate,
|
||||
@@ -62,14 +125,15 @@ export const handleFlatFieldMetadataUpdateSideEffect = ({
|
||||
flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
flatIndexMetadatasToUpdate,
|
||||
flatViewFiltersToDelete,
|
||||
flatViewFiltersToUpdate,
|
||||
flatViewGroupsToCreate,
|
||||
flatViewGroupsToDelete,
|
||||
flatIndexMetadatasToDelete,
|
||||
flatIndexMetadatasToCreate,
|
||||
flatViewGroupsToUpdate,
|
||||
};
|
||||
sideEffectResult.flatIndexMetadatasToUpdate.push(
|
||||
...flatIndexMetadatasToUpdate,
|
||||
);
|
||||
sideEffectResult.flatIndexMetadatasToCreate.push(
|
||||
...flatIndexMetadatasToCreate,
|
||||
);
|
||||
sideEffectResult.flatIndexMetadatasToDelete.push(
|
||||
...flatIndexMetadatasToDelete,
|
||||
);
|
||||
|
||||
return sideEffectResult;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
@@ -19,6 +20,7 @@ export type ViewEntityRelationProperties =
|
||||
| ViewGroupEntity
|
||||
| ViewFilterGroupEntity
|
||||
| Workspace
|
||||
| FieldMetadataEntity
|
||||
>;
|
||||
|
||||
export type FlatView = FlatEntityFrom<
|
||||
|
||||
+16
@@ -29,6 +29,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: true,
|
||||
objectMetadataId,
|
||||
@@ -66,6 +68,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -103,6 +107,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -140,6 +146,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -177,6 +185,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -214,6 +224,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -250,6 +262,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
id: v4(),
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
@@ -286,6 +300,8 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
id: v4(),
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
|
||||
+4
@@ -63,6 +63,8 @@ const generateSourceFlatFieldMetadata = ({
|
||||
}
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
viewFilterIds: [],
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
@@ -131,7 +133,9 @@ const generateTargetFlatFieldMetadata = ({
|
||||
|
||||
return {
|
||||
morphId: null,
|
||||
calendarViewIds: [],
|
||||
viewFieldIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
id: sourceFlatFieldMetadata.relationTargetFieldMetadataId,
|
||||
|
||||
+15
-7
@@ -250,13 +250,19 @@ export class ViewFieldV2Service {
|
||||
const {
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFieldMaps', 'flatViewMaps'],
|
||||
},
|
||||
);
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
} = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatViewFieldMaps',
|
||||
'flatViewMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const existingViewFieldToDelete =
|
||||
fromDestroyViewFieldInputToFlatViewFieldOrThrow({
|
||||
@@ -277,6 +283,8 @@ export class ViewFieldV2Service {
|
||||
},
|
||||
dependencyAllFlatEntityMaps: {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
|
||||
@@ -17,6 +17,7 @@ import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/inte
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
|
||||
@@ -101,6 +102,17 @@ export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
kanbanAggregateOperationFieldMetadataId: string | null;
|
||||
|
||||
@ManyToOne(
|
||||
() => FieldMetadataEntity,
|
||||
(FieldMetadataEntity) => FieldMetadataEntity.kanbanAggregateOperationViews,
|
||||
{
|
||||
onDelete: 'CASCADE',
|
||||
nullable: true,
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'kanbanAggregateOperationFieldMetadataId' })
|
||||
kanbanAggregateOperationFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@Column({
|
||||
type: 'enum',
|
||||
enum: Object.values(ViewCalendarLayout),
|
||||
@@ -112,6 +124,17 @@ export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
calendarFieldMetadataId: string | null;
|
||||
|
||||
@ManyToOne(
|
||||
() => FieldMetadataEntity,
|
||||
(fieldMetadata) => fieldMetadata.calendarViews,
|
||||
{
|
||||
onDelete: 'CASCADE',
|
||||
nullable: true,
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'calendarFieldMetadataId' })
|
||||
calendarFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
|
||||
+39
-13
@@ -31,13 +31,20 @@ export class ViewV2Service {
|
||||
createViewInput: CreateViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { flatObjectMetadataMaps, flatViewMaps: existingFlatViewMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps', 'flatViewMaps'],
|
||||
},
|
||||
);
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
} = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatViewMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFromCreateInput = fromCreateViewInputToFlatViewToCreate({
|
||||
createViewInput,
|
||||
@@ -57,6 +64,7 @@ export class ViewV2Service {
|
||||
},
|
||||
dependencyAllFlatEntityMaps: {
|
||||
flatObjectMetadataMaps: flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
@@ -93,11 +101,14 @@ export class ViewV2Service {
|
||||
updateViewInput: UpdateViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
const {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewMaps'],
|
||||
flatMapsKeys: ['flatViewMaps', 'flatFieldMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -118,6 +129,9 @@ export class ViewV2Service {
|
||||
flatEntityToUpdate: [flatViewFromUpdateInput],
|
||||
}),
|
||||
},
|
||||
dependencyAllFlatEntityMaps: {
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
},
|
||||
@@ -153,11 +167,14 @@ export class ViewV2Service {
|
||||
deleteViewInput: DeleteViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
const {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewMaps'],
|
||||
flatMapsKeys: ['flatViewMaps', 'flatFieldMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -178,6 +195,9 @@ export class ViewV2Service {
|
||||
flatEntityToUpdate: [optimisticallyUpdatedFlatViewWithDeletedAt],
|
||||
}),
|
||||
},
|
||||
dependencyAllFlatEntityMaps: {
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
},
|
||||
@@ -213,11 +233,14 @@ export class ViewV2Service {
|
||||
destroyViewInput: DestroyViewInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
const {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewMaps'],
|
||||
flatMapsKeys: ['flatViewMaps', 'flatFieldMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -243,6 +266,9 @@ export class ViewV2Service {
|
||||
view: true,
|
||||
},
|
||||
},
|
||||
dependencyAllFlatEntityMaps: {
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user