PromucFlow_constructor/app/client/src/entities/DataTree/dataTreeFactory.ts
ashit-rath a47dba5e26
feat: List V2 (#15839)
## 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>
2023-02-14 17:07:31 +01:00

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 };