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
|
||||
// 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<WidgetProps> & WidgetConfigProps;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class ChartWidget extends BaseWidget<ChartWidgetProps, WidgetState> {
|
|||
iconSVG: IconSVG,
|
||||
tags: [WIDGET_TAGS.DISPLAY],
|
||||
needsMeta: true,
|
||||
needsErrorInfo: true,
|
||||
searchTags: ["graph", "visuals", "visualisations"],
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -942,10 +942,7 @@ class TableWidgetV2 extends BaseWidget<TableWidgetProps, WidgetState> {
|
|||
|
||||
//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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user