Migrate page layout widget to v2 of the API (#16323)

This commit is contained in:
Raphaël Bosi
2025-12-05 14:04:06 +01:00
committed by GitHub
parent 56e66315cd
commit 077be7644c
159 changed files with 1760 additions and 308 deletions
@@ -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,
};
};
@@ -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(),
};
};
@@ -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;
};
@@ -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,
};
};
@@ -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,
});
};