From 1b858bcf5ce5289d3ebbb07fcaf89af7a03a5efe Mon Sep 17 00:00:00 2001 From: Favour Ohanekwu Date: Fri, 21 Jan 2022 04:08:40 -0800 Subject: [PATCH] fix: Remove private widgets from autocompletion (#10535) --- app/client/src/sagas/PostEvaluationSagas.ts | 9 +- app/client/src/workers/evaluation.test.ts | 2 + .../src/workers/evaluationUtils.test.ts | 175 +++++++++++++++++- app/client/src/workers/evaluationUtils.ts | 24 +++ 4 files changed, 207 insertions(+), 3 deletions(-) diff --git a/app/client/src/sagas/PostEvaluationSagas.ts b/app/client/src/sagas/PostEvaluationSagas.ts index c089e82c95..de7af2a0e7 100644 --- a/app/client/src/sagas/PostEvaluationSagas.ts +++ b/app/client/src/sagas/PostEvaluationSagas.ts @@ -3,6 +3,7 @@ import { DataTree } from "entities/DataTree/dataTreeFactory"; import { DataTreeDiff, DataTreeDiffEvent, + getDataTreeWithoutPrivateWidgets, getEntityNameAndPropertyPath, isAction, isJSAction, @@ -367,7 +368,13 @@ export function* updateTernDefinitions( } if (shouldUpdate) { const start = performance.now(); - const { def, entityInfo } = dataTreeTypeDefCreator(dataTree); + // remove private widgets from dataTree used for autocompletion + const treeWithoutPrivateWidgets = getDataTreeWithoutPrivateWidgets( + dataTree, + ); + const { def, entityInfo } = dataTreeTypeDefCreator( + treeWithoutPrivateWidgets, + ); TernServer.updateDef("DATA_TREE", def, entityInfo); const end = performance.now(); log.debug("Tern", { updates }); diff --git a/app/client/src/workers/evaluation.test.ts b/app/client/src/workers/evaluation.test.ts index 36f1821a09..9d22e62e57 100644 --- a/app/client/src/workers/evaluation.test.ts +++ b/app/client/src/workers/evaluation.test.ts @@ -225,6 +225,7 @@ const BASE_WIDGET: DataTreeWidget = { triggerPaths: {}, validationPaths: {}, ENTITY_TYPE: ENTITY_TYPE.WIDGET, + privateWidgets: {}, }; const BASE_ACTION: DataTreeAction = { @@ -247,6 +248,7 @@ const BASE_ACTION: DataTreeAction = { data: EvaluationSubstitutionType.TEMPLATE, }, dependencyMap: {}, + datasourceUrl: "", }; describe("DataTreeEvaluator", () => { diff --git a/app/client/src/workers/evaluationUtils.test.ts b/app/client/src/workers/evaluationUtils.test.ts index 9d1008e0c0..822a88ccdc 100644 --- a/app/client/src/workers/evaluationUtils.test.ts +++ b/app/client/src/workers/evaluationUtils.test.ts @@ -1,5 +1,106 @@ -import { PrivateWidgets } from "entities/DataTree/dataTreeFactory"; -import { getAllPaths, isPrivateEntityPath } from "./evaluationUtils"; +import { RenderModes } from "constants/WidgetConstants"; +import { ValidationTypes } from "constants/WidgetValidation"; +import { + DataTreeWidget, + ENTITY_TYPE, + EvaluationSubstitutionType, + PrivateWidgets, +} from "entities/DataTree/dataTreeFactory"; +import { + getAllPaths, + getAllPrivateWidgetsInDataTree, + getDataTreeWithoutPrivateWidgets, + isPrivateEntityPath, +} from "./evaluationUtils"; + +const BASE_WIDGET: DataTreeWidget = { + logBlackList: {}, + widgetId: "randomID", + widgetName: "randomWidgetName", + bottomRow: 0, + isLoading: false, + leftColumn: 0, + parentColumnSpace: 0, + parentRowSpace: 0, + renderMode: RenderModes.CANVAS, + rightColumn: 0, + topRow: 0, + type: "SKELETON_WIDGET", + parentId: "0", + version: 1, + bindingPaths: {}, + triggerPaths: {}, + validationPaths: {}, + ENTITY_TYPE: ENTITY_TYPE.WIDGET, + privateWidgets: {}, +}; + +const testDataTree: Record = { + Text1: { + ...BASE_WIDGET, + widgetName: "Text1", + text: "Label", + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + Text2: { + ...BASE_WIDGET, + widgetName: "Text2", + text: "{{Text1.text}}", + dynamicBindingPathList: [{ key: "text" }], + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + Text3: { + ...BASE_WIDGET, + widgetName: "Text3", + text: "{{Text1.text}}", + dynamicBindingPathList: [{ key: "text" }], + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + Text4: { + ...BASE_WIDGET, + widgetName: "Text4", + text: "{{Text1.text}}", + dynamicBindingPathList: [{ key: "text" }], + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + + List1: { + ...BASE_WIDGET, + privateWidgets: { + Text2: true, + }, + }, + List2: { + ...BASE_WIDGET, + privateWidgets: { + Text3: true, + }, + }, +}; describe("Correctly handle paths", () => { it("getsAllPaths", () => { @@ -39,7 +140,9 @@ describe("Correctly handle paths", () => { const actual = getAllPaths(myTree); expect(actual).toStrictEqual(result); }); +}); +describe("privateWidgets", () => { it("correctly checks if path is a PrivateEntityPath", () => { const privateWidgets: PrivateWidgets = { Button1: true, @@ -57,4 +160,72 @@ describe("Correctly handle paths", () => { ).toBeFalsy(); expect(isPrivateEntityPath(privateWidgets, "Image2.data")).toBeTruthy(); }); + + it("Returns list of all privateWidgets", () => { + const expectedPrivateWidgetsList = { + Text2: true, + Text3: true, + }; + + const actualPrivateWidgetsList = getAllPrivateWidgetsInDataTree( + testDataTree, + ); + + expect(expectedPrivateWidgetsList).toStrictEqual(actualPrivateWidgetsList); + }); + + it("Returns data tree without privateWidgets", () => { + const expectedDataTreeWithoutPrivateWidgets: Record< + string, + DataTreeWidget + > = { + Text1: { + ...BASE_WIDGET, + widgetName: "Text1", + text: "Label", + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + + Text4: { + ...BASE_WIDGET, + widgetName: "Text4", + text: "{{Text1.text}}", + dynamicBindingPathList: [{ key: "text" }], + type: "TEXT_WIDGET", + bindingPaths: { + text: EvaluationSubstitutionType.TEMPLATE, + }, + validationPaths: { + text: { type: ValidationTypes.TEXT }, + }, + }, + + List1: { + ...BASE_WIDGET, + privateWidgets: { + Text2: true, + }, + }, + List2: { + ...BASE_WIDGET, + privateWidgets: { + Text3: true, + }, + }, + }; + + const actualDataTreeWithoutPrivateWidgets = getDataTreeWithoutPrivateWidgets( + testDataTree, + ); + + expect(expectedDataTreeWithoutPrivateWidgets).toStrictEqual( + actualDataTreeWithoutPrivateWidgets, + ); + }); }); diff --git a/app/client/src/workers/evaluationUtils.ts b/app/client/src/workers/evaluationUtils.ts index 2f367d9b4f..1f22e85f12 100644 --- a/app/client/src/workers/evaluationUtils.ts +++ b/app/client/src/workers/evaluationUtils.ts @@ -722,3 +722,27 @@ export const isPrivateEntityPath = ( } return false; }; + +export const getAllPrivateWidgetsInDataTree = ( + dataTree: DataTree, +): PrivateWidgets => { + let privateWidgets: PrivateWidgets = {}; + + Object.keys(dataTree).forEach((entityName) => { + const entity = dataTree[entityName]; + if (isWidget(entity) && !_.isEmpty(entity.privateWidgets)) { + privateWidgets = { ...privateWidgets, ...entity.privateWidgets }; + } + }); + + return privateWidgets; +}; + +export const getDataTreeWithoutPrivateWidgets = ( + dataTree: DataTree, +): DataTree => { + const privateWidgets = getAllPrivateWidgetsInDataTree(dataTree); + const privateWidgetNames = Object.keys(privateWidgets); + const treeWithoutPrivateWidgets = _.omit(dataTree, privateWidgetNames); + return treeWithoutPrivateWidgets; +};