Baptiste Devessier
2026-02-17 14:46:19 +01:00
committed by GitHub
parent 5750c9be0c
commit 347298902d
3 changed files with 259 additions and 1 deletions
@@ -7,6 +7,7 @@ import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
@@ -123,11 +124,20 @@ export class PageLayoutUpdateService {
},
);
const optimisticFlatPageLayoutTabMaps = tabsToCreate.reduce(
(maps, tab) =>
addFlatEntityToFlatEntityMapsOrThrow({
flatEntity: tab,
flatEntityMaps: maps,
}),
flatPageLayoutTabMaps,
);
const { widgetsToCreate, widgetsToUpdate, widgetsToDelete } =
this.computeWidgetOperationsForAllTabs({
tabs,
flatPageLayoutWidgetMaps,
flatPageLayoutTabMaps,
flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps,
flatObjectMetadataMaps,
workspaceId,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
@@ -0,0 +1,91 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`Page layout with tabs creation via update should succeed should create a new tab with a widget via page layout update 1`] = `
{
"createdAt": Any<String>,
"deletedAt": null,
"id": Any<String>,
"name": "Layout With New Tab",
"objectMetadataId": null,
"tabs": [
{
"createdAt": Any<String>,
"deletedAt": null,
"id": Any<String>,
"pageLayoutId": Any<String>,
"position": 0,
"title": "Existing Tab",
"updatedAt": Any<String>,
"widgets": [
{
"configuration": {
"aggregateFieldMetadataId": Any<String>,
"aggregateOperation": "COUNT",
"color": null,
"configurationType": "PIE_CHART",
"dateGranularity": "DAY",
"description": null,
"displayDataLabel": false,
"displayLegend": true,
"filter": null,
"firstDayOfTheWeek": 1,
"groupByFieldMetadataId": Any<String>,
"groupBySubFieldName": null,
"manualSortOrder": null,
"orderBy": "VALUE_DESC",
"showCenterMetric": true,
"timezone": "UTC",
},
"createdAt": Any<String>,
"deletedAt": null,
"gridPosition": {
"column": 0,
"columnSpan": 1,
"row": 0,
"rowSpan": 1,
},
"id": Any<String>,
"objectMetadataId": Any<String>,
"pageLayoutTabId": Any<String>,
"title": "Existing Tab Widget",
"type": "GRAPH",
"updatedAt": Any<String>,
},
],
},
{
"createdAt": Any<String>,
"deletedAt": null,
"id": Any<String>,
"pageLayoutId": Any<String>,
"position": 1,
"title": "New Tab Created Via Update",
"updatedAt": Any<String>,
"widgets": [
{
"configuration": {
"configurationType": "IFRAME",
"url": "https://example.com",
},
"createdAt": Any<String>,
"deletedAt": null,
"gridPosition": {
"column": 0,
"columnSpan": 1,
"row": 0,
"rowSpan": 1,
},
"id": Any<String>,
"objectMetadataId": null,
"pageLayoutTabId": Any<String>,
"title": "New Tab Iframe Widget",
"type": "IFRAME",
"updatedAt": Any<String>,
},
],
},
],
"type": "RECORD_PAGE",
"updatedAt": Any<String>,
}
`;
@@ -0,0 +1,157 @@
import { createOnePageLayoutTab } from 'test/integration/metadata/suites/page-layout-tab/utils/create-one-page-layout-tab.util';
import { destroyOnePageLayoutTab } from 'test/integration/metadata/suites/page-layout-tab/utils/destroy-one-page-layout-tab.util';
import { fetchTestFieldMetadataIds } from 'test/integration/metadata/suites/page-layout-widget/utils/fetch-test-field-metadata-ids.util';
import { createOnePageLayout } from 'test/integration/metadata/suites/page-layout/utils/create-one-page-layout.util';
import { destroyOnePageLayout } from 'test/integration/metadata/suites/page-layout/utils/destroy-one-page-layout.util';
import { updateOnePageLayoutWithTabsAndWidgets } from 'test/integration/metadata/suites/page-layout/utils/update-one-page-layout-with-tabs-and-widgets.util';
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
import { v4 } from 'uuid';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
describe('Page layout with tabs creation via update should succeed', () => {
let testFieldMetadataIds: {
objectMetadataId: string;
fieldMetadataId1: string;
fieldMetadataId2: string;
};
let testPageLayoutId: string;
let existingTabId: string;
let newTabId: string;
beforeAll(async () => {
const allFieldMetadataIds = await fetchTestFieldMetadataIds();
testFieldMetadataIds = {
objectMetadataId: allFieldMetadataIds.objectMetadataId,
fieldMetadataId1: allFieldMetadataIds.fieldMetadataId1,
fieldMetadataId2: allFieldMetadataIds.fieldMetadataId2,
};
const { data: layoutData } = await createOnePageLayout({
expectToFail: false,
input: {
name: 'Test Page Layout',
type: PageLayoutType.RECORD_PAGE,
},
});
testPageLayoutId = layoutData.createPageLayout.id;
const { data: tabData } = await createOnePageLayoutTab({
expectToFail: false,
input: {
title: 'Initial Tab',
pageLayoutId: testPageLayoutId,
},
});
existingTabId = tabData.createPageLayoutTab.id;
});
afterAll(async () => {
if (newTabId) {
await destroyOnePageLayoutTab({
expectToFail: null,
input: { id: newTabId },
});
}
await destroyOnePageLayoutTab({
expectToFail: false,
input: { id: existingTabId },
});
await destroyOnePageLayout({
expectToFail: false,
input: { id: testPageLayoutId },
});
});
it('should create a new tab with a widget via page layout update', async () => {
const existingTabWidgetId = v4();
newTabId = v4();
const newTabWidgetId = v4();
const { data } = await updateOnePageLayoutWithTabsAndWidgets({
expectToFail: false,
input: {
id: testPageLayoutId,
name: 'Layout With New Tab',
type: PageLayoutType.RECORD_PAGE,
objectMetadataId: null,
tabs: [
{
id: existingTabId,
title: 'Existing Tab',
position: 0,
widgets: [
{
id: existingTabWidgetId,
pageLayoutTabId: existingTabId,
title: 'Existing Tab Widget',
type: WidgetType.GRAPH,
objectMetadataId: testFieldMetadataIds.objectMetadataId,
gridPosition: {
row: 0,
column: 0,
rowSpan: 1,
columnSpan: 1,
},
configuration: {
configurationType: WidgetConfigurationType.PIE_CHART,
aggregateFieldMetadataId:
testFieldMetadataIds.fieldMetadataId1,
aggregateOperation: AggregateOperations.COUNT,
groupByFieldMetadataId: testFieldMetadataIds.fieldMetadataId2,
},
},
],
},
{
id: newTabId,
title: 'New Tab Created Via Update',
position: 1,
widgets: [
{
id: newTabWidgetId,
pageLayoutTabId: newTabId,
title: 'New Tab Iframe Widget',
type: WidgetType.IFRAME,
objectMetadataId: null,
gridPosition: {
row: 0,
column: 0,
rowSpan: 1,
columnSpan: 1,
},
configuration: {
configurationType: WidgetConfigurationType.IFRAME,
url: 'https://example.com',
},
},
],
},
],
},
});
const result = data.updatePageLayoutWithTabsAndWidgets;
expect(result.tabs).toHaveLength(2);
for (const tab of result.tabs!) {
expect(tab.widgets!.length).toBeGreaterThanOrEqual(1);
}
expect(result).toMatchSnapshot(
extractRecordIdsAndDatesAsExpectAny({
...result,
}),
);
});
});