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

123 lines
3.9 KiB
TypeScript
Raw Normal View History

2020-10-06 09:01:51 +00:00
import React from "react";
import BaseWidget, { WidgetProps } from "./BaseWidget";
import _ from "lodash";
import { EditorContext } from "../components/editorComponents/EditorContextProvider";
import { clearEvalPropertyCache } from "sagas/EvaluationsSaga";
2020-10-06 16:47:16 +00:00
import { ExecuteActionPayload } from "../constants/ActionConstants";
type DebouncedExecuteActionPayload = Omit<
ExecuteActionPayload,
"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: any,
actionExecution?: DebouncedExecuteActionPayload,
) => void;
2020-10-06 09:01:51 +00:00
}
const withMeta = (WrappedWidget: typeof BaseWidget) => {
return class MetaHOC extends React.Component<WidgetProps, any> {
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(
this.handleUpdateWidgetMetaProperty.bind(this),
200,
{
leading: true,
trailing: true,
},
);
constructor(props: any) {
super(props);
const metaProperties = WrappedWidget.getMetaPropertiesMap();
this.state = _.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]];
}),
);
}
componentDidUpdate(prevProps: WidgetProps) {
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];
if (
!_.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: any,
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);
}
this.setState(
{
[propertyName]: propertyValue,
},
() => {
this.debouncedHandleUpdateWidgetMetaProperty();
},
);
2020-10-06 09:01:51 +00:00
};
handleUpdateWidgetMetaProperty() {
2020-10-06 16:47:16 +00:00
const { updateWidgetMetaProperty, executeAction } = this.context;
2020-10-06 09:01:51 +00:00
const { widgetId, widgetName } = this.props;
// 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.
2020-10-06 16:47:16 +00:00
// Then we will execute any action associated with the trigger of
// that value changing
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];
clearEvalPropertyCache(`${widgetName}.${propertyName}`);
2020-10-06 09:01:51 +00:00
updateWidgetMetaProperty(widgetId, propertyName, propertyValue);
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);
this.propertyTriggers.delete(propertyName);
}
2020-10-06 09:01:51 +00:00
});
}
updatedProps = () => {
return {
...this.props,
...this.state,
updateWidgetMetaProperty: this.updateWidgetMetaProperty,
};
};
render() {
return <WrappedWidget {...this.updatedProps()} />;
}
};
};
export default withMeta;