Add workspace migration orchestrator + refactor builders + view/viewField action builders (#14383)
This commit is contained in:
+12
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ViewCacheService } from 'src/engine/core-modules/view/cache/services/view-cache.service';
|
||||
import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([ViewEntity])],
|
||||
providers: [ViewCacheService],
|
||||
exports: [ViewCacheService],
|
||||
})
|
||||
export class ViewCacheModule {}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
import { FlatViewMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-maps.type';
|
||||
import { generateFlatViewMaps } from 'src/engine/core-modules/view/flat-view/utils/generate-flat-view-maps.util';
|
||||
|
||||
type GetExistingOrRecomputeFlatViewMapsResult = {
|
||||
flatViewMaps: FlatViewMaps;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class ViewCacheService {
|
||||
logger = new Logger(ViewCacheService.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(ViewEntity)
|
||||
private readonly viewRepository: Repository<ViewEntity>,
|
||||
) {}
|
||||
|
||||
async getExistingOrRecomputeFlatViewMaps({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<GetExistingOrRecomputeFlatViewMapsResult> {
|
||||
// TODO: get from cache later
|
||||
const existingViews = await this.viewRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
relations: ['viewFields'],
|
||||
select: {
|
||||
viewFields: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const existingFlatViewMaps = generateFlatViewMaps(existingViews);
|
||||
|
||||
return {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,10 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
||||
where: '"deletedAt" IS NULL',
|
||||
},
|
||||
)
|
||||
export class ViewFieldEntity extends SyncableEntity {
|
||||
export class ViewFieldEntity
|
||||
extends SyncableEntity
|
||||
implements Required<ViewFieldEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@@ -59,7 +62,7 @@ export class ViewFieldEntity extends SyncableEntity {
|
||||
nullable: true,
|
||||
default: null,
|
||||
})
|
||||
aggregateOperation?: AggregateOperations | null;
|
||||
aggregateOperation: AggregateOperations | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
viewId: string;
|
||||
@@ -74,7 +77,7 @@ export class ViewFieldEntity extends SyncableEntity {
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt?: Date | null;
|
||||
deletedAt: Date | null;
|
||||
|
||||
@ManyToOne(() => Workspace, {
|
||||
onDelete: 'CASCADE',
|
||||
|
||||
@@ -31,7 +31,7 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
|
||||
'workspaceId',
|
||||
'objectMetadataId',
|
||||
])
|
||||
export class ViewEntity extends SyncableEntity {
|
||||
export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@@ -89,10 +89,10 @@ export class ViewEntity extends SyncableEntity {
|
||||
nullable: true,
|
||||
default: null,
|
||||
})
|
||||
kanbanAggregateOperation?: AggregateOperations | null;
|
||||
kanbanAggregateOperation: AggregateOperations | null;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
kanbanAggregateOperationFieldMetadataId?: string | null;
|
||||
kanbanAggregateOperationFieldMetadataId: string | null;
|
||||
|
||||
@Column({ nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
@@ -104,10 +104,10 @@ export class ViewEntity extends SyncableEntity {
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt?: Date | null;
|
||||
deletedAt: Date | null;
|
||||
|
||||
@Column({ nullable: true, type: 'text', default: null })
|
||||
anyFieldFilterValue?: string | null;
|
||||
anyFieldFilterValue: string | null;
|
||||
|
||||
@ManyToOne(() => Workspace, {
|
||||
onDelete: 'CASCADE',
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import {
|
||||
appendCommonExceptionCode,
|
||||
CustomException,
|
||||
} from 'src/utils/custom-exception';
|
||||
|
||||
export class FlatViewException extends CustomException<
|
||||
keyof typeof FlatViewExceptionCode
|
||||
> {}
|
||||
|
||||
export const FlatViewExceptionCode = appendCommonExceptionCode({
|
||||
VIEW_NOT_FOUND: 'VIEW_NOT_FOUND',
|
||||
VIEW_ALREADY_EXISTS: 'VIEW_ALREADY_EXISTS',
|
||||
} as const);
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export const FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE = [
|
||||
'isVisible',
|
||||
'size',
|
||||
'position',
|
||||
'aggregateOperation',
|
||||
] as const satisfies (keyof FlatViewField)[];
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export const FLAT_VIEW_PROPERTIES_TO_COMPARE = [
|
||||
'name',
|
||||
'type',
|
||||
'key',
|
||||
'isCompact',
|
||||
'openRecordIn',
|
||||
'kanbanAggregateOperation',
|
||||
'kanbanAggregateOperationFieldMetadataId',
|
||||
'position',
|
||||
'anyFieldFilterValue',
|
||||
'icon',
|
||||
] as const satisfies (keyof FlatView)[];
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { type ViewEntityRelationProperties } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export const VIEW_ENTITY_RELATION_PROPERTIES = [
|
||||
'objectMetadata',
|
||||
'viewFields',
|
||||
'viewFilters',
|
||||
'viewFilterGroups',
|
||||
'viewGroups',
|
||||
'viewSorts',
|
||||
'workspace',
|
||||
] as const satisfies ViewEntityRelationProperties[];
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { type ViewFieldEntityRelationProperties } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export const VIEW_FIELD_ENTITY_RELATION_PROPERTIES = [
|
||||
'fieldMetadata',
|
||||
'view',
|
||||
'workspace',
|
||||
] as const satisfies ViewFieldEntityRelationProperties[];
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export type FailedFlatViewFieldValidationMinimalInformation = Partial<
|
||||
Pick<FlatViewField, 'id' | 'fieldMetadataId' | 'viewId'>
|
||||
>;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type FailedFlatViewFieldValidationMinimalInformation } from 'src/engine/core-modules/view/flat-view/types/failed-flat-view-field-validation-minimal-information.type';
|
||||
import { type FlatViewFieldValidationError } from 'src/engine/core-modules/view/flat-view/types/flat-view-field-validation-error.type';
|
||||
import { type WorkspaceMigrationViewFieldActionTypeV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type';
|
||||
|
||||
export type FailedFlatViewFieldValidation = {
|
||||
type: WorkspaceMigrationViewFieldActionTypeV2;
|
||||
viewFieldLevelErrors: FlatViewFieldValidationError[];
|
||||
failedViewFieldValidationMinimalInformation: Partial<FailedFlatViewFieldValidationMinimalInformation>;
|
||||
};
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export type FailedFlatViewValidationMinimalInformation = Partial<
|
||||
Pick<FlatView, 'id' | 'name' | 'objectMetadataId'>
|
||||
>;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type FailedFlatViewValidationMinimalInformation } from 'src/engine/core-modules/view/flat-view/types/failed-flat-view-validation-minimal-information.type';
|
||||
import { type FlatViewValidationError } from 'src/engine/core-modules/view/flat-view/types/flat-view-validation-error.type';
|
||||
import { type WorkspaceMigrationViewActionTypeV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type';
|
||||
|
||||
export type FailedFlatViewValidation = {
|
||||
type: WorkspaceMigrationViewActionTypeV2;
|
||||
viewLevelErrors: FlatViewValidationError[];
|
||||
failedViewValidationMinimalInformation: Partial<FailedFlatViewValidationMinimalInformation>;
|
||||
};
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export type FlatViewFieldMaps = FlatEntityMaps<FlatViewField>;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE } from 'src/engine/core-modules/view/flat-view/constants/flat-view-field-properties-to-compare.constant';
|
||||
|
||||
export type FlatViewFieldPropertiesToCompare =
|
||||
(typeof FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE)[number];
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export type FlatViewFieldValidationError = {
|
||||
message: string;
|
||||
code: string;
|
||||
};
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity';
|
||||
import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
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 ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type ViewFieldEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
ViewFieldEntity,
|
||||
FieldMetadataEntity | ViewEntity | Workspace
|
||||
>;
|
||||
|
||||
export type FlatViewField = Omit<
|
||||
ViewFieldEntity,
|
||||
ViewFieldEntityRelationProperties
|
||||
> & {
|
||||
universalIdentifier: string;
|
||||
};
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export type FlatViewMaps = FlatEntityMaps<FlatView>;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FLAT_VIEW_PROPERTIES_TO_COMPARE } from 'src/engine/core-modules/view/flat-view/constants/flat-view-properies-to-compare.constant';
|
||||
|
||||
export type FlatViewPropertiesToCompare =
|
||||
(typeof FLAT_VIEW_PROPERTIES_TO_COMPARE)[number];
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type ViewExceptionCode } from 'src/engine/core-modules/view/exceptions/view.exception';
|
||||
|
||||
export type FlatViewValidationError = {
|
||||
code: ViewExceptionCode;
|
||||
message: string;
|
||||
userFriendlyMessage?: string;
|
||||
value?: unknown;
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity';
|
||||
import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity';
|
||||
import { type ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity';
|
||||
import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity';
|
||||
import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity';
|
||||
import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type ViewEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
ViewEntity,
|
||||
| ObjectMetadataEntity
|
||||
| ViewFieldEntity
|
||||
| ViewSortEntity
|
||||
| ViewFilterEntity
|
||||
| ViewGroupEntity
|
||||
| ViewFilterGroupEntity
|
||||
| Workspace
|
||||
>;
|
||||
|
||||
export type FlatView = Omit<ViewEntity, ViewEntityRelationProperties> & {
|
||||
universalIdentifier: string;
|
||||
viewFieldIds: string[];
|
||||
};
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
import diff from 'microdiff';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE } from 'src/engine/core-modules/view/flat-view/constants/flat-view-field-properties-to-compare.constant';
|
||||
import { type FlatViewFieldPropertiesToCompare } from 'src/engine/core-modules/view/flat-view/types/flat-view-field-properties-to-compare.type';
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
import { type UpdateViewFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
type GetWorkspaceMigrationUpdateViewFieldActionArgs = FromTo<
|
||||
FlatViewField,
|
||||
'FlatViewField'
|
||||
>;
|
||||
|
||||
export const compareTwoFlatViewField = ({
|
||||
fromFlatViewField,
|
||||
toFlatViewField,
|
||||
}: GetWorkspaceMigrationUpdateViewFieldActionArgs) => {
|
||||
const transformMetadataForComparisonParameters = {
|
||||
shouldIgnoreProperty: (property: string) =>
|
||||
!FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE.includes(
|
||||
property as FlatViewFieldPropertiesToCompare,
|
||||
),
|
||||
propertiesToStringify: [],
|
||||
};
|
||||
const fromCompare = transformMetadataForComparison(
|
||||
fromFlatViewField,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
const toCompare = transformMetadataForComparison(
|
||||
toFlatViewField,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
|
||||
const flatViewFieldDifferences = diff(fromCompare, toCompare);
|
||||
|
||||
return flatViewFieldDifferences.flatMap<
|
||||
UpdateViewFieldAction['updates'][number]
|
||||
>((difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { oldValue, path, value } = difference;
|
||||
const property = path[0] as FlatViewFieldPropertiesToCompare;
|
||||
|
||||
return {
|
||||
from: oldValue,
|
||||
to: value,
|
||||
property,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occurs, we should only provide null never undefined and so on
|
||||
return [];
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
import diff from 'microdiff';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { FLAT_VIEW_PROPERTIES_TO_COMPARE } from 'src/engine/core-modules/view/flat-view/constants/flat-view-properies-to-compare.constant';
|
||||
import { type FlatViewPropertiesToCompare } from 'src/engine/core-modules/view/flat-view/types/flat-view-properties-to-compare.type';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
import { type UpdateViewAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
type GetWorkspaceMigrationUpdateViewActionArgs = FromTo<FlatView, 'FlatView'>;
|
||||
|
||||
export const compareTwoFlatView = ({
|
||||
fromFlatView,
|
||||
toFlatView,
|
||||
}: GetWorkspaceMigrationUpdateViewActionArgs) => {
|
||||
const transformMetadataForComparisonParameters = {
|
||||
shouldIgnoreProperty: (property: string) =>
|
||||
!FLAT_VIEW_PROPERTIES_TO_COMPARE.includes(
|
||||
property as FlatViewPropertiesToCompare,
|
||||
),
|
||||
propertiesToStringify: [],
|
||||
};
|
||||
const fromCompare = transformMetadataForComparison(
|
||||
fromFlatView,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
const toCompare = transformMetadataForComparison(
|
||||
toFlatView,
|
||||
transformMetadataForComparisonParameters,
|
||||
);
|
||||
|
||||
const flatViewDifferences = diff(fromCompare, toCompare);
|
||||
|
||||
return flatViewDifferences.flatMap<UpdateViewAction['updates'][number]>(
|
||||
(difference) => {
|
||||
switch (difference.type) {
|
||||
case 'CHANGE': {
|
||||
const { oldValue, path, value } = difference;
|
||||
const property = path[0] as FlatViewPropertiesToCompare;
|
||||
|
||||
return {
|
||||
from: oldValue,
|
||||
to: value,
|
||||
property,
|
||||
};
|
||||
}
|
||||
case 'CREATE':
|
||||
case 'REMOVE':
|
||||
default: {
|
||||
// Should never occurs, we should only provide null never undefined and so on
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export const fromPartialFlatViewFieldToFlatViewFieldWithDefault = (
|
||||
partialFlatViewField: Partial<FlatViewField>,
|
||||
): FlatViewField => {
|
||||
const createdAt = new Date();
|
||||
const viewFieldId = partialFlatViewField.id ?? v4();
|
||||
|
||||
return {
|
||||
...partialFlatViewField,
|
||||
id: viewFieldId,
|
||||
fieldMetadataId: partialFlatViewField.fieldMetadataId ?? '',
|
||||
isVisible: partialFlatViewField.isVisible ?? true,
|
||||
size: partialFlatViewField.size ?? 0,
|
||||
position: partialFlatViewField.position ?? 0,
|
||||
aggregateOperation: partialFlatViewField.aggregateOperation ?? null,
|
||||
viewId: partialFlatViewField.viewId ?? '',
|
||||
workspaceId: partialFlatViewField.workspaceId ?? '',
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier:
|
||||
partialFlatViewField.universalIdentifier ?? viewFieldId,
|
||||
};
|
||||
};
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in';
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export const fromPartialFlatViewToFlatViewWithDefault = (
|
||||
partialFlatView: Partial<FlatView>,
|
||||
): FlatView => {
|
||||
const createdAt = new Date();
|
||||
const viewId = partialFlatView.id ?? v4();
|
||||
|
||||
return {
|
||||
...partialFlatView,
|
||||
id: viewId,
|
||||
name: partialFlatView.name ?? '',
|
||||
objectMetadataId: partialFlatView.objectMetadataId ?? '',
|
||||
type: partialFlatView.type ?? ViewType.TABLE,
|
||||
key: partialFlatView.key ?? null,
|
||||
icon: partialFlatView.icon ?? '',
|
||||
position: partialFlatView.position ?? 0,
|
||||
isCompact: partialFlatView.isCompact ?? false,
|
||||
isCustom: partialFlatView.isCustom ?? false,
|
||||
openRecordIn: partialFlatView.openRecordIn ?? ViewOpenRecordIn.SIDE_PANEL,
|
||||
kanbanAggregateOperation: partialFlatView.kanbanAggregateOperation ?? null,
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
partialFlatView.kanbanAggregateOperationFieldMetadataId ?? null,
|
||||
workspaceId: partialFlatView.workspaceId ?? '',
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
anyFieldFilterValue: partialFlatView.anyFieldFilterValue ?? null,
|
||||
universalIdentifier: partialFlatView.universalIdentifier ?? viewId,
|
||||
viewFieldIds: partialFlatView.viewFieldIds ?? [],
|
||||
};
|
||||
};
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
import { VIEW_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/view/flat-view/constants/view-entity-relation-properties.constant';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export const fromViewEntityToFlatView = (viewEntity: ViewEntity): FlatView => {
|
||||
const viewEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewEntity,
|
||||
VIEW_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
|
||||
return {
|
||||
...viewEntityWithoutRelations,
|
||||
universalIdentifier:
|
||||
viewEntityWithoutRelations.universalIdentifier ??
|
||||
viewEntityWithoutRelations.id,
|
||||
viewFieldIds: viewEntity.viewFields?.map((viewField) => viewField.id) ?? [],
|
||||
};
|
||||
};
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity';
|
||||
import { VIEW_FIELD_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/view/flat-view/constants/view-field-entity-relation-properties.constant';
|
||||
import { type FlatViewField } from 'src/engine/core-modules/view/flat-view/types/flat-view-field.type';
|
||||
|
||||
export const fromViewFieldEntityToFlatViewField = (
|
||||
viewFieldEntity: ViewFieldEntity,
|
||||
): FlatViewField => {
|
||||
const viewFieldEntityWithoutRelations = removePropertiesFromRecord(
|
||||
viewFieldEntity,
|
||||
VIEW_FIELD_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
|
||||
return {
|
||||
...viewFieldEntityWithoutRelations,
|
||||
universalIdentifier:
|
||||
viewFieldEntityWithoutRelations.universalIdentifier ??
|
||||
viewFieldEntityWithoutRelations.id,
|
||||
};
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
import { type FlatViewMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-maps.type';
|
||||
import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat-view.type';
|
||||
|
||||
export const generateFlatViewMaps = (
|
||||
viewCollection: ViewEntity[],
|
||||
): FlatViewMaps => {
|
||||
const flatViewMaps: FlatViewMaps = {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
for (const view of viewCollection) {
|
||||
const processedFlatView: FlatView = {
|
||||
...view,
|
||||
viewFieldIds: view.viewFields?.map((viewField) => viewField.id) ?? [],
|
||||
universalIdentifier: view.universalIdentifier ?? view.id, // TODO: should not fallback to id, to remove once we have universalIdentifier required
|
||||
};
|
||||
|
||||
flatViewMaps.byId[view.id] = processedFlatView;
|
||||
flatViewMaps.idByUniversalIdentifier[
|
||||
processedFlatView.universalIdentifier
|
||||
] = view.id;
|
||||
}
|
||||
|
||||
return flatViewMaps;
|
||||
};
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { Equal, Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity';
|
||||
import {
|
||||
ViewFieldException,
|
||||
ViewFieldExceptionCode,
|
||||
ViewFieldExceptionMessageKey,
|
||||
generateViewFieldExceptionMessage,
|
||||
generateViewFieldUserFriendlyExceptionMessage,
|
||||
} from 'src/engine/core-modules/view/exceptions/view-field.exception';
|
||||
import { VIEW_FIELD_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/view/flat-view/constants/view-field-entity-relation-properties.constant';
|
||||
import { FlatViewFieldMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-field-maps.type';
|
||||
import { fromPartialFlatViewFieldToFlatViewFieldWithDefault } from 'src/engine/core-modules/view/flat-view/utils/from-partial-flat-view-field-to-flat-view-field-with-default.util';
|
||||
import { fromViewFieldEntityToFlatViewField } from 'src/engine/core-modules/view/flat-view/utils/from-view-field-entity-to-flat-view-field.util';
|
||||
import { WorkspaceMigrationOrchestratorException } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-orchestrator-exception';
|
||||
import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service';
|
||||
|
||||
@Injectable()
|
||||
export class ViewFieldV2Service {
|
||||
constructor(
|
||||
@InjectRepository(ViewFieldEntity)
|
||||
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
|
||||
private readonly workspaceMigrationOrchestratorService: WorkspaceMigrationBuildOrchestratorService,
|
||||
) {}
|
||||
|
||||
// TODO: move to cache service
|
||||
private async getExistingFlatViewFieldMaps(
|
||||
workspaceId: string,
|
||||
): Promise<FlatViewFieldMaps> {
|
||||
const existingViewFields = await this.viewFieldRepository.find({
|
||||
where: { workspaceId },
|
||||
});
|
||||
|
||||
const flatViewFieldMaps: FlatViewFieldMaps = {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
for (const viewFieldEntity of existingViewFields) {
|
||||
const flatViewField = fromViewFieldEntityToFlatViewField(viewFieldEntity);
|
||||
|
||||
flatViewFieldMaps.byId[flatViewField.id] = flatViewField;
|
||||
flatViewFieldMaps.idByUniversalIdentifier[
|
||||
flatViewField.universalIdentifier
|
||||
] = flatViewField.id;
|
||||
}
|
||||
|
||||
return flatViewFieldMaps;
|
||||
}
|
||||
|
||||
async createOne(
|
||||
viewFieldData: Partial<ViewFieldEntity>,
|
||||
): Promise<ViewFieldEntity> {
|
||||
if (!isDefined(viewFieldData.workspaceId)) {
|
||||
throw new ViewFieldException(
|
||||
generateViewFieldExceptionMessage(
|
||||
ViewFieldExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
ViewFieldExceptionCode.INVALID_VIEW_FIELD_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewFieldUserFriendlyExceptionMessage(
|
||||
ViewFieldExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const existingFlatViewFieldMaps = await this.getExistingFlatViewFieldMaps(
|
||||
viewFieldData.workspaceId,
|
||||
);
|
||||
|
||||
const flatViewFieldFromCreateInput =
|
||||
fromPartialFlatViewFieldToFlatViewFieldWithDefault({
|
||||
...viewFieldData,
|
||||
universalIdentifier: viewFieldData.universalIdentifier ?? v4(),
|
||||
});
|
||||
|
||||
const toFlatViewFieldMaps: FlatViewFieldMaps =
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatViewFieldFromCreateInput,
|
||||
flatEntityMaps: existingFlatViewFieldMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
viewField: {
|
||||
fromFlatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
toFlatViewFieldMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
workspaceId: viewFieldData.workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while creating view field',
|
||||
);
|
||||
}
|
||||
|
||||
const [createdViewField] = await this.viewFieldRepository.find({
|
||||
where: {
|
||||
id: flatViewFieldFromCreateInput.id,
|
||||
},
|
||||
});
|
||||
|
||||
return createdViewField;
|
||||
}
|
||||
|
||||
async updateOne(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
updateData: Partial<ViewFieldEntity>,
|
||||
): Promise<ViewFieldEntity> {
|
||||
const existingFlatViewFieldMaps =
|
||||
await this.getExistingFlatViewFieldMaps(workspaceId);
|
||||
|
||||
const existingViewField = existingFlatViewFieldMaps.byId[id];
|
||||
|
||||
if (!isDefined(existingViewField)) {
|
||||
throw new ViewFieldException(
|
||||
generateViewFieldExceptionMessage(
|
||||
ViewFieldExceptionMessageKey.VIEW_FIELD_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewFieldExceptionCode.VIEW_FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const existingViewFieldToUpdate = removePropertiesFromRecord(
|
||||
{
|
||||
...existingViewField,
|
||||
...updateData,
|
||||
},
|
||||
VIEW_FIELD_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
|
||||
const flatViewFieldFromUpdateInput =
|
||||
fromPartialFlatViewFieldToFlatViewFieldWithDefault({
|
||||
...existingViewFieldToUpdate,
|
||||
universalIdentifier:
|
||||
existingViewFieldToUpdate.universalIdentifier ?? '',
|
||||
});
|
||||
|
||||
const toFlatViewFieldMaps: FlatViewFieldMaps =
|
||||
replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: flatViewFieldFromUpdateInput,
|
||||
flatEntityMaps: existingFlatViewFieldMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
viewField: {
|
||||
fromFlatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
toFlatViewFieldMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while updating view field',
|
||||
);
|
||||
}
|
||||
|
||||
const [updatedViewField] = await this.viewFieldRepository.find({
|
||||
where: {
|
||||
id: Equal(id),
|
||||
},
|
||||
});
|
||||
|
||||
return updatedViewField;
|
||||
}
|
||||
|
||||
async deleteOne(id: string, workspaceId: string): Promise<boolean> {
|
||||
const existingFlatViewFieldMaps =
|
||||
await this.getExistingFlatViewFieldMaps(workspaceId);
|
||||
|
||||
const existingViewFieldToDelete = existingFlatViewFieldMaps.byId[id];
|
||||
|
||||
if (!isDefined(existingViewFieldToDelete)) {
|
||||
throw new ViewFieldException(
|
||||
generateViewFieldExceptionMessage(
|
||||
ViewFieldExceptionMessageKey.VIEW_FIELD_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewFieldExceptionCode.VIEW_FIELD_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const toFlatViewFieldMaps: FlatViewFieldMaps =
|
||||
deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: existingFlatViewFieldMaps,
|
||||
entityToDeleteId: existingViewFieldToDelete.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
viewField: {
|
||||
fromFlatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
toFlatViewFieldMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: true,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while deleting view field',
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { Equal, Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util';
|
||||
import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util';
|
||||
import { ViewCacheService } from 'src/engine/core-modules/view/cache/services/view-cache.service';
|
||||
import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity';
|
||||
import {
|
||||
ViewException,
|
||||
ViewExceptionCode,
|
||||
ViewExceptionMessageKey,
|
||||
generateViewExceptionMessage,
|
||||
generateViewUserFriendlyExceptionMessage,
|
||||
} from 'src/engine/core-modules/view/exceptions/view.exception';
|
||||
import { VIEW_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/view/flat-view/constants/view-entity-relation-properties.constant';
|
||||
import { FlatViewMaps } from 'src/engine/core-modules/view/flat-view/types/flat-view-maps.type';
|
||||
import { fromPartialFlatViewToFlatViewWithDefault } from 'src/engine/core-modules/view/flat-view/utils/from-partial-flat-view-to-flat-view-to-with-default.util';
|
||||
import { WorkspaceMigrationOrchestratorException } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-orchestrator-exception';
|
||||
import { WorkspaceMigrationBuildOrchestratorService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service';
|
||||
|
||||
@Injectable()
|
||||
export class ViewV2Service {
|
||||
constructor(
|
||||
@InjectRepository(ViewEntity)
|
||||
private readonly viewRepository: Repository<ViewEntity>,
|
||||
private readonly workspaceMigrationOrchestratorService: WorkspaceMigrationBuildOrchestratorService,
|
||||
private readonly viewCacheService: ViewCacheService,
|
||||
) {}
|
||||
|
||||
async createOne(viewData: Partial<ViewEntity>): Promise<ViewEntity> {
|
||||
if (!isDefined(viewData.workspaceId)) {
|
||||
throw new ViewException(
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
ViewExceptionCode.INVALID_VIEW_DATA,
|
||||
{
|
||||
userFriendlyMessage: generateViewUserFriendlyExceptionMessage(
|
||||
ViewExceptionMessageKey.WORKSPACE_ID_REQUIRED,
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.viewCacheService.getExistingOrRecomputeFlatViewMaps({
|
||||
workspaceId: viewData.workspaceId,
|
||||
});
|
||||
|
||||
const flatViewFromCreateInput = fromPartialFlatViewToFlatViewWithDefault({
|
||||
...viewData,
|
||||
universalIdentifier: viewData.universalIdentifier ?? v4(),
|
||||
});
|
||||
|
||||
const toFlatViewMaps: FlatViewMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatViewFromCreateInput,
|
||||
flatEntityMaps: existingFlatViewMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
view: {
|
||||
fromFlatViewMaps: existingFlatViewMaps,
|
||||
toFlatViewMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
workspaceId: viewData.workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while creating view',
|
||||
);
|
||||
}
|
||||
|
||||
const [createdView] = await this.viewRepository.find({
|
||||
where: {
|
||||
id: flatViewFromCreateInput.id,
|
||||
},
|
||||
});
|
||||
|
||||
return createdView;
|
||||
}
|
||||
|
||||
async updateOne(
|
||||
id: string,
|
||||
workspaceId: string,
|
||||
updateData: Partial<ViewEntity>,
|
||||
): Promise<ViewEntity> {
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.viewCacheService.getExistingOrRecomputeFlatViewMaps({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const existingView = existingFlatViewMaps.byId[id];
|
||||
|
||||
if (!isDefined(existingView)) {
|
||||
throw new ViewException(
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.VIEW_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewExceptionCode.VIEW_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const existingViewToUpdate = removePropertiesFromRecord(
|
||||
{
|
||||
...existingView,
|
||||
...updateData,
|
||||
},
|
||||
VIEW_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
|
||||
const flatViewFromUpdateInput = fromPartialFlatViewToFlatViewWithDefault({
|
||||
...existingViewToUpdate,
|
||||
universalIdentifier: existingViewToUpdate.universalIdentifier ?? '',
|
||||
});
|
||||
|
||||
const toFlatViewMaps: FlatViewMaps =
|
||||
replaceFlatEntityInFlatEntityMapsOrThrow({
|
||||
flatEntity: flatViewFromUpdateInput,
|
||||
flatEntityMaps: existingFlatViewMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
view: {
|
||||
fromFlatViewMaps: existingFlatViewMaps,
|
||||
toFlatViewMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: false,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while updating view',
|
||||
);
|
||||
}
|
||||
|
||||
const [updatedView] = await this.viewRepository.find({
|
||||
where: {
|
||||
id: Equal(id),
|
||||
},
|
||||
});
|
||||
|
||||
return updatedView;
|
||||
}
|
||||
|
||||
async deleteOne(id: string, workspaceId: string): Promise<boolean> {
|
||||
const { flatViewMaps: existingFlatViewMaps } =
|
||||
await this.viewCacheService.getExistingOrRecomputeFlatViewMaps({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const existingViewToDelete = existingFlatViewMaps.byId[id];
|
||||
|
||||
if (!isDefined(existingViewToDelete)) {
|
||||
throw new ViewException(
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.VIEW_NOT_FOUND,
|
||||
id,
|
||||
),
|
||||
ViewExceptionCode.VIEW_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const toFlatViewMaps: FlatViewMaps =
|
||||
deleteFlatEntityFromFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: existingFlatViewMaps,
|
||||
entityToDeleteId: existingViewToDelete.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationOrchestratorService.buildWorkspaceMigrations(
|
||||
{
|
||||
entityMaps: {
|
||||
view: {
|
||||
fromFlatViewMaps: existingFlatViewMaps,
|
||||
toFlatViewMaps,
|
||||
},
|
||||
},
|
||||
buildOptions: {
|
||||
isSystemBuild: false,
|
||||
inferDeletionFromMissingEntities: true,
|
||||
},
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(validateAndBuildResult)) {
|
||||
throw new WorkspaceMigrationOrchestratorException(
|
||||
'Multiple validation errors occurred while deleting view',
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { I18nModule } from 'src/engine/core-modules/i18n/i18n.module';
|
||||
import { ViewCacheModule } from 'src/engine/core-modules/view/cache/services/view-cache.module';
|
||||
import { ViewFieldController } from 'src/engine/core-modules/view/controllers/view-field.controller';
|
||||
import { ViewFilterGroupController } from 'src/engine/core-modules/view/controllers/view-filter-group.controller';
|
||||
import { ViewFilterController } from 'src/engine/core-modules/view/controllers/view-filter.controller';
|
||||
@@ -20,14 +21,17 @@ import { ViewFilterResolver } from 'src/engine/core-modules/view/resolvers/view-
|
||||
import { ViewGroupResolver } from 'src/engine/core-modules/view/resolvers/view-group.resolver';
|
||||
import { ViewSortResolver } from 'src/engine/core-modules/view/resolvers/view-sort.resolver';
|
||||
import { ViewResolver } from 'src/engine/core-modules/view/resolvers/view.resolver';
|
||||
import { ViewFieldV2Service } from 'src/engine/core-modules/view/services/view-field-v2.service';
|
||||
import { ViewFieldService } from 'src/engine/core-modules/view/services/view-field.service';
|
||||
import { ViewFilterGroupService } from 'src/engine/core-modules/view/services/view-filter-group.service';
|
||||
import { ViewFilterService } from 'src/engine/core-modules/view/services/view-filter.service';
|
||||
import { ViewGroupService } from 'src/engine/core-modules/view/services/view-group.service';
|
||||
import { ViewSortService } from 'src/engine/core-modules/view/services/view-sort.service';
|
||||
import { ViewV2Service } from 'src/engine/core-modules/view/services/view-v2.service';
|
||||
import { ViewService } from 'src/engine/core-modules/view/services/view.service';
|
||||
import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -42,6 +46,8 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
|
||||
I18nModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
WorkspaceMetadataCacheModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
ViewCacheModule,
|
||||
],
|
||||
controllers: [
|
||||
ViewController,
|
||||
@@ -64,6 +70,8 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
|
||||
ViewFilterGroupResolver,
|
||||
ViewGroupResolver,
|
||||
ViewSortResolver,
|
||||
ViewV2Service,
|
||||
ViewFieldV2Service,
|
||||
],
|
||||
exports: [
|
||||
ViewService,
|
||||
@@ -72,6 +80,8 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
|
||||
ViewFilterGroupService,
|
||||
ViewGroupService,
|
||||
ViewSortService,
|
||||
ViewV2Service,
|
||||
ViewFieldV2Service,
|
||||
],
|
||||
})
|
||||
export class CoreViewModule {}
|
||||
|
||||
Reference in New Issue
Block a user