## Description Move middlewares to a new folder and added an ee specific middleware `app/client/src/ee/middlewares/PackageMiddleware.ts`. This will eventually be added to the store but as of now it is detached since the functionality is incomplete. It will be extended in EE PR for https://github.com/appsmithorg/appsmith-ee/pull/6324 ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/13493097420> > Commit: a0a94db05767a5f3b8e511e6c72252b1f9f22a17 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=13493097420&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Mon, 24 Feb 2025 08:58:32 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced an enterprise middleware that enhances package-specific functionality. - **Refactor** - Improved internal integration by adjusting module access and reorganizing route handling. - Updated import paths and consolidated middleware components to streamline application structure. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
178 lines
5.2 KiB
TypeScript
178 lines
5.2 KiB
TypeScript
import { createImmerReducer } from "utils/ReducerUtils";
|
|
import type { ReduxAction } from "actions/ReduxActionTypes";
|
|
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
|
|
import type { WidgetProps } from "widgets/BaseWidget";
|
|
import { uniq, get, set } from "lodash";
|
|
import type { Diff } from "deep-diff";
|
|
import { diff } from "deep-diff";
|
|
import {
|
|
getCanvasBottomRow,
|
|
getCanvasWidgetHeightsToUpdate,
|
|
} from "utils/WidgetSizeUtils";
|
|
import { klona } from "klona";
|
|
import type { UpdateCanvasPayload } from "actions/pageActions";
|
|
import type { SetWidgetDynamicPropertyPayload } from "../../../actions/controlActions";
|
|
|
|
/* 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;
|
|
}>
|
|
>;
|
|
|
|
export const initialState: CanvasWidgetsReduxState = {};
|
|
|
|
export type FlattenedWidgetProps<orType = never> =
|
|
| (WidgetProps & {
|
|
children?: string[];
|
|
})
|
|
| orType;
|
|
|
|
/**
|
|
*
|
|
* @param updateLayoutDiff
|
|
* @returns list of widgets that were updated
|
|
*/
|
|
export function getUpdatedWidgetLists(
|
|
updateLayoutDiff: Diff<
|
|
CanvasWidgetsReduxState,
|
|
{
|
|
[widgetId: string]: WidgetProps;
|
|
}
|
|
>[],
|
|
) {
|
|
return uniq(
|
|
updateLayoutDiff
|
|
.map((diff: Diff<CanvasWidgetsReduxState>) => diff.path?.[0])
|
|
.filter((widgetId) => !!widgetId),
|
|
);
|
|
}
|
|
|
|
export const handlers = {
|
|
[ReduxActionTypes.INIT_CANVAS_LAYOUT]: (
|
|
state: CanvasWidgetsReduxState,
|
|
action: ReduxAction<UpdateCanvasPayload>,
|
|
) => {
|
|
const { widgets } = action.payload;
|
|
|
|
for (const [widgetId, widgetProps] of Object.entries(widgets)) {
|
|
if (widgetProps.type === "CANVAS_WIDGET") {
|
|
const bottomRow = getCanvasBottomRow(widgetId, widgets);
|
|
|
|
widgets[widgetId].bottomRow = bottomRow;
|
|
}
|
|
}
|
|
|
|
return widgets;
|
|
},
|
|
[ReduxActionTypes.UPDATE_LAYOUT]: (
|
|
state: CanvasWidgetsReduxState,
|
|
action: ReduxAction<UpdateCanvasPayload>,
|
|
) => {
|
|
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];
|
|
}
|
|
}
|
|
|
|
const canvasWidgetHeightsToUpdate: Record<string, number> =
|
|
getCanvasWidgetHeightsToUpdate(listOfUpdatedWidgets, state);
|
|
|
|
for (const widgetId in canvasWidgetHeightsToUpdate) {
|
|
state[widgetId] = {
|
|
...state[widgetId],
|
|
bottomRow: canvasWidgetHeightsToUpdate[widgetId],
|
|
};
|
|
}
|
|
},
|
|
[ReduxActionTypes.UPDATE_MULTIPLE_WIDGET_PROPERTIES]: (
|
|
state: CanvasWidgetsReduxState,
|
|
action: ReduxAction<{
|
|
widgetsToUpdate: UpdateWidgetsPayload;
|
|
shouldEval: boolean;
|
|
}>,
|
|
) => {
|
|
// For each widget whose properties we would like to update
|
|
for (const [widgetId, propertyPathsToUpdate] of Object.entries(
|
|
action.payload.widgetsToUpdate,
|
|
)) {
|
|
// 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);
|
|
});
|
|
}
|
|
|
|
const canvasWidgetHeightsToUpdate: Record<string, number> =
|
|
getCanvasWidgetHeightsToUpdate(
|
|
Object.keys(action.payload.widgetsToUpdate),
|
|
state,
|
|
);
|
|
|
|
for (const widgetId in canvasWidgetHeightsToUpdate) {
|
|
state[widgetId].bottomRow = canvasWidgetHeightsToUpdate[widgetId];
|
|
}
|
|
},
|
|
[ReduxActionTypes.RESET_EDITOR_REQUEST]: () => {
|
|
return klona(initialState);
|
|
},
|
|
[ReduxActionTypes.SET_WIDGET_DYNAMIC_PROPERTY]: (
|
|
state: CanvasWidgetsReduxState,
|
|
action: ReduxAction<SetWidgetDynamicPropertyPayload>,
|
|
) => {
|
|
const { isDynamic, propertyPath, widgetId } = action.payload;
|
|
const widget = state[widgetId];
|
|
|
|
// When options JS mode is disabled, reset the optionLabel and optionValue to standard values
|
|
if (
|
|
widget.type === "WDS_SELECT_WIDGET" &&
|
|
propertyPath === "options" &&
|
|
!isDynamic
|
|
) {
|
|
set(state, `${widgetId}.optionLabel`, "label");
|
|
set(state, `${widgetId}.optionValue`, "value");
|
|
}
|
|
|
|
return state;
|
|
},
|
|
};
|
|
|
|
export interface CanvasWidgetsReduxState {
|
|
[widgetId: string]: FlattenedWidgetProps;
|
|
}
|
|
|
|
const canvasWidgetsReducer = createImmerReducer(initialState, handlers);
|
|
|
|
export default canvasWidgetsReducer;
|