From 4d73e7e0b3b425b5ae380d546f82b109af5bea62 Mon Sep 17 00:00:00 2001 From: Hetu Nandu Date: Wed, 21 Apr 2021 20:04:25 +0530 Subject: [PATCH] Widget validation for nested property paths (#3947) --- .../constants/PropertyControlConstants.tsx | 2 + app/client/src/constants/WidgetValidation.ts | 57 ++-- .../src/entities/DataTree/dataTreeFactory.ts | 2 + .../entities/DataTree/dataTreeWidget.test.ts | 245 ++++++++++++++++++ .../src/entities/DataTree/dataTreeWidget.ts | 7 +- app/client/src/entities/Widget/utils.test.ts | 14 + app/client/src/entities/Widget/utils.ts | 17 +- .../mockResponses/WidgetConfigResponse.tsx | 10 - .../entityReducers/widgetConfigReducer.tsx | 2 - app/client/src/sagas/EvaluationsSaga.ts | 7 +- app/client/src/sagas/WidgetOperationSagas.tsx | 1 - app/client/src/selectors/editorSelectors.tsx | 1 + app/client/src/utils/WidgetFactory.tsx | 23 -- app/client/src/utils/WidgetRegistry.tsx | 25 -- app/client/src/utils/WidgetValidation.ts | 16 -- .../dataTreeTypeDefCreator.test.ts | 1 + app/client/src/widgets/AlertWidget.tsx | 20 -- app/client/src/widgets/BaseWidget.tsx | 9 - app/client/src/widgets/ButtonWidget.tsx | 16 +- app/client/src/widgets/ChartWidget/index.tsx | 13 - .../src/widgets/ChartWidget/propertyConfig.ts | 8 + app/client/src/widgets/CheckboxWidget.tsx | 17 +- app/client/src/widgets/ContainerWidget.tsx | 3 + app/client/src/widgets/DatePickerWidget.tsx | 27 +- app/client/src/widgets/DatePickerWidget2.tsx | 28 +- app/client/src/widgets/DropdownWidget.tsx | 24 +- app/client/src/widgets/FilepickerWidget.tsx | 21 +- app/client/src/widgets/FormButtonWidget.tsx | 18 +- app/client/src/widgets/FormWidget.tsx | 3 + app/client/src/widgets/ImageWidget.tsx | 17 +- app/client/src/widgets/InputWidget.tsx | 35 +-- app/client/src/widgets/MapWidget.tsx | 17 +- app/client/src/widgets/RadioGroupWidget.tsx | 20 +- .../src/widgets/RichTextEditorWidget.tsx | 12 +- app/client/src/widgets/SwitchWidget.tsx | 16 +- .../TableWidget/TablePropertyPaneConfig.ts | 5 + app/client/src/widgets/TableWidget/index.tsx | 21 -- app/client/src/widgets/TabsWidget.tsx | 10 +- app/client/src/widgets/TextWidget.tsx | 14 +- app/client/src/widgets/VideoWidget.tsx | 13 +- app/client/src/workers/DataTreeEvaluator.ts | 74 +++--- app/client/src/workers/evaluate.test.ts | 1 + app/client/src/workers/evaluation.test.ts | 210 +-------------- app/client/src/workers/evaluation.worker.ts | 18 +- app/client/src/workers/evaluationUtils.ts | 97 +++---- app/client/src/workers/validations.ts | 3 +- 46 files changed, 507 insertions(+), 713 deletions(-) create mode 100644 app/client/src/entities/DataTree/dataTreeWidget.test.ts delete mode 100644 app/client/src/utils/WidgetValidation.ts delete mode 100644 app/client/src/widgets/AlertWidget.tsx diff --git a/app/client/src/constants/PropertyControlConstants.tsx b/app/client/src/constants/PropertyControlConstants.tsx index f11d0174d0..abcfe209eb 100644 --- a/app/client/src/constants/PropertyControlConstants.tsx +++ b/app/client/src/constants/PropertyControlConstants.tsx @@ -1,4 +1,5 @@ import { getPropertyControlTypes } from "components/propertyControls"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; const ControlTypes = getPropertyControlTypes(); export type ControlType = typeof ControlTypes[keyof typeof ControlTypes]; @@ -42,6 +43,7 @@ export type PropertyPaneControlConfig = { hidden?: (props: any, propertyPath: string) => boolean; isBindProperty: boolean; isTriggerProperty: boolean; + validation?: VALIDATION_TYPES; useValidationMessage?: boolean; additionalAutoComplete?: ( props: any, diff --git a/app/client/src/constants/WidgetValidation.ts b/app/client/src/constants/WidgetValidation.ts index 5139ec6dc0..39d7878cd3 100644 --- a/app/client/src/constants/WidgetValidation.ts +++ b/app/client/src/constants/WidgetValidation.ts @@ -2,34 +2,34 @@ import { WidgetProps } from "widgets/BaseWidget"; import { DataTree } from "entities/DataTree/dataTreeFactory"; import { EXECUTION_PARAM_KEY } from "constants/AppsmithActionConstants/ActionConstants"; -// Always add a validator function in ./Validators for these types -export const VALIDATION_TYPES = { - TEXT: "TEXT", - REGEX: "REGEX", - NUMBER: "NUMBER", - BOOLEAN: "BOOLEAN", - OBJECT: "OBJECT", - ARRAY: "ARRAY", - TABLE_DATA: "TABLE_DATA", - OPTIONS_DATA: "OPTIONS_DATA", - DATE_ISO_STRING: "DATE_ISO_STRING", - DEFAULT_DATE: "DEFAULT_DATE", - MIN_DATE: "MIN_DATE", - MAX_DATE: "MAX_DATE", - TABS_DATA: "TABS_DATA", - CHART_DATA: "CHART_DATA", - CUSTOM_FUSION_CHARTS_DATA: "CUSTOM_FUSION_CHARTS_DATA", - MARKERS: "MARKERS", - ACTION_SELECTOR: "ACTION_SELECTOR", - ARRAY_ACTION_SELECTOR: "ARRAY_ACTION_SELECTOR", - SELECTED_TAB: "SELECTED_TAB", - DEFAULT_OPTION_VALUE: "DEFAULT_OPTION_VALUE", - DEFAULT_SELECTED_ROW: "DEFAULT_SELECTED_ROW", - COLUMN_PROPERTIES_ARRAY: "COLUMN_PROPERTIES_ARRAY", - LAT_LONG: "LAT_LONG", - TABLE_PAGE_NO: "TABLE_PAGE_NO", - ROW_INDICES: "ROW_INDICES", -}; +// Always add a validator function in ./worker/validation for these types +export enum VALIDATION_TYPES { + TEXT = "TEXT", + REGEX = "REGEX", + NUMBER = "NUMBER", + BOOLEAN = "BOOLEAN", + OBJECT = "OBJECT", + ARRAY = "ARRAY", + TABLE_DATA = "TABLE_DATA", + OPTIONS_DATA = "OPTIONS_DATA", + DATE_ISO_STRING = "DATE_ISO_STRING", + DEFAULT_DATE = "DEFAULT_DATE", + MIN_DATE = "MIN_DATE", + MAX_DATE = "MAX_DATE", + TABS_DATA = "TABS_DATA", + CHART_DATA = "CHART_DATA", + CUSTOM_FUSION_CHARTS_DATA = "CUSTOM_FUSION_CHARTS_DATA", + MARKERS = "MARKERS", + ACTION_SELECTOR = "ACTION_SELECTOR", + ARRAY_ACTION_SELECTOR = "ARRAY_ACTION_SELECTOR", + SELECTED_TAB = "SELECTED_TAB", + DEFAULT_OPTION_VALUE = "DEFAULT_OPTION_VALUE", + DEFAULT_SELECTED_ROW = "DEFAULT_SELECTED_ROW", + COLUMN_PROPERTIES_ARRAY = "COLUMN_PROPERTIES_ARRAY", + LAT_LONG = "LAT_LONG", + TABLE_PAGE_NO = "TABLE_PAGE_NO", + ROW_INDICES = "ROW_INDICES", +} export type ValidationResponse = { isValid: boolean; @@ -38,7 +38,6 @@ export type ValidationResponse = { transformed?: any; }; -export type ValidationType = typeof VALIDATION_TYPES[keyof typeof VALIDATION_TYPES]; export type Validator = ( value: any, props: WidgetProps, diff --git a/app/client/src/entities/DataTree/dataTreeFactory.ts b/app/client/src/entities/DataTree/dataTreeFactory.ts index b78308fdef..5c6dee3737 100644 --- a/app/client/src/entities/DataTree/dataTreeFactory.ts +++ b/app/client/src/entities/DataTree/dataTreeFactory.ts @@ -12,6 +12,7 @@ import { AppDataState } from "reducers/entityReducers/appReducer"; import { DynamicPath } from "utils/DynamicBindingUtils"; import { generateDataTreeAction } from "entities/DataTree/dataTreeAction"; import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; export type ActionDescription = { type: string; @@ -52,6 +53,7 @@ export interface DataTreeAction extends Omit { export interface DataTreeWidget extends WidgetProps { bindingPaths: Record; triggerPaths: Record; + validationPaths: Record; ENTITY_TYPE: ENTITY_TYPE.WIDGET; } diff --git a/app/client/src/entities/DataTree/dataTreeWidget.test.ts b/app/client/src/entities/DataTree/dataTreeWidget.test.ts new file mode 100644 index 0000000000..23ab042a17 --- /dev/null +++ b/app/client/src/entities/DataTree/dataTreeWidget.test.ts @@ -0,0 +1,245 @@ +import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget"; +import { DataTreeWidget, ENTITY_TYPE } from "entities/DataTree/dataTreeFactory"; +import { RenderModes, WidgetTypes } from "constants/WidgetConstants"; +import WidgetFactory from "utils/WidgetFactory"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; + +describe("generateDataTreeWidget", () => { + beforeEach(() => { + const getMetaProps = jest.spyOn( + WidgetFactory, + "getWidgetMetaPropertiesMap", + ); + getMetaProps.mockReturnValueOnce({ + text: undefined, + isDirty: false, + isFocused: false, + }); + + const getDerivedProps = jest.spyOn( + WidgetFactory, + "getWidgetDerivedPropertiesMap", + ); + getDerivedProps.mockReturnValueOnce({ + isValid: "{{true}}", + value: "{{this.text}}", + }); + + const getDefaultProps = jest.spyOn( + WidgetFactory, + "getWidgetDefaultPropertiesMap", + ); + getDefaultProps.mockReturnValueOnce({ + text: "defaultText", + }); + + const getPropertyConfig = jest.spyOn( + WidgetFactory, + "getWidgetPropertyPaneConfig", + ); + getPropertyConfig.mockReturnValueOnce([ + { + sectionName: "General", + children: [ + { + propertyName: "inputType", + label: "Data Type", + controlType: "DROP_DOWN", + isBindProperty: false, + isTriggerProperty: false, + }, + { + propertyName: "defaultText", + label: "Default Text", + controlType: "INPUT_TEXT", + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, + }, + { + propertyName: "placeholderText", + label: "Placeholder", + controlType: "INPUT_TEXT", + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, + }, + { + propertyName: "regex", + label: "Regex", + controlType: "INPUT_TEXT", + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.REGEX, + }, + { + propertyName: "errorMessage", + label: "Error Message", + controlType: "INPUT_TEXT", + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, + }, + { + propertyName: "isRequired", + label: "Required", + controlType: "SWITCH", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, + }, + { + propertyName: "isVisible", + label: "Visible", + controlType: "SWITCH", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, + }, + { + propertyName: "isDisabled", + label: "Disabled", + controlType: "SWITCH", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, + }, + { + propertyName: "resetOnSubmit", + label: "Reset on submit", + controlType: "SWITCH", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, + }, + ], + }, + { + sectionName: "Actions", + children: [ + { + propertyName: "onTextChanged", + label: "onTextChanged", + controlType: "ACTION_SELECTOR", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: true, + }, + { + propertyName: "onSubmit", + label: "onSubmit", + controlType: "ACTION_SELECTOR", + isJSConvertible: true, + isBindProperty: true, + isTriggerProperty: true, + }, + ], + }, + ]); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it("generates enhanced widget with the right properties", () => { + const widget: FlattenedWidgetProps = { + bottomRow: 0, + isLoading: false, + leftColumn: 0, + parentColumnSpace: 0, + parentRowSpace: 0, + renderMode: RenderModes.CANVAS, + rightColumn: 0, + topRow: 0, + type: WidgetTypes.INPUT_WIDGET, + version: 0, + widgetId: "123", + widgetName: "Input1", + defaultText: "Testing", + }; + + const widgetMetaProps: Record = { + text: "Tester", + isDirty: true, + }; + + const getMetaProps = jest.spyOn( + WidgetFactory, + "getWidgetMetaPropertiesMap", + ); + + getMetaProps.mockReturnValueOnce({ + text: true, + isDirty: true, + }); + + const expected: DataTreeWidget = { + bindingPaths: { + defaultText: true, + errorMessage: true, + isDirty: true, + isDisabled: true, + isFocused: true, + isRequired: true, + isValid: true, + isVisible: true, + placeholderText: true, + regex: true, + resetOnSubmit: true, + text: true, + value: true, + }, + triggerPaths: { + onSubmit: true, + onTextChanged: true, + }, + validationPaths: { + defaultText: VALIDATION_TYPES.TEXT, + errorMessage: VALIDATION_TYPES.TEXT, + isDisabled: VALIDATION_TYPES.BOOLEAN, + isRequired: VALIDATION_TYPES.BOOLEAN, + isVisible: VALIDATION_TYPES.BOOLEAN, + placeholderText: VALIDATION_TYPES.TEXT, + regex: VALIDATION_TYPES.REGEX, + resetOnSubmit: VALIDATION_TYPES.BOOLEAN, + }, + dynamicBindingPathList: [ + { + key: "isValid", + }, + { + key: "value", + }, + ], + value: "{{Input1.text}}", + isDirty: true, + isFocused: false, + isValid: "{{true}}", + text: "Tester", + bottomRow: 0, + isLoading: false, + leftColumn: 0, + parentColumnSpace: 0, + parentRowSpace: 0, + renderMode: RenderModes.CANVAS, + rightColumn: 0, + topRow: 0, + type: WidgetTypes.INPUT_WIDGET, + version: 0, + widgetId: "123", + widgetName: "Input1", + ENTITY_TYPE: ENTITY_TYPE.WIDGET, + defaultText: "Testing", + }; + + const result = generateDataTreeWidget(widget, widgetMetaProps); + + expect(result).toStrictEqual(expected); + }); +}); diff --git a/app/client/src/entities/DataTree/dataTreeWidget.ts b/app/client/src/entities/DataTree/dataTreeWidget.ts index ab53a257e6..a0dacf901f 100644 --- a/app/client/src/entities/DataTree/dataTreeWidget.ts +++ b/app/client/src/entities/DataTree/dataTreeWidget.ts @@ -19,7 +19,11 @@ export const generateDataTreeWidget = ( const propertyPaneConfigs = WidgetFactory.getWidgetPropertyPaneConfig( widget.type, ); - const { bindingPaths, triggerPaths } = getAllPathsFromPropertyConfig( + const { + bindingPaths, + triggerPaths, + validationPaths, + } = getAllPathsFromPropertyConfig( widget, propertyPaneConfigs, Object.fromEntries( @@ -67,6 +71,7 @@ export const generateDataTreeWidget = ( dynamicBindingPathList, bindingPaths, triggerPaths, + validationPaths, ENTITY_TYPE: ENTITY_TYPE.WIDGET, }; }; diff --git a/app/client/src/entities/Widget/utils.test.ts b/app/client/src/entities/Widget/utils.test.ts index b6d23090f3..bab8f09a93 100644 --- a/app/client/src/entities/Widget/utils.test.ts +++ b/app/client/src/entities/Widget/utils.test.ts @@ -145,6 +145,12 @@ describe("getAllPathsFromPropertyConfig", () => { onPageSizeChange: true, "primaryColumns.status.onClick": true, }, + validationPaths: { + defaultSearchText: "TEXT", + defaultSelectedRow: "DEFAULT_SELECTED_ROW", + isVisible: "BOOLEAN", + tableData: "TABLE_DATA", + }, }; const result = getAllPathsFromPropertyConfig(widget, config, { @@ -202,6 +208,14 @@ describe("getAllPathsFromPropertyConfig", () => { triggerPaths: { onDataPointClick: true, }, + validationPaths: { + "chartData[0].data": "CHART_DATA", + "chartData[0].seriesName": "TEXT", + chartName: "TEXT", + isVisible: "BOOLEAN", + xAxisName: "TEXT", + yAxisName: "TEXT", + }, }; const result = getAllPathsFromPropertyConfig(widget, config, {}); diff --git a/app/client/src/entities/Widget/utils.ts b/app/client/src/entities/Widget/utils.ts index ce23c7e529..84ae7d552a 100644 --- a/app/client/src/entities/Widget/utils.ts +++ b/app/client/src/entities/Widget/utils.ts @@ -2,6 +2,7 @@ import { WidgetProps } from "widgets/BaseWidget"; import { PropertyPaneConfig } from "constants/PropertyControlConstants"; import { get } from "lodash"; import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; export const getAllPathsFromPropertyConfig = ( widget: WidgetProps, @@ -10,9 +11,11 @@ export const getAllPathsFromPropertyConfig = ( ): { bindingPaths: Record; triggerPaths: Record; + validationPaths: Record; } => { const bindingPaths: Record = derivedProperties; const triggerPaths: Record = {}; + const validationPaths: Record = {}; widgetConfig.forEach((config) => { if (config.children) { config.children.forEach((controlConfig: any) => { @@ -27,6 +30,10 @@ export const getAllPathsFromPropertyConfig = ( !controlConfig.isTriggerProperty ) { bindingPaths[controlConfig.propertyName] = true; + if (controlConfig.validation) { + validationPaths[controlConfig.propertyName] = + controlConfig.validation; + } } else if ( controlConfig.isBindProperty && controlConfig.isTriggerProperty @@ -66,6 +73,10 @@ export const getAllPathsFromPropertyConfig = ( !panelColumnControlConfig.isTriggerProperty ) { bindingPaths[panelPropertyPath] = true; + if (panelColumnControlConfig.validation) { + validationPaths[panelPropertyPath] = + panelColumnControlConfig.validation; + } } else if ( panelColumnControlConfig.isBindProperty && panelColumnControlConfig.isTriggerProperty @@ -97,6 +108,10 @@ export const getAllPathsFromPropertyConfig = ( !childPropertyConfig.isTriggerProperty ) { bindingPaths[childArrayPropertyPath] = true; + if (childPropertyConfig.validation) { + validationPaths[childArrayPropertyPath] = + childPropertyConfig.validation; + } } else if ( childPropertyConfig.isBindProperty && childPropertyConfig.isTriggerProperty @@ -112,7 +127,7 @@ export const getAllPathsFromPropertyConfig = ( } }); - return { bindingPaths, triggerPaths }; + return { bindingPaths, triggerPaths, validationPaths }; }; export const nextAvailableRowInContainer = ( diff --git a/app/client/src/mockResponses/WidgetConfigResponse.tsx b/app/client/src/mockResponses/WidgetConfigResponse.tsx index 03cf9ab4b5..b1e1545e93 100644 --- a/app/client/src/mockResponses/WidgetConfigResponse.tsx +++ b/app/client/src/mockResponses/WidgetConfigResponse.tsx @@ -199,16 +199,6 @@ const WidgetConfigResponse: WidgetConfigReducerState = { widgetName: "RadioGroup", version: 1, }, - ALERT_WIDGET: { - alertType: "NOTIFICATION", - intent: "SUCCESS", - rows: 3, - columns: 3, - header: "", - message: "", - widgetName: "Alert", - version: 1, - }, FILE_PICKER_WIDGET: { rows: 1, files: [], diff --git a/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx b/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx index 65e7d5a939..155fae76c6 100644 --- a/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx +++ b/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx @@ -14,7 +14,6 @@ import { TableWidgetProps } from "../../widgets/TableWidget/TableWidgetConstants import { DropdownWidgetProps } from "../../widgets/DropdownWidget"; import { CheckboxWidgetProps } from "../../widgets/CheckboxWidget"; import { RadioGroupWidgetProps } from "../../widgets/RadioGroupWidget"; -import { AlertWidgetProps } from "../../widgets/AlertWidget"; import { FilePickerWidgetProps } from "../../widgets/FilepickerWidget"; import { TabsWidgetProps, @@ -67,7 +66,6 @@ export interface WidgetConfigReducerState { CHECKBOX_WIDGET: Partial & WidgetConfigProps; SWITCH_WIDGET: Partial & WidgetConfigProps; RADIO_GROUP_WIDGET: Partial & WidgetConfigProps; - ALERT_WIDGET: Partial & WidgetConfigProps; FILE_PICKER_WIDGET: Partial & WidgetConfigProps; TABS_WIDGET: Partial> & WidgetConfigProps; diff --git a/app/client/src/sagas/EvaluationsSaga.ts b/app/client/src/sagas/EvaluationsSaga.ts index 26bb33222f..338fa02883 100644 --- a/app/client/src/sagas/EvaluationsSaga.ts +++ b/app/client/src/sagas/EvaluationsSaga.ts @@ -23,7 +23,6 @@ import { EvalErrorTypes, } from "utils/DynamicBindingUtils"; import log from "loglevel"; -import { WidgetType } from "constants/WidgetConstants"; import { WidgetProps } from "widgets/BaseWidget"; import PerformanceTracker, { PerformanceTransactionName, @@ -209,17 +208,17 @@ export function* clearEvalPropertyCacheOfWidget(widgetName: string) { } export function* validateProperty( - widgetType: WidgetType, property: string, value: any, props: WidgetProps, ) { + const unevalTree = yield select(getUnevaluatedDataTree); + const validation = unevalTree[props.widgetName].validationPaths[property]; return yield call(worker.request, EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY, { - widgetTypeConfigMap, - widgetType, property, value, props, + validation, }); } diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index adce7022ea..88a0fb3b0a 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -817,7 +817,6 @@ function* setWidgetDynamicPropertySaga( }); const { parsed } = yield call( validateProperty, - widget.type, propertyPath, propertyValue, widget, diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index 9be7d4aea8..e6d8176c85 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -262,6 +262,7 @@ const createLoadingWidget = ( ENTITY_TYPE: ENTITY_TYPE.WIDGET, bindingPaths: {}, triggerPaths: {}, + validationPaths: {}, isLoading: true, }; }; diff --git a/app/client/src/utils/WidgetFactory.tsx b/app/client/src/utils/WidgetFactory.tsx index 559933a04f..cc5418552b 100644 --- a/app/client/src/utils/WidgetFactory.tsx +++ b/app/client/src/utils/WidgetFactory.tsx @@ -5,10 +5,6 @@ import { WidgetDataProps, WidgetState, } from "widgets/BaseWidget"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "./WidgetValidation"; import React from "react"; import { PropertyPaneConfig, @@ -49,10 +45,6 @@ class WidgetFactory { WidgetType, WidgetBuilder > = new Map(); - static widgetPropValidationMap: Map< - WidgetType, - WidgetPropertyValidationType - > = new Map(); static widgetDerivedPropertiesGetterMap: Map< WidgetType, WidgetDerivedPropertyType @@ -74,14 +66,12 @@ class WidgetFactory { static registerWidgetBuilder( widgetType: WidgetType, widgetBuilder: WidgetBuilder, - widgetPropertyValidation: WidgetPropertyValidationType, derivedPropertiesMap: DerivedPropertiesMap, defaultPropertiesMap: Record, metaPropertiesMap: Record, propertyPaneConfig?: PropertyPaneConfig[], ) { this.widgetMap.set(widgetType, widgetBuilder); - this.widgetPropValidationMap.set(widgetType, widgetPropertyValidation); this.derivedPropertiesMap.set(widgetType, derivedPropertiesMap); this.defaultPropertiesMap.set(widgetType, defaultPropertiesMap); this.metaPropertiesMap.set(widgetType, metaPropertiesMap); @@ -122,17 +112,6 @@ class WidgetFactory { return Array.from(this.widgetMap.keys()); } - static getWidgetPropertyValidationMap( - widgetType: WidgetType, - ): WidgetPropertyValidationType { - const map = this.widgetPropValidationMap.get(widgetType); - if (!map) { - console.error("Widget type validation is not defined"); - return BASE_WIDGET_VALIDATION; - } - return map; - } - static getWidgetDerivedPropertiesMap( widgetType: WidgetType, ): DerivedPropertiesMap { @@ -181,7 +160,6 @@ class WidgetFactory { const typeConfigMap: WidgetTypeConfigMap = {}; WidgetFactory.getWidgetTypes().forEach((type) => { typeConfigMap[type] = { - validations: WidgetFactory.getWidgetPropertyValidationMap(type), defaultProperties: WidgetFactory.getWidgetDefaultPropertiesMap(type), derivedProperties: WidgetFactory.getWidgetDerivedPropertiesMap(type), metaProperties: WidgetFactory.getWidgetMetaPropertiesMap(type), @@ -194,7 +172,6 @@ class WidgetFactory { export type WidgetTypeConfigMap = Record< string, { - validations: WidgetPropertyValidationType; derivedProperties: WidgetDerivedPropertyType; defaultProperties: Record; metaProperties: Record; diff --git a/app/client/src/utils/WidgetRegistry.tsx b/app/client/src/utils/WidgetRegistry.tsx index 82776f5c62..9a27a44666 100644 --- a/app/client/src/utils/WidgetRegistry.tsx +++ b/app/client/src/utils/WidgetRegistry.tsx @@ -105,7 +105,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - ContainerWidget.getPropertyValidationMap(), ContainerWidget.getDerivedPropertiesMap(), ContainerWidget.getDefaultPropertiesMap(), ContainerWidget.getMetaPropertiesMap(), @@ -119,7 +118,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - TextWidget.getPropertyValidationMap(), TextWidget.getDerivedPropertiesMap(), TextWidget.getDefaultPropertiesMap(), TextWidget.getMetaPropertiesMap(), @@ -133,7 +131,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - ButtonWidget.getPropertyValidationMap(), ButtonWidget.getDerivedPropertiesMap(), ButtonWidget.getDefaultPropertiesMap(), ButtonWidget.getMetaPropertiesMap(), @@ -147,7 +144,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - InputWidget.getPropertyValidationMap(), InputWidget.getDerivedPropertiesMap(), InputWidget.getDefaultPropertiesMap(), InputWidget.getMetaPropertiesMap(), @@ -161,7 +157,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - CheckboxWidget.getPropertyValidationMap(), CheckboxWidget.getDerivedPropertiesMap(), CheckboxWidget.getDefaultPropertiesMap(), CheckboxWidget.getMetaPropertiesMap(), @@ -175,7 +170,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - SwitchWidget.getPropertyValidationMap(), SwitchWidget.getDerivedPropertiesMap(), SwitchWidget.getDefaultPropertiesMap(), SwitchWidget.getMetaPropertiesMap(), @@ -189,7 +183,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - DropdownWidget.getPropertyValidationMap(), DropdownWidget.getDerivedPropertiesMap(), DropdownWidget.getDefaultPropertiesMap(), DropdownWidget.getMetaPropertiesMap(), @@ -203,7 +196,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - RadioGroupWidget.getPropertyValidationMap(), RadioGroupWidget.getDerivedPropertiesMap(), RadioGroupWidget.getDefaultPropertiesMap(), RadioGroupWidget.getMetaPropertiesMap(), @@ -217,7 +209,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - ImageWidget.getPropertyValidationMap(), ImageWidget.getDerivedPropertiesMap(), ImageWidget.getDefaultPropertiesMap(), ImageWidget.getMetaPropertiesMap(), @@ -230,7 +221,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - TableWidget.getPropertyValidationMap(), TableWidget.getDerivedPropertiesMap(), TableWidget.getDefaultPropertiesMap(), TableWidget.getMetaPropertiesMap(), @@ -244,7 +234,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - VideoWidget.getPropertyValidationMap(), VideoWidget.getDerivedPropertiesMap(), VideoWidget.getDefaultPropertiesMap(), VideoWidget.getMetaPropertiesMap(), @@ -258,7 +247,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - FilePickerWidget.getPropertyValidationMap(), FilePickerWidget.getDerivedPropertiesMap(), FilePickerWidget.getDefaultPropertiesMap(), FilePickerWidget.getMetaPropertiesMap(), @@ -271,7 +259,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - DatePickerWidget.getPropertyValidationMap(), DatePickerWidget.getDerivedPropertiesMap(), DatePickerWidget.getDefaultPropertiesMap(), DatePickerWidget.getMetaPropertiesMap(), @@ -284,7 +271,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - DatePickerWidget2.getPropertyValidationMap(), DatePickerWidget2.getDerivedPropertiesMap(), DatePickerWidget2.getDefaultPropertiesMap(), DatePickerWidget2.getMetaPropertiesMap(), @@ -299,7 +285,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - TabsWidget.getPropertyValidationMap(), TabsWidget.getDerivedPropertiesMap(), TabsWidget.getDefaultPropertiesMap(), TabsWidget.getMetaPropertiesMap(), @@ -312,7 +297,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - BaseWidget.getPropertyValidationMap(), BaseWidget.getDerivedPropertiesMap(), BaseWidget.getDefaultPropertiesMap(), BaseWidget.getMetaPropertiesMap(), @@ -325,7 +309,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - RichTextEditorWidget.getPropertyValidationMap(), RichTextEditorWidget.getDerivedPropertiesMap(), RichTextEditorWidget.getDefaultPropertiesMap(), RichTextEditorWidget.getMetaPropertiesMap(), @@ -338,7 +321,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - ChartWidget.getPropertyValidationMap(), ChartWidget.getDerivedPropertiesMap(), ChartWidget.getDefaultPropertiesMap(), ChartWidget.getMetaPropertiesMap(), @@ -353,7 +335,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - FormWidget.getPropertyValidationMap(), FormWidget.getDerivedPropertiesMap(), FormWidget.getDefaultPropertiesMap(), FormWidget.getMetaPropertiesMap(), @@ -367,7 +348,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - FormButtonWidget.getPropertyValidationMap(), FormButtonWidget.getDerivedPropertiesMap(), FormButtonWidget.getDefaultPropertiesMap(), FormButtonWidget.getMetaPropertiesMap(), @@ -381,7 +361,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - MapWidget.getPropertyValidationMap(), MapWidget.getDerivedPropertiesMap(), MapWidget.getDefaultPropertiesMap(), MapWidget.getMetaPropertiesMap(), @@ -397,7 +376,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - CanvasWidget.getPropertyValidationMap(), CanvasWidget.getDerivedPropertiesMap(), CanvasWidget.getDefaultPropertiesMap(), CanvasWidget.getMetaPropertiesMap(), @@ -411,7 +389,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - IconWidget.getPropertyValidationMap(), IconWidget.getDerivedPropertiesMap(), IconWidget.getDefaultPropertiesMap(), IconWidget.getMetaPropertiesMap(), @@ -425,7 +402,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - SkeletonWidget.getPropertyValidationMap(), SkeletonWidget.getDerivedPropertiesMap(), SkeletonWidget.getDefaultPropertiesMap(), SkeletonWidget.getMetaPropertiesMap(), @@ -439,7 +415,6 @@ export default class WidgetBuilderRegistry { return ; }, }, - ModalWidget.getPropertyValidationMap(), ModalWidget.getDerivedPropertiesMap(), ModalWidget.getDefaultPropertiesMap(), ModalWidget.getMetaPropertiesMap(), diff --git a/app/client/src/utils/WidgetValidation.ts b/app/client/src/utils/WidgetValidation.ts deleted file mode 100644 index a45d083981..0000000000 --- a/app/client/src/utils/WidgetValidation.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { - VALIDATION_TYPES, - ValidationType, - Validator, -} from "constants/WidgetValidation"; - -export const BASE_WIDGET_VALIDATION = { - isLoading: VALIDATION_TYPES.BOOLEAN, - isVisible: VALIDATION_TYPES.BOOLEAN, - isDisabled: VALIDATION_TYPES.BOOLEAN, -}; - -export type WidgetPropertyValidationType = Record< - string, - ValidationType | Validator ->; diff --git a/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.test.ts b/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.test.ts index 853bb76e67..bff6e9a8a5 100644 --- a/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.test.ts +++ b/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.test.ts @@ -31,6 +31,7 @@ describe("dataTreeTypeDefCreator", () => { triggerPaths: { onTextChange: true, }, + validationPaths: {}, }, }; const def = dataTreeTypeDefCreator(dataTree); diff --git a/app/client/src/widgets/AlertWidget.tsx b/app/client/src/widgets/AlertWidget.tsx deleted file mode 100644 index 50a3c915c3..0000000000 --- a/app/client/src/widgets/AlertWidget.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { Component } from "react"; -import { WidgetProps } from "./BaseWidget"; - -class AlertWidget extends Component { - getPageView() { - return
; - } -} - -export type AlertType = "DIALOG" | "NOTIFICATION"; -export type MessageIntent = "SUCCESS" | "ERROR" | "INFO" | "WARNING"; - -export interface AlertWidgetProps extends WidgetProps { - alertType: AlertType; - intent: MessageIntent; - header: string; - message: string; -} - -export default AlertWidget; diff --git a/app/client/src/widgets/BaseWidget.tsx b/app/client/src/widgets/BaseWidget.tsx index d3454c99f7..4bc1a15ea2 100644 --- a/app/client/src/widgets/BaseWidget.tsx +++ b/app/client/src/widgets/BaseWidget.tsx @@ -24,10 +24,6 @@ import shallowequal from "shallowequal"; import { PositionTypes } from "constants/WidgetConstants"; import { EditorContext } from "components/editorComponents/EditorContextProvider"; import ErrorBoundary from "components/editorComponents/ErrorBoundry"; -import { - BASE_WIDGET_VALIDATION, - WidgetPropertyValidationType, -} from "utils/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import { WidgetDynamicPathListProps, @@ -57,11 +53,6 @@ abstract class BaseWidget< static getPropertyPaneConfig(): PropertyPaneConfig[] { return []; } - // Needed to send a default no validation option. In case a widget needs - // validation implement this in the widget class again - static getPropertyValidationMap(): WidgetPropertyValidationType { - return BASE_WIDGET_VALIDATION; - } static getDerivedPropertiesMap(): DerivedPropertiesMap { return {}; diff --git a/app/client/src/widgets/ButtonWidget.tsx b/app/client/src/widgets/ButtonWidget.tsx index 57bb53fdd1..5adb5df62e 100644 --- a/app/client/src/widgets/ButtonWidget.tsx +++ b/app/client/src/widgets/ButtonWidget.tsx @@ -5,10 +5,6 @@ import ButtonComponent, { ButtonType, } from "components/designSystems/blueprint/ButtonComponent"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; @@ -38,6 +34,7 @@ class ButtonWidget extends BaseWidget { placeholderText: "Enter label text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "buttonStyle", @@ -69,6 +66,7 @@ class ButtonWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -78,6 +76,7 @@ class ButtonWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "googleRecaptchaKey", @@ -87,6 +86,7 @@ class ButtonWidget extends BaseWidget { placeholderText: "Enter google recaptcha key", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, ], }, @@ -107,14 +107,6 @@ class ButtonWidget extends BaseWidget { ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - text: VALIDATION_TYPES.TEXT, - buttonStyle: VALIDATION_TYPES.TEXT, - // onClick: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } static getMetaPropertiesMap(): Record { return { recaptchaToken: undefined, diff --git a/app/client/src/widgets/ChartWidget/index.tsx b/app/client/src/widgets/ChartWidget/index.tsx index 2c479d2154..a7c1f18b88 100644 --- a/app/client/src/widgets/ChartWidget/index.tsx +++ b/app/client/src/widgets/ChartWidget/index.tsx @@ -1,8 +1,6 @@ import React, { lazy, Suspense } from "react"; import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; -import { WidgetPropertyValidationType } from "utils/WidgetValidation"; -import { VALIDATION_TYPES } from "constants/WidgetValidation"; import Skeleton from "components/utils/Skeleton"; import * as Sentry from "@sentry/react"; import { retryPromise } from "utils/AppsmithUtils"; @@ -20,17 +18,6 @@ const ChartComponent = lazy(() => ); class ChartWidget extends BaseWidget { - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - xAxisName: VALIDATION_TYPES.TEXT, - yAxisName: VALIDATION_TYPES.TEXT, - chartName: VALIDATION_TYPES.TEXT, - isVisible: VALIDATION_TYPES.BOOLEAN, - chartData: VALIDATION_TYPES.CHART_DATA, - customFusionChartConfig: VALIDATION_TYPES.CUSTOM_FUSION_CHARTS_DATA, - }; - } - static getMetaPropertiesMap(): Record { return { selectedDataPoint: undefined, diff --git a/app/client/src/widgets/ChartWidget/propertyConfig.ts b/app/client/src/widgets/ChartWidget/propertyConfig.ts index e2e47d5dbc..6a16419166 100644 --- a/app/client/src/widgets/ChartWidget/propertyConfig.ts +++ b/app/client/src/widgets/ChartWidget/propertyConfig.ts @@ -1,4 +1,5 @@ import { ChartWidgetProps } from "widgets/ChartWidget"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; export default [ { @@ -12,6 +13,7 @@ export default [ controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Changes the visualisation of the chart data", @@ -56,6 +58,7 @@ export default [ isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -69,6 +72,7 @@ export default [ isBindProperty: true, isTriggerProperty: false, hidden: (x: any) => x.chartType !== "CUSTOM_FUSION_CHART", + validation: VALIDATION_TYPES.CUSTOM_FUSION_CHARTS_DATA, }, { sectionName: "Chart Data", @@ -92,6 +96,7 @@ export default [ controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Series data", @@ -100,6 +105,7 @@ export default [ controlType: "INPUT_TEXT_AREA", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.CHART_DATA, }, ], }, @@ -118,6 +124,7 @@ export default [ controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Specifies the label of the y-axis", @@ -127,6 +134,7 @@ export default [ controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Enables scrolling inside the chart", diff --git a/app/client/src/widgets/CheckboxWidget.tsx b/app/client/src/widgets/CheckboxWidget.tsx index 361ab3df63..ec99b3b486 100644 --- a/app/client/src/widgets/CheckboxWidget.tsx +++ b/app/client/src/widgets/CheckboxWidget.tsx @@ -4,10 +4,6 @@ import { WidgetType } from "constants/WidgetConstants"; import CheckboxComponent from "components/designSystems/blueprint/CheckboxComponent"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; @@ -27,6 +23,7 @@ class CheckboxWidget extends BaseWidget { placeholderText: "Enter label text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "alignWidget", @@ -55,6 +52,7 @@ class CheckboxWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isRequired", @@ -64,6 +62,7 @@ class CheckboxWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -73,6 +72,7 @@ class CheckboxWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -82,6 +82,7 @@ class CheckboxWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -101,14 +102,6 @@ class CheckboxWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - label: VALIDATION_TYPES.TEXT, - defaultCheckedState: VALIDATION_TYPES.BOOLEAN, - // onCheckChange: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } static getDefaultPropertiesMap(): Record { return { diff --git a/app/client/src/widgets/ContainerWidget.tsx b/app/client/src/widgets/ContainerWidget.tsx index 0d3d7f56ca..39667e11cb 100644 --- a/app/client/src/widgets/ContainerWidget.tsx +++ b/app/client/src/widgets/ContainerWidget.tsx @@ -14,6 +14,7 @@ import { import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import * as Sentry from "@sentry/react"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; class ContainerWidget extends BaseWidget< ContainerWidgetProps, @@ -37,6 +38,7 @@ class ContainerWidget extends BaseWidget< controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Controls the visibility of the widget", @@ -46,6 +48,7 @@ class ContainerWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "shouldScrollContents", diff --git a/app/client/src/widgets/DatePickerWidget.tsx b/app/client/src/widgets/DatePickerWidget.tsx index ff3651239d..8cf5748e77 100644 --- a/app/client/src/widgets/DatePickerWidget.tsx +++ b/app/client/src/widgets/DatePickerWidget.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import * as Sentry from "@sentry/react"; @@ -29,6 +25,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DEFAULT_DATE, }, { helpText: "Sets the format of the selected date", @@ -60,6 +57,7 @@ class DatePickerWidget extends BaseWidget { ], isBindProperty: true, isTriggerProperty: false, + dateFormat: VALIDATION_TYPES.TEXT, }, { propertyName: "isRequired", @@ -69,6 +67,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -78,6 +77,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -87,6 +87,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "minDate", @@ -96,6 +97,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.MIN_DATE, }, { propertyName: "maxDate", @@ -105,6 +107,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.MAX_DATE, }, ], }, @@ -123,22 +126,6 @@ class DatePickerWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - defaultDate: VALIDATION_TYPES.DEFAULT_DATE, - timezone: VALIDATION_TYPES.TEXT, - enableTimePicker: VALIDATION_TYPES.BOOLEAN, - dateFormat: VALIDATION_TYPES.TEXT, - label: VALIDATION_TYPES.TEXT, - datePickerType: VALIDATION_TYPES.TEXT, - maxDate: VALIDATION_TYPES.MAX_DATE, - minDate: VALIDATION_TYPES.MIN_DATE, - isRequired: VALIDATION_TYPES.BOOLEAN, - // onDateSelected: VALIDATION_TYPES.ACTION_SELECTOR, - // onDateRangeSelected: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } static getDerivedPropertiesMap(): DerivedPropertiesMap { return { diff --git a/app/client/src/widgets/DatePickerWidget2.tsx b/app/client/src/widgets/DatePickerWidget2.tsx index ab0528b4d9..6a98b7d0bf 100644 --- a/app/client/src/widgets/DatePickerWidget2.tsx +++ b/app/client/src/widgets/DatePickerWidget2.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import DatePickerComponent from "components/designSystems/blueprint/DatePickerComponent2"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import * as Sentry from "@sentry/react"; @@ -30,6 +26,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DEFAULT_DATE, }, { helpText: "Sets the format of the selected date", @@ -122,6 +119,7 @@ class DatePickerWidget extends BaseWidget { ], isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "isRequired", @@ -131,6 +129,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -140,6 +139,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -149,6 +149,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "minDate", @@ -159,6 +160,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DATE_ISO_STRING, }, { propertyName: "maxDate", @@ -169,6 +171,7 @@ class DatePickerWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DATE_ISO_STRING, }, ], }, @@ -188,23 +191,6 @@ class DatePickerWidget extends BaseWidget { ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - defaultDate: VALIDATION_TYPES.DEFAULT_DATE, - timezone: VALIDATION_TYPES.TEXT, - enableTimePicker: VALIDATION_TYPES.BOOLEAN, - dateFormat: VALIDATION_TYPES.TEXT, - label: VALIDATION_TYPES.TEXT, - datePickerType: VALIDATION_TYPES.TEXT, - maxDate: VALIDATION_TYPES.DATE_ISO_STRING, - minDate: VALIDATION_TYPES.DATE_ISO_STRING, - isRequired: VALIDATION_TYPES.BOOLEAN, - // onDateSelected: VALIDATION_TYPES.ACTION_SELECTOR, - // onDateRangeSelected: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } - static getDerivedPropertiesMap(): DerivedPropertiesMap { return { isValid: `{{ this.isRequired ? !!this.selectedDate : true }}`, diff --git a/app/client/src/widgets/DropdownWidget.tsx b/app/client/src/widgets/DropdownWidget.tsx index d4adbd943b..cf56553bab 100644 --- a/app/client/src/widgets/DropdownWidget.tsx +++ b/app/client/src/widgets/DropdownWidget.tsx @@ -4,10 +4,6 @@ import { WidgetType } from "constants/WidgetConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import DropDownComponent from "components/designSystems/blueprint/DropdownComponent"; import _ from "lodash"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { Intent as BlueprintIntent } from "@blueprintjs/core"; import * as Sentry from "@sentry/react"; @@ -48,6 +44,7 @@ class DropdownWidget extends BaseWidget { placeholderText: 'Enter [{label: "label1", value: "value2"}]', isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.OPTIONS_DATA, }, { helpText: "Selects the option with value by default", @@ -57,6 +54,7 @@ class DropdownWidget extends BaseWidget { placeholderText: "Enter option value", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DEFAULT_OPTION_VALUE, }, { propertyName: "isRequired", @@ -66,6 +64,7 @@ class DropdownWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Controls the visibility of the widget", @@ -75,6 +74,7 @@ class DropdownWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -84,6 +84,7 @@ class DropdownWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -103,21 +104,6 @@ class DropdownWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - placeholderText: VALIDATION_TYPES.TEXT, - label: VALIDATION_TYPES.TEXT, - options: VALIDATION_TYPES.OPTIONS_DATA, - selectionType: VALIDATION_TYPES.TEXT, - isRequired: VALIDATION_TYPES.BOOLEAN, - // onOptionChange: VALIDATION_TYPES.ACTION_SELECTOR, - selectedOptionValues: VALIDATION_TYPES.ARRAY, - selectedOptionLabels: VALIDATION_TYPES.ARRAY, - selectedOptionLabel: VALIDATION_TYPES.TEXT, - defaultOptionValue: VALIDATION_TYPES.DEFAULT_OPTION_VALUE, - }; - } static getDerivedPropertiesMap() { return { diff --git a/app/client/src/widgets/FilepickerWidget.tsx b/app/client/src/widgets/FilepickerWidget.tsx index 2fbc092f94..f8a7a57cff 100644 --- a/app/client/src/widgets/FilepickerWidget.tsx +++ b/app/client/src/widgets/FilepickerWidget.tsx @@ -7,10 +7,6 @@ import GoogleDrive from "@uppy/google-drive"; import Webcam from "@uppy/webcam"; import Url from "@uppy/url"; import OneDrive from "@uppy/onedrive"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { EventType, @@ -50,6 +46,7 @@ class FilePickerWidget extends BaseWidget< inputType: "TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "maxNumFiles", @@ -61,6 +58,7 @@ class FilePickerWidget extends BaseWidget< inputType: "INTEGER", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.NUMBER, }, { propertyName: "maxFileSize", @@ -115,6 +113,7 @@ class FilePickerWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.ARRAY, }, { helpText: "Set the format of the data read from the files", @@ -146,6 +145,7 @@ class FilePickerWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -155,6 +155,7 @@ class FilePickerWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "uploadedFileUrlPaths", @@ -175,6 +176,7 @@ class FilePickerWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -195,17 +197,6 @@ class FilePickerWidget extends BaseWidget< }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - label: VALIDATION_TYPES.TEXT, - maxNumFiles: VALIDATION_TYPES.NUMBER, - allowedFileTypes: VALIDATION_TYPES.ARRAY, - selectedFiles: VALIDATION_TYPES.ARRAY, - isRequired: VALIDATION_TYPES.BOOLEAN, - // onFilesSelected: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } static getDerivedPropertiesMap(): DerivedPropertiesMap { return { diff --git a/app/client/src/widgets/FormButtonWidget.tsx b/app/client/src/widgets/FormButtonWidget.tsx index 10fd49fe5f..6afa8477dd 100644 --- a/app/client/src/widgets/FormButtonWidget.tsx +++ b/app/client/src/widgets/FormButtonWidget.tsx @@ -8,10 +8,6 @@ import { EventType, ExecutionResult, } from "constants/AppsmithActionConstants/ActionConstants"; -import { - BASE_WIDGET_VALIDATION, - WidgetPropertyValidationType, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; @@ -45,6 +41,7 @@ class FormButtonWidget extends BaseWidget< placeholderText: "Enter label text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "buttonStyle", @@ -86,6 +83,7 @@ class FormButtonWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -95,6 +93,7 @@ class FormButtonWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "googleRecaptchaKey", @@ -104,6 +103,7 @@ class FormButtonWidget extends BaseWidget< placeholderText: "Enter google recaptcha key", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, ], }, @@ -130,16 +130,6 @@ class FormButtonWidget extends BaseWidget< }; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - text: VALIDATION_TYPES.TEXT, - disabledWhenInvalid: VALIDATION_TYPES.BOOLEAN, - buttonStyle: VALIDATION_TYPES.TEXT, - buttonType: VALIDATION_TYPES.TEXT, - }; - } - clickWithRecaptcha(token: string) { if (this.props.onClick) { this.setState({ diff --git a/app/client/src/widgets/FormWidget.tsx b/app/client/src/widgets/FormWidget.tsx index 80f3889d1b..dfc2450c0e 100644 --- a/app/client/src/widgets/FormWidget.tsx +++ b/app/client/src/widgets/FormWidget.tsx @@ -6,6 +6,7 @@ import ContainerWidget, { ContainerWidgetProps } from "widgets/ContainerWidget"; import { ContainerComponentProps } from "components/designSystems/appsmith/ContainerComponent"; import * as Sentry from "@sentry/react"; import withMeta from "./MetaHOC"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; class FormWidget extends ContainerWidget { static getPropertyPaneConfig() { @@ -21,6 +22,7 @@ class FormWidget extends ContainerWidget { controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Controls the visibility of the widget", @@ -30,6 +32,7 @@ class FormWidget extends ContainerWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "shouldScrollContents", diff --git a/app/client/src/widgets/ImageWidget.tsx b/app/client/src/widgets/ImageWidget.tsx index 3eb5fcfe6d..b285fb4ade 100644 --- a/app/client/src/widgets/ImageWidget.tsx +++ b/app/client/src/widgets/ImageWidget.tsx @@ -2,10 +2,6 @@ import * as React from "react"; import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType, RenderModes } from "constants/WidgetConstants"; import ImageComponent from "components/designSystems/appsmith/ImageComponent"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import * as Sentry from "@sentry/react"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; @@ -28,6 +24,7 @@ class ImageWidget extends BaseWidget { placeholderText: "Enter URL / Base64", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Renders the url or Base64 when no image is provided", @@ -37,6 +34,7 @@ class ImageWidget extends BaseWidget { placeholderText: "Enter URL / Base64", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Controls the visibility of the widget", @@ -46,6 +44,7 @@ class ImageWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Controls the max zoom of the widget", @@ -77,6 +76,7 @@ class ImageWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.NUMBER, }, ], }, @@ -97,15 +97,6 @@ class ImageWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - image: VALIDATION_TYPES.TEXT, - imageShape: VALIDATION_TYPES.TEXT, - defaultImage: VALIDATION_TYPES.TEXT, - maxZoomLevel: VALIDATION_TYPES.NUMBER, - }; - } getPageView() { const { maxZoomLevel } = this.props; return ( diff --git a/app/client/src/widgets/InputWidget.tsx b/app/client/src/widgets/InputWidget.tsx index 12c6b8af8d..0dfa1550ef 100644 --- a/app/client/src/widgets/InputWidget.tsx +++ b/app/client/src/widgets/InputWidget.tsx @@ -8,10 +8,6 @@ import { EventType, ExecutionResult, } from "constants/AppsmithActionConstants/ActionConstants"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { createMessage, FIELD_REQUIRED_ERROR } from "constants/messages"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; @@ -65,6 +61,7 @@ class InputWidget extends BaseWidget { placeholderText: "Enter default text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Sets a placeholder text for the input", @@ -74,6 +71,7 @@ class InputWidget extends BaseWidget { placeholderText: "Enter placeholder text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: @@ -85,6 +83,7 @@ class InputWidget extends BaseWidget { inputType: "TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.REGEX, }, { helpText: @@ -96,6 +95,7 @@ class InputWidget extends BaseWidget { inputType: "TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "isRequired", @@ -105,6 +105,7 @@ class InputWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Controls the visibility of the widget", @@ -114,6 +115,7 @@ class InputWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Disables input to this widget", @@ -123,6 +125,7 @@ class InputWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Clears the input value after submit", @@ -132,6 +135,7 @@ class InputWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -161,29 +165,6 @@ class InputWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - inputType: VALIDATION_TYPES.TEXT, - defaultText: VALIDATION_TYPES.TEXT, - isDisabled: VALIDATION_TYPES.BOOLEAN, - text: VALIDATION_TYPES.TEXT, - regex: VALIDATION_TYPES.REGEX, - errorMessage: VALIDATION_TYPES.TEXT, - placeholderText: VALIDATION_TYPES.TEXT, - maxChars: VALIDATION_TYPES.NUMBER, - minNum: VALIDATION_TYPES.NUMBER, - maxNum: VALIDATION_TYPES.NUMBER, - label: VALIDATION_TYPES.TEXT, - inputValidators: VALIDATION_TYPES.ARRAY, - focusIndex: VALIDATION_TYPES.NUMBER, - isAutoFocusEnabled: VALIDATION_TYPES.BOOLEAN, - // onTextChanged: VALIDATION_TYPES.ACTION_SELECTOR, - isRequired: VALIDATION_TYPES.BOOLEAN, - isValid: VALIDATION_TYPES.BOOLEAN, - resetOnSubmit: VALIDATION_TYPES.BOOLEAN, - }; - } static getDerivedPropertiesMap(): DerivedPropertiesMap { return { diff --git a/app/client/src/widgets/MapWidget.tsx b/app/client/src/widgets/MapWidget.tsx index 12d28a472b..c9c30443fc 100644 --- a/app/client/src/widgets/MapWidget.tsx +++ b/app/client/src/widgets/MapWidget.tsx @@ -2,7 +2,6 @@ import React from "react"; import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import MapComponent from "components/designSystems/appsmith/MapComponent"; -import { WidgetPropertyValidationType } from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { getAppsmithConfigs } from "configs"; @@ -52,6 +51,7 @@ class MapWidget extends BaseWidget { controlType: "LOCATION_SEARCH", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.LAT_LONG, }, { propertyName: "defaultMarkers", @@ -62,6 +62,7 @@ class MapWidget extends BaseWidget { placeholderText: 'Enter [{ "lat": "val1", "long": "val2" }]', isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.MARKERS, }, { propertyName: "enableSearch", @@ -104,6 +105,7 @@ class MapWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -130,19 +132,6 @@ class MapWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - defaultMarkers: VALIDATION_TYPES.MARKERS, - isDisabled: VALIDATION_TYPES.BOOLEAN, - isVisible: VALIDATION_TYPES.BOOLEAN, - enableSearch: VALIDATION_TYPES.BOOLEAN, - enablePickLocation: VALIDATION_TYPES.BOOLEAN, - enableCreateMarker: VALIDATION_TYPES.BOOLEAN, - allowZoom: VALIDATION_TYPES.BOOLEAN, - zoomLevel: VALIDATION_TYPES.NUMBER, - mapCenter: VALIDATION_TYPES.LAT_LONG, - }; - } static getDefaultPropertiesMap(): Record { return { diff --git a/app/client/src/widgets/RadioGroupWidget.tsx b/app/client/src/widgets/RadioGroupWidget.tsx index 1cc37328eb..a5334611af 100644 --- a/app/client/src/widgets/RadioGroupWidget.tsx +++ b/app/client/src/widgets/RadioGroupWidget.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import RadioGroupComponent from "components/designSystems/blueprint/RadioGroupComponent"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; @@ -26,6 +22,7 @@ class RadioGroupWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.OPTIONS_DATA, }, { helpText: "Selects a value of the options entered by default", @@ -35,6 +32,7 @@ class RadioGroupWidget extends BaseWidget { controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "isRequired", @@ -44,6 +42,7 @@ class RadioGroupWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Controls the visibility of the widget", @@ -53,6 +52,7 @@ class RadioGroupWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -62,6 +62,7 @@ class RadioGroupWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -82,17 +83,6 @@ class RadioGroupWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - label: VALIDATION_TYPES.TEXT, - options: VALIDATION_TYPES.OPTIONS_DATA, - selectedOptionValue: VALIDATION_TYPES.TEXT, - defaultOptionValue: VALIDATION_TYPES.TEXT, - isRequired: VALIDATION_TYPES.BOOLEAN, - // onSelectionChange: VALIDATION_TYPES.ACTION_SELECTOR, - }; - } static getDerivedPropertiesMap() { return { selectedOption: diff --git a/app/client/src/widgets/RichTextEditorWidget.tsx b/app/client/src/widgets/RichTextEditorWidget.tsx index 86b85a5361..5957e647dc 100644 --- a/app/client/src/widgets/RichTextEditorWidget.tsx +++ b/app/client/src/widgets/RichTextEditorWidget.tsx @@ -2,7 +2,6 @@ import React, { lazy, Suspense } from "react"; import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; -import { WidgetPropertyValidationType } from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import Skeleton from "components/utils/Skeleton"; @@ -60,6 +59,7 @@ class RichTextEditorWidget extends BaseWidget< placeholderText: "Enter HTML", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "isVisible", @@ -69,6 +69,7 @@ class RichTextEditorWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -78,6 +79,7 @@ class RichTextEditorWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -97,14 +99,6 @@ class RichTextEditorWidget extends BaseWidget< }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - placeholder: VALIDATION_TYPES.TEXT, - defaultText: VALIDATION_TYPES.TEXT, - isDisabled: VALIDATION_TYPES.BOOLEAN, - isVisible: VALIDATION_TYPES.BOOLEAN, - }; - } static getMetaPropertiesMap(): Record { return { diff --git a/app/client/src/widgets/SwitchWidget.tsx b/app/client/src/widgets/SwitchWidget.tsx index 898b048772..e64223c7fd 100644 --- a/app/client/src/widgets/SwitchWidget.tsx +++ b/app/client/src/widgets/SwitchWidget.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; -import { - BASE_WIDGET_VALIDATION, - WidgetPropertyValidationType, -} from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import { SwitchComponent } from "components/designSystems/blueprint/SwitchComponent"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; @@ -26,6 +22,7 @@ class SwitchWidget extends BaseWidget { placeholderText: "Enter label text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "alignWidget", @@ -54,6 +51,7 @@ class SwitchWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isVisible", @@ -63,6 +61,7 @@ class SwitchWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "isDisabled", @@ -72,6 +71,7 @@ class SwitchWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -110,14 +110,6 @@ class SwitchWidget extends BaseWidget { return "SWITCH_WIDGET"; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - label: VALIDATION_TYPES.TEXT, - defaultSwitchState: VALIDATION_TYPES.BOOLEAN, - }; - } - static getDefaultPropertiesMap(): Record { return { isSwitchedOn: "defaultSwitchState", diff --git a/app/client/src/widgets/TableWidget/TablePropertyPaneConfig.ts b/app/client/src/widgets/TableWidget/TablePropertyPaneConfig.ts index d2ae80c08e..2273b8ed17 100644 --- a/app/client/src/widgets/TableWidget/TablePropertyPaneConfig.ts +++ b/app/client/src/widgets/TableWidget/TablePropertyPaneConfig.ts @@ -2,6 +2,7 @@ import { get } from "lodash"; import { Colors } from "constants/Colors"; import { ColumnProperties } from "components/designSystems/appsmith/TableComponent/Constants"; import { TableWidgetProps } from "./TableWidgetConstants"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; // A hook to update all column styles when global table styles are updated const updateColumnStyles = ( @@ -142,6 +143,7 @@ export default [ inputType: "ARRAY", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TABLE_DATA, }, { helpText: "Columns", @@ -637,6 +639,7 @@ export default [ placeholderText: "Enter default search text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { helpText: "Selects the default selected row", @@ -646,6 +649,7 @@ export default [ placeholderText: "Enter row index", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.DEFAULT_SELECTED_ROW, }, { helpText: @@ -664,6 +668,7 @@ export default [ controlType: "SWITCH", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { propertyName: "multiRowSelection", diff --git a/app/client/src/widgets/TableWidget/index.tsx b/app/client/src/widgets/TableWidget/index.tsx index 77aaa693fe..1f96a11805 100644 --- a/app/client/src/widgets/TableWidget/index.tsx +++ b/app/client/src/widgets/TableWidget/index.tsx @@ -10,11 +10,6 @@ import { renderActions, } from "components/designSystems/appsmith/TableComponent/TableUtilities"; import { getAllTableColumnKeys } from "components/designSystems/appsmith/TableComponent/TableHelpers"; -import { VALIDATION_TYPES } from "constants/WidgetValidation"; -import { - BASE_WIDGET_VALIDATION, - WidgetPropertyValidationType, -} from "utils/WidgetValidation"; import Skeleton from "components/utils/Skeleton"; import moment from "moment"; import { isNumber, isString, isNil, isEqual, xor, without } from "lodash"; @@ -45,22 +40,6 @@ const ReactTableComponent = lazy(() => ); class TableWidget extends BaseWidget { - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - tableData: VALIDATION_TYPES.TABLE_DATA, - nextPageKey: VALIDATION_TYPES.TEXT, - prevPageKey: VALIDATION_TYPES.TEXT, - label: VALIDATION_TYPES.TEXT, - searchText: VALIDATION_TYPES.TEXT, - defaultSearchText: VALIDATION_TYPES.TEXT, - defaultSelectedRow: VALIDATION_TYPES.DEFAULT_SELECTED_ROW, - pageSize: VALIDATION_TYPES.NUMBER, - selectedRowIndices: VALIDATION_TYPES.ROW_INDICES, - pageNo: VALIDATION_TYPES.TABLE_PAGE_NO, - }; - } - static getPropertyPaneConfig() { return tablePropertyPaneConfig; } diff --git a/app/client/src/widgets/TabsWidget.tsx b/app/client/src/widgets/TabsWidget.tsx index a9159423d8..4e123ebee4 100644 --- a/app/client/src/widgets/TabsWidget.tsx +++ b/app/client/src/widgets/TabsWidget.tsx @@ -3,7 +3,6 @@ import TabsComponent from "components/designSystems/appsmith/TabsComponent"; import { WidgetType, WidgetTypes } from "constants/WidgetConstants"; import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import WidgetFactory from "utils/WidgetFactory"; -import { WidgetPropertyValidationType } from "utils/WidgetValidation"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; import _ from "lodash"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; @@ -29,6 +28,7 @@ class TabsWidget extends BaseWidget< controlType: "TABS_INPUT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TABS_DATA, }, { propertyName: "defaultTab", @@ -38,6 +38,7 @@ class TabsWidget extends BaseWidget< controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.SELECTED_TAB, }, { propertyName: "shouldShowTabs", @@ -63,6 +64,7 @@ class TabsWidget extends BaseWidget< isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -82,12 +84,6 @@ class TabsWidget extends BaseWidget< }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - tabs: VALIDATION_TYPES.TABS_DATA, - defaultTab: VALIDATION_TYPES.SELECTED_TAB, - }; - } onTabChange = (tabWidgetId: string) => { this.props.updateWidgetMetaProperty("selectedTabWidgetId", tabWidgetId, { diff --git a/app/client/src/widgets/TextWidget.tsx b/app/client/src/widgets/TextWidget.tsx index 90b8603064..0ccc039c68 100644 --- a/app/client/src/widgets/TextWidget.tsx +++ b/app/client/src/widgets/TextWidget.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType, TextSize } from "constants/WidgetConstants"; import TextComponent from "components/designSystems/blueprint/TextComponent"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import * as Sentry from "@sentry/react"; @@ -24,6 +20,7 @@ class TextWidget extends BaseWidget { placeholderText: "Enter text", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "shouldScroll", @@ -41,6 +38,7 @@ class TextWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -143,14 +141,6 @@ class TextWidget extends BaseWidget { }, ]; } - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - text: VALIDATION_TYPES.TEXT, - textStyle: VALIDATION_TYPES.TEXT, - shouldScroll: VALIDATION_TYPES.BOOLEAN, - }; - } getPageView() { return ( diff --git a/app/client/src/widgets/VideoWidget.tsx b/app/client/src/widgets/VideoWidget.tsx index 1f56fa0994..f0a1d0895c 100644 --- a/app/client/src/widgets/VideoWidget.tsx +++ b/app/client/src/widgets/VideoWidget.tsx @@ -3,10 +3,6 @@ import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget"; import { WidgetType } from "constants/WidgetConstants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { VALIDATION_TYPES } from "constants/WidgetValidation"; -import { - WidgetPropertyValidationType, - BASE_WIDGET_VALIDATION, -} from "utils/WidgetValidation"; import Skeleton from "components/utils/Skeleton"; import * as Sentry from "@sentry/react"; import { retryPromise } from "utils/AppsmithUtils"; @@ -40,6 +36,7 @@ class VideoWidget extends BaseWidget { inputType: "TEXT", isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.TEXT, }, { propertyName: "autoPlay", @@ -49,6 +46,7 @@ class VideoWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, { helpText: "Controls the visibility of the widget", @@ -58,6 +56,7 @@ class VideoWidget extends BaseWidget { isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, + validation: VALIDATION_TYPES.BOOLEAN, }, ], }, @@ -96,12 +95,6 @@ class VideoWidget extends BaseWidget { ]; } private _player = React.createRef(); - static getPropertyValidationMap(): WidgetPropertyValidationType { - return { - ...BASE_WIDGET_VALIDATION, - url: VALIDATION_TYPES.TEXT, - }; - } static getMetaPropertiesMap(): Record { return { diff --git a/app/client/src/workers/DataTreeEvaluator.ts b/app/client/src/workers/DataTreeEvaluator.ts index f32995e889..1a724726de 100644 --- a/app/client/src/workers/DataTreeEvaluator.ts +++ b/app/client/src/workers/DataTreeEvaluator.ts @@ -24,6 +24,7 @@ import { CrashingError, DataTreeDiffEvent, getAllPaths, + getEntityNameAndPropertyPath, getImmediateParentsOfPropertyPaths, getValidatedTree, makeParentsDependOnChildren, @@ -86,7 +87,7 @@ export default class DataTreeEvaluator { const evaluateEnd = performance.now(); // Validate Widgets const validateStart = performance.now(); - this.evalTree = getValidatedTree(this.widgetConfigMap, evaluatedTree); + this.evalTree = getValidatedTree(evaluatedTree); const validateEnd = performance.now(); this.oldUnEvalTree = unEvalTree; @@ -350,24 +351,25 @@ export default class DataTreeEvaluator { const tree = _.cloneDeep(oldUnevalTree); try { return sortedDependencies.reduce( - (currentTree: DataTree, propertyPath: string) => { - this.logs.push(`evaluating ${propertyPath}`); - const entityName = propertyPath.split(".")[0]; + (currentTree: DataTree, fullPropertyPath: string) => { + this.logs.push(`evaluating ${fullPropertyPath}`); + const { entityName, propertyPath } = getEntityNameAndPropertyPath( + fullPropertyPath, + ); const entity: DataTreeEntity = currentTree[entityName]; - const unEvalPropertyValue = _.get(currentTree as any, propertyPath); + const unEvalPropertyValue = _.get( + currentTree as any, + fullPropertyPath, + ); const isABindingPath = (isAction(entity) || isWidget(entity)) && - isPathADynamicBinding( - entity, - propertyPath.substring(propertyPath.indexOf(".") + 1), - ); + isPathADynamicBinding(entity, propertyPath); let evalPropertyValue; const requiresEval = isABindingPath && isDynamicValue(unEvalPropertyValue); if (requiresEval) { try { evalPropertyValue = this.evaluateDynamicProperty( - propertyPath, currentTree, unEvalPropertyValue, ); @@ -376,7 +378,7 @@ export default class DataTreeEvaluator { type: EvalErrorTypes.EVAL_PROPERTY_ERROR, message: e.message, context: { - propertyPath, + propertyPath: fullPropertyPath, }, }); evalPropertyValue = undefined; @@ -386,42 +388,37 @@ export default class DataTreeEvaluator { } if (isWidget(entity)) { const widgetEntity = entity; - // TODO fix for nested properties - // For nested properties like Table1.selectedRow.email - // The following line will calculated the property name to be selectedRow - // instead of selectedRow.email - const propertyName = propertyPath.split(".")[1]; const defaultPropertyMap = this.widgetConfigMap[widgetEntity.type] .defaultProperties; const isDefaultProperty = !!Object.values( defaultPropertyMap, ).filter( - (defaultPropertyName) => propertyName === defaultPropertyName, + (defaultPropertyName) => propertyPath === defaultPropertyName, ).length; - if (propertyName) { + if (propertyPath) { let parsedValue = this.validateAndParseWidgetProperty( - propertyPath, + fullPropertyPath, widgetEntity, currentTree, evalPropertyValue, unEvalPropertyValue, isDefaultProperty, ); - const hasDefaultProperty = propertyName in defaultPropertyMap; + const hasDefaultProperty = propertyPath in defaultPropertyMap; if (hasDefaultProperty) { - const defaultProperty = defaultPropertyMap[propertyName]; + const defaultProperty = defaultPropertyMap[propertyPath]; parsedValue = this.overwriteDefaultDependentProps( defaultProperty, parsedValue, - propertyPath, + fullPropertyPath, widgetEntity, ); } - return _.set(currentTree, propertyPath, parsedValue); + return _.set(currentTree, fullPropertyPath, parsedValue); } - return _.set(currentTree, propertyPath, evalPropertyValue); + return _.set(currentTree, fullPropertyPath, evalPropertyValue); } else { - return _.set(currentTree, propertyPath, evalPropertyValue); + return _.set(currentTree, fullPropertyPath, evalPropertyValue); } }, tree, @@ -573,7 +570,6 @@ export default class DataTreeEvaluator { } evaluateDynamicProperty( - propertyPath: string, currentTree: DataTree, unEvalPropertyValue: any, ): any { @@ -581,14 +577,14 @@ export default class DataTreeEvaluator { } validateAndParseWidgetProperty( - propertyPath: string, + fullPropertyPath: string, widget: DataTreeWidget, currentTree: DataTree, evalPropertyValue: any, unEvalPropertyValue: string, isDefaultProperty: boolean, ): any { - const entityPropertyName = _.drop(propertyPath.split(".")).join("."); + const { propertyPath } = getEntityNameAndPropertyPath(fullPropertyPath); let valueToValidate = evalPropertyValue; if (isPathADynamicTrigger(widget, propertyPath)) { const { triggers } = this.getDynamicValue( @@ -599,12 +595,12 @@ export default class DataTreeEvaluator { ); valueToValidate = triggers; } + const validation = widget.validationPaths[propertyPath]; const { parsed, isValid, message, transformed } = validateWidgetProperty( - this.widgetConfigMap, - widget.type, - entityPropertyName, + propertyPath, valueToValidate, widget, + validation, currentTree, ); const evaluatedValue = isValid @@ -613,23 +609,23 @@ export default class DataTreeEvaluator { ? evalPropertyValue : transformed; const safeEvaluatedValue = removeFunctions(evaluatedValue); - _.set(widget, `evaluatedValues.${entityPropertyName}`, safeEvaluatedValue); + _.set(widget, `evaluatedValues.${propertyPath}`, safeEvaluatedValue); if (!isValid) { - _.set(widget, `invalidProps.${entityPropertyName}`, true); - _.set(widget, `validationMessages.${entityPropertyName}`, message); + _.set(widget, `invalidProps.${propertyPath}`, true); + _.set(widget, `validationMessages.${propertyPath}`, message); } else { - _.set(widget, `invalidProps.${entityPropertyName}`, false); - _.set(widget, `validationMessages.${entityPropertyName}`, ""); + _.set(widget, `invalidProps.${propertyPath}`, false); + _.set(widget, `validationMessages.${propertyPath}`, ""); } - if (isPathADynamicTrigger(widget, entityPropertyName)) { + if (isPathADynamicTrigger(widget, propertyPath)) { return unEvalPropertyValue; } else { - const parsedCache = this.getParsedValueCache(propertyPath); + const parsedCache = this.getParsedValueCache(fullPropertyPath); // In case this is a default property, always set the cache even if the value remains the same so that the version // in cache gets updated and the property dependent on default property updates accordingly. if (!equal(parsedCache.value, parsed) || isDefaultProperty) { - this.parsedValueCache.set(propertyPath, { + this.parsedValueCache.set(fullPropertyPath, { value: parsed, version: Date.now(), }); diff --git a/app/client/src/workers/evaluate.test.ts b/app/client/src/workers/evaluate.test.ts index c07c7a3a79..d658e35fc4 100644 --- a/app/client/src/workers/evaluate.test.ts +++ b/app/client/src/workers/evaluate.test.ts @@ -24,6 +24,7 @@ describe("evaluate", () => { ENTITY_TYPE: ENTITY_TYPE.WIDGET, bindingPaths: {}, triggerPaths: {}, + validationPaths: {}, }; const dataTree: DataTree = { Input1: widget, diff --git a/app/client/src/workers/evaluation.test.ts b/app/client/src/workers/evaluation.test.ts index 519d500603..bfda076995 100644 --- a/app/client/src/workers/evaluation.test.ts +++ b/app/client/src/workers/evaluation.test.ts @@ -7,27 +7,15 @@ import { WidgetTypeConfigMap } from "../utils/WidgetFactory"; import { RenderModes, WidgetTypes } from "../constants/WidgetConstants"; import { PluginType } from "../entities/Action"; import DataTreeEvaluator from "workers/DataTreeEvaluator"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { CONTAINER_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, TEXT_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - text: "TEXT", - textStyle: "TEXT", - shouldScroll: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: { value: "{{ this.text }}", @@ -35,38 +23,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, BUTTON_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - text: "TEXT", - buttonStyle: "TEXT", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, INPUT_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - inputType: "TEXT", - defaultText: "TEXT", - text: "TEXT", - regex: "REGEX", - errorMessage: "TEXT", - placeholderText: "TEXT", - maxChars: "NUMBER", - minNum: "NUMBER", - maxNum: "NUMBER", - label: "TEXT", - inputValidators: "ARRAY", - focusIndex: "NUMBER", - isAutoFocusEnabled: "BOOLEAN", - isRequired: "BOOLEAN", - isValid: "BOOLEAN", - }, defaultProperties: { text: "defaultText", }, @@ -81,13 +42,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { }, }, CHECKBOX_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - label: "TEXT", - defaultCheckedState: "BOOLEAN", - }, defaultProperties: { isChecked: "defaultCheckedState", }, @@ -97,18 +51,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, DROP_DOWN_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - placeholderText: "TEXT", - label: "TEXT", - options: "OPTIONS_DATA", - selectionType: "TEXT", - isRequired: "BOOLEAN", - selectedOptionValues: "ARRAY", - defaultOptionValue: "DEFAULT_OPTION_VALUE", - }, defaultProperties: { selectedOptionValue: "defaultOptionValue", selectedOptionValueArr: "defaultOptionValue", @@ -131,16 +73,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, RADIO_GROUP_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - label: "TEXT", - options: "OPTIONS_DATA", - selectedOptionValue: "TEXT", - defaultOptionValue: "TEXT", - isRequired: "BOOLEAN", - }, defaultProperties: { selectedOptionValue: "defaultOptionValue", }, @@ -153,32 +85,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, IMAGE_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - image: "TEXT", - imageShape: "TEXT", - defaultImage: "TEXT", - maxZoomLevel: "NUMBER", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, TABLE_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - tableData: "TABLE_DATA", - nextPageKey: "TEXT", - prevPageKey: "TEXT", - label: "TEXT", - searchText: "TEXT", - defaultSearchText: "TEXT", - defaultSelectedRow: "DEFAULT_SELECTED_ROW", - }, defaultProperties: { searchText: "defaultSearchText", selectedRowIndex: "defaultSelectedRow", @@ -195,12 +106,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { }, }, VIDEO_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - url: "TEXT", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: { @@ -208,16 +113,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { }, }, FILE_PICKER_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - label: "TEXT", - maxNumFiles: "NUMBER", - allowedFileTypes: "ARRAY", - files: "ARRAY", - isRequired: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: { isValid: "{{ this.isRequired ? this.files.length > 0 : true }}", @@ -229,20 +124,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { }, }, DATE_PICKER_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - defaultDate: "DATE", - timezone: "TEXT", - enableTimePicker: "BOOLEAN", - dateFormat: "TEXT", - label: "TEXT", - datePickerType: "TEXT", - maxDate: "DATE", - minDate: "DATE", - isRequired: "BOOLEAN", - }, defaultProperties: { selectedDate: "defaultDate", }, @@ -253,20 +134,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, DATE_PICKER_WIDGET2: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - defaultDate: "DATE", - timezone: "TEXT", - enableTimePicker: "BOOLEAN", - dateFormat: "TEXT", - label: "TEXT", - datePickerType: "TEXT", - maxDate: "DATE", - minDate: "DATE", - isRequired: "BOOLEAN", - }, defaultProperties: { selectedDate: "defaultDate", }, @@ -277,10 +144,6 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, TABS_WIDGET: { - validations: { - tabs: "TABS_DATA", - defaultTab: "SELECTED_TAB", - }, defaultProperties: {}, derivedProperties: { selectedTab: @@ -289,23 +152,11 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, MODAL_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, RICH_TEXT_EDITOR_WIDGET: { - validations: { - text: "TEXT", - placeholder: "TEXT", - defaultValue: "TEXT", - isDisabled: "BOOLEAN", - isVisible: "BOOLEAN", - }, defaultProperties: { text: "defaultText", }, @@ -315,52 +166,21 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, CHART_WIDGET: { - validations: { - xAxisName: "TEXT", - yAxisName: "TEXT", - chartName: "TEXT", - isVisible: "BOOLEAN", - chartData: "CHART_DATA", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, FORM_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, FORM_BUTTON_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - text: "TEXT", - disabledWhenInvalid: "BOOLEAN", - buttonStyle: "TEXT", - buttonType: "TEXT", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, MAP_WIDGET: { - validations: { - defaultMarkers: "MARKERS", - isDisabled: "BOOLEAN", - isVisible: "BOOLEAN", - enableSearch: "BOOLEAN", - enablePickLocation: "BOOLEAN", - allowZoom: "BOOLEAN", - zoomLevel: "NUMBER", - mapCenter: "OBJECT", - }, defaultProperties: { markers: "defaultMarkers", center: "mapCenter", @@ -369,31 +189,16 @@ const WIDGET_CONFIG_MAP: WidgetTypeConfigMap = { metaProperties: {}, }, CANVAS_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, ICON_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, }, SKELETON_WIDGET: { - validations: { - isLoading: "BOOLEAN", - isVisible: "BOOLEAN", - isDisabled: "BOOLEAN", - }, defaultProperties: {}, derivedProperties: {}, metaProperties: {}, @@ -416,6 +221,7 @@ const BASE_WIDGET: DataTreeWidget = { version: 1, bindingPaths: {}, triggerPaths: {}, + validationPaths: {}, ENTITY_TYPE: ENTITY_TYPE.WIDGET, }; @@ -457,6 +263,9 @@ describe("DataTreeEvaluator", () => { bindingPaths: { text: true, }, + validationPaths: { + text: VALIDATION_TYPES.TEXT, + }, }, Text3: { ...BASE_WIDGET, @@ -467,6 +276,9 @@ describe("DataTreeEvaluator", () => { bindingPaths: { text: true, }, + validationPaths: { + text: VALIDATION_TYPES.TEXT, + }, }, Dropdown1: { ...BASE_WIDGET, @@ -506,6 +318,9 @@ describe("DataTreeEvaluator", () => { selectedRow: true, selectedRows: true, }, + validationPaths: { + tableData: VALIDATION_TYPES.TABLE_DATA, + }, }, Text4: { ...BASE_WIDGET, @@ -515,6 +330,9 @@ describe("DataTreeEvaluator", () => { bindingPaths: { text: true, }, + validationPaths: { + text: VALIDATION_TYPES.TEXT, + }, }, }; const evaluator = new DataTreeEvaluator(WIDGET_CONFIG_MAP); diff --git a/app/client/src/workers/evaluation.worker.ts b/app/client/src/workers/evaluation.worker.ts index 2c9d3c65c0..85a7399224 100644 --- a/app/client/src/workers/evaluation.worker.ts +++ b/app/client/src/workers/evaluation.worker.ts @@ -73,7 +73,7 @@ ctx.addEventListener( }); console.error(e); } - dataTree = getValidatedTree(widgetTypeConfigMap, unevalTree); + dataTree = getValidatedTree(unevalTree); dataTreeEvaluator = undefined; } return { @@ -148,21 +148,9 @@ ctx.addEventListener( return true; } case EVAL_WORKER_ACTIONS.VALIDATE_PROPERTY: { - const { - widgetType, - widgetTypeConfigMap, - property, - value, - props, - } = requestData; + const { property, value, props, validation } = requestData; return removeFunctions( - validateWidgetProperty( - widgetTypeConfigMap, - widgetType, - property, - value, - props, - ), + validateWidgetProperty(property, value, props, validation), ); } default: { diff --git a/app/client/src/workers/evaluationUtils.ts b/app/client/src/workers/evaluationUtils.ts index c92b6edce1..76d706ddec 100644 --- a/app/client/src/workers/evaluationUtils.ts +++ b/app/client/src/workers/evaluationUtils.ts @@ -3,9 +3,7 @@ import { isChildPropertyPath, isDynamicValue, } from "utils/DynamicBindingUtils"; -import { WidgetType } from "constants/WidgetConstants"; import { WidgetProps } from "widgets/BaseWidget"; -import { WidgetTypeConfigMap } from "utils/WidgetFactory"; import { VALIDATORS } from "./validations"; import { Diff } from "deep-diff"; import { @@ -16,6 +14,7 @@ import { ENTITY_TYPE, } from "entities/DataTree/dataTreeFactory"; import _ from "lodash"; +import { VALIDATION_TYPES } from "constants/WidgetValidation"; // Dropdown1.options[1].value -> Dropdown1.options[1] // Dropdown1.options[1] -> Dropdown1.options @@ -61,6 +60,16 @@ function isInt(val: string | number): boolean { return !isNaN(parseInt(val)); } +// Removes the entity name from the property path +export function getEntityNameAndPropertyPath( + fullPath: string, +): { entityName: string; propertyPath: string } { + const indexOfFirstDot = fullPath.indexOf("."); + const entityName = fullPath.substring(0, indexOfFirstDot); + const propertyPath = fullPath.substring(fullPath.indexOf(".") + 1); + return { entityName, propertyPath }; +} + export const translateDiffEventToDataTreeDiffEvent = ( difference: Diff, ): DataTreeDiff => { @@ -244,73 +253,53 @@ export const getImmediateParentsOfPropertyPaths = ( }; export function validateWidgetProperty( - widgetConfigMap: WidgetTypeConfigMap, - widgetType: WidgetType, property: string, value: any, props: WidgetProps, + validation?: VALIDATION_TYPES, dataTree?: DataTree, ) { - const propertyValidationTypes = widgetConfigMap[widgetType].validations; - const validationTypeOrValidator = propertyValidationTypes[property]; - let validator; - - if (typeof validationTypeOrValidator === "function") { - validator = validationTypeOrValidator; - } else { - validator = VALIDATORS[validationTypeOrValidator]; - } - if (validator) { - return validator(value, props, dataTree); - } else { + if (!validation) { return { isValid: true, parsed: value }; } + const validator = VALIDATORS[validation]; + if (!validator) { + return { isValid: true, parsed: value }; + } + return validator(value, props, dataTree); } -export function getValidatedTree( - widgetConfigMap: WidgetTypeConfigMap, - tree: DataTree, -) { +export function getValidatedTree(tree: DataTree) { return Object.keys(tree).reduce((tree, entityKey: string) => { const entity = tree[entityKey] as DataTreeWidget; if (!isWidget(entity)) { return tree; } const parsedEntity = { ...entity }; - Object.keys(entity).forEach((property: string) => { - const validationProperties = widgetConfigMap[entity.type].validations; - - if (property in validationProperties) { - const value = _.get(entity, property); - // Pass it through parse - const { - parsed, - isValid, - message, - transformed, - } = validateWidgetProperty( - widgetConfigMap, - entity.type, - property, - value, - entity, - tree, - ); - parsedEntity[property] = parsed; - const evaluatedValue = isValid - ? parsed - : _.isUndefined(transformed) - ? value - : transformed; - const safeEvaluatedValue = removeFunctions(evaluatedValue); - _.set(parsedEntity, `evaluatedValues.${property}`, safeEvaluatedValue); - if (!isValid) { - _.set(parsedEntity, `invalidProps.${property}`, true); - _.set(parsedEntity, `validationMessages.${property}`, message); - } else { - _.set(parsedEntity, `invalidProps.${property}`, false); - _.set(parsedEntity, `validationMessages.${property}`, ""); - } + Object.entries(entity.validationPaths).forEach(([property, validation]) => { + const value = _.get(entity, property); + // Pass it through parse + const { parsed, isValid, message, transformed } = validateWidgetProperty( + property, + value, + entity, + validation, + tree, + ); + _.set(parsedEntity, property, parsed); + const evaluatedValue = isValid + ? parsed + : _.isUndefined(transformed) + ? value + : transformed; + const safeEvaluatedValue = removeFunctions(evaluatedValue); + _.set(parsedEntity, `evaluatedValues.${property}`, safeEvaluatedValue); + if (!isValid) { + _.set(parsedEntity, `invalidProps.${property}`, true); + _.set(parsedEntity, `validationMessages.${property}`, message); + } else { + _.set(parsedEntity, `invalidProps.${property}`, false); + _.set(parsedEntity, `validationMessages.${property}`, ""); } }); return { ...tree, [entityKey]: parsedEntity }; diff --git a/app/client/src/workers/validations.ts b/app/client/src/workers/validations.ts index 9c5fcd05f2..68a9356dd8 100644 --- a/app/client/src/workers/validations.ts +++ b/app/client/src/workers/validations.ts @@ -2,7 +2,6 @@ import { ISO_DATE_FORMAT, VALIDATION_TYPES, ValidationResponse, - ValidationType, Validator, } from "../constants/WidgetValidation"; import { DataTree } from "../entities/DataTree/dataTreeFactory"; @@ -48,7 +47,7 @@ export function validateDateString( const WIDGET_TYPE_VALIDATION_ERROR = "Value does not match type"; // TODO: Lot's of changes in validations.ts file -export const VALIDATORS: Record = { +export const VALIDATORS: Record = { [VALIDATION_TYPES.TEXT]: (value: any): ValidationResponse => { let parsed = value; if (isUndefined(value) || value === null) {