chore: making body and variables as optional props- 31568 (#31665)

## Description
> [!TIP]  
> _Add a TL;DR when the description is longer than 500 words or
extremely technical (helps the content team)._
>
> _Please also include relevant motivation and context. List any
dependencies that are required for this change. Add links to Notion,
Figma or any other documents that might be relevant to the PR._

Fixes #`Issue Number`  
_or_  
Fixes https://github.com/appsmithorg/appsmith/issues/31568
> [!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  -->
> [!IMPORTANT]  
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/8325305172>
> Commit: `ce37f05a17f494b1a5409cf79895248cc32f453f`
> Cypress dashboard url: <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8325305172&attempt=2"
target="_blank">Click here!</a>
> All cypress tests have passed 🎉🎉🎉

<!-- end of auto-generated comment: Cypress test results  -->
This commit is contained in:
Apeksha Bhosale 2024-03-20 19:03:52 +05:30 committed by GitHub
parent 0f28934491
commit 54a9d06fb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 69 additions and 45 deletions

View File

@ -20,11 +20,12 @@ export const generateDataTreeJSAction = (
const dynamicBindingPathList = [];
const bindingPaths: Record<string, EvaluationSubstitutionType> = {};
const variableList: Record<string, any> = {};
const variables = js.config.variables;
const variables = js.config?.variables;
const listVariables: Array<string> = [];
dynamicBindingPathList.push({ key: "body" });
const removeThisReference = js.config.body.replace(reg, `${js.config.name}.`);
const removeThisReference =
js.config.body && js.config.body.replace(reg, `${js.config.name}.`);
bindingPaths["body"] = EvaluationSubstitutionType.SMART_SUBSTITUTE;
if (variables) {
@ -44,7 +45,7 @@ export const generateDataTreeJSAction = (
for (let i = 0; i < actions.length; i++) {
const action = actions[i];
meta[action.name] = {
arguments: action.actionConfiguration?.jsArguments,
arguments: action.actionConfiguration?.jsArguments || [],
confirmBeforeExecute: !!action.confirmBeforeExecute,
};
bindingPaths[action.name] = EvaluationSubstitutionType.SMART_SUBSTITUTE;

View File

@ -85,7 +85,7 @@ export interface JSActionEntityConfig extends EntityConfig {
dynamicBindingPathList: DynamicPath[];
bindingPaths: Record<string, EvaluationSubstitutionType>;
reactivePaths: Record<string, EvaluationSubstitutionType>;
variables: Array<string>;
variables?: Array<string>;
dependencyMap: DependencyMap;
pluginType: PluginType.JS;
name: string;
@ -98,7 +98,7 @@ export interface JSActionEntityConfig extends EntityConfig {
export interface JSActionEntity {
[propName: string]: any;
body: string;
body?: string;
ENTITY_TYPE: typeof ENTITY_TYPE.JSACTION;
actionId: string;
}

View File

@ -89,10 +89,12 @@ export const entityDefGeneratorMap: EntityDefGeneratorMap = {
jsPropertiesDef[`${funcName}.data`] = funcTypeDef.data;
}
for (let i = 0; i < entityConfig?.variables?.length; i++) {
const varKey = entityConfig?.variables[i];
const varValue = (entity as JSActionEntity)[varKey];
jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine);
if (entityConfig.variables) {
for (let i = 0; i < entityConfig?.variables?.length; i++) {
const varKey = entityConfig?.variables[i];
const varValue = (entity as JSActionEntity)[varKey];
jsPropertiesDef[varKey] = generateTypeDef(varValue, extraDefsToDefine);
}
}
def[entityName] = jsPropertiesDef;

View File

@ -16,8 +16,8 @@ export interface JSCollection {
pluginId: string;
pluginType: PluginType.JS;
actions: Array<JSAction>;
body: string;
variables: Array<Variable>;
body?: string;
variables?: Array<Variable>;
userPermissions?: string[];
errorReports?: Array<LayoutOnLoadActionErrors>;
isPublic?: boolean;
@ -33,9 +33,9 @@ export interface JSCollection {
}
export interface JSActionConfig {
body: string;
body?: string;
timeoutInMillisecond: number;
jsArguments: Array<Variable>;
jsArguments?: Array<Variable>;
}
export interface JSAction extends BaseAction {
actionConfiguration: JSActionConfig;

View File

@ -162,22 +162,24 @@ function JSEditorForm({
// Hash here could mean to navigate (set cursor/focus) to a particular function
// If the hash has a function name in this JS Object, we will set that
const actionName = hash.substring(1);
const position = getJSPropertyLineFromName(
currentJSCollection.body,
actionName,
);
if (position) {
// Resetting the focus and position based on the cmd click navigation
dispatch(setFocusableInputField(`${currentJSCollection.name}.body`));
dispatch(
setCodeEditorCursorAction(
`${currentJSCollection.name}.body`,
position,
CursorPositionOrigin.Navigation,
),
if (currentJSCollection.body) {
const position = getJSPropertyLineFromName(
currentJSCollection.body,
actionName,
);
// Replace to remove the hash and set back the original URL
history.replace(window.location.pathname + window.location.search);
if (position) {
// Resetting the focus and position based on the cmd click navigation
dispatch(setFocusableInputField(`${currentJSCollection.name}.body`));
dispatch(
setCodeEditorCursorAction(
`${currentJSCollection.name}.body`,
position,
CursorPositionOrigin.Navigation,
),
);
// Replace to remove the hash and set back the original URL
history.replace(window.location.pathname + window.location.search);
}
}
}
}, [hash]);

View File

@ -55,7 +55,7 @@ export class JSLintEntityParser implements EntityParser {
parsedEntityConfig: {},
};
parse(entity: TJSActionEntity, entityConfig: JSActionEntityConfig) {
const jsEntityBody = entity.body;
const jsEntityBody = entity.body || "";
if (
this.#parsedJSCache &&
jsEntityBody === this.#parsedJSCache.parsedEntity.body

View File

@ -18,7 +18,7 @@ export const getJsChildrenNavData = (
let childNavData: EntityNavigationData = {};
const dataTreeAction = dataTree[jsAction.config.name] as JSActionEntity;
const jsActionVariables = jsAction.config.variables || [];
if (dataTreeAction) {
let children: NavigationData[] = jsAction.config.actions.map((jsChild) => {
return createNavData({
@ -36,7 +36,7 @@ export const getJsChildrenNavData = (
});
});
const variableChildren: NavigationData[] = jsAction.config.variables.map(
const variableChildren: NavigationData[] = jsActionVariables.map(
(jsChild) => {
return createNavData({
id: `${jsAction.config.name}.${jsChild.name}`,

View File

@ -1,4 +1,4 @@
import { get, isEmpty, set } from "lodash";
import { get, isEmpty, isUndefined, set } from "lodash";
import type { JSActionEntity } from "@appsmith/entities/DataTree/types";
import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes";
import { EvalErrorTypes, getEvalValuePath } from "utils/DynamicBindingUtils";
@ -85,10 +85,16 @@ export function saveResolvedFunctionsAndJSUpdates(
entityName: string,
) {
jsPropertiesState.delete(entityName);
const correctFormat = validJSBodyRegex.test(entity.body);
const isEmptyBody = entity.body.trim() === "";
const correctFormat =
entity.hasOwnProperty("body") &&
!isUndefined(entity.body) &&
validJSBodyRegex.test(entity.body);
const isEmptyBody =
entity.hasOwnProperty("body") &&
!isUndefined(entity.body) &&
entity?.body.trim() === "";
if (correctFormat || isEmptyBody) {
if (!isUndefined(entity.body) && (correctFormat || isEmptyBody)) {
try {
JSObjectCollection.deleteResolvedFunction(entityName);
JSObjectCollection.deleteUnEvalState(entityName);
@ -196,9 +202,19 @@ export function saveResolvedFunctionsAndJSUpdates(
} catch (e) {
//if we need to push error as popup in case
}
} else {
const parsedBody = {
body: entity.body,
actions: [],
variables: [],
};
set(jsUpdates, `${entityName}`, {
parsedBody: parsedBody,
id: entity.actionId,
});
}
if (!correctFormat) {
if (!correctFormat && !isUndefined(entity.body)) {
const errors = {
type: EvalErrorTypes.PARSE_JS_ERROR,
context: {

View File

@ -46,7 +46,7 @@ export const updateJSCollectionInUnEvalTree = (
const modifiedUnEvalTree = unEvalTree;
const functionsList: Array<string> = [];
const jsEntityConfig = configTree[entityName] as JSActionEntityConfig;
const varList: Array<string> = jsEntityConfig?.variables;
const varList: Array<string> | undefined = jsEntityConfig?.variables;
Object.keys(jsEntityConfig?.meta).forEach((action) => {
functionsList.push(action);
});
@ -134,7 +134,7 @@ export const updateJSCollectionInUnEvalTree = (
}
}
}
if (parsedBody.variables.length) {
if (parsedBody.variables.length && varList) {
for (let i = 0; i < parsedBody.variables.length; i++) {
const newVar = parsedBody.variables[i];
const existedVar = varList.indexOf(newVar.name);
@ -210,14 +210,17 @@ export const removeFunctionsAndVariableJSCollection = (
functionsList.push(action);
});
//removed variables
const varList: Array<string> = oldConfig.variables;
const varList: Array<string> | undefined = oldConfig.variables;
set(oldConfig, `${entityName}.variables`, []);
for (let i = 0; i < varList.length; i++) {
const varName = varList[i];
unset(modifiedDataTree[entityName], varName);
// When user updates the JSObject all the variable's reset's to initial value
JSObjectCollection.removeVariable(`${entityName}.${varName}`);
if (varList) {
for (let i = 0; i < varList.length; i++) {
const varName = varList[i];
unset(modifiedDataTree[entityName], varName);
// When user updates the JSObject all the variable's reset's to initial value
JSObjectCollection.removeVariable(`${entityName}.${varName}`);
}
}
//remove functions
const reactivePaths = entity.reactivePaths;
const meta = entity.meta;
@ -264,7 +267,7 @@ export function isJSObjectVariable(
const entity = configTree[jsObjectName];
const variables = entityConfig.variables;
return (
isJSAction(entity as unknown as DataTreeEntity) && variables.includes(key)
isJSAction(entity as unknown as DataTreeEntity) && variables?.includes(key)
);
}