2022-08-04 05:40:44 +00:00
|
|
|
import { createImmerReducer } from "utils/ReducerUtils";
|
2019-02-10 13:06:05 +00:00
|
|
|
import {
|
2019-09-12 11:19:38 +00:00
|
|
|
ReduxActionTypes,
|
2019-09-24 12:36:03 +00:00
|
|
|
UpdateCanvasPayload,
|
2019-09-09 10:30:22 +00:00
|
|
|
ReduxAction,
|
2022-04-12 10:50:01 +00:00
|
|
|
} from "@appsmith/constants/ReduxActionConstants";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { WidgetProps } from "widgets/BaseWidget";
|
2022-11-14 04:19:25 +00:00
|
|
|
import { uniq, get, set } from "lodash";
|
2022-11-23 09:48:23 +00:00
|
|
|
import { Diff, diff } from "deep-diff";
|
2019-08-26 12:41:21 +00:00
|
|
|
|
2022-11-14 04:19:25 +00:00
|
|
|
/* This type is an object whose keys are widgetIds and values are arrays with property paths
|
|
|
|
|
and property values
|
|
|
|
|
For example:
|
|
|
|
|
{ "xyz123": [{ propertyPath: "bottomRow", propertyValue: 20 }] }
|
|
|
|
|
*/
|
|
|
|
|
export type UpdateWidgetsPayload = Record<
|
|
|
|
|
string,
|
|
|
|
|
Array<{
|
|
|
|
|
propertyPath: string;
|
|
|
|
|
propertyValue: unknown;
|
|
|
|
|
}>
|
|
|
|
|
>;
|
|
|
|
|
|
2022-11-23 09:48:23 +00:00
|
|
|
const initialState: CanvasWidgetsReduxState = {};
|
|
|
|
|
|
2021-08-25 05:00:31 +00:00
|
|
|
export type FlattenedWidgetProps<orType = never> =
|
|
|
|
|
| (WidgetProps & {
|
|
|
|
|
children?: string[];
|
|
|
|
|
})
|
|
|
|
|
| orType;
|
2019-02-10 13:06:05 +00:00
|
|
|
|
2022-08-19 10:10:36 +00:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param updateLayoutDiff
|
|
|
|
|
* @returns list of widgets that were updated
|
|
|
|
|
*/
|
|
|
|
|
function getUpdatedWidgetLists(
|
|
|
|
|
updateLayoutDiff: Diff<
|
|
|
|
|
CanvasWidgetsReduxState,
|
|
|
|
|
{
|
|
|
|
|
[widgetId: string]: WidgetProps;
|
|
|
|
|
}
|
|
|
|
|
>[],
|
|
|
|
|
) {
|
|
|
|
|
return uniq(
|
|
|
|
|
updateLayoutDiff
|
|
|
|
|
.map((diff: Diff<CanvasWidgetsReduxState>) => diff.path?.[0])
|
|
|
|
|
.filter((widgetId) => !!widgetId),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-30 12:42:09 +00:00
|
|
|
const canvasWidgetsReducer = createImmerReducer(initialState, {
|
2021-01-25 08:57:26 +00:00
|
|
|
[ReduxActionTypes.INIT_CANVAS_LAYOUT]: (
|
2019-03-21 17:42:23 +00:00
|
|
|
state: CanvasWidgetsReduxState,
|
2019-09-24 12:36:03 +00:00
|
|
|
action: ReduxAction<UpdateCanvasPayload>,
|
2019-03-21 17:42:23 +00:00
|
|
|
) => {
|
2020-09-30 12:42:09 +00:00
|
|
|
return action.payload.widgets;
|
2019-08-26 12:41:21 +00:00
|
|
|
},
|
2019-09-19 22:25:37 +00:00
|
|
|
[ReduxActionTypes.UPDATE_LAYOUT]: (
|
2019-08-26 12:41:21 +00:00
|
|
|
state: CanvasWidgetsReduxState,
|
2019-09-24 12:36:03 +00:00
|
|
|
action: ReduxAction<UpdateCanvasPayload>,
|
2019-08-26 12:41:21 +00:00
|
|
|
) => {
|
2022-08-19 10:10:36 +00:00
|
|
|
let listOfUpdatedWidgets;
|
|
|
|
|
// if payload has knowledge of which widgets were changed, use that
|
|
|
|
|
if (action.payload.updatedWidgetIds) {
|
|
|
|
|
listOfUpdatedWidgets = action.payload.updatedWidgetIds;
|
|
|
|
|
} // else diff out the widgets that need to be updated
|
|
|
|
|
else {
|
|
|
|
|
const updatedLayoutDiffs = diff(state, action.payload.widgets);
|
|
|
|
|
if (!updatedLayoutDiffs) return state;
|
|
|
|
|
|
|
|
|
|
listOfUpdatedWidgets = getUpdatedWidgetLists(updatedLayoutDiffs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//update only the widgets that need to be updated.
|
|
|
|
|
for (const widgetId of listOfUpdatedWidgets) {
|
|
|
|
|
const updatedWidget = action.payload.widgets[widgetId];
|
|
|
|
|
if (updatedWidget) {
|
|
|
|
|
state[widgetId] = updatedWidget;
|
|
|
|
|
} else {
|
|
|
|
|
delete state[widgetId];
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-09 10:30:22 +00:00
|
|
|
},
|
2022-11-14 04:19:25 +00:00
|
|
|
[ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES]: (
|
|
|
|
|
state: CanvasWidgetsReduxState,
|
|
|
|
|
action: ReduxAction<UpdateWidgetsPayload>,
|
|
|
|
|
) => {
|
|
|
|
|
// For each widget whose properties we would like to update
|
|
|
|
|
for (const [widgetId, propertyPathsToUpdate] of Object.entries(
|
|
|
|
|
action.payload,
|
|
|
|
|
)) {
|
|
|
|
|
// Iterate through each property to update in `widgetId`
|
|
|
|
|
propertyPathsToUpdate.forEach(({ propertyPath, propertyValue }) => {
|
|
|
|
|
const path = `${widgetId}.${propertyPath}`;
|
|
|
|
|
// Get original value in reducer
|
|
|
|
|
const originalPropertyValue = get(state, path);
|
|
|
|
|
// If the original and new values are different
|
|
|
|
|
if (propertyValue !== originalPropertyValue)
|
|
|
|
|
// Set the new values
|
|
|
|
|
set(state, path, propertyValue);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
2019-09-09 10:30:22 +00:00
|
|
|
});
|
2022-11-23 09:48:23 +00:00
|
|
|
|
2019-02-10 13:06:05 +00:00
|
|
|
export interface CanvasWidgetsReduxState {
|
2019-09-09 10:30:22 +00:00
|
|
|
[widgetId: string]: FlattenedWidgetProps;
|
2019-02-10 13:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
2019-09-09 10:30:22 +00:00
|
|
|
export default canvasWidgetsReducer;
|