From c8d661ab0241a1662d7f4431b8aa673370c21d50 Mon Sep 17 00:00:00 2001 From: arunvjn <32433245+arunvjn@users.noreply.github.com> Date: Tue, 10 Oct 2023 12:38:45 +0530 Subject: [PATCH 01/75] chore: prevent mutation during evaluation and execution (#27722) ## Description Fixes the data mutation bug introduced back in [#11001](https://github.com/appsmithorg/appsmith/pull/11001). We now create 2 data tree in evaluation flow, one that is set against the execution context (prone to mutation) and another one which only gets the values of the path that is being evaluated. Accidental mutation often crashes the app. To replicate the issue 1. D&D a text widget and an Input widget 2. In the input widget default text field, write `{{ Text1.text = 123 }}` Context - https://theappsmith.slack.com/archives/C02K0SZQ7V3/p1695975703880489 #### PR fixes following issue(s) Fixes #19221 > > #### Type of change - Bug fix (non-breaking change which fixes an issue) > > ## Testing > #### How Has This Been Tested? - [x] Manual - [x] Jest > > #### Test Plan - [x] Test evaluations across widgets, framework functions, setter methods - [x] Existing application sanity check - [x] Template apps and CRUD > > #### Issues raised during DP testing none > > > ## Checklist: #### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [x] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [x] 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 - [x] 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 --- .../ce/workers/Evaluation/evaluationUtils.ts | 30 +- .../Evaluation/__tests__/evaluation.test.ts | 34 ++ .../src/workers/Evaluation/dataStore/index.ts | 17 +- .../workers/Evaluation/evalTreeWithChanges.ts | 8 - .../src/workers/Evaluation/fns/storeFns.ts | 14 +- .../Evaluation/handlers/evalExpression.ts | 3 +- .../workers/Evaluation/handlers/evalTree.ts | 15 - .../Evaluation/handlers/evalTrigger.ts | 5 +- .../workers/common/DataTreeEvaluator/index.ts | 536 ++++++++++-------- 9 files changed, 368 insertions(+), 294 deletions(-) diff --git a/app/client/src/ce/workers/Evaluation/evaluationUtils.ts b/app/client/src/ce/workers/Evaluation/evaluationUtils.ts index 409511eac7..bf99148ca7 100644 --- a/app/client/src/ce/workers/Evaluation/evaluationUtils.ts +++ b/app/client/src/ce/workers/Evaluation/evaluationUtils.ts @@ -782,6 +782,7 @@ export const overrideWidgetProperties = (params: { isNewWidget: boolean; shouldUpdateGlobalContext?: boolean; overriddenProperties?: string[]; + safeTree?: DataTree; }) => { const { configTree, @@ -792,14 +793,15 @@ export const overrideWidgetProperties = (params: { isNewWidget, overriddenProperties, propertyPath, + safeTree, shouldUpdateGlobalContext, value, } = params; - const clonedValue = klona(value); const { entityName } = getEntityNameAndPropertyPath(fullPropertyPath); const configEntity = configTree[entityName] as WidgetEntityConfig; if (propertyPath in configEntity.overridingPropertyPaths) { + const clonedValue = klona(value); const overridingPropertyPaths = configEntity.overridingPropertyPaths[propertyPath]; @@ -812,14 +814,12 @@ export const overrideWidgetProperties = (params: { overridingPropertyPaths.forEach((overriddenPropertyPath) => { const overriddenPropertyPathArray = overriddenPropertyPath.split("."); if (pathsNotToOverride.includes(overriddenPropertyPath)) return; - _.set( - currentTree, - [entityName, ...overriddenPropertyPathArray], - clonedValue, - ); + const fullPath = [entityName, ...overriddenPropertyPathArray]; + _.set(currentTree, fullPath, clonedValue); + if (safeTree) _.set(safeTree, fullPath, klona(value)); if (shouldUpdateGlobalContext) { - _.set(self, [entityName, ...overriddenPropertyPathArray], clonedValue); + _.set(self, fullPath, clonedValue); } overriddenProperties?.push(overriddenPropertyPath); // evalMetaUpdates has all updates from property which overrides meta values. @@ -837,7 +837,7 @@ export const overrideWidgetProperties = (params: { }); } else if ( propertyPath in configEntity.propertyOverrideDependency && - clonedValue === undefined + value === undefined ) { // When a reset a widget its meta value becomes undefined, ideally they should reset to default value. // below we handle logic to reset meta values to default values. @@ -845,17 +845,14 @@ export const overrideWidgetProperties = (params: { configEntity.propertyOverrideDependency[propertyPath]; if (propertyOverridingKeyMap.DEFAULT) { const defaultValue = entity[propertyOverridingKeyMap.DEFAULT]; - const clonedDefaultValue = klona(defaultValue); if (defaultValue !== undefined) { - const propertyPathArray = propertyPath.split("."); - _.set( - currentTree, - [entityName, ...propertyPathArray], - clonedDefaultValue, - ); + const clonedDefaultValue = klona(defaultValue); + const fullPath = [entityName, ...propertyPath.split(".")]; + _.set(currentTree, fullPath, clonedDefaultValue); + if (safeTree) _.set(safeTree, fullPath, klona(defaultValue)); if (shouldUpdateGlobalContext) { - _.set(self, [entityName, ...propertyPathArray], clonedDefaultValue); + _.set(self, fullPath, clonedDefaultValue); } return { @@ -866,6 +863,7 @@ export const overrideWidgetProperties = (params: { } } }; + export function isValidEntity( entity: DataTreeEntity, ): entity is DataTreeEntityObject { diff --git a/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts b/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts index ff16a9cbf6..4c3880bbb5 100644 --- a/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts @@ -988,4 +988,38 @@ describe("DataTreeEvaluator", () => { // @ts-expect-error: Types are not available expect(dataTree3.Api2.config.body).toBe("{ 'name': \"Test\" }"); }); + it("Prevents data mutation in eval cycle", () => { + const { configEntity, unEvalEntity } = generateDataTreeWidget( + { + ...BASE_WIDGET_CONFIG, + ...BASE_WIDGET, + widgetName: "TextX", + text: "{{Text1.text = 123}}", + dynamicBindingPathList: [{ key: "text" }], + type: "TEXT_WIDGET", + }, + {}, + new Set(), + ); + const updatedUnEvalTree = { + ...unEvalTree, + TextX: unEvalEntity, + }; + const updatedConfigTree = { + ...configTree, + TextX: configEntity, + }; + const { evalOrder, nonDynamicFieldValidationOrder, unEvalUpdates } = + evaluator.setupUpdateTree(updatedUnEvalTree, updatedConfigTree); + expect(evalOrder).toContain("TextX.text"); + evaluator.evalAndValidateSubTree( + evalOrder, + nonDynamicFieldValidationOrder, + updatedConfigTree, + unEvalUpdates, + ); + const dataTree = evaluator.evalTree; + expect(dataTree).toHaveProperty("TextX.text", 123); + expect(dataTree).toHaveProperty("Text1.text", "Label"); + }); }); diff --git a/app/client/src/workers/Evaluation/dataStore/index.ts b/app/client/src/workers/Evaluation/dataStore/index.ts index 71948f0b7d..d83fc696d4 100644 --- a/app/client/src/workers/Evaluation/dataStore/index.ts +++ b/app/client/src/workers/Evaluation/dataStore/index.ts @@ -8,27 +8,32 @@ export default class DataStore { private static store: TDataStore = {}; static setActionData(fullPath: string, value: unknown) { - set(this.store, fullPath, value); + set(DataStore.store, fullPath, value); } static getActionData(fullPath: string): unknown | undefined { - return get(this.store, fullPath, undefined); + return get(DataStore.store, fullPath, undefined); } static getDataStore() { - return this.store; + return DataStore.store; } static deleteActionData(fullPath: string) { - unset(this.store, fullPath); + unset(DataStore.store, fullPath); } static clear() { - this.store = {}; + DataStore.store = {}; } + + static replaceDataStore(store: TDataStore) { + DataStore.store = store; + } + static update(dataTreeDiff: Diff[]) { const deleteDiffs = dataTreeDiff.filter((diff) => diff.kind === "D"); deleteDiffs.forEach((diff) => { const deletedPath = diff.path || []; const deletedPathString = convertPathToString(deletedPath); - this.deleteActionData(deletedPathString); + DataStore.deleteActionData(deletedPathString); }); } } diff --git a/app/client/src/workers/Evaluation/evalTreeWithChanges.ts b/app/client/src/workers/Evaluation/evalTreeWithChanges.ts index 0f9d8d4693..28a9b2523d 100644 --- a/app/client/src/workers/Evaluation/evalTreeWithChanges.ts +++ b/app/client/src/workers/Evaluation/evalTreeWithChanges.ts @@ -13,7 +13,6 @@ import { MessageType, sendMessage } from "utils/MessageUtil"; import { MAIN_THREAD_ACTION } from "@appsmith/workers/Evaluation/evalWorkerActions"; import type { UpdateDataTreeMessageData } from "sagas/EvalWorkerActionSagas"; import type { JSUpdate } from "utils/JSPaneUtils"; -import { setEvalContext } from "./evaluate"; import { generateOptimisedUpdatesAndSetPrevState } from "./helpers"; export function evalTreeWithChanges( @@ -55,13 +54,6 @@ export function evalTreeWithChanges( reValidatedPaths = updateResponse.reValidatedPaths; - setEvalContext({ - dataTree: dataTreeEvaluator.getEvalTree(), - configTree: dataTreeEvaluator.getConfigTree(), - isDataField: false, - isTriggerBased: true, - }); - dataTree = makeEntityConfigsAsObjProperties(dataTreeEvaluator.evalTree, { evalProps: dataTreeEvaluator.evalProps, identicalEvalPathsPatches: diff --git a/app/client/src/workers/Evaluation/fns/storeFns.ts b/app/client/src/workers/Evaluation/fns/storeFns.ts index ea308f9682..e9605ab2dc 100644 --- a/app/client/src/workers/Evaluation/fns/storeFns.ts +++ b/app/client/src/workers/Evaluation/fns/storeFns.ts @@ -1,5 +1,7 @@ import set from "lodash/set"; import TriggerEmitter, { BatchKey } from "./utils/TriggerEmitter"; +import { dataTreeEvaluator } from "../handlers/evalTree"; +import unset from "lodash/unset"; function storeFnDescriptor(key: string, value: string, persist = true) { return { @@ -22,7 +24,10 @@ export async function storeValue( value: string, persist = true, ) { - set(this, ["appsmith", "store", key], value); + const evalTree = dataTreeEvaluator?.getEvalTree(); + const path = ["appsmith", "store", key]; + if (evalTree) set(evalTree, path, value); + set(this, path, value); TriggerEmitter.emit( BatchKey.process_store_updates, storeFnDescriptor(key, value, persist), @@ -46,7 +51,10 @@ export type TRemoveValueDescription = ReturnType< export type TRemoveValueActionType = TRemoveValueDescription["type"]; export async function removeValue(this: any, key: string) { - delete this.appsmith.store[key]; + const evalTree = dataTreeEvaluator?.getEvalTree(); + const path = ["appsmith", "store", key]; + if (evalTree) unset(evalTree, path); + unset(this, path); TriggerEmitter.emit( BatchKey.process_store_updates, removeValueFnDescriptor(key), @@ -66,6 +74,8 @@ export type TClearStoreDescription = ReturnType; export type TClearStoreActionType = TClearStoreDescription["type"]; export async function clearStore(this: any) { + const evalTree = dataTreeEvaluator?.getEvalTree(); + if (evalTree) set(evalTree, ["appsmith", "store"], {}); this.appsmith.store = {}; TriggerEmitter.emit(BatchKey.process_store_updates, clearStoreFnDescriptor()); return {}; diff --git a/app/client/src/workers/Evaluation/handlers/evalExpression.ts b/app/client/src/workers/Evaluation/handlers/evalExpression.ts index 9f48afc9ec..3018159cec 100644 --- a/app/client/src/workers/Evaluation/handlers/evalExpression.ts +++ b/app/client/src/workers/Evaluation/handlers/evalExpression.ts @@ -1,3 +1,4 @@ +import { klona } from "klona/full"; import { evaluateAsync } from "../evaluate"; import type { EvalWorkerASyncRequest } from "../types"; import { dataTreeEvaluator } from "./evalTree"; @@ -8,5 +9,5 @@ export default function (request: EvalWorkerASyncRequest) { const evalTree = dataTreeEvaluator?.evalTree; const configTree = dataTreeEvaluator?.configTree; if (!evalTree || !configTree) return {}; - return evaluateAsync(expression, evalTree, configTree, {}, undefined); + return evaluateAsync(expression, klona(evalTree), configTree, {}, undefined); } diff --git a/app/client/src/workers/Evaluation/handlers/evalTree.ts b/app/client/src/workers/Evaluation/handlers/evalTree.ts index 4cea458c17..7be32dce8c 100644 --- a/app/client/src/workers/Evaluation/handlers/evalTree.ts +++ b/app/client/src/workers/Evaluation/handlers/evalTree.ts @@ -20,7 +20,6 @@ import type { } from "../types"; import { clearAllIntervals } from "../fns/overrides/interval"; import JSObjectCollection from "workers/Evaluation/JSObject/Collection"; -import { setEvalContext } from "../evaluate"; import { getJSVariableCreatedEvents } from "../JSObject/JSVariableEvents"; import { errorModifier } from "../errorModifier"; import { generateOptimisedUpdatesAndSetPrevState } from "../helpers"; @@ -117,13 +116,6 @@ export default function (request: EvalWorkerSyncRequest) { const dataTreeResponse = dataTreeEvaluator.evalAndValidateFirstTree(); - setEvalContext({ - dataTree: dataTreeEvaluator.evalTree, - configTree, - isDataField: false, - isTriggerBased: true, - }); - dataTree = makeEntityConfigsAsObjProperties(dataTreeResponse.evalTree, { evalProps: dataTreeEvaluator.evalProps, identicalEvalPathsPatches: @@ -164,13 +156,6 @@ export default function (request: EvalWorkerSyncRequest) { reValidatedPaths = updateResponse.reValidatedPaths; - setEvalContext({ - dataTree: dataTreeEvaluator.evalTree, - configTree, - isDataField: false, - isTriggerBased: true, - }); - dataTree = makeEntityConfigsAsObjProperties(dataTreeEvaluator.evalTree, { evalProps: dataTreeEvaluator.evalProps, identicalEvalPathsPatches: diff --git a/app/client/src/workers/Evaluation/handlers/evalTrigger.ts b/app/client/src/workers/Evaluation/handlers/evalTrigger.ts index 33732a6e3a..8970a242ca 100644 --- a/app/client/src/workers/Evaluation/handlers/evalTrigger.ts +++ b/app/client/src/workers/Evaluation/handlers/evalTrigger.ts @@ -24,17 +24,16 @@ export default async function (request: EvalWorkerASyncRequest) { unEvalTree.configTree, ); - dataTreeEvaluator.evalAndValidateSubTree( + const { contextTree } = dataTreeEvaluator.evalAndValidateSubTree( evalOrder, nonDynamicFieldValidationOrder, unEvalTree.configTree, unEvalUpdates, ); - const evalTree = dataTreeEvaluator.evalTree; return dataTreeEvaluator.evaluateTriggers( dynamicTrigger, - evalTree, + contextTree, unEvalTree.configTree, callbackData, { diff --git a/app/client/src/workers/common/DataTreeEvaluator/index.ts b/app/client/src/workers/common/DataTreeEvaluator/index.ts index 0cdf836b56..4ec054d5b9 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/index.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/index.ts @@ -81,7 +81,10 @@ import { THIS_DOT_PARAMS_KEY, } from "constants/AppsmithActionConstants/ActionConstants"; import type { EvalResult, EvaluateContext } from "workers/Evaluation/evaluate"; -import evaluateSync, { evaluateAsync } from "workers/Evaluation/evaluate"; +import evaluateSync, { + evaluateAsync, + setEvalContext, +} from "workers/Evaluation/evaluate"; import { substituteDynamicBindingWithValues } from "workers/Evaluation/evaluationSubstitution"; import { Severity } from "entities/AppsmithConsole"; import { error as logError } from "loglevel"; @@ -338,9 +341,10 @@ export default class DataTreeEvaluator { const evaluationOrder = this.sortedDependencies; + const unEvalTreeClone = klonaJSON(this.oldUnEvalTree); // Evaluate const { evalMetaUpdates, evaluatedTree, staleMetaIds } = this.evaluateTree( - this.oldUnEvalTree, + unEvalTreeClone, evaluationOrder, undefined, this.oldConfigTree, @@ -771,10 +775,12 @@ export default class DataTreeEvaluator { evalMetaUpdates: EvalMetaUpdates; staleMetaIds: string[]; reValidatedPaths: string[]; + contextTree: DataTree; } { const evaluationStartTime = performance.now(); const { + contextTree, evalMetaUpdates, evaluatedTree: newEvalTree, staleMetaIds, @@ -818,6 +824,7 @@ export default class DataTreeEvaluator { evalMetaUpdates, staleMetaIds, reValidatedPaths: pathsToValidate, + contextTree, }; } @@ -919,7 +926,7 @@ export default class DataTreeEvaluator { } evaluateTree( - oldUnevalTree: DataTree, + unEvalTree: DataTree, evaluationOrder: Array, options: { isFirstTree: boolean; @@ -935,12 +942,24 @@ export default class DataTreeEvaluator { evaluatedTree: DataTree; evalMetaUpdates: EvalMetaUpdates; staleMetaIds: string[]; + contextTree: DataTree; } { - const tree = klona(oldUnevalTree); - updateTreeWithData(tree, klonaJSON(DataStore.getDataStore())); + const safeTree = klona(unEvalTree); + const dataStore = DataStore.getDataStore(); + const dataStoreClone = klonaJSON(dataStore); + updateTreeWithData(safeTree, dataStoreClone); + updateTreeWithData(unEvalTree, dataStore); + + /** + * contextTree is a mutable dataTree, it gets passed as a context for each evaluation + * and gets updated both, with evaluated values and mutations. + * + * SafeTree is free of mutations because we make sure to only set evaluated values into it. + */ + const contextTree = unEvalTree; errorModifier.updateAsyncFunctions( - tree, + contextTree, this.getConfigTree(), this.dependencyMap, ); @@ -949,248 +968,276 @@ export default class DataTreeEvaluator { const { isFirstTree, metaWidgets, unevalUpdates } = options; let staleMetaIds: string[] = []; try { - const evaluatedTree = evaluationOrder.reduce( - (currentTree: DataTree, fullPropertyPath: string) => { - const { entityName, propertyPath } = - getEntityNameAndPropertyPath(fullPropertyPath); - const entity = currentTree[entityName]; - const entityConfig = oldConfigTree[entityName]; - if (!isWidgetActionOrJsObject(entity, entityConfig)) - return currentTree; - let unEvalPropertyValue = get(currentTree as any, fullPropertyPath); + for (const fullPropertyPath of evaluationOrder) { + const { entityName, propertyPath } = + getEntityNameAndPropertyPath(fullPropertyPath); + const entity = contextTree[entityName]; + const entityConfig = oldConfigTree[entityName]; + if (!isWidgetActionOrJsObject(entity, entityConfig)) continue; - const isADynamicBindingPath = isAPathDynamicBindingPath( - entity, - entityConfig, + let unEvalPropertyValue = get(contextTree as any, fullPropertyPath); + + const isADynamicBindingPath = isAPathDynamicBindingPath( + entity, + entityConfig, + propertyPath, + ); + + const isATriggerPath = + isWidget(entity) && + isPathDynamicTrigger( + entityConfig as WidgetEntityConfig, propertyPath, ); + let evalPropertyValue; + const requiresEval = + isADynamicBindingPath && + !isATriggerPath && + (isDynamicValue(unEvalPropertyValue) || isJSAction(entity)); + if (propertyPath) { + set(this.evalProps, getEvalErrorPath(fullPropertyPath), []); + } - const isATriggerPath = - isWidget(entity) && - isPathDynamicTrigger( - entityConfig as WidgetEntityConfig, - propertyPath, + if (requiresEval) { + const evaluationSubstitutionType = + entityConfig?.reactivePaths?.[propertyPath] || + EvaluationSubstitutionType.TEMPLATE; + + const contextData: EvaluateContext = {}; + if (isAction(entity)) { + // Add empty object for this.params to avoid undefined errors + contextData.globalContext = { + [THIS_DOT_PARAMS_KEY]: {}, + }; + + unEvalPropertyValue = replaceThisDotParams(unEvalPropertyValue); + } + try { + evalPropertyValue = this.getDynamicValue( + unEvalPropertyValue, + contextTree, + oldConfigTree, + evaluationSubstitutionType, + contextData, + undefined, + fullPropertyPath, ); - let evalPropertyValue; - const requiresEval = - isADynamicBindingPath && - !isATriggerPath && - (isDynamicValue(unEvalPropertyValue) || isJSAction(entity)); - if (propertyPath) { - set(this.evalProps, getEvalErrorPath(fullPropertyPath), []); + } catch (error) { + this.errors.push({ + type: EvalErrorTypes.EVAL_PROPERTY_ERROR, + message: (error as Error).message, + context: { + propertyPath: fullPropertyPath, + }, + }); + evalPropertyValue = undefined; } + } else { + evalPropertyValue = unEvalPropertyValue; + } - if (requiresEval) { - const evaluationSubstitutionType = - (!!entityConfig && - entityConfig.hasOwnProperty("reactivePaths") && - entityConfig.reactivePaths[propertyPath]) || - EvaluationSubstitutionType.TEMPLATE; + this.updateUndefinedEvalValuesMap( + this.undefinedEvalValuesMap, + evalPropertyValue, + fullPropertyPath, + ); - const contextData: EvaluateContext = {}; - if (isAction(entity)) { - // Add empty object for this.params to avoid undefined errors - contextData.globalContext = { - [THIS_DOT_PARAMS_KEY]: {}, - }; + const entityType = entityConfig.ENTITY_TYPE; - unEvalPropertyValue = replaceThisDotParams(unEvalPropertyValue); - } - try { - evalPropertyValue = this.getDynamicValue( - unEvalPropertyValue, - currentTree, - oldConfigTree, - evaluationSubstitutionType, - contextData, - undefined, - fullPropertyPath, - ); - } catch (error) { - this.errors.push({ - type: EvalErrorTypes.EVAL_PROPERTY_ERROR, - message: (error as Error).message, - context: { - propertyPath: fullPropertyPath, - }, - }); - evalPropertyValue = undefined; - } - } else { - evalPropertyValue = unEvalPropertyValue; - } + if (!propertyPath) continue; - this.updateUndefinedEvalValuesMap( - this.undefinedEvalValuesMap, - evalPropertyValue, - fullPropertyPath, - ); + switch (entityType) { + case ENTITY_TYPE_VALUE.WIDGET: { + if (isATriggerPath) continue; - const entityType = entityConfig.ENTITY_TYPE; + const isNewWidget = + isFirstTree || isNewEntity(unevalUpdates, entityName); - if (!propertyPath) - return set(currentTree, fullPropertyPath, evalPropertyValue); + const widgetEntity = entity as WidgetEntity; - switch (entityType) { - case ENTITY_TYPE_VALUE.WIDGET: { - if (isATriggerPath) return currentTree; + let parsedValue = validateAndParseWidgetProperty({ + fullPropertyPath, + widget: widgetEntity, + configTree: oldConfigTree, + evalPropertyValue, + unEvalPropertyValue, + evalProps: this.evalProps, + evalPathsIdenticalToState: this.evalPathsIdenticalToState, + }); - const isNewWidget = - isFirstTree || isNewEntity(unevalUpdates, entityName); + parsedValue = this.getParsedValueForWidgetProperty({ + currentTree: contextTree, + configTree: oldConfigTree, + entity: widgetEntity, + evalMetaUpdates, + fullPropertyPath, + parsedValue, + propertyPath, + isNewWidget, + safeTree, + }); - const widgetEntity = entity as WidgetEntity; + // setting evalPropertyValue in unParsedEvalTree + set( + this.getUnParsedEvalTree(), + fullPropertyPath, + evalPropertyValue, + ); - const parsedValue = validateAndParseWidgetProperty({ - fullPropertyPath, - widget: widgetEntity, - configTree: oldConfigTree, - evalPropertyValue, - unEvalPropertyValue, - evalProps: this.evalProps, - evalPathsIdenticalToState: this.evalPathsIdenticalToState, - }); + set(contextTree, fullPropertyPath, parsedValue); + set(safeTree, fullPropertyPath, klona(parsedValue)); - this.setParsedValue({ - currentTree, - configTree: oldConfigTree, + staleMetaIds = staleMetaIds.concat( + getStaleMetaStateIds({ entity: widgetEntity, - evalMetaUpdates, - fullPropertyPath, - parsedValue, + entityConfig: entityConfig as WidgetEntityConfig, propertyPath, isNewWidget, - }); + metaWidgets, + }), + ); + break; + } + case ENTITY_TYPE_VALUE.ACTION: { + const configProperty = propertyPath.replace( + "config", + "actionConfiguration", + ); + const validationConfig = + this.allActionValidationConfig?.[entity.actionId]?.[ + configProperty + ]; + this.validateActionProperty( + fullPropertyPath, + entity as ActionEntity, + contextTree, + evalPropertyValue, + unEvalPropertyValue, + oldConfigTree, + validationConfig, + ); - // setting evalPropertyValue in unParsedEvalTree - set( - this.getUnParsedEvalTree(), - fullPropertyPath, - evalPropertyValue, - ); + if (!propertyPath) continue; - staleMetaIds = staleMetaIds.concat( - getStaleMetaStateIds({ - entity: widgetEntity, - entityConfig: entityConfig as WidgetEntityConfig, - propertyPath, - isNewWidget, - metaWidgets, - }), - ); + const evalPath = getEvalValuePath(fullPropertyPath); + setToEvalPathsIdenticalToState({ + evalPath, + evalPathsIdenticalToState: this.evalPathsIdenticalToState, + evalProps: this.evalProps, + isParsedValueTheSame: true, + fullPropertyPath, + value: evalPropertyValue, + }); - return currentTree; - } - case ENTITY_TYPE_VALUE.ACTION: { - if (this.allActionValidationConfig) { - const configProperty = propertyPath.replace( - "config", - "actionConfiguration", - ); - const validationConfig = - !!this.allActionValidationConfig[entity.actionId] && - this.allActionValidationConfig[entity.actionId][ - configProperty - ]; - if (!!validationConfig && !isEmpty(validationConfig)) { - this.validateActionProperty( - fullPropertyPath, - entity as ActionEntity, - currentTree, - evalPropertyValue, - unEvalPropertyValue, - validationConfig, - oldConfigTree, - ); - } - } + /** + * Perf optimization very specific to handling actions + * Fields like Api1.data doesn't get evaluated since it is not in dynamicBindingPathList + * Action validation only captures validation error and doesn't transform the evaluated values. + * This means that the values we are looking to set back in the 2 dataTrees are already there. + */ + if (!requiresEval) continue; - if (!propertyPath) return currentTree; + set(contextTree, fullPropertyPath, evalPropertyValue); + set(safeTree, fullPropertyPath, klona(evalPropertyValue)); + break; + } + case ENTITY_TYPE_VALUE.JSACTION: { + const variableList = + (entityConfig as JSActionEntityConfig).variables || []; + if (variableList.indexOf(propertyPath) === -1) break; - const evalPath = getEvalValuePath(fullPropertyPath); + const prevEvaluatedValue = get( + this.evalProps, + getEvalValuePath(fullPropertyPath, { + isPopulated: true, + fullPath: true, + }), + ); + + const prevUnEvalValue = JSObjectCollection.getPrevUnEvalState({ + fullPath: fullPropertyPath, + }); + + const hasUnEvalValueModified = !isEqual( + prevUnEvalValue, + unEvalPropertyValue, + ); + + const skipVariableValueAssignment = + !hasUnEvalValueModified && prevEvaluatedValue; + + const evalValue = skipVariableValueAssignment + ? prevEvaluatedValue + : evalPropertyValue; + + const evalPath = getEvalValuePath(fullPropertyPath, { + isPopulated: true, + //what is the purpose of this argument + fullPath: true, + }); + + /** Variables defined in a JS object are not reactive. + * Their evaluated values need to be reset only when the variable is modified by the user. + * When uneval value of a js variable hasn't changed, it means that the previously evaluated values are in both trees already */ + if (skipVariableValueAssignment) { setToEvalPathsIdenticalToState({ evalPath, evalPathsIdenticalToState: this.evalPathsIdenticalToState, evalProps: this.evalProps, isParsedValueTheSame: true, fullPropertyPath, - value: evalPropertyValue, + value: evalValue, + }); + } else { + const valueForSafeTree = klona(evalValue); + setToEvalPathsIdenticalToState({ + evalPath, + evalPathsIdenticalToState: this.evalPathsIdenticalToState, + evalProps: this.evalProps, + isParsedValueTheSame: true, + fullPropertyPath, + value: valueForSafeTree, }); - set(currentTree, fullPropertyPath, evalPropertyValue); - return currentTree; + set(contextTree, fullPropertyPath, evalValue); + set(safeTree, fullPropertyPath, valueForSafeTree); + JSObjectCollection.setVariableValue(evalValue, fullPropertyPath); + JSObjectCollection.setPrevUnEvalState({ + fullPath: fullPropertyPath, + unEvalValue: unEvalPropertyValue, + }); } - case ENTITY_TYPE_VALUE.JSACTION: { - const variableList = - (entityConfig as JSActionEntityConfig).variables || []; - - if (variableList.indexOf(propertyPath) > -1) { - const prevEvaluatedValue = get( - this.evalProps, - getEvalValuePath(fullPropertyPath, { - isPopulated: true, - fullPath: true, - }), - ); - - const prevUnEvalValue = JSObjectCollection.getPrevUnEvalState({ - fullPath: fullPropertyPath, - }); - - const hasUnEvalValueModified = !isEqual( - prevUnEvalValue, - unEvalPropertyValue, - ); - - const evalValue = - !hasUnEvalValueModified && prevEvaluatedValue - ? prevEvaluatedValue - : evalPropertyValue; - - const evalPath = getEvalValuePath(fullPropertyPath, { - isPopulated: true, - //what is the purpose of this argument - fullPath: true, - }); - - setToEvalPathsIdenticalToState({ - evalPath, - evalPathsIdenticalToState: this.evalPathsIdenticalToState, - evalProps: this.evalProps, - isParsedValueTheSame: true, - fullPropertyPath, - value: evalValue, - }); - - set(currentTree, fullPropertyPath, evalValue); - JSObjectCollection.setVariableValue( - evalValue, - fullPropertyPath, - ); - JSObjectCollection.setPrevUnEvalState({ - fullPath: fullPropertyPath, - unEvalValue: unEvalPropertyValue, - }); - } - return currentTree; - } - default: - return set(currentTree, fullPropertyPath, evalPropertyValue); + break; } - }, - tree, - ); - - return { - evaluatedTree, - evalMetaUpdates, - staleMetaIds: staleMetaIds, - }; + default: + set(contextTree, fullPropertyPath, evalPropertyValue); + set(safeTree, fullPropertyPath, klona(evalPropertyValue)); + } + } } catch (error) { + staleMetaIds = []; this.errors.push({ type: EvalErrorTypes.EVAL_TREE_ERROR, message: (error as Error).message, }); - return { evaluatedTree: tree, evalMetaUpdates, staleMetaIds: [] }; + } finally { + // Restore the dataStore since it was a part of contextTree and prone to mutation. + DataStore.replaceDataStore(dataStoreClone); + + // The below statement restores the execution context for async tasks are probably queued. + setEvalContext({ + dataTree: contextTree, + configTree: oldConfigTree, + isDataField: false, + isTriggerBased: true, + }); + + return { + evaluatedTree: safeTree, + contextTree: contextTree, + evalMetaUpdates, + staleMetaIds, + }; } } @@ -1446,7 +1493,7 @@ export default class DataTreeEvaluator { return evalResponse; } - setParsedValue({ + getParsedValueForWidgetProperty({ configTree, currentTree, entity, @@ -1455,6 +1502,7 @@ export default class DataTreeEvaluator { isNewWidget, parsedValue, propertyPath, + safeTree, }: { currentTree: DataTree; configTree: ConfigTree; @@ -1464,6 +1512,7 @@ export default class DataTreeEvaluator { isNewWidget: boolean; parsedValue: unknown; propertyPath: string; + safeTree?: DataTree; }) { const overwriteObj = overrideWidgetProperties({ entity, @@ -1474,13 +1523,14 @@ export default class DataTreeEvaluator { evalMetaUpdates, fullPropertyPath, isNewWidget, + safeTree, }); if (overwriteObj && overwriteObj.overwriteParsedValue) { parsedValue = overwriteObj.newValue; } - // setting parseValue in dataTree - set(currentTree, fullPropertyPath, parsedValue); + + return parsedValue; } validateEntityDependentProperty({ @@ -1535,39 +1585,37 @@ export default class DataTreeEvaluator { currentTree: DataTree, evalPropertyValue: any, unEvalPropertyValue: string, - validationConfig: ValidationConfig, configTree: ConfigTree, + validationConfig?: ValidationConfig, ) { - if (evalPropertyValue && validationConfig) { - // runs VALIDATOR function and returns errors - const { isValid, messages } = validateActionProperty( - validationConfig, - evalPropertyValue, - ); - if (!isValid) { - resetValidationErrorsForEntityProperty({ - evalProps: this.evalProps, - fullPropertyPath, - }); - const evalErrors: EvaluationError[] = - messages?.map((message) => { - return { - raw: unEvalPropertyValue, - errorMessage: message || { name: "", text: "" }, - errorType: PropertyEvaluationErrorType.VALIDATION, - severity: Severity.ERROR, - }; - }) ?? []; - // saves error in dataTree at fullPropertyPath - // Later errors can consumed by the forms and debugger - addErrorToEntityProperty({ - errors: evalErrors, - evalProps: this.evalProps, - fullPropertyPath, - configTree, - }); - } - } + if (!evalPropertyValue || isEmpty(validationConfig)) return; + // runs VALIDATOR function and returns errors + const { isValid, messages } = validateActionProperty( + validationConfig, + evalPropertyValue, + ); + if (isValid) return; + resetValidationErrorsForEntityProperty({ + evalProps: this.evalProps, + fullPropertyPath, + }); + const evalErrors: EvaluationError[] = + messages?.map((message) => { + return { + raw: unEvalPropertyValue, + errorMessage: message || { name: "", text: "" }, + errorType: PropertyEvaluationErrorType.VALIDATION, + severity: Severity.ERROR, + }; + }) ?? []; + // saves error in dataTree at fullPropertyPath + // Later errors can consumed by the forms and debugger + addErrorToEntityProperty({ + errors: evalErrors, + evalProps: this.evalProps, + fullPropertyPath, + configTree, + }); } /** @@ -1704,6 +1752,8 @@ export default class DataTreeEvaluator { ); } + const dataTree = klona(this.evalTree); + return bindings.map((binding) => { // Replace any reference of 'this.params' to 'executionParams' (backwards compatibility) // also helps with dealing with IIFE which are normal functions (not arrow) @@ -1714,7 +1764,7 @@ export default class DataTreeEvaluator { ); return this.getDynamicValue( `{{${replacedBinding}}}`, - this.evalTree, + dataTree, this.oldConfigTree, EvaluationSubstitutionType.TEMPLATE, // params can be accessed via "this.params" or "executionParams" From 02b4e02ffe4b464ad410f9975b445584f319052c Mon Sep 17 00:00:00 2001 From: NandanAnantharamu <67676905+NandanAnantharamu@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:51:33 +0530 Subject: [PATCH 02/75] test: cypress - commenting a test in Tab spec (#27916) Skipping a test in this Tab regression spec --- .../e2e/Regression/ClientSide/Widgets/Tab/Tabs_2_spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Tab/Tabs_2_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Tab/Tabs_2_spec.ts index eeca97b3f6..57240928a3 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Widgets/Tab/Tabs_2_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Widgets/Tab/Tabs_2_spec.ts @@ -178,7 +178,8 @@ describe("Tabs widget Tests", function () { propPane.SelectPropertiesDropDown("height", "Auto Height"); }); - it("7. Verify colors, borders and shadows", () => { + // to work on redesign of the test, commenting for now + it.skip("7. Verify colors, borders and shadows", () => { // Verify font color picker opens up propPane.MoveToTab("Style"); agHelper.GetNClick(propPane._propertyControlColorPicker("accentcolor")); From 317dae4479a1f944a8067557ab209549095d69aa Mon Sep 17 00:00:00 2001 From: ChandanBalajiBP <104058110+ChandanBalajiBP@users.noreply.github.com> Date: Tue, 10 Oct 2023 14:54:28 +0530 Subject: [PATCH 03/75] feat: Connection pooling CE (#27328) Co-authored-by: Ayush Pahwa Co-authored-by: Ayush Pahwa Co-authored-by: Ankita Kinger --- .../AdminSettings/Admin_settings_spec.js | 6 ++-- .../ExplorerTests/Admin_settings_1_spec.js | 12 +++---- .../ExplorerTests/Admin_settings_2_spec.js | 4 +-- app/client/cypress/locators/AdminsSettings.js | 2 +- .../cypress/support/Pages/AdminSettings.ts | 7 ++-- .../AdminSettings/BreadcrumbCategories.tsx | 8 +++-- .../config/DeveloperSettings/googleMaps.ts | 24 +++++++++++++ .../config/DeveloperSettings/index.ts | 17 ++++++++++ .../ce/pages/AdminSettings/config/index.ts | 4 +-- .../ce/pages/AdminSettings/config/types.ts | 3 +- .../components/utils/ReduxFormTextField.tsx | 7 ++-- .../config/DeveloperSettings/index.ts | 1 + .../AdminSettings/FormGroup/TextInput.tsx | 21 +++++++++++- .../src/pages/AdminSettings/SettingsForm.tsx | 5 +-- .../pages/AdminSettings/config/googleMaps.ts | 34 ------------------- 15 files changed, 93 insertions(+), 62 deletions(-) create mode 100644 app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/googleMaps.ts create mode 100644 app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/index.ts create mode 100644 app/client/src/ee/pages/AdminSettings/config/DeveloperSettings/index.ts delete mode 100644 app/client/src/pages/AdminSettings/config/googleMaps.ts diff --git a/app/client/cypress/e2e/Regression/ClientSide/AdminSettings/Admin_settings_spec.js b/app/client/cypress/e2e/Regression/ClientSide/AdminSettings/Admin_settings_spec.js index 640d6ffee6..dcc7cf26ec 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/AdminSettings/Admin_settings_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/AdminSettings/Admin_settings_spec.js @@ -62,8 +62,8 @@ describe("Admin settings page", function () { cy.url().should("contain", "/settings/authentication"); cy.get(adminsSettings.emailTab).click(); cy.url().should("contain", "/settings/email"); - cy.get(adminsSettings.googleMapsTab).click(); - cy.url().should("contain", "/settings/google-maps"); + cy.get(adminsSettings.developerSettingsTab).click(); + cy.url().should("contain", "/settings/developer-settings"); cy.get(adminsSettings.versionTab).click(); cy.url().should("contain", "/settings/version"); }, @@ -90,7 +90,7 @@ describe("Admin settings page", function () { cy.url().should("contain", "/settings/authentication"); cy.get(adminsSettings.emailTab).click(); cy.url().should("contain", "/settings/email"); - cy.get(adminsSettings.googleMapsTab).should("not.exist"); + cy.get(adminsSettings.developerSettingsTab).should("not.exist"); cy.get(adminsSettings.versionTab).click(); cy.url().should("contain", "/settings/version"); }, diff --git a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_1_spec.js b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_1_spec.js index 28e19fae75..2e5524d998 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_1_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_1_spec.js @@ -12,7 +12,7 @@ const routes = { SETTINGS: "/settings", GENERAL: "/settings/general", EMAIL: "/settings/email", - GOOGLE_MAPS: "/settings/google-maps", + DEVELOPER_SETTINGS: "/settings/developer-settings", AUTHENTICATION: "/settings/authentication", GOOGLEAUTH: "/settings/authentication/google-auth", GITHUBAUTH: "/settings/authentication/github-auth", @@ -45,8 +45,8 @@ describe("Admin settings page", function () { it("2. should test that page header is visible", () => { cy.get(adminsSettings.appsmithHeader).should("be.visible"); - cy.visit(routes.GOOGLE_MAPS, { timeout: 60000 }); - cy.url().should("contain", "/google-maps"); + cy.visit(routes.DEVELOPER_SETTINGS, { timeout: 60000 }); + cy.url().should("contain", "/developer-settings"); cy.wait(2000); //page to load properly cy.get(adminsSettings.appsmithHeader).should("be.visible"); cy.visit(routes.GOOGLEAUTH, { timeout: 60000 }); @@ -84,8 +84,8 @@ describe("Admin settings page", function () { cy.url().should("contain", routes.AUTHENTICATION); cy.get(adminsSettings.emailTab).click(); cy.url().should("contain", routes.EMAIL); - cy.get(adminsSettings.googleMapsTab).click(); - cy.url().should("contain", routes.GOOGLE_MAPS); + cy.get(adminsSettings.developerSettingsTab).click(); + cy.url().should("contain", routes.DEVELOPER_SETTINGS); cy.get(adminsSettings.versionTab).click(); cy.url().should("contain", routes.VERSION); }, @@ -105,7 +105,7 @@ describe("Admin settings page", function () { cy.get(adminsSettings.authenticationTab).click(); cy.url().should("contain", routes.AUTHENTICATION); cy.get(adminsSettings.emailTab).click(); - cy.get(adminsSettings.googleMapsTab).should("not.exist"); + cy.get(adminsSettings.developerSettingsTab).should("not.exist"); cy.url().should("contain", routes.EMAIL); cy.get(adminsSettings.versionTab).click(); cy.url().should("contain", routes.VERSION); diff --git a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_2_spec.js b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_2_spec.js index 70020fe1e6..116f302685 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_2_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/ExplorerTests/Admin_settings_2_spec.js @@ -12,7 +12,7 @@ const routes = { SETTINGS: "/settings", GENERAL: "/settings/general", EMAIL: "/settings/email", - GOOGLE_MAPS: "/settings/google-maps", + DEVELOPER_SETTINGS: "/settings/developer-settings", AUTHENTICATION: "/settings/authentication", GOOGLEAUTH: "/settings/authentication/google-auth", GITHUBAUTH: "/settings/authentication/github-auth", @@ -23,7 +23,7 @@ const routes = { describe("Admin settings page", function () { it("1. should test that configure link redirects to google maps setup doc", () => { - cy.visit(routes.GOOGLE_MAPS, { timeout: 60000 }); + cy.visit(routes.DEVELOPER_SETTINGS, { timeout: 60000 }); cy.get(adminsSettings.readMoreLink).within(() => { cy.get("a") .should("have.attr", "target", "_blank") diff --git a/app/client/cypress/locators/AdminsSettings.js b/app/client/cypress/locators/AdminsSettings.js index 1fec88b0fb..ba9e74523b 100644 --- a/app/client/cypress/locators/AdminsSettings.js +++ b/app/client/cypress/locators/AdminsSettings.js @@ -4,7 +4,7 @@ export default { advancedTab: ".t--settings-category-advanced", authenticationTab: ".t--settings-category-authentication", emailTab: ".t--settings-category-email", - googleMapsTab: ".t--settings-category-google-maps", + developerSettingsTab: ".t--settings-category-developer-settings", googleButton: ".t--settings-sub-category-google-auth", githubButton: ".t--settings-sub-category-github-auth", formloginButton: ".t--settings-sub-category-form-login", diff --git a/app/client/cypress/support/Pages/AdminSettings.ts b/app/client/cypress/support/Pages/AdminSettings.ts index 47f34be115..c4506bb040 100644 --- a/app/client/cypress/support/Pages/AdminSettings.ts +++ b/app/client/cypress/support/Pages/AdminSettings.ts @@ -4,6 +4,7 @@ export class AdminSettings { public agHelper = ObjectsRegistry.AggregateHelper; public locator = ObjectsRegistry.CommonLocators; public homePage = ObjectsRegistry.HomePage; + public assertHelper = ObjectsRegistry.AssertHelper; public _adminSettingsBtn = '[data-testid="t--admin-settings-menu-option"]'; private _settingsList = ".t--settings-category-list"; @@ -11,13 +12,13 @@ export class AdminSettings { public _roles = (user: string) => "//span[contains(text(), '" + user + - "')]/parent::div/parent::a/parent::td/following-sibling::td[1]"; - public _instanceName = - "//label[text()='Instance name']/following-sibling::div//input"; + "')]/parent::div/parent::span/parent::a/parent::td/following-sibling::td[1]"; + public _instanceName = '[name="instanceName"]'; public NavigateToAdminSettings() { this.homePage.NavigateToHome(); this.agHelper.GetNClick(this._adminSettingsBtn); + this.assertHelper.AssertNetworkStatus("getEnvVariables"); this.agHelper.AssertElementVisibility(this._settingsList); } } diff --git a/app/client/src/ce/pages/AdminSettings/BreadcrumbCategories.tsx b/app/client/src/ce/pages/AdminSettings/BreadcrumbCategories.tsx index ff1bbe61c9..ccb7100503 100644 --- a/app/client/src/ce/pages/AdminSettings/BreadcrumbCategories.tsx +++ b/app/client/src/ce/pages/AdminSettings/BreadcrumbCategories.tsx @@ -15,9 +15,11 @@ export const BreadcrumbCategories = { href: adminSettingsCategoryUrl({ category: SettingCategories.EMAIL }), text: "Email", }, - [SettingCategories.GOOGLE_MAPS]: { - href: adminSettingsCategoryUrl({ category: SettingCategories.GOOGLE_MAPS }), - text: "Google Maps", + [SettingCategories.DEVELOPER_SETTINGS]: { + href: adminSettingsCategoryUrl({ + category: SettingCategories.DEVELOPER_SETTINGS, + }), + text: "Developer settings", }, [SettingCategories.VERSION]: { href: adminSettingsCategoryUrl({ category: SettingCategories.VERSION }), diff --git a/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/googleMaps.ts b/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/googleMaps.ts new file mode 100644 index 0000000000..7835e79366 --- /dev/null +++ b/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/googleMaps.ts @@ -0,0 +1,24 @@ +import { GOOGLE_MAPS_SETUP_DOC } from "constants/ThirdPartyConstants"; +import type { Setting } from "../types"; +import { + SettingCategories, + SettingSubtype, + SettingTypes, +} from "@appsmith/pages/AdminSettings/config/types"; + +export const googleMapsConfig: Setting[] = [ + { + id: "APPSMITH_GOOGLE_MAPS_READ_MORE", + category: SettingCategories.DEVELOPER_SETTINGS, + controlType: SettingTypes.CALLOUT, + label: "How to configure google maps?", + url: GOOGLE_MAPS_SETUP_DOC, + }, + { + id: "googleMapsKey", + category: SettingCategories.DEVELOPER_SETTINGS, + controlType: SettingTypes.TEXTINPUT, + controlSubType: SettingSubtype.TEXT, + label: "Google Maps API key", + }, +]; diff --git a/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/index.ts b/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/index.ts new file mode 100644 index 0000000000..1d887a6388 --- /dev/null +++ b/app/client/src/ce/pages/AdminSettings/config/DeveloperSettings/index.ts @@ -0,0 +1,17 @@ +import type { AdminConfigType } from "@appsmith/pages/AdminSettings/config/types"; +import { + CategoryType, + SettingCategories, + SettingTypes, +} from "@appsmith/pages/AdminSettings/config/types"; +import { googleMapsConfig } from "./googleMaps"; + +export const config: AdminConfigType = { + icon: "snippet", + type: SettingCategories.DEVELOPER_SETTINGS, + categoryType: CategoryType.GENERAL, + controlType: SettingTypes.GROUP, + title: "Developer settings", + canSave: true, + settings: [...googleMapsConfig], +}; diff --git a/app/client/src/ce/pages/AdminSettings/config/index.ts b/app/client/src/ce/pages/AdminSettings/config/index.ts index b5ac5778ba..e87e2f1add 100644 --- a/app/client/src/ce/pages/AdminSettings/config/index.ts +++ b/app/client/src/ce/pages/AdminSettings/config/index.ts @@ -2,7 +2,7 @@ import { ConfigFactory } from "pages/AdminSettings/config/ConfigFactory"; import { config as GeneralConfig } from "@appsmith/pages/AdminSettings/config/general"; import { config as EmailConfig } from "pages/AdminSettings/config/email"; -import { config as MapsConfig } from "pages/AdminSettings/config/googleMaps"; +import { config as DeveloperSettings } from "@appsmith/pages/AdminSettings/config/DeveloperSettings"; import { config as VersionConfig } from "pages/AdminSettings/config/version"; import { config as AdvancedConfig } from "pages/AdminSettings/config/advanced"; import { config as Authentication } from "@appsmith/pages/AdminSettings/config/authentication"; @@ -13,7 +13,7 @@ import { config as AuditLogsConfig } from "@appsmith/pages/AdminSettings/config/ ConfigFactory.register(GeneralConfig); ConfigFactory.register(EmailConfig); -ConfigFactory.register(MapsConfig); +ConfigFactory.register(DeveloperSettings); ConfigFactory.register(Authentication); ConfigFactory.register(AdvancedConfig); ConfigFactory.register(VersionConfig); diff --git a/app/client/src/ce/pages/AdminSettings/config/types.ts b/app/client/src/ce/pages/AdminSettings/config/types.ts index 7b214c07e7..f9d1ee213f 100644 --- a/app/client/src/ce/pages/AdminSettings/config/types.ts +++ b/app/client/src/ce/pages/AdminSettings/config/types.ts @@ -86,6 +86,7 @@ export type Setting = ControlType & { dropdownOptions?: Partial[]; isFeatureEnabled?: boolean; tooltip?: string; + isEnterprise?: boolean; }; export interface Category { @@ -104,7 +105,6 @@ export interface Category { export const SettingCategories = { GENERAL: "general", EMAIL: "email", - GOOGLE_MAPS: "google-maps", VERSION: "version", ADVANCED: "advanced", AUTHENTICATION: "authentication", @@ -117,6 +117,7 @@ export const SettingCategories = { BRANDING: "branding", SAML_AUTH: "saml-auth", OIDC_AUTH: "oidc-auth", + DEVELOPER_SETTINGS: "developer-settings", }; export enum CategoryType { diff --git a/app/client/src/components/utils/ReduxFormTextField.tsx b/app/client/src/components/utils/ReduxFormTextField.tsx index afc12c86fa..25de22e0ab 100644 --- a/app/client/src/components/utils/ReduxFormTextField.tsx +++ b/app/client/src/components/utils/ReduxFormTextField.tsx @@ -20,11 +20,9 @@ const renderComponent = ( {...omit(componentProps, "type")} {...componentProps.input} errorMessage={ - !componentProps.hideErrorMessage && - showError && - componentProps.meta.error && - componentProps.meta.error + !componentProps.hideErrorMessage && componentProps.meta.error } + isDisabled={componentProps.disabled} label={componentProps.label as string} /> ) : ( @@ -36,6 +34,7 @@ const renderComponent = ( showError && componentProps.meta.error } + isDisabled={componentProps.disabled} renderAs={"input"} size="md" /> diff --git a/app/client/src/ee/pages/AdminSettings/config/DeveloperSettings/index.ts b/app/client/src/ee/pages/AdminSettings/config/DeveloperSettings/index.ts new file mode 100644 index 0000000000..bdc549e9f3 --- /dev/null +++ b/app/client/src/ee/pages/AdminSettings/config/DeveloperSettings/index.ts @@ -0,0 +1 @@ +export * from "ce/pages/AdminSettings/config/DeveloperSettings"; diff --git a/app/client/src/pages/AdminSettings/FormGroup/TextInput.tsx b/app/client/src/pages/AdminSettings/FormGroup/TextInput.tsx index 3d3c6981c3..ecbc2b57e7 100644 --- a/app/client/src/pages/AdminSettings/FormGroup/TextInput.tsx +++ b/app/client/src/pages/AdminSettings/FormGroup/TextInput.tsx @@ -2,8 +2,26 @@ import FormTextField from "components/utils/ReduxFormTextField"; import { createMessage } from "@appsmith/constants/messages"; import React from "react"; import type { SettingComponentProps } from "./Common"; +import BusinessTag from "components/BusinessTag"; +import EnterpriseTag from "components/EnterpriseTag"; +import styled from "styled-components"; + +const LabelWrapper = styled.div` + display: flex; + gap: 4px; + align-items: center; +`; export default function TextInput({ setting }: SettingComponentProps) { + const inputLabel = setting.label ? ( + +
{setting.label}
+ {setting.isFeatureEnabled === false && + (setting.isEnterprise === true ? : )} +
+ ) : ( + "" + ); return (
setting.placeholder || "")} type={setting.controlSubType} diff --git a/app/client/src/pages/AdminSettings/SettingsForm.tsx b/app/client/src/pages/AdminSettings/SettingsForm.tsx index 5ddcb06b6b..986866520f 100644 --- a/app/client/src/pages/AdminSettings/SettingsForm.tsx +++ b/app/client/src/pages/AdminSettings/SettingsForm.tsx @@ -337,8 +337,9 @@ export default withRouter( setting.controlType === SettingTypes.CHECKBOX && !settingsConfig[name] && !fieldValue; - - if (fieldValue !== settingsConfig[name] && !doNotUpdate) { + //We are not performing type check here as inputs we take are stored as string + //But server stores as numeric, string etc.. + if (fieldValue != settingsConfig[name] && !doNotUpdate) { newProps.settings[name] = fieldValue; } }); diff --git a/app/client/src/pages/AdminSettings/config/googleMaps.ts b/app/client/src/pages/AdminSettings/config/googleMaps.ts deleted file mode 100644 index 159ccd026c..0000000000 --- a/app/client/src/pages/AdminSettings/config/googleMaps.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { GOOGLE_MAPS_SETUP_DOC } from "constants/ThirdPartyConstants"; -import type { AdminConfigType } from "@appsmith/pages/AdminSettings/config/types"; -import { - CategoryType, - SettingCategories, - SettingSubtype, - SettingTypes, -} from "@appsmith/pages/AdminSettings/config/types"; - -export const config: AdminConfigType = { - icon: "map-pin-2-line", - type: SettingCategories.GOOGLE_MAPS, - categoryType: CategoryType.GENERAL, - controlType: SettingTypes.GROUP, - title: "Google Maps", - canSave: true, - needsRefresh: true, - settings: [ - { - id: "APPSMITH_GOOGLE_MAPS_READ_MORE", - category: SettingCategories.GOOGLE_MAPS, - controlType: SettingTypes.CALLOUT, - label: "How to configure?", - url: GOOGLE_MAPS_SETUP_DOC, - }, - { - id: "googleMapsKey", - category: SettingCategories.GOOGLE_MAPS, - controlType: SettingTypes.TEXTINPUT, - controlSubType: SettingSubtype.TEXT, - label: "Google Maps API key", - }, - ], -}; From b697550dffcab9d6b3d6b9bf6ca3d87671520f3f Mon Sep 17 00:00:00 2001 From: arunvjn <32433245+arunvjn@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:13:33 +0530 Subject: [PATCH 04/75] chore: Fix bug in unique accessor generation logic for js libraries (#27911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Fixed bug in unique accessor generation logic - potential infinite loop. This was encountered in https://github.com/appsmithorg/appsmith/pull/27857 and tests for this is covered there. #### PR fixes following issue(s) Fixes # (issue number) > if no issue exists, please create an issue and ask the maintainers about this first > > #### 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 - Chore (housekeeping or task changes that don't impact user perception) > > ## Testing > #### How Has This Been Tested? - [x] Manual > > #### 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 - [x] My code follows the style guidelines of this project - [x] 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 - [x] 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 --- app/client/src/workers/Evaluation/handlers/jsLibrary.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/src/workers/Evaluation/handlers/jsLibrary.ts b/app/client/src/workers/Evaluation/handlers/jsLibrary.ts index 600d2ba89e..f45992d918 100644 --- a/app/client/src/workers/Evaluation/handlers/jsLibrary.ts +++ b/app/client/src/workers/Evaluation/handlers/jsLibrary.ts @@ -306,8 +306,8 @@ function generateUniqueAccessor( ) { return validVar; } - const index = 1; - while (true && index < 100) { + let index = 0; + while (index++ < 100) { const name = `Library_${index}`; if (!takenAccessors.includes(name) && !takenNamesMap.hasOwnProperty(name)) { return name; From 277a3a0f454a779219e394cf533c9d87041d75aa Mon Sep 17 00:00:00 2001 From: Nirmal Sarswat <25587962+vivonk@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:36:30 +0530 Subject: [PATCH 05/75] chore: Using retrieve by id for fetching super admin permission group (#27898) ## Description Fetching super admin permission group without user context check using retrieveById. #### Type of change - Chore (housekeeping or task changes that don't impact user perception) #### How Has This Been Tested? - [x] Manual - [x] JUnit ## Checklist: #### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] 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 - [x] Added `Test Plan Approved` label after Cypress tests were reviewed - [x] Added `Test Plan Approved` label after JUnit tests were reviewed --- .../main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java index b080c7784c..c2d19bccd7 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java @@ -204,7 +204,7 @@ public class UserUtilsCE { .flatMap(instanceConfig -> { JSONObject config = instanceConfig.getConfig(); String defaultPermissionGroup = (String) config.getOrDefault(DEFAULT_PERMISSION_GROUP, ""); - return permissionGroupRepository.findById(defaultPermissionGroup); + return permissionGroupRepository.retrieveById(defaultPermissionGroup); }); } } From 8b14b9c4840748912dc414c61155ccd1fdf33c15 Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Tue, 10 Oct 2023 15:40:53 +0530 Subject: [PATCH 06/75] fix: Modal Widget Context switching (#27575) ## Description - Fix issue where modal widget did not reliably open when the url has the modal widget id - Fix issue where modal widget did not open when url has the modal widget's child id #### PR fixes following issue(s) Fixes #20439 Fixes #27204 #### Media #### Type of change - Bug fix (non-breaking change which fixes an issue) ## Testing #### How Has This Been Tested? - [x] Manual - [ ] JUnit - [ ] Jest - [x] Cypress #### Test Plan #### Issues raised during DP testing ## 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 --- .../Canvas_Context_Selected_Widgets_spec.js | 36 ++++++++++++++ app/client/src/sagas/WidgetSelectionSagas.ts | 47 ++++++++++++++++--- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/IDE/Canvas_Context_Selected_Widgets_spec.js b/app/client/cypress/e2e/Regression/ClientSide/IDE/Canvas_Context_Selected_Widgets_spec.js index 01f5416bd7..afe47d3a16 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/IDE/Canvas_Context_Selected_Widgets_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/IDE/Canvas_Context_Selected_Widgets_spec.js @@ -272,4 +272,40 @@ describe("Canvas context widget selection", function () { cy.get(".is-selected").should("contain", "Tab 2"); cy.get(".t--property-pane-title").should("contain", "Button4"); }); + + it("11. Widgets inside modal widget should open when loaded from the URL", function () { + //select widget in page1 + _.entityExplorer.SelectEntityInModal("Modal1", "Widgets"); + + //verify the Modal1 is open and Text1 is selected in page1 + cy.get(`div[data-testid='t--selected']`).should("have.length", 1); + cy.get(".t--modal-widget").should("have.length", 1); + cy.get(".t--property-pane-title").should("contain", "Text1"); + + // Get the current URL + cy.url().then((url) => { + //switch to page2 + _.entityExplorer.SelectEntityByName(page2, "Pages"); + + //select widget in page2 + _.entityExplorer.SelectEntityByName("Text1", "Widgets"); + + //verify the widget is selected in page2 + cy.get(`div[data-testid='t--selected']`).should("have.length", 1); + + // open the URL + cy.visit(url); + + // wati for the page to load + cy.wait(4000); + + //select widget in page1 + _.entityExplorer.SelectEntityInModal("Modal1", "Widgets"); + + //verify the Modal1 is open and Text1 is selected in page1 + cy.get(`div[data-testid='t--selected']`).should("have.length", 1); + cy.get(".t--modal-widget").should("have.length", 1); + cy.get(".t--property-pane-title").should("contain", "Text1"); + }); + }); }); diff --git a/app/client/src/sagas/WidgetSelectionSagas.ts b/app/client/src/sagas/WidgetSelectionSagas.ts index 9d4b2e6aa3..60741561b3 100644 --- a/app/client/src/sagas/WidgetSelectionSagas.ts +++ b/app/client/src/sagas/WidgetSelectionSagas.ts @@ -215,15 +215,22 @@ function* appendSelectedWidgetToUrlSaga( function* waitForInitialization(saga: any, action: ReduxAction) { const isEditorInitialized: boolean = yield select(getIsEditorInitialized); - const isPageFetching: boolean = yield select(getIsFetchingPage); const appMode: APP_MODE = yield select(getAppMode); - const viewMode = appMode === APP_MODE.PUBLISHED; - if (!isEditorInitialized && !viewMode) { + const isViewMode = appMode === APP_MODE.PUBLISHED; + + // Wait until the editor is initialised, and ensure we're not in the view mode + if (!isEditorInitialized && !isViewMode) { yield take(ReduxActionTypes.INITIALIZE_EDITOR_SUCCESS); } + + // Wait until we're done fetching the page + // This is so that we can reliably assume that the Editor and the Canvas have loaded + const isPageFetching: boolean = yield select(getIsFetchingPage); if (isPageFetching) { yield take(ReduxActionTypes.FETCH_PAGE_SUCCESS); } + + // Continue yielding yield call(saga, action); } @@ -238,17 +245,43 @@ function* handleWidgetSelectionSaga( function* openOrCloseModalSaga(action: ReduxAction<{ widgetIds: string[] }>) { if (action.payload.widgetIds.length !== 1) return; - const selectedWidget = action.payload.widgetIds[0]; + // Let's assume that the payload widgetId is a modal widget and we need to open the modal as it is selected + let modalWidgetToOpen: string = action.payload.widgetIds[0]; + // Get all modal widget ids const modalWidgetIds: string[] = yield select( getWidgetIdsByType, "MODAL_WIDGET", ); - const widgetIsModal = modalWidgetIds.includes(selectedWidget); + // Get all widgets + const allWidgets: CanvasWidgetsReduxState = yield select(getWidgets); + // Get the ancestry of the selected widget + const widgetAncestry = getWidgetAncestry(modalWidgetToOpen, allWidgets); - if (widgetIsModal) { - yield put(showModal(selectedWidget)); + // If the selected widget is a modal, we want to open the modal + const widgetIsModal = + // Check if the widget is a modal widget + modalWidgetIds.includes(modalWidgetToOpen); + + // Let's assume that this is not a child of a modal widget + let widgetIsChildOfModal = false; + + if (!widgetIsModal) { + // Check if the widget is a child of a modal widget + const indexOfParentModalWidget: number = widgetAncestry.findIndex((id) => + modalWidgetIds.includes(id), + ); + // If we found a modal widget in the ancestry, we want to open that modal + if (indexOfParentModalWidget > -1) { + // Set the flag to true, so that we can open the modal + widgetIsChildOfModal = true; + modalWidgetToOpen = widgetAncestry[indexOfParentModalWidget]; + } + } + + if (widgetIsModal || widgetIsChildOfModal) { + yield put(showModal(modalWidgetToOpen)); } } From 31ce25f2753be1ab8365509ef0c45c47619b8e68 Mon Sep 17 00:00:00 2001 From: Nilesh Sarupriya Date: Tue, 10 Oct 2023 16:24:38 +0530 Subject: [PATCH 07/75] chore: 1-click refactor for gac (#27162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description > 1-click refactor for GAC > https://github.com/appsmithorg/appsmith-ee/pull/2294 #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/27075 #### 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 - Chore (housekeeping or task changes that don't impact user perception) ## 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 --------- > Pull Request Template > > Use this template to quickly create a well written pull request. Delete all quotes before creating the pull request. > ## Description > Add a TL;DR when description is extra long (helps content team) > > Please include a summary of the changes and which issue has been fixed. Please also include relevant motivation > and context. List any dependencies that are required for this change > > Links to Notion, Figma or any other documents that might be relevant to the PR > > #### PR fixes following issue(s) Fixes # (issue number) > if no issue exists, please create an issue and ask the maintainers about this first > > #### 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 --------- Co-authored-by: Nilesh Sarupriya <20905988+nsarupr@users.noreply.github.com> Co-authored-by: Trisha Anand --- .../AuthenticationSuccessHandler.java | 7 +- .../ce/AuthenticationSuccessHandlerCE.java | 4 +- .../server/helpers/EmailServiceHelper.java | 5 + .../helpers/EmailServiceHelperImpl.java | 12 +++ .../InMemoryCacheableRepositoryHelper.java | 38 +++++++ .../server/helpers/UserServiceHelper.java | 5 + .../server/helpers/UserServiceHelperImpl.java | 13 +++ .../helpers/WorkspaceServiceHelper.java | 5 + .../helpers/WorkspaceServiceHelperImpl.java | 7 ++ .../helpers/ce/EmailServiceHelperCE.java | 17 +++ .../helpers/ce/EmailServiceHelperCEImpl.java | 55 ++++++++++ .../helpers/ce/UserServiceHelperCE.java | 8 ++ .../helpers/ce/UserServiceHelperCEImpl.java | 48 +++++++++ .../server/helpers/ce/UserUtilsCE.java | 2 - .../helpers/ce/WorkspaceServiceHelperCE.java | 7 ++ .../ce/WorkspaceServiceHelperCEImpl.java | 17 +++ .../CacheableRepositoryHelper.java | 4 +- .../CacheableRepositoryHelperImpl.java | 11 +- .../ce/CacheableRepositoryHelperCE.java | 2 + .../ce/CacheableRepositoryHelperCEImpl.java | 101 +++++++++++++----- ...CacheableRepositoryHelperCECompatible.java | 5 + ...eableRepositoryHelperCECompatibleImpl.java | 18 ++++ .../server/services/ApplicationService.java | 4 +- .../services/ApplicationServiceImpl.java | 4 +- .../server/services/EmailServiceImpl.java | 5 +- .../services/PermissionGroupService.java | 4 +- .../services/PermissionGroupServiceImpl.java | 5 +- .../server/services/UserServiceImpl.java | 7 +- .../server/services/WorkspaceServiceImpl.java | 7 +- .../ce/ApplicationPageServiceCEImpl.java | 2 + .../services/ce/ApplicationServiceCEImpl.java | 2 + .../services/ce/EmailServiceCEImpl.java | 85 ++++++--------- .../ce/LayoutActionServiceCEImpl.java | 2 + .../ce/PermissionGroupServiceCEImpl.java | 35 +++--- .../server/services/ce/UserServiceCEImpl.java | 35 ++---- .../ce/UserWorkspaceServiceCEImpl.java | 2 + .../services/ce/WorkspaceServiceCE.java | 2 - .../services/ce/WorkspaceServiceCEImpl.java | 15 +-- .../ApplicationServiceCECompatible.java | 5 + .../ApplicationServiceCECompatibleImpl.java | 54 ++++++++++ .../PermissionGroupServiceCECompatible.java | 5 + ...ermissionGroupServiceCECompatibleImpl.java | 48 +++++++++ .../UserServiceCECompatibleImpl.java | 7 +- .../solutions/ce/ActionPermissionCEImpl.java | 2 + .../ce/ApplicationPermissionCEImpl.java | 2 + .../ce/DatasourcePermissionCEImpl.java | 2 + .../ce/EnvironmentPermissionCEImpl.java | 2 + .../solutions/ce/PagePermissionCEImpl.java | 2 + .../ce/WorkspacePermissionCEImpl.java | 2 + .../helpers/ce/EmailServiceHelperCETest.java | 73 +++++++++++++ ...portApplicationPermissionProviderTest.java | 27 +++-- .../repositories/CacheableRepositoryTest.java | 11 ++ .../UserWorkspaceServiceUnitTest.java | 3 +- .../services/ce/ApplicationServiceCETest.java | 11 +- .../ApplicationSnapshotServiceUnitTest.java | 4 +- .../services/ce/EmailServiceCEImplTest.java | 30 ++---- .../ApplicationForkingServiceTests.java | 3 +- .../ImportExportApplicationServiceTests.java | 7 +- .../ce/RefactoringSolutionCEImplTest.java | 12 ++- 59 files changed, 716 insertions(+), 203 deletions(-) create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelper.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelper.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelperImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelper.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelperImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCE.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCEImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCE.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCEImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatible.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatibleImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatible.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatibleImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatible.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java create mode 100644 app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java index 7e7e0fc419..66467580e4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/AuthenticationSuccessHandler.java @@ -2,6 +2,7 @@ package com.appsmith.server.authentication.handlers; import com.appsmith.server.authentication.handlers.ce.AuthenticationSuccessHandlerCE; import com.appsmith.server.helpers.RedirectHelper; +import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.WorkspaceRepository; @@ -32,7 +33,8 @@ public class AuthenticationSuccessHandler extends AuthenticationSuccessHandlerCE WorkspacePermission workspacePermission, RateLimitService rateLimitService, TenantService tenantService, - UserService userService) { + UserService userService, + WorkspaceServiceHelper workspaceServiceHelper) { super( redirectHelper, sessionUserService, @@ -45,6 +47,7 @@ public class AuthenticationSuccessHandler extends AuthenticationSuccessHandlerCE workspacePermission, rateLimitService, tenantService, - userService); + userService, + workspaceServiceHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java index d201bafdae..d784ae8170 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java @@ -11,6 +11,7 @@ import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.ResendEmailVerificationDTO; import com.appsmith.server.helpers.RedirectHelper; +import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.repositories.WorkspaceRepository; @@ -66,6 +67,7 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce private final RateLimitService rateLimitService; private final TenantService tenantService; private final UserService userService; + private final WorkspaceServiceHelper workspaceServiceHelper; private Mono isVerificationRequired(String userEmail, String method) { Mono emailVerificationEnabledMono = tenantService @@ -283,7 +285,7 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce } if (isFromSignup) { boolean finalIsFromSignup = isFromSignup; - redirectionMono = workspaceService + redirectionMono = workspaceServiceHelper .isCreateWorkspaceAllowed(TRUE) .flatMap(isCreateWorkspaceAllowed -> { if (isCreateWorkspaceAllowed.equals(Boolean.TRUE)) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelper.java new file mode 100644 index 0000000000..bcaf02df37 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelper.java @@ -0,0 +1,5 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.EmailServiceHelperCE; + +public interface EmailServiceHelper extends EmailServiceHelperCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java new file mode 100644 index 0000000000..afa9819ce7 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/EmailServiceHelperImpl.java @@ -0,0 +1,12 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.EmailServiceHelperCEImpl; +import com.appsmith.server.services.TenantService; +import org.springframework.stereotype.Component; + +@Component +public class EmailServiceHelperImpl extends EmailServiceHelperCEImpl implements EmailServiceHelper { + public EmailServiceHelperImpl(TenantService tenantService) { + super(tenantService); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java new file mode 100644 index 0000000000..cbf2e123c3 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/InMemoryCacheableRepositoryHelper.java @@ -0,0 +1,38 @@ +package com.appsmith.server.helpers; + +import org.springframework.stereotype.Component; + +import java.util.Set; + +@Component +public class InMemoryCacheableRepositoryHelper { + private Set anonymousUserPermissionGroupIds = null; + + private String defaultTenantId = null; + + private String instanceAdminPermissionGroupId = null; + + public Set getAnonymousUserPermissionGroupIds() { + return anonymousUserPermissionGroupIds; + } + + public void setAnonymousUserPermissionGroupIds(Set anonymousUserPermissionGroupIds) { + this.anonymousUserPermissionGroupIds = anonymousUserPermissionGroupIds; + } + + public String getDefaultTenantId() { + return defaultTenantId; + } + + public void setDefaultTenantId(String defaultTenantId) { + this.defaultTenantId = defaultTenantId; + } + + public void setInstanceAdminPermissionGroupId(String instanceAdminPermissionGroupId) { + this.instanceAdminPermissionGroupId = instanceAdminPermissionGroupId; + } + + public String getInstanceAdminPermissionGroupId() { + return instanceAdminPermissionGroupId; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelper.java new file mode 100644 index 0000000000..6e66e33eea --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelper.java @@ -0,0 +1,5 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.UserServiceHelperCE; + +public interface UserServiceHelper extends UserServiceHelperCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelperImpl.java new file mode 100644 index 0000000000..8b96e78ec9 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/UserServiceHelperImpl.java @@ -0,0 +1,13 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.UserServiceHelperCEImpl; +import com.appsmith.server.services.PermissionGroupService; +import com.appsmith.server.solutions.PolicySolution; +import org.springframework.stereotype.Component; + +@Component +public class UserServiceHelperImpl extends UserServiceHelperCEImpl implements UserServiceHelper { + public UserServiceHelperImpl(PolicySolution policySolution, PermissionGroupService permissionGroupService) { + super(policySolution, permissionGroupService); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelper.java new file mode 100644 index 0000000000..59e53ffa5b --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelper.java @@ -0,0 +1,5 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.WorkspaceServiceHelperCE; + +public interface WorkspaceServiceHelper extends WorkspaceServiceHelperCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelperImpl.java new file mode 100644 index 0000000000..d82dd81a00 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/WorkspaceServiceHelperImpl.java @@ -0,0 +1,7 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.helpers.ce.WorkspaceServiceHelperCEImpl; +import org.springframework.stereotype.Component; + +@Component +public class WorkspaceServiceHelperImpl extends WorkspaceServiceHelperCEImpl implements WorkspaceServiceHelper {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java new file mode 100644 index 0000000000..0c4ff608fd --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java @@ -0,0 +1,17 @@ +package com.appsmith.server.helpers.ce; + +import reactor.core.publisher.Mono; + +import java.util.Map; + +public interface EmailServiceHelperCE { + Mono> enrichWithBrandParams(Map params, String origin); + + String getForgotPasswordTemplate(); + + String getWorkspaceInviteTemplate(boolean isNewUser); + + String getEmailVerificationTemplate(); + + String getAdminInstanceInviteTemplate(); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java new file mode 100644 index 0000000000..3360126080 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java @@ -0,0 +1,55 @@ +package com.appsmith.server.helpers.ce; + +import com.appsmith.server.domains.TenantConfiguration; +import com.appsmith.server.services.TenantService; +import lombok.AllArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Map; + +import static com.appsmith.server.constants.ce.EmailConstantsCE.EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.FORGOT_PASSWORD_TEMPLATE_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INSTANCE_NAME; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; + +@Component +@AllArgsConstructor +public class EmailServiceHelperCEImpl implements EmailServiceHelperCE { + + private final TenantService tenantService; + + @Override + public Mono> enrichWithBrandParams(Map params, String origin) { + return tenantService.getTenantConfiguration().map(tenant -> { + final TenantConfiguration tenantConfiguration = tenant.getTenantConfiguration(); + params.put(INSTANCE_NAME, StringUtils.defaultIfEmpty(tenantConfiguration.getInstanceName(), "Appsmith")); + return params; + }); + } + + @Override + public String getForgotPasswordTemplate() { + return FORGOT_PASSWORD_TEMPLATE_CE; + } + + @Override + public String getWorkspaceInviteTemplate(boolean isNewUser) { + if (isNewUser) return INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; + + return INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; + } + + @Override + public String getEmailVerificationTemplate() { + return EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; + } + + @Override + public String getAdminInstanceInviteTemplate() { + return INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCE.java new file mode 100644 index 0000000000..f8fd147529 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCE.java @@ -0,0 +1,8 @@ +package com.appsmith.server.helpers.ce; + +import com.appsmith.server.domains.User; +import reactor.core.publisher.Mono; + +public interface UserServiceHelperCE { + Mono addPoliciesToUser(User user); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCEImpl.java new file mode 100644 index 0000000000..25d8cbb52d --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserServiceHelperCEImpl.java @@ -0,0 +1,48 @@ +package com.appsmith.server.helpers.ce; + +import com.appsmith.external.models.Policy; +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.PermissionGroup; +import com.appsmith.server.domains.User; +import com.appsmith.server.dtos.Permission; +import com.appsmith.server.services.PermissionGroupService; +import com.appsmith.server.solutions.PolicySolution; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import java.util.Map; +import java.util.Set; + +import static com.appsmith.server.acl.AclPermission.MANAGE_USERS; + +@Component +@AllArgsConstructor +public class UserServiceHelperCEImpl implements UserServiceHelperCE { + + private final PolicySolution policySolution; + private final PermissionGroupService permissionGroupService; + + @Override + public Mono addPoliciesToUser(User user) { + // Create user management permission group + PermissionGroup userManagementPermissionGroup = new PermissionGroup(); + userManagementPermissionGroup.setName(user.getUsername() + FieldName.SUFFIX_USER_MANAGEMENT_ROLE); + // Add CRUD permissions for user to the group + userManagementPermissionGroup.setPermissions(Set.of(new Permission(user.getId(), MANAGE_USERS))); + userManagementPermissionGroup.setDefaultDomainType(User.class.getSimpleName()); + userManagementPermissionGroup.setDefaultDomainId(user.getId()); + + // Assign the permission group to the user + userManagementPermissionGroup.setAssignedToUserIds(Set.of(user.getId())); + + return permissionGroupService.save(userManagementPermissionGroup).map(savedPermissionGroup -> { + Map crudUserPolicies = + policySolution.generatePolicyFromPermissionGroupForObject(savedPermissionGroup, user.getId()); + + User updatedWithPolicies = policySolution.addPoliciesToExistingObject(crudUserPolicies, user); + + return updatedWithPolicies; + }); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java index c2d19bccd7..4255102e54 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/UserUtilsCE.java @@ -39,7 +39,6 @@ public class UserUtilsCE { private final PermissionGroupRepository permissionGroupRepository; - private final CacheableRepositoryHelper cacheableRepositoryHelper; private final PermissionGroupPermission permissionGroupPermission; public UserUtilsCE( @@ -49,7 +48,6 @@ public class UserUtilsCE { PermissionGroupPermission permissionGroupPermission) { this.configRepository = configRepository; this.permissionGroupRepository = permissionGroupRepository; - this.cacheableRepositoryHelper = cacheableRepositoryHelper; this.permissionGroupPermission = permissionGroupPermission; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCE.java new file mode 100644 index 0000000000..d299747c1d --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCE.java @@ -0,0 +1,7 @@ +package com.appsmith.server.helpers.ce; + +import reactor.core.publisher.Mono; + +public interface WorkspaceServiceHelperCE { + Mono isCreateWorkspaceAllowed(Boolean isDefaultWorkspace); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCEImpl.java new file mode 100644 index 0000000000..e579ba4456 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/WorkspaceServiceHelperCEImpl.java @@ -0,0 +1,17 @@ +package com.appsmith.server.helpers.ce; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; +import reactor.core.publisher.Mono; + +import static java.lang.Boolean.TRUE; + +@Component +@AllArgsConstructor +public class WorkspaceServiceHelperCEImpl implements WorkspaceServiceHelperCE { + + @Override + public Mono isCreateWorkspaceAllowed(Boolean isDefaultWorkspace) { + return Mono.just(TRUE); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelper.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelper.java index 6d4a45d5cd..ece6fe5e7a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelper.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelper.java @@ -1,5 +1,5 @@ package com.appsmith.server.repositories; -import com.appsmith.server.repositories.ce.CacheableRepositoryHelperCE; +import com.appsmith.server.repositories.ce_compatible.CacheableRepositoryHelperCECompatible; -public interface CacheableRepositoryHelper extends CacheableRepositoryHelperCE {} +public interface CacheableRepositoryHelper extends CacheableRepositoryHelperCECompatible {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelperImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelperImpl.java index 9bbb4787b1..ed91d3b621 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelperImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CacheableRepositoryHelperImpl.java @@ -1,14 +1,17 @@ package com.appsmith.server.repositories; -import com.appsmith.server.repositories.ce.CacheableRepositoryHelperCEImpl; +import com.appsmith.server.helpers.InMemoryCacheableRepositoryHelper; +import com.appsmith.server.repositories.ce_compatible.CacheableRepositoryHelperCECompatibleImpl; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.stereotype.Component; @Component -public class CacheableRepositoryHelperImpl extends CacheableRepositoryHelperCEImpl +public class CacheableRepositoryHelperImpl extends CacheableRepositoryHelperCECompatibleImpl implements CacheableRepositoryHelper { - public CacheableRepositoryHelperImpl(ReactiveMongoOperations mongoOperations) { - super(mongoOperations); + public CacheableRepositoryHelperImpl( + ReactiveMongoOperations mongoOperations, + InMemoryCacheableRepositoryHelper inMemoryCacheableRepositoryHelper) { + super(mongoOperations, inMemoryCacheableRepositoryHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java index b5e780f293..c0527340ec 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java @@ -20,4 +20,6 @@ public interface CacheableRepositoryHelperCE { Mono getAnonymousUser(); Mono getDefaultTenantId(); + + Mono getInstanceAdminPermissionGroupId(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java index 2629602b69..307281baeb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java @@ -11,12 +11,16 @@ import com.appsmith.server.domains.QTenant; import com.appsmith.server.domains.QUser; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.User; +import com.appsmith.server.domains.Workspace; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.InMemoryCacheableRepositoryHelper; import lombok.extern.slf4j.Slf4j; +import net.minidev.json.JSONObject; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.util.HashMap; @@ -26,23 +30,23 @@ import java.util.stream.Collectors; import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID; import static com.appsmith.server.constants.ce.FieldNameCE.ANONYMOUS_USER; +import static com.appsmith.server.constants.ce.FieldNameCE.DEFAULT_PERMISSION_GROUP; +import static com.appsmith.server.constants.ce.FieldNameCE.INSTANCE_CONFIG; import static com.appsmith.server.repositories.BaseAppsmithRepositoryImpl.fieldName; import static com.appsmith.server.repositories.ce.BaseAppsmithRepositoryCEImpl.notDeleted; @Slf4j +@Component public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelperCE { private final ReactiveMongoOperations mongoOperations; - private final Map tenantAnonymousUserMap; + private final InMemoryCacheableRepositoryHelper inMemoryCacheableRepositoryHelper; + private final Map tenantAnonymousUserMap = new HashMap<>(); - private Set anonymousUserPermissionGroupIds; - - private String defaultTenantId; - - public CacheableRepositoryHelperCEImpl(ReactiveMongoOperations mongoOperations) { + public CacheableRepositoryHelperCEImpl( + ReactiveMongoOperations mongoOperations, + InMemoryCacheableRepositoryHelper inMemoryCacheableRepositoryHelper) { this.mongoOperations = mongoOperations; - this.defaultTenantId = null; - this.tenantAnonymousUserMap = new HashMap<>(); - anonymousUserPermissionGroupIds = null; + this.inMemoryCacheableRepositoryHelper = inMemoryCacheableRepositoryHelper; } @Cache(cacheName = "permissionGroupsForUser", key = "{#user.email + #user.tenantId}") @@ -62,28 +66,48 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe return Mono.error(new AppsmithException(AppsmithError.SESSION_BAD_STATE)); } - Criteria assignedToUserIdsCriteria = Criteria.where( - fieldName(QPermissionGroup.permissionGroup.assignedToUserIds)) - .is(user.getId()); - Criteria notDeletedCriteria = notDeleted(); + Mono createQueryMono = getInstanceAdminPermissionGroupId().map(instanceAdminPermissionGroupId -> { + Criteria assignedToUserIdsCriteria = Criteria.where( + fieldName(QPermissionGroup.permissionGroup.assignedToUserIds)) + .is(user.getId()); - Criteria andCriteria = new Criteria(); - andCriteria.andOperator(assignedToUserIdsCriteria, notDeletedCriteria); + Criteria notDeletedCriteria = notDeleted(); - Query query = new Query(); - query.addCriteria(andCriteria); + // The roles should be either workspace default roles, user management role, or instance admin role + Criteria ceSupportedRolesCriteria = new Criteria() + .orOperator( + Criteria.where(fieldName(QPermissionGroup.permissionGroup.defaultDomainType)) + .is(Workspace.class.getSimpleName()), + Criteria.where(fieldName(QPermissionGroup.permissionGroup.defaultDomainType)) + .is(User.class.getSimpleName()), + Criteria.where(fieldName(QPermissionGroup.permissionGroup.id)) + .is(instanceAdminPermissionGroupId)); - return mongoOperations - .find(query, PermissionGroup.class) + Criteria andCriteria = new Criteria(); + andCriteria.andOperator(assignedToUserIdsCriteria, notDeletedCriteria, ceSupportedRolesCriteria); + + Query query = new Query(); + query.addCriteria(andCriteria); + + // Since we are only interested in the permission group ids, we can project only the id field. + query.fields().include(fieldName(QPermissionGroup.permissionGroup.id)); + + return query; + }); + + return createQueryMono + .map(query -> mongoOperations.find(query, PermissionGroup.class)) + .flatMapMany(obj -> obj) .map(permissionGroup -> permissionGroup.getId()) .collect(Collectors.toSet()); } @Override public Mono> preFillAnonymousUserPermissionGroupIdsCache() { + Set roleIdsForAnonymousUser = inMemoryCacheableRepositoryHelper.getAnonymousUserPermissionGroupIds(); - if (anonymousUserPermissionGroupIds != null && !anonymousUserPermissionGroupIds.isEmpty()) { - return Mono.just(anonymousUserPermissionGroupIds); + if (roleIdsForAnonymousUser != null && !roleIdsForAnonymousUser.isEmpty()) { + return Mono.just(inMemoryCacheableRepositoryHelper.getAnonymousUserPermissionGroupIds()); } log.debug( @@ -97,14 +121,15 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe Config.class) .map(publicPermissionGroupConfig -> Set.of(publicPermissionGroupConfig.getConfig().getAsString(PERMISSION_GROUP_ID))) - .doOnSuccess(permissionGroupIds -> anonymousUserPermissionGroupIds = permissionGroupIds); + .doOnSuccess(inMemoryCacheableRepositoryHelper::setAnonymousUserPermissionGroupIds); } @Override public Mono> getPermissionGroupsOfAnonymousUser() { + Set roleIdsForAnonymousUser = inMemoryCacheableRepositoryHelper.getAnonymousUserPermissionGroupIds(); - if (anonymousUserPermissionGroupIds != null) { - return Mono.just(anonymousUserPermissionGroupIds); + if (roleIdsForAnonymousUser != null) { + return Mono.just(roleIdsForAnonymousUser); } // If we have reached this state, then the cache is not populated. We need to wait for this to get populated @@ -142,6 +167,7 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe @Override public Mono getAnonymousUser() { + String defaultTenantId = inMemoryCacheableRepositoryHelper.getDefaultTenantId(); if (defaultTenantId != null && !defaultTenantId.isEmpty()) { return getAnonymousUser(defaultTenantId); } @@ -152,13 +178,14 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe query.addCriteria(defaultTenantCriteria); return mongoOperations.findOne(query, Tenant.class).flatMap(defaultTenant -> { - defaultTenantId = defaultTenant.getId(); + inMemoryCacheableRepositoryHelper.setDefaultTenantId(defaultTenant.getId()); return getAnonymousUser(defaultTenant.getId()); }); } @Override public Mono getDefaultTenantId() { + String defaultTenantId = inMemoryCacheableRepositoryHelper.getDefaultTenantId(); if (defaultTenantId != null && !defaultTenantId.isEmpty()) { return Mono.just(defaultTenantId); } @@ -169,8 +196,28 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe query.addCriteria(defaultTenantCriteria); return mongoOperations.findOne(query, Tenant.class).map(defaultTenant -> { - defaultTenantId = defaultTenant.getId(); - return defaultTenantId; + String newDefaultTenantId = defaultTenant.getId(); + inMemoryCacheableRepositoryHelper.setDefaultTenantId(newDefaultTenantId); + return newDefaultTenantId; }); } + + @Override + public Mono getInstanceAdminPermissionGroupId() { + String instanceAdminPermissionGroupId = inMemoryCacheableRepositoryHelper.getInstanceAdminPermissionGroupId(); + if (instanceAdminPermissionGroupId != null && !instanceAdminPermissionGroupId.isEmpty()) { + return Mono.just(instanceAdminPermissionGroupId); + } + + Criteria configName = Criteria.where(fieldName(QConfig.config1.name)).is(INSTANCE_CONFIG); + + return mongoOperations + .findOne(new Query().addCriteria(configName), Config.class) + .map(instanceConfig -> { + JSONObject config = instanceConfig.getConfig(); + return (String) config.getOrDefault(DEFAULT_PERMISSION_GROUP, ""); + }) + .doOnSuccess(permissionGroupId -> + inMemoryCacheableRepositoryHelper.setInstanceAdminPermissionGroupId(permissionGroupId)); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatible.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatible.java new file mode 100644 index 0000000000..d2ecd348a2 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatible.java @@ -0,0 +1,5 @@ +package com.appsmith.server.repositories.ce_compatible; + +import com.appsmith.server.repositories.ce.CacheableRepositoryHelperCE; + +public interface CacheableRepositoryHelperCECompatible extends CacheableRepositoryHelperCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatibleImpl.java new file mode 100644 index 0000000000..d7c0f10cfa --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce_compatible/CacheableRepositoryHelperCECompatibleImpl.java @@ -0,0 +1,18 @@ +package com.appsmith.server.repositories.ce_compatible; + +import com.appsmith.server.helpers.InMemoryCacheableRepositoryHelper; +import com.appsmith.server.repositories.ce.CacheableRepositoryHelperCEImpl; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class CacheableRepositoryHelperCECompatibleImpl extends CacheableRepositoryHelperCEImpl + implements CacheableRepositoryHelperCECompatible { + public CacheableRepositoryHelperCECompatibleImpl( + ReactiveMongoOperations mongoOperations, + InMemoryCacheableRepositoryHelper inMemoryCacheableRepositoryHelper) { + super(mongoOperations, inMemoryCacheableRepositoryHelper); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java index cdbd24a48a..c028a8c689 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationService.java @@ -1,5 +1,5 @@ package com.appsmith.server.services; -import com.appsmith.server.services.ce.ApplicationServiceCE; +import com.appsmith.server.services.ce_compatible.ApplicationServiceCECompatible; -public interface ApplicationService extends ApplicationServiceCE {} +public interface ApplicationService extends ApplicationServiceCECompatible {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java index 52173dfa09..7d2f78bb44 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationServiceImpl.java @@ -3,7 +3,7 @@ package com.appsmith.server.services; import com.appsmith.server.helpers.ResponseUtils; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.NewActionRepository; -import com.appsmith.server.services.ce.ApplicationServiceCEImpl; +import com.appsmith.server.services.ce_compatible.ApplicationServiceCECompatibleImpl; import com.appsmith.server.solutions.ApplicationPermission; import com.appsmith.server.solutions.DatasourcePermission; import com.appsmith.server.solutions.PolicySolution; @@ -16,7 +16,7 @@ import reactor.core.scheduler.Scheduler; @Slf4j @Service -public class ApplicationServiceImpl extends ApplicationServiceCEImpl implements ApplicationService { +public class ApplicationServiceImpl extends ApplicationServiceCECompatibleImpl implements ApplicationService { public ApplicationServiceImpl( Scheduler scheduler, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java index 6fa983232c..7e4d440d3a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java @@ -1,12 +1,13 @@ package com.appsmith.server.services; +import com.appsmith.server.helpers.EmailServiceHelper; import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.services.ce.EmailServiceCEImpl; import org.springframework.stereotype.Service; @Service public class EmailServiceImpl extends EmailServiceCEImpl implements EmailService { - public EmailServiceImpl(EmailSender emailSender, TenantService tenantService) { - super(emailSender, tenantService); + public EmailServiceImpl(EmailSender emailSender, EmailServiceHelper emailServiceHelper) { + super(emailSender, emailServiceHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupService.java index 2aec6a1f3e..d7c617be5d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupService.java @@ -1,5 +1,5 @@ package com.appsmith.server.services; -import com.appsmith.server.services.ce.PermissionGroupServiceCE; +import com.appsmith.server.services.ce_compatible.PermissionGroupServiceCECompatible; -public interface PermissionGroupService extends PermissionGroupServiceCE {} +public interface PermissionGroupService extends PermissionGroupServiceCECompatible {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java index 826f7290da..76a4083f31 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/PermissionGroupServiceImpl.java @@ -3,7 +3,7 @@ package com.appsmith.server.services; import com.appsmith.server.repositories.ConfigRepository; import com.appsmith.server.repositories.PermissionGroupRepository; import com.appsmith.server.repositories.UserRepository; -import com.appsmith.server.services.ce.PermissionGroupServiceCEImpl; +import com.appsmith.server.services.ce_compatible.PermissionGroupServiceCECompatibleImpl; import com.appsmith.server.solutions.PermissionGroupPermission; import com.appsmith.server.solutions.PolicySolution; import jakarta.validation.Validator; @@ -13,7 +13,8 @@ import org.springframework.stereotype.Service; import reactor.core.scheduler.Scheduler; @Service -public class PermissionGroupServiceImpl extends PermissionGroupServiceCEImpl implements PermissionGroupService { +public class PermissionGroupServiceImpl extends PermissionGroupServiceCECompatibleImpl + implements PermissionGroupService { public PermissionGroupServiceImpl( Scheduler scheduler, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java index 9f53632fe7..87f48686f1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java @@ -3,6 +3,7 @@ package com.appsmith.server.services; import com.appsmith.external.services.EncryptionService; import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.EmailConfig; +import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.ratelimiting.RateLimitService; @@ -50,7 +51,8 @@ public class UserServiceImpl extends UserServiceCECompatibleImpl implements User EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, RateLimitService rateLimitService, - PACConfigurationService pacConfigurationService) { + PACConfigurationService pacConfigurationService, + UserServiceHelper userServiceHelper) { super( scheduler, validator, @@ -76,6 +78,7 @@ public class UserServiceImpl extends UserServiceCECompatibleImpl implements User emailVerificationTokenRepository, emailService, rateLimitService, - pacConfigurationService); + pacConfigurationService, + userServiceHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/WorkspaceServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/WorkspaceServiceImpl.java index 68f27aac6b..b9c3ebc09b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/WorkspaceServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/WorkspaceServiceImpl.java @@ -1,5 +1,6 @@ package com.appsmith.server.services; +import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.AssetRepository; import com.appsmith.server.repositories.PluginRepository; @@ -36,7 +37,8 @@ public class WorkspaceServiceImpl extends WorkspaceServiceCEImpl implements Work PolicySolution policySolution, ModelMapper modelMapper, WorkspacePermission workspacePermission, - PermissionGroupPermission permissionGroupPermission) { + PermissionGroupPermission permissionGroupPermission, + WorkspaceServiceHelper workspaceServiceHelper) { super( scheduler, @@ -54,6 +56,7 @@ public class WorkspaceServiceImpl extends WorkspaceServiceCEImpl implements Work policySolution, modelMapper, workspacePermission, - permissionGroupPermission); + permissionGroupPermission, + workspaceServiceHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java index abcb1fff0d..34fcf1bdb9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java @@ -64,6 +64,7 @@ import jakarta.annotation.Nullable; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; +import org.springframework.stereotype.Service; import org.springframework.transaction.reactive.TransactionalOperator; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; @@ -88,6 +89,7 @@ import static org.apache.commons.lang.ObjectUtils.defaultIfNull; @Slf4j @RequiredArgsConstructor +@Service public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE { private final WorkspaceService workspaceService; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationServiceCEImpl.java index f57877907f..d04373096e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationServiceCEImpl.java @@ -46,6 +46,7 @@ import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; import org.springframework.data.mongodb.core.convert.MongoConverter; import org.springframework.http.codec.multipart.Part; +import org.springframework.stereotype.Service; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; @@ -68,6 +69,7 @@ import static com.appsmith.server.constants.Constraint.MAX_LOGO_SIZE_KB; import static org.apache.commons.lang3.StringUtils.isBlank; @Slf4j +@Service public class ApplicationServiceCEImpl extends BaseService implements ApplicationServiceCE { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java index bab662d65a..95571ce473 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java @@ -2,12 +2,12 @@ package com.appsmith.server.services.ce; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; +import com.appsmith.server.helpers.EmailServiceHelper; import com.appsmith.server.notifications.EmailSender; -import com.appsmith.server.services.TenantService; import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; import java.net.URLEncoder; @@ -17,26 +17,28 @@ import java.util.Map; import static com.appsmith.server.constants.ce.EmailConstantsCE.*; +@Component public class EmailServiceCEImpl implements EmailServiceCE { private final EmailSender emailSender; - private final TenantService tenantService; - public EmailServiceCEImpl(EmailSender emailSender, TenantService tenantService) { + private final EmailServiceHelper emailServiceHelper; + + public EmailServiceCEImpl(EmailSender emailSender, EmailServiceHelper emailServiceHelper) { this.emailSender = emailSender; - this.tenantService = tenantService; + this.emailServiceHelper = emailServiceHelper; } @Override public Mono sendForgotPasswordEmail(String email, String resetUrl, String originHeader) { Map params = new HashMap<>(); params.put(RESET_URL, resetUrl); - return this.enrichParams(params) - .flatMap(enrichedParams -> this.enrichWithBrandParams(enrichedParams, originHeader) - .flatMap(updatedParams -> emailSender.sendMail( - email, - String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)), - getForgotPasswordTemplate(), - updatedParams))); + return emailServiceHelper + .enrichWithBrandParams(params, originHeader) + .flatMap(updatedParams -> emailSender.sendMail( + email, + String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)), + emailServiceHelper.getForgotPasswordTemplate(), + updatedParams)); } @Override @@ -56,23 +58,26 @@ public class EmailServiceCEImpl implements EmailServiceCE { String emailSubject = String.format(WORKSPACE_EMAIL_SUBJECT_FOR_NEW_USER, workspaceInvitedTo.getName()); Map params = getInviteToWorkspaceEmailParams( workspaceInvitedTo, invitingUser, inviteUrl, assignedPermissionGroup.getName(), isNewUser); - return this.enrichParams(params).flatMap(enrichedParams -> this.enrichWithBrandParams( - enrichedParams, originHeader) + return emailServiceHelper + .enrichWithBrandParams(params, originHeader) .flatMap(updatedParams -> emailSender.sendMail( - invitedUser.getEmail(), emailSubject, getWorkspaceInviteTemplate(isNewUser), updatedParams))); + invitedUser.getEmail(), + emailSubject, + emailServiceHelper.getWorkspaceInviteTemplate(isNewUser), + updatedParams)); } @Override public Mono sendEmailVerificationEmail(User user, String verificationURL, String originHeader) { Map params = new HashMap<>(); params.put(EMAIL_VERIFICATION_URL, verificationURL); - return this.enrichParams(params) - .flatMap(enrichedParams -> this.enrichWithBrandParams(enrichedParams, originHeader) - .flatMap(updatedParams -> emailSender.sendMail( - user.getEmail(), - EMAIL_VERIFICATION_EMAIL_SUBJECT, - getEmailVerificationTemplate(), - updatedParams))); + return emailServiceHelper + .enrichWithBrandParams(params, originHeader) + .flatMap(updatedParams -> emailSender.sendMail( + user.getEmail(), + EMAIL_VERIFICATION_EMAIL_SUBJECT, + emailServiceHelper.getEmailVerificationTemplate(), + updatedParams)); } @Override @@ -93,45 +98,15 @@ public class EmailServiceCEImpl implements EmailServiceCE { if (invitingUser != null) { params.put(INVITER_FIRST_NAME, StringUtils.defaultIfEmpty(invitingUser.getName(), invitingUser.getEmail())); } - return this.enrichParams(params) - .flatMap(enrichedParams -> this.enrichWithBrandParams(enrichedParams, originHeader)) + return emailServiceHelper + .enrichWithBrandParams(params, originHeader) .flatMap(updatedParams -> emailSender.sendMail( invitedUser.getEmail(), String.format(INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT), - getAdminInstanceInviteTemplate(), + emailServiceHelper.getAdminInstanceInviteTemplate(), updatedParams)); } - protected Mono> enrichParams(Map params) { - return tenantService.getDefaultTenant().map(tenant -> { - final TenantConfiguration tenantConfiguration = tenant.getTenantConfiguration(); - params.put(INSTANCE_NAME, StringUtils.defaultIfEmpty(tenantConfiguration.getInstanceName(), "Appsmith")); - return params; - }); - } - - protected Mono> enrichWithBrandParams(Map params, String origin) { - return Mono.just(params); - } - - protected String getForgotPasswordTemplate() { - return FORGOT_PASSWORD_TEMPLATE_CE; - } - - protected String getWorkspaceInviteTemplate(boolean isNewUser) { - if (isNewUser) return INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; - - return INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; - } - - protected String getEmailVerificationTemplate() { - return EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; - } - - protected String getAdminInstanceInviteTemplate() { - return INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; - } - private Map getInviteToWorkspaceEmailParams( Workspace workspace, User inviter, String inviteUrl, String roleType, boolean isNewUser) { Map params = new HashMap<>(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java index d50f55c2af..76400911fc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java @@ -47,6 +47,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import net.minidev.json.JSONObject; import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -73,6 +74,7 @@ import static java.util.stream.Collectors.toSet; @Slf4j @RequiredArgsConstructor +@Service public class LayoutActionServiceCEImpl implements LayoutActionServiceCE { private final ObjectMapper objectMapper; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java index cbf5d237e3..30933db3af 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/PermissionGroupServiceCEImpl.java @@ -21,6 +21,7 @@ import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.TenantService; import com.appsmith.server.solutions.PermissionGroupPermission; import com.appsmith.server.solutions.PolicySolution; +import com.mongodb.client.result.UpdateResult; import jakarta.validation.Validator; import org.apache.commons.collections.CollectionUtils; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -172,9 +173,11 @@ public class PermissionGroupServiceCEImpl extends BaseService clearCacheForUsersMono = + cleanPermissionGroupCacheForUsers(userIds).thenReturn(TRUE); + + return permissionGroupUpdateMono + .zipWhen(updatedPermissionGroup -> clearCacheForUsersMono) .map(tuple -> tuple.getT1()); } @@ -203,9 +206,12 @@ public class PermissionGroupServiceCEImpl extends BaseService userIds = users.stream().map(User::getId).collect(Collectors.toList()); pg.getAssignedToUserIds().removeAll(userIds); - return Mono.zip( - repository.updateById(pg.getId(), pg, permissionGroupPermission.getUnAssignPermission()), - cleanPermissionGroupCacheForUsers(userIds).thenReturn(TRUE)) + Mono updatePermissionGroupMono = + repository.updateById(pg.getId(), pg, permissionGroupPermission.getUnAssignPermission()); + Mono clearCacheForUsersMono = + cleanPermissionGroupCacheForUsers(userIds).thenReturn(TRUE); + return updatePermissionGroupMono + .zipWhen(updatedPermissionGroup -> clearCacheForUsersMono) .map(tuple -> tuple.getT1()); } @@ -219,9 +225,12 @@ public class PermissionGroupServiceCEImpl extends BaseService bulkUnassignFromUserIds(PermissionGroup pg, List userIds) { ensureAssignedToUserIds(pg); pg.getAssignedToUserIds().removeAll(userIds); - return Mono.zip( - repository.updateById(pg.getId(), pg, permissionGroupPermission.getUnAssignPermission()), - cleanPermissionGroupCacheForUsers(userIds).thenReturn(TRUE)) + Mono updatePermissionGroupMono = + repository.updateById(pg.getId(), pg, permissionGroupPermission.getUnAssignPermission()); + Mono clearCacheForUsersMono = + cleanPermissionGroupCacheForUsers(userIds).thenReturn(TRUE); + return updatePermissionGroupMono + .zipWhen(updatedPermissionGroup -> clearCacheForUsersMono) .map(tuple -> tuple.getT1()); } @@ -239,9 +248,11 @@ public class PermissionGroupServiceCEImpl extends BaseService updatePermissionGroupResultMono = repository.updateById(pg.getId(), updateObj); + Mono clearCacheForUsersMono = cleanPermissionGroupCacheForUsers(List.copyOf(userIds)); + + return updatePermissionGroupResultMono + .zipWhen(updatedPermissionGroupResult -> clearCacheForUsersMono) .map(tuple -> tuple.getT1()); }) .then(Mono.just(TRUE)); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java index f412879c08..72ad7d0ae0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java @@ -1,7 +1,6 @@ package com.appsmith.server.services.ce; import com.appsmith.external.helpers.AppsmithBeanUtils; -import com.appsmith.external.models.Policy; import com.appsmith.external.services.EncryptionService; import com.appsmith.server.acl.AclPermission; import com.appsmith.server.configurations.CommonConfig; @@ -11,14 +10,12 @@ import com.appsmith.server.constants.RateLimitConstants; import com.appsmith.server.domains.EmailVerificationToken; import com.appsmith.server.domains.LoginSource; import com.appsmith.server.domains.PasswordResetToken; -import com.appsmith.server.domains.PermissionGroup; import com.appsmith.server.domains.QUser; import com.appsmith.server.domains.User; import com.appsmith.server.domains.UserData; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.EmailTokenDTO; import com.appsmith.server.dtos.InviteUsersDTO; -import com.appsmith.server.dtos.Permission; import com.appsmith.server.dtos.ResendEmailVerificationDTO; import com.appsmith.server.dtos.ResetUserPasswordDTO; import com.appsmith.server.dtos.UserProfileDTO; @@ -26,6 +23,7 @@ import com.appsmith.server.dtos.UserSignupDTO; import com.appsmith.server.dtos.UserUpdateDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.ValidationUtils; import com.appsmith.server.notifications.EmailSender; @@ -118,6 +116,8 @@ public class UserServiceCEImpl extends BaseService private final RateLimitService rateLimitService; private final PACConfigurationService pacConfigurationService; + private final UserServiceHelper userPoliciesComputeHelper; + private static final WebFilterChain EMPTY_WEB_FILTER_CHAIN = serverWebExchange -> Mono.empty(); private static final String FORGOT_PASSWORD_CLIENT_URL_FORMAT = "%s/user/resetPassword?token=%s"; private static final Pattern ALLOWED_ACCENTED_CHARACTERS_PATTERN = Pattern.compile("^[\\p{L} 0-9 .\'\\-]+$"); @@ -156,7 +156,8 @@ public class UserServiceCEImpl extends BaseService EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, RateLimitService rateLimitService, - PACConfigurationService pacConfigurationService) { + PACConfigurationService pacConfigurationService, + UserServiceHelper userServiceHelper) { super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService); this.workspaceService = workspaceService; @@ -174,6 +175,7 @@ public class UserServiceCEImpl extends BaseService this.rateLimitService = rateLimitService; this.emailVerificationTokenRepository = emailVerificationTokenRepository; this.emailService = emailService; + this.userPoliciesComputeHelper = userServiceHelper; this.pacConfigurationService = pacConfigurationService; } @@ -471,31 +473,8 @@ public class UserServiceCEImpl extends BaseService .flatMap(tuple -> analyticsService.identifyUser(tuple.getT1(), tuple.getT2())); } - protected Mono addUserPolicies(User savedUser) { - - // Create user management permission group - PermissionGroup userManagementPermissionGroup = new PermissionGroup(); - userManagementPermissionGroup.setName(savedUser.getUsername() + FieldName.SUFFIX_USER_MANAGEMENT_ROLE); - // Add CRUD permissions for user to the group - userManagementPermissionGroup.setPermissions(Set.of(new Permission(savedUser.getId(), MANAGE_USERS))); - userManagementPermissionGroup.setDefaultDomainType(User.class.getSimpleName()); - userManagementPermissionGroup.setDefaultDomainId(savedUser.getId()); - - // Assign the permission group to the user - userManagementPermissionGroup.setAssignedToUserIds(Set.of(savedUser.getId())); - - return permissionGroupService.save(userManagementPermissionGroup).map(savedPermissionGroup -> { - Map crudUserPolicies = - policySolution.generatePolicyFromPermissionGroupForObject(savedPermissionGroup, savedUser.getId()); - - User updatedWithPolicies = policySolution.addPoliciesToExistingObject(crudUserPolicies, savedUser); - - return updatedWithPolicies; - }); - } - private Mono addUserPoliciesAndSaveToRepo(User user) { - return addUserPolicies(user).flatMap(repository::save); + return userPoliciesComputeHelper.addPoliciesToUser(user).flatMap(repository::save); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java index ae717c2071..01ec083329 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java @@ -25,6 +25,7 @@ import com.appsmith.server.solutions.WorkspacePermission; import com.mongodb.client.result.UpdateResult; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; @@ -43,6 +44,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; @Slf4j +@Service public class UserWorkspaceServiceCEImpl implements UserWorkspaceServiceCE { private final SessionUserService sessionUserService; private final WorkspaceRepository workspaceRepository; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java index 90f8f640a3..438144a97a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCE.java @@ -43,7 +43,5 @@ public interface WorkspaceServiceCE extends CrudService { Mono archiveById(String s); - Mono isCreateWorkspaceAllowed(Boolean isDefaultWorkspace); - Mono getDefaultEnvironmentId(String workspaceId, AclPermission aclPermission); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java index 622acd1a82..c3b7689677 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java @@ -18,6 +18,7 @@ import com.appsmith.server.dtos.WorkspacePluginStatus; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.TextUtils; +import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.AssetRepository; import com.appsmith.server.repositories.PluginRepository; @@ -42,6 +43,7 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.http.codec.multipart.Part; +import org.springframework.stereotype.Service; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; @@ -74,6 +76,7 @@ import static com.appsmith.server.repositories.ce.BaseAppsmithRepositoryCEImpl.f import static java.lang.Boolean.TRUE; @Slf4j +@Service public class WorkspaceServiceCEImpl extends BaseService implements WorkspaceServiceCE { @@ -87,6 +90,7 @@ public class WorkspaceServiceCEImpl extends BaseService createWorkspaceAllowedMono = isCreateWorkspaceAllowed(isDefault); + Mono createWorkspaceAllowedMono = workspaceServiceHelper.isCreateWorkspaceAllowed(isDefault); // Populate all the required fields for a valid workspace prepareWorkspaceToCreate(workspace, user); @@ -233,11 +239,6 @@ public class WorkspaceServiceCEImpl extends BaseService isCreateWorkspaceAllowed(Boolean isDefaultWorkspace) { - return Mono.just(TRUE); - } - @Override public Mono getDefaultEnvironmentId(String workspaceId, AclPermission aclPermission) { return Mono.just(FieldName.UNUSED_ENVIRONMENT_ID); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatible.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatible.java new file mode 100644 index 0000000000..c5cfbcfefe --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatible.java @@ -0,0 +1,5 @@ +package com.appsmith.server.services.ce_compatible; + +import com.appsmith.server.services.ce.ApplicationServiceCE; + +public interface ApplicationServiceCECompatible extends ApplicationServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatibleImpl.java new file mode 100644 index 0000000000..37c281d86b --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/ApplicationServiceCECompatibleImpl.java @@ -0,0 +1,54 @@ +package com.appsmith.server.services.ce_compatible; + +import com.appsmith.server.helpers.ResponseUtils; +import com.appsmith.server.repositories.ApplicationRepository; +import com.appsmith.server.repositories.NewActionRepository; +import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.AssetService; +import com.appsmith.server.services.ConfigService; +import com.appsmith.server.services.PermissionGroupService; +import com.appsmith.server.services.ce.ApplicationServiceCEImpl; +import com.appsmith.server.solutions.ApplicationPermission; +import com.appsmith.server.solutions.DatasourcePermission; +import com.appsmith.server.solutions.PolicySolution; +import jakarta.validation.Validator; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.stereotype.Service; +import reactor.core.scheduler.Scheduler; + +@Service +public class ApplicationServiceCECompatibleImpl extends ApplicationServiceCEImpl + implements ApplicationServiceCECompatible { + public ApplicationServiceCECompatibleImpl( + Scheduler scheduler, + Validator validator, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + ApplicationRepository repository, + AnalyticsService analyticsService, + PolicySolution policySolution, + ConfigService configService, + ResponseUtils responseUtils, + PermissionGroupService permissionGroupService, + NewActionRepository newActionRepository, + AssetService assetService, + DatasourcePermission datasourcePermission, + ApplicationPermission applicationPermission) { + super( + scheduler, + validator, + mongoConverter, + reactiveMongoTemplate, + repository, + analyticsService, + policySolution, + configService, + responseUtils, + permissionGroupService, + newActionRepository, + assetService, + datasourcePermission, + applicationPermission); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatible.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatible.java new file mode 100644 index 0000000000..2089b1a4da --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatible.java @@ -0,0 +1,5 @@ +package com.appsmith.server.services.ce_compatible; + +import com.appsmith.server.services.ce.PermissionGroupServiceCE; + +public interface PermissionGroupServiceCECompatible extends PermissionGroupServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java new file mode 100644 index 0000000000..7e0bd5ff6f --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/PermissionGroupServiceCECompatibleImpl.java @@ -0,0 +1,48 @@ +package com.appsmith.server.services.ce_compatible; + +import com.appsmith.server.repositories.ConfigRepository; +import com.appsmith.server.repositories.PermissionGroupRepository; +import com.appsmith.server.repositories.UserRepository; +import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.SessionUserService; +import com.appsmith.server.services.TenantService; +import com.appsmith.server.services.ce.PermissionGroupServiceCEImpl; +import com.appsmith.server.solutions.PermissionGroupPermission; +import com.appsmith.server.solutions.PolicySolution; +import jakarta.validation.Validator; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.stereotype.Service; +import reactor.core.scheduler.Scheduler; + +@Service +public class PermissionGroupServiceCECompatibleImpl extends PermissionGroupServiceCEImpl + implements PermissionGroupServiceCECompatible { + public PermissionGroupServiceCECompatibleImpl( + Scheduler scheduler, + Validator validator, + MongoConverter mongoConverter, + ReactiveMongoTemplate reactiveMongoTemplate, + PermissionGroupRepository repository, + AnalyticsService analyticsService, + SessionUserService sessionUserService, + TenantService tenantService, + UserRepository userRepository, + PolicySolution policySolution, + ConfigRepository configRepository, + PermissionGroupPermission permissionGroupPermission) { + super( + scheduler, + validator, + mongoConverter, + reactiveMongoTemplate, + repository, + analyticsService, + sessionUserService, + tenantService, + userRepository, + policySolution, + configRepository, + permissionGroupPermission); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java index 79c8d40398..8b458b36fe 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java @@ -3,6 +3,7 @@ package com.appsmith.server.services.ce_compatible; import com.appsmith.external.services.EncryptionService; import com.appsmith.server.configurations.CommonConfig; import com.appsmith.server.configurations.EmailConfig; +import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.ratelimiting.RateLimitService; @@ -55,7 +56,8 @@ public class UserServiceCECompatibleImpl extends UserServiceCEImpl implements Us EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, RateLimitService rateLimitService, - PACConfigurationService pacConfigurationService) { + PACConfigurationService pacConfigurationService, + UserServiceHelper userServiceHelper) { super( scheduler, validator, @@ -81,6 +83,7 @@ public class UserServiceCECompatibleImpl extends UserServiceCEImpl implements Us emailVerificationTokenRepository, emailService, rateLimitService, - pacConfigurationService); + pacConfigurationService, + userServiceHelper); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java index 27913ee091..1a855eaa5b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class ActionPermissionCEImpl implements ActionPermissionCE, DomainPermissionCE { @Override public AclPermission getEditPermission() { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java index 5860a43814..ef277b9f4c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class ApplicationPermissionCEImpl implements ApplicationPermissionCE, DomainPermissionCE { @Override public AclPermission getEditPermission() { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java index 5b2d64516c..29e90297cd 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class DatasourcePermissionCEImpl implements DatasourcePermissionCE, DomainPermissionCE { @Override public AclPermission getReadPermission() { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvironmentPermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvironmentPermissionCEImpl.java index 34fb084ae4..a1aca01bc1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvironmentPermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/EnvironmentPermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class EnvironmentPermissionCEImpl implements EnvironmentPermissionCE { @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java index 5dc48bed2f..03b270ddc6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class PagePermissionCEImpl implements PagePermissionCE, DomainPermissionCE { @Override public AclPermission getEditPermission() { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java index 78b25c9baf..abc8b9a240 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java @@ -1,7 +1,9 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.springframework.stereotype.Component; +@Component public class WorkspacePermissionCEImpl implements WorkspacePermissionCE, DomainPermissionCE { @Override public AclPermission getEditPermission() { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java new file mode 100644 index 0000000000..16e857736e --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java @@ -0,0 +1,73 @@ +package com.appsmith.server.helpers.ce; + +import com.appsmith.server.domains.Tenant; +import com.appsmith.server.services.TenantService; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import reactor.test.StepVerifier; + +import java.util.HashMap; + +import static com.appsmith.server.constants.ce.EmailConstantsCE.EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.FORGOT_PASSWORD_TEMPLATE_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INSTANCE_NAME; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; +import static com.appsmith.server.constants.ce.EmailConstantsCE.INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +class EmailServiceHelperCETest { + + @Autowired + @Qualifier("emailServiceHelperCEImpl") private EmailServiceHelperCE emailServiceHelperCE; + + @Autowired + TenantService tenantService; + + @Test + @WithUserDetails(value = "api_user") + public void testEnrichWithBrandParams() { + Tenant defautTenant = tenantService.getTenantConfiguration().block(); + String instanceName = + StringUtils.defaultIfEmpty(defautTenant.getTenantConfiguration().getInstanceName(), "Appsmith"); + StepVerifier.create(emailServiceHelperCE.enrichWithBrandParams(new HashMap<>(), "www.test.com")) + .assertNext(map -> { + assertThat(map.containsKey(INSTANCE_NAME)).isTrue(); + assertThat(map.get(INSTANCE_NAME)).isEqualTo(instanceName); + }) + .verifyComplete(); + } + + @Test + void testGetForgotPasswordTemplate() { + assertThat(emailServiceHelperCE.getForgotPasswordTemplate()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE); + } + + @Test + void testGetWorkspaceInviteTemplate() { + assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE)) + .isEqualTo(INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE); + assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.FALSE)) + .isEqualTo(INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE); + } + + @Test + void testGetEmailVerificationTemplate() { + assertThat(emailServiceHelperCE.getEmailVerificationTemplate()).isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE); + } + + @Test + void testGetAdminInstanceInviteTemplate() { + assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate()) + .isEqualTo(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE); + } +} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportApplicationPermissionProviderTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportApplicationPermissionProviderTest.java index 91d45d8923..1930362aaa 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportApplicationPermissionProviderTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportApplicationPermissionProviderTest.java @@ -10,17 +10,14 @@ import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Workspace; import com.appsmith.server.solutions.ActionPermission; -import com.appsmith.server.solutions.ActionPermissionImpl; import com.appsmith.server.solutions.ApplicationPermission; -import com.appsmith.server.solutions.ApplicationPermissionImpl; import com.appsmith.server.solutions.DatasourcePermission; -import com.appsmith.server.solutions.DatasourcePermissionImpl; import com.appsmith.server.solutions.DomainPermission; import com.appsmith.server.solutions.PagePermission; -import com.appsmith.server.solutions.PagePermissionImpl; import com.appsmith.server.solutions.WorkspacePermission; -import com.appsmith.server.solutions.WorkspacePermissionImpl; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import reactor.util.function.Tuple2; import reactor.util.function.Tuples; @@ -32,12 +29,22 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +@SpringBootTest class ImportApplicationPermissionProviderTest { - ApplicationPermission applicationPermission = new ApplicationPermissionImpl(); - PagePermission pagePermission = new PagePermissionImpl(); - ActionPermission actionPermission = new ActionPermissionImpl(); - DatasourcePermission datasourcePermission = new DatasourcePermissionImpl(); - WorkspacePermission workspacePermission = new WorkspacePermissionImpl(); + @Autowired + ApplicationPermission applicationPermission; + + @Autowired + PagePermission pagePermission; + + @Autowired + ActionPermission actionPermission; + + @Autowired + DatasourcePermission datasourcePermission; + + @Autowired + WorkspacePermission workspacePermission; @Test public void testCheckPermissionMethods_WhenNoPermissionProvided_ReturnsTrue() { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/repositories/CacheableRepositoryTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/repositories/CacheableRepositoryTest.java index c6f8fc4bc1..c7742032ba 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/repositories/CacheableRepositoryTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/repositories/CacheableRepositoryTest.java @@ -3,7 +3,9 @@ package com.appsmith.server.repositories; import com.appsmith.server.domains.PermissionGroup; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; +import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.services.WorkspaceService; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +37,15 @@ public class CacheableRepositoryTest { @Autowired UserRepository userRepository; + @Autowired + UserUtils userUtils; + + @BeforeEach() + public void setup() { + User api_user = userRepository.findByEmail("api_user").block(); + userUtils.makeSuperUser(List.of(api_user)).block(); + } + @Test @WithUserDetails(value = "api_user") public void getUserPermissionsTest_onPermissionGroupDelete_valid() { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java index d6ff1b1560..ea439a0d5d 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java @@ -1,5 +1,6 @@ package com.appsmith.server.services; +import com.appsmith.server.configurations.WithMockAppsmithUser; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.PermissionGroup; import com.appsmith.server.domains.Workspace; @@ -89,7 +90,6 @@ public class UserWorkspaceServiceUnitTest { .findByDefaultDomainIdAndDefaultDomainType(createdWorkspace.getId(), Workspace.class.getSimpleName()) .flatMap(permissionGroup -> { permissionGroup.setDefaultDomainId(null); - permissionGroup.setDefaultDomainType(null); return permissionGroupRepository.save(permissionGroup); }) .collectList() @@ -104,6 +104,7 @@ public class UserWorkspaceServiceUnitTest { } @Test + @WithMockAppsmithUser public void getWorkspaceMembers_WhenNoOrgFound_ThrowsException() { String sampleWorkspaceId = "test-org-id"; Mono> workspaceMembers = userWorkspaceService.getWorkspaceMembers(sampleWorkspaceId); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java index a018d9c426..427aad6e42 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java @@ -81,6 +81,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.core.io.ClassPathResource; @@ -160,7 +161,7 @@ public class ApplicationServiceCETest { @Autowired ApplicationService applicationService; - @Autowired + @Qualifier("applicationPageServiceImpl") @Autowired ApplicationPageServiceCE applicationPageService; @Autowired @@ -266,11 +267,11 @@ public class ApplicationServiceCETest { Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())) .thenReturn(Mono.just(new MockPluginExecutor())); User apiUser = userService.findByEmail("api_user").block(); - - Workspace toCreate = new Workspace(); - toCreate.setName("ApplicationServiceTest"); - if (workspaceId == null) { + + Workspace toCreate = new Workspace(); + toCreate.setName("ApplicationServiceTest"); + Workspace workspace = workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); workspaceId = workspace.getId(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceUnitTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceUnitTest.java index c4024e6cf0..5593c75b59 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceUnitTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationSnapshotServiceUnitTest.java @@ -14,7 +14,6 @@ import com.appsmith.server.repositories.ApplicationSnapshotRepository; import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.ApplicationSnapshotService; import com.appsmith.server.solutions.ApplicationPermission; -import com.appsmith.server.solutions.ApplicationPermissionImpl; import com.appsmith.server.solutions.ImportExportApplicationService; import com.google.gson.Gson; import net.minidev.json.JSONObject; @@ -54,7 +53,8 @@ public class ApplicationSnapshotServiceUnitTest { @Autowired ApplicationSnapshotService applicationSnapshotService; - ApplicationPermission applicationPermission = new ApplicationPermissionImpl(); + @Autowired + ApplicationPermission applicationPermission; @Autowired Gson gson; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java index d6ccc8e0d5..e4c1c1110d 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/EmailServiceCEImplTest.java @@ -2,19 +2,16 @@ package com.appsmith.server.services.ce; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.PermissionGroup; -import com.appsmith.server.domains.Tenant; -import com.appsmith.server.domains.TenantConfiguration; import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.services.TenantService; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import reactor.core.publisher.Mono; @@ -34,6 +31,7 @@ import static com.appsmith.server.constants.ce.EmailConstantsCE.PRIMARY_LINK_URL import static com.appsmith.server.constants.ce.EmailConstantsCE.RESET_URL; import static com.appsmith.server.constants.ce.EmailConstantsCE.WORKSPACE_EMAIL_SUBJECT_FOR_NEW_USER; import static graphql.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.anyString; @@ -46,22 +44,11 @@ class EmailServiceCEImplTest { @Autowired TenantService tenantService; - @Mock + @SpyBean EmailSender mockEmailSender; - private EmailServiceCE emailService; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - TenantConfiguration tenantConfiguration = new TenantConfiguration(); - - Tenant tenant = tenantService.getDefaultTenant().block(); - assert tenant != null; - tenant.setTenantConfiguration(tenantConfiguration); - - this.emailService = new EmailServiceCEImpl(mockEmailSender, tenantService); - } + @Autowired + @Qualifier("emailServiceCEImpl") private EmailServiceCE emailService; @Test void sendForgotPasswordEmail() { @@ -83,7 +70,10 @@ class EmailServiceCEImplTest { assertEquals( String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, expectedParams.get(INSTANCE_NAME)), subject); assertEquals(FORGOT_PASSWORD_TEMPLATE_CE, text); - assertEquals(expectedParams, params); + assertThat(params).containsKey(RESET_URL); + assertThat(params.get(RESET_URL)).isEqualTo(resetUrl); + assertThat(params).containsKey(INSTANCE_NAME); + assertThat(params.get(INSTANCE_NAME)).isEqualTo("Appsmith"); return Mono.just(true); }) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java index 67eb4feff2..38943610cd 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java @@ -492,7 +492,8 @@ public class ApplicationForkingServiceTests { // Trigger the fork application flow applicationForkingService .forkApplicationToWorkspaceWithEnvironment(sourceAppId, targetWorkspace.getId(), sourceEnvironmentId) - .timeout(Duration.ofMillis(10)) + // Increase the timer because feature flags are taking some tiem to be computed. + .timeout(Duration.ofMillis(50)) .subscribe(); // Wait for fork to complete diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java index 0f09a9dfbf..522b48f924 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java @@ -198,8 +198,11 @@ public class ImportExportApplicationServiceTests { @Autowired EnvironmentPermission environmentPermission; - PagePermission pagePermission = new PagePermissionImpl(); - ApplicationPermission applicationPermission = new ApplicationPermissionImpl(); + @Autowired + PagePermission pagePermission; + + @Autowired + ApplicationPermission applicationPermission; @BeforeEach public void setup() { diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/RefactoringSolutionCEImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/RefactoringSolutionCEImplTest.java index 1b3ddb41c2..567d534b1e 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/RefactoringSolutionCEImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/RefactoringSolutionCEImplTest.java @@ -11,9 +11,7 @@ import com.appsmith.server.services.LayoutActionService; import com.appsmith.server.services.NewPageService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.solutions.ActionPermission; -import com.appsmith.server.solutions.ActionPermissionImpl; import com.appsmith.server.solutions.PagePermission; -import com.appsmith.server.solutions.PagePermissionImpl; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; @@ -21,6 +19,8 @@ import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; import reactor.core.publisher.Mono; @@ -33,13 +33,19 @@ import java.util.regex.Pattern; @ExtendWith(SpringExtension.class) @Slf4j +@SpringBootTest class RefactoringSolutionCEImplTest { private final String preWord = "\\b("; private final String postWord = ")\\b"; RefactoringSolutionCEImpl refactoringSolutionCE; + + @Autowired PagePermission pagePermission; + + @Autowired ActionPermission actionPermission; + ObjectMapper mapper = new ObjectMapper(); @MockBean @@ -77,8 +83,6 @@ class RefactoringSolutionCEImplTest { @BeforeEach public void setUp() { - pagePermission = new PagePermissionImpl(); - actionPermission = new ActionPermissionImpl(); refactoringSolutionCE = new RefactoringSolutionCEImpl( objectMapper, newPageService, From 7a3792ed977e2cd159841a079012918bbb892395 Mon Sep 17 00:00:00 2001 From: Trisha Anand Date: Tue, 10 Oct 2023 16:52:40 +0530 Subject: [PATCH 08/75] fix: Making login rate limit service reactive (#27903) Refactor : While debugging the production downtime, took a deeper look into the code path of rate limiting. Blocking calls to redis were being made on the main threads which can impact the overall response times of the appsmith server (since the number of main threads equals no of CPUs on the machine). No blocking calls should be made in the main thread. Moving executions to bounded elastic threadpool and making the reset flow reactive. Also the code was not split according to the code split guidelines of the server. Taking care of that as well. --- .../ce/AuthenticationSuccessHandlerCE.java | 6 +- .../com/appsmith/server/filters/PreAuth.java | 12 ++- .../server/ratelimiting/RateLimitConfig.java | 10 ++- .../server/ratelimiting/RateLimitService.java | 44 +-------- .../ratelimiting/RateLimitServiceImpl.java | 17 ++++ .../ratelimiting/aspects/RateLimitAspect.java | 3 +- .../ratelimiting/ce/RateLimitServiceCE.java | 9 ++ .../ce/RateLimitServiceCEImpl.java | 90 +++++++++++++++++++ .../server/services/ce/UserServiceCEImpl.java | 8 +- 9 files changed, 144 insertions(+), 55 deletions(-) create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitServiceImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCE.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCEImpl.java diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java index d784ae8170..e1e7e6136e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/authentication/handlers/ce/AuthenticationSuccessHandlerCE.java @@ -254,7 +254,6 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce log.debug("Login succeeded for user: {}", authentication.getPrincipal()); Mono redirectionMono = null; User user = (User) authentication.getPrincipal(); - rateLimitService.resetCounter(RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, user.getEmail()); String originHeader = webFilterExchange.getExchange().getRequest().getHeaders().getOrigin(); @@ -316,6 +315,11 @@ public class AuthenticationSuccessHandlerCE implements ServerAuthenticationSucce .getCurrentUser() .flatMap(currentUser -> { List> monos = new ArrayList<>(); + + // Since the user has successfully logged in, lets reset the rate limit counter for the user. + monos.add(rateLimitService.resetCounter( + RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, user.getEmail())); + monos.add(userDataService.ensureViewedCurrentVersionReleaseNotes(currentUser)); String modeOfLogin = FieldName.FORM_LOGIN; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/filters/PreAuth.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/filters/PreAuth.java index 20f998d1e5..ccaceda3d8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/filters/PreAuth.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/filters/PreAuth.java @@ -15,6 +15,8 @@ import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import static java.lang.Boolean.FALSE; + @Slf4j public class PreAuth implements WebFilter { @@ -27,21 +29,23 @@ public class PreAuth implements WebFilter { @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { + + Mono filterMono = chain.filter(exchange); + return getUsername(exchange).flatMap(username -> { if (!username.isEmpty()) { return rateLimitService .tryIncreaseCounter(RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, username) .flatMap(counterIncreaseAttemptSuccessful -> { - if (Boolean.FALSE.equals(counterIncreaseAttemptSuccessful)) { - log.error("Rate limit exceeded. Redirecting to login page."); + if (FALSE.equals(counterIncreaseAttemptSuccessful)) { return handleRateLimitExceeded(exchange); } - return chain.filter(exchange); + return filterMono; }); } else { // If username is empty, simply continue with the filter chain - return chain.filter(exchange); + return filterMono; } }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitConfig.java index 84ac04cce5..2ed255f5b4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitConfig.java @@ -10,6 +10,7 @@ import io.github.bucket4j.redis.lettuce.cas.LettuceBasedProxyManager; import io.lettuce.core.AbstractRedisClient; import io.lettuce.core.RedisClient; import io.lettuce.core.cluster.RedisClusterClient; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -20,8 +21,9 @@ import java.util.Map; import java.util.Optional; @Configuration +@Slf4j public class RateLimitConfig { - private static final Map apiConfigurations = new HashMap<>(); + private static final Map apiConfigurationMap = new HashMap<>(); @Autowired private final AbstractRedisClient redisClient; @@ -31,7 +33,7 @@ public class RateLimitConfig { } static { - apiConfigurations.put( + apiConfigurationMap.put( RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, createBucketConfiguration(Duration.ofDays(1), 5)); // Add more API configurations as needed } @@ -60,7 +62,7 @@ public class RateLimitConfig { public Map apiBuckets() { Map apiBuckets = new HashMap<>(); - apiConfigurations.forEach((apiIdentifier, configuration) -> + apiConfigurationMap.forEach((apiIdentifier, configuration) -> apiBuckets.put(apiIdentifier, proxyManager().builder().build(apiIdentifier.getBytes(), configuration))); return apiBuckets; @@ -73,7 +75,7 @@ public class RateLimitConfig { return proxyManager().builder().build(bucketIdentifier.getBytes(), bucketProxy.get()); } - return proxyManager().builder().build(bucketIdentifier.getBytes(), apiConfigurations.get(apiIdentifier)); + return proxyManager().builder().build(bucketIdentifier.getBytes(), apiConfigurationMap.get(apiIdentifier)); } private static BucketConfiguration createBucketConfiguration(Duration refillDuration, int limit) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitService.java index 51a9b048d9..483d001a2d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitService.java @@ -1,45 +1,5 @@ package com.appsmith.server.ratelimiting; -import io.github.bucket4j.distributed.BucketProxy; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Mono; +import com.appsmith.server.ratelimiting.ce.RateLimitServiceCE; -import java.util.Map; - -@Slf4j -@Service -public class RateLimitService { - - private final Map apiBuckets; - private final RateLimitConfig rateLimitConfig; - // this number of tokens var can later be customised per API in the configuration. - private final Integer DEFAULT_NUMBER_OF_TOKENS_CONSUMED_PER_REQUEST = 1; - - public RateLimitService(Map apiBuckets, RateLimitConfig rateLimitConfig) { - this.apiBuckets = apiBuckets; - this.rateLimitConfig = rateLimitConfig; - } - - public Mono tryIncreaseCounter(String apiIdentifier, String userIdentifier) { - log.debug( - "RateLimitService.tryIncreaseCounter() called with apiIdentifier = {}, userIdentifier = {}", - apiIdentifier, - userIdentifier); - // handle the case where API itself is not rate limited - log.debug( - apiBuckets.containsKey(apiIdentifier) ? "apiBuckets contains key" : "apiBuckets does not contain key"); - if (!apiBuckets.containsKey(apiIdentifier)) return Mono.just(false); - - BucketProxy userSpecificBucket = - rateLimitConfig.getOrCreateAPIUserSpecificBucket(apiIdentifier, userIdentifier); - log.debug("userSpecificBucket = {}", userSpecificBucket); - return Mono.just(userSpecificBucket.tryConsume(DEFAULT_NUMBER_OF_TOKENS_CONSUMED_PER_REQUEST)); - } - - public void resetCounter(String apiIdentifier, String userIdentifier) { - rateLimitConfig - .getOrCreateAPIUserSpecificBucket(apiIdentifier, userIdentifier) - .reset(); - } -} +public interface RateLimitService extends RateLimitServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitServiceImpl.java new file mode 100644 index 0000000000..697445a4d9 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/RateLimitServiceImpl.java @@ -0,0 +1,17 @@ +package com.appsmith.server.ratelimiting; + +import com.appsmith.server.ratelimiting.ce.RateLimitServiceCEImpl; +import io.github.bucket4j.distributed.BucketProxy; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Slf4j +@Service +public class RateLimitServiceImpl extends RateLimitServiceCEImpl implements RateLimitService { + + public RateLimitServiceImpl(Map apiBuckets, RateLimitConfig rateLimitConfig) { + super(apiBuckets, rateLimitConfig); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/aspects/RateLimitAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/aspects/RateLimitAspect.java index 5e67421bb0..da42da1743 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/aspects/RateLimitAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/aspects/RateLimitAspect.java @@ -42,8 +42,7 @@ public class RateLimitAspect { Object result = joinPoint.proceed(); return result instanceof Mono ? (Mono) result : Mono.just(result); } catch (Throwable e) { - AppsmithError error = AppsmithError.INTERNAL_SERVER_ERROR; - throw new AppsmithException(error, e.getMessage()); + return Mono.error(new AppsmithException(AppsmithError.INTERNAL_SERVER_ERROR)); } }); }); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCE.java new file mode 100644 index 0000000000..78bbe99efc --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCE.java @@ -0,0 +1,9 @@ +package com.appsmith.server.ratelimiting.ce; + +import reactor.core.publisher.Mono; + +public interface RateLimitServiceCE { + Mono tryIncreaseCounter(String apiIdentifier, String userIdentifier); + + Mono resetCounter(String apiIdentifier, String userIdentifier); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCEImpl.java new file mode 100644 index 0000000000..4eb33c9a83 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/ratelimiting/ce/RateLimitServiceCEImpl.java @@ -0,0 +1,90 @@ +package com.appsmith.server.ratelimiting.ce; + +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.ratelimiting.RateLimitConfig; +import io.github.bucket4j.distributed.BucketProxy; +import lombok.extern.slf4j.Slf4j; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Scheduler; +import reactor.core.scheduler.Schedulers; + +import java.util.Map; + +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; + +@Slf4j +public class RateLimitServiceCEImpl implements RateLimitServiceCE { + + private final Scheduler scheduler = Schedulers.boundedElastic(); + private final Map apiBuckets; + private final RateLimitConfig rateLimitConfig; + // this number of tokens can later be customised per API in the configuration. + private final Integer DEFAULT_NUMBER_OF_TOKENS_CONSUMED_PER_REQUEST = 1; + + public RateLimitServiceCEImpl(Map apiBuckets, RateLimitConfig rateLimitConfig) { + this.apiBuckets = apiBuckets; + this.rateLimitConfig = rateLimitConfig; + } + + @Override + public Mono tryIncreaseCounter(String apiIdentifier, String userIdentifier) { + + return sanitizeInput(apiIdentifier, userIdentifier) + .flatMap(isInputValid -> { + BucketProxy userSpecificBucket = + rateLimitConfig.getOrCreateAPIUserSpecificBucket(apiIdentifier, userIdentifier); + + return Mono.just(userSpecificBucket.tryConsume(DEFAULT_NUMBER_OF_TOKENS_CONSUMED_PER_REQUEST)); + }) + .map(isSuccessful -> { + if (FALSE.equals(isSuccessful)) { + log.debug( + "{} - Rate Limit exceeded for apiIdentifier = {}, userIdentifier = {}", + Thread.currentThread().getName(), + apiIdentifier, + userIdentifier); + } + + return isSuccessful; + }) + // Since we are interacting with redis, we want to make sure that the operation is done on a separate + // thread pool + .subscribeOn(scheduler); + } + + @Override + public Mono resetCounter(String apiIdentifier, String userIdentifier) { + + return sanitizeInput(apiIdentifier, userIdentifier) + .flatMap(isInputValid -> { + rateLimitConfig + .getOrCreateAPIUserSpecificBucket(apiIdentifier, userIdentifier) + .reset(); + + return Mono.just(TRUE); + }) + .then() + // Since we are interacting with redis, we want to make sure that the operation is done on a separate + // thread pool + .subscribeOn(scheduler); + } + + private Mono sanitizeInput(String apiIdentifier, String userIdentifier) { + if (userIdentifier == null) { + return Mono.error(new AppsmithException(AppsmithError.INTERNAL_SERVER_ERROR)); + } + + return Mono.just(userIdentifier) + .flatMap(username -> { + // Handle the case where API itself is not rate limited. + if (!apiBuckets.containsKey(apiIdentifier)) { + return Mono.error(new AppsmithException(AppsmithError.UNSUPPORTED_OPERATION)); + } + + return Mono.just(true); + }) + .subscribeOn(scheduler); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java index 72ad7d0ae0..c99221bb52 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java @@ -425,8 +425,12 @@ public class UserServiceCEImpl extends BaseService .subscribe(); // we reset the counter for user's login attempts once password is reset - rateLimitService.resetCounter( - RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, userFromDb.getEmail()); + rateLimitService + .resetCounter( + RateLimitConstants.BUCKET_KEY_FOR_LOGIN_API, + userFromDb.getEmail()) + .subscribeOn(Schedulers.boundedElastic()) + .subscribe(); }) .thenReturn(true); })); From 65178eaf7e1f4ac6a600fb518ef3c7c4794baab5 Mon Sep 17 00:00:00 2001 From: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:16:17 +0530 Subject: [PATCH 09/75] feat: Added custom hex colors for testing workflow (#27568) ## Description Added workflow to check if there is any custom colors or hex codes is being used. This workflow will be checking for the anomalies in the entire file that has been changed by the developer. #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/27839 #### Type of change - New feature (non-breaking change which adds functionality) ## 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 - [x] My code follows the style guidelines of this project - [x] 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 - [x] 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 --------- Co-authored-by: Saroj --- .github/workflows/client-build.yml | 47 +++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/.github/workflows/client-build.yml b/.github/workflows/client-build.yml index 9c444f4191..d3b3b4554a 100644 --- a/.github/workflows/client-build.yml +++ b/.github/workflows/client-build.yml @@ -21,6 +21,11 @@ on: description: "This is the branch to be used for the build." required: false type: string + ads-compliant-check: + description: "This is a boolean value in case the workflow is being called in build deploy-preview" + required: false + type: string + default: "true" # Change the working directory for all the jobs in this workflow @@ -93,7 +98,7 @@ jobs: done echo "non_ts_files=${non_ts_files[@]}" >> $GITHUB_OUTPUT echo "non_ts_files_count=${#non_ts_files[@]}" >> $GITHUB_OUTPUT - + # Comment in PR if test files are not written in ts and fail the workflow - name: Comment in PR if test files are not written in ts if: steps.check_files.outputs.non_ts_files_count != 0 && inputs.check-test-files == 'true' && inputs.pr != 0 @@ -106,6 +111,46 @@ jobs:
    ${{ steps.check_files.outputs.non_ts_files }}
- if: steps.check_files.outputs.non_ts_files_count != 0 && inputs.check-test-files == 'true' && inputs.pr != 0 run: exit 1 + + - name: Get all the added or changed files in client/src folder + if: inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release' + id: client_files + uses: umani/changed-files@v4.0.0 + with: + repo-token: ${{ secrets.APPSMITH_CI_TEST_PAT }} + pattern: 'app/client/src/.*' + pr-number: ${{ inputs.pr }} + + # Check all the newly added files are in ts + - name: ADS compliant check + if: inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release' + id: ads_check + run: | + comment_files="" + files=(${{steps.client_files.outputs.files_created}}${{steps.client_files.outputs.files_updated}}) + for file in "${files[@]}"; do + while IFS= read -r line; do + if echo "$line" | grep -q -E '(color|Color).*#|border.*#|(color|Color).*"'; then + comment_files+=("$file") + break + fi + done < ${file#app/client/} + done + unique_files=$(echo "${comment_files[@]}" | sort -u | sed '/^[[:space:]]*$/d' | sed 's/ /
  • /g') + echo "ads_non_compliant_files=$unique_files" >> $GITHUB_OUTPUT + echo "ads_non_compliant_count=${#unique_files[@]}" >> $GITHUB_OUTPUT + + # Comment in PR if test files are not written in ts and fail the workflow + - name: Comment in PR if test files are not written in ts + if: steps.ads_check.outputs.ads_non_compliant_count != 0 && inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release' + uses: peter-evans/create-or-update-comment@v1 + with: + issue-number: ${{ inputs.pr }} + body: | + 🔴 Below files are not compliant with ADS. Please fix and re-trigger ok-to-test +
      ${{steps.ads_check.outputs.ads_non_compliant_files}}
    + - if: steps.ads_check.outputs.ads_non_compliant_count != 0 && inputs.ads-compliant-check == 'true' && inputs.pr != 0 && github.pull_request.base.ref == 'release' + run: exit 1 # Create a run record exactly at the time of merge to release to # ensure we compare run details with code at this point From 8eac493b80b78278ac90ca18564ac62a3454ad35 Mon Sep 17 00:00:00 2001 From: Nilesh Sarupriya Date: Tue, 10 Oct 2023 17:56:43 +0530 Subject: [PATCH 10/75] chore: remove additional parameters from UserService constructor (#27924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description > Remove additional parameters from UserService constructors #### PR fixes following issue(s) Fixes # (issue number) > if no issue exists, please create an issue and ask the maintainers about this first > > #### 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 Co-authored-by: Nilesh Sarupriya <20905988+nsarupr@users.noreply.github.com> --- .../appsmith/server/services/UserServiceImpl.java | 5 ----- .../server/services/ce/UserServiceCEImpl.java | 14 -------------- .../UserServiceCECompatibleImpl.java | 15 --------------- 3 files changed, 34 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java index 87f48686f1..ffd2131688 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java @@ -64,16 +64,11 @@ public class UserServiceImpl extends UserServiceCECompatibleImpl implements User sessionUserService, passwordResetTokenRepository, passwordEncoder, - emailSender, - applicationRepository, - policySolution, commonConfig, - emailConfig, userChangedHandler, encryptionService, userDataService, tenantService, - permissionGroupService, userUtils, emailVerificationTokenRepository, emailService, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java index c99221bb52..cef13ad126 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java @@ -4,7 +4,6 @@ import com.appsmith.external.helpers.AppsmithBeanUtils; import com.appsmith.external.services.EncryptionService; import com.appsmith.server.acl.AclPermission; import com.appsmith.server.configurations.CommonConfig; -import com.appsmith.server.configurations.EmailConfig; import com.appsmith.server.constants.FieldName; import com.appsmith.server.constants.RateLimitConstants; import com.appsmith.server.domains.EmailVerificationToken; @@ -26,9 +25,7 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserUtils; import com.appsmith.server.helpers.ValidationUtils; -import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.ratelimiting.RateLimitService; -import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.EmailVerificationTokenRepository; import com.appsmith.server.repositories.PasswordResetTokenRepository; import com.appsmith.server.repositories.UserRepository; @@ -36,12 +33,10 @@ import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.BaseService; import com.appsmith.server.services.EmailService; import com.appsmith.server.services.PACConfigurationService; -import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.WorkspaceService; -import com.appsmith.server.solutions.PolicySolution; import com.appsmith.server.solutions.UserChangedHandler; import jakarta.validation.Validator; import lombok.extern.slf4j.Slf4j; @@ -104,13 +99,11 @@ public class UserServiceCEImpl extends BaseService private final PasswordEncoder passwordEncoder; - private final PolicySolution policySolution; private final CommonConfig commonConfig; private final UserChangedHandler userChangedHandler; private final EncryptionService encryptionService; private final UserDataService userDataService; private final TenantService tenantService; - private final PermissionGroupService permissionGroupService; private final UserUtils userUtils; private final EmailService emailService; private final RateLimitService rateLimitService; @@ -142,16 +135,11 @@ public class UserServiceCEImpl extends BaseService SessionUserService sessionUserService, PasswordResetTokenRepository passwordResetTokenRepository, PasswordEncoder passwordEncoder, - EmailSender emailSender, - ApplicationRepository applicationRepository, - PolicySolution policySolution, CommonConfig commonConfig, - EmailConfig emailConfig, UserChangedHandler userChangedHandler, EncryptionService encryptionService, UserDataService userDataService, TenantService tenantService, - PermissionGroupService permissionGroupService, UserUtils userUtils, EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, @@ -164,13 +152,11 @@ public class UserServiceCEImpl extends BaseService this.sessionUserService = sessionUserService; this.passwordResetTokenRepository = passwordResetTokenRepository; this.passwordEncoder = passwordEncoder; - this.policySolution = policySolution; this.commonConfig = commonConfig; this.userChangedHandler = userChangedHandler; this.encryptionService = encryptionService; this.userDataService = userDataService; this.tenantService = tenantService; - this.permissionGroupService = permissionGroupService; this.userUtils = userUtils; this.rateLimitService = rateLimitService; this.emailVerificationTokenRepository = emailVerificationTokenRepository; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java index 8b458b36fe..506695dfcb 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce_compatible/UserServiceCECompatibleImpl.java @@ -2,25 +2,20 @@ package com.appsmith.server.services.ce_compatible; import com.appsmith.external.services.EncryptionService; import com.appsmith.server.configurations.CommonConfig; -import com.appsmith.server.configurations.EmailConfig; import com.appsmith.server.helpers.UserServiceHelper; import com.appsmith.server.helpers.UserUtils; -import com.appsmith.server.notifications.EmailSender; import com.appsmith.server.ratelimiting.RateLimitService; -import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.EmailVerificationTokenRepository; import com.appsmith.server.repositories.PasswordResetTokenRepository; import com.appsmith.server.repositories.UserRepository; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.EmailService; import com.appsmith.server.services.PACConfigurationService; -import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.TenantService; import com.appsmith.server.services.UserDataService; import com.appsmith.server.services.WorkspaceService; import com.appsmith.server.services.ce.UserServiceCEImpl; -import com.appsmith.server.solutions.PolicySolution; import com.appsmith.server.solutions.UserChangedHandler; import jakarta.validation.Validator; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; @@ -42,16 +37,11 @@ public class UserServiceCECompatibleImpl extends UserServiceCEImpl implements Us SessionUserService sessionUserService, PasswordResetTokenRepository passwordResetTokenRepository, PasswordEncoder passwordEncoder, - EmailSender emailSender, - ApplicationRepository applicationRepository, - PolicySolution policySolution, CommonConfig commonConfig, - EmailConfig emailConfig, UserChangedHandler userChangedHandler, EncryptionService encryptionService, UserDataService userDataService, TenantService tenantService, - PermissionGroupService permissionGroupService, UserUtils userUtils, EmailVerificationTokenRepository emailVerificationTokenRepository, EmailService emailService, @@ -69,16 +59,11 @@ public class UserServiceCECompatibleImpl extends UserServiceCEImpl implements Us sessionUserService, passwordResetTokenRepository, passwordEncoder, - emailSender, - applicationRepository, - policySolution, commonConfig, - emailConfig, userChangedHandler, encryptionService, userDataService, tenantService, - permissionGroupService, userUtils, emailVerificationTokenRepository, emailService, From 0f393a2423e90b75a9487b3bca245dbd41ebe75b Mon Sep 17 00:00:00 2001 From: Apeksha Bhosale <7846888+ApekshaBhosale@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:02:17 +0530 Subject: [PATCH 11/75] chore: separated tree type into common file to be extended on EE (#27812) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description UnEvalTree, dataTree and configTree's entities needs to be extended on EE to accommodate module inputs and different types of modules hence the separation. I have added few more sanity checks in the existing code which were throwing errors/warning on EE. #### PR fixes following issue(s) Fixes # (issue number) #### 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 - Chore (housekeeping or task changes that don't impact user perception) > > > ## 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 --- app/client/src/ce/entities/DataTree/types.ts | 20 ------ app/client/src/ce/entities/DataTree/utils.ts | 12 ++-- .../src/ce/workers/Evaluation/Actions.ts | 4 +- .../__tests__/dataTreeUtils.test.ts | 2 +- .../ce/workers/Evaluation/dataTreeUtils.ts | 2 +- .../Evaluation/evaluationUtils.test.ts | 12 ++-- .../ce/workers/Evaluation/evaluationUtils.ts | 22 +++--- .../ActionCreator/helpers.tsx | 2 +- .../CodeEditor/EditorConfig.ts | 3 +- .../editorComponents/CodeEditor/index.tsx | 6 +- .../fields/EmbeddedDatasourcePathField.tsx | 2 +- .../PrimaryColumnsControl.tsx | 2 +- .../PrimaryColumnsControlV2.tsx | 2 +- .../src/entities/DataTree/dataTreeFactory.ts | 27 +++---- .../src/entities/DataTree/dataTreeTypes.ts | 27 +++++++ .../src/layoutSystems/common/selectors.ts | 2 +- app/client/src/plugins/Linting/globalData.ts | 2 +- .../plugins/Linting/lib/entity/EntityTree.ts | 2 +- .../src/plugins/Linting/lib/entity/index.ts | 2 +- app/client/src/plugins/Linting/types.ts | 2 +- .../src/plugins/Linting/utils/entityParser.ts | 2 +- .../Linting/utils/getEntityDependencies.ts | 2 +- .../Linting/utils/getEvaluationContext.ts | 2 +- .../src/plugins/Linting/utils/getJSToLint.ts | 2 +- .../plugins/Linting/utils/isEntityFunction.ts | 2 +- .../plugins/Linting/utils/lintJSObjectBody.ts | 6 +- .../plugins/Linting/utils/lintJSProperty.ts | 2 +- .../Linting/utils/sortLintingPathsByType.ts | 2 +- .../evaluationReducers/treeReducer.ts | 2 +- .../ActionExecution/ResetWidgetActionSaga.ts | 7 +- app/client/src/sagas/DebuggerSagas.ts | 2 +- app/client/src/sagas/EvalWorkerActionSagas.ts | 2 +- app/client/src/sagas/EvaluationsSaga.ts | 8 +-- app/client/src/sagas/FormEvaluationSaga.ts | 2 +- app/client/src/sagas/OnboardingSagas.ts | 2 +- app/client/src/sagas/PostEvaluationSagas.ts | 4 +- app/client/src/sagas/PostLintingSagas.ts | 2 +- app/client/src/sagas/WidgetAdditionSagas.ts | 2 +- app/client/src/sagas/WidgetLoadingSaga.ts | 2 +- app/client/src/sagas/WidgetOperationSagas.tsx | 7 +- app/client/src/sagas/WidgetOperationUtils.ts | 2 +- .../src/sagas/autoHeightSagas/containers.ts | 3 +- .../src/sagas/autoHeightSagas/helpers.ts | 3 +- app/client/src/selectors/actionSelectors.tsx | 2 +- app/client/src/selectors/dataTreeSelectors.ts | 3 +- .../src/selectors/debuggerSelectors.test.ts | 2 +- .../src/selectors/debuggerSelectors.tsx | 3 +- app/client/src/selectors/editorSelectors.tsx | 3 +- app/client/src/selectors/formSelectors.ts | 2 +- .../src/selectors/navigationSelectors.ts | 3 +- .../src/selectors/propertyPaneSelectors.tsx | 7 +- app/client/src/utils/DynamicBindingUtils.ts | 6 +- .../utils/FilterInternalProperties/Action.ts | 3 +- .../FilterInternalProperties/Appsmith.ts | 6 +- .../FilterInternalProperties/JsAction.ts | 6 +- .../utils/FilterInternalProperties/Widget.ts | 3 +- .../utils/FilterInternalProperties/index.ts | 2 +- .../utils/NavigationSelector/JsChildren.ts | 6 +- .../NavigationSelector/WidgetChildren.ts | 3 +- app/client/src/utils/SuccessfulBindingsMap.ts | 2 +- .../src/utils/WidgetLoadingStateUtils.ts | 2 +- .../autocomplete/dataTreeTypeDefCreator.ts | 8 ++- app/client/src/utils/configTree.ts | 2 +- .../src/utils/widgetRenderUtils.test.ts | 2 +- app/client/src/utils/widgetRenderUtils.tsx | 3 +- .../JSObject/__test__/mutation.test.ts | 2 +- .../src/workers/Evaluation/JSObject/index.ts | 7 +- .../src/workers/Evaluation/JSObject/test.ts | 2 +- .../src/workers/Evaluation/JSObject/utils.ts | 8 ++- .../Evaluation/__tests__/Actions.test.ts | 3 +- .../__tests__/errorModifier.test.ts | 2 +- .../Evaluation/__tests__/evaluate.test.ts | 3 +- .../Evaluation/__tests__/evaluation.test.ts | 3 +- .../Evaluation/__tests__/setters.test.ts | 2 +- .../Evaluation/__tests__/timeout.test.ts | 3 +- .../src/workers/Evaluation/dataStore/index.ts | 2 +- .../src/workers/Evaluation/dataStore/utils.ts | 2 +- .../src/workers/Evaluation/errorModifier.ts | 2 +- .../workers/Evaluation/evalTreeWithChanges.ts | 2 +- app/client/src/workers/Evaluation/evaluate.ts | 2 +- .../fns/__tests__/LocalStorage.test.ts | 3 +- .../Evaluation/fns/__tests__/interval.test.ts | 3 +- .../src/workers/Evaluation/fns/index.ts | 6 +- app/client/src/workers/Evaluation/fns/mock.ts | 2 +- .../workers/Evaluation/getEntityForContext.ts | 6 +- .../workers/Evaluation/handlers/evalTree.ts | 2 +- app/client/src/workers/Evaluation/helpers.ts | 2 +- app/client/src/workers/Evaluation/setters.ts | 4 +- app/client/src/workers/Evaluation/types.ts | 2 +- .../workers/common/DataTreeEvaluator/index.ts | 71 ++++++++----------- .../mockData/ArrayAccessorTree.ts | 2 +- .../mockData/NestedArrayAccessorTree.ts | 2 +- .../workers/common/DataTreeEvaluator/test.ts | 2 +- .../workers/common/DataTreeEvaluator/utils.ts | 17 ++++- .../DataTreeEvaluator/validationUtils.ts | 3 +- .../src/workers/common/DependencyMap/index.ts | 10 +-- .../src/workers/common/DependencyMap/test.ts | 3 +- .../src/workers/common/DependencyMap/utils.ts | 4 +- .../utils/getEntityDependencies.ts | 15 ++-- .../utils/getValidationDependencies.ts | 2 +- 100 files changed, 252 insertions(+), 258 deletions(-) create mode 100644 app/client/src/entities/DataTree/dataTreeTypes.ts diff --git a/app/client/src/ce/entities/DataTree/types.ts b/app/client/src/ce/entities/DataTree/types.ts index f2daa0fed1..52fd8b87ab 100644 --- a/app/client/src/ce/entities/DataTree/types.ts +++ b/app/client/src/ce/entities/DataTree/types.ts @@ -145,11 +145,6 @@ export type UnEvalTreeEntityObject = | JSActionEntity | WidgetEntity; -export type UnEvalTreeEntity = UnEvalTreeEntityObject | AppsmithEntity | Page[]; - -export type UnEvalTree = { - [entityName: string]: UnEvalTreeEntity; -}; export interface WidgetEntity extends WidgetProps { meta: Record; ENTITY_TYPE: ENTITY_TYPE.WIDGET; @@ -160,12 +155,6 @@ export type DataTreeEntityObject = | WidgetEntity | AppsmithEntity; -export type DataTreeEntity = DataTreeEntityObject | Page[] | ActionDispatcher; - -export type DataTree = { - [entityName: string]: DataTreeEntity; -}; - export interface WidgetEntityConfig extends Partial, Omit, @@ -207,12 +196,3 @@ export type DataTreeEntityConfig = | WidgetEntityConfig | ActionEntityConfig | JSActionEntityConfig; - -export type ConfigTree = { - [entityName: string]: DataTreeEntityConfig; -}; - -export type unEvalAndConfigTree = { - unEvalTree: UnEvalTree; - configTree: ConfigTree; -}; diff --git a/app/client/src/ce/entities/DataTree/utils.ts b/app/client/src/ce/entities/DataTree/utils.ts index 60cbcf622b..91edd3a031 100644 --- a/app/client/src/ce/entities/DataTree/utils.ts +++ b/app/client/src/ce/entities/DataTree/utils.ts @@ -2,14 +2,12 @@ import type { PropertyOverrideDependency, OverridingPropertyPaths, ModuleInput, - DataTreeEntity, WidgetEntity, ActionEntity, JSActionEntity, - ConfigTree, - UnEvalTree, DataTreeEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { OverridingPropertyType } from "@appsmith/entities/DataTree/types"; import { isAction, @@ -70,14 +68,12 @@ export const setOverridingProperty = ({ }; export const generateDataTreeModuleInputs = ( - dataTree: UnEvalTree, - configTree: ConfigTree, // eslint-disable-next-line @typescript-eslint/no-unused-vars - moduleInputs: Record, + moduleInput: ModuleInput, ) => { return { - dataTree, - configTree, + unEvalEntity: null, + configEntity: null, }; }; diff --git a/app/client/src/ce/workers/Evaluation/Actions.ts b/app/client/src/ce/workers/Evaluation/Actions.ts index 03d4d128a4..fcfe8a4a87 100644 --- a/app/client/src/ce/workers/Evaluation/Actions.ts +++ b/app/client/src/ce/workers/Evaluation/Actions.ts @@ -1,12 +1,12 @@ /* eslint-disable @typescript-eslint/ban-types */ import set from "lodash/set"; +import type { DataTreeEntityConfig } from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree, DataTreeEntity, - DataTreeEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { EvalContext } from "workers/Evaluation/evaluate"; import type { EvaluationVersion } from "@appsmith/api/ApplicationApi"; import { addFn } from "workers/Evaluation/fns/utils/fnGuard"; diff --git a/app/client/src/ce/workers/Evaluation/__tests__/dataTreeUtils.test.ts b/app/client/src/ce/workers/Evaluation/__tests__/dataTreeUtils.test.ts index 08742a7a71..4d0af2cc54 100644 --- a/app/client/src/ce/workers/Evaluation/__tests__/dataTreeUtils.test.ts +++ b/app/client/src/ce/workers/Evaluation/__tests__/dataTreeUtils.test.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { makeEntityConfigsAsObjProperties } from "@appsmith/workers/Evaluation/dataTreeUtils"; import { smallDataSet } from "workers/Evaluation/__tests__/generateOpimisedUpdates.test"; import produce from "immer"; diff --git a/app/client/src/ce/workers/Evaluation/dataTreeUtils.ts b/app/client/src/ce/workers/Evaluation/dataTreeUtils.ts index f5ea3b6fe5..814aaf2be2 100644 --- a/app/client/src/ce/workers/Evaluation/dataTreeUtils.ts +++ b/app/client/src/ce/workers/Evaluation/dataTreeUtils.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { get, isObject, set, unset } from "lodash"; import { klona } from "klona/json"; import type { EvalProps } from "workers/common/DataTreeEvaluator"; diff --git a/app/client/src/ce/workers/Evaluation/evaluationUtils.test.ts b/app/client/src/ce/workers/Evaluation/evaluationUtils.test.ts index 543dca900c..538663cf19 100644 --- a/app/client/src/ce/workers/Evaluation/evaluationUtils.test.ts +++ b/app/client/src/ce/workers/Evaluation/evaluationUtils.test.ts @@ -4,19 +4,20 @@ import { RenderModes } from "constants/WidgetConstants"; import { ValidationTypes } from "constants/WidgetValidation"; import type { - ConfigTree, - DataTreeEntity, WidgetEntity, WidgetEntityConfig, + PrivateWidgets, + JSActionEntity, } from "@appsmith/entities/DataTree/types"; import { ENTITY_TYPE_VALUE, EvaluationSubstitutionType, } from "entities/DataTree/dataTreeFactory"; import type { - PrivateWidgets, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; + ConfigTree, + DataTreeEntity, + DataTree, +} from "entities/DataTree/dataTreeTypes"; import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils"; import { addErrorToEntityProperty, @@ -36,7 +37,6 @@ import { overrideWidgetProperties, findDatatype, } from "@appsmith/workers/Evaluation/evaluationUtils"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types"; import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget"; import TableWidget from "widgets/TableWidget"; diff --git a/app/client/src/ce/workers/Evaluation/evaluationUtils.ts b/app/client/src/ce/workers/Evaluation/evaluationUtils.ts index bf99148ca7..60d185451d 100644 --- a/app/client/src/ce/workers/Evaluation/evaluationUtils.ts +++ b/app/client/src/ce/workers/Evaluation/evaluationUtils.ts @@ -9,28 +9,28 @@ import { } from "utils/DynamicBindingUtils"; import type { Diff } from "deep-diff"; import type { - DataTree, - AppsmithEntity, DataTreeEntity, - WidgetEntity, - DataTreeEntityConfig, + DataTree, ConfigTree, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "@appsmith/entities/DataTree/types"; -import _, { difference, find, get, has, isNil, set } from "lodash"; +import _, { difference, find, get, has, isEmpty, isNil, set } from "lodash"; import type { WidgetTypeConfigMap } from "WidgetProvider/factory"; import { PluginType } from "entities/Action"; import { klona } from "klona/full"; import { warn as logWarn } from "loglevel"; import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types"; import { isObject } from "lodash"; -import type { DataTreeEntityObject } from "@appsmith/entities/DataTree/types"; import type { JSActionEntityConfig, PrivateWidgets, JSActionEntity, ActionEntity, + AppsmithEntity, + WidgetEntity, + DataTreeEntityConfig, + WidgetEntityConfig, + DataTreeEntityObject, } from "@appsmith/entities/DataTree/types"; import type { EvalProps } from "workers/common/DataTreeEvaluator"; import { validateWidgetProperty } from "workers/common/DataTreeEvaluator/validationUtils"; @@ -656,7 +656,8 @@ export const isDynamicLeaf = ( return false; const relativePropertyPath = convertPathToString(propPathEls); return ( - relativePropertyPath in entityConfig.reactivePaths || + (!isEmpty(entityConfig.reactivePaths) && + relativePropertyPath in entityConfig.reactivePaths) || (isWidget(entityConfig) && relativePropertyPath in entityConfig?.triggerPaths) ); @@ -870,8 +871,9 @@ export function isValidEntity( if (!isObject(entity)) { return false; } - return "ENTITY_TYPE" in entity; + return true; } + export const isATriggerPath = ( entityConfig: DataTreeEntityConfig, propertyPath: string, diff --git a/app/client/src/components/editorComponents/ActionCreator/helpers.tsx b/app/client/src/components/editorComponents/ActionCreator/helpers.tsx index d5de020d2f..c534fe3f04 100644 --- a/app/client/src/components/editorComponents/ActionCreator/helpers.tsx +++ b/app/client/src/components/editorComponents/ActionCreator/helpers.tsx @@ -60,7 +60,7 @@ import { isAction, isJSAction, } from "@appsmith/workers/Evaluation/evaluationUtils"; -import type { DataTreeEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; const actionList: { label: string; diff --git a/app/client/src/components/editorComponents/CodeEditor/EditorConfig.ts b/app/client/src/components/editorComponents/CodeEditor/EditorConfig.ts index a6228afe78..131613b052 100644 --- a/app/client/src/components/editorComponents/CodeEditor/EditorConfig.ts +++ b/app/client/src/components/editorComponents/CodeEditor/EditorConfig.ts @@ -1,5 +1,6 @@ import type CodeMirror from "codemirror"; -import type { DataTree, ENTITY_TYPE } from "@appsmith/entities/DataTree/types"; +import type { ENTITY_TYPE } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; import type { EntityNavigationData } from "selectors/navigationSelectors"; import type { ExpectedValueExample } from "utils/validation/common"; diff --git a/app/client/src/components/editorComponents/CodeEditor/index.tsx b/app/client/src/components/editorComponents/CodeEditor/index.tsx index 46b40f5181..316b413031 100644 --- a/app/client/src/components/editorComponents/CodeEditor/index.tsx +++ b/app/client/src/components/editorComponents/CodeEditor/index.tsx @@ -31,10 +31,8 @@ import _, { debounce, isEqual } from "lodash"; import scrollIntoView from "scroll-into-view-if-needed"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; -import type { - DataTree, - EvaluationSubstitutionType, -} from "@appsmith/entities/DataTree/types"; +import type { EvaluationSubstitutionType } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { Skin } from "constants/DefaultTheme"; import AnalyticsUtil from "utils/AnalyticsUtil"; import "components/editorComponents/CodeEditor/sql/customMimes"; diff --git a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx index 2d5002db86..ee675469e7 100644 --- a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx +++ b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @@ -34,7 +34,7 @@ import { getCurrentApplicationId } from "selectors/editorSelectors"; import { Indices } from "constants/Layers"; import { getExpectedValue } from "utils/validation/common"; import { ValidationTypes } from "constants/WidgetValidation"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { getDataTree } from "selectors/dataTreeSelectors"; import type { KeyValuePair } from "entities/Action"; diff --git a/app/client/src/components/propertyControls/PrimaryColumnsControl.tsx b/app/client/src/components/propertyControls/PrimaryColumnsControl.tsx index 476bd671f7..51decad7e0 100644 --- a/app/client/src/components/propertyControls/PrimaryColumnsControl.tsx +++ b/app/client/src/components/propertyControls/PrimaryColumnsControl.tsx @@ -17,7 +17,7 @@ import { getTableStyles, } from "widgets/TableWidget/component/TableUtilities"; import { reorderColumns } from "widgets/TableWidget/component/TableHelpers"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getDataTreeForAutocomplete } from "selectors/dataTreeSelectors"; import type { EvaluationError } from "utils/DynamicBindingUtils"; import { getEvalErrorPath, getEvalValuePath } from "utils/DynamicBindingUtils"; diff --git a/app/client/src/components/propertyControls/PrimaryColumnsControlV2.tsx b/app/client/src/components/propertyControls/PrimaryColumnsControlV2.tsx index 484de803ed..7d21870d0e 100644 --- a/app/client/src/components/propertyControls/PrimaryColumnsControlV2.tsx +++ b/app/client/src/components/propertyControls/PrimaryColumnsControlV2.tsx @@ -18,7 +18,7 @@ import { isColumnTypeEditable, reorderColumns, } from "widgets/TableWidgetV2/widget/utilities"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getDataTreeForAutocomplete, getPathEvalErrors, diff --git a/app/client/src/entities/DataTree/dataTreeFactory.ts b/app/client/src/entities/DataTree/dataTreeFactory.ts index 7428610823..e3a49e7c65 100644 --- a/app/client/src/entities/DataTree/dataTreeFactory.ts +++ b/app/client/src/entities/DataTree/dataTreeFactory.ts @@ -9,12 +9,14 @@ import { import { generateDataTreeModuleInputs } from "@appsmith/entities/DataTree/utils"; import type { DataTreeSeed, - unEvalAndConfigTree, - ConfigTree, AppsmithEntity, - UnEvalTree, ENTITY_TYPE, } from "@appsmith/entities/DataTree/types"; +import type { + unEvalAndConfigTree, + ConfigTree, + UnEvalTree, +} from "entities/DataTree/dataTreeTypes"; import { isEmpty } from "lodash"; export class DataTreeFactory { @@ -34,8 +36,8 @@ export class DataTreeFactory { widgets, widgetsMeta, }: DataTreeSeed): unEvalAndConfigTree { - let dataTree: UnEvalTree = {}; - let configTree: ConfigTree = {}; + const dataTree: UnEvalTree = {}; + const configTree: ConfigTree = {}; const start = performance.now(); const startActions = performance.now(); @@ -64,13 +66,14 @@ export class DataTreeFactory { const startWidgets = performance.now(); if (!isEmpty(moduleInputs)) { - const data = generateDataTreeModuleInputs( - dataTree, - configTree, - moduleInputs, - ); - dataTree = data.dataTree; - configTree = data.configTree; + for (const [key, value] of Object.entries(moduleInputs)) { + const { configEntity, unEvalEntity } = + generateDataTreeModuleInputs(value); + if (!!configEntity && !!unEvalEntity) { + dataTree[key] = unEvalEntity; + configTree[key] = configEntity; + } + } } Object.values(widgets).forEach((widget) => { diff --git a/app/client/src/entities/DataTree/dataTreeTypes.ts b/app/client/src/entities/DataTree/dataTreeTypes.ts new file mode 100644 index 0000000000..73b3042f4c --- /dev/null +++ b/app/client/src/entities/DataTree/dataTreeTypes.ts @@ -0,0 +1,27 @@ +import type { + DataTreeEntityConfig, + DataTreeEntityObject, + ActionDispatcher, + UnEvalTreeEntityObject, + AppsmithEntity, +} from "@appsmith/entities/DataTree/types"; +import type { Page } from "@appsmith/constants/ReduxActionConstants"; + +export type unEvalAndConfigTree = { + unEvalTree: UnEvalTree; + configTree: ConfigTree; +}; + +export type ConfigTree = { + [entityName: string]: DataTreeEntityConfig; +}; +export type DataTreeEntity = DataTreeEntityObject | Page[] | ActionDispatcher; + +export type DataTree = { + [entityName: string]: DataTreeEntity; +}; +export type UnEvalTreeEntity = UnEvalTreeEntityObject | AppsmithEntity | Page[]; + +export type UnEvalTree = { + [entityName: string]: UnEvalTreeEntity; +}; diff --git a/app/client/src/layoutSystems/common/selectors.ts b/app/client/src/layoutSystems/common/selectors.ts index 97d88fc27c..341ad7e922 100644 --- a/app/client/src/layoutSystems/common/selectors.ts +++ b/app/client/src/layoutSystems/common/selectors.ts @@ -12,7 +12,7 @@ import { getErrorCount } from "layoutSystems/common/widgetName/utils"; import type { WidgetPositions } from "./types"; import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetNameData } from "./WidgetNamesCanvas/WidgetNameTypes"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; export const getWidgetPositions = (state: AppState) => state.entities.widgetPositions; diff --git a/app/client/src/plugins/Linting/globalData.ts b/app/client/src/plugins/Linting/globalData.ts index 8a2f1e5da1..d16e08ac13 100644 --- a/app/client/src/plugins/Linting/globalData.ts +++ b/app/client/src/plugins/Linting/globalData.ts @@ -1,4 +1,4 @@ -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { isEmpty } from "lodash"; import type { EvalContext } from "workers/Evaluation/evaluate"; import { getEvaluationContext } from "./utils/getEvaluationContext"; diff --git a/app/client/src/plugins/Linting/lib/entity/EntityTree.ts b/app/client/src/plugins/Linting/lib/entity/EntityTree.ts index b69b880ea1..fe088a6d31 100644 --- a/app/client/src/plugins/Linting/lib/entity/EntityTree.ts +++ b/app/client/src/plugins/Linting/lib/entity/EntityTree.ts @@ -2,7 +2,7 @@ import type { ConfigTree, DataTree, DataTreeEntity, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { IEntity } from "."; import type { Diff } from "deep-diff"; import EntityFactory from "."; diff --git a/app/client/src/plugins/Linting/lib/entity/index.ts b/app/client/src/plugins/Linting/lib/entity/index.ts index 1309c50502..3c99d5a5ec 100644 --- a/app/client/src/plugins/Linting/lib/entity/index.ts +++ b/app/client/src/plugins/Linting/lib/entity/index.ts @@ -8,7 +8,6 @@ import type { WidgetEntity as TWidgetEntity, AppsmithEntity as TAppsmithEntity, DataTreeEntityConfig, - DataTreeEntity, WidgetEntityConfig as TWidgetEntityConfig, JSActionEntity as TJSActionEntity, ActionEntity as TActionEntity, @@ -16,6 +15,7 @@ import type { ActionEntityConfig as TActionEntityConfig, JSActionEntityConfig as TJSActionEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { defaultDiffGenerator, type EntityDiffGenerator, diff --git a/app/client/src/plugins/Linting/types.ts b/app/client/src/plugins/Linting/types.ts index 68c9371367..dd09224e54 100644 --- a/app/client/src/plugins/Linting/types.ts +++ b/app/client/src/plugins/Linting/types.ts @@ -2,7 +2,7 @@ import type { ConfigTree, DataTree, DataTreeEntity, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { LintErrorsStore } from "reducers/lintingReducers/lintErrorsReducers"; import type { createEvaluationContext, diff --git a/app/client/src/plugins/Linting/utils/entityParser.ts b/app/client/src/plugins/Linting/utils/entityParser.ts index dd3ec465f1..601822a819 100644 --- a/app/client/src/plugins/Linting/utils/entityParser.ts +++ b/app/client/src/plugins/Linting/utils/entityParser.ts @@ -1,9 +1,9 @@ import type { - DataTreeEntity, DataTreeEntityConfig, JSActionEntityConfig, JSActionEntity as TJSActionEntity, } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { EvaluationSubstitutionType } from "@appsmith/entities/DataTree/types"; import type { TParsedJSProperty } from "@shared/ast"; import { isJSFunctionProperty } from "@shared/ast"; diff --git a/app/client/src/plugins/Linting/utils/getEntityDependencies.ts b/app/client/src/plugins/Linting/utils/getEntityDependencies.ts index 31f514ac5c..acb66065e7 100644 --- a/app/client/src/plugins/Linting/utils/getEntityDependencies.ts +++ b/app/client/src/plugins/Linting/utils/getEntityDependencies.ts @@ -18,7 +18,7 @@ import type { JSEntity, WidgetEntity, } from "../lib/entity"; -import type { DataTreeEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; export function getEntityDependencies( entity: IEntity, diff --git a/app/client/src/plugins/Linting/utils/getEvaluationContext.ts b/app/client/src/plugins/Linting/utils/getEvaluationContext.ts index bf4b7b80fc..84f04b6e6d 100644 --- a/app/client/src/plugins/Linting/utils/getEvaluationContext.ts +++ b/app/client/src/plugins/Linting/utils/getEvaluationContext.ts @@ -1,4 +1,4 @@ -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { createEvaluationContext } from "workers/Evaluation/evaluate"; import { getActionTriggerFunctionNames } from "@appsmith/workers/Evaluation/fns"; diff --git a/app/client/src/plugins/Linting/utils/getJSToLint.ts b/app/client/src/plugins/Linting/utils/getJSToLint.ts index d71e1805b2..ad5c9bedc3 100644 --- a/app/client/src/plugins/Linting/utils/getJSToLint.ts +++ b/app/client/src/plugins/Linting/utils/getJSToLint.ts @@ -1,4 +1,4 @@ -import type { DataTreeEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { isJSAction } from "@appsmith/workers/Evaluation/evaluationUtils"; // Removes "export default" statement from js Object diff --git a/app/client/src/plugins/Linting/utils/isEntityFunction.ts b/app/client/src/plugins/Linting/utils/isEntityFunction.ts index f759e0f655..d982006be9 100644 --- a/app/client/src/plugins/Linting/utils/isEntityFunction.ts +++ b/app/client/src/plugins/Linting/utils/isEntityFunction.ts @@ -1,4 +1,4 @@ -import type { DataTreeEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { isDataTreeEntity } from "@appsmith/workers/Evaluation/evaluationUtils"; import { entityFns } from "@appsmith/workers/Evaluation/fns"; import setters from "workers/Evaluation/setters"; diff --git a/app/client/src/plugins/Linting/utils/lintJSObjectBody.ts b/app/client/src/plugins/Linting/utils/lintJSObjectBody.ts index ba7ba31143..10da015c0c 100644 --- a/app/client/src/plugins/Linting/utils/lintJSObjectBody.ts +++ b/app/client/src/plugins/Linting/utils/lintJSObjectBody.ts @@ -1,7 +1,5 @@ -import type { - DataTree, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { LintError } from "utils/DynamicBindingUtils"; import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils"; import { getScriptToEval, getScriptType } from "workers/Evaluation/evaluate"; diff --git a/app/client/src/plugins/Linting/utils/lintJSProperty.ts b/app/client/src/plugins/Linting/utils/lintJSProperty.ts index e9f6ea2e7d..331b8335ee 100644 --- a/app/client/src/plugins/Linting/utils/lintJSProperty.ts +++ b/app/client/src/plugins/Linting/utils/lintJSProperty.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { LintError } from "utils/DynamicBindingUtils"; import { isNil } from "lodash"; import { diff --git a/app/client/src/plugins/Linting/utils/sortLintingPathsByType.ts b/app/client/src/plugins/Linting/utils/sortLintingPathsByType.ts index cb863f9cf7..2c61bd3e24 100644 --- a/app/client/src/plugins/Linting/utils/sortLintingPathsByType.ts +++ b/app/client/src/plugins/Linting/utils/sortLintingPathsByType.ts @@ -1,4 +1,4 @@ -import type { DataTree, ConfigTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import { getEntityNameAndPropertyPath, isATriggerPath, diff --git a/app/client/src/reducers/evaluationReducers/treeReducer.ts b/app/client/src/reducers/evaluationReducers/treeReducer.ts index 5ce7b0e410..7edc07137b 100644 --- a/app/client/src/reducers/evaluationReducers/treeReducer.ts +++ b/app/client/src/reducers/evaluationReducers/treeReducer.ts @@ -2,7 +2,7 @@ import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import type { Diff } from "deep-diff"; import { applyChange } from "deep-diff"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { createImmerReducer } from "utils/ReducerUtils"; import * as Sentry from "@sentry/react"; import { get } from "lodash"; diff --git a/app/client/src/sagas/ActionExecution/ResetWidgetActionSaga.ts b/app/client/src/sagas/ActionExecution/ResetWidgetActionSaga.ts index 49b4932c3e..117b624c31 100644 --- a/app/client/src/sagas/ActionExecution/ResetWidgetActionSaga.ts +++ b/app/client/src/sagas/ActionExecution/ResetWidgetActionSaga.ts @@ -13,11 +13,8 @@ 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 { - DataTree, - ConfigTree, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; +import type { 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"; diff --git a/app/client/src/sagas/DebuggerSagas.ts b/app/client/src/sagas/DebuggerSagas.ts index bdbfb66c18..8aa2f80ae3 100644 --- a/app/client/src/sagas/DebuggerSagas.ts +++ b/app/client/src/sagas/DebuggerSagas.ts @@ -34,7 +34,7 @@ import type { Action } from "entities/Action"; import { PluginType } from "entities/Action"; import type { JSCollection } from "entities/JSCollection"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { getConfigTree, getDataTree, diff --git a/app/client/src/sagas/EvalWorkerActionSagas.ts b/app/client/src/sagas/EvalWorkerActionSagas.ts index 11c39502af..3f48c50d16 100644 --- a/app/client/src/sagas/EvalWorkerActionSagas.ts +++ b/app/client/src/sagas/EvalWorkerActionSagas.ts @@ -27,7 +27,7 @@ import type { JSVarMutatedEvents, } from "workers/Evaluation/types"; import isEmpty from "lodash/isEmpty"; -import type { UnEvalTree } from "@appsmith/entities/DataTree/types"; +import type { UnEvalTree } from "entities/DataTree/dataTreeTypes"; import { sortJSExecutionDataByCollectionId } from "workers/Evaluation/JSObject/utils"; import type { LintTreeSagaRequestData } from "plugins/Linting/types"; export type UpdateDataTreeMessageData = { diff --git a/app/client/src/sagas/EvaluationsSaga.ts b/app/client/src/sagas/EvaluationsSaga.ts index 4eecd793e3..6078ed9cab 100644 --- a/app/client/src/sagas/EvaluationsSaga.ts +++ b/app/client/src/sagas/EvaluationsSaga.ts @@ -82,12 +82,8 @@ import { getAllActionValidationConfig, getAllJSActionsData, } from "@appsmith/selectors/entitiesSelector"; -import type { - DataTree, - UnEvalTree, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; - +import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types"; +import type { DataTree, UnEvalTree } from "entities/DataTree/dataTreeTypes"; import { initiateLinting, lintWorker } from "./LintingSagas"; import type { EvalTreeRequestData, diff --git a/app/client/src/sagas/FormEvaluationSaga.ts b/app/client/src/sagas/FormEvaluationSaga.ts index 56499c6240..7151fb41f5 100644 --- a/app/client/src/sagas/FormEvaluationSaga.ts +++ b/app/client/src/sagas/FormEvaluationSaga.ts @@ -22,7 +22,7 @@ import { getDataTree } from "selectors/dataTreeSelectors"; import { getDynamicBindings, isDynamicValue } from "utils/DynamicBindingUtils"; import get from "lodash/get"; import { klona } from "klona/lite"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { extractFetchDynamicValueFormConfigs, extractQueueOfValuesToBeFetched, diff --git a/app/client/src/sagas/OnboardingSagas.ts b/app/client/src/sagas/OnboardingSagas.ts index 2d566a9149..011f28a1c3 100644 --- a/app/client/src/sagas/OnboardingSagas.ts +++ b/app/client/src/sagas/OnboardingSagas.ts @@ -77,7 +77,7 @@ import { selectWidgetInitAction } from "actions/widgetSelectionActions"; import { hideIndicator } from "pages/Editor/GuidedTour/utils"; import { updateWidgetName } from "actions/propertyPaneActions"; import AnalyticsUtil from "utils/AnalyticsUtil"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; import type { User } from "constants/userConstants"; import { builderURL, queryEditorIdURL } from "RouteBuilder"; diff --git a/app/client/src/sagas/PostEvaluationSagas.ts b/app/client/src/sagas/PostEvaluationSagas.ts index 656e46d790..d8f859e7e8 100644 --- a/app/client/src/sagas/PostEvaluationSagas.ts +++ b/app/client/src/sagas/PostEvaluationSagas.ts @@ -4,12 +4,12 @@ import { PLATFORM_ERROR, Severity, } from "entities/AppsmithConsole"; +import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree, UnEvalTree, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils"; import { DataTreeDiffEvent, diff --git a/app/client/src/sagas/PostLintingSagas.ts b/app/client/src/sagas/PostLintingSagas.ts index ec62c6bda5..6dc006c25d 100644 --- a/app/client/src/sagas/PostLintingSagas.ts +++ b/app/client/src/sagas/PostLintingSagas.ts @@ -1,6 +1,6 @@ import { ENTITY_TYPE, Severity } from "entities/AppsmithConsole"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { isEmpty } from "lodash"; import AppsmithConsole from "utils/AppsmithConsole"; import { diff --git a/app/client/src/sagas/WidgetAdditionSagas.ts b/app/client/src/sagas/WidgetAdditionSagas.ts index e24c454749..e5bf2fa5f3 100644 --- a/app/client/src/sagas/WidgetAdditionSagas.ts +++ b/app/client/src/sagas/WidgetAdditionSagas.ts @@ -37,7 +37,7 @@ import { } from "WidgetProvider/constants"; import { getPropertiesToUpdate } from "./WidgetOperationSagas"; import { klona as clone } from "klona/full"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions"; import { toast } from "design-system"; import { ResponsiveBehavior } from "layoutSystems/common/utils/constants"; diff --git a/app/client/src/sagas/WidgetLoadingSaga.ts b/app/client/src/sagas/WidgetLoadingSaga.ts index f619a4988f..10548cf102 100644 --- a/app/client/src/sagas/WidgetLoadingSaga.ts +++ b/app/client/src/sagas/WidgetLoadingSaga.ts @@ -4,7 +4,7 @@ import { getEvaluationInverseDependencyMap, getDataTree, } from "selectors/dataTreeSelectors"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getActions } from "@appsmith/selectors/entitiesSelector"; import type { ActionData, diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index c94be7f11b..e99b8553ab 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -137,11 +137,8 @@ import { purgeOrphanedDynamicPaths, } from "./WidgetOperationUtils"; import { widgetSelectionSagas } from "./WidgetSelectionSagas"; -import type { - DataTree, - ConfigTree, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; +import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types"; +import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import { getCanvasSizeAfterWidgetMove } from "./CanvasSagas/DraggingCanvasSagas"; import widgetAdditionSagas from "./WidgetAdditionSagas"; import widgetDeletionSagas from "./WidgetDeletionSagas"; diff --git a/app/client/src/sagas/WidgetOperationUtils.ts b/app/client/src/sagas/WidgetOperationUtils.ts index 2618465f7a..fdfaa7a47f 100644 --- a/app/client/src/sagas/WidgetOperationUtils.ts +++ b/app/client/src/sagas/WidgetOperationUtils.ts @@ -16,7 +16,7 @@ import { WIDGET_PADDING, } from "constants/WidgetConstants"; import { all, call } from "redux-saga/effects"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { select } from "redux-saga/effects"; import { getCopiedWidgets } from "utils/storage"; import type { WidgetProps } from "widgets/BaseWidget"; diff --git a/app/client/src/sagas/autoHeightSagas/containers.ts b/app/client/src/sagas/autoHeightSagas/containers.ts index dbcd1ed882..62cae50c6b 100644 --- a/app/client/src/sagas/autoHeightSagas/containers.ts +++ b/app/client/src/sagas/autoHeightSagas/containers.ts @@ -14,7 +14,8 @@ import { } from "widgets/WidgetUtils"; import { getChildOfContainerLikeWidget } from "./helpers"; import { getDataTree } from "selectors/dataTreeSelectors"; -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getLayoutTree } from "./layoutTree"; import { getWidgetsForBreakpoint } from "selectors/editorSelectors"; diff --git a/app/client/src/sagas/autoHeightSagas/helpers.ts b/app/client/src/sagas/autoHeightSagas/helpers.ts index f6a541081b..e9b82571e6 100644 --- a/app/client/src/sagas/autoHeightSagas/helpers.ts +++ b/app/client/src/sagas/autoHeightSagas/helpers.ts @@ -15,7 +15,8 @@ import { previewModeSelector } from "selectors/editorSelectors"; import { getAppMode } from "@appsmith/selectors/entitiesSelector"; import { isAutoHeightEnabledForWidget } from "widgets/WidgetUtils"; import { getCanvasHeightOffset } from "utils/WidgetSizeUtils"; -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getDataTree } from "selectors/dataTreeSelectors"; export function* shouldWidgetsCollapse() { diff --git a/app/client/src/selectors/actionSelectors.tsx b/app/client/src/selectors/actionSelectors.tsx index de38e7e91f..47f3d97b49 100644 --- a/app/client/src/selectors/actionSelectors.tsx +++ b/app/client/src/selectors/actionSelectors.tsx @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { createSelector } from "reselect"; import WidgetFactory from "WidgetProvider/factory"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; diff --git a/app/client/src/selectors/dataTreeSelectors.ts b/app/client/src/selectors/dataTreeSelectors.ts index 48a4cecc40..ba8cf9b1c0 100644 --- a/app/client/src/selectors/dataTreeSelectors.ts +++ b/app/client/src/selectors/dataTreeSelectors.ts @@ -7,7 +7,8 @@ import { getCurrentJSCollections, getInputsForModule, } from "@appsmith/selectors/entitiesSelector"; -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { DataTreeFactory } from "entities/DataTree/dataTreeFactory"; import { getMetaWidgets, diff --git a/app/client/src/selectors/debuggerSelectors.test.ts b/app/client/src/selectors/debuggerSelectors.test.ts index 965664cbd0..366a2bff90 100644 --- a/app/client/src/selectors/debuggerSelectors.test.ts +++ b/app/client/src/selectors/debuggerSelectors.test.ts @@ -1,6 +1,6 @@ import { Severity, ENTITY_TYPE, LOG_CATEGORY } from "entities/AppsmithConsole"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils"; import { getFilteredErrors } from "./debuggerSelectors"; diff --git a/app/client/src/selectors/debuggerSelectors.tsx b/app/client/src/selectors/debuggerSelectors.tsx index a42c077587..e647d88add 100644 --- a/app/client/src/selectors/debuggerSelectors.tsx +++ b/app/client/src/selectors/debuggerSelectors.tsx @@ -1,5 +1,6 @@ import type { Log } from "entities/AppsmithConsole"; -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { isEmpty } from "lodash"; import type { AppState } from "@appsmith/reducers"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index 074ad833f7..2f8bd2080e 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -25,11 +25,10 @@ import { } from "constants/WidgetConstants"; import { APP_MODE } from "entities/App"; import type { - DataTree, - ConfigTree, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import { find, sortBy } from "lodash"; import { getDataTree, diff --git a/app/client/src/selectors/formSelectors.ts b/app/client/src/selectors/formSelectors.ts index 8371d89797..ada72b22ae 100644 --- a/app/client/src/selectors/formSelectors.ts +++ b/app/client/src/selectors/formSelectors.ts @@ -9,7 +9,7 @@ import type { import { createSelector } from "reselect"; import { isEmpty, replace } from "lodash"; import { getDataTree } from "./dataTreeSelectors"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { Action } from "entities/Action"; import type { EvaluationError } from "utils/DynamicBindingUtils"; import { getActionIdFromURL } from "@appsmith/pages/Editor/Explorer/helpers"; diff --git a/app/client/src/selectors/navigationSelectors.ts b/app/client/src/selectors/navigationSelectors.ts index d59bf00024..ccd6c36bbf 100644 --- a/app/client/src/selectors/navigationSelectors.ts +++ b/app/client/src/selectors/navigationSelectors.ts @@ -1,4 +1,5 @@ -import type { DataTree, ENTITY_TYPE } from "@appsmith/entities/DataTree/types"; +import type { ENTITY_TYPE } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { createSelector } from "reselect"; import { diff --git a/app/client/src/selectors/propertyPaneSelectors.tsx b/app/client/src/selectors/propertyPaneSelectors.tsx index 78f6469bce..0f0b4777a1 100644 --- a/app/client/src/selectors/propertyPaneSelectors.tsx +++ b/app/client/src/selectors/propertyPaneSelectors.tsx @@ -1,11 +1,8 @@ import type { AppState } from "@appsmith/reducers"; import { find, get, set } from "lodash"; import { createSelector } from "reselect"; -import type { - DataTree, - DataTreeEntity, - WidgetEntity, -} from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree, DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; import type { PropertyPaneReduxState, diff --git a/app/client/src/utils/DynamicBindingUtils.ts b/app/client/src/utils/DynamicBindingUtils.ts index 9aa02e9f73..71845fd11e 100644 --- a/app/client/src/utils/DynamicBindingUtils.ts +++ b/app/client/src/utils/DynamicBindingUtils.ts @@ -10,10 +10,8 @@ import { isTrueObject, isWidget, } from "@appsmith/workers/Evaluation/evaluationUtils"; -import type { - DataTreeEntity, - DataTreeEntityConfig, -} from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntityConfig } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { getType, Types } from "./TypeHelpers"; import { ViewTypes } from "components/formControls/utils"; diff --git a/app/client/src/utils/FilterInternalProperties/Action.ts b/app/client/src/utils/FilterInternalProperties/Action.ts index 6d3c72af72..3eadb852eb 100644 --- a/app/client/src/utils/FilterInternalProperties/Action.ts +++ b/app/client/src/utils/FilterInternalProperties/Action.ts @@ -1,5 +1,6 @@ import { entityDefinitions } from "@appsmith/utils/autocomplete/EntityDefinitions"; -import type { DataTree, ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; export const getActionChildrenPeekData = ( actionName: string, diff --git a/app/client/src/utils/FilterInternalProperties/Appsmith.ts b/app/client/src/utils/FilterInternalProperties/Appsmith.ts index edda5fbd2c..86e84cd09b 100644 --- a/app/client/src/utils/FilterInternalProperties/Appsmith.ts +++ b/app/client/src/utils/FilterInternalProperties/Appsmith.ts @@ -1,8 +1,6 @@ import { entityDefinitions } from "@appsmith/utils/autocomplete/EntityDefinitions"; -import type { - AppsmithEntity, - DataTree, -} from "@appsmith/entities/DataTree/types"; +import type { AppsmithEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { createObjectPeekData } from "./Common"; export const getAppsmithPeekData = (dataTree: DataTree) => { diff --git a/app/client/src/utils/FilterInternalProperties/JsAction.ts b/app/client/src/utils/FilterInternalProperties/JsAction.ts index 04b8e38de2..ead880bed5 100644 --- a/app/client/src/utils/FilterInternalProperties/JsAction.ts +++ b/app/client/src/utils/FilterInternalProperties/JsAction.ts @@ -1,7 +1,5 @@ -import type { - DataTree, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { JSCollectionData } from "reducers/entityReducers/jsActionsReducer"; export const getJsActionPeekData = ( diff --git a/app/client/src/utils/FilterInternalProperties/Widget.ts b/app/client/src/utils/FilterInternalProperties/Widget.ts index bbcb062c58..322f3e55aa 100644 --- a/app/client/src/utils/FilterInternalProperties/Widget.ts +++ b/app/client/src/utils/FilterInternalProperties/Widget.ts @@ -1,9 +1,8 @@ import type { - ConfigTree, - DataTree, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import type { EntityDefinitionsOptions } from "@appsmith/utils/autocomplete/EntityDefinitions"; import { isFunction } from "lodash"; import type { Def } from "tern"; diff --git a/app/client/src/utils/FilterInternalProperties/index.ts b/app/client/src/utils/FilterInternalProperties/index.ts index fdade132ea..9d1ae25bb0 100644 --- a/app/client/src/utils/FilterInternalProperties/index.ts +++ b/app/client/src/utils/FilterInternalProperties/index.ts @@ -3,7 +3,7 @@ import type { ConfigTree, DataTree, DataTreeEntity, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { JSCollectionDataState } from "reducers/entityReducers/jsActionsReducer"; import { getWidgetChildrenPeekData } from "./Widget"; import { getJsActionPeekData } from "./JsAction"; diff --git a/app/client/src/utils/NavigationSelector/JsChildren.ts b/app/client/src/utils/NavigationSelector/JsChildren.ts index c5c65c278f..6e228618d3 100644 --- a/app/client/src/utils/NavigationSelector/JsChildren.ts +++ b/app/client/src/utils/NavigationSelector/JsChildren.ts @@ -1,7 +1,5 @@ -import type { - DataTree, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { keyBy } from "lodash"; import type { JSCollectionData } from "reducers/entityReducers/jsActionsReducer"; diff --git a/app/client/src/utils/NavigationSelector/WidgetChildren.ts b/app/client/src/utils/NavigationSelector/WidgetChildren.ts index 5451f16cb1..e18267a6a5 100644 --- a/app/client/src/utils/NavigationSelector/WidgetChildren.ts +++ b/app/client/src/utils/NavigationSelector/WidgetChildren.ts @@ -1,4 +1,5 @@ -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { builderURL } from "RouteBuilder"; import type { EntityNavigationData } from "selectors/navigationSelectors"; diff --git a/app/client/src/utils/SuccessfulBindingsMap.ts b/app/client/src/utils/SuccessfulBindingsMap.ts index 2afc124e78..9a436a4148 100644 --- a/app/client/src/utils/SuccessfulBindingsMap.ts +++ b/app/client/src/utils/SuccessfulBindingsMap.ts @@ -1,4 +1,4 @@ -import type { UnEvalTreeEntity } from "@appsmith/entities/DataTree/types"; +import type { UnEvalTreeEntity } from "entities/DataTree/dataTreeTypes"; export type SuccessfulBindings = { [entityName: string]: UnEvalTreeEntity; diff --git a/app/client/src/utils/WidgetLoadingStateUtils.ts b/app/client/src/utils/WidgetLoadingStateUtils.ts index 61c92b446f..8cc8e9dc90 100644 --- a/app/client/src/utils/WidgetLoadingStateUtils.ts +++ b/app/client/src/utils/WidgetLoadingStateUtils.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { get, set } from "lodash"; import { isJSObject, diff --git a/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.ts b/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.ts index 0ed43c9cac..eb9fb4ea37 100644 --- a/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.ts +++ b/app/client/src/utils/autocomplete/dataTreeTypeDefCreator.ts @@ -1,10 +1,12 @@ +import type { + WidgetEntityConfig, + JSActionEntityConfig, +} from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree, DataTreeEntity, - WidgetEntityConfig, - JSActionEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { uniqueId, isFunction, isObject } from "lodash"; import { entityDefinitions } from "@appsmith/utils/autocomplete/EntityDefinitions"; diff --git a/app/client/src/utils/configTree.ts b/app/client/src/utils/configTree.ts index e6b64b64d9..3a6c5f274d 100644 --- a/app/client/src/utils/configTree.ts +++ b/app/client/src/utils/configTree.ts @@ -1,4 +1,4 @@ -import type { ConfigTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree } from "entities/DataTree/dataTreeTypes"; export default class ConfigTreeActions { static tree: ConfigTree = {}; diff --git a/app/client/src/utils/widgetRenderUtils.test.ts b/app/client/src/utils/widgetRenderUtils.test.ts index ee10a4862d..544d1bc337 100644 --- a/app/client/src/utils/widgetRenderUtils.test.ts +++ b/app/client/src/utils/widgetRenderUtils.test.ts @@ -1,8 +1,8 @@ import type { - DataTree, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer"; import { buildChildWidgetTree, createCanvasWidget } from "./widgetRenderUtils"; diff --git a/app/client/src/utils/widgetRenderUtils.tsx b/app/client/src/utils/widgetRenderUtils.tsx index b01eec1cc6..419c9c2e8d 100644 --- a/app/client/src/utils/widgetRenderUtils.tsx +++ b/app/client/src/utils/widgetRenderUtils.tsx @@ -3,11 +3,10 @@ import type { FlattenedWidgetProps, } from "reducers/entityReducers/canvasWidgetsReducer"; import type { - ConfigTree, - DataTree, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { pick } from "lodash"; import { diff --git a/app/client/src/workers/Evaluation/JSObject/__test__/mutation.test.ts b/app/client/src/workers/Evaluation/JSObject/__test__/mutation.test.ts index dfffa85de9..4af11f511e 100644 --- a/app/client/src/workers/Evaluation/JSObject/__test__/mutation.test.ts +++ b/app/client/src/workers/Evaluation/JSObject/__test__/mutation.test.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { createEvaluationContext } from "workers/Evaluation/evaluate"; import JSObjectCollection from "../Collection"; diff --git a/app/client/src/workers/Evaluation/JSObject/index.ts b/app/client/src/workers/Evaluation/JSObject/index.ts index 304b28009f..a1af115b2a 100644 --- a/app/client/src/workers/Evaluation/JSObject/index.ts +++ b/app/client/src/workers/Evaluation/JSObject/index.ts @@ -1,9 +1,6 @@ import { get, isEmpty, merge, set } from "lodash"; -import type { - ConfigTree, - DataTree, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { EvalErrorTypes, getEvalValuePath } from "utils/DynamicBindingUtils"; import type { JSUpdate, ParsedJSSubAction } from "utils/JSPaneUtils"; import { parseJSObject, isJSFunctionProperty } from "@shared/ast"; diff --git a/app/client/src/workers/Evaluation/JSObject/test.ts b/app/client/src/workers/Evaluation/JSObject/test.ts index ab20d4c79a..90a400ecf9 100644 --- a/app/client/src/workers/Evaluation/JSObject/test.ts +++ b/app/client/src/workers/Evaluation/JSObject/test.ts @@ -1,4 +1,4 @@ -import type { ConfigTree, UnEvalTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, UnEvalTree } from "entities/DataTree/dataTreeTypes"; import { getUpdatedLocalUnEvalTreeAfterJSUpdates } from "."; describe("updateJSCollectionInUnEvalTree", function () { diff --git a/app/client/src/workers/Evaluation/JSObject/utils.ts b/app/client/src/workers/Evaluation/JSObject/utils.ts index 5310a6e254..ee1aa042be 100644 --- a/app/client/src/workers/Evaluation/JSObject/utils.ts +++ b/app/client/src/workers/Evaluation/JSObject/utils.ts @@ -1,10 +1,12 @@ +import type { + JSActionEntityConfig, + JSActionEntity, +} from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree, DataTreeEntity, - JSActionEntityConfig, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory"; import type { ParsedBody, ParsedJSSubAction } from "utils/JSPaneUtils"; import { unset, set, get, find } from "lodash"; diff --git a/app/client/src/workers/Evaluation/__tests__/Actions.test.ts b/app/client/src/workers/Evaluation/__tests__/Actions.test.ts index c9549bb6e1..f3a1d100d9 100644 --- a/app/client/src/workers/Evaluation/__tests__/Actions.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/Actions.test.ts @@ -1,4 +1,5 @@ -import type { DataTree, ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { PluginType } from "entities/Action"; import type { EvalContext } from "workers/Evaluation/evaluate"; diff --git a/app/client/src/workers/Evaluation/__tests__/errorModifier.test.ts b/app/client/src/workers/Evaluation/__tests__/errorModifier.test.ts index 3855e42b96..130167e1d7 100644 --- a/app/client/src/workers/Evaluation/__tests__/errorModifier.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/errorModifier.test.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { errorModifier } from "../errorModifier"; import DependencyMap from "entities/DependencyMap"; import { APP_MODE } from "entities/App"; diff --git a/app/client/src/workers/Evaluation/__tests__/evaluate.test.ts b/app/client/src/workers/Evaluation/__tests__/evaluate.test.ts index 2ba23a7b47..1d561ba6e5 100644 --- a/app/client/src/workers/Evaluation/__tests__/evaluate.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/evaluate.test.ts @@ -2,7 +2,8 @@ import evaluate, { evaluateAsync, convertAllDataTypesToString, } from "workers/Evaluation/evaluate"; -import type { DataTree, WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { WidgetEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { RenderModes } from "constants/WidgetConstants"; import setupEvalEnv from "../handlers/setupEvalEnv"; diff --git a/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts b/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts index 4c3880bbb5..e277b90c5a 100644 --- a/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/evaluation.test.ts @@ -1,11 +1,10 @@ import type { - ConfigTree, WidgetEntity, - UnEvalTree, WidgetEntityConfig, ActionEntityConfig, ActionEntity, } from "@appsmith/entities/DataTree/types"; +import type { UnEvalTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE, EvaluationSubstitutionType, diff --git a/app/client/src/workers/Evaluation/__tests__/setters.test.ts b/app/client/src/workers/Evaluation/__tests__/setters.test.ts index 3df4337fcd..c1cf7f8f8f 100644 --- a/app/client/src/workers/Evaluation/__tests__/setters.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/setters.test.ts @@ -2,7 +2,7 @@ import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget"; import setters from "../setters"; import TableWidget from "widgets/TableWidgetV2/widget"; import { RenderModes } from "constants/WidgetConstants"; -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { createEvaluationContext } from "../evaluate"; import { registerWidgets } from "WidgetProvider/factory/registrationHelper"; diff --git a/app/client/src/workers/Evaluation/__tests__/timeout.test.ts b/app/client/src/workers/Evaluation/__tests__/timeout.test.ts index c78811c365..966671e114 100644 --- a/app/client/src/workers/Evaluation/__tests__/timeout.test.ts +++ b/app/client/src/workers/Evaluation/__tests__/timeout.test.ts @@ -1,5 +1,6 @@ import { PluginType } from "entities/Action"; -import type { DataTree, ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { createEvaluationContext } from "../evaluate"; import { addPlatformFunctionsToEvalContext } from "@appsmith/workers/Evaluation/Actions"; diff --git a/app/client/src/workers/Evaluation/dataStore/index.ts b/app/client/src/workers/Evaluation/dataStore/index.ts index d83fc696d4..b42d577d2a 100644 --- a/app/client/src/workers/Evaluation/dataStore/index.ts +++ b/app/client/src/workers/Evaluation/dataStore/index.ts @@ -1,6 +1,6 @@ import { convertPathToString } from "@appsmith/workers/Evaluation/evaluationUtils"; import type { Diff } from "deep-diff"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { get, set, unset } from "lodash"; export type TDataStore = Record>; diff --git a/app/client/src/workers/Evaluation/dataStore/utils.ts b/app/client/src/workers/Evaluation/dataStore/utils.ts index 5d23d3d8f0..eddce7c81b 100644 --- a/app/client/src/workers/Evaluation/dataStore/utils.ts +++ b/app/client/src/workers/Evaluation/dataStore/utils.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import type { TDataStore } from "."; import { isAction, diff --git a/app/client/src/workers/Evaluation/errorModifier.ts b/app/client/src/workers/Evaluation/errorModifier.ts index f8fa16ed33..701c091582 100644 --- a/app/client/src/workers/Evaluation/errorModifier.ts +++ b/app/client/src/workers/Evaluation/errorModifier.ts @@ -1,4 +1,4 @@ -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { getAllAsyncFunctions } from "@appsmith/workers/Evaluation/Actions"; import type { EvaluationError } from "utils/DynamicBindingUtils"; import { PropertyEvaluationErrorCategory } from "utils/DynamicBindingUtils"; diff --git a/app/client/src/workers/Evaluation/evalTreeWithChanges.ts b/app/client/src/workers/Evaluation/evalTreeWithChanges.ts index 28a9b2523d..413840c1e0 100644 --- a/app/client/src/workers/Evaluation/evalTreeWithChanges.ts +++ b/app/client/src/workers/Evaluation/evalTreeWithChanges.ts @@ -2,7 +2,7 @@ import type { ConfigTree, DataTree, UnEvalTree, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { dataTreeEvaluator } from "./handlers/evalTree"; import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils"; import type { EvalMetaUpdates } from "@appsmith/workers/common/DataTreeEvaluator/types"; diff --git a/app/client/src/workers/Evaluation/evaluate.ts b/app/client/src/workers/Evaluation/evaluate.ts index 815da264bc..f7d115c3ce 100644 --- a/app/client/src/workers/Evaluation/evaluate.ts +++ b/app/client/src/workers/Evaluation/evaluate.ts @@ -3,7 +3,7 @@ import type { ConfigTree, DataTree, DataTreeEntity, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { EvaluationError } from "utils/DynamicBindingUtils"; import { PropertyEvaluationErrorType } from "utils/DynamicBindingUtils"; import unescapeJS from "unescape-js"; diff --git a/app/client/src/workers/Evaluation/fns/__tests__/LocalStorage.test.ts b/app/client/src/workers/Evaluation/fns/__tests__/LocalStorage.test.ts index f7d4ecd421..296e460a85 100644 --- a/app/client/src/workers/Evaluation/fns/__tests__/LocalStorage.test.ts +++ b/app/client/src/workers/Evaluation/fns/__tests__/LocalStorage.test.ts @@ -1,6 +1,7 @@ import { addPlatformFunctionsToEvalContext } from "@appsmith/workers/Evaluation/Actions"; import { PluginType } from "entities/Action"; -import type { DataTree, ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { createEvaluationContext } from "workers/Evaluation/evaluate"; import initLocalStorage from "../overrides/localStorage"; import { ENTITY_TYPE } from "pages/common/SearchSnippets"; diff --git a/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts b/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts index c4d17b33e6..a28445581b 100644 --- a/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts +++ b/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts @@ -2,7 +2,8 @@ jest.useFakeTimers(); import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { PluginType } from "entities/Action"; -import type { DataTree, ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import { overrideWebAPIs } from "../overrides"; import ExecutionMetaData from "../utils/ExecutionMetaData"; diff --git a/app/client/src/workers/Evaluation/fns/index.ts b/app/client/src/workers/Evaluation/fns/index.ts index 73e737edc9..b8d9e37fc0 100644 --- a/app/client/src/workers/Evaluation/fns/index.ts +++ b/app/client/src/workers/Evaluation/fns/index.ts @@ -46,10 +46,8 @@ import { isAction, isAppsmithEntity, } from "@appsmith/workers/Evaluation/evaluationUtils"; -import type { - DataTreeEntity, - ActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { ActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import type { TGetGeoLocationActionType, TGetGeoLocationDescription, diff --git a/app/client/src/workers/Evaluation/fns/mock.ts b/app/client/src/workers/Evaluation/fns/mock.ts index 2899f040d0..392b70d9da 100644 --- a/app/client/src/workers/Evaluation/fns/mock.ts +++ b/app/client/src/workers/Evaluation/fns/mock.ts @@ -1,4 +1,4 @@ -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE } from "pages/common/SearchSnippets"; import { createEvaluationContext } from "workers/Evaluation/evaluate"; diff --git a/app/client/src/workers/Evaluation/getEntityForContext.ts b/app/client/src/workers/Evaluation/getEntityForContext.ts index 06dd01c605..35b5bc46db 100644 --- a/app/client/src/workers/Evaluation/getEntityForContext.ts +++ b/app/client/src/workers/Evaluation/getEntityForContext.ts @@ -1,7 +1,5 @@ -import type { - DataTreeEntity, - JSActionEntity, -} from "@appsmith/entities/DataTree/types"; +import type { JSActionEntity } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { ENTITY_TYPE_VALUE } from "entities/DataTree/dataTreeFactory"; import JSObjectCollection from "./JSObject/Collection"; import JSFactory from "./JSObject/JSVariableFactory"; diff --git a/app/client/src/workers/Evaluation/handlers/evalTree.ts b/app/client/src/workers/Evaluation/handlers/evalTree.ts index 7be32dce8c..4d8a58853d 100644 --- a/app/client/src/workers/Evaluation/handlers/evalTree.ts +++ b/app/client/src/workers/Evaluation/handlers/evalTree.ts @@ -1,4 +1,4 @@ -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import type ReplayEntity from "entities/Replay"; import ReplayCanvas from "entities/Replay/ReplayEntity/ReplayCanvas"; import { isEmpty } from "lodash"; diff --git a/app/client/src/workers/Evaluation/helpers.ts b/app/client/src/workers/Evaluation/helpers.ts index d56eec7ce6..be22577896 100644 --- a/app/client/src/workers/Evaluation/helpers.ts +++ b/app/client/src/workers/Evaluation/helpers.ts @@ -1,7 +1,7 @@ import { serialiseToBigInt } from "@appsmith/workers/Evaluation/evaluationUtils"; import type { Diff } from "deep-diff"; import { diff } from "deep-diff"; -import type { DataTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import equal from "fast-deep-equal"; import { get, isNumber, isObject } from "lodash"; import { EvalErrorTypes } from "utils/DynamicBindingUtils"; diff --git a/app/client/src/workers/Evaluation/setters.ts b/app/client/src/workers/Evaluation/setters.ts index 5c1f81afc2..b9b089f107 100644 --- a/app/client/src/workers/Evaluation/setters.ts +++ b/app/client/src/workers/Evaluation/setters.ts @@ -8,12 +8,12 @@ import { evalTreeWithChanges } from "./evalTreeWithChanges"; import { dataTreeEvaluator } from "./handlers/evalTree"; import { get, set } from "lodash"; import { validate } from "./validations"; +import type { DataTreeEntityConfig } from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTree, DataTreeEntity, - DataTreeEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { getFnWithGuards, isAsyncGuard } from "./fns/utils/fnGuard"; import { shouldAddSetter } from "./evaluate"; diff --git a/app/client/src/workers/Evaluation/types.ts b/app/client/src/workers/Evaluation/types.ts index c92ce164ee..ee5f1f7f82 100644 --- a/app/client/src/workers/Evaluation/types.ts +++ b/app/client/src/workers/Evaluation/types.ts @@ -1,7 +1,7 @@ import type { ConfigTree, unEvalAndConfigTree, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import type { ActionValidationConfigMap } from "constants/PropertyControlConstants"; import type { AppTheme } from "entities/AppTheming"; diff --git a/app/client/src/workers/common/DataTreeEvaluator/index.ts b/app/client/src/workers/common/DataTreeEvaluator/index.ts index 4ec054d5b9..c2a0500985 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/index.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/index.ts @@ -19,18 +19,21 @@ import { } from "utils/DynamicBindingUtils"; import type { WidgetTypeConfigMap } from "WidgetProvider/factory"; import type { - DataTree, - DataTreeEntity, WidgetEntity, - ConfigTree, WidgetEntityConfig, DataTreeEntityConfig, - UnEvalTree, ActionEntity, JSActionEntity, JSActionEntityConfig, PrivateWidgets, + ActionEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { + DataTree, + DataTreeEntity, + ConfigTree, + UnEvalTree, +} from "entities/DataTree/dataTreeTypes"; import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory"; import { ENTITY_TYPE_VALUE } from "@appsmith/entities/DataTree/types"; import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils"; @@ -50,7 +53,6 @@ import { trimDependantChangePaths, overrideWidgetProperties, getAllPaths, - isValidEntity, isNewEntity, getStaleMetaStateIds, convertJSFunctionsToString, @@ -1000,7 +1002,8 @@ export default class DataTreeEvaluator { if (requiresEval) { const evaluationSubstitutionType = - entityConfig?.reactivePaths?.[propertyPath] || + (!isEmpty(entityConfig.reactivePaths) && + entityConfig.reactivePaths[propertyPath]) || EvaluationSubstitutionType.TEMPLATE; const contextData: EvaluateContext = {}; @@ -1099,17 +1102,19 @@ export default class DataTreeEvaluator { break; } case ENTITY_TYPE_VALUE.ACTION: { + const actionEntity = entity as ActionEntity; + const configProperty = propertyPath.replace( "config", "actionConfiguration", ); const validationConfig = - this.allActionValidationConfig?.[entity.actionId]?.[ + this.allActionValidationConfig?.[actionEntity.actionId]?.[ configProperty ]; this.validateActionProperty( fullPropertyPath, - entity as ActionEntity, + actionEntity, contextTree, evalPropertyValue, unEvalPropertyValue, @@ -1278,7 +1283,8 @@ export default class DataTreeEvaluator { if (entity && isWidget(entity)) { entityType = entity.type; } else if (entity && isAction(entity)) { - entityType = entityConfig.pluginType; + const actionEntityConfig = entityConfig as ActionEntityConfig; + entityType = actionEntityConfig.pluginType; } else if (entity && isJSAction(entity)) { entityType = entity.ENTITY_TYPE; } @@ -1618,23 +1624,6 @@ export default class DataTreeEvaluator { }); } - /** - * Update the entity config set as prototype according to latest unEvalTree changes else code would consume stale configs. - * - * Example scenario: On addition of a JS binding to widget, it's dynamicBindingPathList changes and needs to be updated. - */ - updateConfigForModifiedEntity(unEvalTree: DataTree, entityName: string) { - const unEvalEntity = unEvalTree[entityName]; - // skip entity if entity is not present in the evalTree or is not a valid entity - if (!this.evalTree[entityName] || !isValidEntity(this.evalTree[entityName])) - return; - const entityConfig = Object.getPrototypeOf(unEvalEntity); - const newEntityObject = Object.create(entityConfig); - this.evalTree[entityName] = Object.assign(newEntityObject, { - ...this.evalTree[entityName], - }); - } - updateEvalTreeWithChanges({ differences, }: { @@ -1688,20 +1677,22 @@ export default class DataTreeEvaluator { ); } const parentPropertyPath = convertPathToString(path); - Object.keys(entityConfig.reactivePaths).forEach((relativePath) => { - const childPropertyPath = `${entityName}.${relativePath}`; - // Check if relative path has dynamic binding - if ( - entityDynamicBindingPaths && - entityDynamicBindingPaths.length && - entityDynamicBindingPaths.includes(relativePath) - ) { - changePaths.add(childPropertyPath); - } - if (isChildPropertyPath(parentPropertyPath, childPropertyPath)) { - changePaths.add(childPropertyPath); - } - }); + if (!isEmpty(entityConfig.reactivePaths)) { + Object.keys(entityConfig.reactivePaths).forEach((relativePath) => { + const childPropertyPath = `${entityName}.${relativePath}`; + // Check if relative path has dynamic binding + if ( + entityDynamicBindingPaths && + entityDynamicBindingPaths.length && + entityDynamicBindingPaths.includes(relativePath) + ) { + changePaths.add(childPropertyPath); + } + if (isChildPropertyPath(parentPropertyPath, childPropertyPath)) { + changePaths.add(childPropertyPath); + } + }); + } } } diff --git a/app/client/src/workers/common/DataTreeEvaluator/mockData/ArrayAccessorTree.ts b/app/client/src/workers/common/DataTreeEvaluator/mockData/ArrayAccessorTree.ts index 7ee3e31557..acde8b2eff 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/mockData/ArrayAccessorTree.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/mockData/ArrayAccessorTree.ts @@ -1,11 +1,11 @@ import { PluginType, PaginationType } from "entities/Action"; import type { - DataTree, WidgetEntity, WidgetEntityConfig, ActionEntityConfig, ActionEntity, } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { EvaluationSubstitutionType, ENTITY_TYPE_VALUE, diff --git a/app/client/src/workers/common/DataTreeEvaluator/mockData/NestedArrayAccessorTree.ts b/app/client/src/workers/common/DataTreeEvaluator/mockData/NestedArrayAccessorTree.ts index 577b3e44c1..1492beca9d 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/mockData/NestedArrayAccessorTree.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/mockData/NestedArrayAccessorTree.ts @@ -1,11 +1,11 @@ import { PluginType, PaginationType } from "entities/Action"; import type { - DataTree, WidgetEntity, WidgetEntityConfig, ActionEntityConfig, ActionEntity, } from "@appsmith/entities/DataTree/types"; +import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { EvaluationSubstitutionType, ENTITY_TYPE_VALUE, diff --git a/app/client/src/workers/common/DataTreeEvaluator/test.ts b/app/client/src/workers/common/DataTreeEvaluator/test.ts index eb72885f1b..dbd69786bd 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/test.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/test.ts @@ -1,7 +1,7 @@ import DataTreeEvaluator from "."; import { unEvalTree } from "./mockData/mockUnEvalTree"; import { configTree } from "./mockData/mockConfigTree"; -import type { DataTree, ConfigTree } from "@appsmith/entities/DataTree/types"; +import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import type { DataTreeDiff } from "@appsmith/workers/Evaluation/evaluationUtils"; import { arrayAccessorCyclicDependency, diff --git a/app/client/src/workers/common/DataTreeEvaluator/utils.ts b/app/client/src/workers/common/DataTreeEvaluator/utils.ts index 3375928d34..aca443c0c7 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/utils.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/utils.ts @@ -1,14 +1,17 @@ import { getEntityNameAndPropertyPath, isJSAction, + isValidEntity, } from "@appsmith/workers/Evaluation/evaluationUtils"; import { EXECUTION_PARAM_REFERENCE_REGEX, THIS_DOT_PARAMS_KEY, } from "constants/AppsmithActionConstants/ActionConstants"; -import type { ConfigTree, DataTree } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import type DependencyMap from "entities/DependencyMap"; import type { TJSPropertiesState } from "workers/Evaluation/JSObject/jsPropertiesState"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; +import type { DataTreeEntityConfig } from "@appsmith/entities/DataTree/types"; export function getFixedTimeDifference(endTime: number, startTime: number) { return (endTime - startTime).toFixed(2) + " ms"; @@ -54,3 +57,15 @@ export function getAllAsyncJSFunctions( } return allAsyncJSFunctions; } + +export function getValidEntityType( + entity: DataTreeEntity, + entityConfig: DataTreeEntityConfig, +) { + let entityType; + if (isValidEntity(entity)) { + entityType = + (!!entityConfig && entityConfig.ENTITY_TYPE) || entity.ENTITY_TYPE; + } + return !!entityType ? entityType : "noop"; +} diff --git a/app/client/src/workers/common/DataTreeEvaluator/validationUtils.ts b/app/client/src/workers/common/DataTreeEvaluator/validationUtils.ts index ef0df3a3ac..dac11271d6 100644 --- a/app/client/src/workers/common/DataTreeEvaluator/validationUtils.ts +++ b/app/client/src/workers/common/DataTreeEvaluator/validationUtils.ts @@ -1,11 +1,10 @@ import type { ValidationConfig } from "constants/PropertyControlConstants"; import { Severity } from "entities/AppsmithConsole"; import type { - ConfigTree, - DataTree, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { get, isObject, isUndefined, set } from "lodash"; import type { EvaluationError } from "utils/DynamicBindingUtils"; import { diff --git a/app/client/src/workers/common/DependencyMap/index.ts b/app/client/src/workers/common/DependencyMap/index.ts index 6b3d1e0e80..f65c34afa2 100644 --- a/app/client/src/workers/common/DependencyMap/index.ts +++ b/app/client/src/workers/common/DependencyMap/index.ts @@ -3,18 +3,17 @@ import { getAllPaths, DataTreeDiffEvent, isWidget, - isValidEntity, getEntityNameAndPropertyPath, isDynamicLeaf, } from "@appsmith/workers/Evaluation/evaluationUtils"; import type { - DataTree, WidgetEntity, - ConfigTree, WidgetEntityConfig, ActionEntity, JSActionEntity, + DataTreeEntityObject, } from "@appsmith/entities/DataTree/types"; +import type { ConfigTree, DataTree } from "entities/DataTree/dataTreeTypes"; import { getEntityId, getEvalErrorPath } from "utils/DynamicBindingUtils"; import { convertArrayToObject, extractInfoFromBindings } from "./utils"; import type DataTreeEvaluator from "workers/common/DataTreeEvaluator"; @@ -32,6 +31,7 @@ import { getEntitySetterFunctions, } from "@appsmith/workers/Evaluation/Actions"; import { isWidgetActionOrJsObject } from "@appsmith/entities/DataTree/utils"; +import { getValidEntityType } from "workers/common/DataTreeEvaluator/utils"; interface CreateDependencyMap { dependencies: Record; @@ -60,7 +60,7 @@ export function createDependencyMap( const entity = unEvalTree[entityName]; const entityConfig = configTree[entityName]; const entityDependencies = getEntityDependencies( - entity, + entity as DataTreeEntityObject, entityConfig, allKeys, ); @@ -142,7 +142,7 @@ export const updateDependencyMap = ({ event === DataTreeDiffEvent.DELETE ? oldUnEvalTree[entityName] : unEvalDataTree[entityName]; - const entityType = isValidEntity(entity) ? entity.ENTITY_TYPE : "noop"; + const entityType = getValidEntityType(entity, entityConfig); if (entityType !== "noop") { switch (event) { diff --git a/app/client/src/workers/common/DependencyMap/test.ts b/app/client/src/workers/common/DependencyMap/test.ts index 531c9eabb9..3bb6b933a8 100644 --- a/app/client/src/workers/common/DependencyMap/test.ts +++ b/app/client/src/workers/common/DependencyMap/test.ts @@ -6,11 +6,10 @@ import { import ButtonWidget from "widgets/ButtonWidget"; import SelectWidget from "widgets/SelectWidget"; import type { - DataTree, - ConfigTree, WidgetEntity, DataTreeEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTree, ConfigTree } from "entities/DataTree/dataTreeTypes"; import { unEvalTreeWidgetSelectWidgetConfig, configTree, diff --git a/app/client/src/workers/common/DependencyMap/utils.ts b/app/client/src/workers/common/DependencyMap/utils.ts index 76fe2bbcbc..7365d5bca4 100644 --- a/app/client/src/workers/common/DependencyMap/utils.ts +++ b/app/client/src/workers/common/DependencyMap/utils.ts @@ -9,11 +9,11 @@ import { isWidget, } from "@appsmith/workers/Evaluation/evaluationUtils"; +import type { WidgetEntityConfig } from "@appsmith/entities/DataTree/types"; import type { ConfigTree, DataTreeEntity, - WidgetEntityConfig, -} from "@appsmith/entities/DataTree/types"; +} from "entities/DataTree/dataTreeTypes"; import { DEDICATED_WORKER_GLOBAL_SCOPE_IDENTIFIERS, JAVASCRIPT_KEYWORDS, diff --git a/app/client/src/workers/common/DependencyMap/utils/getEntityDependencies.ts b/app/client/src/workers/common/DependencyMap/utils/getEntityDependencies.ts index 21493fafe7..4105f75c78 100644 --- a/app/client/src/workers/common/DependencyMap/utils/getEntityDependencies.ts +++ b/app/client/src/workers/common/DependencyMap/utils/getEntityDependencies.ts @@ -9,20 +9,21 @@ import type { ActionEntityConfig, JSActionEntity, JSActionEntityConfig, - DataTreeEntity, DataTreeEntityConfig, WidgetEntity, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import { find, get, union } from "lodash"; import { getDynamicBindings, getEntityDynamicBindingPathList, } from "utils/DynamicBindingUtils"; import { isWidgetActionOrJsObject } from "@appsmith/entities/DataTree/utils"; +import type { DataTreeEntityObject } from "@appsmith/entities/DataTree/types"; export function getEntityDependencies( - entity: DataTreeEntity, + entity: DataTreeEntityObject, entityConfig: DataTreeEntityConfig, allKeys: Record, ): Record { @@ -30,13 +31,13 @@ export function getEntityDependencies( switch (entity.ENTITY_TYPE) { case ENTITY_TYPE_VALUE.ACTION: return getActionDependencies( - entity, + entity as ActionEntity, entityConfig as ActionEntityConfig, allKeys, ); case ENTITY_TYPE_VALUE.JSACTION: return getJSDependencies( - entity, + entity as JSActionEntity, entityConfig as JSActionEntityConfig, allKeys, ); @@ -159,21 +160,21 @@ export function getEntityPathDependencies( switch (entity.ENTITY_TYPE) { case ENTITY_TYPE_VALUE.ACTION: return getActionPropertyPathDependencies( - entity, + entity as ActionEntity, entityConfig as ActionEntityConfig, fullPropertyPath, allKeys, ); case ENTITY_TYPE_VALUE.JSACTION: return getJSPropertyPathDependencies( - entity, + entity as JSActionEntity, entityConfig as JSActionEntityConfig, fullPropertyPath, allKeys, ); case ENTITY_TYPE_VALUE.WIDGET: return getWidgetPropertyPathDependencies( - entity, + entity as WidgetEntity, entityConfig as WidgetEntityConfig, fullPropertyPath, ); diff --git a/app/client/src/workers/common/DependencyMap/utils/getValidationDependencies.ts b/app/client/src/workers/common/DependencyMap/utils/getValidationDependencies.ts index b6929f53c9..6ac10d10f3 100644 --- a/app/client/src/workers/common/DependencyMap/utils/getValidationDependencies.ts +++ b/app/client/src/workers/common/DependencyMap/utils/getValidationDependencies.ts @@ -1,9 +1,9 @@ import { isWidget } from "@appsmith/workers/Evaluation/evaluationUtils"; import type { - DataTreeEntity, DataTreeEntityConfig, WidgetEntityConfig, } from "@appsmith/entities/DataTree/types"; +import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes"; import type { DependencyMap } from "utils/DynamicBindingUtils"; const DATA_DERIVED_PROPERTY_PLACEHOLDER = "*"; From 356ff3292af914c0dc2c47b323a32a2c178c4d33 Mon Sep 17 00:00:00 2001 From: Parthvi <80334441+Parthvi12@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:03:51 +0530 Subject: [PATCH 12/75] test: Add common method to delete app via api (#27923) ## Description Adds cypress method to delete app via api and updated git test. ## Testing locally #### 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 --------- Co-authored-by: Aishwarya UR --- .../RepoLimitExceededErrorModal_spec.js | 24 ++++--------------- app/client/cypress/support/Pages/HomePage.ts | 11 +++++++++ 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js index f537cfe973..b42282c3e6 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js @@ -92,26 +92,10 @@ describe("Repo Limit Exceeded Error Modal", function () { }); after(() => { - cy.request({ - method: "DELETE", - url: "api/v1/applications/" + repoName1, - failOnStatusCode: false, - }); - cy.request({ - method: "DELETE", - url: "api/v1/applications/" + repoName2, - failOnStatusCode: false, - }); - cy.request({ - method: "DELETE", - url: "api/v1/applications/" + repoName3, - failOnStatusCode: false, - }); - cy.request({ - method: "DELETE", - url: "api/v1/applications/" + repoName4, - failOnStatusCode: false, - }); + homePage.DeleteAppviaAPI(repoName1); + homePage.DeleteAppviaAPI(repoName2); + homePage.DeleteAppviaAPI(repoName3); + homePage.DeleteAppviaAPI(repoName4); gitSync.DeleteTestGithubRepo(repoName1); gitSync.DeleteTestGithubRepo(repoName2); gitSync.DeleteTestGithubRepo(repoName3); diff --git a/app/client/cypress/support/Pages/HomePage.ts b/app/client/cypress/support/Pages/HomePage.ts index 9e3a03625f..846fb2e9c2 100644 --- a/app/client/cypress/support/Pages/HomePage.ts +++ b/app/client/cypress/support/Pages/HomePage.ts @@ -623,6 +623,17 @@ export class HomePage { this.agHelper.WaitUntilToastDisappear("Deleting application..."); } + public DeleteAppviaAPI(appId: any) { + cy.request({ + method: "DELETE", + url: "api/v1/applications/" + appId, + failOnStatusCode: false, + headers: { + "X-Requested-By": "Appsmith", + }, + }); + } + //Maps to leaveworkspace in command.js public LeaveWorkspace(workspaceName: string) { this.OpenWorkspaceOptions(workspaceName); From 8b2d2568b0795131ea426cba4bfd7107e04208c8 Mon Sep 17 00:00:00 2001 From: Manish Kumar <107841575+sondermanish@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:42:20 +0530 Subject: [PATCH 13/75] feat: CE support for connection pooling (#27859) ### Description > This is a CE support PR for thie connection pooling issue Ref: https://github.com/appsmithorg/appsmith-ee/pull/2143 Fixes https://github.com/appsmithorg/appsmith-ee/issues/2124 --- .../configurations/ConnectionPoolConfig.java | 3 ++ .../ConnectionPoolConfigCE.java | 7 +++++ .../ConnectionPoolConfigCECompatible.java | 3 ++ .../com/external/plugins/PostgresPlugin.java | 26 ++++++++++++---- .../external/plugins/PostgresPluginTest.java | 10 +++++- .../ConnectionPoolConfigCECompatibleImpl.java | 8 +++++ .../ConnectionPoolConfigCEImpl.java | 14 +++++++++ .../ConnectionPoolConfigImpl.java | 9 ++++++ .../ConnectionPoolConfigCETest.java | 31 +++++++++++++++++++ 9 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfig.java create mode 100644 app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCE.java create mode 100644 app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatible.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatibleImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCEImpl.java create mode 100644 app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigImpl.java create mode 100644 app/server/appsmith-server/src/test/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCETest.java diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfig.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfig.java new file mode 100644 index 0000000000..66e84e22df --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfig.java @@ -0,0 +1,3 @@ +package com.appsmith.external.connectionpoolconfig.configurations; + +public interface ConnectionPoolConfig extends ConnectionPoolConfigCECompatible {} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCE.java new file mode 100644 index 0000000000..f093a42d96 --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCE.java @@ -0,0 +1,7 @@ +package com.appsmith.external.connectionpoolconfig.configurations; + +import reactor.core.publisher.Mono; + +public interface ConnectionPoolConfigCE { + Mono getMaxConnectionPoolSize(); +} diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatible.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatible.java new file mode 100644 index 0000000000..12fb7a3b0f --- /dev/null +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatible.java @@ -0,0 +1,3 @@ +package com.appsmith.external.connectionpoolconfig.configurations; + +public interface ConnectionPoolConfigCECompatible extends ConnectionPoolConfigCE {} diff --git a/app/server/appsmith-plugins/postgresPlugin/src/main/java/com/external/plugins/PostgresPlugin.java b/app/server/appsmith-plugins/postgresPlugin/src/main/java/com/external/plugins/PostgresPlugin.java index 7d9c178395..eec7c01a91 100644 --- a/app/server/appsmith-plugins/postgresPlugin/src/main/java/com/external/plugins/PostgresPlugin.java +++ b/app/server/appsmith-plugins/postgresPlugin/src/main/java/com/external/plugins/PostgresPlugin.java @@ -1,5 +1,6 @@ package com.external.plugins; +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfig; import com.appsmith.external.constants.DataType; import com.appsmith.external.datatypes.AppsmithType; import com.appsmith.external.dtos.ExecuteActionDTO; @@ -182,9 +183,11 @@ public class PostgresPlugin extends BasePlugin { private static final int PREPARED_STATEMENT_INDEX = 0; private final SharedConfig sharedConfig; + private final ConnectionPoolConfig connectionPoolConfig; - public PostgresPluginExecutor(SharedConfig sharedConfig) { + public PostgresPluginExecutor(SharedConfig sharedConfig, ConnectionPoolConfig connectionPoolConfig) { this.sharedConfig = sharedConfig; + this.connectionPoolConfig = connectionPoolConfig; MAX_SIZE_SUPPORTED = sharedConfig.getMaxResponseSize(); } @@ -609,9 +612,13 @@ public class PostgresPlugin extends BasePlugin { e.getMessage())); } - return Mono.fromCallable(() -> { - log.debug("Connecting to Postgres db"); - return createConnectionPool(datasourceConfiguration); + return connectionPoolConfig + .getMaxConnectionPoolSize() + .flatMap(maxPoolSize -> { + return Mono.fromCallable(() -> { + log.debug("Connecting to Postgres db"); + return createConnectionPool(datasourceConfiguration, maxPoolSize); + }); }) .subscribeOn(scheduler); } @@ -1070,7 +1077,8 @@ public class PostgresPlugin extends BasePlugin { * @param datasourceConfiguration * @return connection pool */ - private static HikariDataSource createConnectionPool(DatasourceConfiguration datasourceConfiguration) + private static HikariDataSource createConnectionPool( + DatasourceConfiguration datasourceConfiguration, Integer maximumConfigurablePoolSize) throws AppsmithPluginException { HikariConfig config = new HikariConfig(); @@ -1079,7 +1087,13 @@ public class PostgresPlugin extends BasePlugin { // Set SSL property com.appsmith.external.models.Connection configurationConnection = datasourceConfiguration.getConnection(); config.setMinimumIdle(MINIMUM_POOL_SIZE); - config.setMaximumPoolSize(MAXIMUM_POOL_SIZE); + + int maxPoolSize = MAXIMUM_POOL_SIZE; + if (maximumConfigurablePoolSize != null && maximumConfigurablePoolSize >= maxPoolSize) { + maxPoolSize = maximumConfigurablePoolSize; + } + + config.setMaximumPoolSize(maxPoolSize); // Set authentication properties DBAuth authentication = (DBAuth) datasourceConfiguration.getAuthentication(); diff --git a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java index f3bb5e77ec..9dba145e86 100644 --- a/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java +++ b/app/server/appsmith-plugins/postgresPlugin/src/test/java/com/external/plugins/PostgresPluginTest.java @@ -1,5 +1,6 @@ package com.external.plugins; +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfig; import com.appsmith.external.datatypes.ClientDataType; import com.appsmith.external.dtos.ExecuteActionDTO; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException; @@ -77,8 +78,15 @@ public class PostgresPluginTest { } } + public class MockConnectionPoolConfig implements ConnectionPoolConfig { + @Override + public Mono getMaxConnectionPoolSize() { + return Mono.just(5); + } + } + PostgresPlugin.PostgresPluginExecutor pluginExecutor = - new PostgresPlugin.PostgresPluginExecutor(new MockSharedConfig()); + new PostgresPlugin.PostgresPluginExecutor(new MockSharedConfig(), new MockConnectionPoolConfig()); @SuppressWarnings("rawtypes") // The type parameter for the container type is just itself and is pseudo-optional. @Container diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatibleImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatibleImpl.java new file mode 100644 index 0000000000..74ee25d6c6 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCECompatibleImpl.java @@ -0,0 +1,8 @@ +package com.appsmith.server.connectionpoolconfig.configurations; + +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfigCECompatible; +import org.springframework.stereotype.Component; + +@Component +public class ConnectionPoolConfigCECompatibleImpl extends ConnectionPoolConfigCEImpl + implements ConnectionPoolConfigCECompatible {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCEImpl.java new file mode 100644 index 0000000000..16db95e0a8 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCEImpl.java @@ -0,0 +1,14 @@ +package com.appsmith.server.connectionpoolconfig.configurations; + +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfigCE; +import reactor.core.publisher.Mono; + +public class ConnectionPoolConfigCEImpl implements ConnectionPoolConfigCE { + + protected static final Integer DEFAULT_MINIMUM_MAX_POOL_SIZE = 5; + + @Override + public Mono getMaxConnectionPoolSize() { + return Mono.just(DEFAULT_MINIMUM_MAX_POOL_SIZE); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigImpl.java new file mode 100644 index 0000000000..6d64667672 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigImpl.java @@ -0,0 +1,9 @@ +package com.appsmith.server.connectionpoolconfig.configurations; + +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfig; +import org.springframework.stereotype.Component; + +@Component +public class ConnectionPoolConfigImpl extends ConnectionPoolConfigCECompatibleImpl implements ConnectionPoolConfig { + public ConnectionPoolConfigImpl() {} +} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCETest.java new file mode 100644 index 0000000000..f9570cead6 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/connectionpoolconfig/configurations/ConnectionPoolConfigCETest.java @@ -0,0 +1,31 @@ +package com.appsmith.server.connectionpoolconfig.configurations; + +import com.appsmith.external.connectionpoolconfig.configurations.ConnectionPoolConfig; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +public class ConnectionPoolConfigCETest { + + @Autowired + ConnectionPoolConfig connectionPoolConfig; + + @Test + public void verifyGetMaxConnectionPoolSizeProvidesDefaultValue() { + // this is same as default + Integer connectionPoolMaxSize = 5; + + Mono connectionPoolMaxSizeMono = connectionPoolConfig.getMaxConnectionPoolSize(); + StepVerifier.create(connectionPoolMaxSizeMono).assertNext(poolSize -> { + assertThat(poolSize).isEqualTo(connectionPoolMaxSize); + }); + } +} From b2f7451f5b0979e79c134aefcaba9e0f29dc015e Mon Sep 17 00:00:00 2001 From: Appsmith Bot <74705725+appsmith-bot@users.noreply.github.com> Date: Wed, 11 Oct 2023 06:52:40 +0530 Subject: [PATCH 14/75] Update top contributors --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a34afce3ab..012bf3ed6d 100644 --- a/README.md +++ b/README.md @@ -94,16 +94,16 @@ Let's build great software together. [![ayushpahwa](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/8526215?v=4&w=50&h=50&mask=circle)](https://github.com/ayushpahwa) [![yatinappsmith](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/84702014?v=4&w=50&h=50&mask=circle)](https://github.com/yatinappsmith) [![Parthvi12](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/80334441?v=4&w=50&h=50&mask=circle)](https://github.com/Parthvi12) -[![somangshu](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/11089579?v=4&w=50&h=50&mask=circle)](https://github.com/somangshu) [![ApekshaBhosale](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/7846888?v=4&w=50&h=50&mask=circle)](https://github.com/ApekshaBhosale) +[![somangshu](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/11089579?v=4&w=50&h=50&mask=circle)](https://github.com/somangshu) [![pranavkanade](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/13262095?v=4&w=50&h=50&mask=circle)](https://github.com/pranavkanade) [![sneha122](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/30018882?v=4&w=50&h=50&mask=circle)](https://github.com/sneha122) [![pratapaprasanna](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/15846947?v=4&w=50&h=50&mask=circle)](https://github.com/pratapaprasanna) [![albinAppsmith](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/87797149?v=4&w=50&h=50&mask=circle)](https://github.com/albinAppsmith) [![sum35h](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/20785806?v=4&w=50&h=50&mask=circle)](https://github.com/sum35h) [![marks0351](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/35134347?v=4&w=50&h=50&mask=circle)](https://github.com/marks0351) -[![ashit-rath](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/88306433?v=4&w=50&h=50&mask=circle)](https://github.com/ashit-rath) [![nsarupr](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/20905988?v=4&w=50&h=50&mask=circle)](https://github.com/nsarupr) +[![ashit-rath](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/88306433?v=4&w=50&h=50&mask=circle)](https://github.com/ashit-rath) [![rajatagrawal](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/1189106?v=4&w=50&h=50&mask=circle)](https://github.com/rajatagrawal) [![NilanshBansal](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/25542733?v=4&w=50&h=50&mask=circle)](https://github.com/NilanshBansal) [![dhruvikn](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/22471214?v=4&w=50&h=50&mask=circle)](https://github.com/dhruvikn) @@ -122,8 +122,8 @@ Let's build great software together. [![brayn003](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/8724051?v=4&w=50&h=50&mask=circle)](https://github.com/brayn003) [![shubham7saxena7](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/136057998?v=4&w=50&h=50&mask=circle)](https://github.com/shubham7saxena7) [![ramsaptami](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/79509062?v=4&w=50&h=50&mask=circle)](https://github.com/ramsaptami) -[![dvj1988](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/18716465?v=4&w=50&h=50&mask=circle)](https://github.com/dvj1988) [![vivonk](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/25587962?v=4&w=50&h=50&mask=circle)](https://github.com/vivonk) +[![dvj1988](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/18716465?v=4&w=50&h=50&mask=circle)](https://github.com/dvj1988) [![gitstart-appsmith](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/114667275?v=4&w=50&h=50&mask=circle)](https://github.com/gitstart-appsmith) [![rohan-arthur](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/94514895?v=4&w=50&h=50&mask=circle)](https://github.com/rohan-arthur) [![danciaclara](https://images.weserv.nl/?url=https://avatars.githubusercontent.com/u/32227135?v=4&w=50&h=50&mask=circle)](https://github.com/danciaclara) From b6d176bc9435fe321f4af770e8879d8d1e7570c3 Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Wed, 11 Oct 2023 10:43:51 +0530 Subject: [PATCH 15/75] chore: remove postcss-for (#27902) Removed postcss-for as it's causin to pull in some old dependencies due to which have CVEs discovered on them. --- app/client/craco.common.config.js | 1 - app/client/package.json | 1 - .../packages/storybook/.storybook/main.ts | 2 -- app/client/packages/storybook/package.json | 1 - app/client/yarn.lock | 23 +------------------ 5 files changed, 1 insertion(+), 27 deletions(-) diff --git a/app/client/craco.common.config.js b/app/client/craco.common.config.js index a2c3185f65..154a45c27e 100644 --- a/app/client/craco.common.config.js +++ b/app/client/craco.common.config.js @@ -50,7 +50,6 @@ module.exports = { "postcss-import", "postcss-at-rules-variables", "postcss-conditionals", - "postcss-for", "postcss-each", "postcss-url", "postcss-modules-values", diff --git a/app/client/package.json b/app/client/package.json index 07f8cceb0f..a0b9ec81c6 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -333,7 +333,6 @@ "postcss-at-rules-variables": "^0.3.0", "postcss-conditionals": "^2.1.0", "postcss-each": "^1.1.0", - "postcss-for": "^2.1.1", "postcss-import": "^15.1.0", "postcss-modules-values": "^4.0.0", "postcss-nesting": "^12.0.1", diff --git a/app/client/packages/storybook/.storybook/main.ts b/app/client/packages/storybook/.storybook/main.ts index a479bba93e..85ff4b33f6 100644 --- a/app/client/packages/storybook/.storybook/main.ts +++ b/app/client/packages/storybook/.storybook/main.ts @@ -4,7 +4,6 @@ import postcssNesting from "postcss-nesting"; import postcssImport from "postcss-import"; import postcssAtRulesVariables from "postcss-at-rules-variables"; import postcssConditionals from "postcss-conditionals"; -import postcssFor from "postcss-for"; import postcssEach from "postcss-each"; import postcssModulesValues from "postcss-modules-values"; import * as glob from "glob"; @@ -34,7 +33,6 @@ module.exports = { postcssImport, postcssAtRulesVariables, postcssConditionals, - postcssFor, postcssEach, postcssModulesValues, ], diff --git a/app/client/packages/storybook/package.json b/app/client/packages/storybook/package.json index 54bdb065b1..b853457e6c 100644 --- a/app/client/packages/storybook/package.json +++ b/app/client/packages/storybook/package.json @@ -31,7 +31,6 @@ "postcss-at-rules-variables": "*", "postcss-conditionals": "*", "postcss-each": "*", - "postcss-for": "*", "postcss-import": "*", "postcss-loader": "*", "postcss-modules-values": "*", diff --git a/app/client/yarn.lock b/app/client/yarn.lock index d937cd91bf..a74ffd2aba 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -2321,7 +2321,6 @@ __metadata: postcss-at-rules-variables: "*" postcss-conditionals: "*" postcss-each: "*" - postcss-for: "*" postcss-import: "*" postcss-loader: "*" postcss-modules-values: "*" @@ -10406,7 +10405,6 @@ __metadata: postcss-at-rules-variables: ^0.3.0 postcss-conditionals: ^2.1.0 postcss-each: ^1.1.0 - postcss-for: ^2.1.1 postcss-import: ^15.1.0 postcss-modules-values: ^4.0.0 postcss-nesting: ^12.0.1 @@ -23986,16 +23984,6 @@ __metadata: languageName: node linkType: hard -"postcss-for@npm:*, postcss-for@npm:^2.1.1": - version: 2.1.1 - resolution: "postcss-for@npm:2.1.1" - dependencies: - postcss: ^5.0.0 - postcss-simple-vars: ^2.0.0 - checksum: aee8da42f7fdd8f15a835fb1d817a5c833d58149c7a76efcee31de2f727bcd615bd03627b96822cd6d6e5171fde2e798ef23b2cafb36047eb097fefcda661e61 - languageName: node - linkType: hard - "postcss-gap-properties@npm:^3.0.3": version: 3.0.3 resolution: "postcss-gap-properties@npm:3.0.3" @@ -24779,15 +24767,6 @@ __metadata: languageName: node linkType: hard -"postcss-simple-vars@npm:^2.0.0": - version: 2.0.0 - resolution: "postcss-simple-vars@npm:2.0.0" - dependencies: - postcss: ^5.0.21 - checksum: 9d70600d7fc0b810453761ff6136ab1b66bbb03e807eb1b129dd1b1366f595766c358b66afb3c35bc1f574d9e5c5d21a10c18f5e569cc85489b4ce053c2b1dbe - languageName: node - linkType: hard - "postcss-simple-vars@npm:^6.0.0": version: 6.0.3 resolution: "postcss-simple-vars@npm:6.0.3" @@ -24875,7 +24854,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^5.0.0, postcss@npm:^5.0.21, postcss@npm:^5.0.4": +"postcss@npm:^5.0.4": version: 5.2.18 resolution: "postcss@npm:5.2.18" dependencies: From d8501f82ad5da5e3cc8419f9f299ddf50e1e0413 Mon Sep 17 00:00:00 2001 From: Satish Gandham Date: Wed, 11 Oct 2023 11:10:43 +0530 Subject: [PATCH 16/75] ci: Run perf infra v2 in /perf-test command (#27934) Co-authored-by: Satish Gandham --- .github/workflows/perf-tests-command.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/perf-tests-command.yml b/.github/workflows/perf-tests-command.yml index 2114a5b1f9..f1a67967a1 100644 --- a/.github/workflows/perf-tests-command.yml +++ b/.github/workflows/perf-tests-command.yml @@ -60,3 +60,13 @@ jobs: secrets: inherit with: pr: ${{ github.event.client_payload.pull_request.number }} + + perf-test-v2: + needs: [ build-docker-image ] + # Only run if the build step is successful + if: success() + name: perf-test-v2 + uses: ./.github/workflows/perf-test-v2.yml + secrets: inherit + with: + pr: ${{ github.event.client_payload.pull_request.number }} From f5a0e41f606c157633c5b44bd4042fa29fb3e983 Mon Sep 17 00:00:00 2001 From: Valera Melnikov Date: Wed, 11 Oct 2023 10:14:38 +0300 Subject: [PATCH 17/75] chore: update eslint and dependencies then fix revealed errors (#27908) ## Description Update eslint and dependencies then fix revealed errors --- .../JSFunctionExecution_spec.ts | 8 +- .../cypress/support/Pages/AggregateHelper.ts | 2 +- .../cypress/support/Pages/EntityExplorer.ts | 5 +- app/client/cypress/support/Pages/Table.ts | 2 +- app/client/package.json | 31 +- .../src/components/Checkbox/src/Checkbox.tsx | 2 +- .../src/components/Field/src/Field.tsx | 8 +- .../src/components/Tooltip/src/useTooltip.ts | 8 +- .../theming/src/token/src/styles.module.css | 4 +- .../theming/src/token/src/themeTokens.json | 2 +- .../theming/src/utils/tokensToCss.ts | 2 +- .../widgets-old/src/Dropdown/index.tsx | 8 +- .../components/Button/src/styles.module.css | 4 +- .../components/Checkbox/src/styles.module.css | 4 +- .../components/Radio/src/styles.module.css | 4 +- .../components/Switch/src/styles.module.css | 4 +- .../src/components/testing/styles.module.css | 4 +- .../WidgetQueryGenerators/GSheets/index.ts | 12 +- .../WidgetQueryGenerators/MongoDB/index.ts | 11 +- app/client/src/actions/gitSyncActions.ts | 2 +- app/client/src/ce/pages/Upgrade/Carousel.tsx | 3 +- .../businessEdition/UpgradeToBEPage.tsx | 6 +- app/client/src/ce/sagas/ApplicationSagas.tsx | 16 +- app/client/src/ce/sagas/WorkspaceSagas.ts | 5 +- app/client/src/ce/sagas/analyticsSaga.ts | 10 +- app/client/src/ce/sagas/userSagas.tsx | 15 +- .../src/ce/selectors/entitiesSelector.ts | 16 +- .../editorComponents/CodeEditor/modes.ts | 27 +- .../EditorContextProvider.tsx | 13 +- .../editorComponents/GlobalSearch/index.tsx | 4 +- .../editorComponents/PaneWrapper.tsx | 4 +- .../WidgetQueryGeneratorForm/index.tsx | 12 +- .../fields/EmbeddedDatasourcePathField.tsx | 3 +- .../walkthroughRenderer.tsx | 6 +- .../propertyControls/DropDownControl.tsx | 5 +- .../FieldConfigurationControl.tsx | 4 +- .../src/entities/URLRedirect/URLAssembly.ts | 15 +- .../common/resizer/ModalResizable.tsx | 2 +- .../layoutSystems/common/resizer/common.tsx | 2 +- .../widgetGrouping/WidgetsMultiSelectBox.tsx | 6 +- .../AdminSettings/FormGroup/ColorInput.tsx | 4 +- .../EntityNavigation/PropertyPane/utils.ts | 15 +- .../pages/Editor/Explorer/Actions/helpers.tsx | 5 +- .../Explorer/JSActions/MoreJSActionsMenu.tsx | 4 +- .../pages/Editor/Explorer/Libraries/index.tsx | 11 +- app/client/src/pages/Editor/Explorer/hooks.ts | 15 +- app/client/src/pages/Editor/Popper.tsx | 8 +- .../Tabs/GitConnectionV2/AddDeployKey.tsx | 6 +- .../GitConnectionV2/ChooseGitProvider.tsx | 2 +- .../Tabs/GitConnectionV2/GenerateSSH.tsx | 2 +- .../gitSync/Tabs/GitConnectionV2/Steps.tsx | 2 +- .../Editor/gitSync/components/CopyButton.tsx | 4 +- .../Editor/gitSync/components/Statusbar.tsx | 9 +- .../Editor/gitSync/hooks/useSSHKeyPair.ts | 4 +- .../src/pages/Templates/TemplateView.tsx | 3 +- app/client/src/pages/common/SuccessTick.tsx | 3 +- .../common/datasourceAuth/AuthMessage.tsx | 2 +- .../src/pages/common/datasourceAuth/index.tsx | 18 +- app/client/src/plugins/Linting/constants.ts | 2 +- .../plugins/Linting/handlers/lintService.ts | 9 +- .../entityReducers/pageListReducer.tsx | 11 +- .../sagas/ActionExecution/geolocationSaga.ts | 5 +- app/client/src/sagas/ActionSagas.ts | 10 +- app/client/src/sagas/ApiPaneSagas.ts | 2 +- app/client/src/sagas/AppThemingSaga.tsx | 15 +- .../src/sagas/AutoLayoutUpdateSagas.tsx | 10 +- .../sagas/CanvasSagas/DraggingCanvasSagas.ts | 10 +- app/client/src/sagas/DebuggerSagas.ts | 10 +- app/client/src/sagas/EvaluationsSaga.ts | 19 +- app/client/src/sagas/FormEvaluationSaga.ts | 5 +- app/client/src/sagas/GitSyncSagas.ts | 5 +- app/client/src/sagas/JSActionSagas.ts | 5 +- app/client/src/sagas/JSLibrarySaga.ts | 5 +- app/client/src/sagas/JSPaneSagas.ts | 5 +- app/client/src/sagas/ModalSagas.ts | 5 +- app/client/src/sagas/OnboardingSagas.ts | 20 +- app/client/src/sagas/PageSagas.tsx | 31 +- app/client/src/sagas/PostEvaluationSagas.ts | 5 +- app/client/src/sagas/ProvidersSaga.ts | 5 +- app/client/src/sagas/QueryPaneSagas.ts | 5 +- app/client/src/sagas/SnapshotSagas.ts | 10 +- app/client/src/sagas/WidgetDeletionSagas.ts | 10 +- app/client/src/sagas/WidgetOperationSagas.tsx | 22 +- app/client/src/sagas/WidgetOperationUtils.ts | 15 +- app/client/src/sagas/WidgetSelectionSagas.ts | 4 +- .../src/sagas/autoHeightSagas/widgets.ts | 5 +- app/client/src/selectors/editorSelectors.tsx | 13 +- app/client/src/selectors/themeSelectors.tsx | 6 +- .../src/utils/hooks/dragResizeHooks.tsx | 8 +- app/client/src/utils/storage.ts | 18 +- .../ButtonWidgetV2/component/Container.tsx | 17 +- .../ButtonWidgetV2/component/RecaptchaV2.tsx | 8 +- .../ButtonWidgetV2/component/RecaptchaV3.tsx | 4 +- .../component/CurrencyCodeDropdown.tsx | 4 +- .../component/CurrencyCodeDropdown.tsx | 4 +- .../InputWidget/component/ISDCodeDropdown.tsx | 4 +- .../src/widgets/JSONFormWidget/constants.ts | 13 +- .../widgets/JSONFormWidget/schemaParser.ts | 4 +- .../widgets/JSONFormWidget/widget/index.tsx | 7 +- .../ListWidgetV2/MetaWidgetGenerator.ts | 8 +- .../ListWidgetV2/component/ListPagination.tsx | 4 +- .../ListWidgetV2/widget/propertyConfig.ts | 2 +- .../MapChartWidget/CustomMapConstants.ts | 4 +- .../src/widgets/MapWidget/component/Map.tsx | 6 +- .../MenuButtonWidget/component/index.tsx | 4 +- .../MultiSelectWidget/component/index.tsx | 10 +- .../component/ISDCodeDropdown.tsx | 4 +- .../widgets/SwitchWidget/component/index.tsx | 4 +- .../src/widgets/TableWidget/widget/index.tsx | 10 +- .../TableWidget/widget/propertyUtils.ts | 2 +- .../component/cellComponents/ImageCell.tsx | 18 +- .../cellComponents/InlineCellEditor.tsx | 6 +- .../widgets/TableWidgetV2/widget/index.tsx | 28 +- .../src/widgets/TabsWidget/widget/index.tsx | 4 +- app/client/src/widgets/WidgetUtils.ts | 16 +- app/client/src/workers/Evaluation/domApis.ts | 11 +- .../workers/common/DataTreeEvaluator/index.ts | 8 +- .../src/workers/common/DependencyMap/utils.ts | 9 +- app/client/yarn.lock | 1443 +++++++++++------ 119 files changed, 1454 insertions(+), 940 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ServerSide/JsFunctionExecution/JSFunctionExecution_spec.ts b/app/client/cypress/e2e/Regression/ServerSide/JsFunctionExecution/JSFunctionExecution_spec.ts index 6e3f8803e8..d9ed33889b 100644 --- a/app/client/cypress/e2e/Regression/ServerSide/JsFunctionExecution/JSFunctionExecution_spec.ts +++ b/app/client/cypress/e2e/Regression/ServerSide/JsFunctionExecution/JSFunctionExecution_spec.ts @@ -366,13 +366,13 @@ describe("JS Function Execution", function () { : i === functionsLength - 1 ? ` ${functionName}: ${ - isMarkedAsync ? "async" : "" - } ()=>"${functionName}", + isMarkedAsync ? "async" : "" + } ()=>"${functionName}", }` : ` ${functionName}: ${ - isMarkedAsync ? "async" : "" - } ()=> "${functionName}",`; + isMarkedAsync ? "async" : "" + } ()=> "${functionName}",`; } return JS_OBJECT_BODY; }; diff --git a/app/client/cypress/support/Pages/AggregateHelper.ts b/app/client/cypress/support/Pages/AggregateHelper.ts index 0f4c85aee1..0217b56fa9 100644 --- a/app/client/cypress/support/Pages/AggregateHelper.ts +++ b/app/client/cypress/support/Pages/AggregateHelper.ts @@ -1043,8 +1043,8 @@ export class AggregateHelper extends ReusableHelper { public ActionContextMenuWithInPane({ action = "Delete", - subAction = "", entityType = EntityItems.JSObject, + subAction = "", toastToValidate = "", }: DeleteParams) { cy.get(this.locator._contextMenuInPane).click(); diff --git a/app/client/cypress/support/Pages/EntityExplorer.ts b/app/client/cypress/support/Pages/EntityExplorer.ts index 8e42bd557a..48a94a178a 100644 --- a/app/client/cypress/support/Pages/EntityExplorer.ts +++ b/app/client/cypress/support/Pages/EntityExplorer.ts @@ -28,6 +28,7 @@ interface EntityActionParams { | "Refresh" | "Set as home page"; subAction?: string; + //@ts-expect-error: type mismatch entityType?: EntityItems; toAssertAction?: boolean; toastToValidate?: string; @@ -232,10 +233,10 @@ export class EntityExplorer { } public ActionContextMenuByEntityName({ - entityNameinLeftSidebar, action = "Delete", - subAction = "", + entityNameinLeftSidebar, entityType = EntityItems.Query, + subAction = "", toAssertAction, toastToValidate = "", }: EntityActionParams) { diff --git a/app/client/cypress/support/Pages/Table.ts b/app/client/cypress/support/Pages/Table.ts index 94add0da1c..bf48613063 100644 --- a/app/client/cypress/support/Pages/Table.ts +++ b/app/client/cypress/support/Pages/Table.ts @@ -189,7 +189,7 @@ export class Table { _divFirstChild = "div:first-child abbr"; _listPreviousPage = ".rc-pagination-prev"; _listNavigation = (move: string) => - "//button[@area-label='" + move + " page']"; + "//button[@aria-label='" + move + " page']"; _listNextPage = ".rc-pagination-next"; _listActivePage = (version: "v1" | "v2") => `.t--widget-listwidget${ diff --git a/app/client/package.json b/app/client/package.json index a0b9ec81c6..adb4c390a8 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -282,10 +282,11 @@ "@types/tinycolor2": "^1.4.2", "@types/to-json-schema": "^0.2.1", "@types/toposort": "^2.0.3", + "@types/uuid": "^9.0.5", "@types/webfontloader": "1.6.33", "@types/zipcelx": "^1.5.0", - "@typescript-eslint/eslint-plugin": "^5.54.1", - "@typescript-eslint/parser": "^5.54.1", + "@typescript-eslint/eslint-plugin": "^6.7.4", + "@typescript-eslint/parser": "^6.7.4", "babel-plugin-lodash": "^3.3.4", "babel-plugin-module-resolver": "^4.1.0", "chalk": "^4.1.1", @@ -306,17 +307,17 @@ "cypress-xpath": "^1.6.0", "diff": "^5.0.0", "dotenv": "^8.1.0", - "eslint": "^8.42.0", - "eslint-config-prettier": "^8.6.0", - "eslint-import-resolver-babel-module": "^5.3.1", - "eslint-plugin-cypress": "^2.11.2", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jest": "^27.2.1", - "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.30.0", - "eslint-plugin-react-hooks": "^2.3.0", - "eslint-plugin-sort-destructure-keys": "^1.3.5", - "eslint-plugin-storybook": "^0.6.11", + "eslint": "^8.51.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-babel-module": "^5.3.2", + "eslint-plugin-cypress": "^2.15.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jest": "^27.4.2", + "eslint-plugin-prettier": "^5.0.0", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-sort-destructure-keys": "^1.5.0", + "eslint-plugin-storybook": "^0.6.15", "esm": "^3.2.25", "factory.ts": "^0.5.1", "husky": "^8.0.0", @@ -325,7 +326,7 @@ "jest-environment-jsdom": "^27.4.1", "jest-styled-components": "^7.0.8", "json5": "^2.2.3", - "lint-staged": "^13.2.0", + "lint-staged": "^14.0.1", "msw": "^0.28.0", "pg": "^8.11.3", "plop": "^3.1.1", @@ -338,7 +339,7 @@ "postcss-nesting": "^12.0.1", "postcss-url": "^10.1.3", "postinstall-postinstall": "^2.1.0", - "prettier": "^2.8.6", + "prettier": "^3.0.3", "prop-types": "^15.8.1", "raw-loader": "^4.0.2", "react-is": "^16.12.0", diff --git a/app/client/packages/design-system/headless/src/components/Checkbox/src/Checkbox.tsx b/app/client/packages/design-system/headless/src/components/Checkbox/src/Checkbox.tsx index 06149c86bd..93fac5a2f9 100644 --- a/app/client/packages/design-system/headless/src/components/Checkbox/src/Checkbox.tsx +++ b/app/client/packages/design-system/headless/src/components/Checkbox/src/Checkbox.tsx @@ -36,8 +36,8 @@ const _Checkbox = (props: CheckboxProps, ref: CheckboxRef) => { icon: Icon = CheckIcon, isDisabled: isDisabledProp = false, isIndeterminate = false, - validationState, labelPosition = "right", + validationState, } = props; const state = useToggleState(props); const inputRef = useRef(null); diff --git a/app/client/packages/design-system/headless/src/components/Field/src/Field.tsx b/app/client/packages/design-system/headless/src/components/Field/src/Field.tsx index 8a388d553c..ffb5e26604 100644 --- a/app/client/packages/design-system/headless/src/components/Field/src/Field.tsx +++ b/app/client/packages/design-system/headless/src/components/Field/src/Field.tsx @@ -24,19 +24,19 @@ export type FieldRef = Ref; const _Field = (props: FieldProps, ref: FieldRef) => { const { children, + contextualHelp, + description, + descriptionProps, elementType, errorMessage, errorMessageProps = {}, + fieldType = "field", isDisabled = false, label, labelProps, validationState, wrapperClassName, - description, - descriptionProps, wrapperProps = {}, - contextualHelp, - fieldType = "field", } = props; const hasHelpText = Boolean(description) || diff --git a/app/client/packages/design-system/headless/src/components/Tooltip/src/useTooltip.ts b/app/client/packages/design-system/headless/src/components/Tooltip/src/useTooltip.ts index bd7ee2387b..94360530e6 100644 --- a/app/client/packages/design-system/headless/src/components/Tooltip/src/useTooltip.ts +++ b/app/client/packages/design-system/headless/src/components/Tooltip/src/useTooltip.ts @@ -35,14 +35,14 @@ export interface TooltipOptions { export function useTooltip({ closeDelay = 0, initialOpen = false, + interaction = "hover", + offset: offsetProp = DEFAULT_TOOLTIP_OFFSET, onOpenChange: setControlledOpen, open: controlledOpen, openDelay = 0, - placement = "top", - interaction = "hover", - offset: offsetProp = DEFAULT_TOOLTIP_OFFSET, - shift: shiftProp = DEFAULT_TOOLTIP_SHIFT, padding: paddingProp = DEFAULT_TOOLTIP_PADDING, + placement = "top", + shift: shiftProp = DEFAULT_TOOLTIP_SHIFT, }: TooltipOptions = {}) { const [uncontrolledOpen, setUncontrolledOpen] = React.useState(initialOpen); diff --git a/app/client/packages/design-system/theming/src/token/src/styles.module.css b/app/client/packages/design-system/theming/src/token/src/styles.module.css index 94240e4ef2..525c30fcf1 100644 --- a/app/client/packages/design-system/theming/src/token/src/styles.module.css +++ b/app/client/packages/design-system/theming/src/token/src/styles.module.css @@ -1,4 +1,4 @@ -//THIS FILE IS CREATED AUTOMATICALLY. PLEASE DON'T EDIT IT. +/* THIS FILE IS CREATED AUTOMATICALLY. PLEASE DON'T EDIT IT. */ :root { --root-unit: clamp(4px, calc(0.06vw + 3.77px), 5px); --spacing-0: 0; @@ -159,7 +159,7 @@ --color-fg-on-warning: rgb(21.953% 9.0775% 0%); --color-bd: rgb(72.54% 73.727% 82.602%); --color-bd-accent: rgb(33.333% 23.922% 91.373%); - --color-bd-focus: rgb(78.161% 34.431% 0%); + --color-bd-focus: rgb(33.333% 23.922% 91.373%); --color-bd-neutral: rgb(37.869% 38.922% 47.553%); --color-bd-neutral-hover: rgb(49.162% 50.308% 59.345%); --color-bd-positive: rgb(6.7435% 63.436% 18.481%); diff --git a/app/client/packages/design-system/theming/src/token/src/themeTokens.json b/app/client/packages/design-system/theming/src/token/src/themeTokens.json index 3a500e1f6c..e69207cc5c 100644 --- a/app/client/packages/design-system/theming/src/token/src/themeTokens.json +++ b/app/client/packages/design-system/theming/src/token/src/themeTokens.json @@ -193,7 +193,7 @@ "type": "color" }, "bd-focus": { - "value": "rgb(78.161% 34.431% 0%)", + "value": "rgb(33.333% 23.922% 91.373%)", "type": "color" }, "bd-neutral": { diff --git a/app/client/packages/design-system/theming/src/utils/tokensToCss.ts b/app/client/packages/design-system/theming/src/utils/tokensToCss.ts index 67de7e7058..3ab42ecc42 100644 --- a/app/client/packages/design-system/theming/src/utils/tokensToCss.ts +++ b/app/client/packages/design-system/theming/src/utils/tokensToCss.ts @@ -18,7 +18,7 @@ const allTokens = new TokensAccessor({ }).getAllTokens(); const ATTENTION_MESSAGE = - "//THIS FILE IS CREATED AUTOMATICALLY. PLEASE DON'T EDIT IT."; + "/* THIS FILE IS CREATED AUTOMATICALLY. PLEASE DON'T EDIT IT. */"; const cssStyles = `:root {--root-unit: ${getFluidRootUnit(fluid)}; ${cssRule( allTokens, )}}`; diff --git a/app/client/packages/design-system/widgets-old/src/Dropdown/index.tsx b/app/client/packages/design-system/widgets-old/src/Dropdown/index.tsx index fb9557c44d..caf712d81d 100644 --- a/app/client/packages/design-system/widgets-old/src/Dropdown/index.tsx +++ b/app/client/packages/design-system/widgets-old/src/Dropdown/index.tsx @@ -346,7 +346,8 @@ export const DropdownWrapper = styled.div<{ border: 1px solid var(--ads-dropdown-default-menu-border-color); overflow: hidden; overflow-y: auto; - box-shadow: 0px 12px 16px -4px rgba(0, 0, 0, 0.1), + box-shadow: + 0px 12px 16px -4px rgba(0, 0, 0, 0.1), 0px 4px 6px -2px rgba(0, 0, 0, 0.05); display: ${(props) => (props.isOpen ? "inline-block" : "none")}; .dropdown-search { @@ -1121,9 +1122,8 @@ export default function Dropdown(props: DropdownProps) { const handleKeydown = useCallback( (e: React.KeyboardEvent) => { - const elementList = document.getElementById( - "ds--dropdown-options", - )?.children; + const elementList = document.getElementById("ds--dropdown-options") + ?.children; if (!elementList || elementList?.length === 0) { setHighlight(-1); } diff --git a/app/client/packages/design-system/widgets/src/components/Button/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Button/src/styles.module.css index 1a882211e2..99ec4a3435 100644 --- a/app/client/packages/design-system/widgets/src/components/Button/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Button/src/styles.module.css @@ -108,7 +108,9 @@ *----------------------------------------------------------------------------- */ &[data-focused] { - box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-bd-focus); + box-shadow: + 0 0 0 2px var(--color-bg), + 0 0 0 4px var(--color-bd-focus); } /** diff --git a/app/client/packages/design-system/widgets/src/components/Checkbox/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Checkbox/src/styles.module.css index 6cde08c23e..08c22fa5a9 100644 --- a/app/client/packages/design-system/widgets/src/components/Checkbox/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Checkbox/src/styles.module.css @@ -50,7 +50,9 @@ *----------------------------------------------------------------------------- */ &[data-focused] [data-icon] { - box-shadow: var(--checkbox-box-shadow), 0 0 0 2px var(--color-bg), + box-shadow: + var(--checkbox-box-shadow), + 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-bd-focus); } diff --git a/app/client/packages/design-system/widgets/src/components/Radio/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Radio/src/styles.module.css index 79a92fa649..5da0dc267f 100644 --- a/app/client/packages/design-system/widgets/src/components/Radio/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Radio/src/styles.module.css @@ -48,7 +48,9 @@ *----------------------------------------------------------------------------- */ &[data-focused] [data-icon] { - box-shadow: var(--radio-box-shadow), 0 0 0 2px var(--color-bg), + box-shadow: + var(--radio-box-shadow), + 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-bd-focus); } diff --git a/app/client/packages/design-system/widgets/src/components/Switch/src/styles.module.css b/app/client/packages/design-system/widgets/src/components/Switch/src/styles.module.css index e4f3ebdaa8..57332dfe0e 100644 --- a/app/client/packages/design-system/widgets/src/components/Switch/src/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/Switch/src/styles.module.css @@ -56,6 +56,8 @@ *----------------------------------------------------------------------------- */ &[data-focused] [data-icon] { - box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-bd-focus); + box-shadow: + 0 0 0 2px var(--color-bg), + 0 0 0 4px var(--color-bd-focus); } } diff --git a/app/client/packages/design-system/widgets/src/components/testing/styles.module.css b/app/client/packages/design-system/widgets/src/components/testing/styles.module.css index 5677dac88c..bc1c1cb604 100644 --- a/app/client/packages/design-system/widgets/src/components/testing/styles.module.css +++ b/app/client/packages/design-system/widgets/src/components/testing/styles.module.css @@ -59,7 +59,9 @@ &[data-focused], &:focus-visible { - box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-bd-focus); + box-shadow: + 0 0 0 2px var(--color-bg), + 0 0 0 4px var(--color-bd-focus); } &[data-disabled] { diff --git a/app/client/src/WidgetQueryGenerators/GSheets/index.ts b/app/client/src/WidgetQueryGenerators/GSheets/index.ts index b79a1ef3b4..fed3841500 100644 --- a/app/client/src/WidgetQueryGenerators/GSheets/index.ts +++ b/app/client/src/WidgetQueryGenerators/GSheets/index.ts @@ -15,6 +15,7 @@ enum COMMAND_TYPES { "FIND" = "FETCH_MANY", "INSERT" = "INSERT_ONE", "UPDATE" = "UPDATE_ONE", + // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values "COUNT" = "FETCH_MANY", } const COMMON_INITIAL_VALUE_KEYS = [ @@ -237,10 +238,13 @@ export default abstract class GSheets extends BaseQueryGenerator { ]; const scrubedOutInitialValues = allowedInitialValueKeys .filter((key) => initialValues[key as keyof GSheetsFormData]) - .reduce((acc, key) => { - acc[key] = initialValues[key as keyof GSheetsFormData]; - return acc; - }, {} as Record); + .reduce( + (acc, key) => { + acc[key] = initialValues[key as keyof GSheetsFormData]; + return acc; + }, + {} as Record, + ); const { formData, ...rest } = builtValues; diff --git a/app/client/src/WidgetQueryGenerators/MongoDB/index.ts b/app/client/src/WidgetQueryGenerators/MongoDB/index.ts index cf6b3c1b45..eaf0b6d88d 100644 --- a/app/client/src/WidgetQueryGenerators/MongoDB/index.ts +++ b/app/client/src/WidgetQueryGenerators/MongoDB/index.ts @@ -191,10 +191,13 @@ export default abstract class MongoDB extends BaseQueryGenerator { const scrubedOutInitalValues = [...ALLOWED_INITAL_VALUE_KEYS, commandKey] .filter((key) => initialValues[key as keyof MongoDBFormData]) - .reduce((acc, key) => { - acc[key] = initialValues[key as keyof MongoDBFormData]; - return acc; - }, {} as Record); + .reduce( + (acc, key) => { + acc[key] = initialValues[key as keyof MongoDBFormData]; + return acc; + }, + {} as Record, + ); const { formData, ...rest } = builtValues; diff --git a/app/client/src/actions/gitSyncActions.ts b/app/client/src/actions/gitSyncActions.ts index ce998114e4..a5fa06cc84 100644 --- a/app/client/src/actions/gitSyncActions.ts +++ b/app/client/src/actions/gitSyncActions.ts @@ -183,8 +183,8 @@ export const fetchGitStatusSuccess = (payload: GitStatusData) => ({ }); export const fetchGitRemoteStatusInit = ({ - onSuccessCallback = noop, onErrorCallback = noop, + onSuccessCallback = noop, } = {}) => ({ type: ReduxActionTypes.FETCH_GIT_REMOTE_STATUS_INIT, onSuccessCallback, diff --git a/app/client/src/ce/pages/Upgrade/Carousel.tsx b/app/client/src/ce/pages/Upgrade/Carousel.tsx index 3a57a41f59..0cfae1f499 100644 --- a/app/client/src/ce/pages/Upgrade/Carousel.tsx +++ b/app/client/src/ce/pages/Upgrade/Carousel.tsx @@ -65,7 +65,8 @@ const CarouselContainer = styled.div` &.active { height: max-content; - box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.06), + box-shadow: + 0 2px 4px -2px rgba(0, 0, 0, 0.06), 0 4px 8px -2px rgba(0, 0, 0, 0.1); background-color: var(--ads-v2-color-bg); diff --git a/app/client/src/ce/pages/Upgrade/businessEdition/UpgradeToBEPage.tsx b/app/client/src/ce/pages/Upgrade/businessEdition/UpgradeToBEPage.tsx index 1a9da5b11f..3e51e3e05e 100644 --- a/app/client/src/ce/pages/Upgrade/businessEdition/UpgradeToBEPage.tsx +++ b/app/client/src/ce/pages/Upgrade/businessEdition/UpgradeToBEPage.tsx @@ -13,8 +13,10 @@ import { getAssetUrl } from "@appsmith/utils/airgapHelpers"; export const UpgradeToBEPageWrapper = styled.div` width: 100%; height: 100%; - background: linear-gradient(90deg, #fff 20px, transparent 1%) center, - linear-gradient(#fff 20px, transparent 1%) center, #d2ddec; + background: + linear-gradient(90deg, #fff 20px, transparent 1%) center, + linear-gradient(#fff 20px, transparent 1%) center, + #d2ddec; background-size: 22px 22px; position: relative; diff --git a/app/client/src/ce/sagas/ApplicationSagas.tsx b/app/client/src/ce/sagas/ApplicationSagas.tsx index 0f49425f24..f571d8a9bc 100644 --- a/app/client/src/ce/sagas/ApplicationSagas.tsx +++ b/app/client/src/ce/sagas/ApplicationSagas.tsx @@ -260,10 +260,13 @@ export function* fetchAppAndPagesSaga( const isValidResponse: boolean = yield call(validateResponse, response); if (isValidResponse) { const prevPagesState: Page[] = yield select(getPageList); - const pagePermissionsMap = prevPagesState.reduce((acc, page) => { - acc[page.pageId] = page.userPermissions ?? []; - return acc; - }, {} as Record); + const pagePermissionsMap = prevPagesState.reduce( + (acc, page) => { + acc[page.pageId] = page.userPermissions ?? []; + return acc; + }, + {} as Record, + ); yield put({ type: ReduxActionTypes.FETCH_APPLICATION_SUCCESS, payload: { ...response.data.application, pages: response.data.pages }, @@ -921,9 +924,8 @@ export function* initializeDatasourceWithDefaultValues(datasource: Datasource) { datasource.datasourceStorages[currentEnvironment], ); payload.isConfigured = false; // imported datasource as not configured yet - const response: ApiResponse = yield DatasourcesApi.updateDatasourceStorage( - payload, - ); + const response: ApiResponse = + yield DatasourcesApi.updateDatasourceStorage(payload); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { yield put({ diff --git a/app/client/src/ce/sagas/WorkspaceSagas.ts b/app/client/src/ce/sagas/WorkspaceSagas.ts index 12efda80a1..097b5e4904 100644 --- a/app/client/src/ce/sagas/WorkspaceSagas.ts +++ b/app/client/src/ce/sagas/WorkspaceSagas.ts @@ -273,9 +273,8 @@ export function* createWorkspaceSaga( ); const isValidResponse: boolean = yield validateResponse(response); if (!isValidResponse) { - const errorMessage: string | undefined = yield getResponseErrorMessage( - response, - ); + const errorMessage: string | undefined = + yield getResponseErrorMessage(response); yield call(reject, { _error: errorMessage }); } else { yield put({ diff --git a/app/client/src/ce/sagas/analyticsSaga.ts b/app/client/src/ce/sagas/analyticsSaga.ts index e6460ee5dc..769ef7d71c 100644 --- a/app/client/src/ce/sagas/analyticsSaga.ts +++ b/app/client/src/ce/sagas/analyticsSaga.ts @@ -44,12 +44,10 @@ export function* getUserAndAppDetails() { getCurrentApplication, ); const user: ReturnType = yield select(getCurrentUser); - const instanceId: ReturnType = yield select( - getInstanceId, - ); - const pageId: ReturnType = yield select( - getCurrentPageId, - ); + const instanceId: ReturnType = + yield select(getInstanceId); + const pageId: ReturnType = + yield select(getCurrentPageId); const userAndAppDetails: UserAndAppDetails = { pageId, appId: currentApp?.id || "", diff --git a/app/client/src/ce/sagas/userSagas.tsx b/app/client/src/ce/sagas/userSagas.tsx index 957fc49a9e..608dbb9c59 100644 --- a/app/client/src/ce/sagas/userSagas.tsx +++ b/app/client/src/ce/sagas/userSagas.tsx @@ -228,9 +228,8 @@ export function* forgotPasswordSaga( ); const isValidResponse: boolean = yield validateResponse(response); if (!isValidResponse) { - const errorMessage: string | undefined = yield getResponseErrorMessage( - response, - ); + const errorMessage: string | undefined = + yield getResponseErrorMessage(response); yield call(reject, { _error: errorMessage }); } else { yield put({ @@ -260,9 +259,8 @@ export function* resetPasswordSaga( const response: ApiResponse = yield callAPI(UserApi.resetPassword, request); const isValidResponse: boolean = yield validateResponse(response); if (!isValidResponse) { - const errorMessage: string | undefined = yield getResponseErrorMessage( - response, - ); + const errorMessage: string | undefined = + yield getResponseErrorMessage(response); yield call(reject, { _error: errorMessage }); } else { yield put({ @@ -294,9 +292,8 @@ export function* invitedUserSignupSaga( ); const isValidResponse: boolean = yield validateResponse(response); if (!isValidResponse) { - const errorMessage: string | undefined = yield getResponseErrorMessage( - response, - ); + const errorMessage: string | undefined = + yield getResponseErrorMessage(response); yield call(reject, { _error: errorMessage }); } else { yield put(invitedUserSignupSuccess()); diff --git a/app/client/src/ce/selectors/entitiesSelector.ts b/app/client/src/ce/selectors/entitiesSelector.ts index e7c414f902..35aa61a050 100644 --- a/app/client/src/ce/selectors/entitiesSelector.ts +++ b/app/client/src/ce/selectors/entitiesSelector.ts @@ -860,10 +860,13 @@ export const getPageActions = (pageId = "") => { export const selectDatasourceIdToNameMap = createSelector( getDatasources, (datasources) => { - return datasources.reduce((acc, datasource) => { - acc[datasource.id] = datasource.name; - return acc; - }, {} as Record); + return datasources.reduce( + (acc, datasource) => { + acc[datasource.id] = datasource.name; + return acc; + }, + {} as Record, + ); }, ); @@ -1185,9 +1188,8 @@ export const getDatasourceScopeValue = ( const options = formConfig[0]?.children?.find( (child: any) => child?.configProperty === configProperty, )?.options; - const label = options?.find( - (option: any) => option.value === scopeValue, - )?.label; + const label = options?.find((option: any) => option.value === scopeValue) + ?.label; return label; }; diff --git a/app/client/src/components/editorComponents/CodeEditor/modes.ts b/app/client/src/components/editorComponents/CodeEditor/modes.ts index ab3d6bb07a..65c0a3a690 100644 --- a/app/client/src/components/editorComponents/CodeEditor/modes.ts +++ b/app/client/src/components/editorComponents/CodeEditor/modes.ts @@ -59,18 +59,21 @@ export const MULTIPLEXING_MODE_CONFIGS: MultiplexingModeConfigs = { }, ...Object.values(sqlModesConfig) .filter((config) => config.isMultiplex) - .reduce((prev, current) => { - prev[current.mode] = { - outerMode: current.mime, - innerModes: [ - { - open: BINDING_OPEN, - close: BINDING_CLOSE, - }, - ], - }; - return prev; - }, {} as Record), + .reduce( + (prev, current) => { + prev[current.mode] = { + outerMode: current.mime, + innerModes: [ + { + open: BINDING_OPEN, + close: BINDING_CLOSE, + }, + ], + }; + return prev; + }, + {} as Record, + ), "text/plain": undefined, "application/json": undefined, javascript: undefined, diff --git a/app/client/src/components/editorComponents/EditorContextProvider.tsx b/app/client/src/components/editorComponents/EditorContextProvider.tsx index 01591ea968..25b287de8e 100644 --- a/app/client/src/components/editorComponents/EditorContextProvider.tsx +++ b/app/client/src/components/editorComponents/EditorContextProvider.tsx @@ -152,12 +152,15 @@ function extractFromObj( keys: K[], ): [Pick, T[K][]] { const deps = [] as T[K][]; - const newObj = keys.reduce((newObj, curr) => { - newObj[curr] = obj[curr]; - deps.push(obj[curr]); + const newObj = keys.reduce( + (newObj, curr) => { + newObj[curr] = obj[curr]; + deps.push(obj[curr]); - return newObj; - }, {} as Pick); + return newObj; + }, + {} as Pick, + ); return [newObj, deps]; } diff --git a/app/client/src/components/editorComponents/GlobalSearch/index.tsx b/app/client/src/components/editorComponents/GlobalSearch/index.tsx index 45455f0523..86e1a1ef33 100644 --- a/app/client/src/components/editorComponents/GlobalSearch/index.tsx +++ b/app/client/src/components/editorComponents/GlobalSearch/index.tsx @@ -68,7 +68,9 @@ import { const StyledContainer = styled.div<{ category: SearchCategory; query: string }>` max-height: 530px; - transition: height 0.1s ease, width 0.1s ease; + transition: + height 0.1s ease, + width 0.1s ease; height: ${(props) => isMenu(props.category) || isActionOperation(props.category) || diff --git a/app/client/src/components/editorComponents/PaneWrapper.tsx b/app/client/src/components/editorComponents/PaneWrapper.tsx index a82fdbebf0..ad2dd63d65 100644 --- a/app/client/src/components/editorComponents/PaneWrapper.tsx +++ b/app/client/src/components/editorComponents/PaneWrapper.tsx @@ -4,7 +4,9 @@ import { Colors } from "constants/Colors"; export default styled.div` background-color: ${Colors.GREY_1}; border-radius: ${(props) => props.theme.radii[0]}px; - box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.2), 0px 2px 10px rgba(0, 0, 0, 0.1); + box-shadow: + 0px 0px 2px rgba(0, 0, 0, 0.2), + 0px 2px 10px rgba(0, 0, 0, 0.1); color: ${(props) => props.theme.colors.textOnDarkBG}; text-transform: capitalize; `; diff --git a/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/index.tsx b/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/index.tsx index 0ef8bba672..9b62c7b545 100644 --- a/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/index.tsx +++ b/app/client/src/components/editorComponents/WidgetQueryGeneratorForm/index.tsx @@ -121,22 +121,22 @@ function WidgetQueryGeneratorForm(props: Props) { const [pristine, setPristine] = useState(true); const { - aliases, - alertMessage, - showEditFieldsModal = false, actionButtonCtaText = createMessage(CONNECT_BUTTON_TEXT), + alertMessage, + aliases, + datasourceDropdownVariant, errorMsg, excludePrimaryColumnFromQueryGeneration, expectedType, + isConnectableToWidget, onUpdate, + otherFields = [], propertyPath, propertyValue, sampleData, searchableColumn, + showEditFieldsModal = false, widgetId, - otherFields = [], - isConnectableToWidget, - datasourceDropdownVariant, } = props; const isSourceOpen = useSelector(getIsOneClickBindingOptionsVisibility); diff --git a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx index ee675469e7..e55bb41094 100644 --- a/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx +++ b/app/client/src/components/editorComponents/form/fields/EmbeddedDatasourcePathField.tsx @@ -147,7 +147,8 @@ const StyledTooltip = styled.span<{ width?: number }>` text-align: left; background-color: var(--ads-v2-color-bg-emphasis-max); border-radius: var(--ads-v2-border-radius); - box-shadow: 0 2px 4px -2px rgba(0, 0, 0, 0.06), + box-shadow: + 0 2px 4px -2px rgba(0, 0, 0, 0.06), 0 4px 8px -2px rgba(0, 0, 0, 0.1); color: var(--ads-v2-color-fg-on-emphasis-max); font-family: var(--ads-v2-font-family); diff --git a/app/client/src/components/featureWalkthrough/walkthroughRenderer.tsx b/app/client/src/components/featureWalkthrough/walkthroughRenderer.tsx index 89f7d6c6f0..fab3f46416 100644 --- a/app/client/src/components/featureWalkthrough/walkthroughRenderer.tsx +++ b/app/client/src/components/featureWalkthrough/walkthroughRenderer.tsx @@ -122,12 +122,12 @@ type BoundingRectTargets = Record; const WalkthroughRenderer = ({ details, - offset, - targetId, + dismissOnOverlayClick, eventParams = {}, multipleHighlights, + offset, overlayColor, - dismissOnOverlayClick, + targetId, }: FeatureParams) => { const [boundingRects, setBoundingRects] = useState(null); diff --git a/app/client/src/components/propertyControls/DropDownControl.tsx b/app/client/src/components/propertyControls/DropDownControl.tsx index 430f839e29..9406f5296b 100644 --- a/app/client/src/components/propertyControls/DropDownControl.tsx +++ b/app/client/src/components/propertyControls/DropDownControl.tsx @@ -100,9 +100,8 @@ class DropDownControl extends BaseControl { ? this.props.evaluatedValue : this.props.propertyValue; - selected = options.find( - (option) => option.value === computedValue, - )?.value; + selected = options.find((option) => option.value === computedValue) + ?.value; if (this.props.alwaysShowSelected && !selected) { selected = computedValue; diff --git a/app/client/src/components/propertyControls/FieldConfigurationControl.tsx b/app/client/src/components/propertyControls/FieldConfigurationControl.tsx index c7f43c6f61..4e866233ba 100644 --- a/app/client/src/components/propertyControls/FieldConfigurationControl.tsx +++ b/app/client/src/components/propertyControls/FieldConfigurationControl.tsx @@ -113,7 +113,7 @@ class FieldConfigurationControl extends BaseControl { addNewField = () => { if (this.isArrayItem()) return; - const { propertyValue = {}, propertyName, widgetProperties } = this.props; + const { propertyName, propertyValue = {}, widgetProperties } = this.props; const { childStylesheet, widgetName } = widgetProperties as JSONFormWidgetProps; const schema: Schema = propertyValue; @@ -193,7 +193,7 @@ class FieldConfigurationControl extends BaseControl { }; render() { - const { propertyValue = {}, panelConfig } = this.props; + const { panelConfig, propertyValue = {} } = this.props; const schema: Schema = propertyValue; const schemaItems = Object.values(schema); diff --git a/app/client/src/entities/URLRedirect/URLAssembly.ts b/app/client/src/entities/URLRedirect/URLAssembly.ts index 45bbb79a98..c4ddadf9a7 100644 --- a/app/client/src/entities/URLRedirect/URLAssembly.ts +++ b/app/client/src/entities/URLRedirect/URLAssembly.ts @@ -129,10 +129,13 @@ export class URLBuilder { appParams.applicationVersion || this.appParams.applicationVersion; } if (pageParams) { - const params = pageParams.reduce((acc, page) => { - acc[page.pageId] = page; - return acc; - }, {} as Record); + const params = pageParams.reduce( + (acc, page) => { + acc[page.pageId] = page; + return acc; + }, + {} as Record, + ); Object.assign(this.pageParams, params); } } @@ -196,12 +199,12 @@ export class URLBuilder { */ build(builderParams: URLBuilderParams, mode: APP_MODE = APP_MODE.EDIT) { const { + branch, hash = "", + pageId, params = {}, persistExistingParams = false, suffix, - pageId, - branch, } = builderParams; if (!pageId) { diff --git a/app/client/src/layoutSystems/common/resizer/ModalResizable.tsx b/app/client/src/layoutSystems/common/resizer/ModalResizable.tsx index 42ed69b0f0..570d87c8b3 100644 --- a/app/client/src/layoutSystems/common/resizer/ModalResizable.tsx +++ b/app/client/src/layoutSystems/common/resizer/ModalResizable.tsx @@ -42,7 +42,7 @@ type ResizableHandleProps = { function ResizableHandle(props: ResizableHandleProps) { const bind = useDrag( - ({ first, last, dragging, movement: [mx, my], memo }) => { + ({ dragging, first, last, memo, movement: [mx, my] }) => { if (!props.allowResize) { return; } diff --git a/app/client/src/layoutSystems/common/resizer/common.tsx b/app/client/src/layoutSystems/common/resizer/common.tsx index 06e2bfbeb9..a8ba4b472e 100644 --- a/app/client/src/layoutSystems/common/resizer/common.tsx +++ b/app/client/src/layoutSystems/common/resizer/common.tsx @@ -168,9 +168,9 @@ type ResizableHandleProps = { export function ResizableHandle(props: ResizableHandleProps) { const bind = useDrag((state) => { const { + dragging, first, last, - dragging, memo, movement: [mx, my], } = state; diff --git a/app/client/src/layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox.tsx b/app/client/src/layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox.tsx index f40d8d7578..d8e6d4f19e 100644 --- a/app/client/src/layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox.tsx +++ b/app/client/src/layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox.tsx @@ -206,10 +206,8 @@ function WidgetsMultiSelectBox(props: { left: (e.clientX - bounds.left) / props.snapColumnSpace, }; const top = minBy(selectedWidgets, (rect) => rect.topRow)?.topRow; - const left = minBy( - selectedWidgets, - (rect) => rect.leftColumn, - )?.leftColumn; + const left = minBy(selectedWidgets, (rect) => rect.leftColumn) + ?.leftColumn; setDraggingState({ isDragging: true, dragGroupActualParent: parentId || "", diff --git a/app/client/src/pages/AdminSettings/FormGroup/ColorInput.tsx b/app/client/src/pages/AdminSettings/FormGroup/ColorInput.tsx index 1dd4ea0c68..c5263ee0ba 100644 --- a/app/client/src/pages/AdminSettings/FormGroup/ColorInput.tsx +++ b/app/client/src/pages/AdminSettings/FormGroup/ColorInput.tsx @@ -102,11 +102,11 @@ export const ColorInput = (props: ColorInputProps) => { useState("primary"); const { className, + filter = () => true, + logEvent, onChange, tooltips, value, - filter = () => true, - logEvent, } = props; const colorInputRef = useRef(null); diff --git a/app/client/src/pages/Editor/EntityNavigation/PropertyPane/utils.ts b/app/client/src/pages/Editor/EntityNavigation/PropertyPane/utils.ts index 231e8e58cc..4e7b4e5bdf 100644 --- a/app/client/src/pages/Editor/EntityNavigation/PropertyPane/utils.ts +++ b/app/client/src/pages/Editor/EntityNavigation/PropertyPane/utils.ts @@ -78,14 +78,13 @@ export const getSectionId = ( // "boxShadow" and "resetButtonStyles.boxShadow" // The intendened match is "resetButtonStyles.boxShadow". // So we aggregrate matches and find the best match which is the longest string - const bestMatchedSection = matchedSections.reduce(function ( - sectiona, - sectionb, - ) { - return sectiona.propertyName.length > sectionb.propertyName.length - ? sectiona - : sectionb; - }); + const bestMatchedSection = matchedSections.reduce( + function (sectiona, sectionb) { + return sectiona.propertyName.length > sectionb.propertyName.length + ? sectiona + : sectionb; + }, + ); return bestMatchedSection.id; }; diff --git a/app/client/src/pages/Editor/Explorer/Actions/helpers.tsx b/app/client/src/pages/Editor/Explorer/Actions/helpers.tsx index 5587dab081..1da72a8483 100644 --- a/app/client/src/pages/Editor/Explorer/Actions/helpers.tsx +++ b/app/client/src/pages/Editor/Explorer/Actions/helpers.tsx @@ -97,8 +97,9 @@ export const ACTION_PLUGIN_MAP: Array = [ ]; export const getActionConfig = (type: PluginType) => - ACTION_PLUGIN_MAP.find((configByType: ActionGroupConfig | undefined) => - configByType?.types.includes(type), + ACTION_PLUGIN_MAP.find( + (configByType: ActionGroupConfig | undefined) => + configByType?.types.includes(type), ); export const useNewActionName = () => { diff --git a/app/client/src/pages/Editor/Explorer/JSActions/MoreJSActionsMenu.tsx b/app/client/src/pages/Editor/Explorer/JSActions/MoreJSActionsMenu.tsx index 328179681d..bb076a17f5 100644 --- a/app/client/src/pages/Editor/Explorer/JSActions/MoreJSActionsMenu.tsx +++ b/app/client/src/pages/Editor/Explorer/JSActions/MoreJSActionsMenu.tsx @@ -188,10 +188,10 @@ export function MoreJSCollectionsMenu(props: EntityContextMenuProps) { /> - {options.map((option) => { + {options.map((option, index) => { if (option.children) { return ( - + {option.label} diff --git a/app/client/src/pages/Editor/Explorer/Libraries/index.tsx b/app/client/src/pages/Editor/Explorer/Libraries/index.tsx index 2d3ba566d8..7e502331be 100644 --- a/app/client/src/pages/Editor/Explorer/Libraries/index.tsx +++ b/app/client/src/pages/Editor/Explorer/Libraries/index.tsx @@ -46,10 +46,13 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag"; import { getHasCreateActionPermission } from "@appsmith/utils/BusinessFeatures/permissionPageHelpers"; -const docsURLMap = recommendedLibraries.reduce((acc, lib) => { - acc[lib.url] = lib.docsURL; - return acc; -}, {} as Record); +const docsURLMap = recommendedLibraries.reduce( + (acc, lib) => { + acc[lib.url] = lib.docsURL; + return acc; + }, + {} as Record, +); const Library = styled.li` list-style: none; diff --git a/app/client/src/pages/Editor/Explorer/hooks.ts b/app/client/src/pages/Editor/Explorer/hooks.ts index c8a8ff5828..d0068e4bd8 100644 --- a/app/client/src/pages/Editor/Explorer/hooks.ts +++ b/app/client/src/pages/Editor/Explorer/hooks.ts @@ -123,15 +123,17 @@ export const useAppWideAndOtherDatasource = () => { const otherDatasourceInWorkspace = useOtherDatasourcesInWorkspace(); const appWideDS = useMemo( () => - [...datasourcesUsedInApplication].sort((ds1, ds2) => - ds1.name?.toLowerCase()?.localeCompare(ds2.name?.toLowerCase()), + [...datasourcesUsedInApplication].sort( + (ds1, ds2) => + ds1.name?.toLowerCase()?.localeCompare(ds2.name?.toLowerCase()), ), [datasourcesUsedInApplication], ); const otherDS = useMemo( () => - [...otherDatasourceInWorkspace].sort((ds1, ds2) => - ds1.name?.toLowerCase()?.localeCompare(ds2.name?.toLowerCase()), + [...otherDatasourceInWorkspace].sort( + (ds1, ds2) => + ds1.name?.toLowerCase()?.localeCompare(ds2.name?.toLowerCase()), ), [otherDatasourceInWorkspace], ); @@ -249,8 +251,9 @@ export const usePageIds = (searchKeyword?: string) => { }; export const useEntityUpdateState = (entityId: string) => { - return useSelector((state: AppState) => - get(state, "ui.explorer.entity.updatingEntity")?.includes(entityId), + return useSelector( + (state: AppState) => + get(state, "ui.explorer.entity.updatingEntity")?.includes(entityId), ); }; diff --git a/app/client/src/pages/Editor/Popper.tsx b/app/client/src/pages/Editor/Popper.tsx index 4a94460835..3db62f80d4 100644 --- a/app/client/src/pages/Editor/Popper.tsx +++ b/app/client/src/pages/Editor/Popper.tsx @@ -104,14 +104,14 @@ export default (props: PopperProps) => { const { boundaryParent = "viewport", - isDraggable = false, + cypressSelectorDragHandle, disablePopperEvents = false, + isDraggable = false, + onPositionChange = onPositionChangeFn, position, renderDragBlock, - onPositionChange = onPositionChangeFn, - themeMode = props.themeMode || ThemeMode.LIGHT, renderDragBlockPositions, - cypressSelectorDragHandle, + themeMode = props.themeMode || ThemeMode.LIGHT, } = props; // Memoizing to avoid rerender of draggable icon. diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/AddDeployKey.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/AddDeployKey.tsx index be6208e8e7..bca05c7d55 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/AddDeployKey.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/AddDeployKey.tsx @@ -147,11 +147,11 @@ interface AddDeployKeyProps { } function AddDeployKey({ + connectLoading = false, + errorData, + isImport = false, onChange = noop, value = {}, - isImport = false, - errorData, - connectLoading = false, }: AddDeployKeyProps) { const isModalOpen = useSelector(getIsGitSyncModalOpen); const [fetched, setFetched] = useState(false); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/ChooseGitProvider.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/ChooseGitProvider.tsx index f0ec3289b6..00d6829500 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/ChooseGitProvider.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/ChooseGitProvider.tsx @@ -66,9 +66,9 @@ interface ChooseGitProviderProps { } function ChooseGitProvider({ + isImport = false, onChange = noop, value = {}, - isImport = false, }: ChooseGitProviderProps) { const workspace = useSelector(getCurrentAppWorkspace); const isMobile = useIsMobileDevice(); diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/GenerateSSH.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/GenerateSSH.tsx index ce194d6001..181d900723 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/GenerateSSH.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/GenerateSSH.tsx @@ -44,9 +44,9 @@ interface GenerateSSHProps { } function GenerateSSH({ + errorData, onChange = noop, value = {}, - errorData, }: GenerateSSHProps) { const [isTouched, setIsTouched] = useState(false); const isInvalid = diff --git a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/Steps.tsx b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/Steps.tsx index a621ae5188..e702e2ce3e 100644 --- a/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/Steps.tsx +++ b/app/client/src/pages/Editor/gitSync/Tabs/GitConnectionV2/Steps.tsx @@ -77,9 +77,9 @@ interface StepsProps { } function Steps({ - steps = [], activeKey, onActiveKeyChange = noop, + steps = [], }: StepsProps) { const activeIndex = steps.findIndex((s) => s.key === activeKey); diff --git a/app/client/src/pages/Editor/gitSync/components/CopyButton.tsx b/app/client/src/pages/Editor/gitSync/components/CopyButton.tsx index 7bdbf5065d..1bceb97188 100644 --- a/app/client/src/pages/Editor/gitSync/components/CopyButton.tsx +++ b/app/client/src/pages/Editor/gitSync/components/CopyButton.tsx @@ -21,11 +21,11 @@ interface CopyButtonProps { } export function CopyButton({ - value, delay = 2000, + isDisabled = false, onCopy = noop, tooltipMessage, - isDisabled = false, + value, }: CopyButtonProps) { const timerRef = useRef(); const [showCopied, setShowCopied] = useState(false); diff --git a/app/client/src/pages/Editor/gitSync/components/Statusbar.tsx b/app/client/src/pages/Editor/gitSync/components/Statusbar.tsx index 155f8439f7..726231295c 100644 --- a/app/client/src/pages/Editor/gitSync/components/Statusbar.tsx +++ b/app/client/src/pages/Editor/gitSync/components/Statusbar.tsx @@ -27,9 +27,12 @@ export default function GitSyncStatusbar(props: StatusbarProps) { } } else { if (percentage < 90) { - const interval = setInterval(() => { - setPercentage((percentage) => percentage + 10); - }, (period * 1000) / 9); + const interval = setInterval( + () => { + setPercentage((percentage) => percentage + 10); + }, + (period * 1000) / 9, + ); return () => clearInterval(interval); } } diff --git a/app/client/src/pages/Editor/gitSync/hooks/useSSHKeyPair.ts b/app/client/src/pages/Editor/gitSync/hooks/useSSHKeyPair.ts index 26684aba83..03073ab82f 100644 --- a/app/client/src/pages/Editor/gitSync/hooks/useSSHKeyPair.ts +++ b/app/client/src/pages/Editor/gitSync/hooks/useSSHKeyPair.ts @@ -23,7 +23,7 @@ export const useSSHKeyPair = () => { const [failedGeneratingSSHKey, setFailedGeneratingSSHKey] = useState(false); const fetchSSHKeyPair = useCallback( - ({ onSuccessCallback = noop, onErrorCallback = noop } = {}) => { + ({ onErrorCallback = noop, onSuccessCallback = noop } = {}) => { setIsFetchingSSHKeyPair(true); dispatch( getSSHKeyPair({ @@ -44,7 +44,7 @@ export const useSSHKeyPair = () => { const generateSSHKey = useCallback( ( keyType = "ECDSA", - { onSuccessCallback = noop, onErrorCallback = noop } = {}, + { onErrorCallback = noop, onSuccessCallback = noop } = {}, ) => { // if (currentApplication?.id) { setIsGeneratingSSHKey(true); diff --git a/app/client/src/pages/Templates/TemplateView.tsx b/app/client/src/pages/Templates/TemplateView.tsx index bde92c63e0..181f57588c 100644 --- a/app/client/src/pages/Templates/TemplateView.tsx +++ b/app/client/src/pages/Templates/TemplateView.tsx @@ -52,7 +52,8 @@ export const IframeWrapper = styled.div` iframe { border-radius: 0px 0px 16px 16px; - box-shadow: 0px 20px 24px -4px rgba(16, 24, 40, 0.1), + box-shadow: + 0px 20px 24px -4px rgba(16, 24, 40, 0.1), 0px 8px 8px -4px rgba(16, 24, 40, 0.04); width: 100%; height: 734px; diff --git a/app/client/src/pages/common/SuccessTick.tsx b/app/client/src/pages/common/SuccessTick.tsx index a1c9f1a91e..d423dd50a0 100644 --- a/app/client/src/pages/common/SuccessTick.tsx +++ b/app/client/src/pages/common/SuccessTick.tsx @@ -33,7 +33,8 @@ const CheckmarkWrapper = styled.div<{ $height: string; $width: string }>` stroke-miterlimit: 10; margin: 10% auto; box-shadow: inset 0px 0px 0px #7ac142; - animation: fill 0.4s ease-in-out 0.4s forwards, + animation: + fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both; } diff --git a/app/client/src/pages/common/datasourceAuth/AuthMessage.tsx b/app/client/src/pages/common/datasourceAuth/AuthMessage.tsx index f2be6c97ce..ad8ebcabc5 100644 --- a/app/client/src/pages/common/datasourceAuth/AuthMessage.tsx +++ b/app/client/src/pages/common/datasourceAuth/AuthMessage.tsx @@ -47,9 +47,9 @@ export default function AuthMessage(props: AuthMessageProps) { calloutType = "error", datasource, description, + isInViewMode = false, pageId, style = {}, - isInViewMode = false, } = props; const dispatch = useDispatch(); const pluginType = useSelector((state: AppState) => diff --git a/app/client/src/pages/common/datasourceAuth/index.tsx b/app/client/src/pages/common/datasourceAuth/index.tsx index 04d26e0ada..c69a72a087 100644 --- a/app/client/src/pages/common/datasourceAuth/index.tsx +++ b/app/client/src/pages/common/datasourceAuth/index.tsx @@ -134,20 +134,20 @@ function DatasourceAuth({ ], formData, getSanitizedFormData, + isFormDirty, + isInsideReconnectModal, isInvalid, - pageId: pageIdProp = "", - pluginType, - pluginName, - pluginPackageName, isSaving, isTesting, - viewMode, + onCancel, + pageId: pageIdProp = "", + pluginName, + pluginPackageName, + pluginType, + scopeValue, shouldDisplayAuthMessage = true, triggerSave, - isFormDirty, - scopeValue, - isInsideReconnectModal, - onCancel, + viewMode, }: Props) { const shouldRender = !viewMode || isInsideReconnectModal; const authType = diff --git a/app/client/src/plugins/Linting/constants.ts b/app/client/src/plugins/Linting/constants.ts index c985f1a90b..5c04ff6e24 100644 --- a/app/client/src/plugins/Linting/constants.ts +++ b/app/client/src/plugins/Linting/constants.ts @@ -27,7 +27,7 @@ export const lintOptions = (globalData: Record) => // global values globals: globalData, loopfunc: true, - } as LintOptions); + }) as LintOptions; export const JS_OBJECT_START_STATEMENT = "export default"; export const INVALID_JSOBJECT_START_STATEMENT = `JSObject must start with '${JS_OBJECT_START_STATEMENT}'`; export const INVALID_JSOBJECT_START_STATEMENT_ERROR_CODE = diff --git a/app/client/src/plugins/Linting/handlers/lintService.ts b/app/client/src/plugins/Linting/handlers/lintService.ts index 9eb7c8913f..7cf77eeab4 100644 --- a/app/client/src/plugins/Linting/handlers/lintService.ts +++ b/app/client/src/plugins/Linting/handlers/lintService.ts @@ -318,9 +318,12 @@ class LintService { } function convertArrayToObject(arr: string[]) { - return arr.reduce((acc, item) => { - return { ...acc, [item]: true } as const; - }, {} as Record); + return arr.reduce( + (acc, item) => { + return { ...acc, [item]: true } as const; + }, + {} as Record, + ); } function filterDataPaths(paths: string[], entityTree: EntityTree) { diff --git a/app/client/src/reducers/entityReducers/pageListReducer.tsx b/app/client/src/reducers/entityReducers/pageListReducer.tsx index fc2bee888e..acf24c650b 100644 --- a/app/client/src/reducers/entityReducers/pageListReducer.tsx +++ b/app/client/src/reducers/entityReducers/pageListReducer.tsx @@ -59,10 +59,13 @@ export const pageListReducer = createReducer(initialState, { Array<{ pageId: string; dsl: DSL; userPermissions: string[] }> >, ) => { - const pagePermissionsMap = action.payload.reduce((acc, page) => { - acc[page.pageId] = page.userPermissions; - return acc; - }, {} as Record); + const pagePermissionsMap = action.payload.reduce( + (acc, page) => { + acc[page.pageId] = page.userPermissions; + return acc; + }, + {} as Record, + ); return { ...state, diff --git a/app/client/src/sagas/ActionExecution/geolocationSaga.ts b/app/client/src/sagas/ActionExecution/geolocationSaga.ts index f216bcca4c..53be2acb11 100644 --- a/app/client/src/sagas/ActionExecution/geolocationSaga.ts +++ b/app/client/src/sagas/ActionExecution/geolocationSaga.ts @@ -12,7 +12,10 @@ import type { } from "workers/Evaluation/fns/geolocationFns"; class GeoLocationError extends Error { - constructor(message: string, private responseData?: any) { + constructor( + message: string, + private responseData?: any, + ) { super(message); } } diff --git a/app/client/src/sagas/ActionSagas.ts b/app/client/src/sagas/ActionSagas.ts index 302b3eabc3..699b304b30 100644 --- a/app/client/src/sagas/ActionSagas.ts +++ b/app/client/src/sagas/ActionSagas.ts @@ -301,9 +301,8 @@ export function* fetchActionsSaga( { mode: "EDITOR", appId: applicationId }, ); try { - const response: ApiResponse = yield ActionAPI.fetchActions( - applicationId, - ); + const response: ApiResponse = + yield ActionAPI.fetchActions(applicationId); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { yield put({ @@ -727,9 +726,8 @@ export function* refactorActionName( newName: newName, }); - const isRefactorSuccessful: boolean = yield validateResponse( - refactorResponse, - ); + const isRefactorSuccessful: boolean = + yield validateResponse(refactorResponse); const currentPageId: string = yield select(getCurrentPageId); diff --git a/app/client/src/sagas/ApiPaneSagas.ts b/app/client/src/sagas/ApiPaneSagas.ts index 9ee5664afd..4dae512000 100644 --- a/app/client/src/sagas/ApiPaneSagas.ts +++ b/app/client/src/sagas/ApiPaneSagas.ts @@ -666,7 +666,7 @@ function* handleCreateNewApiActionSaga( }>, ) { const workspaceId: string = yield select(getCurrentWorkspaceId); - const { pageId, apiType = PluginPackageName.REST_API } = action.payload; + const { apiType = PluginPackageName.REST_API, pageId } = action.payload; const pluginId: string = yield select(getPluginIdOfPackageName, apiType); // Default Config is Rest Api Plugin Config let defaultConfig = DEFAULT_CREATE_API_CONFIG; diff --git a/app/client/src/sagas/AppThemingSaga.tsx b/app/client/src/sagas/AppThemingSaga.tsx index 13c16026c3..3855bc7f6a 100644 --- a/app/client/src/sagas/AppThemingSaga.tsx +++ b/app/client/src/sagas/AppThemingSaga.tsx @@ -74,9 +74,8 @@ export function* initAppTheming() { export function* fetchAppThemes(action: ReduxAction) { try { const { applicationId } = action.payload; - const response: ApiResponse = yield ThemingApi.fetchThemes( - applicationId, - ); + const response: ApiResponse = + yield ThemingApi.fetchThemes(applicationId); yield put({ type: ReduxActionTypes.FETCH_APP_THEMES_SUCCESS, @@ -294,9 +293,8 @@ function* closeisBetaCardShown() { */ function* resetTheme() { try { - const canvasWidgets: CanvasWidgetsReduxState = yield select( - getCanvasWidgets, - ); + const canvasWidgets: CanvasWidgetsReduxState = + yield select(getCanvasWidgets); const propertiesToUpdate: UpdateWidgetPropertyPayload[] = getPropertiesToUpdateForReset(canvasWidgets); @@ -313,9 +311,8 @@ function* setDefaultSelectedThemeOnError() { const applicationId: string = yield select(getCurrentApplicationId); try { // Fetch all system themes - const response: ApiResponse = yield ThemingApi.fetchThemes( - applicationId, - ); + const response: ApiResponse = + yield ThemingApi.fetchThemes(applicationId); // Gets default theme const theme = find(response.data, { name: "Default" }); diff --git a/app/client/src/sagas/AutoLayoutUpdateSagas.tsx b/app/client/src/sagas/AutoLayoutUpdateSagas.tsx index 1032caae51..32a20323cc 100644 --- a/app/client/src/sagas/AutoLayoutUpdateSagas.tsx +++ b/app/client/src/sagas/AutoLayoutUpdateSagas.tsx @@ -149,9 +149,8 @@ export function* updateLayoutSystemTypeSaga( actionPayload: ReduxAction, ) { try { - const currLayoutSystemType: LayoutSystemTypes = yield select( - getLayoutSystemType, - ); + const currLayoutSystemType: LayoutSystemTypes = + yield select(getLayoutSystemType); const payloadLayoutSystemType = actionPayload.payload; if (currLayoutSystemType === payloadLayoutSystemType) return; @@ -194,9 +193,8 @@ export function* recalculateAutoLayoutColumnsAndSave( widgets?: CanvasWidgetsReduxState, ) { const layoutSystemType: LayoutSystemTypes = yield select(getLayoutSystemType); - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); yield put( updateLayoutForMobileBreakpointAction( diff --git a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts index 2354a0c9d3..c4078a3ef1 100644 --- a/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts +++ b/app/client/src/sagas/CanvasSagas/DraggingCanvasSagas.ts @@ -72,9 +72,8 @@ export function* getCanvasSizeAfterWidgetMove( let mainCanvasMinHeight; let canvasParentMinHeight = canvasWidget.minHeight; if (canvasWidgetId === MAIN_CONTAINER_WIDGET_ID) { - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); mainCanvasMinHeight = mainCanvasProps?.height; } else if (canvasWidget.parentId) { const parent: FlattenedWidgetProps = yield select( @@ -335,9 +334,8 @@ function* moveWidgetsSaga( ); } - const layoutSystemType: LayoutSystemTypes = yield select( - getLayoutSystemType, - ); + const layoutSystemType: LayoutSystemTypes = + yield select(getLayoutSystemType); let updatedWidgets: CanvasWidgetsReduxState = { ...allWidgets }; if (layoutSystemType === LayoutSystemTypes.AUTO) { /** diff --git a/app/client/src/sagas/DebuggerSagas.ts b/app/client/src/sagas/DebuggerSagas.ts index 8aa2f80ae3..4bf9b77c6f 100644 --- a/app/client/src/sagas/DebuggerSagas.ts +++ b/app/client/src/sagas/DebuggerSagas.ts @@ -453,9 +453,8 @@ function* logDebuggerErrorAnalyticsSaga( function* addDebuggerErrorLogsSaga(action: ReduxAction) { const errorLogs = action.payload; - const currentDebuggerErrors: Record = yield select( - getDebuggerErrors, - ); + const currentDebuggerErrors: Record = + yield select(getDebuggerErrors); const appMode: ReturnType = yield select(getAppMode); yield put(debuggerLogInit(errorLogs)); const validErrorLogs = errorLogs.filter((log) => log.source && log.id); @@ -585,9 +584,8 @@ function* deleteDebuggerErrorLogsSaga( action: ReduxAction<{ id: string; analytics: Log["analytics"] }[]>, ) { const { payload } = action; - const currentDebuggerErrors: Record = yield select( - getDebuggerErrors, - ); + const currentDebuggerErrors: Record = + yield select(getDebuggerErrors); const appMode: ReturnType = yield select(getAppMode); const existingErrorPayloads = payload.filter((item) => currentDebuggerErrors.hasOwnProperty(item.id), diff --git a/app/client/src/sagas/EvaluationsSaga.ts b/app/client/src/sagas/EvaluationsSaga.ts index 6078ed9cab..93de0767b8 100644 --- a/app/client/src/sagas/EvaluationsSaga.ts +++ b/app/client/src/sagas/EvaluationsSaga.ts @@ -130,16 +130,16 @@ export function* updateDataTreeHandler( errors, evalMetaUpdates = [], evaluationOrder, - reValidatedPaths, isCreateFirstTree = false, isNewWidgetAdded, jsUpdates, + jsVarsCreatedEvent, logs, removedPaths, + reValidatedPaths, staleMetaIds, undefinedEvalValuesMap, unEvalUpdates, - jsVarsCreatedEvent, updates, } = evalTreeResponse; @@ -243,12 +243,10 @@ export function* evaluateTreeSaga( > = yield select(getAllActionValidationConfig); const unevalTree = unEvalAndConfigTree.unEvalTree; const widgets: ReturnType = yield select(getWidgets); - const metaWidgets: ReturnType = yield select( - getMetaWidgets, - ); - const theme: ReturnType = yield select( - getSelectedAppTheme, - ); + const metaWidgets: ReturnType = + yield select(getMetaWidgets); + const theme: ReturnType = + yield select(getSelectedAppTheme); const toPrintConfigTree = unEvalAndConfigTree.configTree; log.debug({ unevalTree, configTree: toPrintConfigTree }); PerformanceTracker.startAsyncTracking( @@ -600,9 +598,8 @@ function* evaluationChangeListenerSaga(): any { evalQueueBuffer(), ); while (true) { - const action: EvaluationReduxAction = yield take( - evtActionChannel, - ); + const action: EvaluationReduxAction = + yield take(evtActionChannel); yield call(evalAndLintingHandler, true, action, { shouldReplay: get(action, "payload.shouldReplay"), diff --git a/app/client/src/sagas/FormEvaluationSaga.ts b/app/client/src/sagas/FormEvaluationSaga.ts index 7151fb41f5..adf5c383ec 100644 --- a/app/client/src/sagas/FormEvaluationSaga.ts +++ b/app/client/src/sagas/FormEvaluationSaga.ts @@ -270,9 +270,8 @@ function* formEvaluationChangeListenerSaga() { type: ReduxActionTypes.FORM_EVALUATION_EMPTY_BUFFER, }); } - const action: ReduxAction = yield take( - formEvalChannel, - ); + const action: ReduxAction = + yield take(formEvalChannel); yield call(setFormEvaluationSagaAsync, action); } } diff --git a/app/client/src/sagas/GitSyncSagas.ts b/app/client/src/sagas/GitSyncSagas.ts index 9408ddc60f..47df5af578 100644 --- a/app/client/src/sagas/GitSyncSagas.ts +++ b/app/client/src/sagas/GitSyncSagas.ts @@ -1072,9 +1072,8 @@ function* watchGitRequests() { ); while (true) { - const { type, ...args }: ReduxAction = yield take( - gitActionChannel, - ); + const { type, ...args }: ReduxAction = + yield take(gitActionChannel); yield call(gitRequestActions[type], { type, ...args }); } } diff --git a/app/client/src/sagas/JSActionSagas.ts b/app/client/src/sagas/JSActionSagas.ts index 51cfc162e7..16d2ba8ed2 100644 --- a/app/client/src/sagas/JSActionSagas.ts +++ b/app/client/src/sagas/JSActionSagas.ts @@ -361,9 +361,8 @@ export function* refactorJSObjectName( newName: newName, }); - const isRefactorSuccessful: boolean = yield validateResponse( - refactorResponse, - ); + const isRefactorSuccessful: boolean = + yield validateResponse(refactorResponse); const currentPageId: string | undefined = yield select(getCurrentPageId); diff --git a/app/client/src/sagas/JSLibrarySaga.ts b/app/client/src/sagas/JSLibrarySaga.ts index 0e1857ab9f..17d57a7101 100644 --- a/app/client/src/sagas/JSLibrarySaga.ts +++ b/app/client/src/sagas/JSLibrarySaga.ts @@ -404,9 +404,8 @@ function* startInstallationRequestChannel() { ReduxActionTypes.INSTALL_LIBRARY_INIT, ]); while (true) { - const action: ReduxAction> = yield take( - queueInstallChannel, - ); + const action: ReduxAction> = + yield take(queueInstallChannel); yield put({ type: ReduxActionTypes.INSTALL_LIBRARY_START, payload: action.payload.url, diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts index d19df1b87b..4a8c004622 100644 --- a/app/client/src/sagas/JSPaneSagas.ts +++ b/app/client/src/sagas/JSPaneSagas.ts @@ -568,9 +568,8 @@ function* handleRefactorJSActionNameSaga( const refactorResponse: ApiResponse = yield JSActionAPI.updateJSCollectionActionRefactor(requestData); - const isRefactorSuccessful: boolean = yield validateResponse( - refactorResponse, - ); + const isRefactorSuccessful: boolean = + yield validateResponse(refactorResponse); const currentPageId: string | undefined = yield select(getCurrentPageId); diff --git a/app/client/src/sagas/ModalSagas.ts b/app/client/src/sagas/ModalSagas.ts index 036e4501c8..b2f5dbc06a 100644 --- a/app/client/src/sagas/ModalSagas.ts +++ b/app/client/src/sagas/ModalSagas.ts @@ -109,9 +109,8 @@ export function* createModalSaga(action: ReduxAction<{ modalName: string }>) { export function* showModalByNameSaga( action: ReduxAction<{ modalName: string }>, ) { - const widgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const widgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const modal: FlattenedWidgetProps | undefined = Object.values(widgets).find( (widget: FlattenedWidgetProps) => widget.widgetName === action.payload.modalName, diff --git a/app/client/src/sagas/OnboardingSagas.ts b/app/client/src/sagas/OnboardingSagas.ts index 011f28a1c3..ff743506fa 100644 --- a/app/client/src/sagas/OnboardingSagas.ts +++ b/app/client/src/sagas/OnboardingSagas.ts @@ -186,9 +186,8 @@ function* setCurrentStepSaga(action: ReduxAction) { function* setUpTourAppSaga() { yield put(setPreviewModeAction(false)); // Delete the container widget - const widgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const widgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const containerWidget = Object.values(widgets).find( (widget) => widget.type === "CONTAINER_WIDGET", ); @@ -281,9 +280,8 @@ function* addOnboardingWidget(action: ReduxAction>) { // Wait for widget names to be updated // Updating widget names here as widget blueprints don't take widget names yield take(ReduxActionTypes.SAVE_PAGE_SUCCESS); - const widgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const widgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const nameInput = Object.values(widgets).find( (widget) => widget.widgetName === "Input1", @@ -331,9 +329,8 @@ function* addOnboardingWidget(action: ReduxAction>) { // Update button widget text function* updateWidgetTextSaga() { - const widgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const widgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const buttonWidget = Object.values(widgets).find( (widget) => widget.type === "BUTTON_WIDGET", ); @@ -373,9 +370,8 @@ function* endGuidedTourSaga(action: ReduxAction) { function* selectWidgetSaga( action: ReduxAction<{ widgetName: string; propertyName?: string }>, ) { - const widgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const widgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const widget = Object.values(widgets).find((widget) => { return widget.widgetName === action.payload.widgetName; }); diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx index 363d4aca8e..5c5e8263e6 100644 --- a/app/client/src/sagas/PageSagas.tsx +++ b/app/client/src/sagas/PageSagas.tsx @@ -171,10 +171,13 @@ export function* fetchPageListSaga( const response: FetchPageListResponse = yield call(apiCall, applicationId); const isValidResponse: boolean = yield validateResponse(response); const prevPagesState: Page[] = yield select(getPageList); - const pagePermissionsMap = prevPagesState.reduce((acc, page) => { - acc[page.pageId] = page.userPermissions ?? []; - return acc; - }, {} as Record); + const pagePermissionsMap = prevPagesState.reduce( + (acc, page) => { + acc[page.pageId] = page.userPermissions ?? []; + return acc; + }, + {} as Record, + ); if (isValidResponse) { const workspaceId = response.data.workspaceId; const pages: Page[] = response.data.pages.map((page) => ({ @@ -292,9 +295,8 @@ export function* handleFetchedPage({ isFirstLoad?: boolean; }) { const isAutoLayout: boolean = yield select(getIsAutoLayout); - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); const isValidResponse: boolean = yield validateResponse(fetchPageResponse); const willPageBeMigrated = checkIfMigrationIsNeeded(fetchPageResponse); const lastUpdatedTime = getLastUpdateTime(fetchPageResponse); @@ -705,9 +707,8 @@ export function* createNewPageFromEntity( ) { try { const isAutoLayout: boolean = yield select(getIsAutoLayout); - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); // Default layout is extracted by adding dynamically computed properties like min-height. const defaultPageLayouts = [ { @@ -748,9 +749,8 @@ export function* createPageSaga( try { const guidedTourEnabled: boolean = yield select(inGuidedTour); const isAutoLayout: boolean = yield select(getIsAutoLayout); - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); // Prevent user from creating a new page during the guided tour if (guidedTourEnabled) { @@ -1130,9 +1130,8 @@ export function* setDataUrl() { export function* fetchPageDSLSaga(pageId: string) { try { const isAutoLayout: boolean = yield select(getIsAutoLayout); - const mainCanvasProps: MainCanvasReduxState = yield select( - getMainCanvasProps, - ); + const mainCanvasProps: MainCanvasReduxState = + yield select(getMainCanvasProps); const fetchPageResponse: FetchPageResponse = yield call(PageApi.fetchPage, { id: pageId, }); diff --git a/app/client/src/sagas/PostEvaluationSagas.ts b/app/client/src/sagas/PostEvaluationSagas.ts index d8f859e7e8..dfb89089f8 100644 --- a/app/client/src/sagas/PostEvaluationSagas.ts +++ b/app/client/src/sagas/PostEvaluationSagas.ts @@ -222,9 +222,8 @@ export function* evalErrorHandler( removedPaths?: Array<{ entityId: string; fullpath: string }>, ) { if (dataTree && evaluationOrder && configTree && reValidatedPaths) { - const currentDebuggerErrors: Record = yield select( - getDebuggerErrors, - ); + const currentDebuggerErrors: Record = + yield select(getDebuggerErrors); const evalAndValidationOrder = new Set([ ...reValidatedPaths, diff --git a/app/client/src/sagas/ProvidersSaga.ts b/app/client/src/sagas/ProvidersSaga.ts index 368ecfcc66..a9bd13e6cf 100644 --- a/app/client/src/sagas/ProvidersSaga.ts +++ b/app/client/src/sagas/ProvidersSaga.ts @@ -124,9 +124,8 @@ export function* fetchProvidersWithCategorySaga( ) { try { const request: FetchProviderWithCategoryRequest = action.payload; - const response: Providers = yield ProvidersApi.fetchProvidersWithCategory( - request, - ); + const response: Providers = + yield ProvidersApi.fetchProvidersWithCategory(request); const isValidResponse: boolean = yield validateResponse(response); diff --git a/app/client/src/sagas/QueryPaneSagas.ts b/app/client/src/sagas/QueryPaneSagas.ts index 66f78bf805..ad5401dbf8 100644 --- a/app/client/src/sagas/QueryPaneSagas.ts +++ b/app/client/src/sagas/QueryPaneSagas.ts @@ -342,9 +342,8 @@ function* handleQueryCreatedSaga(actionPayload: ReduxAction) { actionPayload.payload; const pageId: string = yield select(getCurrentPageId); if (pluginType !== PluginType.DB && pluginType !== PluginType.REMOTE) return; - const pluginTemplates: Record = yield select( - getPluginTemplates, - ); + const pluginTemplates: Record = + yield select(getPluginTemplates); const queryTemplate = pluginTemplates[pluginId]; // Do not show template view if the query has body(code) or if there are no templates or if the plugin is MongoDB const showTemplate = !( diff --git a/app/client/src/sagas/SnapshotSagas.ts b/app/client/src/sagas/SnapshotSagas.ts index 2ca9bacfa2..e95fc19624 100644 --- a/app/client/src/sagas/SnapshotSagas.ts +++ b/app/client/src/sagas/SnapshotSagas.ts @@ -84,9 +84,8 @@ function* restoreApplicationFromSnapshotSaga() { applicationId, }); - const currentLayoutSystemType: LayoutSystemTypes = yield select( - getLayoutSystemType, - ); + const currentLayoutSystemType: LayoutSystemTypes = + yield select(getLayoutSystemType); const isValidResponse: boolean = yield validateResponse( response, @@ -170,9 +169,8 @@ export function* deleteApplicationSnapshotSaga() { //Saga to update snapshot details by fetching info from backend function* updateSnapshotDetailsSaga() { try { - const snapShotDetails: { updatedTime: Date } | undefined = yield call( - fetchSnapshotSaga, - ); + const snapShotDetails: { updatedTime: Date } | undefined = + yield call(fetchSnapshotSaga); yield put( updateSnapshotDetails( snapShotDetails && snapShotDetails.updatedTime diff --git a/app/client/src/sagas/WidgetDeletionSagas.ts b/app/client/src/sagas/WidgetDeletionSagas.ts index b0866e552e..485509f422 100644 --- a/app/client/src/sagas/WidgetDeletionSagas.ts +++ b/app/client/src/sagas/WidgetDeletionSagas.ts @@ -122,9 +122,8 @@ function* deleteTabChildSaga( function* deleteSagaInit(deleteAction: ReduxAction) { const { widgetId } = deleteAction.payload; - const selectedWidget: FlattenedWidgetProps | undefined = yield select( - getSelectedWidget, - ); + const selectedWidget: FlattenedWidgetProps | undefined = + yield select(getSelectedWidget); const selectedWidgets: string[] = yield select(getSelectedWidgets); const guidedTourEnabled: boolean = yield select(inGuidedTour); const isExploring: boolean = yield select(isExploringSelector); @@ -209,9 +208,8 @@ function* deleteSaga(deleteAction: ReduxAction) { const { disallowUndo, isShortcut } = deleteAction.payload; if (!widgetId) { - const selectedWidget: FlattenedWidgetProps | undefined = yield select( - getSelectedWidget, - ); + const selectedWidget: FlattenedWidgetProps | undefined = + yield select(getSelectedWidget); if (!selectedWidget) return; // if widget is not deletable, don't do anything diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index e99b8553ab..028c461e2f 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -209,9 +209,8 @@ export function* resizeSaga(resizeAction: ReduxAction) { widgetId, } = resizeAction.payload; - const layoutSystemType: LayoutSystemTypes = yield select( - getLayoutSystemType, - ); + const layoutSystemType: LayoutSystemTypes = + yield select(getLayoutSystemType); const mainCanvasWidth: number = yield select(getCanvasWidth); widget = { ...widget, @@ -689,7 +688,7 @@ export function* getPropertiesUpdatedWidget( ) { const { dynamicUpdates, updates, widgetId } = updatesObj; - const { modify = {}, remove = [], postUpdateAction, triggerPaths } = updates; + const { modify = {}, postUpdateAction, remove = [], triggerPaths } = updates; const stateWidget: WidgetProps = yield select(getWidget, widgetId); @@ -990,9 +989,8 @@ function* createSelectedWidgetsCopy( * @returns */ function* copyWidgetSaga(action: ReduxAction<{ isShortcut: boolean }>) { - const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const selectedWidgets: string[] = yield select(getSelectedWidgets); if (!selectedWidgets) { toast.show(createMessage(ERROR_WIDGET_COPY_NO_WIDGET_SELECTED), { @@ -1834,9 +1832,8 @@ function* pasteWidgetSaga( !flexLayers || flexLayers.length <= 0) ) { - const metaProps: Record = yield select( - getWidgetsMeta, - ); + const metaProps: Record = + yield select(getWidgetsMeta); if (widget.widgetId === widgetIdMap[copiedWidget.widgetId]) widgets = pasteWidgetInFlexLayers( widgets, @@ -1955,9 +1952,8 @@ function* pasteWidgetSaga( } function* cutWidgetSaga() { - const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const selectedWidgets: string[] = yield select(getSelectedWidgets); if (!selectedWidgets) { toast.show(createMessage(ERROR_WIDGET_CUT_NO_WIDGET_SELECTED), { diff --git a/app/client/src/sagas/WidgetOperationUtils.ts b/app/client/src/sagas/WidgetOperationUtils.ts index fdfaa7a47f..9d7693ef84 100644 --- a/app/client/src/sagas/WidgetOperationUtils.ts +++ b/app/client/src/sagas/WidgetOperationUtils.ts @@ -671,13 +671,11 @@ export const getSelectedWidgetWhenPasting = function* () { const { widgets: copiedWidgetGroups }: { widgets: CopiedWidgetGroup[] } = yield getCopiedWidgets(); - let selectedWidget: FlattenedWidgetProps | undefined = yield select( - getSelectedWidget, - ); + let selectedWidget: FlattenedWidgetProps | undefined = + yield select(getSelectedWidget); - const focusedWidget: FlattenedWidgetProps | undefined = yield select( - getFocusedWidget, - ); + const focusedWidget: FlattenedWidgetProps | undefined = + yield select(getFocusedWidget); selectedWidget = getSelectedWidgetIfPastingIntoListWidget( canvasWidgets, @@ -1490,9 +1488,8 @@ export function getNextWidgetName( * @returns */ export function* createWidgetCopy(widget: FlattenedWidgetProps) { - const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = yield select( - getWidgets, - ); + const allWidgets: { [widgetId: string]: FlattenedWidgetProps } = + yield select(getWidgets); const widgetsToStore = getAllWidgetsInTree(widget.widgetId, allWidgets); return { widgetId: widget.widgetId, diff --git a/app/client/src/sagas/WidgetSelectionSagas.ts b/app/client/src/sagas/WidgetSelectionSagas.ts index 60741561b3..e574d96a15 100644 --- a/app/client/src/sagas/WidgetSelectionSagas.ts +++ b/app/client/src/sagas/WidgetSelectionSagas.ts @@ -56,10 +56,10 @@ import { APP_MODE } from "entities/App"; function* selectWidgetSaga(action: ReduxAction) { try { const { - payload = [], - selectionRequestType, invokedBy, pageId, + payload = [], + selectionRequestType, } = action.payload; if (payload.some(isInvalidSelectionRequest)) { diff --git a/app/client/src/sagas/autoHeightSagas/widgets.ts b/app/client/src/sagas/autoHeightSagas/widgets.ts index 34a0f12505..573921b022 100644 --- a/app/client/src/sagas/autoHeightSagas/widgets.ts +++ b/app/client/src/sagas/autoHeightSagas/widgets.ts @@ -243,9 +243,8 @@ export function* updateWidgetAutoHeightSaga( // Get the canvas level map from the store // This map tells us the nesting of each canvas widget in the DSL. // MainContainer's level is 0. - const canvasLevelMap: CanvasLevelsReduxState = yield select( - getCanvasLevelMap, - ); + const canvasLevelMap: CanvasLevelsReduxState = + yield select(getCanvasLevelMap); // 1. Get all siblings together. // Get all updates for that level. diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index 2f8bd2080e..4c4763dd49 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -184,11 +184,14 @@ export const getCurrentPageDescription = createSelector( ); export const selectPageSlugToIdMap = createSelector(getPageList, (pages) => - pages.reduce((acc, page: Page) => { - // Comeback - acc[page.pageId] = page.slug || ""; - return acc; - }, {} as Record), + pages.reduce( + (acc, page: Page) => { + // Comeback + acc[page.pageId] = page.slug || ""; + return acc; + }, + {} as Record, + ), ); export const getCurrentApplication = (state: AppState) => diff --git a/app/client/src/selectors/themeSelectors.tsx b/app/client/src/selectors/themeSelectors.tsx index f99a127c1b..e61cfdf255 100644 --- a/app/client/src/selectors/themeSelectors.tsx +++ b/app/client/src/selectors/themeSelectors.tsx @@ -12,8 +12,10 @@ export const lightTheme = { ...theme, colors: { ...theme.colors, ...light } }; const darkTheme = { ...theme, colors: { ...theme.colors, ...dark } }; // Only for usage with ThemeProvider -export const getThemeDetails = (state: AppState, themeMode: ThemeMode): Theme => - themeMode === ThemeMode.LIGHT ? lightTheme : darkTheme; +export const getThemeDetails = ( + state: AppState, + themeMode: ThemeMode, +): Theme => (themeMode === ThemeMode.LIGHT ? lightTheme : darkTheme); export const getTheme = (themeMode: ThemeMode) => { const colors = themeMode === ThemeMode.LIGHT ? light : dark; diff --git a/app/client/src/utils/hooks/dragResizeHooks.tsx b/app/client/src/utils/hooks/dragResizeHooks.tsx index 6c61a5d922..b04ce458b9 100644 --- a/app/client/src/utils/hooks/dragResizeHooks.tsx +++ b/app/client/src/utils/hooks/dragResizeHooks.tsx @@ -109,11 +109,11 @@ export const useWidgetDragResize = () => { ), setDraggingState: useCallback( ({ - isDragging, - dragGroupActualParent = "", - draggingGroupCenter = {}, - startPoints, draggedOn, + draggingGroupCenter = {}, + dragGroupActualParent = "", + isDragging, + startPoints, }: { isDragging: boolean; dragGroupActualParent?: string; diff --git a/app/client/src/utils/storage.ts b/app/client/src/utils/storage.ts index 4be8f3717b..d6bf0a21ae 100644 --- a/app/client/src/utils/storage.ts +++ b/app/client/src/utils/storage.ts @@ -716,15 +716,15 @@ export const initAppKbState = async ( const appKbState = { checksum, - pageSlugs: pageSlugs.reduce((acc, pageSlug) => { - acc[pageSlug] = { - hasReacted: false, - }; - return acc; - }, {} as Record) as Record< - string, - { hasReacted: boolean } - >, + pageSlugs: pageSlugs.reduce( + (acc, pageSlug) => { + acc[pageSlug] = { + hasReacted: false, + }; + return acc; + }, + {} as Record, + ) as Record, }; aiKBApplicationMap[appId] = appKbState; diff --git a/app/client/src/widgets/ButtonWidgetV2/component/Container.tsx b/app/client/src/widgets/ButtonWidgetV2/component/Container.tsx index a09eb4e7dc..45780d680d 100644 --- a/app/client/src/widgets/ButtonWidgetV2/component/Container.tsx +++ b/app/client/src/widgets/ButtonWidgetV2/component/Container.tsx @@ -7,16 +7,15 @@ const StyledContainer = styled.div` height: 100%; position: relative; - ${({ maxWidth, minHeight, minWidth }) => - css` - & [data-button] { - display: flex; - width: auto; - ${minWidth ? `min-width: ${minWidth}px;` : ""} - ${minHeight ? `min-height: ${minHeight}px;` : ""} + ${({ maxWidth, minHeight, minWidth }) => css` + & [data-button] { + display: flex; + width: auto; + ${minWidth ? `min-width: ${minWidth}px;` : ""} + ${minHeight ? `min-height: ${minHeight}px;` : ""} ${maxWidth ? `max-width: ${maxWidth}px;` : ""} - } - `} + } + `} .grecaptcha-badge { visibility: hidden; diff --git a/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV2.tsx b/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV2.tsx index fab1348d9c..6c230d84d3 100644 --- a/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV2.tsx +++ b/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV2.tsx @@ -19,12 +19,12 @@ export function RecaptchaV2(props: RecaptchaV2Props) { props.handleRecaptchaV2Loading && props.handleRecaptchaV2Loading(isloading); }; const { - isLoading, isDisabled, - recaptchaKey, - onRecaptchaSubmitSuccess, - onRecaptchaSubmitError = noop, + isLoading, onPress: onClickProp, + onRecaptchaSubmitError = noop, + onRecaptchaSubmitSuccess, + recaptchaKey, } = props; const onClick = () => { if (isDisabled) return onClickProp; diff --git a/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV3.tsx b/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV3.tsx index b37f11ae67..eb7229dc6a 100644 --- a/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV3.tsx +++ b/app/client/src/widgets/ButtonWidgetV2/component/RecaptchaV3.tsx @@ -17,10 +17,10 @@ export function RecaptchaV3(props: RecaptchaV3Props) { }; const { - recaptchaKey, onPress: onClickProp, - onRecaptchaSubmitSuccess, onRecaptchaSubmitError = noop, + onRecaptchaSubmitSuccess, + recaptchaKey, } = props; const onClick: ButtonComponentProps["onPress"] = () => { diff --git a/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx b/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx index 4b70d6d83e..6d34dfc074 100644 --- a/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx +++ b/app/client/src/widgets/CurrencyInputWidget/component/CurrencyCodeDropdown.tsx @@ -101,8 +101,8 @@ export const PopoverStyles = createGlobalStyle<{ } .${props.portalClassName} .${Classes.INPUT}:focus, .${ - props.portalClassName - } .${Classes.INPUT}:active { + props.portalClassName + } .${Classes.INPUT}:active { border: 1px solid ${props.accentColor} !important; box-shadow: 0px 0px 0px 2px ${lightenColor(props.accentColor)} !important; } diff --git a/app/client/src/widgets/InputWidget/component/CurrencyCodeDropdown.tsx b/app/client/src/widgets/InputWidget/component/CurrencyCodeDropdown.tsx index 817a072caf..ddb0f74784 100644 --- a/app/client/src/widgets/InputWidget/component/CurrencyCodeDropdown.tsx +++ b/app/client/src/widgets/InputWidget/component/CurrencyCodeDropdown.tsx @@ -66,8 +66,8 @@ export const PopoverStyles = createGlobalStyle<{ } .${props.portalClassName} .${Classes.INPUT}:focus, .${ - props.portalClassName - } .${Classes.INPUT}:active { + props.portalClassName + } .${Classes.INPUT}:active { border: 1px solid ${props.accentColor} !important; } diff --git a/app/client/src/widgets/InputWidget/component/ISDCodeDropdown.tsx b/app/client/src/widgets/InputWidget/component/ISDCodeDropdown.tsx index e6bbf5797d..0c987adc04 100644 --- a/app/client/src/widgets/InputWidget/component/ISDCodeDropdown.tsx +++ b/app/client/src/widgets/InputWidget/component/ISDCodeDropdown.tsx @@ -61,8 +61,8 @@ export const PopoverStyles = createGlobalStyle<{ } .${props.portalClassName} .${Classes.INPUT}:focus, .${ - props.portalClassName - } .${Classes.INPUT}:active { + props.portalClassName + } .${Classes.INPUT}:active { border: 1px solid ${props.accentColor} !important; box-shadow: 0px 0px 0px 3px ${lightenColor( props.accentColor, diff --git a/app/client/src/widgets/JSONFormWidget/constants.ts b/app/client/src/widgets/JSONFormWidget/constants.ts index 14abbab5e2..44dfc15e92 100644 --- a/app/client/src/widgets/JSONFormWidget/constants.ts +++ b/app/client/src/widgets/JSONFormWidget/constants.ts @@ -40,11 +40,14 @@ export type FieldTypeKey = keyof typeof FieldType; export const inverseFieldType = Object.entries(FieldType).reduce< Record ->((previousValue, currentValue) => { - const [key, value] = currentValue; - previousValue[value] = key as FieldTypeKey; - return previousValue; -}, {} as Record); +>( + (previousValue, currentValue) => { + const [key, value] = currentValue; + previousValue[value] = key as FieldTypeKey; + return previousValue; + }, + {} as Record, +); export enum DataType { STRING = "string", diff --git a/app/client/src/widgets/JSONFormWidget/schemaParser.ts b/app/client/src/widgets/JSONFormWidget/schemaParser.ts index da913cf137..28c6f426d7 100644 --- a/app/client/src/widgets/JSONFormWidget/schemaParser.ts +++ b/app/client/src/widgets/JSONFormWidget/schemaParser.ts @@ -367,7 +367,7 @@ class SchemaParser { * @param schema Previous generated schema if present. */ static parse = (widgetName: string, options: ParseOptions) => { - const { currSourceData, schema = {}, fieldThemeStylesheets } = options; + const { currSourceData, fieldThemeStylesheets, schema = {} } = options; if (!currSourceData) return { schema, modifiedSchemaItems: {}, removedSchemaItems: [] }; @@ -709,9 +709,9 @@ class SchemaParser { static convertObjectToSchema = ({ baseSchemaPath, currSourceData, - removedSchemaItems, modifiedSchemaItems, prevSchema = {}, + removedSchemaItems, sourceDataPath, ...rest }: Omit): Schema => { diff --git a/app/client/src/widgets/JSONFormWidget/widget/index.tsx b/app/client/src/widgets/JSONFormWidget/widget/index.tsx index 3565e647a0..4a3ed77fa7 100644 --- a/app/client/src/widgets/JSONFormWidget/widget/index.tsx +++ b/app/client/src/widgets/JSONFormWidget/widget/index.tsx @@ -270,9 +270,10 @@ class JSONFormWidget extends BaseWidget< (column) => `${column.name}`, ); modify = { - sourceData: `{{_.pick(${ - formConfig?.otherFields?.defaultValues - },${selectedColumnNames.map((name) => `'${name}'`).join(",")})}}`, + sourceData: `{{_.pick(${formConfig?.otherFields + ?.defaultValues},${selectedColumnNames + .map((name) => `'${name}'`) + .join(",")})}}`, title: `Update Row ${primaryKey} {{${formConfig?.otherFields?.defaultValues}.${primaryKey}}}`, onSubmit: queryConfig?.update.run, }; diff --git a/app/client/src/widgets/ListWidgetV2/MetaWidgetGenerator.ts b/app/client/src/widgets/ListWidgetV2/MetaWidgetGenerator.ts index 3c52019e8f..d5ef0281ee 100644 --- a/app/client/src/widgets/ListWidgetV2/MetaWidgetGenerator.ts +++ b/app/client/src/widgets/ListWidgetV2/MetaWidgetGenerator.ts @@ -914,8 +914,8 @@ class MetaWidgetGenerator { } return newObj; })(${metaContainerName}.data, ${JSON.stringify( - BLACKLISTED_ENTITY_DEFINITION_IN_LEVEL_DATA[type], - )} ) + BLACKLISTED_ENTITY_DEFINITION_IN_LEVEL_DATA[type], + )} ) }}`, }, }, @@ -1665,8 +1665,8 @@ class MetaWidgetGenerator { // "Input1: { value: List1_Input1_1.value, text: List1_Input1_1.text }" dependantBinding[templateWidgetName] = ` ${templateWidgetName}: {${ - dependantMetaWidget?.entityDefinition || "" - }} + dependantMetaWidget?.entityDefinition || "" + }} `; } }); diff --git a/app/client/src/widgets/ListWidgetV2/component/ListPagination.tsx b/app/client/src/widgets/ListWidgetV2/component/ListPagination.tsx index 0897d9075e..095988f529 100644 --- a/app/client/src/widgets/ListWidgetV2/component/ListPagination.tsx +++ b/app/client/src/widgets/ListWidgetV2/component/ListPagination.tsx @@ -439,7 +439,7 @@ export function ServerSideListPagination(props: ServerSideListPaginationProps) { title="Previous Page" >