PromucFlow_constructor/app/client/src/utils/JSPaneUtils.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

312 lines
8.3 KiB
TypeScript

//check difference for after body change and parsing
import type { JSCollection, JSAction, Variable } from "entities/JSCollection";
import { ENTITY_TYPE } from "ee/entities/AppsmithConsole/utils";
import LOG_TYPE from "entities/AppsmithConsole/logtype";
import AppsmithConsole from "utils/AppsmithConsole";
export interface ParsedJSSubAction {
name: string;
body: string;
arguments: Array<Variable>;
}
export interface ParsedBody {
actions: Array<ParsedJSSubAction>;
variables: Array<Variable>;
}
export interface JSUpdate {
id: string;
parsedBody: ParsedBody | undefined;
}
export interface JSCollectionDifference {
newActions: Partial<JSAction>[];
updateActions: JSAction[];
deletedActions: JSAction[];
nameChangedActions: Array<{
id: string;
collectionId?: string;
oldName: string;
newName: string;
pageId: string;
moduleId?: string;
workflowId?: string;
}>;
changedVariables: Variable[];
}
export const getDifferenceInJSCollection = (
parsedBody: ParsedBody,
jsAction: JSCollection,
): JSCollectionDifference => {
const newActions: ParsedJSSubAction[] = [];
const toBearchivedActions: JSAction[] = [];
const toBeUpdatedActions: JSAction[] = [];
const nameChangedActions = [];
const toBeAddedActions: Partial<JSAction>[] = [];
//check if body is changed and update if exists or
// add to new array so it can be added to main collection
if (parsedBody.actions && parsedBody.actions.length > 0) {
for (let i = 0; i < parsedBody.actions.length; i++) {
const action = parsedBody.actions[i];
const preExisted = jsAction.actions.find((js) => js.name === action.name);
if (preExisted) {
if (preExisted.actionConfiguration.body !== action.body) {
toBeUpdatedActions.push({
...preExisted,
actionConfiguration: {
...preExisted.actionConfiguration,
body: action.body,
jsArguments: action.arguments,
},
});
}
} else {
newActions.push(action);
}
}
}
//create deleted action list
if (jsAction.actions && jsAction.actions.length > 0 && parsedBody.actions) {
for (let i = 0; i < jsAction.actions.length; i++) {
const preAction = jsAction.actions[i];
const existed = parsedBody.actions.find(
(js: ParsedJSSubAction) => js.name === preAction.name,
);
if (!existed) {
toBearchivedActions.push(preAction);
}
}
}
//check if new is name changed from deleted actions
if (toBearchivedActions.length && newActions.length) {
for (let i = 0; i < newActions.length; i++) {
const nameChange = toBearchivedActions.find(
(js) => js.actionConfiguration.body === newActions[i].body,
);
if (nameChange) {
const updateExisting = jsAction.actions.find(
(js) => js.id === nameChange.id,
);
if (updateExisting) {
const indexOfArchived = toBearchivedActions.findIndex((js) => {
js.id === updateExisting.id;
});
//will be part of new nameChangedActions for now
toBeUpdatedActions.push({
...updateExisting,
name: newActions[i].name,
});
nameChangedActions.push({
id: updateExisting.id,
collectionId: updateExisting.collectionId,
oldName: updateExisting.name,
newName: newActions[i].name,
pageId: updateExisting.pageId,
moduleId: updateExisting.moduleId,
workflowId: updateExisting.workflowId,
});
newActions.splice(i, 1);
toBearchivedActions.splice(indexOfArchived, 1);
}
}
}
}
if (newActions.length > 0) {
for (let i = 0; i < newActions.length; i++) {
const action = newActions[i];
const obj = {
name: action.name,
collectionId: jsAction.id,
executeOnLoad: false,
pageId: jsAction.pageId,
workspaceId: jsAction.workspaceId,
actionConfiguration: {
body: action.body,
timeoutInMillisecond: 0,
jsArguments: action.arguments || [],
},
};
toBeAddedActions.push(obj);
}
}
if (toBearchivedActions.length > 0) {
for (let i = 0; i < toBearchivedActions.length; i++) {
const action = toBearchivedActions[i];
const deleteArchived = jsAction.actions.findIndex((js) => {
action.id === js.id;
});
jsAction.actions.splice(deleteArchived, 1);
}
}
//change in variables. In cases the variable list is not present, jsAction.variables will be undefined
// we are setting to empty array to avoid undefined errors further in the code (especially in case of workflows main file)
const varList = jsAction.variables || [];
let changedVariables: Array<Variable> = [];
if (parsedBody.variables.length) {
for (let i = 0; i < parsedBody.variables.length; i++) {
const newVar = parsedBody.variables[i];
const existedVar = varList.find((item) => item.name === newVar.name);
if (!!existedVar) {
const existedValue = existedVar.value;
if (
(!!existedValue &&
existedValue.toString() !==
(newVar.value && newVar.value.toString())) ||
(!existedValue && !!newVar.value)
) {
changedVariables.push(newVar);
}
} else {
changedVariables.push(newVar);
}
}
} else {
changedVariables = varList;
}
//delete variable
if (varList && varList.length > 0 && parsedBody.variables) {
for (let i = 0; i < varList.length; i++) {
const preVar = varList[i];
const existed = parsedBody.variables.find(
(jsVar: Variable) => jsVar.name === preVar.name,
);
if (!existed) {
const newvarList = varList.filter(
(deletedVar) => deletedVar.name !== preVar.name,
);
changedVariables = changedVariables.concat(newvarList);
}
}
}
return {
newActions: toBeAddedActions,
updateActions: toBeUpdatedActions,
deletedActions: toBearchivedActions,
nameChangedActions: nameChangedActions,
changedVariables: changedVariables,
};
};
export const pushLogsForObjectUpdate = (
actions: Partial<JSAction>[],
jsCollection: JSCollection,
text: string,
) => {
for (let i = 0; i < actions.length; i++) {
AppsmithConsole.info({
logType: LOG_TYPE.JS_ACTION_UPDATE,
text: text,
source: {
type: ENTITY_TYPE.JSACTION,
name: jsCollection.name + "." + actions[i].name,
id: jsCollection.id,
},
});
}
};
export const createDummyJSCollectionActions = (
workspaceId: string,
additionalParams: Record<string, unknown> = {},
) => {
const body =
"export default {\n\tmyVar1: [],\n\tmyVar2: {},\n\tmyFun1 () {\n\t\t//\twrite code here\n\t\t//\tthis.myVar1 = [1,2,3]\n\t},\n\tasync myFun2 () {\n\t\t//\tuse async-await or promises\n\t\t//\tawait storeValue('varName', 'hello world')\n\t}\n}";
const actions = [
{
name: "myFun1",
workspaceId,
executeOnLoad: false,
actionConfiguration: {
body: "function () {}",
timeoutInMillisecond: 0,
jsArguments: [],
},
clientSideExecution: true,
...additionalParams,
},
{
name: "myFun2",
workspaceId,
executeOnLoad: false,
actionConfiguration: {
body: "async function () {}",
timeoutInMillisecond: 0,
jsArguments: [],
},
clientSideExecution: true,
...additionalParams,
},
];
const variables = [
{
name: "myVar1",
value: "[]",
},
{
name: "myVar2",
value: "{}",
},
];
return {
actions,
body,
variables,
};
};
export const createSingleFunctionJsCollection = (
workspaceId: string,
functionName: string,
additionalParams: Record<string, unknown> = {},
) => {
const body = `export default {\n\t${functionName} () {\n\t\t//\twrite code here\n\t}\n}`;
const actions = [
{
name: functionName,
workspaceId,
executeOnLoad: false,
actionConfiguration: {
body: "function () {}",
timeoutInMillisecond: 0,
jsArguments: [],
},
clientSideExecution: true,
...additionalParams,
},
];
const variables: Variable[] = [];
return {
actions,
body,
variables,
};
};