PromucFlow_constructor/app/client/src/utils/widgetRenderUtils.tsx
Ilia d6f249b42d
chore: add blank line eslint rule (#36369)
## Description
Added ESLint rule to force blank lines between statements. 


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!CAUTION]
> 🔴 🔴 🔴 Some tests have failed.
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/10924926728>
> Commit: 34f57714a1575ee04e94e03cbcaf95e57a96c86c
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10924926728&attempt=1&selectiontype=test&testsstatus=failed&specsstatus=fail"
target="_blank">Cypress dashboard</a>.
> Tags: @tag.All
> Spec: 
> The following are new failures, please fix them before merging the PR:
<ol>
> <li>cypress/e2e/Regression/ClientSide/Anvil/AnvilModal_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCheckboxGroupWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilCurrencyInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilIconButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInlineButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilParagraphWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilPhoneInputWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilStatsWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchGroupWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilSwitchWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilTableWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilToolbarButtonWidgetSnapshot_spec.ts
>
<li>cypress/e2e/Regression/ClientSide/Anvil/Widgets/AnvilZoneSectionWidgetSnapshot_spec.ts</ol>
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/identified-flaky-tests-65890b3c81d7400d08fa9ee3?branch=master"
target="_blank">List of identified flaky tests</a>.
> <hr>Wed, 18 Sep 2024 16:33:36 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [ ] No

---------

Co-authored-by: Valera Melnikov <valera@appsmith.com>
2024-09-18 19:35:28 +03:00

195 lines
5.7 KiB
TypeScript

import type {
CanvasWidgetsReduxState,
FlattenedWidgetProps,
} from "reducers/entityReducers/canvasWidgetsReducer";
import type {
WidgetEntity,
WidgetEntityConfig,
} from "ee/entities/DataTree/types";
import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes";
import { ENTITY_TYPE } from "entities/DataTree/dataTreeFactory";
import { pick } from "lodash";
import {
WIDGET_DSL_STRUCTURE_PROPS,
WIDGET_STATIC_PROPS,
} from "constants/WidgetConstants";
import WidgetFactory from "../WidgetProvider/factory";
import type { WidgetProps } from "widgets/BaseWidget";
import type { LoadingEntitiesState } from "reducers/evaluationReducers/loadingEntitiesReducer";
import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer";
import type { WidgetError } from "widgets/BaseWidget";
import { get } from "lodash";
import type { DataTreeError } from "utils/DynamicBindingUtils";
import { EVAL_ERROR_PATH } from "utils/DynamicBindingUtils";
export const createCanvasWidget = (
canvasWidget: FlattenedWidgetProps,
evaluatedWidget: WidgetEntity,
evaluatedWidgetConfig: WidgetEntityConfig,
specificChildProps?: string[],
) => {
/**
* WIDGET_DSL_STRUCTURE_PROPS is required for Building the List widget meta widgets
* requiresFlatWidgetChildren and hasMetaWidgets are the keys required.
*/
const widgetStaticProps = pick(canvasWidget, [
...Object.keys({ ...WIDGET_STATIC_PROPS, ...WIDGET_DSL_STRUCTURE_PROPS }),
...(canvasWidget.additionalStaticProps || []),
]);
//Pick required only contents for specific widgets
const evaluatedStaticProps = specificChildProps
? pick(evaluatedWidget, specificChildProps)
: evaluatedWidget;
const widgetProps = {
...evaluatedStaticProps,
...evaluatedWidgetConfig,
...widgetStaticProps,
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
return widgetProps;
};
export function widgetErrorsFromStaticProps(props: Record<string, unknown>) {
/**
* Evaluation Error Map
* {
widgetPropertyName : DataTreeError[]
}
*/
const evaluationErrorMap = get(props, EVAL_ERROR_PATH, {}) as Record<
string,
DataTreeError[]
>;
const widgetErrors: WidgetError[] = [];
Object.keys(evaluationErrorMap).forEach((propertyPath) => {
const propertyErrors = evaluationErrorMap[propertyPath];
propertyErrors.forEach((evalError) => {
const widgetError: WidgetError = {
name: evalError.errorMessage.name,
message: evalError.errorMessage.message,
stack: evalError.raw,
type: "property",
path: propertyPath,
};
widgetErrors.push(widgetError);
});
});
return widgetErrors;
}
const WidgetTypes = WidgetFactory?.widgetTypes;
export const createLoadingWidget = (
canvasWidget: FlattenedWidgetProps,
): WidgetEntity => {
const widgetStaticProps = pick(
canvasWidget,
Object.keys(WIDGET_STATIC_PROPS),
) as WidgetProps;
return {
...widgetStaticProps,
type:
// We don't need to set skeleton type for modals
// since modals are not displayed when the app is loaded
canvasWidget?.type !== "MODAL_WIDGET"
? WidgetTypes.SKELETON_WIDGET
: canvasWidget?.type,
ENTITY_TYPE: ENTITY_TYPE.WIDGET,
bindingPaths: {},
reactivePaths: {},
triggerPaths: {},
validationPaths: {},
logBlackList: {},
isLoading: true,
propertyOverrideDependency: {},
overridingPropertyPaths: {},
privateWidgets: {},
meta: {},
};
};
/**
* Method to build a child widget tree
* This method is used to build the child widgets array for widgets like Form, or List widget,
* That need to know the state of its child or grandChild to derive properties
* This can be replaced with deived properties of the individual widgets
*
* @param canvasWidgets
* @param evaluatedDataTree
* @param loadingEntities
* @param widgetId
* @param requiredWidgetProps
* @returns
*/
export function buildChildWidgetTree(
canvasWidgets: CanvasWidgetsReduxState,
metaWidgets: MetaWidgetsReduxState,
evaluatedDataTree: DataTree,
loadingEntities: LoadingEntitiesState,
configTree: ConfigTree,
widgetId: string,
requiredWidgetProps?: string[],
) {
const parentWidget = canvasWidgets[widgetId] || metaWidgets[widgetId];
// specificChildProps are the only properties required by the parent to derive it's properties
const specificChildProps =
requiredWidgetProps || getWidgetSpecificChildProps(parentWidget.type);
if (parentWidget.children) {
return parentWidget.children.map((childWidgetId) => {
const childWidget =
canvasWidgets[childWidgetId] || metaWidgets[childWidgetId];
const evaluatedWidget = evaluatedDataTree[
childWidget.widgetName
] as WidgetEntity;
const evaluatedWidgetConfig = configTree[
childWidget.widgetName
] as WidgetEntityConfig;
const widget = evaluatedWidget
? createCanvasWidget(
childWidget,
evaluatedWidget,
evaluatedWidgetConfig,
specificChildProps,
)
: createLoadingWidget(childWidget);
widget.isLoading = loadingEntities.has(childWidget.widgetName);
if (widget?.children?.length > 0) {
widget.children = buildChildWidgetTree(
canvasWidgets,
metaWidgets,
evaluatedDataTree,
loadingEntities,
configTree,
childWidgetId,
specificChildProps,
);
}
return widget;
});
}
return [];
}
function getWidgetSpecificChildProps(type: string) {
if (type === "FORM_WIDGET") {
return ["value", "isDirty", "isValid", "isLoading", "children"];
}
}