Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ describe(
formWidgetsPage.datepickerWidget,
widgetsPage.widgetNameSpan,
);

// change the date to next day
cy.get(formWidgetsPage.defaultDate).click();

/**
* setDate--> is a Command to select the date in the date picker
*/

cy.setDate(1);
const nextDay = dayjs().add(1, "days").format("DD/MM/YYYY");
cy.log(nextDay);
Expand Down
1 change: 0 additions & 1 deletion app/client/cypress/limited-tests.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# To run only limited tests - give the spec names in below format:
cypress/e2e/Regression/ClientSide/Templates/Fork_Template_spec.js

# For running all specs - uncomment below:
#cypress/e2e/**/**/*

Expand Down
4 changes: 3 additions & 1 deletion app/client/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable cypress/no-assigning-return-values */
/* This file is used to maintain comman methods across tests , refer other *.js files for adding common methods */
import { ANVIL_EDITOR_TEST } from "./Constants.js";
import advancedFormat from "dayjs/plugin/advancedFormat";

import EditorNavigation, {
EntityType,
Expand All @@ -18,6 +19,7 @@ import { v4 as uuidv4 } from "uuid";
const dayjs = require("dayjs");
const loginPage = require("../locators/LoginPage.json");
import homePage from "../locators/HomePage";
dayjs.extend(advancedFormat);

const commonlocators = require("../locators/commonlocators.json");
const widgetsPage = require("../locators/Widgets.json");
Expand Down Expand Up @@ -525,7 +527,7 @@ Cypress.Commands.add("getDate", (date, dateFormate) => {
});

Cypress.Commands.add("setDate", (date) => {
const expDate = dayjs().add(date, "days").format("dddd, MMMM DD");
const expDate = dayjs().add(date, "days").format("dddd, MMMM Do, YYYY");
cy.get(`.react-datepicker__day[aria-label^="Choose ${expDate}"]`).click();
});

Expand Down
1 change: 0 additions & 1 deletion app/client/src/ce/entities/DataTree/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ export interface DataTreeSeed {
pluginDependencyConfig: Record<string, DependencyMap>;
widgets: CanvasWidgetsReduxState;
widgetsMeta: MetaState;
pageList: Page[];
appData: AppDataState;
jsActions: JSCollectionDataState;
theme: AppTheme["properties"];
Expand Down
197 changes: 93 additions & 104 deletions app/client/src/entities/DataTree/dataTreeFactory.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,71 @@
import { generateDataTreeAction } from "ee/entities/DataTree/dataTreeAction";
import { generateDataTreeJSAction } from "ee/entities/DataTree/dataTreeJSAction";
import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget";
import log from "loglevel";
import {
ENTITY_TYPE,
EvaluationSubstitutionType,
} from "ee/entities/DataTree/types";
import { generateDataTreeModuleInputs } from "ee/entities/DataTree/utils";
import type {
DataTreeSeed,
AppsmithEntity,
EntityTypeValue,
} from "ee/entities/DataTree/types";
import type {
unEvalAndConfigTree,
ConfigTree,
UnEvalTree,
} from "entities/DataTree/dataTreeTypes";
import type { EntityTypeValue } from "ee/entities/DataTree/types";
import type { ConfigTree, UnEvalTree } from "entities/DataTree/dataTreeTypes";
import { isEmpty } from "lodash";
import { generateModuleInstance } from "ee/entities/DataTree/dataTreeModuleInstance";
import {
endSpan,
startNestedSpan,
startRootSpan,
} from "UITelemetry/generateTraces";
import { endSpan, startRootSpan } from "UITelemetry/generateTraces";
import type { ActionDataState } from "ee/reducers/entityReducers/actionsReducer";
import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer";
import type { LayoutSystemTypes } from "layoutSystems/types";
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import type { MetaState } from "reducers/entityReducers/metaReducer";
import type { LoadingEntitiesState } from "reducers/evaluationReducers/loadingEntitiesReducer";
import type { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer";
import type { Module } from "ee/constants/ModuleConstants";
import type { ModuleInstance } from "ee/constants/ModuleInstanceConstants";
import type {
DependencyMap,
FormEditorConfigs,
} from "utils/DynamicBindingUtils";
export class DataTreeFactory {
static create({
actions,
appData,
editorConfigs,
isMobile,
jsActions,
layoutSystemType,
loadingEntities,
metaWidgets,
moduleInputs,
moduleInstanceEntities,
moduleInstances,
pluginDependencyConfig,
theme,
widgets,
widgetsMeta,
}: DataTreeSeed): unEvalAndConfigTree {
public static metaWidgets(
metaWidgets: MetaWidgetsReduxState,
widgetsMeta: MetaState,
loadingEntities: LoadingEntitiesState,
) {
const dataTree: UnEvalTree = {};
const configTree: ConfigTree = {};
const start = performance.now();
const startActions = performance.now();
const rootSpan = startRootSpan("DataTreeFactory.create");
const actionsSpan = startNestedSpan("DataTreeFactory.actions", rootSpan);
const metaWidgetsSpan = startRootSpan("DataTreeFactory.metaWidgets");

actions.forEach((action) => {
const editorConfig = editorConfigs[action.config.pluginId];
const dependencyConfig = pluginDependencyConfig[action.config.pluginId];
const { configEntity, unEvalEntity } = generateDataTreeAction(
action,
editorConfig,
dependencyConfig,
Object.values(metaWidgets).forEach((widget) => {
const { configEntity, unEvalEntity } = generateDataTreeWidget(
widget,
widgetsMeta[widget.metaWidgetId || widget.widgetId],
loadingEntities,
);

dataTree[action.config.name] = unEvalEntity;
configTree[action.config.name] = configEntity;
});
const endActions = performance.now();

endSpan(actionsSpan);

const startJsActions = performance.now();
const jsActionsSpan = startNestedSpan(
"DataTreeFactory.jsActions",
rootSpan,
);

jsActions.forEach((js) => {
const { configEntity, unEvalEntity } = generateDataTreeJSAction(js);

dataTree[js.config.name] = unEvalEntity;
configTree[js.config.name] = configEntity;
dataTree[widget.widgetName] = unEvalEntity;
configTree[widget.widgetName] = configEntity;
});
const endJsActions = performance.now();
endSpan(metaWidgetsSpan);

endSpan(jsActionsSpan);
return {
dataTree,
configTree,
};
}

const startWidgets = performance.now();
const widgetsSpan = startNestedSpan("DataTreeFactory.widgets", rootSpan);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public static widgets(
moduleInputs: Module["inputsForm"],
moduleInstances: Record<string, ModuleInstance> | null,
moduleInstanceEntities: null,
widgets: CanvasWidgetsReduxState,
widgetsMeta: MetaState,
loadingEntities: LoadingEntitiesState,
layoutSystemType: LayoutSystemTypes,
isMobile: boolean,
) {
const dataTree: UnEvalTree = {};
const configTree: ConfigTree = {};
const widgetsSpan = startRootSpan("DataTreeFactory.widgets");

if (!isEmpty(moduleInputs)) {
const { configEntity, unEvalEntity } =
Expand Down Expand Up @@ -120,54 +103,60 @@ export class DataTreeFactory {
dataTree[widget.widgetName] = unEvalEntity;
configTree[widget.widgetName] = configEntity;
});

const endWidgets = performance.now();

endSpan(widgetsSpan);

dataTree.appsmith = {
...appData,
// combine both persistent and transient state with the transient state
// taking precedence in case the key is the same
store: appData.store,
theme,
} as AppsmithEntity;
(dataTree.appsmith as AppsmithEntity).ENTITY_TYPE = ENTITY_TYPE.APPSMITH;

const startMetaWidgets = performance.now();
const metaWidgetsSpan = startNestedSpan(
"DataTreeFactory.metaWidgets",
rootSpan,
);
return {
dataTree,
configTree,
};
}

Object.values(metaWidgets).forEach((widget) => {
const { configEntity, unEvalEntity } = generateDataTreeWidget(
widget,
widgetsMeta[widget.metaWidgetId || widget.widgetId],
loadingEntities,
);
public static jsActions(jsActions: JSCollectionDataState) {
const dataTree: UnEvalTree = {};
const configTree: ConfigTree = {};
const actionsSpan = startRootSpan("DataTreeFactory.jsActions");

dataTree[widget.widgetName] = unEvalEntity;
configTree[widget.widgetName] = configEntity;
jsActions.forEach((js) => {
const { configEntity, unEvalEntity } = generateDataTreeJSAction(js);

dataTree[js.config.name] = unEvalEntity;
configTree[js.config.name] = configEntity;
});
const endMetaWidgets = performance.now();
endSpan(actionsSpan);

endSpan(metaWidgetsSpan);
endSpan(rootSpan);
return {
dataTree,
configTree,
};
}

const end = performance.now();
public static actions(
actions: ActionDataState,
editorConfigs: FormEditorConfigs,
pluginDependencyConfig: Record<string, DependencyMap>,
) {
const dataTree: UnEvalTree = {};
const configTree: ConfigTree = {};
const actionsSpan = startRootSpan("DataTreeFactory.actions");

const out = {
total: end - start,
widgets: endWidgets - startWidgets,
actions: endActions - startActions,
jsActions: endJsActions - startJsActions,
metaWidgets: endMetaWidgets - startMetaWidgets,
};
actions.forEach((action) => {
const editorConfig = editorConfigs[action.config.pluginId];
const dependencyConfig = pluginDependencyConfig[action.config.pluginId];
const { configEntity, unEvalEntity } = generateDataTreeAction(
action,
editorConfig,
dependencyConfig,
);

log.debug("### Create unevalTree timing", out);
dataTree[action.config.name] = unEvalEntity;
configTree[action.config.name] = configEntity;
});
endSpan(actionsSpan);

return { unEvalTree: dataTree, configTree };
return {
dataTree,
configTree,
};
}
}

Expand Down
2 changes: 0 additions & 2 deletions app/client/src/entities/DataTree/dataTreeWidget.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,6 @@ describe("generateDataTreeWidget", () => {
parentColumnSpace: 0,
parentRowSpace: 0,
rightColumn: 0,
renderMode: RenderModes.CANVAS,
version: 0,
topRow: 0,
widgetId: "123",
widgetName: "Input1",
Expand Down
9 changes: 7 additions & 2 deletions app/client/src/entities/DataTree/dataTreeWidget.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getAllPathsFromPropertyConfig } from "entities/Widget/utils";
import _, { get, isEmpty } from "lodash";
import _, { get, isEmpty, omit } from "lodash";
import memoize from "micro-memoize";
import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
import type { DynamicPath } from "utils/DynamicBindingUtils";
Expand All @@ -21,6 +21,7 @@ import WidgetFactory from "WidgetProvider/factory";
import { getComponentDimensions } from "layoutSystems/common/utils/ComponentSizeUtils";
import type { LoadingEntitiesState } from "reducers/evaluationReducers/loadingEntitiesReducer";
import { LayoutSystemTypes } from "layoutSystems/types";
import { WIDGET_PROPS_TO_SKIP_FROM_EVAL } from "constants/WidgetConstants";

/**
*
Expand Down Expand Up @@ -176,13 +177,17 @@ export function getSetterConfig(
// Widget changes only when dynamicBindingPathList changes.
// Only meta properties change very often, for example typing in an input or selecting a table row.
const generateDataTreeWidgetWithoutMeta = (
widget: FlattenedWidgetProps,
widgetWithEval: FlattenedWidgetProps,
): {
dataTreeWidgetWithoutMetaProps: WidgetEntity;
overridingMetaPropsMap: Record<string, boolean>;
defaultMetaProps: Record<string, unknown>;
entityConfig: WidgetEntityConfig;
} => {
const widget = omit(
widgetWithEval,
Object.keys(WIDGET_PROPS_TO_SKIP_FROM_EVAL),
) as FlattenedWidgetProps;
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const derivedProps: any = {};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createReducer } from "utils/ReducerUtils";
import type { ReduxAction } from "ee/constants/ReduxActionConstants";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { isEqual } from "lodash";

export type LoadingEntitiesState = Set<string>;

Expand All @@ -10,7 +11,16 @@ const loadingEntitiesReducer = createReducer(initialState, {
[ReduxActionTypes.SET_LOADING_ENTITIES]: (
state: LoadingEntitiesState,
action: ReduxAction<Set<string>>,
): LoadingEntitiesState => action.payload,
): LoadingEntitiesState => {
const newLoadingEntities = action.payload;

// its just a set with string properties time complexity of equal is not too bad
if (isEqual(state, newLoadingEntities)) {
return state;
}

return newLoadingEntities;
},
[ReduxActionTypes.FETCH_PAGE_INIT]: () => initialState,
});

Expand Down
5 changes: 5 additions & 0 deletions app/client/src/sagas/EvalWorkerActionSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { sortJSExecutionDataByCollectionId } from "workers/Evaluation/JSObject/u
import type { LintTreeSagaRequestData } from "plugins/Linting/types";
import { evalErrorHandler } from "./EvalErrorHandler";
import { getUnevaluatedDataTree } from "selectors/dataTreeSelectors";
import { endSpan, startRootSpan } from "UITelemetry/generateTraces";

export interface UpdateDataTreeMessageData {
workerResponse: EvalTreeResponseData;
Expand Down Expand Up @@ -166,9 +167,13 @@ export function* handleEvalWorkerMessage(message: TMessage<any>) {
}
case MAIN_THREAD_ACTION.UPDATE_DATATREE: {
const { workerResponse } = data as UpdateDataTreeMessageData;
const rootSpan = startRootSpan("DataTreeFactory.create");

const unEvalAndConfigTree: ReturnType<typeof getUnevaluatedDataTree> =
yield select(getUnevaluatedDataTree);

endSpan(rootSpan);

yield call(updateDataTreeHandler, {
evalTreeResponse: workerResponse as EvalTreeResponseData,
unevalTree: unEvalAndConfigTree.unEvalTree || {},
Expand Down
Loading