[BREAKING_CHANGE_DASHBOARDS][DASHBOARD_CACHE_FLUSH_REQUIRED] Refactor page layout widget configuration type (#16671)

# Introduction
In this pull-request we're refactoring the page layout widget
configuration entity to be containing its discriminated key simplifying
underlying code and maintainability
- Made the configuration and title non nullable
- Introduced a generic predicate for the `widgetConfigurationType`
- Upgraded command to remove `graphType` and insert new
`configurationType` to existing entries
- Migrated frontend to new type system

---------

Co-authored-by: bosiraphael <raphael.bosi@gmail.com>
Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This commit is contained in:
Paul Rastoin
2025-12-29 15:46:59 +01:00
committed by GitHub
parent 2b9728230a
commit 4135a6473a
221 changed files with 3241 additions and 1947 deletions
@@ -4,12 +4,14 @@ import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layou
export const fromFlatPageLayoutWidgetToPageLayoutWidgetDto = (
flatPageLayoutWidget: FlatPageLayoutWidget,
): PageLayoutWidgetDTO => {
const { createdAt, updatedAt, deletedAt, ...rest } = flatPageLayoutWidget;
const { createdAt, updatedAt, deletedAt, objectMetadataId, ...rest } =
flatPageLayoutWidget;
return {
...rest,
objectMetadataId: objectMetadataId ?? undefined,
createdAt: new Date(createdAt),
updatedAt: new Date(updatedAt),
deletedAt: deletedAt ? new Date(deletedAt) : null,
deletedAt: deletedAt ? new Date(deletedAt) : undefined,
};
};
@@ -1,39 +0,0 @@
import { type WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
type ConfigurationWithDiscriminator = WidgetConfigurationInterface & {
configurationType: WidgetConfigurationType;
};
export const injectWidgetConfigurationDiscriminator = (
widgetType: WidgetType,
configuration: WidgetConfigurationInterface | null,
): ConfigurationWithDiscriminator | null => {
if (!configuration) {
return null;
}
if (widgetType === WidgetType.IFRAME) {
return {
...configuration,
configurationType: WidgetConfigurationType.IFRAME_CONFIG,
} satisfies ConfigurationWithDiscriminator;
}
if (widgetType === WidgetType.GRAPH && 'graphType' in configuration) {
return {
...configuration,
configurationType: WidgetConfigurationType.CHART_CONFIG,
} satisfies ConfigurationWithDiscriminator;
}
if (widgetType === WidgetType.STANDALONE_RICH_TEXT) {
return {
...configuration,
configurationType: WidgetConfigurationType.STANDALONE_RICH_TEXT_CONFIG,
} satisfies ConfigurationWithDiscriminator;
}
return configuration as ConfigurationWithDiscriminator;
};
@@ -10,10 +10,10 @@ import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
import { StandaloneRichTextConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/standalone-rich-text-configuration.dto';
import { type WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
import { BarChartGroupMode } from 'src/engine/metadata-modules/page-layout-widget/enums/bar-chart-group-mode.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
import { type AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
const formatValidationErrors = (errors: ValidationError[]): string => {
return errors
@@ -33,22 +33,24 @@ const validateGraphConfiguration = ({
}: {
configuration: Record<string, unknown>;
isDashboardV2Enabled: boolean;
}): WidgetConfigurationInterface | null => {
const graphType = configuration.graphType as GraphType;
}): AllPageLayoutWidgetConfiguration | null => {
const configurationType = configuration.configurationType as GraphType;
if (!graphType || !Object.values(GraphType).includes(graphType)) {
if (
!configurationType ||
!Object.values(GraphType).includes(configurationType)
) {
return null;
}
if (graphType === GraphType.GAUGE && !isDashboardV2Enabled) {
if (configurationType === GraphType.GAUGE_CHART && !isDashboardV2Enabled) {
throw new Error(
`Chart type ${graphType} requires IS_DASHBOARD_V2_ENABLED feature flag`,
`Chart type ${configurationType} requires IS_DASHBOARD_V2_ENABLED feature flag`,
);
}
switch (graphType) {
case GraphType.VERTICAL_BAR:
case GraphType.HORIZONTAL_BAR: {
switch (configurationType) {
case GraphType.BAR_CHART: {
const instance = plainToInstance(BarChartConfigurationDTO, configuration);
const errors = validateSync(instance, {
@@ -69,7 +71,7 @@ const validateGraphConfiguration = ({
return instance;
}
case GraphType.LINE: {
case GraphType.LINE_CHART: {
const instance = plainToInstance(
LineChartConfigurationDTO,
configuration,
@@ -93,7 +95,7 @@ const validateGraphConfiguration = ({
return instance;
}
case GraphType.PIE: {
case GraphType.PIE_CHART: {
const instance = plainToInstance(PieChartConfigurationDTO, configuration);
const errors = validateSync(instance, {
@@ -107,7 +109,7 @@ const validateGraphConfiguration = ({
return instance;
}
case GraphType.AGGREGATE: {
case GraphType.AGGREGATE_CHART: {
const instance = plainToInstance(
AggregateChartConfigurationDTO,
configuration,
@@ -124,7 +126,7 @@ const validateGraphConfiguration = ({
return instance;
}
case GraphType.GAUGE: {
case GraphType.GAUGE_CHART: {
const instance = plainToInstance(
GaugeChartConfigurationDTO,
configuration,
@@ -148,7 +150,7 @@ const validateGraphConfiguration = ({
const validateIframeConfiguration = (
configuration: unknown,
): WidgetConfigurationInterface | null => {
): AllPageLayoutWidgetConfiguration | null => {
const instance = plainToInstance(IframeConfigurationDTO, configuration);
const errors = validateSync(instance, {
@@ -165,7 +167,7 @@ const validateIframeConfiguration = (
const validateStandaloneRichTextConfiguration = async (
configuration: unknown,
): Promise<WidgetConfigurationInterface | null> => {
): Promise<AllPageLayoutWidgetConfiguration | null> => {
const instance = plainToInstance(
StandaloneRichTextConfigurationDTO,
configuration,
@@ -195,7 +197,7 @@ export const validateAndTransformWidgetConfiguration = async ({
type: WidgetType;
configuration: unknown;
isDashboardV2Enabled: boolean;
}): Promise<WidgetConfigurationInterface | null> => {
}): Promise<AllPageLayoutWidgetConfiguration | null> => {
if (!configuration || typeof configuration !== 'object') {
throw new Error('Invalid configuration: not an object');
}