chore: Add config to widgets to ask for evaluations error and table widget optimisation (#31956)
## Description - Add `needsErrorInfo` to widget configuration - Replace usage of `fast-deep-equal` with referential check for tableData ## Automation /ok-to-test tags="@tag.Widget" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!IMPORTANT] > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/8370220547> > Commit: `ded6b16333e1df5d5d55f22df0559ba378f33d9c` > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8370220547&attempt=1" target="_blank">Click here!</a> > All cypress tests have passed 🎉🎉🎉 <!-- end of auto-generated comment: Cypress test results --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a mechanism to display evaluation errors directly on widgets when necessary. - **Enhancements** - Simplified data comparison logic in `TableWidgetV2` to improve performance. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
0e50c57d6b
commit
b498c7e9c4
|
|
@ -88,6 +88,9 @@ export interface WidgetBaseConfiguration {
|
||||||
// Flag to tell platform to disaplay this widget when search key
|
// Flag to tell platform to disaplay this widget when search key
|
||||||
// is not matching any widget.
|
// is not matching any widget.
|
||||||
isSearchWildcard?: boolean;
|
isSearchWildcard?: boolean;
|
||||||
|
|
||||||
|
// Flag to tell withWidgetProps HOC to inject evaluation errors into the widget
|
||||||
|
needsErrorInfo?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WidgetDefaultProps = Partial<WidgetProps> & WidgetConfigProps;
|
export type WidgetDefaultProps = Partial<WidgetProps> & WidgetConfigProps;
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ class WidgetFactory {
|
||||||
isCanvas: config.isCanvas,
|
isCanvas: config.isCanvas,
|
||||||
needsHeightForContent: config.needsHeightForContent,
|
needsHeightForContent: config.needsHeightForContent,
|
||||||
isSearchWildcard: config.isSearchWildcard,
|
isSearchWildcard: config.isSearchWildcard,
|
||||||
|
needsErrorInfo: !!config.needsErrorInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
WidgetFactory.widgetConfigMap.set(widget.type, Object.freeze(_config));
|
WidgetFactory.widgetConfigMap.set(widget.type, Object.freeze(_config));
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,29 @@ import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsR
|
||||||
import { buildChildWidgetTree, createCanvasWidget } from "./widgetRenderUtils";
|
import { buildChildWidgetTree, createCanvasWidget } from "./widgetRenderUtils";
|
||||||
import type { FlattenedWidgetProps } from "WidgetProvider/constants";
|
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", () => {
|
describe("createCanvasWidget functionality", () => {
|
||||||
it("returns an empty errors if no evaluations are present", function () {
|
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 dataTree = {} as unknown as WidgetEntity;
|
||||||
|
|
||||||
const response = createCanvasWidget(
|
const response = createCanvasWidget(
|
||||||
|
|
@ -22,7 +42,9 @@ describe("createCanvasWidget functionality", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns an empty errors if no evaluation errors are present", () => {
|
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 = {
|
const dataTree = {
|
||||||
__evaluation__: {},
|
__evaluation__: {},
|
||||||
} as unknown as WidgetEntity;
|
} as unknown as WidgetEntity;
|
||||||
|
|
@ -35,8 +57,10 @@ describe("createCanvasWidget functionality", () => {
|
||||||
expect(response.errors.length).toEqual(0);
|
expect(response.errors.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("populates __evaluation__ errors inside widget error property", () => {
|
it("populates __evaluation__ errors inside widget error property for widgets that has opt in", () => {
|
||||||
const canvasWidget = {} as unknown as FlattenedWidgetProps;
|
const canvasWidget = {
|
||||||
|
type: "CHART_WIDGET",
|
||||||
|
} as unknown as FlattenedWidgetProps;
|
||||||
|
|
||||||
const dataTree = {
|
const dataTree = {
|
||||||
__evaluation__: {
|
__evaluation__: {
|
||||||
|
|
@ -66,6 +90,35 @@ describe("createCanvasWidget functionality", () => {
|
||||||
expect(response.errors[0].type).toStrictEqual("property");
|
expect(response.errors[0].type).toStrictEqual("property");
|
||||||
expect(response.errors[0].path).toStrictEqual("propertyPath");
|
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", () => {
|
describe("test EditorUtils methods", () => {
|
||||||
|
|
@ -388,7 +441,7 @@ describe("test EditorUtils methods", () => {
|
||||||
reactivePaths: {},
|
reactivePaths: {},
|
||||||
topRow: 4,
|
topRow: 4,
|
||||||
triggerPaths: {},
|
triggerPaths: {},
|
||||||
type: undefined,
|
type: "SKELETON_WIDGET",
|
||||||
validationPaths: {},
|
validationPaths: {},
|
||||||
widgetId: "3",
|
widgetId: "3",
|
||||||
widgetName: "three",
|
widgetName: "three",
|
||||||
|
|
@ -408,7 +461,7 @@ describe("test EditorUtils methods", () => {
|
||||||
reactivePaths: {},
|
reactivePaths: {},
|
||||||
topRow: 6,
|
topRow: 6,
|
||||||
triggerPaths: {},
|
triggerPaths: {},
|
||||||
type: undefined,
|
type: "SKELETON_WIDGET",
|
||||||
validationPaths: {},
|
validationPaths: {},
|
||||||
widgetId: "4",
|
widgetId: "4",
|
||||||
widgetName: "four",
|
widgetName: "four",
|
||||||
|
|
@ -427,7 +480,7 @@ describe("test EditorUtils methods", () => {
|
||||||
reactivePaths: {},
|
reactivePaths: {},
|
||||||
topRow: 0,
|
topRow: 0,
|
||||||
triggerPaths: {},
|
triggerPaths: {},
|
||||||
type: undefined,
|
type: "SKELETON_WIDGET",
|
||||||
validationPaths: {},
|
validationPaths: {},
|
||||||
widgetId: "1_meta",
|
widgetId: "1_meta",
|
||||||
widgetName: "meta_one",
|
widgetName: "meta_one",
|
||||||
|
|
@ -447,7 +500,7 @@ describe("test EditorUtils methods", () => {
|
||||||
reactivePaths: {},
|
reactivePaths: {},
|
||||||
topRow: 0,
|
topRow: 0,
|
||||||
triggerPaths: {},
|
triggerPaths: {},
|
||||||
type: undefined,
|
type: "SKELETON_WIDGET",
|
||||||
validationPaths: {},
|
validationPaths: {},
|
||||||
widgetId: "2_meta",
|
widgetId: "2_meta",
|
||||||
widgetName: "meta_two",
|
widgetName: "meta_two",
|
||||||
|
|
@ -465,7 +518,7 @@ describe("test EditorUtils methods", () => {
|
||||||
reactivePaths: {},
|
reactivePaths: {},
|
||||||
topRow: 0,
|
topRow: 0,
|
||||||
triggerPaths: {},
|
triggerPaths: {},
|
||||||
type: undefined,
|
type: "SKELETON_WIDGET",
|
||||||
validationPaths: {},
|
validationPaths: {},
|
||||||
widgetId: "2",
|
widgetId: "2",
|
||||||
widgetName: "two",
|
widgetName: "two",
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,17 @@ export const createCanvasWidget = (
|
||||||
...evaluatedWidgetConfig,
|
...evaluatedWidgetConfig,
|
||||||
...widgetStaticProps,
|
...widgetStaticProps,
|
||||||
} as any;
|
} 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;
|
return widgetProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
|
||||||
iconSVG: IconSVG,
|
iconSVG: IconSVG,
|
||||||
tags: [WIDGET_TAGS.DISPLAY],
|
tags: [WIDGET_TAGS.DISPLAY],
|
||||||
needsMeta: true,
|
needsMeta: true,
|
||||||
|
needsErrorInfo: true,
|
||||||
searchTags: ["graph", "visuals", "visualisations"],
|
searchTags: ["graph", "visuals", "visualisations"],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -942,10 +942,7 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
|
||||||
|
|
||||||
//check if necessary we are batching now updates
|
//check if necessary we are batching now updates
|
||||||
// Check if tableData is modifed
|
// Check if tableData is modifed
|
||||||
const isTableDataModified = !equal(
|
const isTableDataModified = this.props.tableData !== prevProps.tableData;
|
||||||
this.props.tableData,
|
|
||||||
prevProps.tableData,
|
|
||||||
);
|
|
||||||
|
|
||||||
const { commitBatchMetaUpdates, pushBatchMetaUpdates } = this.props;
|
const { commitBatchMetaUpdates, pushBatchMetaUpdates } = this.props;
|
||||||
// If the user has changed the tableData OR
|
// If the user has changed the tableData OR
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user