## Description TL;DR This is a complete architectural change of of List widget works to support all widgets we currently have and should automatically support any future widgets. It also introduces nested List widgets i.e a list widget can have a another list widget which in turn can have another list widget. Fixes #18206 Fixes #6775 Fixes #13211 Fixes #16582 Fixes #11739 Fixes #15094 Fixes #6840 Fixes #10841 Fixes #17386 Fixes #18340 Fixes #16898 Fixes #17555 Fixes #6858 Fixes #9568 Fixes #17480 Fixes #18523 Fixes #18206 Fixes #16586 Fixes #18106 Fixes #16576 Fixes #14697 Fixes #9607 Fixes #19648 Fixes #19739 Fixes #19652 Fixes #18730 Fixes #19503 Fixes #19498 Fixes #19437 Fixes #5245 Fixes #19150 Fixes #18638 Fixes #11332 Fixes #17901 Fixes #19043 Fixes #17777 Fixes #8237 Fixes #15487 Fixes #15988 Fixes #18621 Fixes #16788 Fixes #18110 Fixes #18382 Fixes #17427 Fixes #18105 Fixes #18287 Fixes #19808 Fixes #14655 ## Type of change - New feature (non-breaking change which adds functionality) ## How Has This Been Tested? - Cypress - Jest - Manual ## Checklist: - [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 --------- Co-authored-by: Tolulope Adetula <31691737+Tooluloope@users.noreply.github.com> Co-authored-by: Favour Ohanekwu <fohanekwu@gmail.com>
192 lines
5.4 KiB
TypeScript
192 lines
5.4 KiB
TypeScript
import { ActionDataState } from "reducers/entityReducers/actionsReducer";
|
|
import { WidgetProps } from "widgets/BaseWidget";
|
|
import { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
|
import { MetaState } from "reducers/entityReducers/metaReducer";
|
|
import { Page } from "@appsmith/constants/ReduxActionConstants";
|
|
import { AppDataState } from "reducers/entityReducers/appReducer";
|
|
import { DependencyMap } from "utils/DynamicBindingUtils";
|
|
import { generateDataTreeAction } from "entities/DataTree/dataTreeAction";
|
|
import { generateDataTreeJSAction } from "entities/DataTree/dataTreeJSAction";
|
|
import { generateDataTreeWidget } from "entities/DataTree/dataTreeWidget";
|
|
import { JSCollectionDataState } from "reducers/entityReducers/jsActionsReducer";
|
|
import { AppTheme } from "entities/AppTheming";
|
|
import log from "loglevel";
|
|
import { MetaWidgetsReduxState } from "reducers/entityReducers/metaWidgetsReducer";
|
|
import { WidgetConfigProps } from "reducers/entityReducers/widgetConfigReducer";
|
|
import {
|
|
ActionDispatcher,
|
|
ActionEntityConfig,
|
|
ActionEntityEvalTree,
|
|
ENTITY_TYPE,
|
|
JSActionEntityConfig,
|
|
JSActionEvalTree,
|
|
WidgetConfig,
|
|
EvaluationSubstitutionType,
|
|
} from "./types";
|
|
|
|
export interface UnEvalTreeAction extends ActionEntityEvalTree {
|
|
__config__: ActionEntityConfig;
|
|
}
|
|
export interface DataTreeAction
|
|
extends ActionEntityEvalTree,
|
|
ActionEntityConfig {}
|
|
|
|
export interface UnEvalTreeJSAction extends JSActionEvalTree {
|
|
__config__: JSActionEntityConfig;
|
|
}
|
|
|
|
export type DataTreeJSAction = JSActionEvalTree & JSActionEntityConfig;
|
|
|
|
export interface WidgetEntityConfig
|
|
extends Partial<WidgetProps>,
|
|
Omit<WidgetConfigProps, "widgetName" | "rows" | "columns">,
|
|
WidgetConfig {
|
|
defaultMetaProps: Array<string>;
|
|
type: string;
|
|
}
|
|
|
|
export interface WidgetEvalTree extends WidgetProps {
|
|
meta: Record<string, unknown>;
|
|
ENTITY_TYPE: ENTITY_TYPE.WIDGET;
|
|
}
|
|
|
|
export interface UnEvalTreeWidget extends WidgetEvalTree {
|
|
__config__: WidgetEntityConfig;
|
|
}
|
|
|
|
export interface DataTreeWidget extends WidgetEvalTree, WidgetConfig {}
|
|
|
|
export interface DataTreeAppsmith extends Omit<AppDataState, "store"> {
|
|
ENTITY_TYPE: ENTITY_TYPE.APPSMITH;
|
|
store: Record<string, unknown>;
|
|
theme: AppTheme["properties"];
|
|
}
|
|
export type DataTreeObjectEntity =
|
|
| DataTreeAction
|
|
| DataTreeJSAction
|
|
| DataTreeWidget
|
|
| DataTreeAppsmith;
|
|
|
|
export type DataTreeEntity = DataTreeObjectEntity | Page[] | ActionDispatcher;
|
|
|
|
export type DataTree = {
|
|
[entityName: string]: DataTreeEntity;
|
|
};
|
|
|
|
export type UnEvalTreeEntityObject =
|
|
| UnEvalTreeAction
|
|
| UnEvalTreeJSAction
|
|
| UnEvalTreeWidget;
|
|
|
|
export type UnEvalTreeEntity =
|
|
| UnEvalTreeEntityObject
|
|
| DataTreeAppsmith
|
|
| Page[];
|
|
|
|
export type UnEvalTree = {
|
|
[entityName: string]: UnEvalTreeEntity;
|
|
};
|
|
|
|
type DataTreeSeed = {
|
|
actions: ActionDataState;
|
|
editorConfigs: Record<string, any[]>;
|
|
pluginDependencyConfig: Record<string, DependencyMap>;
|
|
widgets: CanvasWidgetsReduxState;
|
|
widgetsMeta: MetaState;
|
|
pageList: Page[];
|
|
appData: AppDataState;
|
|
jsActions: JSCollectionDataState;
|
|
theme: AppTheme["properties"];
|
|
metaWidgets: MetaWidgetsReduxState;
|
|
};
|
|
|
|
export type DataTreeEntityConfig =
|
|
| WidgetEntityConfig
|
|
| ActionEntityConfig
|
|
| JSActionEntityConfig
|
|
| DataTreeAppsmith;
|
|
|
|
export class DataTreeFactory {
|
|
static create({
|
|
actions,
|
|
appData,
|
|
editorConfigs,
|
|
jsActions,
|
|
metaWidgets,
|
|
pageList,
|
|
pluginDependencyConfig,
|
|
theme,
|
|
widgets,
|
|
widgetsMeta,
|
|
}: DataTreeSeed): UnEvalTree {
|
|
const dataTree: UnEvalTree = {};
|
|
const start = performance.now();
|
|
const startActions = performance.now();
|
|
|
|
actions.forEach((action) => {
|
|
const editorConfig = editorConfigs[action.config.pluginId];
|
|
const dependencyConfig = pluginDependencyConfig[action.config.pluginId];
|
|
dataTree[action.config.name] = generateDataTreeAction(
|
|
action,
|
|
editorConfig,
|
|
dependencyConfig,
|
|
);
|
|
});
|
|
const endActions = performance.now();
|
|
|
|
const startJsActions = performance.now();
|
|
|
|
jsActions.forEach((js) => {
|
|
dataTree[js.config.name] = generateDataTreeJSAction(js);
|
|
});
|
|
const endJsActions = performance.now();
|
|
|
|
const startWidgets = performance.now();
|
|
|
|
Object.values(widgets).forEach((widget) => {
|
|
dataTree[widget.widgetName] = generateDataTreeWidget(
|
|
widget,
|
|
widgetsMeta[widget.metaWidgetId || widget.widgetId],
|
|
);
|
|
});
|
|
const endWidgets = performance.now();
|
|
|
|
dataTree.pageList = pageList;
|
|
|
|
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 DataTreeAppsmith;
|
|
(dataTree.appsmith as DataTreeAppsmith).ENTITY_TYPE = ENTITY_TYPE.APPSMITH;
|
|
|
|
const startMetaWidgets = performance.now();
|
|
|
|
Object.values(metaWidgets).forEach((widget) => {
|
|
dataTree[widget.widgetName] = generateDataTreeWidget(
|
|
widget,
|
|
widgetsMeta[widget.metaWidgetId || widget.widgetId],
|
|
);
|
|
});
|
|
const endMetaWidgets = performance.now();
|
|
|
|
const end = performance.now();
|
|
|
|
const out = {
|
|
total: end - start,
|
|
widgets: endWidgets - startWidgets,
|
|
actions: endActions - startActions,
|
|
jsActions: endJsActions - startJsActions,
|
|
metaWidgets: endMetaWidgets - startMetaWidgets,
|
|
};
|
|
|
|
log.debug("### Create unevalTree timing", out);
|
|
|
|
return dataTree;
|
|
}
|
|
}
|
|
|
|
export { ENTITY_TYPE, EvaluationSubstitutionType };
|