diff --git a/apps/builder/package.json b/apps/builder/package.json index 889fc549a3..66bb847ece 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -47,6 +47,7 @@ "@illa-design/react": "workspace:*", "@illa-public/avatar": "workspace:*", "@illa-public/code-editor": "workspace:*", + "@illa-public/create-app": "workspace:*", "@illa-public/cropper": "workspace:*", "@illa-public/dynamic-string": "workspace:^", "@illa-public/icon": "workspace:*", @@ -56,6 +57,7 @@ "@illa-public/invite-modal": "workspace:*", "@illa-public/layout-auto-change": "workspace:*", "@illa-public/market-agent": "workspace:*", + "@illa-public/market-app": "workspace:*", "@illa-public/missing-resource-module": "workspace:^", "@illa-public/mixpanel-utils": "workspace:*", "@illa-public/public-configs": "workspace:*", @@ -69,8 +71,6 @@ "@illa-public/user-data": "workspace:*", "@illa-public/user-role-utils": "workspace:*", "@illa-public/utils": "workspace:*", - "@illa-public/create-app": "workspace:*", - "@illa-public/market-app": "workspace:*", "@mui/icons-material": "^5.14.18", "@mui/material": "^5.14.18", "@mui/x-data-grid-premium": "^6.18.2", @@ -108,6 +108,7 @@ "overlap-area": "^1.1.0", "papaparse": "^5.4.1", "pdfjs-dist": "2.16.105", + "qrcode.react": "^3.1.0", "qs": "^6.11.2", "rc-virtual-list": "^3.4.2", "re-resizable": "^6.9.9", diff --git a/apps/builder/src/assets/widgetCover/qrcode.svg b/apps/builder/src/assets/widgetCover/qrcode.svg new file mode 100644 index 0000000000..199b95816a --- /dev/null +++ b/apps/builder/src/assets/widgetCover/qrcode.svg @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/builder/src/middleware/reduxAsync/index.ts b/apps/builder/src/middleware/reduxAsync/index.ts index 4f7490d2ae..9927cf1d68 100644 --- a/apps/builder/src/middleware/reduxAsync/index.ts +++ b/apps/builder/src/middleware/reduxAsync/index.ts @@ -1,6 +1,6 @@ import { Middleware, isAction } from "@reduxjs/toolkit" import { illaSnapshot } from "@/page/App/components/DotPanel/constant/snapshotNew" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { RootState } from "@/store" import { receiveMessage } from "./receiveMessages" import { sendMessage } from "./sendMessage" @@ -18,7 +18,7 @@ export const reduxAsync: Middleware = (store) => (next) => (action) => { const resp = next(action) as RootState if (typeList[0] === "components") { const nextRootState = store.getState() - const snapShot = getExecutionWidgetLayoutInfo(nextRootState) + const snapShot = getClientWidgetLayoutInfo(nextRootState) illaSnapshot.setSnapshot(snapShot) } return resp diff --git a/apps/builder/src/middleware/undoRedo/method/components.tsx b/apps/builder/src/middleware/undoRedo/method/components.tsx index 3ef8d2796d..55c2329e23 100644 --- a/apps/builder/src/middleware/undoRedo/method/components.tsx +++ b/apps/builder/src/middleware/undoRedo/method/components.tsx @@ -8,7 +8,7 @@ import { searchDSLByDisplayName, searchDSLFromTree, } from "@/redux/currentApp/components/componentsSelector" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { RootState } from "@/store" import { buildTreeByMapNode } from "@/utils/componentNode/flatTree" import IllaUndoRedoManager from "@/utils/undoRedo/undo" @@ -119,7 +119,7 @@ export const componentsSnapShot = ( break } case "updateComponentPositionReducer": { - const layoutInfos = getExecutionWidgetLayoutInfo(prevRootState) + const layoutInfos = getClientWidgetLayoutInfo(prevRootState) const originNodeLayoutInfos = ( action.payload as UpdateComponentPositionPayload ).updateSlices.map((item) => { diff --git a/apps/builder/src/page/App/components/ComponentPanel/ComponentItem.tsx b/apps/builder/src/page/App/components/ComponentPanel/ComponentItem.tsx index 7e572667ce..6304ad5aa0 100644 --- a/apps/builder/src/page/App/components/ComponentPanel/ComponentItem.tsx +++ b/apps/builder/src/page/App/components/ComponentPanel/ComponentItem.tsx @@ -3,7 +3,7 @@ import { useDrag } from "react-dnd" import { useSelector } from "react-redux" import { ComponentItemProps } from "@/page/App/components/ComponentPanel/interface" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { getGuideStatus } from "@/redux/guide/guideSelector" import store from "@/store" import { endDragMultiNodes, startDragMultiNodes } from "@/utils/drag/drag" @@ -56,7 +56,7 @@ export const ComponentItem: FC = memo( } } const rootState = store.getState() - let allWidgetLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + let allWidgetLayoutInfo = getClientWidgetLayoutInfo(rootState) illaSnapshot.setSnapshot(allWidgetLayoutInfo) startDragMultiNodes([widgetLayoutInfo]) return { diff --git a/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderComponentCanvasContainer.tsx b/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderComponentCanvasContainer.tsx index d6b9e5279a..1e5fd61881 100644 --- a/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderComponentCanvasContainer.tsx +++ b/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderComponentCanvasContainer.tsx @@ -53,10 +53,10 @@ import { import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { getCurrentPageDisplayName, - getExecutionWidgetLayoutInfo, getIsDragging, getIsResizing, } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { FocusManager } from "@/utils/focusManager" import { newGenerateComponentNode } from "@/utils/generators/generateComponentNode" import { getPaddingShape } from "@/utils/styleUtils/padding" @@ -125,7 +125,7 @@ const RenderComponentCanvasContainer: FC< const unitWidth = fixedBounds.width / columnNumber const [canvasHeight, setCanvasHeight] = useState(fixedBounds.height) - const widgetLayoutInfo = useSelector(getExecutionWidgetLayoutInfo) + const widgetLayoutInfo = useSelector(getClientWidgetLayoutInfo) const childWidgetLayoutInfo = Object.values(widgetLayoutInfo).filter( (item) => item.parentNode === displayName, ) @@ -136,9 +136,8 @@ const RenderComponentCanvasContainer: FC< const isLikeProductMode = useSelector(getIsLikeProductMode) const isEditMode = useSelector(getIsILLAEditMode) - const layoutInfos = useSelector(getExecutionWidgetLayoutInfo) - const currentLayoutInfo = layoutInfos[displayName] + const currentLayoutInfo = widgetLayoutInfo[displayName] const [collectedProps, dropRef] = useDrop< DragInfo, diff --git a/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderModalCanvasContainer.tsx b/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderModalCanvasContainer.tsx index a76b006215..7bfe8b0cd3 100644 --- a/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderModalCanvasContainer.tsx +++ b/apps/builder/src/page/App/components/DotPanel/components/Canvas/renderModalCanvasContainer.tsx @@ -3,11 +3,9 @@ import { useDispatch, useSelector } from "react-redux" import useMeasure from "react-use-measure" import ComponentParser from "@/page/App/components/DotPanel/components/ComponentParser" import { DEFAULT_BODY_COLUMNS_NUMBER } from "@/page/App/components/DotPanel/constant/canvas" -import { - getExecutionResult, - getExecutionWidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionSelector" +import { getExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { RenderComponentCanvasContainerProps } from "./interface" import { maskStyle, outerModalCanvasContainerStyle } from "./style" @@ -28,7 +26,7 @@ export const RenderModalCanvasContainer: FC< const unitWidth = bounds.width / columnNumber - const layoutInfos = useSelector(getExecutionWidgetLayoutInfo) + const layoutInfos = useSelector(getClientWidgetLayoutInfo) const currentLayoutInfo = layoutInfos[displayName] diff --git a/apps/builder/src/page/App/components/DotPanel/components/ComponentParser/index.tsx b/apps/builder/src/page/App/components/DotPanel/components/ComponentParser/index.tsx index 9baa0ce831..d97dc07d39 100644 --- a/apps/builder/src/page/App/components/DotPanel/components/ComponentParser/index.tsx +++ b/apps/builder/src/page/App/components/DotPanel/components/ComponentParser/index.tsx @@ -2,13 +2,13 @@ import { FC, memo } from "react" import { useSelector } from "react-redux" import ScaleSquare from "@/page/App/components/ScaleSquare" import { ModalScaleSquare } from "@/page/App/components/ScaleSquare/modalScaleSquare" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { ComponentParserProps } from "./interface" const ComponentParser: FC = (props) => { const { displayName, unitW, parentNodeDisplayName, columnNumber } = props - const widgetLayoutInfo = useSelector(getExecutionWidgetLayoutInfo) + const widgetLayoutInfo = useSelector(getClientWidgetLayoutInfo) const currentWidgetLayoutInfo = widgetLayoutInfo[displayName] const containerType = currentWidgetLayoutInfo.containerType const widgetType = currentWidgetLayoutInfo.widgetType diff --git a/apps/builder/src/page/App/components/DotPanel/components/MultiSelectedContainer/index.tsx b/apps/builder/src/page/App/components/DotPanel/components/MultiSelectedContainer/index.tsx index fa9746da87..e35afad612 100644 --- a/apps/builder/src/page/App/components/DotPanel/components/MultiSelectedContainer/index.tsx +++ b/apps/builder/src/page/App/components/DotPanel/components/MultiSelectedContainer/index.tsx @@ -3,7 +3,7 @@ import { useSelector } from "react-redux" import { UNIT_HEIGHT } from "@/page/App/components/DotPanel/constant/canvas" import { getLargeItemShapeWithNodeScale } from "@/page/App/components/DotPanel/utils" import { getSelectedComponentDisplayNames } from "@/redux/config/configSelector" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { MultiSelectedScaleSquareProps, SelectedComponentWithShape, @@ -13,7 +13,7 @@ import { applyMultiSelectedScaleSquareStyle } from "./style" const MultiSelectedScaleSquare: FC = (props) => { const { unitW, containerDisplayName } = props const selectedComponents = useSelector(getSelectedComponentDisplayNames) - const widgetExecutionResult = useSelector(getExecutionWidgetLayoutInfo) + const widgetExecutionResult = useSelector(getClientWidgetLayoutInfo) const selectedComponentsWithShape: SelectedComponentWithShape[] = useMemo(() => { let result: SelectedComponentWithShape[] = [] diff --git a/apps/builder/src/page/App/components/DotPanel/constant/snapshotNew.ts b/apps/builder/src/page/App/components/DotPanel/constant/snapshotNew.ts index 159e78f61e..39f284abe2 100644 --- a/apps/builder/src/page/App/components/DotPanel/constant/snapshotNew.ts +++ b/apps/builder/src/page/App/components/DotPanel/constant/snapshotNew.ts @@ -1,4 +1,4 @@ -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" class SnapShot { snapshot: Record = {} diff --git a/apps/builder/src/page/App/components/DotPanel/utils/crossingHelper.ts b/apps/builder/src/page/App/components/DotPanel/utils/crossingHelper.ts index b80142da03..b43b56d2ce 100644 --- a/apps/builder/src/page/App/components/DotPanel/utils/crossingHelper.ts +++ b/apps/builder/src/page/App/components/DotPanel/utils/crossingHelper.ts @@ -1,4 +1,4 @@ -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import { illaSnapshot } from "../constant/snapshotNew" export interface NodeShape { diff --git a/apps/builder/src/page/App/components/DotPanel/utils/getDragShadow.ts b/apps/builder/src/page/App/components/DotPanel/utils/getDragShadow.ts index 14603bf920..0a521e799b 100644 --- a/apps/builder/src/page/App/components/DotPanel/utils/getDragShadow.ts +++ b/apps/builder/src/page/App/components/DotPanel/utils/getDragShadow.ts @@ -2,7 +2,7 @@ import { clamp } from "lodash-es" import { XYCoord } from "react-dnd" import { DRAG_EFFECT } from "@/page/App/components/ScaleSquare/components/DragContainer/interface" import { DEFAULT_MIN_COLUMN } from "@/page/App/components/ScaleSquare/constant/widget" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import { DragCollectedProps } from "../components/DragPreview/interface" import { DEFAULT_BODY_COLUMNS_NUMBER, UNIT_HEIGHT } from "../constant/canvas" import { getScrollBarContainerByDisplayName } from "../context/scrollBarContext" diff --git a/apps/builder/src/page/App/components/DotPanel/utils/getDropResult.ts b/apps/builder/src/page/App/components/DotPanel/utils/getDropResult.ts index 3f422e6a2d..9dbcee0b27 100644 --- a/apps/builder/src/page/App/components/DotPanel/utils/getDropResult.ts +++ b/apps/builder/src/page/App/components/DotPanel/utils/getDropResult.ts @@ -1,4 +1,4 @@ -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import { combineWidgetInfos } from "./getDragShadow" export interface DropResult { diff --git a/apps/builder/src/page/App/components/ScaleSquare/components/AutoHeightWithLimitedContainer/index.tsx b/apps/builder/src/page/App/components/ScaleSquare/components/AutoHeightWithLimitedContainer/index.tsx index bc90c54305..dc695bafb5 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/components/AutoHeightWithLimitedContainer/index.tsx +++ b/apps/builder/src/page/App/components/ScaleSquare/components/AutoHeightWithLimitedContainer/index.tsx @@ -11,11 +11,8 @@ import { import { applyBarHandlerStyle } from "@/page/App/components/ScaleSquare/style" import { configActions } from "@/redux/config/configSlice" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" -import { - getExecutionResult, - getExecutionWidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { getExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" export const DEFAULT_MAX_HEIGHT = 80 export const DEFAULT_MIN_GAP = 8 @@ -35,7 +32,7 @@ export const AutoHeightWithLimitedContainer: FC< const [resizeMaxHeight, setResizeMaxHeight] = useState(false) const [resizeMinHeight, setResizeMinHeight] = useState(false) const executionResult = useSelector(getExecutionResult) - const layoutInfoResult = useSelector(getExecutionWidgetLayoutInfo) + const layoutInfoResult = useSelector(getClientWidgetLayoutInfo) const dynamicMinHeight = get( executionResult, @@ -75,7 +72,7 @@ export const AutoHeightWithLimitedContainer: FC< setResizeMinHeight(true) dispatch(configActions.updateShowDot(true)) dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-minHeight`, ]), ) @@ -85,7 +82,7 @@ export const AutoHeightWithLimitedContainer: FC< setResizeMaxHeight(true) dispatch(configActions.updateShowDot(true)) dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-maxHeight`, ]), ) @@ -111,7 +108,7 @@ export const AutoHeightWithLimitedContainer: FC< ) dispatch(configActions.updateShowDot(false)) window.setTimeout(() => { - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, 16) }, [containerHeight, dispatch, displayName, dynamicMaxHeight], @@ -141,7 +138,7 @@ export const AutoHeightWithLimitedContainer: FC< }, 30) dispatch(configActions.updateShowDot(false)) window.setTimeout(() => { - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, 16) }, [ diff --git a/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/index.tsx b/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/index.tsx index 9e33f42218..d4269c3305 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/index.tsx +++ b/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/index.tsx @@ -12,11 +12,9 @@ import { getIsILLAEditMode, getSelectedComponentDisplayNames, } from "@/redux/config/configSelector" -import { - getExecutionWidgetLayoutInfo, - getIsResizing, -} from "@/redux/currentApp/executionTree/executionSelector" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { getIsResizing } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import store from "@/store" import { endDragMultiNodes, startDragMultiNodes } from "@/utils/drag/drag" import { trackInEditor } from "@/utils/mixpanelHelper" @@ -57,7 +55,7 @@ export const DragContainer: FC = (props) => { }, item: () => { const rootState = store.getState() - let allWidgetLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + let allWidgetLayoutInfo = getClientWidgetLayoutInfo(rootState) illaSnapshot.setSnapshot(allWidgetLayoutInfo) let draggedSelectedComponents: WidgetLayoutInfo[] = [] let currentSelectedComponents = selectedComponents diff --git a/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/interface.ts b/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/interface.ts index 95e0766348..8af4371767 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/interface.ts +++ b/apps/builder/src/page/App/components/ScaleSquare/components/DragContainer/interface.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" export interface DragContainerProps { children: ReactNode diff --git a/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/ResizeHandler/hooks.ts b/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/ResizeHandler/hooks.ts index adfcf498be..1de914e9ea 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/ResizeHandler/hooks.ts +++ b/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/ResizeHandler/hooks.ts @@ -13,12 +13,12 @@ import { sendShadowMessageHandler } from "@/page/App/components/DotPanel/utils/s import { getIsILLAEditMode } from "@/redux/config/configSelector" import { configActions } from "@/redux/config/configSlice" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" +import { layoutInfoActions } from "@/redux/currentApp/layoutInfo/layoutInfoSlice" import { BatchUpdateWidgetLayoutInfoPayload, WidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionState" +} from "@/redux/currentApp/layoutInfo/layoutInfoState" import store from "@/store" import { trackInEditor } from "@/utils/mixpanelHelper" import { BarPosition } from "./interface" @@ -43,10 +43,10 @@ export const useResizeStart = ( }, item: () => { const rootState = store.getState() - let allWidgetLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + let allWidgetLayoutInfo = getClientWidgetLayoutInfo(rootState) illaSnapshot.setSnapshot(allWidgetLayoutInfo) dispatch(configActions.updateShowDot(true)) - dispatch(executionActions.setResizingNodeIDsReducer([displayName])) + dispatch(configActions.setResizingNodeIDsReducer([displayName])) return { barPosition, @@ -105,7 +105,7 @@ export const useResize = () => { parentNode: currentWidgetSnapShot.parentNode, }), ) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) sendShadowMessageHandler(-1, "", [], 0, 0, 0, 0, 0, 0, 0, 0) trackInEditor(ILLA_MIXPANEL_EVENT_TYPE.DRAG, { @@ -220,7 +220,9 @@ export const useResizingUpdateRealTime = (isActive: boolean) => { ) }) } - dispatch(executionActions.batchUpdateWidgetLayoutInfoReducer(updateSlice)) + dispatch( + layoutInfoActions.batchUpdateWidgetLayoutInfoReducer(updateSlice), + ) }, 16) }, [dispatch]) diff --git a/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/index.tsx b/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/index.tsx index ca7e783743..5a53437058 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/index.tsx +++ b/apps/builder/src/page/App/components/ScaleSquare/components/ResizingAndDragContainer/index.tsx @@ -25,10 +25,10 @@ import { getFirstDragShadowInfo } from "@/redux/currentApp/dragShadow/dragShadow import { getExecutionError, getExecutionResult, - getExecutionWidgetLayoutInfo, getIsDragging, getResizingComponentIDs, } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import store from "@/store" import { CopyManager } from "@/utils/copyManager" import { FocusManager } from "@/utils/focusManager" @@ -72,7 +72,7 @@ export const ResizingAndDragContainer: FC = ( const isEditMode = useSelector(getIsILLAEditMode) const selectedComponents = useSelector(getSelectedComponentDisplayNames) const executionResult = useSelector(getExecutionResult) - const layoutInfoResult = useSelector(getExecutionWidgetLayoutInfo) + const layoutInfoResult = useSelector(getClientWidgetLayoutInfo) const currentWidgetLayoutInfo = layoutInfoResult[displayName] const currentWidgetProps = get(executionResult, displayName, {}) @@ -126,7 +126,7 @@ export const ResizingAndDragContainer: FC = ( const rootState = store.getState() const isEditMode = getIsILLAEditMode(rootState) const displayNameMapDepth = getComponentDisplayNameMapDepth(rootState) - const widgetExecutionLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + const widgetExecutionLayoutInfo = getClientWidgetLayoutInfo(rootState) e.stopPropagation() diff --git a/apps/builder/src/page/App/components/ScaleSquare/modalScaleSquare.tsx b/apps/builder/src/page/App/components/ScaleSquare/modalScaleSquare.tsx index a6a765b341..e944ae4c6d 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/modalScaleSquare.tsx +++ b/apps/builder/src/page/App/components/ScaleSquare/modalScaleSquare.tsx @@ -8,8 +8,7 @@ import { } from "@/redux/config/configSelector" import { configActions } from "@/redux/config/configSlice" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import { TransformWidgetWrapper } from "@/widgetLibrary/PublicSector/TransformWidgetWrapper" import { RESIZE_DIRECTION } from "@/widgetLibrary/interface" import { AutoHeightWithLimitedContainer } from "./components/AutoHeightWithLimitedContainer" @@ -34,7 +33,7 @@ export const ModalScaleSquare: FC = (props) => { const dispatch = useDispatch() - const layoutInfoResult = useSelector(getExecutionWidgetLayoutInfo) + const layoutInfoResult = useSelector(getClientWidgetLayoutInfo) const currentWidgetLayoutInfo = layoutInfoResult[displayName] const layoutInfo = currentWidgetLayoutInfo?.layoutInfo ?? {} @@ -72,7 +71,7 @@ export const ModalScaleSquare: FC = (props) => { parentNode: parentNodeDisplayName, }), ) - dispatch(executionActions.setDraggingNodeIDsReducer([])) + dispatch(configActions.setDraggingNodeIDsReducer([])) dispatch(configActions.updateShowDot(false)) }, @@ -91,7 +90,7 @@ export const ModalScaleSquare: FC = (props) => { (e) => { e.preventDefault() e.stopPropagation() - dispatch(executionActions.setDraggingNodeIDsReducer([displayName])) + dispatch(configActions.setDraggingNodeIDsReducer([displayName])) dispatch(configActions.updateShowDot(true)) }, diff --git a/apps/builder/src/page/App/components/ScaleSquare/utils/getRealShapeAndPosition.ts b/apps/builder/src/page/App/components/ScaleSquare/utils/getRealShapeAndPosition.ts index 2ccd203b49..3d8b548304 100644 --- a/apps/builder/src/page/App/components/ScaleSquare/utils/getRealShapeAndPosition.ts +++ b/apps/builder/src/page/App/components/ScaleSquare/utils/getRealShapeAndPosition.ts @@ -3,7 +3,7 @@ import { get } from "lodash-es" import { useMemo } from "react" import { useSelector } from "react-redux" import { UNIT_HEIGHT } from "@/page/App/components/DotPanel/constant/canvas" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import store from "@/store" export const getRealShapeAndPosition = ( @@ -12,7 +12,7 @@ export const getRealShapeAndPosition = ( displayNamePrefix?: string, ) => { const rootState = store.getState() - const executionResult = getExecutionWidgetLayoutInfo(rootState) + const executionResult = getClientWidgetLayoutInfo(rootState) let realDisplayName = componentNode.displayName if (displayNamePrefix) { realDisplayName = realDisplayName.replace(displayNamePrefix, "") @@ -50,7 +50,7 @@ export const useGetRealShapeAndPosition = ( unitW: number, displayNamePrefix?: string, ) => { - const layoutInfos = useSelector(getExecutionWidgetLayoutInfo) + const layoutInfos = useSelector(getClientWidgetLayoutInfo) const result = useMemo(() => { let realDisplayName = displayName diff --git a/apps/builder/src/page/App/index.tsx b/apps/builder/src/page/App/index.tsx index 5e9bb325e9..580c1d4472 100644 --- a/apps/builder/src/page/App/index.tsx +++ b/apps/builder/src/page/App/index.tsx @@ -40,6 +40,7 @@ import { setupActionListeners } from "@/redux/currentApp/action/actionListener" import { collaboratorsActions } from "@/redux/currentApp/collaborators/collaboratorsSlice" import { setupComponentsListeners } from "@/redux/currentApp/components/componentsListener" import { setupExecutionListeners } from "@/redux/currentApp/executionTree/executionListener" +import { setupLayoutInfoListeners } from "@/redux/currentApp/layoutInfo/layoutInfoListener" import { fetchAppBinaryWsUrl, fetchAppTextWsUrl } from "@/services/public" import { startAppListening } from "@/store" import { MediaSourceLoadProvider } from "@/utils/mediaSourceLoad" @@ -130,6 +131,7 @@ export const Editor: FC = () => { useEffect(() => { const subscriptions: Unsubscribe[] = [ setupExecutionListeners(startAppListening), + setupLayoutInfoListeners(startAppListening), setupComponentsListeners(startAppListening), setupActionListeners(startAppListening), setupConfigListeners(startAppListening), diff --git a/apps/builder/src/page/Deploy/content.tsx b/apps/builder/src/page/Deploy/content.tsx index d88e52ea59..0853cf4150 100644 --- a/apps/builder/src/page/Deploy/content.tsx +++ b/apps/builder/src/page/Deploy/content.tsx @@ -19,6 +19,7 @@ import { setupComponentsListeners } from "@/redux/currentApp/components/componen import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { setupExecutionListeners } from "@/redux/currentApp/executionTree/executionListener" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { setupLayoutInfoListeners } from "@/redux/currentApp/layoutInfo/layoutInfoListener" import { startAppListening } from "@/store" import { flatTreeToMap } from "@/utils/componentNode/flatTree" import { @@ -44,6 +45,7 @@ export const DeployContent: FC = () => { const subscriptions: Unsubscribe[] = [ setupComponentsListeners(startAppListening), setupExecutionListeners(startAppListening), + setupLayoutInfoListeners(startAppListening), ] return () => subscriptions.forEach((unsubscribe) => unsubscribe()) }, []) diff --git a/apps/builder/src/page/History/index.tsx b/apps/builder/src/page/History/index.tsx index a6d736664d..fa61af22f9 100644 --- a/apps/builder/src/page/History/index.tsx +++ b/apps/builder/src/page/History/index.tsx @@ -25,6 +25,7 @@ import { appInfoActions } from "@/redux/currentApp/appInfo/appInfoSlice" import { DashboardAppInitialState } from "@/redux/currentApp/appInfo/appInfoState" import { setupComponentsListeners } from "@/redux/currentApp/components/componentsListener" import { setupExecutionListeners } from "@/redux/currentApp/executionTree/executionListener" +import { setupLayoutInfoListeners } from "@/redux/currentApp/layoutInfo/layoutInfoListener" import { getCurrentAppSnapshotID } from "@/redux/currentAppHistory/currentAppHistorySelector" import { currentAppHistoryActions } from "@/redux/currentAppHistory/currentAppHistorySlice" import { fetchSnapShot } from "@/services/history" @@ -61,6 +62,7 @@ export const History: FC = () => { useEffect(() => { const subscriptions: Unsubscribe[] = [ setupExecutionListeners(startAppListening), + setupLayoutInfoListeners(startAppListening), setupComponentsListeners(startAppListening), setupActionListeners(startAppListening), setupConfigListeners(startAppListening), diff --git a/apps/builder/src/page/Template/GuideApp.tsx b/apps/builder/src/page/Template/GuideApp.tsx index b5525fef48..8b04d0ab8d 100644 --- a/apps/builder/src/page/Template/GuideApp.tsx +++ b/apps/builder/src/page/Template/GuideApp.tsx @@ -35,6 +35,7 @@ import { import { setupActionListeners } from "@/redux/currentApp/action/actionListener" import { setupComponentsListeners } from "@/redux/currentApp/components/componentsListener" import { setupExecutionListeners } from "@/redux/currentApp/executionTree/executionListener" +import { setupLayoutInfoListeners } from "@/redux/currentApp/layoutInfo/layoutInfoListener" import { getGuideStatus } from "@/redux/guide/guideSelector" import { startAppListening } from "@/store" import { MediaSourceLoadProvider } from "@/utils/mediaSourceLoad" @@ -65,6 +66,7 @@ const GuideApp: FC = () => { const subscriptions: Unsubscribe[] = [ setupExecutionListeners(startAppListening), setupComponentsListeners(startAppListening), + setupLayoutInfoListeners(startAppListening), setupActionListeners(startAppListening), setupConfigListeners(startAppListening), ] diff --git a/apps/builder/src/redux/config/configListener.ts b/apps/builder/src/redux/config/configListener.ts index a5c54eb353..e080aca183 100644 --- a/apps/builder/src/redux/config/configListener.ts +++ b/apps/builder/src/redux/config/configListener.ts @@ -1,9 +1,11 @@ -import { Unsubscribe } from "@reduxjs/toolkit" +import { UnknownAction, Unsubscribe, isAnyOf } from "@reduxjs/toolkit" import { configActions } from "@/redux/config/configSlice" import { AppListenerEffectAPI, AppStartListening } from "@/store" import { searchParent } from "@/utils/componentNode/search" import { updateCurrentAllComponentsAttachedUsers } from "../currentApp/collaborators/collaboratorsHandlers" -import { getExecutionWidgetLayoutInfo } from "../currentApp/executionTree/executionSelector" +import { cursorActions } from "../currentApp/cursor/cursorSlice" +import { getWidgetExecutionResult } from "../currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "../currentApp/layoutInfo/layoutInfoSelector" export const handleUpdateSelectedComponentExecution = ( action: ReturnType, @@ -11,7 +13,7 @@ export const handleUpdateSelectedComponentExecution = ( ) => { const currentComponentsAttachedUsers = listenerApi.getState().currentApp.collaborators.components - const widgetLayoutInfo = getExecutionWidgetLayoutInfo(listenerApi.getState()) + const widgetLayoutInfo = getClientWidgetLayoutInfo(listenerApi.getState()) const needExpandDisplayName = action.payload .map((displayName) => { @@ -34,6 +36,47 @@ async function handleChangeSelectedActionExecution( listenerApi.dispatch(configActions.updateCachedAction(action.payload)) } +const getAllChildrenDisplayName = ( + nodeDisplayName: string, + displayNameMapProps: Record, +): string[] => { + let result = [nodeDisplayName] + const node = displayNameMapProps[nodeDisplayName] + const children: string[] = node?.$childrenNode || [] + if (children.length > 0) { + children.forEach((child) => { + result = [ + ...result, + ...getAllChildrenDisplayName(child, displayNameMapProps), + ] + }) + } + return result +} + +const batchUpdateComponentStatusInfoEffect = ( + action: UnknownAction, + listenApi: AppListenerEffectAPI, +) => { + if ( + configActions.setDraggingNodeIDsReducer.match(action) || + configActions.setResizingNodeIDsReducer.match(action) + ) { + const { payload } = action + let allChildrenDisplayName: string[] = [] + const displayNameMapProps = getWidgetExecutionResult(listenApi.getState()) + payload.forEach((displayName) => { + allChildrenDisplayName = [ + ...allChildrenDisplayName, + ...getAllChildrenDisplayName(displayName, displayNameMapProps), + ] + }) + listenApi.dispatch( + cursorActions.filterCursorReducer(allChildrenDisplayName), + ) + } +} + export function setupConfigListeners( startListening: AppStartListening, ): Unsubscribe { @@ -46,6 +89,13 @@ export function setupConfigListeners( actionCreator: configActions.updateSelectedComponent, effect: handleUpdateSelectedComponentExecution, }), + startListening({ + matcher: isAnyOf( + configActions.setDraggingNodeIDsReducer, + configActions.setResizingNodeIDsReducer, + ), + effect: batchUpdateComponentStatusInfoEffect, + }), ] return () => { diff --git a/apps/builder/src/redux/config/configReducer.ts b/apps/builder/src/redux/config/configReducer.ts index a3ad4526d3..735d761a81 100644 --- a/apps/builder/src/redux/config/configReducer.ts +++ b/apps/builder/src/redux/config/configReducer.ts @@ -230,3 +230,17 @@ export const removeExpandWidgetReducer: CaseReducer< state.expandedWidgets[displayName] = false }) } + +export const setDraggingNodeIDsReducer: CaseReducer< + ConfigState, + PayloadAction +> = (state, action) => { + state.draggingComponentIDs = action.payload +} + +export const setResizingNodeIDsReducer: CaseReducer< + ConfigState, + PayloadAction +> = (state, action) => { + state.resizingComponentIDs = action.payload +} diff --git a/apps/builder/src/redux/config/configSelector.ts b/apps/builder/src/redux/config/configSelector.ts index 5e982e4c56..3538ce0e9a 100644 --- a/apps/builder/src/redux/config/configSelector.ts +++ b/apps/builder/src/redux/config/configSelector.ts @@ -3,7 +3,7 @@ import { ACTION_RUN_TIME } from "@illa-public/public-types" import { createSelector } from "@reduxjs/toolkit" import { RootState } from "@/store" -const getEditorConfig = (state: RootState) => { +export const getEditorConfig = (state: RootState) => { return state.config } diff --git a/apps/builder/src/redux/config/configSlice.ts b/apps/builder/src/redux/config/configSlice.ts index 5f9e1cf1d5..5bd758299f 100644 --- a/apps/builder/src/redux/config/configSlice.ts +++ b/apps/builder/src/redux/config/configSlice.ts @@ -9,7 +9,9 @@ import { removeExpandedKey, resetConfig, resetSelectedActionReducer, + setDraggingNodeIDsReducer, setExpandedKey, + setResizingNodeIDsReducer, updateBottomPanel, updateCachedAction, updateCachedActionAdvancedConfigReducer, @@ -55,6 +57,8 @@ const configSlice = createSlice({ resetSelectedActionReducer, addExpandedWidgetReducer, removeExpandWidgetReducer, + setDraggingNodeIDsReducer, + setResizingNodeIDsReducer, }, }) diff --git a/apps/builder/src/redux/config/configState.ts b/apps/builder/src/redux/config/configState.ts index 1d2f011799..5abb69a721 100644 --- a/apps/builder/src/redux/config/configState.ts +++ b/apps/builder/src/redux/config/configState.ts @@ -25,6 +25,8 @@ export interface ConfigState { isOnline: boolean wsStatus: Record hoveredComponents: string[] + draggingComponentIDs: string[] + resizingComponentIDs: string[] } export const ConfigInitialState: ConfigState = { @@ -50,4 +52,6 @@ export const ConfigInitialState: ConfigState = { [ILLA_WEBSOCKET_CONTEXT.APP_BINARY]: ILLA_WEBSOCKET_STATUS.INIT, [ILLA_WEBSOCKET_CONTEXT.AI_AGENT]: ILLA_WEBSOCKET_STATUS.INIT, }, + draggingComponentIDs: [], + resizingComponentIDs: [], } diff --git a/apps/builder/src/redux/currentApp/components/componentsListener.ts b/apps/builder/src/redux/currentApp/components/componentsListener.ts index dc1f03c1e7..08d60bcab0 100644 --- a/apps/builder/src/redux/currentApp/components/componentsListener.ts +++ b/apps/builder/src/redux/currentApp/components/componentsListener.ts @@ -19,15 +19,14 @@ import { } from "@/redux/currentApp/components/componentsSelector" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { cursorActions } from "@/redux/currentApp/cursor/cursorSlice" -import { - getExecutionResult, - getExecutionWidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionSelector" +import { getExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" import { AppListenerEffectAPI, AppStartListening } from "@/store" import { mixedChangeDisplayNameHelper } from "@/utils/changeDisplayNameHelper" import IllaUndoRedoManager from "@/utils/undoRedo/undo" +import { getClientWidgetLayoutInfo } from "../layoutInfo/layoutInfoSelector" +import { layoutInfoActions } from "../layoutInfo/layoutInfoSlice" +import { WidgetLayoutInfo } from "../layoutInfo/layoutInfoState" function handleUpdateComponentDisplayNameEffect( action: ReturnType< @@ -216,7 +215,7 @@ function handleUpdateComponentReflowEffect( action: AnyAction, listenApi: AppListenerEffectAPI, ) { - const currentLayoutInfo = getExecutionWidgetLayoutInfo(listenApi.getState()) + const currentLayoutInfo = getClientWidgetLayoutInfo(listenApi.getState()) const updateComponents = updateComponentReflowComponentsAdapter( action as ReturnType< | typeof componentsActions.addComponentReducer @@ -356,7 +355,7 @@ const handleUpdateDisplayNameEffect = ( const { displayName, newDisplayName } = action.payload mixedChangeDisplayNameHelper(listenerApi, displayName, newDisplayName) listenerApi.dispatch( - executionActions.updateWidgetLayoutInfoWhenChangeDisplayNameReducer({ + layoutInfoActions.updateWidgetLayoutInfoWhenChangeDisplayNameReducer({ oldDisplayName: displayName, newDisplayName, }), diff --git a/apps/builder/src/redux/currentApp/components/componentsSelector.ts b/apps/builder/src/redux/currentApp/components/componentsSelector.ts index b45d5a5908..b083ecd038 100644 --- a/apps/builder/src/redux/currentApp/components/componentsSelector.ts +++ b/apps/builder/src/redux/currentApp/components/componentsSelector.ts @@ -8,8 +8,8 @@ import { createSelector } from "@reduxjs/toolkit" import { get, set } from "lodash-es" import { DEFAULT_MIN_COLUMN } from "@/page/App/components/ScaleSquare/constant/widget" import { getSelectedComponentDisplayNames } from "@/redux/config/configSelector" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" import store, { RootState } from "@/store" +import { WidgetLayoutInfo } from "../layoutInfo/layoutInfoState" import { ComponentsState } from "./componentsState" export function searchDSLByDisplayName( diff --git a/apps/builder/src/redux/currentApp/executionTree/executionListener.ts b/apps/builder/src/redux/currentApp/executionTree/executionListener.ts index bb7d302ca2..4d8cedb4a6 100644 --- a/apps/builder/src/redux/currentApp/executionTree/executionListener.ts +++ b/apps/builder/src/redux/currentApp/executionTree/executionListener.ts @@ -1,33 +1,18 @@ -import { ComponentMapNode } from "@illa-public/public-types" -import { AnyAction, Unsubscribe, isAnyOf } from "@reduxjs/toolkit" +import { UnknownAction, Unsubscribe, isAnyOf } from "@reduxjs/toolkit" import { diff } from "deep-diff" -import { klona } from "klona/json" -import { - getNewPositionWithCrossing, - sortedRuleByYAndX, -} from "@/page/App/components/DotPanel/utils/crossingHelper" import { actionActions } from "@/redux/currentApp/action/actionSlice" import { - getAllComponentDisplayNameMapLayoutInfo, getComponentMap, searchComponentFromMap, - searchDSLByDisplayName, } from "@/redux/currentApp/components/componentsSelector" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { getExecutionResult, - getExecutionWidgetLayoutInfo, getRawTree, - getWidgetExecutionResult, } from "@/redux/currentApp/executionTree/executionSelector" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" import { AppListenerEffectAPI, AppStartListening } from "@/store" import { ExecutionTreeFactory } from "@/utils/executionTreeHelper/executionTreeFactory" -import { cursorActions } from "../cursor/cursorSlice" -import { - BatchUpdateWidgetLayoutInfoPayload, - WidgetLayoutInfo, -} from "./executionState" export let executionTree: ExecutionTreeFactory | undefined @@ -76,7 +61,7 @@ const asyncExecutionDataToRedux = ( } async function handleStartExecution( - action: AnyAction, + action: UnknownAction, listenerApi: AppListenerEffectAPI, ) { const rootState = listenerApi.getState() @@ -98,7 +83,7 @@ async function handleStartExecution( } async function handleStartExecutionOnCanvas( - action: AnyAction, + action: UnknownAction, listenerApi: AppListenerEffectAPI, ) { const rootState = listenerApi.getState() @@ -128,137 +113,6 @@ async function handleStartExecutionOnCanvas( } } -async function handleUpdateReflowEffect( - action: ReturnType, - listenerApi: AppListenerEffectAPI, -) { - const rootState = listenerApi.getState() - const widgetLayoutInfos = getExecutionWidgetLayoutInfo(rootState) - const components = getComponentMap(rootState) - let updateSlice: BatchUpdateWidgetLayoutInfoPayload[] = [] - - const { layoutInfo, displayName, parentNode } = action.payload - - const originNodes = searchDSLByDisplayName(parentNode) - - let originChildrenNode: ComponentMapNode[] = [] - - if ( - originNodes && - originNodes.childrenNode && - originNodes.childrenNode.length > 0 - ) { - originChildrenNode = originNodes.childrenNode.map( - (displayName) => components[displayName], - ) - } - - const mainNodeLayoutInfo = { - ...widgetLayoutInfos[displayName].layoutInfo, - h: layoutInfo.h ?? widgetLayoutInfos[displayName].layoutInfo.h, - } - - if (originChildrenNode.length > 0) { - originChildrenNode - .filter((node) => node.displayName !== displayName) - .forEach((node) => { - const layoutInfo = widgetLayoutInfos[node.displayName].layoutInfo - updateSlice.push({ - displayName: node.displayName, - layoutInfo: { - x: layoutInfo.x, - y: node.y, - w: layoutInfo.w, - h: layoutInfo.h, - }, - }) - }) - } - - const effectMap = getNewPositionWithCrossing( - { - ...mainNodeLayoutInfo, - }, - parentNode, - [displayName], - Object.values(widgetLayoutInfos).filter( - (item) => item.parentNode === parentNode, - ), - ) - - if (effectMap && effectMap.size > 0) { - effectMap.forEach((widgetLayoutInfo) => { - const oldSliceIndex = updateSlice.findIndex( - (slice) => slice.displayName === widgetLayoutInfo.displayName, - ) - if (oldSliceIndex !== -1) { - updateSlice.splice(oldSliceIndex, 1) - } - updateSlice.push({ - displayName: widgetLayoutInfo.displayName, - layoutInfo: { - x: widgetLayoutInfo.layoutInfo.x, - y: widgetLayoutInfo.layoutInfo.y, - w: widgetLayoutInfo.layoutInfo.w, - h: widgetLayoutInfo.layoutInfo.h, - }, - }) - }) - } - - const currentLayoutInfos = klona(widgetLayoutInfos) - - updateSlice.forEach((slice) => { - if (currentLayoutInfos[slice.displayName]) { - currentLayoutInfos[slice.displayName] = { - ...currentLayoutInfos[slice.displayName], - layoutInfo: { - ...currentLayoutInfos[slice.displayName].layoutInfo, - ...slice.layoutInfo!, - }, - } - } - }) - - const currentLayoutInfosArray = Object.values(currentLayoutInfos) - .filter((info) => info.parentNode === parentNode) - .sort(sortedRuleByYAndX) - - let effectName: string[] = [] - currentLayoutInfosArray.forEach((item) => { - effectName.push(item.displayName) - const effectMap = getNewPositionWithCrossing( - item.layoutInfo, - parentNode, - effectName, - currentLayoutInfosArray, - ) - if (effectMap && effectMap.size > 0) { - effectMap.forEach((widgetLayoutInfo) => { - const oldSliceIndex = updateSlice.findIndex( - (slice) => slice.displayName === widgetLayoutInfo.displayName, - ) - if (oldSliceIndex !== -1) { - updateSlice.splice(oldSliceIndex, 1) - } - updateSlice.push({ - displayName: widgetLayoutInfo.displayName, - layoutInfo: { - x: widgetLayoutInfo.layoutInfo.x, - y: widgetLayoutInfo.layoutInfo.y, - w: widgetLayoutInfo.layoutInfo.w, - h: widgetLayoutInfo.layoutInfo.h, - }, - }) - }) - } - }) - - listenerApi.dispatch( - executionActions.batchUpdateWidgetLayoutInfoReducer(updateSlice), - ) -} - function handleUpdateModalEffect( action: ReturnType, listenerApi: AppListenerEffectAPI, @@ -296,139 +150,6 @@ function handleUpdateModalEffect( ) } -const updateWidgetPositionAdapter = ( - action: ReturnType< - | typeof componentsActions.addComponentReducer - | typeof componentsActions.updateComponentLayoutInfoReducer - | typeof componentsActions.updateComponentPositionReducer - | typeof componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer - >, -) => { - let effectDisplayNames: string[] = [] - - switch (action.type) { - case "components/addComponentReducer": { - const { payload } = action - payload.forEach((item) => { - effectDisplayNames.push(item.displayName) - }) - break - } - case "components/updateComponentLayoutInfoReducer": { - const { payload } = action - const { displayName } = payload - effectDisplayNames.push(displayName) - break - } - case "components/updateComponentPositionReducer": { - const { payload } = action - payload.updateSlices.forEach((item) => { - effectDisplayNames.push(item.displayName) - }) - break - } - case "components/batchUpdateComponentLayoutInfoWhenReflowReducer": { - const { payload } = action - payload.forEach((item) => { - effectDisplayNames.push(item.displayName) - }) - break - } - } - return effectDisplayNames -} - -function handleUpdateWidgetPositionInExecutionLayoutInfo( - action: AnyAction, - listenerApi: AppListenerEffectAPI, -) { - const rootState = listenerApi.getState() - let displayNameMapNode = getAllComponentDisplayNameMapLayoutInfo(rootState) - if (!displayNameMapNode) return - const executionLayoutInfos = getExecutionWidgetLayoutInfo(rootState) - let setWidgetLayoutInfoReducerActionPayload: Record< - string, - WidgetLayoutInfo - > = {} - let effectDisplayNames: string[] = updateWidgetPositionAdapter( - action as ReturnType< - | typeof componentsActions.addComponentReducer - | typeof componentsActions.updateComponentLayoutInfoReducer - | typeof componentsActions.updateComponentPositionReducer - | typeof componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer - >, - ) - - Object.keys(displayNameMapNode).forEach((displayName) => { - if ( - (displayNameMapNode as Record)[displayName] && - executionLayoutInfos[displayName] && - effectDisplayNames.indexOf(displayName) === -1 - ) { - setWidgetLayoutInfoReducerActionPayload[displayName] = { - ...(displayNameMapNode as Record)[ - displayName - ], - layoutInfo: { - ...(displayNameMapNode as Record)[ - displayName - ].layoutInfo, - y: executionLayoutInfos[displayName].layoutInfo.y, - h: executionLayoutInfos[displayName].layoutInfo.h, - }, - } - } else { - setWidgetLayoutInfoReducerActionPayload[displayName] = { - ...(displayNameMapNode as Record)[ - displayName - ], - } - } - }) - listenerApi.dispatch( - executionActions.setWidgetLayoutInfoReducer( - setWidgetLayoutInfoReducerActionPayload, - ), - ) -} - -const getAllChildrenDisplayName = ( - nodeDisplayName: string, - displayNameMapProps: Record, -): string[] => { - let result = [nodeDisplayName] - const node = displayNameMapProps[nodeDisplayName] - const children: string[] = node?.$childrenNode || [] - if (children.length > 0) { - children.forEach((child) => { - result = [ - ...result, - ...getAllChildrenDisplayName(child, displayNameMapProps), - ] - }) - } - return result -} - -const batchUpdateComponentStatusInfoEffect = ( - action: AnyAction, - listenApi: AppListenerEffectAPI, -) => { - const { payload } = action as ReturnType< - | typeof executionActions.setDraggingNodeIDsReducer - | typeof executionActions.setResizingNodeIDsReducer - > - let allChildrenDisplayName: string[] = [] - const displayNameMapProps = getWidgetExecutionResult(listenApi.getState()) - payload.forEach((displayName) => { - allChildrenDisplayName = [ - ...allChildrenDisplayName, - ...getAllChildrenDisplayName(displayName, displayNameMapProps), - ] - }) - listenApi.dispatch(cursorActions.filterCursorReducer(allChildrenDisplayName)) -} - export function setupExecutionListeners( startListening: AppStartListening, ): Unsubscribe { @@ -487,39 +208,6 @@ export function setupExecutionListeners( actionCreator: componentsActions.addModalComponentReducer, effect: handleUpdateModalEffect, }), - startListening({ - actionCreator: executionActions.updateWidgetLayoutInfoReducer, - effect: handleUpdateReflowEffect, - }), - startListening({ - matcher: isAnyOf( - componentsActions.deleteComponentNodeReducer, - componentsActions.addTargetPageSectionReducer, - componentsActions.deleteTargetPageSectionReducer, - componentsActions.addPageNodeWithSortOrderReducer, - componentsActions.deletePageNodeReducer, - componentsActions.addSectionViewReducer, - componentsActions.addSectionViewConfigByConfigReducer, - componentsActions.deleteSectionViewReducer, - componentsActions.addModalComponentReducer, - componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer, - componentsActions.addComponentReducer, - componentsActions.updateTargetPageLayoutReducer, - componentsActions.updateSectionViewPropsReducer, - componentsActions.updateComponentDisplayNameReducer, - componentsActions.updateComponentPositionReducer, - componentsActions.addSubPageReducer, - executionActions.startExecutionReducer, - ), - effect: handleUpdateWidgetPositionInExecutionLayoutInfo, - }), - startListening({ - matcher: isAnyOf( - executionActions.setDraggingNodeIDsReducer, - executionActions.setResizingNodeIDsReducer, - ), - effect: batchUpdateComponentStatusInfoEffect, - }), ] return () => { diff --git a/apps/builder/src/redux/currentApp/executionTree/executionReducer.ts b/apps/builder/src/redux/currentApp/executionTree/executionReducer.ts index 7691f9fb17..5ba7f402d2 100644 --- a/apps/builder/src/redux/currentApp/executionTree/executionReducer.ts +++ b/apps/builder/src/redux/currentApp/executionTree/executionReducer.ts @@ -2,13 +2,11 @@ import { CaseReducer, PayloadAction } from "@reduxjs/toolkit" import { applyChange } from "deep-diff" import { has, set } from "lodash-es" import { - BatchUpdateWidgetLayoutInfoPayload, DependenciesState, ErrorShape, ExecutionState, UpdateCurrentPagePathPayload, UpdateExecutionByDisplayNamePayload, - UpdateWidgetLayoutInfoPayload, executionInitialState, setExecutionResultPayload, } from "@/redux/currentApp/executionTree/executionState" @@ -134,61 +132,6 @@ export const resetExecutionResultReducer: CaseReducer< return executionInitialState } -export const setWidgetLayoutInfoReducer: CaseReducer< - ExecutionState, - PayloadAction -> = (state, action) => { - state.widgetsLayoutInfo = action.payload -} - -export const updateWidgetLayoutInfoReducer: CaseReducer< - ExecutionState, - PayloadAction -> = (state, action) => { - if (!state) return - const { displayName, layoutInfo } = action.payload - const widgetsLayoutInfo = state.widgetsLayoutInfo - const currentWidget = widgetsLayoutInfo[displayName] - if (!currentWidget || !layoutInfo || Object.keys(layoutInfo).length === 0) { - return - } - currentWidget.layoutInfo = { - ...currentWidget.layoutInfo, - ...layoutInfo, - } -} - -export const batchUpdateWidgetLayoutInfoReducer: CaseReducer< - ExecutionState, - PayloadAction -> = (state, action) => { - if (!state) return - action.payload.forEach((updateSlice) => { - const { displayName, layoutInfo } = updateSlice - const widgetsLayoutInfo = state.widgetsLayoutInfo - const currentWidget = widgetsLayoutInfo[displayName] - if (!currentWidget || !layoutInfo || Object.keys(layoutInfo).length === 0) { - return - } - currentWidget.layoutInfo = { - ...currentWidget.layoutInfo, - ...layoutInfo, - } - }) -} - -export const updateWidgetLayoutInfoWhenChangeDisplayNameReducer: CaseReducer< - ExecutionState, - PayloadAction<{ oldDisplayName: string; newDisplayName: string }> -> = (state, action) => { - const { oldDisplayName, newDisplayName } = action.payload - const widgetsLayoutInfo = state.widgetsLayoutInfo - const currentWidget = widgetsLayoutInfo[oldDisplayName] - if (!currentWidget) return - delete widgetsLayoutInfo[oldDisplayName] - widgetsLayoutInfo[newDisplayName] = currentWidget -} - export const setGlobalStateInExecutionReducer: CaseReducer< ExecutionState, PayloadAction<{ @@ -263,20 +206,6 @@ export const setLocalStorageInExecutionReducer: CaseReducer< ) } -export const setDraggingNodeIDsReducer: CaseReducer< - ExecutionState, - PayloadAction -> = (state, action) => { - state.draggingComponentIDs = action.payload -} - -export const setResizingNodeIDsReducer: CaseReducer< - ExecutionState, - PayloadAction -> = (state, action) => { - state.resizingComponentIDs = action.payload -} - export const updateCurrentPagePathReducer: CaseReducer< ExecutionState, PayloadAction diff --git a/apps/builder/src/redux/currentApp/executionTree/executionSelector.ts b/apps/builder/src/redux/currentApp/executionTree/executionSelector.ts index 47641c5d4f..2586e815c4 100644 --- a/apps/builder/src/redux/currentApp/executionTree/executionSelector.ts +++ b/apps/builder/src/redux/currentApp/executionTree/executionSelector.ts @@ -13,8 +13,10 @@ import { RootState } from "@/store" import { NeedBuildNode, buildForest } from "@/utils/componentNode/buildTree" import { RawTreeFactory } from "@/utils/executionTreeHelper/rawTreeFactory" import { recursiveDelete } from "@/utils/executionTreeHelper/rrecursiveDelete" -import { ExecutionState, WidgetLayoutInfo } from "./executionState" -import { getAllDescendantNodeDisplayNamesByExecution } from "./utils" +import { getEditorConfig } from "../../config/configSelector" +import { getClientWidgetLayoutInfo } from "../layoutInfo/layoutInfoSelector" +import { WidgetLayoutInfo } from "../layoutInfo/layoutInfoState" +import { getAllDescendantNodeDisplayNamesByExecution } from "../layoutInfo/utils" export const getRawTree = createSelector( [ @@ -35,12 +37,18 @@ export const getRawTree = createSelector( }, ) -export const getExecution = (state: RootState) => - state.currentApp.execution as ExecutionState +export const getCurrentApp = (state: RootState) => state.currentApp + +export const getExecution = createSelector( + [getCurrentApp], + (currentApp) => currentApp.execution, +) export const getExecutionResult = createSelector( [getExecution], - (execution) => execution.result || {}, + (execution) => { + return execution.result || {} + }, ) export const getExecutionError = createSelector( @@ -313,11 +321,6 @@ export const getGlobalInfoExecutionResult = createSelector( }, ) -export const getExecutionWidgetLayoutInfo = createSelector( - [getExecution], - (execution) => execution.widgetsLayoutInfo, -) - export const getPageLoadingActions = createSelector( [getActionExecutionResultArray], (actionResult) => { @@ -464,7 +467,7 @@ const getTargetSectionWidget = ( } export const getCurrentPageBodyWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -478,7 +481,7 @@ export const getCurrentPageBodyWidgetTree = createSelector( ) export const getCurrentPageFooterWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -491,7 +494,7 @@ export const getCurrentPageFooterWidgetTree = createSelector( }, ) export const getCurrentPageLeftWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -504,7 +507,7 @@ export const getCurrentPageLeftWidgetTree = createSelector( }, ) export const getCurrentPageHeaderWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -517,7 +520,7 @@ export const getCurrentPageHeaderWidgetTree = createSelector( }, ) export const getCurrentPageRightWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -530,7 +533,7 @@ export const getCurrentPageRightWidgetTree = createSelector( }, ) export const getCurrentPageModalWidgetTree = createSelector( - [getCurrentPageWidgetExecutionResultArray, getExecutionWidgetLayoutInfo], + [getCurrentPageWidgetExecutionResultArray, getClientWidgetLayoutInfo], (currentPageWidgets, widgets) => { return buildForest( getTargetSectionWidget( @@ -544,14 +547,14 @@ export const getCurrentPageModalWidgetTree = createSelector( ) export const getDraggingComponentIDs = createSelector( - [getExecution], - (execution) => execution.draggingComponentIDs, + [getEditorConfig], + (editorConfig) => editorConfig.draggingComponentIDs, ) export const getResizingComponentIDs = createSelector( - [getExecution], - (execution) => { - return execution.resizingComponentIDs + [getEditorConfig], + (editorConfig) => { + return editorConfig.resizingComponentIDs }, ) diff --git a/apps/builder/src/redux/currentApp/executionTree/executionSlice.ts b/apps/builder/src/redux/currentApp/executionTree/executionSlice.ts index 77bd503291..db8bb56c60 100644 --- a/apps/builder/src/redux/currentApp/executionTree/executionSlice.ts +++ b/apps/builder/src/redux/currentApp/executionTree/executionSlice.ts @@ -1,10 +1,8 @@ import { createSlice } from "@reduxjs/toolkit" import { - batchUpdateWidgetLayoutInfoReducer, clearLocalStorageInExecutionReducer, resetExecutionResultReducer, setDependenciesReducer, - setDraggingNodeIDsReducer, setExecutionDebuggerDataReducer, setExecutionErrorReducer, setExecutionResultReducer, @@ -12,15 +10,11 @@ import { setInGlobalStateInExecutionReducer, setIndependenciesReducer, setLocalStorageInExecutionReducer, - setResizingNodeIDsReducer, - setWidgetLayoutInfoReducer, startExecutionReducer, updateCurrentPagePathReducer, updateExecutionByDisplayNameReducer, updateExecutionByMultiDisplayNameReducer, updateModalDisplayReducer, - updateWidgetLayoutInfoReducer, - updateWidgetLayoutInfoWhenChangeDisplayNameReducer, } from "@/redux/currentApp/executionTree/executionReducer" import { executionInitialState } from "@/redux/currentApp/executionTree/executionState" @@ -38,16 +32,10 @@ const executionSlice = createSlice({ updateExecutionByMultiDisplayNameReducer, updateModalDisplayReducer, resetExecutionResultReducer, - setWidgetLayoutInfoReducer, - updateWidgetLayoutInfoReducer, - batchUpdateWidgetLayoutInfoReducer, setGlobalStateInExecutionReducer, setInGlobalStateInExecutionReducer, clearLocalStorageInExecutionReducer, setLocalStorageInExecutionReducer, - updateWidgetLayoutInfoWhenChangeDisplayNameReducer, - setDraggingNodeIDsReducer, - setResizingNodeIDsReducer, updateCurrentPagePathReducer, }, }) diff --git a/apps/builder/src/redux/currentApp/executionTree/executionState.ts b/apps/builder/src/redux/currentApp/executionTree/executionState.ts index d8336bf695..6bd95d61a8 100644 --- a/apps/builder/src/redux/currentApp/executionTree/executionState.ts +++ b/apps/builder/src/redux/currentApp/executionTree/executionState.ts @@ -1,6 +1,4 @@ -import { CONTAINER_TYPE } from "@illa-public/public-types" import { Diff } from "deep-diff" -import { LayoutInfo } from "@/redux/currentApp/components/componentsPayload" export enum ExecutionErrorType { EVALUATED = "EVALUATED", @@ -17,24 +15,12 @@ export interface ErrorShape { } export type DependenciesState = Record -export interface WidgetLayoutInfo { - displayName: string - widgetType: string - layoutInfo: LayoutInfo - parentNode: string - containerType: CONTAINER_TYPE - childrenNode: string[] -} - export interface ExecutionState { dependencies: DependenciesState result: Record error: Record debuggerData: Record independencies: DependenciesState - widgetsLayoutInfo: Record - draggingComponentIDs: string[] - resizingComponentIDs: string[] } export const executionInitialState: ExecutionState = { @@ -43,9 +29,6 @@ export const executionInitialState: ExecutionState = { error: {}, debuggerData: {}, independencies: {}, - widgetsLayoutInfo: {}, - draggingComponentIDs: [], - resizingComponentIDs: [], } export interface setExecutionResultPayload { @@ -57,18 +40,6 @@ export interface UpdateExecutionByDisplayNamePayload { value: Record } -export interface UpdateWidgetLayoutInfoPayload { - displayName: string - layoutInfo: Partial - parentNode: string - effectRows?: number -} - -export interface BatchUpdateWidgetLayoutInfoPayload { - displayName: string - layoutInfo: Partial -} - export interface UpdateCurrentPagePathPayload { pageDisplayName: string subPagePath?: string diff --git a/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoListener.ts b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoListener.ts new file mode 100644 index 0000000000..1db90ce38e --- /dev/null +++ b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoListener.ts @@ -0,0 +1,288 @@ +import { ComponentMapNode } from "@illa-public/public-types" +import { UnknownAction, Unsubscribe, isAnyOf } from "@reduxjs/toolkit" +import { klona } from "klona/json" +import { + getNewPositionWithCrossing, + sortedRuleByYAndX, +} from "@/page/App/components/DotPanel/utils/crossingHelper" +import { + getAllComponentDisplayNameMapLayoutInfo, + getComponentMap, + searchDSLByDisplayName, +} from "@/redux/currentApp/components/componentsSelector" +import { componentsActions } from "@/redux/currentApp/components/componentsSlice" +import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { AppListenerEffectAPI, AppStartListening } from "@/store" +import { getClientWidgetLayoutInfo } from "./layoutInfoSelector" +import { layoutInfoActions } from "./layoutInfoSlice" +import { + BatchUpdateWidgetLayoutInfoPayload, + WidgetLayoutInfo, +} from "./layoutInfoState" + +async function handleUpdateReflowEffect( + action: ReturnType, + listenerApi: AppListenerEffectAPI, +) { + const rootState = listenerApi.getState() + const widgetLayoutInfos = getClientWidgetLayoutInfo(rootState) + const components = getComponentMap(rootState) + let updateSlice: BatchUpdateWidgetLayoutInfoPayload[] = [] + + const { layoutInfo, displayName, parentNode } = action.payload + + const originNodes = searchDSLByDisplayName(parentNode) + + let originChildrenNode: ComponentMapNode[] = [] + + if ( + originNodes && + originNodes.childrenNode && + originNodes.childrenNode.length > 0 + ) { + originChildrenNode = originNodes.childrenNode.map( + (displayName) => components[displayName], + ) + } + + const mainNodeLayoutInfo = { + ...widgetLayoutInfos[displayName].layoutInfo, + h: layoutInfo.h ?? widgetLayoutInfos[displayName].layoutInfo.h, + } + + if (originChildrenNode.length > 0) { + originChildrenNode + .filter((node) => node.displayName !== displayName) + .forEach((node) => { + const layoutInfo = widgetLayoutInfos[node.displayName].layoutInfo + updateSlice.push({ + displayName: node.displayName, + layoutInfo: { + x: layoutInfo.x, + y: node.y, + w: layoutInfo.w, + h: layoutInfo.h, + }, + }) + }) + } + + const effectMap = getNewPositionWithCrossing( + { + ...mainNodeLayoutInfo, + }, + parentNode, + [displayName], + Object.values(widgetLayoutInfos).filter( + (item) => item.parentNode === parentNode, + ), + ) + + if (effectMap && effectMap.size > 0) { + effectMap.forEach((widgetLayoutInfo) => { + const oldSliceIndex = updateSlice.findIndex( + (slice) => slice.displayName === widgetLayoutInfo.displayName, + ) + if (oldSliceIndex !== -1) { + updateSlice.splice(oldSliceIndex, 1) + } + updateSlice.push({ + displayName: widgetLayoutInfo.displayName, + layoutInfo: { + x: widgetLayoutInfo.layoutInfo.x, + y: widgetLayoutInfo.layoutInfo.y, + w: widgetLayoutInfo.layoutInfo.w, + h: widgetLayoutInfo.layoutInfo.h, + }, + }) + }) + } + + const currentLayoutInfos = klona(widgetLayoutInfos) + + updateSlice.forEach((slice) => { + if (currentLayoutInfos[slice.displayName]) { + currentLayoutInfos[slice.displayName] = { + ...currentLayoutInfos[slice.displayName], + layoutInfo: { + ...currentLayoutInfos[slice.displayName].layoutInfo, + ...slice.layoutInfo!, + }, + } + } + }) + + const currentLayoutInfosArray = Object.values(currentLayoutInfos) + .filter((info) => info.parentNode === parentNode) + .sort(sortedRuleByYAndX) + + let effectName: string[] = [] + currentLayoutInfosArray.forEach((item) => { + effectName.push(item.displayName) + const effectMap = getNewPositionWithCrossing( + item.layoutInfo, + parentNode, + effectName, + currentLayoutInfosArray, + ) + if (effectMap && effectMap.size > 0) { + effectMap.forEach((widgetLayoutInfo) => { + const oldSliceIndex = updateSlice.findIndex( + (slice) => slice.displayName === widgetLayoutInfo.displayName, + ) + if (oldSliceIndex !== -1) { + updateSlice.splice(oldSliceIndex, 1) + } + updateSlice.push({ + displayName: widgetLayoutInfo.displayName, + layoutInfo: { + x: widgetLayoutInfo.layoutInfo.x, + y: widgetLayoutInfo.layoutInfo.y, + w: widgetLayoutInfo.layoutInfo.w, + h: widgetLayoutInfo.layoutInfo.h, + }, + }) + }) + } + }) + + listenerApi.dispatch( + layoutInfoActions.batchUpdateWidgetLayoutInfoReducer(updateSlice), + ) +} + +const updateWidgetPositionAdapter = ( + action: ReturnType< + | typeof componentsActions.addComponentReducer + | typeof componentsActions.updateComponentLayoutInfoReducer + | typeof componentsActions.updateComponentPositionReducer + | typeof componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer + >, +) => { + let effectDisplayNames: string[] = [] + + switch (action.type) { + case "components/addComponentReducer": { + const { payload } = action + payload.forEach((item) => { + effectDisplayNames.push(item.displayName) + }) + break + } + case "components/updateComponentLayoutInfoReducer": { + const { payload } = action + const { displayName } = payload + effectDisplayNames.push(displayName) + break + } + case "components/updateComponentPositionReducer": { + const { payload } = action + payload.updateSlices.forEach((item) => { + effectDisplayNames.push(item.displayName) + }) + break + } + case "components/batchUpdateComponentLayoutInfoWhenReflowReducer": { + const { payload } = action + payload.forEach((item) => { + effectDisplayNames.push(item.displayName) + }) + break + } + } + return effectDisplayNames +} + +function handleUpdateWidgetPositionInExecutionLayoutInfo( + action: UnknownAction, + listenerApi: AppListenerEffectAPI, +) { + const rootState = listenerApi.getState() + let displayNameMapNode = getAllComponentDisplayNameMapLayoutInfo(rootState) + if (!displayNameMapNode) return + const executionLayoutInfos = getClientWidgetLayoutInfo(rootState) + let setWidgetLayoutInfoReducerActionPayload: Record< + string, + WidgetLayoutInfo + > = {} + let effectDisplayNames: string[] = [] + if ( + componentsActions.addComponentReducer.match(action) || + componentsActions.updateComponentLayoutInfoReducer.match(action) || + componentsActions.updateComponentPositionReducer.match(action) || + componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer.match( + action, + ) + ) { + effectDisplayNames = updateWidgetPositionAdapter(action) + } + + Object.keys(displayNameMapNode).forEach((displayName) => { + if ( + (displayNameMapNode as Record)[displayName] && + executionLayoutInfos[displayName] && + effectDisplayNames.indexOf(displayName) === -1 + ) { + setWidgetLayoutInfoReducerActionPayload[displayName] = { + ...(displayNameMapNode as Record)[ + displayName + ], + layoutInfo: { + ...(displayNameMapNode as Record)[ + displayName + ].layoutInfo, + y: executionLayoutInfos[displayName].layoutInfo.y, + h: executionLayoutInfos[displayName].layoutInfo.h, + }, + } + } else { + setWidgetLayoutInfoReducerActionPayload[displayName] = { + ...(displayNameMapNode as Record)[ + displayName + ], + } + } + }) + listenerApi.dispatch( + layoutInfoActions.setWidgetLayoutInfoReducer( + setWidgetLayoutInfoReducerActionPayload, + ), + ) +} + +export function setupLayoutInfoListeners( + startListening: AppStartListening, +): Unsubscribe { + const subscriptions = [ + startListening({ + actionCreator: layoutInfoActions.updateWidgetLayoutInfoReducer, + effect: handleUpdateReflowEffect, + }), + startListening({ + matcher: isAnyOf( + componentsActions.deleteComponentNodeReducer, + componentsActions.addTargetPageSectionReducer, + componentsActions.deleteTargetPageSectionReducer, + componentsActions.addPageNodeWithSortOrderReducer, + componentsActions.deletePageNodeReducer, + componentsActions.addSectionViewReducer, + componentsActions.addSectionViewConfigByConfigReducer, + componentsActions.deleteSectionViewReducer, + componentsActions.addModalComponentReducer, + componentsActions.batchUpdateComponentLayoutInfoWhenReflowReducer, + componentsActions.addComponentReducer, + componentsActions.updateTargetPageLayoutReducer, + componentsActions.updateSectionViewPropsReducer, + componentsActions.updateComponentDisplayNameReducer, + componentsActions.updateComponentPositionReducer, + componentsActions.addSubPageReducer, + executionActions.startExecutionReducer, + ), + effect: handleUpdateWidgetPositionInExecutionLayoutInfo, + }), + ] + + return () => { + subscriptions.forEach((unsubscribe) => unsubscribe()) + } +} diff --git a/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoReducer.ts b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoReducer.ts new file mode 100644 index 0000000000..9c3fbe82a1 --- /dev/null +++ b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoReducer.ts @@ -0,0 +1,61 @@ +import { CaseReducer, PayloadAction } from "@reduxjs/toolkit" +import { + BatchUpdateWidgetLayoutInfoPayload, + LayoutInfoState, + UpdateWidgetLayoutInfoPayload, +} from "./layoutInfoState" + +export const setWidgetLayoutInfoReducer: CaseReducer< + LayoutInfoState, + PayloadAction +> = (state, action) => { + state.widgetsLayoutInfo = action.payload +} + +export const updateWidgetLayoutInfoReducer: CaseReducer< + LayoutInfoState, + PayloadAction +> = (state, action) => { + if (!state) return + const { displayName, layoutInfo } = action.payload + const widgetsLayoutInfo = state.widgetsLayoutInfo + const currentWidget = widgetsLayoutInfo[displayName] + if (!currentWidget || !layoutInfo || Object.keys(layoutInfo).length === 0) { + return + } + currentWidget.layoutInfo = { + ...currentWidget.layoutInfo, + ...layoutInfo, + } +} + +export const batchUpdateWidgetLayoutInfoReducer: CaseReducer< + LayoutInfoState, + PayloadAction +> = (state, action) => { + if (!state) return + action.payload.forEach((updateSlice) => { + const { displayName, layoutInfo } = updateSlice + const widgetsLayoutInfo = state.widgetsLayoutInfo + const currentWidget = widgetsLayoutInfo[displayName] + if (!currentWidget || !layoutInfo || Object.keys(layoutInfo).length === 0) { + return + } + currentWidget.layoutInfo = { + ...currentWidget.layoutInfo, + ...layoutInfo, + } + }) +} + +export const updateWidgetLayoutInfoWhenChangeDisplayNameReducer: CaseReducer< + LayoutInfoState, + PayloadAction<{ oldDisplayName: string; newDisplayName: string }> +> = (state, action) => { + const { oldDisplayName, newDisplayName } = action.payload + const widgetsLayoutInfo = state.widgetsLayoutInfo + const currentWidget = widgetsLayoutInfo[oldDisplayName] + if (!currentWidget) return + delete widgetsLayoutInfo[oldDisplayName] + widgetsLayoutInfo[newDisplayName] = currentWidget +} diff --git a/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSelector.ts b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSelector.ts new file mode 100644 index 0000000000..665b51dddb --- /dev/null +++ b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSelector.ts @@ -0,0 +1,12 @@ +import { createSelector } from "@reduxjs/toolkit" +import { getCurrentApp } from "../selector" + +export const layoutInfo = createSelector( + [getCurrentApp], + (currentApp) => currentApp.layoutInfo, +) + +export const getClientWidgetLayoutInfo = createSelector( + [layoutInfo], + (layoutInfo) => layoutInfo.widgetsLayoutInfo, +) diff --git a/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSlice.ts b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSlice.ts new file mode 100644 index 0000000000..e61a3245b2 --- /dev/null +++ b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoSlice.ts @@ -0,0 +1,22 @@ +import { createSlice } from "@reduxjs/toolkit" +import { + batchUpdateWidgetLayoutInfoReducer, + setWidgetLayoutInfoReducer, + updateWidgetLayoutInfoReducer, + updateWidgetLayoutInfoWhenChangeDisplayNameReducer, +} from "./layoutInfoReducer" +import { layoutInfoInitialState } from "./layoutInfoState" + +const layoutInfoSlice = createSlice({ + name: "layoutInfo", + initialState: layoutInfoInitialState, + reducers: { + setWidgetLayoutInfoReducer, + updateWidgetLayoutInfoReducer, + batchUpdateWidgetLayoutInfoReducer, + updateWidgetLayoutInfoWhenChangeDisplayNameReducer, + }, +}) + +export const layoutInfoActions = layoutInfoSlice.actions +export default layoutInfoSlice.reducer diff --git a/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoState.ts b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoState.ts new file mode 100644 index 0000000000..fa17d988d9 --- /dev/null +++ b/apps/builder/src/redux/currentApp/layoutInfo/layoutInfoState.ts @@ -0,0 +1,31 @@ +import { CONTAINER_TYPE } from "@illa-public/public-types" +import { LayoutInfo } from "@/redux/currentApp/components/componentsPayload" + +export interface WidgetLayoutInfo { + displayName: string + widgetType: string + layoutInfo: LayoutInfo + parentNode: string + containerType: CONTAINER_TYPE + childrenNode: string[] +} + +export interface LayoutInfoState { + widgetsLayoutInfo: Record +} + +export const layoutInfoInitialState: LayoutInfoState = { + widgetsLayoutInfo: {}, +} + +export interface UpdateWidgetLayoutInfoPayload { + displayName: string + layoutInfo: Partial + parentNode: string + effectRows?: number +} + +export interface BatchUpdateWidgetLayoutInfoPayload { + displayName: string + layoutInfo: Partial +} diff --git a/apps/builder/src/redux/currentApp/executionTree/utils.ts b/apps/builder/src/redux/currentApp/layoutInfo/utils.ts similarity index 90% rename from apps/builder/src/redux/currentApp/executionTree/utils.ts rename to apps/builder/src/redux/currentApp/layoutInfo/utils.ts index 20f1c2e0f0..7e670d1ba1 100644 --- a/apps/builder/src/redux/currentApp/executionTree/utils.ts +++ b/apps/builder/src/redux/currentApp/layoutInfo/utils.ts @@ -1,4 +1,4 @@ -import { WidgetLayoutInfo } from "./executionState" +import { WidgetLayoutInfo } from "./layoutInfoState" export const getAllDescendantNodeDisplayNamesByExecution = ( node: WidgetLayoutInfo, diff --git a/apps/builder/src/redux/currentApp/selector.ts b/apps/builder/src/redux/currentApp/selector.ts new file mode 100644 index 0000000000..510a449488 --- /dev/null +++ b/apps/builder/src/redux/currentApp/selector.ts @@ -0,0 +1,3 @@ +import { RootState } from "../../store" + +export const getCurrentApp = (state: RootState) => state.currentApp diff --git a/apps/builder/src/redux/currentApp/slice.ts b/apps/builder/src/redux/currentApp/slice.ts new file mode 100644 index 0000000000..163045ca22 --- /dev/null +++ b/apps/builder/src/redux/currentApp/slice.ts @@ -0,0 +1,20 @@ +import { combineReducers } from "@reduxjs/toolkit" +import actionReducer from "./action/actionSlice" +import appInfoReducer from "./appInfo/appInfoSlice" +import collaboratorsReducer from "./collaborators/collaboratorsSlice" +import componentsReducer from "./components/componentsSlice" +import cursorSlice from "./cursor/cursorSlice" +import dragShadowReducer from "./dragShadow/dragShadowSlice" +import executionReducer from "./executionTree/executionSlice" +import layoutInfoReducer from "./layoutInfo/layoutInfoSlice" + +export const appReducer = combineReducers({ + components: componentsReducer, + action: actionReducer, + appInfo: appInfoReducer, + collaborators: collaboratorsReducer, + execution: executionReducer, + cursor: cursorSlice, + dragShadow: dragShadowReducer, + layoutInfo: layoutInfoReducer, +}) diff --git a/apps/builder/src/store.ts b/apps/builder/src/store.ts index 03e698544d..aea43adcce 100644 --- a/apps/builder/src/store.ts +++ b/apps/builder/src/store.ts @@ -3,7 +3,6 @@ import { isCloudVersion } from "@illa-public/utils" import { ListenerEffectAPI, TypedStartListening, - combineReducers, configureStore, createListenerMiddleware, } from "@reduxjs/toolkit" @@ -12,31 +11,15 @@ import { reduxAsync } from "@/middleware/reduxAsync" import aiAgent from "@/redux/aiAgent/dashboardTeamAIAgentSlice" import builderInfoReducer from "@/redux/builderInfo/builderInfoSlice" import configReducer from "@/redux/config/configSlice" -import actionReducer from "@/redux/currentApp/action/actionSlice" -import appInfoReducer from "@/redux/currentApp/appInfo/appInfoSlice" -import collaboratorsReducer from "@/redux/currentApp/collaborators/collaboratorsSlice" -import componentsReducer from "@/redux/currentApp/components/componentsSlice" -import dragShadowReducer from "@/redux/currentApp/dragShadow/dragShadowSlice" -import executionReducer from "@/redux/currentApp/executionTree/executionSlice" import currentAppHistoryReducer from "@/redux/currentAppHistory/currentAppHistorySlice" import guideReducer from "@/redux/guide/guideSlice" import resourceReducer from "@/redux/resource/resourceSlice" import { mixpanelReport } from "./middleware/mixpanelReport" import { UndoRedo } from "./middleware/undoRedo" -import cursorSlice from "./redux/currentApp/cursor/cursorSlice" +import { appReducer } from "./redux/currentApp/slice" const listenerMiddleware = createListenerMiddleware() -const appReducer = combineReducers({ - components: componentsReducer, - action: actionReducer, - appInfo: appInfoReducer, - collaborators: collaboratorsReducer, - execution: executionReducer, - cursor: cursorSlice, - dragShadow: dragShadowReducer, -}) - const middlewares = [reduxAsync, UndoRedo, guideAsync] if (isCloudVersion) { diff --git a/apps/builder/src/utils/action/runAction.ts b/apps/builder/src/utils/action/runAction.ts index f21372529b..5f9ba51ba3 100644 --- a/apps/builder/src/utils/action/runAction.ts +++ b/apps/builder/src/utils/action/runAction.ts @@ -283,7 +283,9 @@ export const runOriginAction = async (action: ActionItem) => { const { displayName } = action const finalContext = ILLAEditorRuntimePropsCollectorInstance.getGlobalCalcContext() - const realAction = finalContext[displayName] as IExecutionActions + const realAction = (finalContext as Record)[ + displayName + ] as IExecutionActions return await runActionWithExecutionResult(realAction) } diff --git a/apps/builder/src/utils/componentNode/buildTree.ts b/apps/builder/src/utils/componentNode/buildTree.ts index f922d86033..94181214e2 100644 --- a/apps/builder/src/utils/componentNode/buildTree.ts +++ b/apps/builder/src/utils/componentNode/buildTree.ts @@ -1,4 +1,4 @@ -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" export interface NeedBuildNode { displayName: string diff --git a/apps/builder/src/utils/componentNode/search.ts b/apps/builder/src/utils/componentNode/search.ts index 82f5564931..598ddd7b73 100644 --- a/apps/builder/src/utils/componentNode/search.ts +++ b/apps/builder/src/utils/componentNode/search.ts @@ -3,19 +3,17 @@ import { DEFAULT_BODY_COLUMNS_NUMBER, } from "@/page/App/components/DotPanel/constant/canvas" import { searchDSLByDisplayName } from "@/redux/currentApp/components/componentsSelector" -import { - getExecutionResult, - getExecutionWidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionSelector" +import { getExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import store from "@/store" export const searchForefatherSectionNodeDisplayName = ( currentDisplayName: string, ): string | null => { const rootState = store.getState() - const widgetsLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + const widgetsLayoutInfo = getClientWidgetLayoutInfo(rootState) const currentLayoutInfo = widgetsLayoutInfo[currentDisplayName] if (currentLayoutInfo && currentLayoutInfo.widgetType !== "SECTION_NODE") { if (currentLayoutInfo.parentNode === "root") { @@ -89,7 +87,7 @@ export const autoChangeContainersIndexWhenClick = ( currentDisplayName: string, ) => { const rootState = store.getState() - const widgetsLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + const widgetsLayoutInfo = getClientWidgetLayoutInfo(rootState) const canvasForeFatherDisplayNames = searchParent( currentDisplayName, widgetsLayoutInfo, @@ -128,7 +126,7 @@ export const autoChangeContainersIndexWhenClick = ( export const autoChangeWhenClickOnCanvas = (canvasDisplayName: string) => { const rootState = store.getState() - const widgetsLayoutInfo = getExecutionWidgetLayoutInfo(rootState) + const widgetsLayoutInfo = getClientWidgetLayoutInfo(rootState) const parentContainerDisplayName = widgetsLayoutInfo[canvasDisplayName]?.parentNode const indexOfCanvas = diff --git a/apps/builder/src/utils/copyManager.ts b/apps/builder/src/utils/copyManager.ts index 8cc49dd13d..0d16f2c5e4 100644 --- a/apps/builder/src/utils/copyManager.ts +++ b/apps/builder/src/utils/copyManager.ts @@ -15,14 +15,12 @@ import { illaSnapshot } from "@/page/App/components/DotPanel/constant/snapshotNe import { canCrossDifferenceColumnNumber } from "@/page/App/components/DotPanel/utils/getDragShadow" import { searchDSLByDisplayName } from "@/redux/currentApp/components/componentsSelector" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" -import { - getExecution, - getExecutionWidgetLayoutInfo, -} from "@/redux/currentApp/executionTree/executionSelector" +import { getExecution } from "@/redux/currentApp/executionTree/executionSelector" import store from "@/store" import { FocusManager } from "@/utils/focusManager" import { DisplayNameGenerator } from "@/utils/generators/generateDisplayName" import { getActionMixedList } from "../redux/currentApp/action/actionSelector" +import { getClientWidgetLayoutInfo } from "../redux/currentApp/layoutInfo/layoutInfoSelector" import { copyWidgetDisplayNameHelper } from "./changeDisplayNameHelper" import { getComponentNodeResultByRelativeCombineShape } from "./componentNode/copyHelper" import { buildTreeByMapNode } from "./componentNode/flatTree" @@ -82,7 +80,7 @@ export class CopyManager { static copyComponentNodeByDisplayName(displayNames: string[]) { if (displayNames.length > 0) { - const widgetLayoutInfos = getExecutionWidgetLayoutInfo(store.getState()) + const widgetLayoutInfos = getClientWidgetLayoutInfo(store.getState()) illaSnapshot.setSnapshot(widgetLayoutInfos) const copiedColumnNumber = getCurrentSectionColumnNumberByChildDisplayName(displayNames[0]) @@ -94,7 +92,7 @@ export class CopyManager { } static paste(sources: "keyboard" | "duplicate") { - const widgetLayoutInfos = getExecutionWidgetLayoutInfo(store.getState()) + const widgetLayoutInfos = getClientWidgetLayoutInfo(store.getState()) illaSnapshot.setSnapshot(widgetLayoutInfos) switch (FocusManager.getFocus()) { case "data_action": diff --git a/apps/builder/src/utils/drag/drag.ts b/apps/builder/src/utils/drag/drag.ts index 92856316ba..be2b575b88 100644 --- a/apps/builder/src/utils/drag/drag.ts +++ b/apps/builder/src/utils/drag/drag.ts @@ -1,6 +1,5 @@ import { configActions } from "@/redux/config/configSlice" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import store from "@/store" import { DisplayNameGenerator } from "@/utils/generators/generateDisplayName" import { FocusManager } from "../focusManager" @@ -8,7 +7,7 @@ import { FocusManager } from "../focusManager" export function startDragMultiNodes(dragWidgetInfos: WidgetLayoutInfo[]) { store.dispatch(configActions.updateShowDot(true)) const displayNames = dragWidgetInfos.map((node) => node.displayName) - store.dispatch(executionActions.setDraggingNodeIDsReducer(displayNames)) + store.dispatch(configActions.setDraggingNodeIDsReducer(displayNames)) } export function endDragMultiNodes( @@ -18,7 +17,7 @@ export function endDragMultiNodes( ) { store.dispatch(configActions.updateShowDot(false)) const displayNames = dragWidgetInfos.map((node) => node.displayName) - store.dispatch(executionActions.setDraggingNodeIDsReducer([])) + store.dispatch(configActions.setDraggingNodeIDsReducer([])) if (isDropOnCanvas) { FocusManager.switchFocus("canvas", { diff --git a/apps/builder/src/utils/evaluateDynamicString/dynamicConverter.ts b/apps/builder/src/utils/evaluateDynamicString/dynamicConverter.ts index a9d306ccf6..0a1e518984 100644 --- a/apps/builder/src/utils/evaluateDynamicString/dynamicConverter.ts +++ b/apps/builder/src/utils/evaluateDynamicString/dynamicConverter.ts @@ -2,7 +2,7 @@ import { getStringSnippets, isDynamicStringSnippet, } from "@illa-public/dynamic-string" -import { merge } from "lodash-es" +import { klona } from "klona" import { ILLAEditorRuntimePropsCollectorInstance } from "../executionTreeHelper/runtimePropsCollector" import { evalScript } from "./codeSandbox" import { substituteDynamicBindingWithValues } from "./valueConverter" @@ -33,11 +33,11 @@ export const getDynamicValue = ( dataTree: Record, ) => { const { jsSnippets, stringSnippets } = getSnippets(dynamicString) - const calcContext = merge( - {}, - dataTree, - ILLAEditorRuntimePropsCollectorInstance.getThirdPartyPackages(), - ) + const cloneDeepDataTree = klona(dataTree) + const calcContext = { + ...cloneDeepDataTree, + ...ILLAEditorRuntimePropsCollectorInstance.getThirdPartyPackages(), + } if (stringSnippets.length) { let context: Record = {} const values = jsSnippets.map((jsSnippet, index) => { diff --git a/apps/builder/src/utils/executionTreeHelper/runtimePropsCollector.ts b/apps/builder/src/utils/executionTreeHelper/runtimePropsCollector.ts index 95cc5c2184..71c6d1ddfd 100644 --- a/apps/builder/src/utils/executionTreeHelper/runtimePropsCollector.ts +++ b/apps/builder/src/utils/executionTreeHelper/runtimePropsCollector.ts @@ -1,5 +1,5 @@ import dayjs from "dayjs" -import { merge } from "lodash-es" +import { klona } from "klona/json" import _ from "lodash-es" import numbro from "numbro" import Papa from "papaparse" @@ -99,13 +99,16 @@ class ILLAEditorRuntimePropsCollector { return THIRD_PARTY_PACKAGES } - public getGlobalCalcContext(otherContext?: Record) { + public getGlobalCalcContext(otherContext: Record = {}) { const rootState = store.getState() const executionResult = getExecutionResult(rootState) + const cloneDeepExecutionResult = klona(executionResult) - const formatedExecutionResult = Object.keys(executionResult).reduce( + const formatedExecutionResult = Object.keys( + cloneDeepExecutionResult, + ).reduce( (acc, prevKey) => { - const prev = executionResult[prevKey] + const prev = cloneDeepExecutionResult[prevKey] if (!prev) { return acc } @@ -120,6 +123,18 @@ class ILLAEditorRuntimePropsCollector { }, } } + if (prev.$type === "WIDGET") { + const runtimePros = this._runtimeProps[prev.displayName] + if (runtimePros) { + return { + ...acc, + [prev.displayName]: { + ...prev, + ...runtimePros, + }, + } + } + } return { ...acc, [prevKey]: prev, @@ -127,17 +142,29 @@ class ILLAEditorRuntimePropsCollector { }, {} as Record, ) - return merge({}, this._runtimeProps, formatedExecutionResult, otherContext) + + const utils = this._runtimeProps.utils as Record + const mergeResult = { + ...formatedExecutionResult, + ...THIRD_PARTY_PACKAGES, + ...utils, + ...otherContext, + } + + return mergeResult } - public getCurrentPageCalcContext(otherContext?: Record) { + public getCurrentPageCalcContext(otherContext: Record = {}) { const rootState = store.getState() const executionResult = getExecutionResultToCurrentPageCodeMirror( rootState, ) as Record - const formatedExecutionResult = Object.keys(executionResult).reduce( + const cloneDeepExecutionResult = klona(executionResult) + const formatedExecutionResult = Object.keys( + cloneDeepExecutionResult, + ).reduce( (acc, prevKey) => { - const prev = executionResult[prevKey] + const prev = cloneDeepExecutionResult[prevKey] if (!prev) { return acc @@ -157,6 +184,7 @@ class ILLAEditorRuntimePropsCollector { }, } } + if (prev.$type === "WIDGET") { switch (prev.$widgetType) { case "MODAL_WIDGET": @@ -182,6 +210,18 @@ class ILLAEditorRuntimePropsCollector { }, }, } + default: { + const runtimePros = this._runtimeProps[prev.displayName] + if (runtimePros) { + return { + ...acc, + [prev.displayName]: { + ...prev, + ...runtimePros, + }, + } + } + } } } return { @@ -191,13 +231,29 @@ class ILLAEditorRuntimePropsCollector { }, {} as Record, ) - return merge({}, this._runtimeProps, formatedExecutionResult, otherContext) + const utils = this._runtimeProps.utils as Record + const mergeResult = { + ...formatedExecutionResult, + ...THIRD_PARTY_PACKAGES, + ...utils, + ...otherContext, + } + + return mergeResult } public getGlobalCalcContextWithLimit(otherContext?: Record) { const rootState = store.getState() const executionResult = getExecutionResultToGlobalCodeMirror(rootState) - return merge({}, this._runtimeProps, executionResult, otherContext) + const cloneDeepExecutionResult = klona(executionResult) + const utils = this._runtimeProps.utils as Record + const mergeResult = { + ...cloneDeepExecutionResult, + ...THIRD_PARTY_PACKAGES, + ...utils, + ...otherContext, + } + return mergeResult } } diff --git a/apps/builder/src/utils/generators/generateComponentNode.ts b/apps/builder/src/utils/generators/generateComponentNode.ts index c1ef533dd9..63a5f3a7a5 100644 --- a/apps/builder/src/utils/generators/generateComponentNode.ts +++ b/apps/builder/src/utils/generators/generateComponentNode.ts @@ -5,7 +5,7 @@ import { get, set } from "lodash-es" import { isObject } from "@illa-design/react" import { buildInitDragInfo } from "@/page/App/components/ComponentPanel/componentListBuilder" import { DEFAULT_MIN_COLUMN } from "@/page/App/components/ScaleSquare/constant/widget" -import { WidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionState" +import { WidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoState" import { DisplayNameGenerator } from "@/utils/generators/generateDisplayName" import { WidgetConfig } from "@/widgetLibrary/interface" import { WidgetType, widgetBuilder } from "@/widgetLibrary/widgetBuilder" diff --git a/apps/builder/src/utils/undoRedo/undo.ts b/apps/builder/src/utils/undoRedo/undo.ts index 3b54454b26..16b3d56d40 100644 --- a/apps/builder/src/utils/undoRedo/undo.ts +++ b/apps/builder/src/utils/undoRedo/undo.ts @@ -3,7 +3,7 @@ import { createMessage } from "@illa-design/react" import i18n from "@/i18n/config" import { REDUX_ACTION_FROM } from "@/middleware/undoRedo/interface" import { illaSnapshot } from "@/page/App/components/DotPanel/constant/snapshotNew" -import { getExecutionWidgetLayoutInfo } from "@/redux/currentApp/executionTree/executionSelector" +import { getClientWidgetLayoutInfo } from "@/redux/currentApp/layoutInfo/layoutInfoSelector" import store from "@/store" import { reduxActionDependOnRestAPI } from "./antonymyRule" import { CircularStack } from "./circularStack" @@ -30,7 +30,7 @@ export class ILLA_UNDO_REDO { popFromUndoStack() { const rootState = store.getState() - const snapShot = getExecutionWidgetLayoutInfo(rootState) + const snapShot = getClientWidgetLayoutInfo(rootState) illaSnapshot.setSnapshot(snapShot) if (this.undoStack.isEmpty()) { message.warning({ @@ -60,7 +60,7 @@ export class ILLA_UNDO_REDO { popFromRedoStack() { const rootState = store.getState() - const snapShot = getExecutionWidgetLayoutInfo(rootState) + const snapShot = getClientWidgetLayoutInfo(rootState) illaSnapshot.setSnapshot(snapShot) if (this.redoStack.isEmpty()) { message.warning({ diff --git a/apps/builder/src/widgetLibrary/ChatWidget/chat.tsx b/apps/builder/src/widgetLibrary/ChatWidget/chat.tsx index 59b7b9a02b..050d19603e 100644 --- a/apps/builder/src/widgetLibrary/ChatWidget/chat.tsx +++ b/apps/builder/src/widgetLibrary/ChatWidget/chat.tsx @@ -2,7 +2,7 @@ import { Resizable, ResizeCallback, ResizeStartCallback } from "re-resizable" import { FC, useCallback, useEffect, useMemo, useState } from "react" import { useDispatch } from "react-redux" import { UNIT_HEIGHT } from "@/page/App/components/DotPanel/constant/canvas" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { BaseChat } from "@/widgetLibrary/ChatWidget/components/baseChat" import { ReplyTo } from "@/widgetLibrary/ChatWidget/components/replyTo" import { @@ -73,9 +73,7 @@ export const ChatWidget: FC = (props) => { e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ - `${displayName}-resize-footer`, - ]), + configActions.setResizingNodeIDsReducer([`${displayName}-resize-footer`]), ) } @@ -85,7 +83,7 @@ export const ChatWidget: FC = (props) => { handleUpdateOriginalDSLMultiAttr({ footerHeight: footerHeight + height, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, footerHeight, handleUpdateOriginalDSLMultiAttr], ) diff --git a/apps/builder/src/widgetLibrary/DataGridWidget/dataGrid.tsx b/apps/builder/src/widgetLibrary/DataGridWidget/dataGrid.tsx index 72b5c89bf1..1e58ccf7a6 100644 --- a/apps/builder/src/widgetLibrary/DataGridWidget/dataGrid.tsx +++ b/apps/builder/src/widgetLibrary/DataGridWidget/dataGrid.tsx @@ -17,7 +17,7 @@ import { import { useDispatch } from "react-redux" import { getColor } from "@illa-design/react" import { dealRawData2ArrayData } from "@/page/App/components/InspectPanel/PanelSetters/DataGridSetter/utils" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { getColumnFromType, getColumnTypeFromValue, @@ -413,14 +413,14 @@ export const DataGridWidget: FC = (props) => { }} onColumnHeaderEnter={() => { dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-column-header-resize`, ]), ) isInnerDragging.current = true }} onColumnHeaderLeave={() => { - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) isInnerDragging.current = false }} /> diff --git a/apps/builder/src/widgetLibrary/FormWidget/form.tsx b/apps/builder/src/widgetLibrary/FormWidget/form.tsx index d6817021bf..daf06a9082 100644 --- a/apps/builder/src/widgetLibrary/FormWidget/form.tsx +++ b/apps/builder/src/widgetLibrary/FormWidget/form.tsx @@ -23,10 +23,10 @@ import { applyXDirectionDashedLineStyle, } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" +import { configActions } from "@/redux/config/configSlice" import { getComponentMap } from "@/redux/currentApp/components/componentsSelector" import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { getExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" import { evaluateDynamicString } from "@/utils/evaluateDynamicString" import { ILLAEditorRuntimePropsCollectorInstance } from "@/utils/executionTreeHelper/runtimePropsCollector" import { isObject } from "@/utils/typeHelper" @@ -405,7 +405,7 @@ export const FormWidget: FC = (props) => { e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-form-header`, ]), ) @@ -423,7 +423,7 @@ export const FormWidget: FC = (props) => { handleUpdateOriginalDSLMultiAttr({ headerHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, headerHeight, headerMaxHeight], ) @@ -440,7 +440,7 @@ export const FormWidget: FC = (props) => { handleUpdateOriginalDSLMultiAttr({ footerHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, footerHeight, footerMaxHeight, handleUpdateOriginalDSLMultiAttr], ) diff --git a/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithAutoPagination/index.tsx b/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithAutoPagination/index.tsx index d8fe04ecfa..63f4a11c17 100644 --- a/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithAutoPagination/index.tsx +++ b/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithAutoPagination/index.tsx @@ -7,7 +7,7 @@ import { Pagination } from "@illa-design/react" import { LIST_ITEM_MARGIN_TOP } from "@/page/App/components/ScaleSquare/constant/widget" import { applyDashedLineStyle } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { getShadowStyle } from "@/utils/styleUtils/shadow" import RenderCopyContainer from "@/widgetLibrary/GridListWidget/components/RenderCopyContainer" import RenderTemplateContainer from "@/widgetLibrary/GridListWidget/components/RenderTemplateContainer" @@ -123,9 +123,7 @@ const ListWidgetWithAutoPagination: FC = ( e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ - `${displayName}-resize-grid`, - ]), + configActions.setResizingNodeIDsReducer([`${displayName}-resize-grid`]), ) } @@ -136,7 +134,7 @@ const ListWidgetWithAutoPagination: FC = ( handleUpdateOriginalDSLMultiAttr({ itemHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, itemHeight], ) diff --git a/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithServerPagination/index.tsx b/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithServerPagination/index.tsx index d7bc4b705c..39394a7102 100644 --- a/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithServerPagination/index.tsx +++ b/apps/builder/src/widgetLibrary/GridListWidget/components/ListWidgetWithServerPagination/index.tsx @@ -7,7 +7,7 @@ import { Pagination } from "@illa-design/react" import { LIST_ITEM_MARGIN_TOP } from "@/page/App/components/ScaleSquare/constant/widget" import { applyDashedLineStyle } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { getShadowStyle } from "@/utils/styleUtils/shadow" import CursorBasedSelector from "@/widgetLibrary/GridListWidget/components/CursorBasedSelector" import RenderCopyContainer from "@/widgetLibrary/GridListWidget/components/RenderCopyContainer" @@ -163,7 +163,7 @@ const ListWidgetWithServerPagination: FC = ( e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-list-item`, ]), ) @@ -175,7 +175,7 @@ const ListWidgetWithServerPagination: FC = ( handleUpdateOriginalDSLMultiAttr({ itemHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, itemHeight], ) diff --git a/apps/builder/src/widgetLibrary/InputWidget/utils.ts b/apps/builder/src/widgetLibrary/InputWidget/utils.ts new file mode 100644 index 0000000000..67861d5a62 --- /dev/null +++ b/apps/builder/src/widgetLibrary/InputWidget/utils.ts @@ -0,0 +1,42 @@ +import { + getValidateVFromString, + handleValidateCheck, +} from "../PublicSector/InvalidMessage/utils" +import { InputWidgetProps } from "./interface" + +export const getValidateMessage = ( + value: string | undefined, + options: { + hideValidationMessage?: InputWidgetProps["hideValidationMessage"] + pattern?: InputWidgetProps["pattern"] + regex?: InputWidgetProps["regex"] + minLength?: InputWidgetProps["minLength"] + maxLength?: InputWidgetProps["maxLength"] + required?: InputWidgetProps["required"] + customRule?: InputWidgetProps["customRule"] + } = {}, +) => { + const { + hideValidationMessage, + pattern, + regex, + maxLength, + minLength, + required, + customRule, + } = options + if (!hideValidationMessage) { + const message = handleValidateCheck({ + value: getValidateVFromString(value), + pattern, + regex, + minLength, + maxLength, + required, + customRule, + }) + const showMessage = message && message.length > 0 + return showMessage ? message : "" + } + return "" +} diff --git a/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithAutoPagination/index.tsx b/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithAutoPagination/index.tsx index 9659be853b..518ae9e26b 100644 --- a/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithAutoPagination/index.tsx +++ b/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithAutoPagination/index.tsx @@ -6,7 +6,7 @@ import useMeasure from "react-use-measure" import { Pagination } from "@illa-design/react" import { applyDashedLineStyle } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { getShadowStyle } from "@/utils/styleUtils/shadow" import { ListWidgetPropsWithChildrenNodes } from "@/widgetLibrary/ListWidget/interface" import { @@ -94,7 +94,7 @@ const ListWidgetWithAutoPagination: FC = ( e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-listItem`, ]), ) @@ -107,7 +107,7 @@ const ListWidgetWithAutoPagination: FC = ( handleUpdateOriginalDSLMultiAttr({ itemHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, itemHeight], ) diff --git a/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithServerPagination/index.tsx b/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithServerPagination/index.tsx index d896d49890..2650f559ca 100644 --- a/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithServerPagination/index.tsx +++ b/apps/builder/src/widgetLibrary/ListWidget/components/ListWidgetWithServerPagination/index.tsx @@ -6,7 +6,7 @@ import useMeasure from "react-use-measure" import { Pagination } from "@illa-design/react" import { applyDashedLineStyle } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import { getShadowStyle } from "@/utils/styleUtils/shadow" import { ListWidgetPropsWithChildrenNodes, @@ -156,7 +156,7 @@ const ListWidgetWithServerPagination: FC = ( e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-listItem`, ]), ) @@ -168,7 +168,7 @@ const ListWidgetWithServerPagination: FC = ( handleUpdateOriginalDSLMultiAttr({ itemHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, itemHeight], ) diff --git a/apps/builder/src/widgetLibrary/ModalWidget/modal.tsx b/apps/builder/src/widgetLibrary/ModalWidget/modal.tsx index d539477c9f..baf694e3ef 100644 --- a/apps/builder/src/widgetLibrary/ModalWidget/modal.tsx +++ b/apps/builder/src/widgetLibrary/ModalWidget/modal.tsx @@ -20,7 +20,7 @@ import { applyXDirectionDashedLineStyle, } from "@/page/App/components/ScaleSquare/style" import { getIsILLAEditMode } from "@/redux/config/configSelector" -import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" +import { configActions } from "@/redux/config/configSlice" import RenderChildrenCanvas from "../PublicSector/RenderChildrenCanvas" import { ModalWidgetProps } from "./interface" import { @@ -147,7 +147,7 @@ export const ModalWidget: FC = (props) => { e.preventDefault() e.stopPropagation() dispatch( - executionActions.setResizingNodeIDsReducer([ + configActions.setResizingNodeIDsReducer([ `${displayName}-resize-modal-header`, ]), ) @@ -165,7 +165,7 @@ export const ModalWidget: FC = (props) => { handleUpdateOriginalDSLMultiAttr({ headerHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, handleUpdateOriginalDSLMultiAttr, headerHeight, headerMaxHeight], ) @@ -182,7 +182,7 @@ export const ModalWidget: FC = (props) => { handleUpdateOriginalDSLMultiAttr({ footerHeight: finalHeight, }) - dispatch(executionActions.setResizingNodeIDsReducer([])) + dispatch(configActions.setResizingNodeIDsReducer([])) }, [dispatch, footerHeight, footerMaxHeight, handleUpdateOriginalDSLMultiAttr], ) diff --git a/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx b/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx index f000e92917..ca92b6ee37 100644 --- a/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx +++ b/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx @@ -18,7 +18,6 @@ import { import { componentsActions } from "@/redux/currentApp/components/componentsSlice" import { getExecutionResult, - getExecutionWidgetLayoutInfo, getIsDragging, } from "@/redux/currentApp/executionTree/executionSelector" import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" @@ -31,6 +30,8 @@ import { isObject } from "@/utils/typeHelper" import { TransformWidgetProps } from "@/widgetLibrary/PublicSector/TransformWidgetWrapper/interface" import { applyWrapperStylesStyle } from "@/widgetLibrary/PublicSector/TransformWidgetWrapper/style" import { widgetBuilder } from "@/widgetLibrary/widgetBuilder" +import { getClientWidgetLayoutInfo } from "../../../redux/currentApp/layoutInfo/layoutInfoSelector" +import { layoutInfoActions } from "../../../redux/currentApp/layoutInfo/layoutInfoSlice" import { MIN_HEIGHT } from "./config" export const TransformWidgetWrapper: FC = memo( @@ -40,7 +41,7 @@ export const TransformWidgetWrapper: FC = memo( const displayNameMapProps = useSelector(getExecutionResult) const layoutInfo = useSelector((rootState) => { - const layoutInfos = getExecutionWidgetLayoutInfo(rootState) + const layoutInfos = getClientWidgetLayoutInfo(rootState) return layoutInfos[displayName].layoutInfo }) const originComponentNode = searchDSLByDisplayName(displayName) @@ -110,7 +111,7 @@ export const TransformWidgetWrapper: FC = memo( (newHeight: number) => { if (isDraggingInGlobal) return const rootState = store.getState() - const widgetLayoutInfos = getExecutionWidgetLayoutInfo(rootState) + const widgetLayoutInfos = getClientWidgetLayoutInfo(rootState) const oldH = widgetLayoutInfos[displayName]?.layoutInfo.h ?? 0 if (dynamicHeight !== "fixed") { @@ -149,7 +150,7 @@ export const TransformWidgetWrapper: FC = memo( if (newH === oldH) return dispatch( - executionActions.updateWidgetLayoutInfoReducer({ + layoutInfoActions.updateWidgetLayoutInfoReducer({ displayName, layoutInfo: { h: newH, diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/eventHandlerConfig.ts b/apps/builder/src/widgetLibrary/QRCodeWidget/eventHandlerConfig.ts new file mode 100644 index 0000000000..59e2eff33e --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/eventHandlerConfig.ts @@ -0,0 +1,6 @@ +import { EventHandlerConfig } from "@/widgetLibrary/interface" + +export const QR_CODE_EVENT_HANDLER_CONFIG: EventHandlerConfig = { + events: [], + methods: ["setValue"], +} diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/index.ts b/apps/builder/src/widgetLibrary/QRCodeWidget/index.ts new file mode 100644 index 0000000000..81d8e65f2d --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/index.ts @@ -0,0 +1,3 @@ +export { QR_CODE_PANEL_CONFIG } from "./panelConfig" +export { QR_CODE_WIDGET_CONFIG } from "./widgetConfig" +export { QR_CODE_EVENT_HANDLER_CONFIG } from "./eventHandlerConfig" diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/interface.ts b/apps/builder/src/widgetLibrary/QRCodeWidget/interface.ts new file mode 100644 index 0000000000..abfc6c2edc --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/interface.ts @@ -0,0 +1,12 @@ +import { TooltipWrapperProps } from "@/widgetLibrary/PublicSector/TooltipWrapper/interface" +import { BaseWidgetProps } from "@/widgetLibrary/interface" + +export interface WrappedQRCodeProps extends QRCodeWidgetProps {} + +export interface QRCodeWidgetProps + extends BaseWidgetProps, + TooltipWrapperProps { + value?: unknown + bgColorSchema?: string + fgColorSchema?: string +} diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/panelConfig.tsx b/apps/builder/src/widgetLibrary/QRCodeWidget/panelConfig.tsx new file mode 100644 index 0000000000..8928ecf676 --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/panelConfig.tsx @@ -0,0 +1,68 @@ +import i18n from "@/i18n/config" +import { PanelConfig } from "@/page/App/components/InspectPanel/interface" +import { VALIDATION_TYPES } from "@/utils/validationFactory" + +const baseWidgetName = "qrCode" +export const QR_CODE_PANEL_CONFIG: PanelConfig[] = [ + { + id: `${baseWidgetName}-basic`, + groupName: i18n.t("editor.inspect.setter_group.basic"), + children: [ + { + id: `${baseWidgetName}-basic-DefaultValue`, + labelName: i18n.t("editor.inspect.setter_label.default_value"), + labelDesc: i18n.t( + "editor.inspect.setter_tooltip.component_default_value", + ), + attrName: "value", + setterType: "INPUT_SETTER", + expectedType: VALIDATION_TYPES.STRING, + }, + ], + }, + { + id: `${baseWidgetName}-Adornments`, + groupName: i18n.t("editor.inspect.setter_group.adornments"), + children: [ + { + id: `${baseWidgetName}-adornments-tooltip`, + labelName: i18n.t("editor.inspect.setter_label.tooltip"), + labelDesc: i18n.t("editor.inspect.setter_tooltip.tooltip"), + attrName: "tooltipText", + setterType: "INPUT_SETTER", + expectedType: VALIDATION_TYPES.STRING, + }, + ], + }, + { + id: `${baseWidgetName}-style`, + groupName: i18n.t("editor.inspect.setter_group.style"), + children: [ + { + id: `${baseWidgetName}-style-colors`, + setterType: "STYLE_CONTAINER_SETTER", + labelName: i18n.t("editor.inspect.setter_label.colors"), + attrName: "styles", + useCustomLayout: true, + childrenSetter: [ + { + id: `${baseWidgetName}-style-colors-bg-color`, + labelName: i18n.t("editor.inspect.setter_label.background"), + attrName: "bgColorSchema", + setterType: "COLOR_PICKER_SETTER", + useCustomLayout: true, + defaultValue: "white", + }, + { + id: `${baseWidgetName}-style-colors-fg-color`, + labelName: i18n.t("editor.inspect.setter_label.qr_code.foreground"), + attrName: "fgColorSchema", + setterType: "COLOR_PICKER_SETTER", + useCustomLayout: true, + defaultValue: "black", + }, + ], + }, + ], + }, +] diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/qrCode.tsx b/apps/builder/src/widgetLibrary/QRCodeWidget/qrCode.tsx new file mode 100644 index 0000000000..789f3fd166 --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/qrCode.tsx @@ -0,0 +1,70 @@ +import { QRCodeSVG } from "qrcode.react" +import { FC, useEffect } from "react" +import { TooltipWrapper } from "@/widgetLibrary/PublicSector/TooltipWrapper" +import { AutoHeightContainer } from "../PublicSector/AutoHeightContainer" +import { QRCodeWidgetProps } from "./interface" +import { fullStyle, qrCodeStyle } from "./style" + +export const WrappedQRCode: FC = ({ + value, + bgColorSchema, + fgColorSchema, +}) => { + return ( + + ) +} + +WrappedQRCode.displayName = "WrappedQRCode" + +export const QRCodeWidget: FC = (props) => { + const { + displayName, + tooltipText, + updateComponentHeight, + updateComponentRuntimeProps, + handleUpdateMultiExecutionResult, + deleteComponentRuntimeProps, + } = props + + useEffect(() => { + updateComponentRuntimeProps({ + setValue: (value: unknown) => { + handleUpdateMultiExecutionResult([ + { + displayName, + value: { + value: `${value}`, + }, + }, + ]) + }, + }) + return () => { + deleteComponentRuntimeProps() + } + }, [ + deleteComponentRuntimeProps, + displayName, + handleUpdateMultiExecutionResult, + updateComponentRuntimeProps, + ]) + + return ( + + +
+ +
+
+
+ ) +} + +QRCodeWidget.displayName = "QRCodeWidget" +export default QRCodeWidget diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/style.ts b/apps/builder/src/widgetLibrary/QRCodeWidget/style.ts new file mode 100644 index 0000000000..7674b8bbab --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/style.ts @@ -0,0 +1,12 @@ +import { css } from "@emotion/react" + +export const fullStyle = css` + width: 100%; + height: 100%; + overflow: hidden; +` + +export const qrCodeStyle = css` + width: 100%; + height: auto; +` diff --git a/apps/builder/src/widgetLibrary/QRCodeWidget/widgetConfig.tsx b/apps/builder/src/widgetLibrary/QRCodeWidget/widgetConfig.tsx new file mode 100644 index 0000000000..8da40555a2 --- /dev/null +++ b/apps/builder/src/widgetLibrary/QRCodeWidget/widgetConfig.tsx @@ -0,0 +1,21 @@ +import QrCodeWidgetIcon from "@/assets/widgetCover/qrcode.svg?react" +import i18n from "@/i18n/config" +import { RESIZE_DIRECTION, WidgetConfig } from "@/widgetLibrary/interface" + +export const QR_CODE_WIDGET_CONFIG: WidgetConfig = { + type: "QR_CODE_WIDGET", + widgetName: i18n.t("widget.qr_code.name"), + displayName: "qrCode", + w: 8, + h: 32, + resizeDirection: RESIZE_DIRECTION.HORIZONTAL, + icon: , + keywords: ["QR code", "二维码生成器"], + sessionType: "PRESENTATION", + version: 0, + defaults: { + value: "https://www.illacloud.com", + bgColorSchema: "white", + fgColorSchema: "black", + }, +} diff --git a/apps/builder/src/widgetLibrary/widgetBuilder.tsx b/apps/builder/src/widgetLibrary/widgetBuilder.tsx index 1c3b7d85c1..8eba7f6384 100644 --- a/apps/builder/src/widgetLibrary/widgetBuilder.tsx +++ b/apps/builder/src/widgetLibrary/widgetBuilder.tsx @@ -281,6 +281,11 @@ import { GRID_LIST_WIDGET_CONFIG, } from "./GridListWidget" import { IFRAME_EVENT_HANDLER_CONFIG } from "./IFrameWidget/eventHandlerConfig" +import { + QR_CODE_EVENT_HANDLER_CONFIG, + QR_CODE_PANEL_CONFIG, + QR_CODE_WIDGET_CONFIG, +} from "./QRCodeWidget" import { EventHandlerConfig, WidgetConfig } from "./interface" export const WidgetConfigMap: Record< @@ -531,6 +536,12 @@ export const WidgetConfigMap: Record< eventHandlerConfig: BUTTON_EVENT_HANDLER_CONFIG, widget: lazy(() => import("@/widgetLibrary/ButtonWidget/button")), }, + QR_CODE_WIDGET: { + config: QR_CODE_WIDGET_CONFIG, + panelConfig: QR_CODE_PANEL_CONFIG, + eventHandlerConfig: QR_CODE_EVENT_HANDLER_CONFIG, + widget: lazy(() => import("@/widgetLibrary/QRCodeWidget/qrCode")), + }, TAGS_WIDGET: { config: TAGS_WIDGET_CONFIG, panelConfig: TAGS_PANEL_CONFIG, diff --git a/packages/illa-public-component b/packages/illa-public-component index 0d84ec2730..a6d9d3ebfa 160000 --- a/packages/illa-public-component +++ b/packages/illa-public-component @@ -1 +1 @@ -Subproject commit 0d84ec27301222bccc3aecebc6e5adc64e5c6305 +Subproject commit a6d9d3ebfa71c5bb0dd0e1cd441504239fc17515 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac09a870a5..17e37be8ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -360,6 +360,9 @@ importers: pdfjs-dist: specifier: 2.16.105 version: 2.16.105 + qrcode.react: + specifier: ^3.1.0 + version: 3.1.0(react@18.2.0) qs: specifier: ^6.11.2 version: 6.11.2 @@ -14788,6 +14791,14 @@ packages: engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: true + /qrcode.react@3.1.0(react@18.2.0): + resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} + peerDependencies: + react: ^18.2.0 + dependencies: + react: 18.2.0 + dev: false + /qs@6.11.2: resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} engines: {node: '>=0.6'}