Migrate page layout services (#16443)
Last step of the page layout migration: - Migrate services - Write integration tests
This commit is contained in:
+41
@@ -0,0 +1,41 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
|
||||
export type FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs = {
|
||||
createPageLayoutInput: CreatePageLayoutInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
|
||||
createPageLayoutInput: rawCreatePageLayoutInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs): FlatPageLayout => {
|
||||
const createPageLayoutInput =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreatePageLayoutInput,
|
||||
['name'],
|
||||
);
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const pageLayoutId = v4();
|
||||
|
||||
return {
|
||||
id: pageLayoutId,
|
||||
name: createPageLayoutInput.name,
|
||||
type: createPageLayoutInput.type ?? PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: createPageLayoutInput.objectMetadataId ?? null,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: pageLayoutId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
tabIds: [],
|
||||
};
|
||||
};
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import {
|
||||
PageLayoutException,
|
||||
PageLayoutExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
|
||||
|
||||
export type DeletePageLayoutInput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const fromDeletePageLayoutInputToFlatPageLayoutOrThrow = ({
|
||||
deletePageLayoutInput: rawDeletePageLayoutInput,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
deletePageLayoutInput: DeletePageLayoutInput;
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
}): FlatPageLayout => {
|
||||
const { id: pageLayoutId } = extractAndSanitizeObjectStringFields(
|
||||
rawDeletePageLayoutInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutToDelete = flatPageLayoutMaps.byId[pageLayoutId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutToDelete)) {
|
||||
throw new PageLayoutException(
|
||||
t`Page layout to delete not found`,
|
||||
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatPageLayoutToDelete,
|
||||
deletedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import {
|
||||
PageLayoutException,
|
||||
PageLayoutExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
|
||||
|
||||
export type DestroyPageLayoutInput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const fromDestroyPageLayoutInputToFlatPageLayoutOrThrow = ({
|
||||
destroyPageLayoutInput,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
destroyPageLayoutInput: DestroyPageLayoutInput;
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
}): FlatPageLayout => {
|
||||
const { id: pageLayoutId } = extractAndSanitizeObjectStringFields(
|
||||
destroyPageLayoutInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutToDestroy = flatPageLayoutMaps.byId[pageLayoutId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutToDestroy)) {
|
||||
throw new PageLayoutException(
|
||||
t`Page layout to destroy not found`,
|
||||
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return existingFlatPageLayoutToDestroy;
|
||||
};
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import {
|
||||
PageLayoutException,
|
||||
PageLayoutExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
|
||||
|
||||
export type RestorePageLayoutInput = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const fromRestorePageLayoutInputToFlatPageLayoutOrThrow = ({
|
||||
restorePageLayoutInput,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
restorePageLayoutInput: RestorePageLayoutInput;
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
}): FlatPageLayout => {
|
||||
const { id: pageLayoutId } = extractAndSanitizeObjectStringFields(
|
||||
restorePageLayoutInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutToRestore = flatPageLayoutMaps.byId[pageLayoutId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutToRestore)) {
|
||||
throw new PageLayoutException(
|
||||
t`Page layout to restore not found`,
|
||||
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutToRestore.deletedAt)) {
|
||||
throw new PageLayoutException(
|
||||
t`Page layout is not deleted and cannot be restored`,
|
||||
PageLayoutExceptionCode.INVALID_PAGE_LAYOUT_DATA,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...existingFlatPageLayoutToRestore,
|
||||
deletedAt: null,
|
||||
};
|
||||
};
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import {
|
||||
extractAndSanitizeObjectStringFields,
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type UpdatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout.input';
|
||||
import {
|
||||
PageLayoutException,
|
||||
PageLayoutExceptionCode,
|
||||
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
export type UpdatePageLayoutInputWithId = {
|
||||
id: string;
|
||||
update: UpdatePageLayoutInput;
|
||||
};
|
||||
|
||||
export const fromUpdatePageLayoutInputToFlatPageLayoutToUpdateOrThrow = ({
|
||||
updatePageLayoutInput: rawUpdatePageLayoutInput,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
updatePageLayoutInput: UpdatePageLayoutInputWithId;
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
}): FlatPageLayout => {
|
||||
const { id: pageLayoutToUpdateId } = extractAndSanitizeObjectStringFields(
|
||||
rawUpdatePageLayoutInput,
|
||||
['id'],
|
||||
);
|
||||
|
||||
const existingFlatPageLayoutToUpdate =
|
||||
flatPageLayoutMaps.byId[pageLayoutToUpdateId];
|
||||
|
||||
if (!isDefined(existingFlatPageLayoutToUpdate)) {
|
||||
throw new PageLayoutException(
|
||||
t`Page layout to update not found`,
|
||||
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdatePageLayoutInput.update,
|
||||
FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPageLayoutToUpdate,
|
||||
properties: FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
};
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
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 FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
|
||||
export type FlatPageLayoutTabWithWidgets = FlatPageLayoutTab & {
|
||||
widgets: FlatPageLayoutWidget[];
|
||||
};
|
||||
|
||||
export type FlatPageLayoutWithTabsAndWidgets = FlatPageLayout & {
|
||||
tabs: FlatPageLayoutTabWithWidgets[];
|
||||
};
|
||||
|
||||
export const reconstructFlatPageLayoutWithTabsAndWidgets = ({
|
||||
layout,
|
||||
flatPageLayoutTabMaps,
|
||||
flatPageLayoutWidgetMaps,
|
||||
}: {
|
||||
layout: FlatPageLayout;
|
||||
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}): FlatPageLayoutWithTabsAndWidgets => {
|
||||
const tabs = Object.values(flatPageLayoutTabMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(tab) => tab.pageLayoutId === layout.id && !isDefined(tab.deletedAt),
|
||||
)
|
||||
.sort((a, b) => (a.position ?? 0) - (b.position ?? 0));
|
||||
|
||||
const tabsWithWidgets: FlatPageLayoutTabWithWidgets[] = tabs.map((tab) => {
|
||||
const widgets = Object.values(flatPageLayoutWidgetMaps.byId)
|
||||
.filter(isDefined)
|
||||
.filter(
|
||||
(widget) =>
|
||||
widget.pageLayoutTabId === tab.id && !isDefined(widget.deletedAt),
|
||||
);
|
||||
|
||||
return {
|
||||
...tab,
|
||||
widgets,
|
||||
widgetIds: widgets.map((widget) => widget.id),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
...layout,
|
||||
tabs: tabsWithWidgets,
|
||||
tabIds: tabsWithWidgets.map((tab) => tab.id),
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user