PromucFlow_constructor/app/client/src/widgets/MetaHOC.tsx

220 lines
7.3 KiB
TypeScript
Raw Normal View History

2020-10-06 09:01:51 +00:00
import React from "react";
import BaseWidget, { WidgetProps } from "./BaseWidget";
import { isObject, debounce, fromPairs, isEqual } from "lodash";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
2021-04-23 13:50:55 +00:00
import AppsmithConsole from "utils/AppsmithConsole";
import { ENTITY_TYPE } from "entities/AppsmithConsole";
import LOG_TYPE from "entities/AppsmithConsole/logtype";
import { ExecuteTriggerPayload } from "constants/AppsmithActionConstants/ActionConstants";
2020-10-06 16:47:16 +00:00
export type DebouncedExecuteActionPayload = Omit<
ExecuteTriggerPayload,
2020-10-06 16:47:16 +00:00
"dynamicString"
> & {
dynamicString?: string;
};
2020-10-06 09:01:51 +00:00
export interface WithMeta {
2020-10-06 16:47:16 +00:00
updateWidgetMetaProperty: (
propertyName: string,
propertyValue: unknown,
2020-10-06 16:47:16 +00:00
actionExecution?: DebouncedExecuteActionPayload,
) => void;
syncUpdateWidgetMetaProperty: (
propertyName: string,
propertyValue: unknown,
) => void;
2020-10-06 09:01:51 +00:00
}
type MetaHOCState = Record<string, unknown>;
2020-10-06 09:01:51 +00:00
const withMeta = (WrappedWidget: typeof BaseWidget) => {
return class MetaHOC extends React.PureComponent<WidgetProps, MetaHOCState> {
2020-10-06 09:01:51 +00:00
static contextType = EditorContext;
updatedProperties = new Map<string, true>();
2020-10-06 16:47:16 +00:00
propertyTriggers = new Map<string, DebouncedExecuteActionPayload>();
2020-10-06 09:01:51 +00:00
debouncedHandleUpdateWidgetMetaProperty = debounce(
2020-10-06 09:01:51 +00:00
this.handleUpdateWidgetMetaProperty.bind(this),
200,
{
leading: true,
2020-10-06 09:01:51 +00:00
trailing: true,
},
);
initialMetaState: Record<string, unknown>;
constructor(props: WidgetProps) {
2020-10-06 09:01:51 +00:00
super(props);
const metaProperties = WrappedWidget.getMetaPropertiesMap();
this.initialMetaState = fromPairs(
2020-12-24 04:32:25 +00:00
Object.keys(metaProperties).map((metaProperty) => {
2020-10-06 09:01:51 +00:00
return [metaProperty, this.props[metaProperty]];
}),
);
this.state = this.initialMetaState;
2020-10-06 09:01:51 +00:00
}
componentDidUpdate(prevProps: WidgetProps) {
/*
Generally the meta property value of a widget will directly be
controlled by itself and the platform will not interfere except:
When we reset the meta property value.
Property which has default value is set to default value and
other meta property are set to initial value.
For eg:- In Input widget, after reset text = "" and isDirty = false
*/
// meta becoming empty only happens on resetWidget action and metaHOC values needs to reset too.
if (
isObject(this.props.meta) &&
isObject(prevProps.meta) &&
Object.keys(this.props.meta).length === 0 &&
Object.keys(prevProps.meta).length > 0
) {
this.setState(this.initialMetaState);
}
2020-10-06 09:01:51 +00:00
const metaProperties = WrappedWidget.getMetaPropertiesMap();
const defaultProperties = WrappedWidget.getDefaultPropertiesMap();
2020-12-24 04:32:25 +00:00
Object.keys(metaProperties).forEach((metaProperty) => {
2020-10-06 09:01:51 +00:00
const defaultProperty = defaultProperties[metaProperty];
/*
Reset operation happens by the platform and is outside the widget logic
so to identify this change, we want to see if the meta value has
changed to the current default value. If this has happened, we should
set the state of the meta property value (controlled by inside the
widget) to the current value that is outside (controlled by platform)
2021-02-17 15:02:36 +00:00
*/
2020-10-06 09:01:51 +00:00
if (
defaultProperty &&
!isEqual(prevProps[metaProperty], this.props[metaProperty]) &&
isEqual(this.props[defaultProperty], this.props[metaProperty])
2020-10-06 09:01:51 +00:00
) {
this.setState({ [metaProperty]: this.props[metaProperty] });
}
});
}
updateWidgetMetaProperty = (
propertyName: string,
propertyValue: unknown,
2020-10-06 16:47:16 +00:00
actionExecution?: DebouncedExecuteActionPayload,
2020-10-06 09:01:51 +00:00
): void => {
this.updatedProperties.set(propertyName, true);
2020-10-06 16:47:16 +00:00
if (actionExecution) {
this.propertyTriggers.set(propertyName, actionExecution);
}
2021-04-23 13:50:55 +00:00
AppsmithConsole.info({
logType: LOG_TYPE.WIDGET_UPDATE,
2021-04-23 13:50:55 +00:00
text: "Widget property was updated",
source: {
type: ENTITY_TYPE.WIDGET,
id: this.props.widgetId,
name: this.props.widgetName,
propertyPath: propertyName,
2021-04-23 13:50:55 +00:00
},
state: {
[propertyName]: propertyValue,
},
});
2020-10-06 16:47:16 +00:00
this.setState(
{
[propertyName]: propertyValue,
},
() => {
this.debouncedHandleUpdateWidgetMetaProperty();
},
);
2020-10-06 09:01:51 +00:00
};
// To be used when there is a race condition noticed on updating different
// properties from a widget in quick succession
syncUpdateWidgetMetaProperty = (
propertyName: string,
propertyValue: unknown,
): void => {
const { updateWidgetMetaProperty } = this.context;
const { widgetId } = this.props;
this.setState({
[propertyName]: propertyValue,
});
updateWidgetMetaProperty(widgetId, propertyName, propertyValue);
};
2020-10-06 09:01:51 +00:00
handleUpdateWidgetMetaProperty() {
const { executeAction, updateWidgetMetaProperty } = this.context;
const { widgetId } = this.props;
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
const metaOptions = this.props.__metaOptions;
2021-02-17 15:02:36 +00:00
/*
We have kept a map of all updated properties. After debouncing we will
go through these properties and update with the final value. This way
we will only update a certain property once per debounce interval.
Then we will execute any action associated with the trigger of
that value changing
*/
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
2020-12-24 04:32:25 +00:00
[...this.updatedProperties.keys()].forEach((propertyName) => {
2020-10-06 09:01:51 +00:00
if (updateWidgetMetaProperty) {
const propertyValue = this.state[propertyName];
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
// step 6 - look at this.props.options, check for metaPropPath value
// if they exist, then update the propertyName
2020-10-06 09:01:51 +00:00
updateWidgetMetaProperty(widgetId, propertyName, propertyValue);
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
if (metaOptions) {
updateWidgetMetaProperty(
metaOptions.widgetId,
`${metaOptions.metaPropPrefix}.${this.props.widgetName}.${propertyName}[${metaOptions.index}]`,
propertyValue,
);
}
2020-10-06 09:01:51 +00:00
this.updatedProperties.delete(propertyName);
}
2020-10-06 16:47:16 +00:00
const debouncedPayload = this.propertyTriggers.get(propertyName);
if (
debouncedPayload &&
debouncedPayload.dynamicString &&
executeAction
) {
executeAction({
...debouncedPayload,
source: {
id: this.props.widgetId,
name: this.props.widgetName,
},
});
2020-10-06 16:47:16 +00:00
this.propertyTriggers.delete(propertyName);
2021-04-23 13:50:55 +00:00
debouncedPayload.triggerPropertyName &&
AppsmithConsole.info({
text: `${debouncedPayload.triggerPropertyName} triggered`,
source: {
type: ENTITY_TYPE.WIDGET,
id: this.props.widgetId,
name: this.props.widgetName,
},
});
2020-10-06 16:47:16 +00:00
}
2020-10-06 09:01:51 +00:00
});
}
updatedProps = () => {
return {
...this.props,
...this.state,
updateWidgetMetaProperty: this.updateWidgetMetaProperty,
syncUpdateWidgetMetaProperty: this.syncUpdateWidgetMetaProperty,
2020-10-06 09:01:51 +00:00
};
};
render() {
return <WrappedWidget {...this.updatedProps()} />;
}
};
};
export default withMeta;