Add front component widget (#17440)
Modified the data model and introduced a seed to introduce front components widgets.
This commit is contained in:
+4
@@ -10,6 +10,8 @@ import {
|
||||
} from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-type-validator.type';
|
||||
import { type FlatPageLayoutWidgetValidationError } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-validation-error.type';
|
||||
import { rejectWidgetType } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/reject-widget-type.util';
|
||||
import { validateFrontComponentFlatPageLayoutWidgetForCreation } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-front-component-flat-page-layout-widget-for-creation.util';
|
||||
import { validateFrontComponentFlatPageLayoutWidgetForUpdate } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-front-component-flat-page-layout-widget-for-update.util';
|
||||
import { validateGraphFlatPageLayoutWidgetForCreation } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-graph-flat-page-layout-widget-for-creation.util';
|
||||
import { validateGraphFlatPageLayoutWidgetForUpdate } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-graph-flat-page-layout-widget-for-update.util';
|
||||
import { validateIframeFlatPageLayoutWidgetForCreation } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-iframe-flat-page-layout-widget-for-creation.util';
|
||||
@@ -58,6 +60,7 @@ export class FlatPageLayoutWidgetTypeValidatorService {
|
||||
GRAPH: validateGraphFlatPageLayoutWidgetForCreation,
|
||||
STANDALONE_RICH_TEXT:
|
||||
validateStandaloneRichTextFlatPageLayoutWidgetForCreation,
|
||||
FRONT_COMPONENT: validateFrontComponentFlatPageLayoutWidgetForCreation,
|
||||
TIMELINE: rejectWidgetType(
|
||||
WidgetType.TIMELINE,
|
||||
'Widget type TIMELINE is not supported yet.',
|
||||
@@ -131,6 +134,7 @@ export class FlatPageLayoutWidgetTypeValidatorService {
|
||||
GRAPH: validateGraphFlatPageLayoutWidgetForUpdate,
|
||||
STANDALONE_RICH_TEXT:
|
||||
validateStandaloneRichTextFlatPageLayoutWidgetForUpdate,
|
||||
FRONT_COMPONENT: validateFrontComponentFlatPageLayoutWidgetForUpdate,
|
||||
TIMELINE: rejectWidgetType(
|
||||
WidgetType.TIMELINE,
|
||||
'Widget type TIMELINE is not supported yet.',
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutWidgetValidationError } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-validation-error.type';
|
||||
import { type FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { PageLayoutWidgetExceptionCode } from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
||||
|
||||
export const validateFrontComponentConfigurationType = (
|
||||
configuration: FrontComponentConfigurationDTO,
|
||||
widgetTitle: string,
|
||||
): FlatPageLayoutWidgetValidationError[] => {
|
||||
const errors: FlatPageLayoutWidgetValidationError[] = [];
|
||||
|
||||
if (!isDefined(configuration.configurationType)) {
|
||||
errors.push({
|
||||
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
||||
message: t`Configuration type is required for widget "${widgetTitle}"`,
|
||||
userFriendlyMessage: msg`Configuration type is required`,
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (
|
||||
configuration.configurationType !== WidgetConfigurationType.FRONT_COMPONENT
|
||||
) {
|
||||
const configurationTypeString = String(configuration.configurationType);
|
||||
|
||||
errors.push({
|
||||
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
||||
message: t`Invalid configuration type for front component widget "${widgetTitle}". Expected FRONT_COMPONENT, got ${configurationTypeString}`,
|
||||
userFriendlyMessage: msg`Invalid configuration type for front component widget`,
|
||||
value: configuration.configurationType,
|
||||
});
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { msg, t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type ValidateFlatPageLayoutWidgetTypeSpecificitiesForCreationArgs } from 'src/engine/metadata-modules/flat-page-layout-widget/services/flat-page-layout-widget-type-validator.service';
|
||||
import { type FlatPageLayoutWidgetValidationError } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-validation-error.type';
|
||||
import { validateFrontComponentConfigurationType } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-front-component-configuration-type.util';
|
||||
import { type FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto';
|
||||
import { PageLayoutWidgetExceptionCode } from 'src/engine/metadata-modules/page-layout-widget/exceptions/page-layout-widget.exception';
|
||||
|
||||
export const validateFrontComponentFlatPageLayoutWidgetForCreation = (
|
||||
args: ValidateFlatPageLayoutWidgetTypeSpecificitiesForCreationArgs,
|
||||
): FlatPageLayoutWidgetValidationError[] => {
|
||||
const { flatEntityToValidate } = args;
|
||||
const { configuration, title } = flatEntityToValidate;
|
||||
const errors: FlatPageLayoutWidgetValidationError[] = [];
|
||||
|
||||
if (!isDefined(configuration)) {
|
||||
errors.push({
|
||||
code: PageLayoutWidgetExceptionCode.INVALID_PAGE_LAYOUT_WIDGET_DATA,
|
||||
message: t`Configuration is required for front component widget "${title}"`,
|
||||
userFriendlyMessage: msg`Configuration is required for front component widget`,
|
||||
});
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const frontComponentConfiguration =
|
||||
configuration as FrontComponentConfigurationDTO;
|
||||
|
||||
const configurationTypeErrors = validateFrontComponentConfigurationType(
|
||||
frontComponentConfiguration,
|
||||
title,
|
||||
);
|
||||
|
||||
errors.push(...configurationTypeErrors);
|
||||
|
||||
return errors;
|
||||
};
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type ValidateFlatPageLayoutWidgetTypeSpecificitiesForUpdateArgs } from 'src/engine/metadata-modules/flat-page-layout-widget/services/flat-page-layout-widget-type-validator.service';
|
||||
import { type FlatPageLayoutWidgetValidationError } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-validation-error.type';
|
||||
import { validateFrontComponentConfigurationType } from 'src/engine/metadata-modules/flat-page-layout-widget/validators/utils/validate-front-component-configuration-type.util';
|
||||
import { type FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto';
|
||||
|
||||
export const validateFrontComponentFlatPageLayoutWidgetForUpdate = (
|
||||
args: ValidateFlatPageLayoutWidgetTypeSpecificitiesForUpdateArgs,
|
||||
): FlatPageLayoutWidgetValidationError[] => {
|
||||
const { flatEntityToValidate } = args;
|
||||
const { configuration, title } = flatEntityToValidate;
|
||||
const errors: FlatPageLayoutWidgetValidationError[] = [];
|
||||
|
||||
if (!isDefined(configuration)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const frontComponentConfiguration =
|
||||
configuration as FrontComponentConfigurationDTO;
|
||||
|
||||
const configurationTypeErrors = validateFrontComponentConfigurationType(
|
||||
frontComponentConfiguration,
|
||||
title,
|
||||
);
|
||||
|
||||
errors.push(...configurationTypeErrors);
|
||||
|
||||
return errors;
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
@ObjectType('FrontComponentCode')
|
||||
export class FrontComponentCodeDTO {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
sourceCode: string;
|
||||
}
|
||||
+13
@@ -10,6 +10,7 @@ import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { CreateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/create-front-component.input';
|
||||
import { FrontComponentCodeDTO } from 'src/engine/metadata-modules/front-component/dtos/front-component-code.dto';
|
||||
import { FrontComponentDTO } from 'src/engine/metadata-modules/front-component/dtos/front-component.dto';
|
||||
import { UpdateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/update-front-component.input';
|
||||
import { FrontComponentService } from 'src/engine/metadata-modules/front-component/front-component.service';
|
||||
@@ -42,6 +43,18 @@ export class FrontComponentResolver {
|
||||
return await this.frontComponentService.findById(id, workspace.id);
|
||||
}
|
||||
|
||||
@Query(() => FrontComponentCodeDTO)
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getFrontComponentCode(
|
||||
@Args('id', { type: () => UUIDScalarType }) id: string,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<FrontComponentCodeDTO> {
|
||||
return await this.frontComponentService.getFrontComponentCode(
|
||||
id,
|
||||
workspace.id,
|
||||
);
|
||||
}
|
||||
|
||||
@Mutation(() => FrontComponentDTO)
|
||||
@UseGuards(SettingsPermissionGuard(PermissionFlagType.APPLICATIONS))
|
||||
async createFrontComponent(
|
||||
|
||||
+11
@@ -11,6 +11,7 @@ import { fromDeleteFrontComponentInputToFlatFrontComponentOrThrow } from 'src/en
|
||||
import { fromFlatFrontComponentToFrontComponentDto } from 'src/engine/metadata-modules/flat-front-component/utils/from-flat-front-component-to-front-component-dto.util';
|
||||
import { fromUpdateFrontComponentInputToFlatFrontComponentToUpdateOrThrow } from 'src/engine/metadata-modules/flat-front-component/utils/from-update-front-component-input-to-flat-front-component-to-update-or-throw.util';
|
||||
import { type CreateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/create-front-component.input';
|
||||
import { type FrontComponentCodeDTO } from 'src/engine/metadata-modules/front-component/dtos/front-component-code.dto';
|
||||
import { type FrontComponentDTO } from 'src/engine/metadata-modules/front-component/dtos/front-component.dto';
|
||||
import { type UpdateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/update-front-component.input';
|
||||
import {
|
||||
@@ -234,4 +235,14 @@ export class FrontComponentService {
|
||||
|
||||
return frontComponent;
|
||||
}
|
||||
|
||||
async getFrontComponentCode(
|
||||
_id: string,
|
||||
_workspaceId: string,
|
||||
): Promise<FrontComponentCodeDTO> {
|
||||
// TODO: get the source code from the front component here, we will implement a mock version for now
|
||||
const sourceCode = '';
|
||||
|
||||
return { sourceCode };
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -6,6 +6,7 @@ import { FieldConfigurationDTO } from 'src/engine/metadata-modules/page-layout-w
|
||||
import { FieldRichTextConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/field-rich-text-configuration.dto';
|
||||
import { FieldsConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/fields-configuration.dto';
|
||||
import { FilesConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/files-configuration.dto';
|
||||
import { FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-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';
|
||||
@@ -31,6 +32,7 @@ export const ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYP
|
||||
GAUGE_CHART: GaugeChartConfigurationDTO,
|
||||
BAR_CHART: BarChartConfigurationDTO,
|
||||
CALENDAR: CalendarConfigurationDTO,
|
||||
FRONT_COMPONENT: FrontComponentConfigurationDTO,
|
||||
EMAILS: EmailsConfigurationDTO,
|
||||
FIELD: FieldConfigurationDTO,
|
||||
FIELD_RICH_TEXT: FieldRichTextConfigurationDTO,
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IsIn, IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
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('FrontComponentConfiguration')
|
||||
export class FrontComponentConfigurationDTO
|
||||
implements PageLayoutWidgetConfigurationBase
|
||||
{
|
||||
@Field(() => WidgetConfigurationType)
|
||||
@IsIn([WidgetConfigurationType.FRONT_COMPONENT])
|
||||
@IsNotEmpty()
|
||||
configurationType: WidgetConfigurationType.FRONT_COMPONENT;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
@IsNotEmpty()
|
||||
@IsUUID()
|
||||
frontComponentId: string;
|
||||
}
|
||||
+1
@@ -25,6 +25,7 @@ export enum WidgetConfigurationType {
|
||||
WORKFLOW = 'WORKFLOW',
|
||||
WORKFLOW_VERSION = 'WORKFLOW_VERSION',
|
||||
WORKFLOW_RUN = 'WORKFLOW_RUN',
|
||||
FRONT_COMPONENT = 'FRONT_COMPONENT',
|
||||
}
|
||||
|
||||
registerEnumType(WidgetConfigurationType, {
|
||||
|
||||
+1
@@ -15,4 +15,5 @@ export enum WidgetType {
|
||||
WORKFLOW = 'WORKFLOW',
|
||||
WORKFLOW_VERSION = 'WORKFLOW_VERSION',
|
||||
WORKFLOW_RUN = 'WORKFLOW_RUN',
|
||||
FRONT_COMPONENT = 'FRONT_COMPONENT',
|
||||
}
|
||||
|
||||
+7
@@ -2,6 +2,7 @@ import { isNotEmptyObject, type ValidationError } from 'class-validator';
|
||||
|
||||
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 { FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-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';
|
||||
@@ -113,6 +114,12 @@ export const validateWidgetConfigurationInput = ({
|
||||
configuration,
|
||||
);
|
||||
break;
|
||||
case WidgetConfigurationType.FRONT_COMPONENT:
|
||||
errors = validateWidgetConfigurationByDto(
|
||||
FrontComponentConfigurationDTO,
|
||||
configuration,
|
||||
);
|
||||
break;
|
||||
case WidgetConfigurationType.VIEW:
|
||||
throw new PageLayoutWidgetException(
|
||||
'View configuration is not supported yet',
|
||||
|
||||
Reference in New Issue
Block a user