[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:
+1
-1
@@ -38,7 +38,7 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
type: createPageLayoutWidgetInput.type ?? WidgetType.VIEW,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
|
||||
gridPosition: createPageLayoutWidgetInput.gridPosition,
|
||||
configuration: createPageLayoutWidgetInput.configuration ?? null,
|
||||
configuration: createPageLayoutWidgetInput.configuration,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/aggregate-chart-configuration.dto';
|
||||
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
|
||||
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
|
||||
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/iframe-configuration.dto';
|
||||
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 { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { type PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
export const ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE =
|
||||
{
|
||||
[WidgetConfigurationType.AGGREGATE_CHART]: AggregateChartConfigurationDTO,
|
||||
[WidgetConfigurationType.BAR_CHART]: BarChartConfigurationDTO,
|
||||
[WidgetConfigurationType.GAUGE_CHART]: GaugeChartConfigurationDTO,
|
||||
[WidgetConfigurationType.IFRAME]: IframeConfigurationDTO,
|
||||
[WidgetConfigurationType.LINE_CHART]: LineChartConfigurationDTO,
|
||||
[WidgetConfigurationType.PIE_CHART]: PieChartConfigurationDTO,
|
||||
[WidgetConfigurationType.STANDALONE_RICH_TEXT]:
|
||||
StandaloneRichTextConfigurationDTO,
|
||||
// TODO: Remove the partial when we have all the widget configuration types in the backend
|
||||
} as const satisfies Partial<{
|
||||
[P in WidgetConfigurationType]: new () => PageLayoutWidgetConfigurationBase;
|
||||
}>;
|
||||
+9
-5
@@ -4,6 +4,7 @@ import { Type } from 'class-transformer';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
@@ -22,14 +23,17 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { RatioAggregateConfigDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/ratio-aggregate-config.dto';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('AggregateChartConfiguration')
|
||||
export class AggregateChartConfigurationDTO {
|
||||
@Field(() => GraphType)
|
||||
@IsEnum(GraphType)
|
||||
export class AggregateChartConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.AGGREGATE_CHART])
|
||||
@IsNotEmpty()
|
||||
graphType: GraphType.AGGREGATE;
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
|
||||
+14
-5
@@ -23,16 +23,20 @@ import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout-widget/enums/axis-name-display.enum';
|
||||
import { BarChartGroupMode } from 'src/engine/metadata-modules/page-layout-widget/enums/bar-chart-group-mode.enum';
|
||||
import { BarChartLayout } from 'src/engine/metadata-modules/page-layout-widget/enums/bar-chart-layout.enum';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout-widget/enums/date-granularity.enum';
|
||||
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('BarChartConfiguration')
|
||||
export class BarChartConfigurationDTO {
|
||||
@Field(() => GraphType)
|
||||
@IsIn([GraphType.VERTICAL_BAR, GraphType.HORIZONTAL_BAR])
|
||||
export class BarChartConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.BAR_CHART])
|
||||
@IsNotEmpty()
|
||||
graphType: GraphType.VERTICAL_BAR | GraphType.HORIZONTAL_BAR;
|
||||
configurationType: WidgetConfigurationType.BAR_CHART;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
@@ -145,6 +149,11 @@ export class BarChartConfigurationDTO {
|
||||
@IsOptional()
|
||||
groupMode?: BarChartGroupMode;
|
||||
|
||||
@Field(() => BarChartLayout)
|
||||
@IsEnum(BarChartLayout)
|
||||
@IsNotEmpty()
|
||||
layout: BarChartLayout;
|
||||
|
||||
@Field(() => Boolean, {
|
||||
nullable: true,
|
||||
})
|
||||
|
||||
+9
-5
@@ -3,6 +3,7 @@ import { Field, Int, ObjectType } from '@nestjs/graphql';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
@@ -19,14 +20,17 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('GaugeChartConfiguration')
|
||||
export class GaugeChartConfigurationDTO {
|
||||
@Field(() => GraphType)
|
||||
@IsEnum(GraphType)
|
||||
export class GaugeChartConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.GAUGE_CHART])
|
||||
@IsNotEmpty()
|
||||
graphType: GraphType.GAUGE;
|
||||
configurationType: WidgetConfigurationType.GAUGE_CHART;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
|
||||
+12
-2
@@ -1,9 +1,19 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsOptional, IsString, IsUrl } from 'class-validator';
|
||||
import { IsIn, IsNotEmpty, IsOptional, IsString, IsUrl } from 'class-validator';
|
||||
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('IframeConfiguration')
|
||||
export class IframeConfigurationDTO {
|
||||
export class IframeConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.IFRAME])
|
||||
@IsNotEmpty()
|
||||
configurationType: WidgetConfigurationType.IFRAME;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
|
||||
+5
-4
@@ -15,6 +15,7 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/grid-position.input';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
|
||||
@InputType()
|
||||
export class CreatePageLayoutWidgetInput {
|
||||
@@ -28,10 +29,10 @@ export class CreatePageLayoutWidgetInput {
|
||||
@IsNotEmpty()
|
||||
title: string;
|
||||
|
||||
@Field(() => WidgetType, { nullable: true, defaultValue: WidgetType.VIEW })
|
||||
@Field(() => WidgetType, { nullable: false })
|
||||
@IsEnum(WidgetType)
|
||||
@IsOptional()
|
||||
type?: WidgetType;
|
||||
type: WidgetType;
|
||||
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
@IsUUID()
|
||||
@@ -43,8 +44,8 @@ export class CreatePageLayoutWidgetInput {
|
||||
@Type(() => GridPositionInput)
|
||||
gridPosition: GridPositionInput;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
@Field(() => GraphQLJSON, { nullable: false })
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
configuration?: Record<string, unknown> | null;
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/grid-position.input';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
|
||||
@InputType()
|
||||
export class UpdatePageLayoutWidgetWithIdInput {
|
||||
@@ -52,5 +53,5 @@ export class UpdatePageLayoutWidgetWithIdInput {
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
configuration: Record<string, unknown> | null;
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
}
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@ import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/grid-position.input';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
|
||||
@InputType()
|
||||
export class UpdatePageLayoutWidgetInput {
|
||||
@@ -41,5 +42,5 @@ export class UpdatePageLayoutWidgetInput {
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
configuration?: Record<string, unknown> | null;
|
||||
configuration?: AllPageLayoutWidgetConfiguration;
|
||||
}
|
||||
|
||||
+9
-5
@@ -3,6 +3,7 @@ import { Field, Int, ObjectType } from '@nestjs/graphql';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsObject,
|
||||
@@ -23,14 +24,17 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/
|
||||
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout-widget/enums/axis-name-display.enum';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout-widget/enums/date-granularity.enum';
|
||||
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('LineChartConfiguration')
|
||||
export class LineChartConfigurationDTO {
|
||||
@Field(() => GraphType)
|
||||
@IsEnum(GraphType)
|
||||
export class LineChartConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.LINE_CHART])
|
||||
@IsNotEmpty()
|
||||
graphType: GraphType.LINE;
|
||||
configurationType: WidgetConfigurationType.LINE_CHART;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
|
||||
+6
-8
@@ -3,11 +3,9 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import {
|
||||
WidgetConfiguration,
|
||||
WidgetConfigurationInterface,
|
||||
} from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
|
||||
registerEnumType(WidgetType, { name: 'WidgetType' });
|
||||
|
||||
@@ -41,13 +39,13 @@ export class PageLayoutWidgetDTO {
|
||||
type: WidgetType;
|
||||
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
objectMetadataId: string | null;
|
||||
objectMetadataId?: string;
|
||||
|
||||
@Field(() => GridPositionDTO, { nullable: false })
|
||||
gridPosition: GridPositionDTO;
|
||||
|
||||
@Field(() => WidgetConfiguration, { nullable: true })
|
||||
configuration: WidgetConfigurationInterface | null;
|
||||
@Field(() => WidgetConfiguration, { nullable: false })
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
|
||||
@Field()
|
||||
createdAt: Date;
|
||||
@@ -56,5 +54,5 @@ export class PageLayoutWidgetDTO {
|
||||
updatedAt: Date;
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date | null;
|
||||
deletedAt?: Date;
|
||||
}
|
||||
|
||||
+9
-5
@@ -3,6 +3,7 @@ import { Field, Int, ObjectType } from '@nestjs/graphql';
|
||||
import {
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
@@ -21,14 +22,17 @@ import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout-widget/enums/date-granularity.enum';
|
||||
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-order-by.enum';
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('PieChartConfiguration')
|
||||
export class PieChartConfigurationDTO {
|
||||
@Field(() => GraphType)
|
||||
@IsEnum(GraphType)
|
||||
export class PieChartConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.PIE_CHART])
|
||||
@IsNotEmpty()
|
||||
graphType: GraphType.PIE;
|
||||
configurationType: WidgetConfigurationType.PIE_CHART;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
|
||||
+1
-2
@@ -1,11 +1,10 @@
|
||||
import { Field, InputType, ObjectType } from '@nestjs/graphql';
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsString, IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
|
||||
@ObjectType('RatioAggregateConfig')
|
||||
@InputType('RatioAggregateConfigInput')
|
||||
export class RatioAggregateConfigDTO {
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsUUID()
|
||||
|
||||
+11
-2
@@ -1,12 +1,21 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsNotEmpty, ValidateNested } from 'class-validator';
|
||||
import { IsIn, IsNotEmpty, ValidateNested } from 'class-validator';
|
||||
|
||||
import { RichTextV2BodyDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/rich-text-v2-body.dto';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetConfigurationBase } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configurationt-base.type';
|
||||
|
||||
@ObjectType('StandaloneRichTextConfiguration')
|
||||
export class StandaloneRichTextConfigurationDTO {
|
||||
export class StandaloneRichTextConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.STANDALONE_RICH_TEXT])
|
||||
@IsNotEmpty()
|
||||
configurationType: WidgetConfigurationType.STANDALONE_RICH_TEXT;
|
||||
|
||||
@Field(() => RichTextV2BodyDTO)
|
||||
@ValidateNested()
|
||||
@Type(() => RichTextV2BodyDTO)
|
||||
|
||||
+10
-70
@@ -1,77 +1,17 @@
|
||||
import { createUnionType } from '@nestjs/graphql';
|
||||
|
||||
import { AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/aggregate-chart-configuration.dto';
|
||||
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
|
||||
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
|
||||
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/iframe-configuration.dto';
|
||||
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 { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.enum';
|
||||
import { ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE } from 'src/engine/metadata-modules/page-layout-widget/constants/all-widget-configuration-type-validator-by-widget-configuration-type.constant';
|
||||
import { type AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
|
||||
export const WidgetConfiguration = createUnionType({
|
||||
name: 'WidgetConfiguration',
|
||||
types: () => [
|
||||
BarChartConfigurationDTO,
|
||||
LineChartConfigurationDTO,
|
||||
PieChartConfigurationDTO,
|
||||
AggregateChartConfigurationDTO,
|
||||
GaugeChartConfigurationDTO,
|
||||
IframeConfigurationDTO,
|
||||
StandaloneRichTextConfigurationDTO,
|
||||
],
|
||||
resolveType(configuration: Record<string, unknown>) {
|
||||
if (!('configurationType' in configuration)) {
|
||||
throw new Error(
|
||||
'Widget configuration missing configurationType discriminator. This indicates a validation bug or data corruption.',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
configuration.configurationType === WidgetConfigurationType.CHART_CONFIG
|
||||
) {
|
||||
switch (configuration.graphType) {
|
||||
case GraphType.VERTICAL_BAR:
|
||||
case GraphType.HORIZONTAL_BAR:
|
||||
return BarChartConfigurationDTO;
|
||||
case GraphType.LINE:
|
||||
return LineChartConfigurationDTO;
|
||||
case GraphType.PIE:
|
||||
return PieChartConfigurationDTO;
|
||||
case GraphType.AGGREGATE:
|
||||
return AggregateChartConfigurationDTO;
|
||||
case GraphType.GAUGE:
|
||||
return GaugeChartConfigurationDTO;
|
||||
default:
|
||||
throw new Error(`Unknown graph type: ${configuration.graphType}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
configuration.configurationType === WidgetConfigurationType.IFRAME_CONFIG
|
||||
) {
|
||||
return IframeConfigurationDTO;
|
||||
}
|
||||
|
||||
if (
|
||||
configuration.configurationType ===
|
||||
WidgetConfigurationType.STANDALONE_RICH_TEXT_CONFIG
|
||||
) {
|
||||
return StandaloneRichTextConfigurationDTO;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`Unknown widget configuration type: ${configuration.configurationType}`,
|
||||
);
|
||||
types: () =>
|
||||
Object.values(
|
||||
ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE,
|
||||
),
|
||||
resolveType({ configurationType }: AllPageLayoutWidgetConfiguration) {
|
||||
return ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE[
|
||||
configurationType
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
export type WidgetConfigurationInterface =
|
||||
| BarChartConfigurationDTO
|
||||
| LineChartConfigurationDTO
|
||||
| PieChartConfigurationDTO
|
||||
| AggregateChartConfigurationDTO
|
||||
| GaugeChartConfigurationDTO
|
||||
| IframeConfigurationDTO
|
||||
| StandaloneRichTextConfigurationDTO;
|
||||
|
||||
+3
-3
@@ -18,8 +18,8 @@ import { SyncableEntity } from 'src/engine/workspace-manager/workspace-sync/inte
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
|
||||
import { WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
import { GridPosition } from 'src/engine/metadata-modules/page-layout-widget/types/grid-position.type';
|
||||
|
||||
@Entity({ name: 'pageLayoutWidget', schema: 'core' })
|
||||
@@ -78,8 +78,8 @@ export class PageLayoutWidgetEntity
|
||||
@Column({ type: 'jsonb', nullable: false })
|
||||
gridPosition: GridPosition;
|
||||
|
||||
@Column({ type: 'jsonb', nullable: true })
|
||||
configuration: WidgetConfigurationInterface | null;
|
||||
@Column({ type: 'jsonb', nullable: false })
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
export enum BarChartLayout {
|
||||
VERTICAL = 'VERTICAL',
|
||||
HORIZONTAL = 'HORIZONTAL',
|
||||
}
|
||||
|
||||
registerEnumType(BarChartLayout, {
|
||||
name: 'BarChartLayout',
|
||||
description: 'Layout orientation for bar charts',
|
||||
});
|
||||
+5
-6
@@ -1,12 +1,11 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
export enum GraphType {
|
||||
AGGREGATE = 'AGGREGATE',
|
||||
GAUGE = 'GAUGE',
|
||||
PIE = 'PIE',
|
||||
VERTICAL_BAR = 'VERTICAL_BAR',
|
||||
HORIZONTAL_BAR = 'HORIZONTAL_BAR',
|
||||
LINE = 'LINE',
|
||||
AGGREGATE_CHART = 'AGGREGATE_CHART',
|
||||
GAUGE_CHART = 'GAUGE_CHART',
|
||||
PIE_CHART = 'PIE_CHART',
|
||||
BAR_CHART = 'BAR_CHART',
|
||||
LINE_CHART = 'LINE_CHART',
|
||||
}
|
||||
|
||||
registerEnumType(GraphType, {
|
||||
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
export enum WidgetConfigurationType {
|
||||
CHART_CONFIG = 'CHART_CONFIG',
|
||||
IFRAME_CONFIG = 'IFRAME_CONFIG',
|
||||
STANDALONE_RICH_TEXT_CONFIG = 'STANDALONE_RICH_TEXT_CONFIG',
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { type Expect } from 'twenty-shared/testing';
|
||||
|
||||
import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/graph-type.enum';
|
||||
|
||||
export enum WidgetConfigurationType {
|
||||
AGGREGATE_CHART = GraphType.AGGREGATE_CHART,
|
||||
GAUGE_CHART = GraphType.GAUGE_CHART,
|
||||
PIE_CHART = GraphType.PIE_CHART,
|
||||
BAR_CHART = GraphType.BAR_CHART,
|
||||
LINE_CHART = GraphType.LINE_CHART,
|
||||
IFRAME = 'IFRAME',
|
||||
STANDALONE_RICH_TEXT = 'STANDALONE_RICH_TEXT',
|
||||
VIEW = 'VIEW',
|
||||
FIELD = 'FIELD',
|
||||
FIELDS = 'FIELDS',
|
||||
TIMELINE = 'TIMELINE',
|
||||
TASKS = 'TASKS',
|
||||
NOTES = 'NOTES',
|
||||
FILES = 'FILES',
|
||||
EMAILS = 'EMAILS',
|
||||
CALENDAR = 'CALENDAR',
|
||||
FIELD_RICH_TEXT = 'FIELD_RICH_TEXT',
|
||||
WORKFLOW = 'WORKFLOW',
|
||||
WORKFLOW_VERSION = 'WORKFLOW_VERSION',
|
||||
WORKFLOW_RUN = 'WORKFLOW_RUN',
|
||||
}
|
||||
|
||||
registerEnumType(WidgetConfigurationType, {
|
||||
name: 'WidgetConfigurationType',
|
||||
});
|
||||
|
||||
// eslint-disable-next-line unused-imports/no-unused-vars
|
||||
type Assertion = Expect<
|
||||
`${GraphType}` extends `${WidgetConfigurationType}` ? true : false
|
||||
>;
|
||||
+1
-5
@@ -26,7 +26,6 @@ import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-la
|
||||
import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service';
|
||||
import { injectWidgetConfigurationDiscriminator } from 'src/engine/metadata-modules/page-layout-widget/utils/inject-widget-configuration-discriminator.util';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
import { WorkspaceMigrationBuilderGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration-v2/interceptors/workspace-migration-builder-graphql-api-exception.interceptor';
|
||||
|
||||
@@ -109,9 +108,6 @@ export class PageLayoutWidgetResolver {
|
||||
|
||||
@ResolveField(() => WidgetConfiguration, { nullable: true })
|
||||
configuration(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return injectWidgetConfigurationDiscriminator(
|
||||
widget.type,
|
||||
widget.configuration,
|
||||
);
|
||||
return widget.configuration;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-25
@@ -20,7 +20,6 @@ import {
|
||||
import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input';
|
||||
import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/update-page-layout-widget.input';
|
||||
import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
import { WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import {
|
||||
PageLayoutWidgetException,
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
PageLayoutWidgetExceptionMessageKey,
|
||||
generatePageLayoutWidgetExceptionMessage,
|
||||
} from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
||||
import { AllPageLayoutWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/types/all-page-layout-widget-configuration.type';
|
||||
import { fromFlatPageLayoutWidgetToPageLayoutWidgetDto } from 'src/engine/metadata-modules/page-layout-widget/utils/from-flat-page-layout-widget-to-page-layout-widget-dto.util';
|
||||
import { validateAndTransformWidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-and-transform-widget-configuration.util';
|
||||
import { validateWidgetGridPosition } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-widget-grid-position.util';
|
||||
@@ -70,16 +70,16 @@ export class PageLayoutWidgetService {
|
||||
titleForError,
|
||||
}: {
|
||||
type: WidgetType;
|
||||
configuration: Record<string, unknown>;
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
workspaceId: string;
|
||||
titleForError: string;
|
||||
}): Promise<WidgetConfigurationInterface> {
|
||||
}): Promise<AllPageLayoutWidgetConfiguration> {
|
||||
const isDashboardV2Enabled = await this.featureFlagService.isFeatureEnabled(
|
||||
FeatureFlagKey.IS_DASHBOARD_V2_ENABLED,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
let validatedConfig: WidgetConfigurationInterface | null = null;
|
||||
let validatedConfig: AllPageLayoutWidgetConfiguration | null = null;
|
||||
|
||||
try {
|
||||
validatedConfig = await validateAndTransformWidgetConfiguration({
|
||||
@@ -210,9 +210,7 @@ export class PageLayoutWidgetService {
|
||||
fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate({
|
||||
createPageLayoutWidgetInput: {
|
||||
...createPageLayoutWidgetInput,
|
||||
...(validatedConfig && {
|
||||
configuration: validatedConfig as Record<string, unknown>,
|
||||
}),
|
||||
configuration: validatedConfig,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
@@ -271,12 +269,8 @@ export class PageLayoutWidgetService {
|
||||
private async getValidatedConfigurationForCreate(
|
||||
input: CreatePageLayoutWidgetInput,
|
||||
workspaceId: string,
|
||||
): Promise<WidgetConfigurationInterface | null> {
|
||||
if (!input.configuration || !input.type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.validateWidgetConfigurationOrThrow({
|
||||
): Promise<AllPageLayoutWidgetConfiguration> {
|
||||
return await this.validateWidgetConfigurationOrThrow({
|
||||
type: input.type,
|
||||
configuration: input.configuration,
|
||||
workspaceId,
|
||||
@@ -313,9 +307,11 @@ export class PageLayoutWidgetService {
|
||||
id,
|
||||
update: {
|
||||
...updateData,
|
||||
...(validatedConfig && {
|
||||
configuration: validatedConfig as Record<string, unknown>,
|
||||
}),
|
||||
...(isDefined(validatedConfig)
|
||||
? {
|
||||
configuration: validatedConfig,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -369,20 +365,15 @@ export class PageLayoutWidgetService {
|
||||
updateData: UpdatePageLayoutWidgetInput,
|
||||
existingWidget: FlatPageLayoutWidget,
|
||||
workspaceId: string,
|
||||
): Promise<WidgetConfigurationInterface | null> {
|
||||
if (!updateData.configuration) {
|
||||
return null;
|
||||
): Promise<AllPageLayoutWidgetConfiguration | undefined> {
|
||||
if (!isDefined(updateData.configuration)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const typeForValidation = updateData.type ?? existingWidget.type;
|
||||
|
||||
if (!typeForValidation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const titleForError = updateData.title ?? existingWidget.title;
|
||||
|
||||
return this.validateWidgetConfigurationOrThrow({
|
||||
return await this.validateWidgetConfigurationOrThrow({
|
||||
type: typeForValidation,
|
||||
configuration: updateData.configuration,
|
||||
workspaceId,
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE } from 'src/engine/metadata-modules/page-layout-widget/constants/all-widget-configuration-type-validator-by-widget-configuration-type.constant';
|
||||
|
||||
export type AllPageLayoutWidgetConfiguration = InstanceType<
|
||||
(typeof ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE)[keyof typeof ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYPE]
|
||||
>;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { type WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
|
||||
export type PageLayoutWidgetConfigurationBase = {
|
||||
configurationType: WidgetConfigurationType;
|
||||
};
|
||||
+4
-2
@@ -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,
|
||||
};
|
||||
};
|
||||
|
||||
-39
@@ -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;
|
||||
};
|
||||
+18
-16
@@ -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');
|
||||
}
|
||||
|
||||
+1
-4
@@ -272,10 +272,7 @@ export class PageLayoutDuplicationService {
|
||||
gridPosition: originalWidget.gridPosition,
|
||||
type: originalWidget.type,
|
||||
objectMetadataId: originalWidget.objectMetadataId,
|
||||
configuration: originalWidget.configuration as Record<
|
||||
string,
|
||||
unknown
|
||||
> | null,
|
||||
configuration: originalWidget.configuration,
|
||||
pageLayoutTabId: newTabId,
|
||||
},
|
||||
workspaceId,
|
||||
|
||||
+26
-17
@@ -6,8 +6,10 @@ import { v4 } from 'uuid';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
|
||||
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 { 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 FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
@@ -63,6 +65,7 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const existingPageLayout = flatPageLayoutMaps.byId[id];
|
||||
|
||||
// TODO move in validator
|
||||
if (
|
||||
!isDefined(existingPageLayout) ||
|
||||
isDefined(existingPageLayout.deletedAt)
|
||||
@@ -75,6 +78,7 @@ export class PageLayoutUpdateService {
|
||||
PageLayoutExceptionCode.PAGE_LAYOUT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
///
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
@@ -201,7 +205,7 @@ export class PageLayoutUpdateService {
|
||||
>({
|
||||
existingObjects: existingTabs,
|
||||
receivedObjects: tabs,
|
||||
propertiesToCompare: ['title', 'position'],
|
||||
propertiesToCompare: FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES,
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
@@ -228,10 +232,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const tabsToUpdate: FlatPageLayoutTab[] = entitiesToUpdate.map(
|
||||
(tabInput) => {
|
||||
const existingTab = flatPageLayoutTabMaps.byId[tabInput.id];
|
||||
const existingTab = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: tabInput.id,
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab!,
|
||||
...existingTab,
|
||||
title: tabInput.title,
|
||||
position: tabInput.position,
|
||||
updatedAt: now.toISOString(),
|
||||
@@ -241,10 +248,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const tabsToRestoreAndUpdate: FlatPageLayoutTab[] =
|
||||
entitiesToRestoreAndUpdate.map((tabInput) => {
|
||||
const existingTab = flatPageLayoutTabMaps.byId[tabInput.id];
|
||||
const existingTab = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: tabInput.id,
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingTab!,
|
||||
...existingTab,
|
||||
title: tabInput.title,
|
||||
position: tabInput.position,
|
||||
deletedAt: null,
|
||||
@@ -349,14 +359,7 @@ export class PageLayoutUpdateService {
|
||||
>({
|
||||
existingObjects: existingWidgets,
|
||||
receivedObjects: widgets,
|
||||
propertiesToCompare: [
|
||||
'pageLayoutTabId',
|
||||
'objectMetadataId',
|
||||
'title',
|
||||
'type',
|
||||
'gridPosition',
|
||||
'configuration',
|
||||
],
|
||||
propertiesToCompare: FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
@@ -385,10 +388,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const widgetsToUpdate: FlatPageLayoutWidget[] = entitiesToUpdate.map(
|
||||
(widgetInput) => {
|
||||
const existingWidget = flatPageLayoutWidgetMaps.byId[widgetInput.id];
|
||||
const existingWidget = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: widgetInput.id,
|
||||
flatEntityMaps: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget!,
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
@@ -402,10 +408,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const widgetsToRestoreAndUpdate: FlatPageLayoutWidget[] =
|
||||
entitiesToRestoreAndUpdate.map((widgetInput) => {
|
||||
const existingWidget = flatPageLayoutWidgetMaps.byId[widgetInput.id];
|
||||
const existingWidget = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: widgetInput.id,
|
||||
flatEntityMaps: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget!,
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
|
||||
Reference in New Issue
Block a user