diff --git a/app/client/src/WidgetProvider/constants.ts b/app/client/src/WidgetProvider/constants.ts index 60d9829058..882d92a9c3 100644 --- a/app/client/src/WidgetProvider/constants.ts +++ b/app/client/src/WidgetProvider/constants.ts @@ -88,6 +88,9 @@ export interface WidgetBaseConfiguration { // Flag to tell platform to disaplay this widget when search key // is not matching any widget. isSearchWildcard?: boolean; + + // Flag to tell withWidgetProps HOC to inject evaluation errors into the widget + needsErrorInfo?: boolean; } export type WidgetDefaultProps = Partial & WidgetConfigProps; diff --git a/app/client/src/WidgetProvider/factory/index.tsx b/app/client/src/WidgetProvider/factory/index.tsx index 746c764118..346a03e0a5 100644 --- a/app/client/src/WidgetProvider/factory/index.tsx +++ b/app/client/src/WidgetProvider/factory/index.tsx @@ -113,6 +113,7 @@ class WidgetFactory { isCanvas: config.isCanvas, needsHeightForContent: config.needsHeightForContent, isSearchWildcard: config.isSearchWildcard, + needsErrorInfo: !!config.needsErrorInfo, }; WidgetFactory.widgetConfigMap.set(widget.type, Object.freeze(_config)); diff --git a/app/client/src/utils/widgetRenderUtils.test.ts b/app/client/src/utils/widgetRenderUtils.test.ts index 544d1bc337..e9ec940659 100644 --- a/app/client/src/utils/widgetRenderUtils.test.ts +++ b/app/client/src/utils/widgetRenderUtils.test.ts @@ -8,9 +8,29 @@ import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsR import { buildChildWidgetTree, createCanvasWidget } from "./widgetRenderUtils"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; +jest.mock("../WidgetProvider/factory", () => { + const originalModule = jest.requireActual("react-redux"); + return { + ...originalModule, + default: { + ...originalModule.default, + getConfig: (type: string) => { + return { + needsErrorInfo: type === "CHART_WIDGET", + }; + }, + widgetTypes: { + SKELETON_WIDGET: "SKELETON_WIDGET", + }, + }, + }; +}); + describe("createCanvasWidget functionality", () => { it("returns an empty errors if no evaluations are present", function () { - const canvasWidget = {} as unknown as FlattenedWidgetProps; + const canvasWidget = { + type: "CHART_WIDGET", + } as unknown as FlattenedWidgetProps; const dataTree = {} as unknown as WidgetEntity; const response = createCanvasWidget( @@ -22,7 +42,9 @@ describe("createCanvasWidget functionality", () => { }); it("returns an empty errors if no evaluation errors are present", () => { - const canvasWidget = {} as unknown as FlattenedWidgetProps; + const canvasWidget = { + type: "CHART_WIDGET", + } as unknown as FlattenedWidgetProps; const dataTree = { __evaluation__: {}, } as unknown as WidgetEntity; @@ -35,8 +57,10 @@ describe("createCanvasWidget functionality", () => { expect(response.errors.length).toEqual(0); }); - it("populates __evaluation__ errors inside widget error property", () => { - const canvasWidget = {} as unknown as FlattenedWidgetProps; + it("populates __evaluation__ errors inside widget error property for widgets that has opt in", () => { + const canvasWidget = { + type: "CHART_WIDGET", + } as unknown as FlattenedWidgetProps; const dataTree = { __evaluation__: { @@ -66,6 +90,35 @@ describe("createCanvasWidget functionality", () => { expect(response.errors[0].type).toStrictEqual("property"); expect(response.errors[0].path).toStrictEqual("propertyPath"); }); + + it("doesn't populates __evaluation__ errors inside widget error property for widget has not opt in", () => { + const canvasWidget = { + type: "TEXT_WIDGET", + } as unknown as FlattenedWidgetProps; + + const dataTree = { + __evaluation__: { + errors: { + propertyPath: [ + { + errorMessage: { + name: "Validation Error", + message: "Error Message", + }, + raw: "Error Message Stack", + }, + ], + }, + }, + } as unknown as WidgetEntity; + + const response = createCanvasWidget( + canvasWidget, + dataTree, + {} as WidgetEntityConfig, + ); + expect(response.errors.length).toEqual(0); + }); }); describe("test EditorUtils methods", () => { @@ -388,7 +441,7 @@ describe("test EditorUtils methods", () => { reactivePaths: {}, topRow: 4, triggerPaths: {}, - type: undefined, + type: "SKELETON_WIDGET", validationPaths: {}, widgetId: "3", widgetName: "three", @@ -408,7 +461,7 @@ describe("test EditorUtils methods", () => { reactivePaths: {}, topRow: 6, triggerPaths: {}, - type: undefined, + type: "SKELETON_WIDGET", validationPaths: {}, widgetId: "4", widgetName: "four", @@ -427,7 +480,7 @@ describe("test EditorUtils methods", () => { reactivePaths: {}, topRow: 0, triggerPaths: {}, - type: undefined, + type: "SKELETON_WIDGET", validationPaths: {}, widgetId: "1_meta", widgetName: "meta_one", @@ -447,7 +500,7 @@ describe("test EditorUtils methods", () => { reactivePaths: {}, topRow: 0, triggerPaths: {}, - type: undefined, + type: "SKELETON_WIDGET", validationPaths: {}, widgetId: "2_meta", widgetName: "meta_two", @@ -465,7 +518,7 @@ describe("test EditorUtils methods", () => { reactivePaths: {}, topRow: 0, triggerPaths: {}, - type: undefined, + type: "SKELETON_WIDGET", validationPaths: {}, widgetId: "2", widgetName: "two", diff --git a/app/client/src/utils/widgetRenderUtils.tsx b/app/client/src/utils/widgetRenderUtils.tsx index df17997848..2ae9b6ac54 100644 --- a/app/client/src/utils/widgetRenderUtils.tsx +++ b/app/client/src/utils/widgetRenderUtils.tsx @@ -48,7 +48,17 @@ export const createCanvasWidget = ( ...evaluatedWidgetConfig, ...widgetStaticProps, } as any; - widgetProps.errors = widgetErrorsFromStaticProps(evaluatedStaticProps); + + /* + * Widgets can ask for error info to be passed to them so they can show errors on the UI + */ + const needsErrorInfo = WidgetFactory.getConfig(canvasWidget.type) + ?.needsErrorInfo; + + widgetProps.errors = needsErrorInfo + ? widgetErrorsFromStaticProps(evaluatedStaticProps) + : []; + return widgetProps; }; diff --git a/app/client/src/widgets/ChartWidget/widget/index.tsx b/app/client/src/widgets/ChartWidget/widget/index.tsx index 1f1cd544a0..7d2c645fc8 100644 --- a/app/client/src/widgets/ChartWidget/widget/index.tsx +++ b/app/client/src/widgets/ChartWidget/widget/index.tsx @@ -68,6 +68,7 @@ class ChartWidget extends BaseWidget { iconSVG: IconSVG, tags: [WIDGET_TAGS.DISPLAY], needsMeta: true, + needsErrorInfo: true, searchTags: ["graph", "visuals", "visualisations"], }; } diff --git a/app/client/src/widgets/TableWidgetV2/widget/index.tsx b/app/client/src/widgets/TableWidgetV2/widget/index.tsx index 4668d6864a..1fcd6cb9d8 100644 --- a/app/client/src/widgets/TableWidgetV2/widget/index.tsx +++ b/app/client/src/widgets/TableWidgetV2/widget/index.tsx @@ -942,10 +942,7 @@ class TableWidgetV2 extends BaseWidget { //check if necessary we are batching now updates // Check if tableData is modifed - const isTableDataModified = !equal( - this.props.tableData, - prevProps.tableData, - ); + const isTableDataModified = this.props.tableData !== prevProps.tableData; const { commitBatchMetaUpdates, pushBatchMetaUpdates } = this.props; // If the user has changed the tableData OR