fix: reset widget to default value after setter method (#29151)
## Description This PR ensures that widgets are reset to their default value after the `setValue` setter method is used to set its value #### PR fixes following issue(s) Fixes #27119 #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Implemented a new reset functionality for widgets, allowing users to revert to default values after changes. - Enhanced widget meta updates with a new reset action. - **Bug Fixes** - Added test cases to ensure widget reset functionality works as expected, even after asynchronous operations. - **Refactor** - Refactored evaluation logic to improve handling of widget meta updates and resets. - Improved action execution logic for resetting widget properties. - **Tests** - Expanded end-to-end regression tests to cover new reset widget functionality. - **Documentation** - Updated internal documentation to reflect new action types and evaluation processes related to widget meta updates. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Druthi Polisetty <druthi@appsmith.com>
This commit is contained in:
parent
40e7e8b535
commit
95fa2328a8
|
|
@ -0,0 +1,83 @@
|
|||
import {
|
||||
entityExplorer,
|
||||
propPane,
|
||||
draggableWidgets,
|
||||
agHelper,
|
||||
deployMode,
|
||||
locators,
|
||||
jsEditor,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
|
||||
describe("Reset widget action", () => {
|
||||
it("Reset widget to default after setValue has been applied", () => {
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.INPUT_V2);
|
||||
propPane.UpdatePropertyFieldValue("Default value", "John");
|
||||
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 300, 300);
|
||||
propPane.EnterJSContext("onClick", `{{Input1.setValue('Hello!')}}`);
|
||||
propPane.UpdatePropertyFieldValue("Label", "Set value");
|
||||
|
||||
entityExplorer.DragDropWidgetNVerify(draggableWidgets.BUTTON, 500, 100);
|
||||
propPane.EnterJSContext("onClick", `{{resetWidget("Input1")}}`);
|
||||
propPane.UpdatePropertyFieldValue("Label", "Reset value");
|
||||
|
||||
deployMode.DeployApp();
|
||||
|
||||
agHelper.ClickButton("Set value");
|
||||
agHelper.AssertText(
|
||||
locators._widgetInDeployed(draggableWidgets.INPUT_V2) + " input",
|
||||
"val",
|
||||
"Hello!",
|
||||
);
|
||||
|
||||
agHelper.ClickButton("Reset value");
|
||||
agHelper.AssertText(
|
||||
locators._widgetInDeployed(draggableWidgets.INPUT_V2) + " input",
|
||||
"val",
|
||||
"John",
|
||||
);
|
||||
|
||||
agHelper.ClearNType(
|
||||
locators._widgetInDeployed(draggableWidgets.INPUT_V2) + " input",
|
||||
"Testing",
|
||||
);
|
||||
agHelper.ClickButton("Reset value");
|
||||
agHelper.AssertText(
|
||||
locators._widgetInDeployed(draggableWidgets.INPUT_V2) + " input",
|
||||
"val",
|
||||
"John",
|
||||
);
|
||||
});
|
||||
it("Reset value is accessible after 'awaiting'", () => {
|
||||
deployMode.NavigateBacktoEditor();
|
||||
agHelper.ClearNType(locators._input, "Meta Text");
|
||||
|
||||
const JS_OBJECT_BODY = `export default {
|
||||
async resetInputWithoutAwait () {
|
||||
resetWidget('Input1')
|
||||
showAlert(Input1.text)
|
||||
},
|
||||
async resetInputWithAwait () {
|
||||
await resetWidget('Input1')
|
||||
showAlert(Input1.text)
|
||||
}
|
||||
}`;
|
||||
|
||||
// Create js object
|
||||
jsEditor.CreateJSObject(JS_OBJECT_BODY, {
|
||||
paste: true,
|
||||
completeReplace: true,
|
||||
toRun: false,
|
||||
prettify: false,
|
||||
shouldCreateNewJSObj: true,
|
||||
});
|
||||
agHelper.Sleep(4000);
|
||||
jsEditor.SelectFunctionDropdown("resetInputWithoutAwait");
|
||||
agHelper.ClickButton("Run");
|
||||
agHelper.AssertContains("Meta Text");
|
||||
|
||||
jsEditor.SelectFunctionDropdown("resetInputWithAwait");
|
||||
agHelper.ClickButton("Run");
|
||||
agHelper.AssertContains("John");
|
||||
});
|
||||
});
|
||||
|
|
@ -55,6 +55,18 @@ export const resetWidgetMetaProperty = (
|
|||
});
|
||||
};
|
||||
|
||||
export const resetWidgetMetaUpdates = (
|
||||
evalMetaUpdates: EvalMetaUpdates,
|
||||
): BatchAction<ResetWidgetMetaPayload> => {
|
||||
return batchAction({
|
||||
type: ReduxActionTypes.RESET_WIDGET_META_UPDATES,
|
||||
payload: {
|
||||
evalMetaUpdates,
|
||||
},
|
||||
postEvalActions: [{ type: ReduxActionTypes.RESET_WIDGET_META_EVALUATED }],
|
||||
});
|
||||
};
|
||||
|
||||
export const resetChildrenMetaProperty = (
|
||||
widgetId: string,
|
||||
): ReduxAction<{ widgetId: string }> => {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ export const EVALUATE_REDUX_ACTIONS = [
|
|||
ReduxActionTypes.SET_META_PROP_AND_EVAL,
|
||||
ReduxActionTypes.META_UPDATE_DEBOUNCED_EVAL,
|
||||
ReduxActionTypes.RESET_WIDGET_META,
|
||||
ReduxActionTypes.RESET_WIDGET_META_UPDATES,
|
||||
// Batches
|
||||
ReduxActionTypes.BATCH_UPDATES_SUCCESS,
|
||||
// App Theme
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ const ActionTypes = {
|
|||
META_UPDATE_DEBOUNCED_EVAL: "META_UPDATE_DEBOUNCED_EVAL",
|
||||
RESET_CHILDREN_WIDGET_META: "RESET_CHILDREN_WIDGET_META",
|
||||
RESET_WIDGET_META: "RESET_WIDGET_META",
|
||||
RESET_WIDGET_META_UPDATES: "RESET_WIDGET_META_UPDATES",
|
||||
RESET_WIDGET_META_EVALUATED: "RESET_WIDGET_META_EVALUATED",
|
||||
RESET_WIDGETS_META_STATE: "RESET_WIDGETS_META_STATE",
|
||||
UPDATE_WIDGET_NAME_INIT: "UPDATE_WIDGET_NAME_INIT",
|
||||
|
|
|
|||
|
|
@ -368,7 +368,6 @@ export const generateDataTreeWidget = (
|
|||
|
||||
// overridingMetaProps maps properties that can be overriden by either default values or meta changes to initial values.
|
||||
// initial value is set to metaProps value or defaultMetaProps value.
|
||||
|
||||
Object.entries(defaultMetaProps).forEach(([key, value]) => {
|
||||
if (overridingMetaPropsMap[key]) {
|
||||
overridingMetaProps[key] =
|
||||
|
|
|
|||
|
|
@ -13,7 +13,11 @@ import {
|
|||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import produce from "immer";
|
||||
import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types";
|
||||
import { getMetaWidgetResetObj } from "./metaReducerUtils";
|
||||
import {
|
||||
getMetaWidgetResetObj,
|
||||
getNextMetaStateWithUpdates,
|
||||
setMetaValuesOnResetFromEval,
|
||||
} from "./metaReducerUtils";
|
||||
import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types";
|
||||
|
||||
export type WidgetMetaState = Record<string, unknown>;
|
||||
|
|
@ -28,18 +32,7 @@ export const metaReducer = createReducer(initialState, {
|
|||
evalMetaUpdates: EvalMetaUpdates;
|
||||
}>,
|
||||
) => {
|
||||
const { evalMetaUpdates } = action.payload;
|
||||
|
||||
if (!evalMetaUpdates.length) return state;
|
||||
|
||||
// if metaObject is updated in dataTree we also update meta values, to keep meta state in sync.
|
||||
const newMetaState = produce(state, (draftMetaState) => {
|
||||
evalMetaUpdates.forEach(({ metaPropertyPath, value, widgetId }) => {
|
||||
set(draftMetaState, [widgetId, ...metaPropertyPath], value);
|
||||
});
|
||||
return draftMetaState;
|
||||
});
|
||||
return newMetaState;
|
||||
return getNextMetaStateWithUpdates(state, action);
|
||||
},
|
||||
[ReduxActionTypes.SET_META_PROP]: (
|
||||
state: MetaState,
|
||||
|
|
@ -132,6 +125,14 @@ export const metaReducer = createReducer(initialState, {
|
|||
}
|
||||
return state;
|
||||
},
|
||||
[ReduxActionTypes.RESET_WIDGET_META_UPDATES]: (
|
||||
state: MetaState,
|
||||
action: ReduxAction<{
|
||||
evalMetaUpdates: EvalMetaUpdates;
|
||||
}>,
|
||||
) => {
|
||||
return setMetaValuesOnResetFromEval(state, action);
|
||||
},
|
||||
[ReduxActionTypes.RESET_WIDGETS_META_STATE]: (
|
||||
state: MetaState,
|
||||
action: ReduxAction<{ widgetIdsToClear: string[] }>,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ import type {
|
|||
PropertyOverrideDependency,
|
||||
} from "@appsmith/entities/DataTree/types";
|
||||
import { klona } from "klona";
|
||||
import type { WidgetMetaState } from ".";
|
||||
import type { MetaState, WidgetMetaState } from ".";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types";
|
||||
import produce from "immer";
|
||||
import { set, unset } from "lodash";
|
||||
|
||||
export function getMetaWidgetResetObj(
|
||||
evaluatedWidget: WidgetEntity | undefined,
|
||||
|
|
@ -30,3 +34,50 @@ export function getMetaWidgetResetObj(
|
|||
}
|
||||
return resetMetaObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* When resetWidget is called from eval, we update all the meta values and remove those meta values which are undefined
|
||||
*/
|
||||
export function setMetaValuesOnResetFromEval(
|
||||
state: MetaState,
|
||||
action: ReduxAction<{
|
||||
evalMetaUpdates: EvalMetaUpdates;
|
||||
}>,
|
||||
) {
|
||||
const { evalMetaUpdates } = action.payload;
|
||||
|
||||
if (!evalMetaUpdates.length) return state;
|
||||
|
||||
const newMetaState = klona(state);
|
||||
|
||||
evalMetaUpdates.forEach(({ metaPropertyPath, value, widgetId }) => {
|
||||
if (value === undefined) {
|
||||
unset(newMetaState, `${widgetId}.${metaPropertyPath.join(".")}`);
|
||||
} else {
|
||||
set(newMetaState, [widgetId, ...metaPropertyPath], value);
|
||||
}
|
||||
});
|
||||
|
||||
return newMetaState;
|
||||
}
|
||||
|
||||
export function getNextMetaStateWithUpdates(
|
||||
state: MetaState,
|
||||
action: ReduxAction<{
|
||||
evalMetaUpdates: EvalMetaUpdates;
|
||||
}>,
|
||||
) {
|
||||
const { evalMetaUpdates } = action.payload;
|
||||
|
||||
if (!evalMetaUpdates.length) return state;
|
||||
|
||||
// if metaObject is updated in dataTree we also update meta values, to keep meta state in sync.
|
||||
const newMetaState = produce(state, (draftMetaState) => {
|
||||
evalMetaUpdates.forEach(({ metaPropertyPath, value, widgetId }) => {
|
||||
set(draftMetaState, [widgetId, ...metaPropertyPath], value);
|
||||
});
|
||||
return draftMetaState;
|
||||
});
|
||||
|
||||
return newMetaState;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { put, select, take } from "redux-saga/effects";
|
||||
import { getWidgetByName } from "sagas/selectors";
|
||||
import {
|
||||
resetChildrenMetaProperty,
|
||||
resetWidgetMetaProperty,
|
||||
} from "actions/metaActions";
|
||||
import AppsmithConsole from "utils/AppsmithConsole";
|
||||
import { resetWidgetMetaUpdates } from "actions/metaActions";
|
||||
|
||||
import {
|
||||
ActionValidationError,
|
||||
TriggerFailureError,
|
||||
|
|
@ -12,20 +9,15 @@ import {
|
|||
import { getType, Types } from "utils/TypeHelpers";
|
||||
import type { FlattenedWidgetProps } from "WidgetProvider/constants";
|
||||
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
|
||||
import { getDataTree, getConfigTree } from "selectors/dataTreeSelectors";
|
||||
import type {
|
||||
WidgetEntity,
|
||||
WidgetEntityConfig,
|
||||
} from "@appsmith/entities/DataTree/types";
|
||||
import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes";
|
||||
import { isWidget } from "@appsmith/workers/Evaluation/evaluationUtils";
|
||||
import type { TResetWidgetDescription } from "workers/Evaluation/fns/resetWidget";
|
||||
import AppsmithConsole from "utils/AppsmithConsole";
|
||||
|
||||
export default function* resetWidgetActionSaga(
|
||||
action: TResetWidgetDescription,
|
||||
) {
|
||||
const { payload } = action;
|
||||
const { widgetName } = payload;
|
||||
const { metaUpdates, widgetName } = payload;
|
||||
|
||||
if (getType(widgetName) !== Types.STRING) {
|
||||
throw new ActionValidationError(
|
||||
"RESET_WIDGET_META_RECURSIVE_BY_NAME",
|
||||
|
|
@ -34,8 +26,6 @@ export default function* resetWidgetActionSaga(
|
|||
getType(widgetName),
|
||||
);
|
||||
}
|
||||
const dataTree: DataTree = yield select(getDataTree);
|
||||
const configTree: ConfigTree = yield select(getConfigTree);
|
||||
|
||||
const widget: FlattenedWidgetProps | undefined = yield select(
|
||||
getWidgetByName,
|
||||
|
|
@ -44,23 +34,10 @@ export default function* resetWidgetActionSaga(
|
|||
if (!widget) {
|
||||
throw new TriggerFailureError(`Widget ${payload.widgetName} not found`);
|
||||
}
|
||||
const evaluatedEntity = dataTree[widget.widgetName];
|
||||
const evaluatedEntityConfig = configTree[widget.widgetName];
|
||||
if (isWidget(evaluatedEntity)) {
|
||||
yield put(
|
||||
resetWidgetMetaProperty(
|
||||
widget.widgetId,
|
||||
evaluatedEntity as WidgetEntity,
|
||||
evaluatedEntityConfig as WidgetEntityConfig,
|
||||
),
|
||||
);
|
||||
if (payload.resetChildren) {
|
||||
yield put(resetChildrenMetaProperty(widget.widgetId));
|
||||
}
|
||||
}
|
||||
|
||||
yield put(resetWidgetMetaUpdates(metaUpdates));
|
||||
|
||||
yield take(ReduxActionTypes.RESET_WIDGET_META_EVALUATED);
|
||||
|
||||
AppsmithConsole.info({
|
||||
text: `resetWidget('${payload.widgetName}', ${payload.resetChildren}) was triggered`,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ const BATCH_PRIORITY = {
|
|||
priority: 0,
|
||||
needsSaga: false,
|
||||
},
|
||||
[ReduxActionTypes.RESET_WIDGET_META_UPDATES]: {
|
||||
priority: 0,
|
||||
needsSaga: false,
|
||||
},
|
||||
[ReduxActionTypes.UPDATE_WIDGET_PROPERTY]: {
|
||||
priority: 0,
|
||||
needsSaga: false,
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import {
|
|||
getDataTree,
|
||||
getUnevaluatedDataTree,
|
||||
} from "selectors/dataTreeSelectors";
|
||||
import { getMetaWidgets, getWidgets } from "sagas/selectors";
|
||||
import { getMetaWidgets, getWidgets, getWidgetsMeta } from "sagas/selectors";
|
||||
import type { WidgetTypeConfigMap } from "WidgetProvider/factory";
|
||||
import WidgetFactory from "WidgetProvider/factory";
|
||||
import { GracefulWorkerService } from "utils/WorkerUtil";
|
||||
|
|
@ -260,6 +260,8 @@ export function* evaluateTreeSaga(
|
|||
PerformanceTransactionName.DATA_TREE_EVALUATION,
|
||||
);
|
||||
const appMode: ReturnType<typeof getAppMode> = yield select(getAppMode);
|
||||
const widgetsMeta: ReturnType<typeof getWidgetsMeta> =
|
||||
yield select(getWidgetsMeta);
|
||||
|
||||
const evalTreeRequestData: EvalTreeRequestData = {
|
||||
unevalTree: unEvalAndConfigTree,
|
||||
|
|
@ -271,6 +273,7 @@ export function* evaluateTreeSaga(
|
|||
forceEvaluation,
|
||||
metaWidgets,
|
||||
appMode,
|
||||
widgetsMeta,
|
||||
};
|
||||
|
||||
const workerResponse: EvalTreeResponseData = yield call(
|
||||
|
|
|
|||
|
|
@ -309,7 +309,6 @@ describe("Add functions", () => {
|
|||
it("resetWidget works", () => {
|
||||
const widgetName = "widget1";
|
||||
const resetChildren = true;
|
||||
|
||||
expect(evalContext.resetWidget(widgetName, resetChildren)).resolves.toBe(
|
||||
{},
|
||||
);
|
||||
|
|
@ -323,6 +322,7 @@ describe("Add functions", () => {
|
|||
payload: {
|
||||
widgetName,
|
||||
resetChildren,
|
||||
metaUpdates: [],
|
||||
},
|
||||
},
|
||||
eventType: undefined,
|
||||
|
|
|
|||
|
|
@ -1,22 +1,284 @@
|
|||
import { promisify } from "./utils/Promisify";
|
||||
|
||||
function resetWidgetFnDescriptor(widgetName: string, resetChildren = true) {
|
||||
import type { FlattenedWidgetProps } from "WidgetProvider/constants";
|
||||
import {
|
||||
canvasWidgets,
|
||||
dataTreeEvaluator,
|
||||
canvasWidgetsMeta,
|
||||
} from "../handlers/evalTree";
|
||||
import _ from "lodash";
|
||||
import type {
|
||||
WidgetEntityConfig,
|
||||
WidgetEntity,
|
||||
} from "@appsmith/entities/DataTree/types";
|
||||
import { isWidget } from "@appsmith/workers/Evaluation/evaluationUtils";
|
||||
import { klona } from "klona";
|
||||
import { getDynamicBindings, isDynamicValue } from "utils/DynamicBindingUtils";
|
||||
import evaluateSync from "../evaluate";
|
||||
import type { DescendantWidgetMap } from "sagas/WidgetOperationUtils";
|
||||
import type { MetaState } from "reducers/entityReducers/metaReducer";
|
||||
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types";
|
||||
import type { DataTree } from "entities/DataTree/dataTreeTypes";
|
||||
import { validateAndParseWidgetProperty } from "workers/common/DataTreeEvaluator/validationUtils";
|
||||
|
||||
function resetWidgetFnDescriptor(
|
||||
widgetName: string,
|
||||
resetChildren = true,
|
||||
metaUpdates: EvalMetaUpdates,
|
||||
) {
|
||||
return {
|
||||
type: "RESET_WIDGET_META_RECURSIVE_BY_NAME" as const,
|
||||
payload: { widgetName, resetChildren },
|
||||
payload: { widgetName, resetChildren, metaUpdates },
|
||||
};
|
||||
}
|
||||
|
||||
export type TResetWidgetArgs = Parameters<typeof resetWidgetFnDescriptor>;
|
||||
export type TResetWidgetDescription = ReturnType<
|
||||
typeof resetWidgetFnDescriptor
|
||||
>;
|
||||
export type TResetWidgetActionType = TResetWidgetDescription["type"];
|
||||
|
||||
async function resetWidget(
|
||||
...args: Parameters<typeof resetWidgetFnDescriptor>
|
||||
...args: [widgetName: string, resetChildren: boolean]
|
||||
) {
|
||||
return promisify(resetWidgetFnDescriptor)(...args);
|
||||
const widgetName = args[0];
|
||||
const resetChildren = args[1] || true;
|
||||
const metaUpdates: EvalMetaUpdates = [];
|
||||
const updatedProperties: string[][] = [];
|
||||
|
||||
resetWidgetMetaProperty(
|
||||
widgetName,
|
||||
resetChildren,
|
||||
metaUpdates,
|
||||
updatedProperties,
|
||||
);
|
||||
|
||||
return promisify(resetWidgetFnDescriptor)(
|
||||
widgetName,
|
||||
resetChildren,
|
||||
metaUpdates,
|
||||
);
|
||||
}
|
||||
|
||||
function resetWidgetMetaProperty(
|
||||
widgetName: string,
|
||||
resetChildren = true,
|
||||
evalMetaUpdates: EvalMetaUpdates,
|
||||
updatedProperties: string[][],
|
||||
) {
|
||||
const widget: FlattenedWidgetProps | undefined = _.find(
|
||||
Object.values(canvasWidgets || {}),
|
||||
(widget) => widget.widgetName === widgetName,
|
||||
);
|
||||
|
||||
if (!dataTreeEvaluator || !widget) return;
|
||||
|
||||
const evalTree = dataTreeEvaluator.getEvalTree();
|
||||
const oldUnEvalTree = dataTreeEvaluator.getOldUnevalTree();
|
||||
const configTree = dataTreeEvaluator.getConfigTree();
|
||||
const evalProps = dataTreeEvaluator.getEvalProps();
|
||||
const evalPathsIdenticalToState =
|
||||
dataTreeEvaluator.getEvalPathsIdenticalToState();
|
||||
|
||||
const evaluatedEntity = evalTree[widget.widgetName];
|
||||
const evaluatedEntityConfig = configTree[
|
||||
widget.widgetName
|
||||
] as WidgetEntityConfig;
|
||||
|
||||
if (evaluatedEntity && isWidget(evaluatedEntity)) {
|
||||
const metaObj = evaluatedEntity.meta;
|
||||
const currentMetaProperties = Object.keys(metaObj);
|
||||
const { propertyOverrideDependency } = evaluatedEntityConfig;
|
||||
|
||||
for (const propertyPath of currentMetaProperties) {
|
||||
const defaultPropertyPath =
|
||||
propertyOverrideDependency[propertyPath]?.DEFAULT;
|
||||
if (defaultPropertyPath) {
|
||||
const unEvalEntity = oldUnEvalTree[widget.widgetName] as WidgetEntity;
|
||||
const expressionToEvaluate: string = unEvalEntity[defaultPropertyPath];
|
||||
|
||||
let finalValue: unknown;
|
||||
if (
|
||||
expressionToEvaluate &&
|
||||
typeof expressionToEvaluate === "string" &&
|
||||
isDynamicValue(expressionToEvaluate)
|
||||
) {
|
||||
const { jsSnippets } = getDynamicBindings(expressionToEvaluate);
|
||||
const { result } = evaluateSync(
|
||||
jsSnippets[0] || expressionToEvaluate,
|
||||
evalTree,
|
||||
false,
|
||||
{},
|
||||
undefined,
|
||||
configTree,
|
||||
);
|
||||
|
||||
finalValue = klona(result);
|
||||
} else {
|
||||
finalValue = klona(expressionToEvaluate);
|
||||
}
|
||||
|
||||
const parsedValue = validateAndParseWidgetProperty({
|
||||
fullPropertyPath: `${widget.widgetName}.${defaultPropertyPath}`,
|
||||
widget: unEvalEntity,
|
||||
configTree,
|
||||
evalPropertyValue: finalValue,
|
||||
unEvalPropertyValue: expressionToEvaluate,
|
||||
evalProps,
|
||||
evalPathsIdenticalToState,
|
||||
});
|
||||
|
||||
evalMetaUpdates.push({
|
||||
widgetId: evaluatedEntity.widgetId,
|
||||
metaPropertyPath: propertyPath.split("."),
|
||||
value: parsedValue,
|
||||
});
|
||||
|
||||
continue;
|
||||
} else {
|
||||
evalMetaUpdates.push({
|
||||
widgetId: evaluatedEntity.widgetId,
|
||||
metaPropertyPath: propertyPath.split("."),
|
||||
value: undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (resetChildren) {
|
||||
resetChildrenMetaProperty(
|
||||
widget.widgetId,
|
||||
evalTree,
|
||||
evalMetaUpdates,
|
||||
updatedProperties,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sortWidgetsMetaByParent(widgetsMeta: MetaState, parentId: string) {
|
||||
return _.reduce(
|
||||
widgetsMeta,
|
||||
function (
|
||||
result: {
|
||||
childrenWidgetsMeta: MetaState;
|
||||
otherWidgetsMeta: MetaState;
|
||||
},
|
||||
currentWidgetMeta,
|
||||
key,
|
||||
) {
|
||||
return key.startsWith(parentId + "_")
|
||||
? {
|
||||
...result,
|
||||
childrenWidgetsMeta: {
|
||||
...result.childrenWidgetsMeta,
|
||||
[key]: currentWidgetMeta,
|
||||
},
|
||||
}
|
||||
: {
|
||||
...result,
|
||||
otherWidgetsMeta: {
|
||||
...result.otherWidgetsMeta,
|
||||
[key]: currentWidgetMeta,
|
||||
},
|
||||
};
|
||||
},
|
||||
{
|
||||
childrenWidgetsMeta: {},
|
||||
otherWidgetsMeta: {},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export function getWidgetDescendantToReset(
|
||||
canvasWidgets: CanvasWidgetsReduxState,
|
||||
widgetId: string,
|
||||
evaluatedDataTree: DataTree,
|
||||
widgetsMeta: MetaState,
|
||||
): DescendantWidgetMap[] {
|
||||
const descendantList: DescendantWidgetMap[] = [];
|
||||
const widget = _.get(canvasWidgets, widgetId);
|
||||
|
||||
const sortedWidgetsMeta = sortWidgetsMetaByParent(widgetsMeta, widgetId);
|
||||
for (const childMetaWidgetId of Object.keys(
|
||||
sortedWidgetsMeta.childrenWidgetsMeta,
|
||||
)) {
|
||||
const evaluatedChildWidget = _.find(evaluatedDataTree, function (entity) {
|
||||
return isWidget(entity) && entity.widgetId === childMetaWidgetId;
|
||||
}) as WidgetEntity | undefined;
|
||||
descendantList.push({
|
||||
id: childMetaWidgetId,
|
||||
evaluatedWidget: evaluatedChildWidget,
|
||||
});
|
||||
const grandChildren = getWidgetDescendantToReset(
|
||||
canvasWidgets,
|
||||
childMetaWidgetId,
|
||||
evaluatedDataTree,
|
||||
sortedWidgetsMeta.otherWidgetsMeta,
|
||||
);
|
||||
if (grandChildren.length) {
|
||||
descendantList.push(...grandChildren);
|
||||
}
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
const { children = [] } = widget;
|
||||
|
||||
if (children && children.length) {
|
||||
for (const childIndex in children) {
|
||||
if (children.hasOwnProperty(childIndex)) {
|
||||
const childWidgetId = children[childIndex];
|
||||
|
||||
const childCanvasWidget = _.get(canvasWidgets, childWidgetId);
|
||||
const childWidgetName = childCanvasWidget.widgetName;
|
||||
const childWidget = evaluatedDataTree[childWidgetName];
|
||||
if (isWidget(childWidget)) {
|
||||
descendantList.push({
|
||||
id: childWidgetId,
|
||||
evaluatedWidget: childWidget,
|
||||
});
|
||||
const grandChildren = getWidgetDescendantToReset(
|
||||
canvasWidgets,
|
||||
childWidgetId,
|
||||
evaluatedDataTree,
|
||||
sortedWidgetsMeta.otherWidgetsMeta,
|
||||
);
|
||||
if (grandChildren.length) {
|
||||
descendantList.push(...grandChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return descendantList;
|
||||
}
|
||||
|
||||
function resetChildrenMetaProperty(
|
||||
parentWidgetId: string,
|
||||
evaluatedDataTree: DataTree,
|
||||
evalMetaUpdates: EvalMetaUpdates,
|
||||
updatedProperties: string[][],
|
||||
) {
|
||||
const childrenList = getWidgetDescendantToReset(
|
||||
canvasWidgets,
|
||||
parentWidgetId,
|
||||
evaluatedDataTree,
|
||||
canvasWidgetsMeta,
|
||||
);
|
||||
|
||||
for (const childIndex in childrenList) {
|
||||
const { evaluatedWidget: childWidget } = childrenList[childIndex];
|
||||
|
||||
if (!childWidget) continue;
|
||||
|
||||
resetWidgetMetaProperty(
|
||||
childWidget?.widgetName,
|
||||
false,
|
||||
evalMetaUpdates,
|
||||
updatedProperties,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default resetWidget;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export function promisify<P extends ReadonlyArray<unknown>>(
|
|||
return async function (...args: P) {
|
||||
const actionDescription = fnDescriptor(...args);
|
||||
const metaData = ExecutionMetaData.getExecutionMetaData();
|
||||
|
||||
const response = await WorkerMessenger.request({
|
||||
method: MAIN_THREAD_ACTION.PROCESS_TRIGGER,
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@ import DataStore from "../dataStore";
|
|||
import type { TransmissionErrorHandler } from "../fns/utils/Messenger";
|
||||
import { MessageType, sendMessage } from "utils/MessageUtil";
|
||||
import { startSpansInAnEvaluation } from "UITelemetry/generateWebWorkerTraces";
|
||||
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
|
||||
export let replayMap: Record<string, ReplayEntity<any>> | undefined;
|
||||
export let dataTreeEvaluator: DataTreeEvaluator | undefined;
|
||||
export const CANVAS = "canvas";
|
||||
export let canvasWidgetsMeta: Record<string, any>;
|
||||
export let canvasWidgets: CanvasWidgetsReduxState;
|
||||
|
||||
export default function (request: EvalWorkerSyncRequest) {
|
||||
const { data } = request;
|
||||
|
|
@ -56,11 +60,15 @@ export default function (request: EvalWorkerSyncRequest) {
|
|||
theme,
|
||||
unevalTree: __unevalTree__,
|
||||
widgets,
|
||||
widgetsMeta,
|
||||
widgetTypeConfigMap,
|
||||
} = data as EvalTreeRequestData;
|
||||
|
||||
const unevalTree = __unevalTree__.unEvalTree;
|
||||
configTree = __unevalTree__.configTree as ConfigTree;
|
||||
canvasWidgets = widgets;
|
||||
canvasWidgetsMeta = widgetsMeta;
|
||||
|
||||
try {
|
||||
if (!dataTreeEvaluator) {
|
||||
isCreateFirstTree = true;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export interface EvalTreeRequestData {
|
|||
forceEvaluation: boolean;
|
||||
metaWidgets: MetaWidgetsReduxState;
|
||||
appMode?: APP_MODE;
|
||||
widgetsMeta: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface EvalTreeResponseData {
|
||||
|
|
|
|||
|
|
@ -192,6 +192,10 @@ export default class DataTreeEvaluator {
|
|||
return this.evalTree;
|
||||
}
|
||||
|
||||
getEvalProps() {
|
||||
return this.evalProps;
|
||||
}
|
||||
|
||||
setEvalTree(evalTree: DataTree) {
|
||||
this.evalTree = evalTree;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ export function validateAndParseWidgetProperty({
|
|||
evalPathsIdenticalToState: EvalPathsIdenticalToState;
|
||||
}): unknown {
|
||||
const { propertyPath } = getEntityNameAndPropertyPath(fullPropertyPath);
|
||||
|
||||
if (isPathDynamicTrigger(widget, propertyPath)) {
|
||||
// TODO find a way to validate triggers
|
||||
return unEvalPropertyValue;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user