Migrate page layout widget to v2 of the API (#16323)
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
|
||||
export const FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES = [
|
||||
'title',
|
||||
'type',
|
||||
'objectMetadataId',
|
||||
'gridPosition',
|
||||
'configuration',
|
||||
] as const satisfies (keyof FlatPageLayoutWidget)[];
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import { type PageLayoutWidgetEntityRelationProperties } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
|
||||
export const PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'pageLayoutTab',
|
||||
'objectMetadata',
|
||||
'application',
|
||||
] as const satisfies PageLayoutWidgetEntityRelationProperties[];
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceFlatPageLayoutWidgetMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service';
|
||||
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([PageLayoutWidgetEntity])],
|
||||
providers: [WorkspaceFlatPageLayoutWidgetMapCacheService],
|
||||
exports: [WorkspaceFlatPageLayoutWidgetMapCacheService],
|
||||
})
|
||||
export class FlatPageLayoutWidgetModule {}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
|
||||
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { fromPageLayoutWidgetEntityToFlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util';
|
||||
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
|
||||
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceCache('flatPageLayoutWidgetMaps')
|
||||
export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCacheProvider<FlatPageLayoutWidgetMaps> {
|
||||
constructor(
|
||||
@InjectRepository(PageLayoutWidgetEntity)
|
||||
private readonly pageLayoutWidgetRepository: Repository<PageLayoutWidgetEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(
|
||||
workspaceId: string,
|
||||
): Promise<FlatPageLayoutWidgetMaps> {
|
||||
const existingPageLayoutWidgets =
|
||||
await this.pageLayoutWidgetRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
const flatPageLayoutWidgetMaps = createEmptyFlatEntityMaps();
|
||||
|
||||
for (const pageLayoutWidgetEntity of existingPageLayoutWidgets) {
|
||||
const flatPageLayoutWidget =
|
||||
fromPageLayoutWidgetEntityToFlatPageLayoutWidget(
|
||||
pageLayoutWidgetEntity,
|
||||
);
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
flatEntity: flatPageLayoutWidget,
|
||||
flatEntityMapsToMutate: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
}
|
||||
|
||||
return flatPageLayoutWidgetMaps;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
|
||||
export type FlatPageLayoutWidgetMaps = FlatEntityMaps<FlatPageLayoutWidget>;
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.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 PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
|
||||
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
|
||||
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
|
||||
|
||||
export type PageLayoutWidgetEntityRelationProperties =
|
||||
ExtractRecordTypeOrmRelationProperties<
|
||||
PageLayoutWidgetEntity,
|
||||
| PageLayoutTabEntity
|
||||
| ObjectMetadataEntity
|
||||
| WorkspaceEntity
|
||||
| ApplicationEntity
|
||||
>;
|
||||
|
||||
export type FlatPageLayoutWidget = FlatEntityFrom<
|
||||
PageLayoutWidgetEntity,
|
||||
PageLayoutWidgetEntityRelationProperties
|
||||
>;
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
|
||||
|
||||
export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
|
||||
{
|
||||
createPageLayoutWidgetInput: CreatePageLayoutWidgetInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
createPageLayoutWidgetInput: rawCreatePageLayoutWidgetInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => {
|
||||
const { pageLayoutTabId, ...createPageLayoutWidgetInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreatePageLayoutWidgetInput,
|
||||
['pageLayoutTabId'],
|
||||
);
|
||||
|
||||
const createdAt = new Date();
|
||||
const pageLayoutWidgetId = v4();
|
||||
|
||||
return {
|
||||
id: pageLayoutWidgetId,
|
||||
pageLayoutTabId,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: pageLayoutWidgetId,
|
||||
title: createPageLayoutWidgetInput.title,
|
||||
type: createPageLayoutWidgetInput.type ?? WidgetType.VIEW,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
|
||||
gridPosition: createPageLayoutWidgetInput.gridPosition,
|
||||
configuration: createPageLayoutWidgetInput.configuration ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type DeletePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/delete-page-layout-widget.input';
|
||||
import {
|
||||
PageLayoutWidgetException,
|
||||
PageLayoutWidgetExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
|
||||
|
||||
export const fromDeletePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow = ({
|
||||
deletePageLayoutWidgetInput: rawDeletePageLayoutWidgetInput,
|
||||
flatPageLayoutWidgetMaps,
|
||||
}: {
|
||||
deletePageLayoutWidgetInput: DeletePageLayoutWidgetInput;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}): FlatPageLayoutWidget => {
|
||||
const { id: pageLayoutWidgetId } = extractAndSanitizeObjectStringFields(
|
||||
rawDeletePageLayoutWidgetInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutWidgetToDelete =
|
||||
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutWidgetToDelete)) {
|
||||
throw new PageLayoutWidgetException(
|
||||
t`Page layout widget to delete not found`,
|
||||
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatPageLayoutWidgetToDelete,
|
||||
deletedAt: new Date(),
|
||||
};
|
||||
};
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type DestroyPageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/destroy-page-layout-widget.input';
|
||||
import {
|
||||
PageLayoutWidgetException,
|
||||
PageLayoutWidgetExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
|
||||
|
||||
export const fromDestroyPageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow = ({
|
||||
destroyPageLayoutWidgetInput,
|
||||
flatPageLayoutWidgetMaps,
|
||||
}: {
|
||||
destroyPageLayoutWidgetInput: DestroyPageLayoutWidgetInput;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}): FlatPageLayoutWidget => {
|
||||
const { id: pageLayoutWidgetId } = extractAndSanitizeObjectStringFields(
|
||||
destroyPageLayoutWidgetInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutWidgetToDestroy =
|
||||
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutWidgetToDestroy)) {
|
||||
throw new PageLayoutWidgetException(
|
||||
t`Page layout widget to destroy not found`,
|
||||
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatPageLayoutWidgetToDestroy;
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/page-layout-widget-entity-relation-properties.constant';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
|
||||
|
||||
export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = (
|
||||
pageLayoutWidgetEntity: PageLayoutWidgetEntity,
|
||||
): FlatPageLayoutWidget => {
|
||||
const pageLayoutWidgetEntityWithoutRelations = removePropertiesFromRecord(
|
||||
pageLayoutWidgetEntity,
|
||||
PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
|
||||
return {
|
||||
...pageLayoutWidgetEntityWithoutRelations,
|
||||
universalIdentifier:
|
||||
pageLayoutWidgetEntityWithoutRelations.universalIdentifier ??
|
||||
pageLayoutWidgetEntityWithoutRelations.id,
|
||||
applicationId: pageLayoutWidgetEntityWithoutRelations.applicationId ?? null,
|
||||
};
|
||||
};
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
|
||||
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
|
||||
import {
|
||||
PageLayoutWidgetException,
|
||||
PageLayoutWidgetExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
export type UpdatePageLayoutWidgetInputWithId = {
|
||||
id: string;
|
||||
update: UpdatePageLayoutWidgetInput;
|
||||
};
|
||||
|
||||
export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThrow =
|
||||
({
|
||||
updatePageLayoutWidgetInput: rawUpdatePageLayoutWidgetInput,
|
||||
flatPageLayoutWidgetMaps,
|
||||
}: {
|
||||
updatePageLayoutWidgetInput: UpdatePageLayoutWidgetInputWithId;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}): FlatPageLayoutWidget => {
|
||||
const { id: pageLayoutWidgetToUpdateId } =
|
||||
extractAndSanitizeObjectStringFields(rawUpdatePageLayoutWidgetInput, [
|
||||
'id',
|
||||
]);
|
||||
|
||||
const existingFlatPageLayoutWidgetToUpdate =
|
||||
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetToUpdateId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutWidgetToUpdate)) {
|
||||
throw new PageLayoutWidgetException(
|
||||
t`Page layout widget to update not found`,
|
||||
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdatePageLayoutWidgetInput.update,
|
||||
FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPageLayoutWidgetToUpdate,
|
||||
properties: FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user