chore: add new condition for form conditionals (#38556)
## Description Added an extra condition for form evaluation. This allows server to render different components for application or any other editors. Form configs can now use this as a conditional to show or hide components `editorContextType === "PAGE"`. Valid values are `WORKFLOWS`, `PAGE` or `MODULE`. Fixes #37735 ## Automation /ok-to-test tags="@tag.Sanity, @tag.IDE" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/13294166183> > Commit: 6ab73336517e1ad6491ae3e63a5387cd65112a7b > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=13294166183&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity, @tag.IDE` > Spec: > <hr>Wed, 12 Feb 2025 21:15:04 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced context-aware evaluation actions to improve dynamic form interactions. - **Refactor** - Streamlined the form evaluation workflow and standardized key extraction for enhanced consistency and reliability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
260765520e
commit
2782994c7d
|
|
@ -2,8 +2,6 @@ import type { ReduxAction } from "./ReduxActionTypes";
|
|||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||
import { intersection } from "lodash";
|
||||
import type { DependencyMap } from "utils/DynamicBindingUtils";
|
||||
import type { QueryActionConfig } from "entities/Action";
|
||||
import type { DatasourceConfiguration } from "entities/Datasource";
|
||||
import type { DiffWithNewTreeState } from "workers/Evaluation/helpers";
|
||||
import {
|
||||
EVALUATE_REDUX_ACTIONS,
|
||||
|
|
@ -81,46 +79,6 @@ export const setDependencyMap = (
|
|||
};
|
||||
};
|
||||
|
||||
// Called when a form is being setup, for setting up the base condition evaluations for the form
|
||||
export const initFormEvaluations = (
|
||||
// TODO: Fix this the next time the file is edited
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
editorConfig: any,
|
||||
// TODO: Fix this the next time the file is edited
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
settingConfig: any,
|
||||
formId: string,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_FORM_EVALUATION,
|
||||
payload: { editorConfig, settingConfig, formId },
|
||||
};
|
||||
};
|
||||
|
||||
// Called when there is change in the data of the form, re evaluates the whole form
|
||||
export const startFormEvaluations = (
|
||||
formId: string,
|
||||
formData: QueryActionConfig,
|
||||
datasourceId: string,
|
||||
pluginId: string,
|
||||
actionDiffPath?: string,
|
||||
hasRouteChanged?: boolean,
|
||||
datasourceConfiguration?: DatasourceConfiguration,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_FORM_EVALUATION,
|
||||
payload: {
|
||||
formId,
|
||||
actionConfiguration: formData,
|
||||
datasourceId,
|
||||
pluginId,
|
||||
actionDiffPath,
|
||||
hasRouteChanged,
|
||||
datasourceConfiguration,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// These actions require the entire tree to be re-evaluated
|
||||
const FORCE_EVAL_ACTIONS = {
|
||||
[ReduxActionTypes.INSTALL_LIBRARY_SUCCESS]: true,
|
||||
|
|
|
|||
46
app/client/src/actions/formEvaluationActions.ts
Normal file
46
app/client/src/actions/formEvaluationActions.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
||||
import type { QueryActionConfig } from "entities/Action";
|
||||
import type { DatasourceConfiguration } from "entities/Datasource";
|
||||
import type { ActionParentEntityTypeInterface } from "ee/entities/Engine/actionHelpers";
|
||||
|
||||
// Called when a form is being setup, for setting up the base condition evaluations for the form
|
||||
export const initFormEvaluations = (
|
||||
// TODO: Fix this the next time the file is edited
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
editorConfig: any,
|
||||
// TODO: Fix this the next time the file is edited
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
settingConfig: any,
|
||||
formId: string,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.INIT_FORM_EVALUATION,
|
||||
payload: { editorConfig, settingConfig, formId },
|
||||
};
|
||||
};
|
||||
|
||||
// Called when there is change in the data of the form, re evaluates the whole form
|
||||
export const startFormEvaluations = (
|
||||
formId: string,
|
||||
formData: QueryActionConfig,
|
||||
datasourceId: string,
|
||||
pluginId: string,
|
||||
editorContextType?: ActionParentEntityTypeInterface,
|
||||
actionDiffPath?: string,
|
||||
hasRouteChanged?: boolean,
|
||||
datasourceConfiguration?: DatasourceConfiguration,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_FORM_EVALUATION,
|
||||
payload: {
|
||||
formId,
|
||||
actionConfiguration: formData,
|
||||
datasourceId,
|
||||
pluginId,
|
||||
editorContextType,
|
||||
actionDiffPath,
|
||||
hasRouteChanged,
|
||||
datasourceConfiguration,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -37,7 +37,10 @@ import {
|
|||
import type { DatasourceConfiguration } from "entities/Datasource";
|
||||
import { buffers } from "redux-saga";
|
||||
import type { Plugin } from "entities/Plugin";
|
||||
import { doesPluginRequireDatasource } from "ee/entities/Engine/actionHelpers";
|
||||
import {
|
||||
doesPluginRequireDatasource,
|
||||
type ActionParentEntityTypeInterface,
|
||||
} from "ee/entities/Engine/actionHelpers";
|
||||
import { klonaLiteWithTelemetry } from "utils/helpers";
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
|
||||
|
|
@ -45,6 +48,7 @@ export interface FormEvalActionPayload {
|
|||
formId: string;
|
||||
datasourceId?: string;
|
||||
pluginId?: string;
|
||||
editorContextType: ActionParentEntityTypeInterface;
|
||||
actionConfiguration?: ActionConfig;
|
||||
editorConfig?: FormConfigType[];
|
||||
settingConfig?: FormConfigType[];
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import get from "lodash/get";
|
|||
import {
|
||||
initFormEvaluations,
|
||||
startFormEvaluations,
|
||||
} from "actions/evaluationActions";
|
||||
} from "actions/formEvaluationActions";
|
||||
import { updateReplayEntity } from "actions/pageActions";
|
||||
import { ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils";
|
||||
import type { EventLocation } from "ee/utils/analyticsUtilTypes";
|
||||
|
|
@ -85,9 +85,13 @@ import {
|
|||
getCurrentApplicationIdForCreateNewApp,
|
||||
} from "ee/selectors/applicationSelectors";
|
||||
import { TEMP_DATASOURCE_ID } from "constants/Datasource";
|
||||
import { doesPluginRequireDatasource } from "ee/entities/Engine/actionHelpers";
|
||||
import {
|
||||
ActionParentEntityType,
|
||||
doesPluginRequireDatasource,
|
||||
} from "ee/entities/Engine/actionHelpers";
|
||||
import { convertToBasePageIdSelector } from "selectors/pageListSelectors";
|
||||
import { openGeneratePageModalWithSelectedDS } from "../utils/GeneratePageUtils";
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
|
||||
// Called whenever the query being edited is changed via the URL or query pane
|
||||
function* changeQuerySaga(actionPayload: ReduxAction<ChangeQueryPayload>) {
|
||||
|
|
@ -187,6 +191,7 @@ function* changeQuerySaga(actionPayload: ReduxAction<ChangeQueryPayload>) {
|
|||
//@ts-expect-error: id does not exists
|
||||
action.datasource.id,
|
||||
pluginId,
|
||||
action.contextType,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -275,7 +280,7 @@ function* formValueChangeSaga(
|
|||
type: ReduxActionTypes.SET_TRIGGER_VALUES_LOADING,
|
||||
payload: {
|
||||
formId: values.id,
|
||||
keys: Object.keys(allTriggers),
|
||||
keys: objectKeys(allTriggers),
|
||||
value: true,
|
||||
},
|
||||
});
|
||||
|
|
@ -317,7 +322,7 @@ function* formValueChangeSaga(
|
|||
"datasourceConfiguration",
|
||||
)
|
||||
) {
|
||||
currentEnvironment = Object.keys(datasourceStorages)[0];
|
||||
currentEnvironment = objectKeys(datasourceStorages)[0];
|
||||
}
|
||||
|
||||
let dsConfig = {
|
||||
|
|
@ -338,6 +343,7 @@ function* formValueChangeSaga(
|
|||
values.actionConfiguration,
|
||||
values.datasource.id,
|
||||
values.pluginId,
|
||||
values.contextType || ActionParentEntityType.PAGE,
|
||||
field,
|
||||
hasRouteChanged,
|
||||
dsConfig,
|
||||
|
|
|
|||
|
|
@ -76,12 +76,13 @@ import {
|
|||
import { AppThemingMode } from "selectors/appThemingSelectors";
|
||||
import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions";
|
||||
import { SelectionRequestType } from "sagas/WidgetSelectUtils";
|
||||
import { startFormEvaluations } from "actions/evaluationActions";
|
||||
import { startFormEvaluations } from "actions/formEvaluationActions";
|
||||
import { getUIComponent } from "pages/Editor/QueryEditor/helpers";
|
||||
import { type Plugin, UIComponentTypes } from "entities/Plugin";
|
||||
import { getCurrentEnvironmentId } from "ee/selectors/environmentSelectors";
|
||||
import { updateAndSaveAnvilLayout } from "layoutSystems/anvil/utils/anvilChecksUtils";
|
||||
import type { ReplayOperation } from "entities/Replay/ReplayEntity/ReplayOperations";
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
|
||||
export interface UndoRedoPayload {
|
||||
operation: ReplayOperation;
|
||||
|
|
@ -103,7 +104,7 @@ export default function* undoRedoListenerSaga() {
|
|||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function* openPropertyPaneSaga(replay: any) {
|
||||
try {
|
||||
const replayWidgetId = Object.keys(replay.widgets)[0];
|
||||
const replayWidgetId = objectKeys(replay.widgets)[0] as string;
|
||||
|
||||
if (!replayWidgetId || !replay.widgets[replayWidgetId].propertyUpdates)
|
||||
return;
|
||||
|
|
@ -155,9 +156,9 @@ export function* postUndoRedoSaga(replay: any) {
|
|||
processUndoRedoToasts(replay.toasts);
|
||||
}
|
||||
|
||||
if (!replay.widgets || Object.keys(replay.widgets).length <= 0) return;
|
||||
if (!replay.widgets || objectKeys(replay.widgets).length <= 0) return;
|
||||
|
||||
const widgetIds = Object.keys(replay.widgets);
|
||||
const widgetIds = objectKeys(replay.widgets) as string[];
|
||||
|
||||
yield put(selectWidgetInitAction(SelectionRequestType.Multiple, widgetIds));
|
||||
scrollWidgetIntoView(widgetIds[0]);
|
||||
|
|
@ -357,6 +358,7 @@ function* replayActionSaga(
|
|||
replayEntity.actionConfiguration,
|
||||
replayEntity.datasource.id || "",
|
||||
replayEntity.pluginId,
|
||||
replayEntity.contextType,
|
||||
u.modifiedProperty,
|
||||
true,
|
||||
datasource?.datasourceStorages[currentEnvironment]
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ import { extractEvalConfigFromFormConfig } from "components/formControls/utils";
|
|||
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
||||
import { isTrueObject } from "ee/workers/Evaluation/evaluationUtils";
|
||||
import type { DatasourceConfiguration } from "entities/Datasource";
|
||||
import { objectKeys } from "@appsmith/utils";
|
||||
import {
|
||||
ActionParentEntityType,
|
||||
type ActionParentEntityTypeInterface,
|
||||
} from "ee/entities/Engine/actionHelpers";
|
||||
|
||||
export enum ConditionType {
|
||||
HIDE = "hide", // When set, the component will be shown until condition is true
|
||||
|
|
@ -71,7 +76,7 @@ const generateInitialEvalState = (formConfig: FormConfigType) => {
|
|||
|
||||
// Any element is only added to the eval state if they have a conditional statement present, if not they are allowed to be rendered
|
||||
if ("conditionals" in formConfig && !!formConfig.conditionals) {
|
||||
const allConditionTypes = Object.keys(formConfig.conditionals);
|
||||
const allConditionTypes = objectKeys(formConfig.conditionals);
|
||||
|
||||
if (
|
||||
allConditionTypes.includes(ConditionType.HIDE) ||
|
||||
|
|
@ -306,12 +311,15 @@ function evaluateDynamicValuesConfig(
|
|||
}
|
||||
|
||||
function evaluateFormConfigElements(
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
actionConfiguration: ActionConfig,
|
||||
config: FormConfigEvalObject,
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
editorContextType: ActionParentEntityTypeInterface,
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
datasourceConfiguration?: DatasourceConfiguration,
|
||||
) {
|
||||
const paths = Object.keys(config);
|
||||
const paths = objectKeys(config);
|
||||
|
||||
if (paths.length > 0) {
|
||||
paths.forEach((path) => {
|
||||
|
|
@ -332,17 +340,18 @@ function evaluateFormConfigElements(
|
|||
function evaluate(
|
||||
actionConfiguration: ActionConfig,
|
||||
currentEvalState: FormEvalOutput,
|
||||
editorContextType: ActionParentEntityTypeInterface,
|
||||
actionDiffPath?: string,
|
||||
hasRouteChanged?: boolean,
|
||||
datasourceConfiguration?: DatasourceConfiguration,
|
||||
) {
|
||||
Object.keys(currentEvalState).forEach((key: string) => {
|
||||
objectKeys(currentEvalState).forEach((key: string) => {
|
||||
try {
|
||||
if (currentEvalState[key].hasOwnProperty("conditionals")) {
|
||||
const conditionBlock = currentEvalState[key].conditionals;
|
||||
|
||||
if (!!conditionBlock) {
|
||||
Object.keys(conditionBlock).forEach((conditionType: string) => {
|
||||
objectKeys(conditionBlock).forEach((conditionType: string) => {
|
||||
const output = eval(conditionBlock[conditionType]);
|
||||
|
||||
if (conditionType === ConditionType.HIDE) {
|
||||
|
|
@ -431,6 +440,7 @@ function evaluate(
|
|||
currentEvalState[key]
|
||||
.evaluateFormConfig as EvaluatedFormConfig
|
||||
).evaluateFormConfigObject,
|
||||
editorContextType,
|
||||
datasourceConfiguration,
|
||||
);
|
||||
}
|
||||
|
|
@ -448,6 +458,7 @@ function getFormEvaluation(
|
|||
formId: string,
|
||||
actionConfiguration: ActionConfig,
|
||||
currentEvalState: FormEvaluationState,
|
||||
editorContextType: ActionParentEntityTypeInterface,
|
||||
actionDiffPath?: string,
|
||||
hasRouteChanged?: boolean,
|
||||
datasourceConfiguration?: DatasourceConfiguration,
|
||||
|
|
@ -502,6 +513,7 @@ function getFormEvaluation(
|
|||
conditionToBeEvaluated = evaluate(
|
||||
actionConfiguration,
|
||||
currentEvalState[formId],
|
||||
editorContextType,
|
||||
actionDiffPath,
|
||||
hasRouteChanged,
|
||||
datasourceConfiguration,
|
||||
|
|
@ -514,6 +526,7 @@ function getFormEvaluation(
|
|||
conditionToBeEvaluated = evaluate(
|
||||
actionConfiguration,
|
||||
conditionToBeEvaluated,
|
||||
editorContextType,
|
||||
actionDiffPath,
|
||||
hasRouteChanged,
|
||||
datasourceConfiguration,
|
||||
|
|
@ -572,6 +585,7 @@ export function setFormEvaluationSaga(
|
|||
actionConfiguration,
|
||||
actionDiffPath,
|
||||
datasourceConfiguration,
|
||||
editorContextType,
|
||||
formId,
|
||||
hasRouteChanged,
|
||||
} = payload;
|
||||
|
|
@ -584,6 +598,7 @@ export function setFormEvaluationSaga(
|
|||
formId,
|
||||
actionConfiguration,
|
||||
currentEvalState,
|
||||
editorContextType || ActionParentEntityType.PAGE,
|
||||
actionDiffPath,
|
||||
hasRouteChanged,
|
||||
datasourceConfiguration,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user