From 9a0430a94a301701aa38ccd2182d819adc2931b6 Mon Sep 17 00:00:00 2001 From: Nakul Nagargade Date: Wed, 25 Jun 2025 22:44:04 +0530 Subject: [PATCH] fix --- .vscode/settings.json | 7 +- .../src/AppBuilder/AppCanvas/Container.jsx | 118 +++++------------- .../src/AppBuilder/AppCanvas/Grid/Grid.jsx | 85 +++---------- .../AppBuilder/AppCanvas/appCanvasUtils.js | 2 +- .../AppCanvas/useCanvasDropHandler.js | 94 ++++++++++++++ .../ComponentManagerTab/DragLayer.jsx | 83 ++++-------- .../src/AppBuilder/_hooks/useGhostMoveable.js | 7 +- .../AppBuilder/_stores/slices/gridSlice.js | 4 + server/package-lock.json | 2 +- 9 files changed, 176 insertions(+), 226 deletions(-) create mode 100644 frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js diff --git a/.vscode/settings.json b/.vscode/settings.json index e13d54d778..50d6d9e897 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,8 +8,11 @@ "typescript", "typescriptreact" ], - "eslint.format.enable": false, - "editor.formatOnSave": false, + "eslint.format.enable": true, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, "json.schemas": [ { "fileMatch": [ diff --git a/frontend/src/AppBuilder/AppCanvas/Container.jsx b/frontend/src/AppBuilder/AppCanvas/Container.jsx index be6aab2803..4bdafa8a15 100644 --- a/frontend/src/AppBuilder/AppCanvas/Container.jsx +++ b/frontend/src/AppBuilder/AppCanvas/Container.jsx @@ -4,19 +4,14 @@ import cx from 'classnames'; import WidgetWrapper from './WidgetWrapper'; import useStore from '@/AppBuilder/_stores/store'; import { shallow } from 'zustand/shallow'; -import { useDrop, useDragLayer } from 'react-dnd'; +import { useDrop, useDragLayer, useDragDropManager } from 'react-dnd'; import { addChildrenWidgetsToParent, addNewWidgetToTheEditor, computeViewerBackgroundColor, getSubContainerWidthAfterPadding, } from './appCanvasUtils'; -import { - CANVAS_WIDTHS, - NO_OF_GRIDS, - WIDGETS_WITH_DEFAULT_CHILDREN, - GRID_HEIGHT, -} from './appCanvasConstants'; +import { CANVAS_WIDTHS, NO_OF_GRIDS, WIDGETS_WITH_DEFAULT_CHILDREN, GRID_HEIGHT } from './appCanvasConstants'; import { useGridStore } from '@/_stores/gridStore'; import NoComponentCanvasContainer from './NoComponentCanvasContainer'; import { RIGHT_SIDE_BAR_TAB } from '../RightSideBar/rightSidebarConstants'; @@ -27,6 +22,7 @@ import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext'; import useSortedComponents from '../_hooks/useSortedComponents'; import { noop } from 'lodash'; import { useGhostMoveable } from '@/AppBuilder/_hooks/useGhostMoveable'; +import { useCanvasDropHandler } from './useCanvasDropHandler'; //TODO: Revisit the logic of height (dropRef) @@ -70,7 +66,7 @@ export const Container = React.memo( const setFocusedParentId = useStore((state) => state.setFocusedParentId, shallow); const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop; - // Initialize ghost moveable hook (only for main canvas) + // Initialize ghost moveable hook const { activateGhost, deactivateGhost } = useGhostMoveable(id); // Monitor drag layer to update ghost position continuously @@ -78,14 +74,12 @@ export const Container = React.memo( isDragging: monitor.isDragging(), })); - // // Cleanup ghost when drag ends - // useEffect(() => { - // if (!isDragging) { - // setTimeout(() => { - // deactivateGhost(); - // }, 1000); - // } - // }, [id, isDragging, deactivateGhost]); + // // // Cleanup ghost when drag ends + useEffect(() => { + if (!isDragging) { + deactivateGhost(); + } + }, [id, isDragging, deactivateGhost]); const isContainerReadOnly = useMemo(() => { return (index !== 0 && (componentType === 'Listview' || componentType === 'Kanban')) || currentMode === 'view'; @@ -93,29 +87,29 @@ export const Container = React.memo( const setCurrentDragCanvasId = useGridStore((state) => state.actions.setCurrentDragCanvasId); + // Get the drop handler from the new hook + const handleDrop = useCanvasDropHandler({ + appType, + }); + const [{ isOverCurrent }, drop] = useDrop({ accept: 'box', - hover: (item, monitor) => { - // Use mouse position to determine the most specific container + hover: (item, monitor) => { const clientOffset = monitor.getClientOffset(); - - // If no client offset, the drag might be ending - clean up ghost - // if (!clientOffset) { - // deactivateGhost(); - // return; - // } - + const appCanvasWidth = realCanvasRef?.current?.offsetWidth || 0; if (clientOffset) { const elementAtPoint = document.elementFromPoint(clientOffset.x, clientOffset.y); const closestCanvas = elementAtPoint?.closest('.real-canvas'); - const canvasId = closestCanvas?.getAttribute('data-parentId') || - closestCanvas?.id?.replace('canvas-', '') || - (closestCanvas?.id === 'real-canvas' ? 'canvas' : null); - + const canvasId = + closestCanvas?.getAttribute('data-parentId') || + closestCanvas?.id?.replace('canvas-', '') || + (closestCanvas?.id === 'real-canvas' ? 'canvas' : null); + // Only update if this container is the most specific one under the mouse if (canvasId === id) { + // console.log('Container hover', canvasId, id); setCurrentDragCanvasId(id); } } @@ -123,73 +117,17 @@ export const Container = React.memo( let width = (appCanvasWidth * item.component?.defaultSize?.width) / NO_OF_GRIDS; const componentSize = { width: width, - height: item.component?.defaultSize?.height + height: item.component?.defaultSize?.height, }; // const clientOffset = monitor.getClientOffset(); - if (clientOffset) { + if (clientOffset && id === 'canvas') { activateGhost(componentSize, clientOffset, realCanvasRef); } }, - drop: async ({ componentType, component }, monitor) => { - console.log('drop'); - // Reset canvas ID when dropping - setCurrentDragCanvasId(null); - - // Ensure ghost is deactivated before processing drop - deactivateGhost(); - - // Add a small delay to allow moveable to properly clean up - // await new Promise(resolve => setTimeout(resolve, 10)); - - // Deactivate ghost when dropping - setShowModuleBorder(false); // Hide the module border when dropping - if (currentMode === 'view' || (appType === 'module' && componentType !== 'ModuleContainer')) return; - const didDrop = monitor.didDrop(); - if (didDrop) return; - if (componentType === 'PDF' && !isPDFSupported()) { - toast.error( - 'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.' - ); - return; - } - - // IMPORTANT: This logic needs to be changed when we implement the module versioning - const moduleInfo = component?.moduleId - ? { - moduleId: component.moduleId, - versionId: component.versionId, - environmentId: component.environmentId, - moduleName: component.displayName, - moduleContainer: component.moduleContainer, - } - : undefined; - - if (WIDGETS_WITH_DEFAULT_CHILDREN.includes(componentType)) { - const parentComponent = addNewWidgetToTheEditor( - componentType, - monitor, - currentLayout, - realCanvasRef, - id, - moduleInfo - ); - const childComponents = addChildrenWidgetsToParent(componentType, parentComponent?.id, currentLayout); - const newComponents = [parentComponent, ...childComponents]; - await addComponentToCurrentPage(newComponents); - setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION); - } else { - const newComponent = addNewWidgetToTheEditor( - componentType, - monitor, - currentLayout, - realCanvasRef, - id, - moduleInfo - ); - await addComponentToCurrentPage([newComponent]); - setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION); - } + drop: (item, monitor) => { + console.log('Container drop', item, monitor.getClientOffset()); + handleDrop(item, monitor, id); }, collect: (monitor) => ({ isOverCurrent: monitor.isOver({ shallow: true }), diff --git a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx index 2e15c2926b..297be699a0 100644 --- a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx +++ b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx @@ -86,12 +86,17 @@ export default function Grid({ gridWidth, currentLayout }) { const getExposedValueOfComponent = useStore((state) => state.getExposedValueOfComponent, shallow); const setReorderContainerChildren = useStore((state) => state.setReorderContainerChildren, shallow); const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); + const snapContainer = useMemo(() => { if (currentDragCanvasId) { return `#canvas-${currentDragCanvasId}`; } + if (dragParentId) { + return `#canvas-${dragParentId}`; + } return '#real-canvas'; - }, [currentDragCanvasId]); + }, [currentDragCanvasId, dragParentId]); + const moveableTarget = useMemo(() => { if (virtualTarget) { return '#moveable-ghost-element'; @@ -109,57 +114,6 @@ export default function Grid({ gridWidth, currentLayout }) { }; }, []); - // useEffect(() => { - // const selectedSet = new Set(selectedComponents); - // const draggingOrResizingId = draggingComponentId || resizingComponentId; - // const isGrouped = findHighestLevelofSelection().length > 1; - // const firstSelectedParent = - // selectedComponents.length > 0 ? boxList.find((b) => b.id === selectedComponents[0])?.parent : null; - // const selectedParent = dragParentId || firstSelectedParent; - - // const guidelines = boxList - // .filter((box) => { - // const isVisible = - // getResolvedValue(box?.component?.definition?.properties?.visibility?.value) || - // getResolvedValue(box?.component?.definition?.styles?.visibility?.value); - - // // Early return for non-visible elements - // if (!isVisible) return false; - - // // if (virtualTarget) { - // // return true; - // // } - - // if (isGrouped) { - // // If component is selected, don't show its guidelines - // if (selectedSet.has(box.id)) return false; - // return selectedParent ? box.parent === selectedParent : !box.parent; - // } - - // if (draggingOrResizingId) { - // if (box.id === draggingOrResizingId) return false; - // return dragParentId ? box.parent === dragParentId : !box.parent; - // } - - // // if (virtualTarget) { - // // return true; - // // } - - // return true; - // }) - // .map((box) => `.ele-${box.id}`); - - // // Combine static guidelines with dynamic ones (for ghost elements) - // setElementGuidelines(guidelines); - // }, [ - // boxList, - // dragParentId, - // draggingComponentId, - // resizingComponentId, - // selectedComponents, - // getResolvedValue, - // ]); - useEffect(() => { setBoxList( Object.keys(currentPageComponents) @@ -626,12 +580,12 @@ export default function Grid({ gridWidth, currentLayout }) { (component) => !selectedComponents.includes(component.getAttribute('widgetid')) ); const draggingOrResizing = draggingComponentId || resizingComponentId; - if (!draggingOrResizing && components.length > 0) { + if (!draggingOrResizing && components.length > 0 && !virtualTarget) { for (const component of components) { component?.classList?.remove('active-target'); } } - }, [draggingComponentId, resizingComponentId, isGroupDragging, selectedComponents]); + }, [draggingComponentId, resizingComponentId, isGroupDragging, selectedComponents, virtualTarget]); useGroupedTargetsScrollHandler(groupedTargets, boxList, moveableRef); if (mode !== 'edit') return null; @@ -995,18 +949,17 @@ export default function Grid({ gridWidth, currentLayout }) { }} onDrag={(e) => { if (e.target.id === 'moveable-ghost-element') { - // showGridLines(); - // + showGridLines(); const _gridWidth = useGridStore.getState().subContainerWidths[currentDragCanvasId] || gridWidth; let left = e.translate[0]; let top = e.translate[1]; // console.log('e.translate', e.translate); - if (currentDragCanvasId === 'canvas') { - left = Math.round(e.translate[0] / _gridWidth) * _gridWidth; - top = Math.round(e.translate[1] / GRID_HEIGHT) * GRID_HEIGHT; - } + // if (currentDragCanvasId === 'canvas') { + // console.log('e.translate', e.translate, _gridWidth); + left = Math.round(e.translate[0] / _gridWidth) * _gridWidth; + top = Math.round(e.translate[1] / GRID_HEIGHT) * GRID_HEIGHT; + console.log('e.translate', e.translate, left, top); e.target.style.transform = `translate(${left}px, ${top}px)`; - console.log('e.target', false); return false; } // Since onDrag is called multiple times when dragging, hence we are using isDraggingRef to prevent setting state again and again @@ -1029,10 +982,10 @@ export default function Grid({ gridWidth, currentLayout }) { e.target.style.width = `${draggingWidgetWidth}px`; // This logic is to handle the case when the dragged element is over a new canvas - if (_dragParentId !== currentParentId) { - left = e.translate[0]; - top = e.translate[1]; - } + // if (_dragParentId !== currentParentId) { + // left = e.translate[0]; + // top = e.translate[1]; + // } // Special case for Modal const oldParentId = boxList.find((b) => b.id === e.target.id)?.parent; @@ -1200,7 +1153,7 @@ export default function Grid({ gridWidth, currentLayout }) { // snapGridAll={true} scrollable={true} snapContainer={snapContainer} - snapGridWidth={100} + // snapGridWidth={100} /> ); diff --git a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js index 6222cc596d..fd58bf2959 100644 --- a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js +++ b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js @@ -34,7 +34,7 @@ export const addNewWidgetToTheEditor = ( parentId, moduleInfo = undefined ) => { - const canvasBoundingRect = realCanvasRef?.current?.getBoundingClientRect(); + const canvasBoundingRect = realCanvasRef?.current?.getBoundingClientRect() || realCanvasRef?.getBoundingClientRect(); const componentMeta = componentTypes.find((component) => component.component === componentType); const componentName = computeComponentName(componentType, useStore.getState().getCurrentPageComponents()); diff --git a/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js b/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js new file mode 100644 index 0000000000..557ec8a697 --- /dev/null +++ b/frontend/src/AppBuilder/AppCanvas/useCanvasDropHandler.js @@ -0,0 +1,94 @@ +import useStore from '@/AppBuilder/_stores/store'; +import { useGridStore } from '@/_stores/gridStore'; +import { shallow } from 'zustand/shallow'; +import { noop } from 'lodash'; +import { addChildrenWidgetsToParent, addNewWidgetToTheEditor } from '../AppCanvas/appCanvasUtils'; +import { WIDGETS_WITH_DEFAULT_CHILDREN } from '../AppCanvas/appCanvasConstants'; +import { RIGHT_SIDE_BAR_TAB } from '../RightSideBar/rightSidebarConstants'; +import { isPDFSupported } from '@/_helpers/appUtils'; +import toast from 'react-hot-toast'; +import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext'; +import { useGhostMoveable } from '../_hooks/useGhostMoveable'; + +export const useCanvasDropHandler = ({ appType }) => { + const { moduleId } = useModuleContext(); + + const addComponentToCurrentPage = useStore((state) => state.addComponentToCurrentPage, shallow); + const setActiveRightSideBarTab = useStore((state) => state.setActiveRightSideBarTab, shallow); + const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop; + const currentMode = useStore((state) => state.modeStore.modules[moduleId].currentMode, shallow); + const currentLayout = useStore((state) => state.currentLayout, shallow); + const setCurrentDragCanvasId = useGridStore((state) => state.actions.setCurrentDragCanvasId); + const { deactivateGhost } = useGhostMoveable(); + const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); + + // console.log('currentDragCanvasId', currentDragCanvasId); + + const handleDrop = ({ componentType: draggedComponentType, component }, monitor, canvasId) => { + const realCanvasRef = + document.getElementById(`canvas-${currentDragCanvasId}`) || document.getElementById(`real-canvas`); + // Reset canvas ID when dropping + setCurrentDragCanvasId(null); + + // Ensure ghost is deactivated before processing drop + deactivateGhost(); + + // Deactivate ghost when dropping + setShowModuleBorder(false); // Hide the module border when dropping + + if (currentMode === 'view' || (appType === 'module' && draggedComponentType !== 'ModuleContainer')) { + return; + } + + // const didDrop = monitor.didDrop(); + // if (didDrop) { + // return; + // } + + if (draggedComponentType === 'PDF' && !isPDFSupported()) { + toast.error( + 'PDF is not supported in this version of browser. We recommend upgrading to the latest version for full support.' + ); + return; + } + + // IMPORTANT: This logic needs to be changed when we implement the module versioning + const moduleInfo = component?.moduleId + ? { + moduleId: component.moduleId, + versionId: component.versionId, + environmentId: component.environmentId, + moduleName: component.displayName, + moduleContainer: component.moduleContainer, + } + : undefined; + + if (WIDGETS_WITH_DEFAULT_CHILDREN.includes(draggedComponentType)) { + const parentComponent = addNewWidgetToTheEditor( + draggedComponentType, + monitor, + currentLayout, + realCanvasRef, + currentDragCanvasId, + moduleInfo + ); + const childComponents = addChildrenWidgetsToParent(draggedComponentType, parentComponent?.id, currentLayout); + const newComponents = [parentComponent, ...childComponents]; + addComponentToCurrentPage(newComponents); + setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION); + } else { + const newComponent = addNewWidgetToTheEditor( + draggedComponentType, + monitor, + currentLayout, + realCanvasRef, + currentDragCanvasId, + moduleInfo + ); + addComponentToCurrentPage([newComponent]); + setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION); + } + }; + + return handleDrop; +}; diff --git a/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx b/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx index d0d6249c98..fb925d5cee 100644 --- a/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx +++ b/frontend/src/AppBuilder/RightSideBar/ComponentManagerTab/DragLayer.jsx @@ -10,21 +10,36 @@ import { shallow } from 'zustand/shallow'; import { useModuleContext } from '@/AppBuilder/_contexts/ModuleContext'; import { noop } from 'lodash'; import { useGridStore } from '@/_stores/gridStore'; +import { useCanvasDropHandler } from '@/AppBuilder/AppCanvas/useCanvasDropHandler'; export const DragLayer = ({ index, component, isModuleTab = false }) => { const { isModuleEditor } = useModuleContext(); const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop; + const handleDrop = useCanvasDropHandler({ appType: isModuleTab ? 'module' : 'app' }) || noop; + const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId, shallow); + const [{ isDragging }, drag, preview] = useDrag( () => ({ type: 'box', item: { componentType: component.component, component }, collect: (monitor) => ({ isDragging: monitor.isDragging() }), + end: (item, monitor) => { + const clientOffset = monitor.getClientOffset(); + console.log('end', item, monitor.getDropResult(), monitor.getClientOffset()); + console.log('currentDragCanvasId', currentDragCanvasId); + if (clientOffset) { + // const canvas = document.getElementById(`canvas-${currentDragCanvasId}`); + const realCanvas = document.getElementById(`real-canvas`); + handleDrop(item, monitor, realCanvas, currentDragCanvasId); + } + // if (didDrop) { + // handleDrop(item, monitor); + // } + }, }), [component.component] ); - const getMoveableRef = useGridStore((state) => state.moveableRef); - const setVirtualTarget = useGridStore((state) => state.actions.setVirtualTarget); - const newDiv = useRef(null); + useEffect(() => { preview(getEmptyImage(), { captureDraggingState: true }); }, []); @@ -41,7 +56,6 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => { // ? component.module_container.layouts[currentLayout] // : component.defaultSize || { width: 30, height: 40 }; - return ( <> {/* {isDragging && } */} @@ -49,66 +63,13 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => { ref={drag} className="draggable-box" style={{ height: '100%', width: isModuleTab && '100%' }} + // onDragEnd={(e) => { + // const realCanvas = document.getElementById(`real-canvas`); + // handleDrop(e, realCanvas, currentDragCanvasId); + // }} > {isModuleTab ? : } ); }; - -const CustomDragLayer = ({ size }) => { - const { currentOffset, item } = useDragLayer((monitor) => ({ - currentOffset: monitor.getSourceClientOffset(), - item: monitor.getItem(), - })); - if (!currentOffset) return null; - - const canvasWidth = item?.canvasWidth; - const canvasBounds = item?.canvasRef?.getBoundingClientRect(); - const height = size.height; - - const appCanvasWidth = document.getElementById('real-canvas')?.offsetWidth || 0; - - // Calculate width based on the app canvas's grid - let width = (appCanvasWidth * size.width) / NO_OF_GRIDS; - - // Calculate position relative to the current canvas (parent or child) - const left = currentOffset.x - (canvasBounds?.left || 0); - const top = currentOffset.y - (canvasBounds?.top || 0); - - // Ensure width doesn't exceed the current container's width - if (width > canvasWidth) { - width = canvasWidth; - } - - // Snap width to grid (round to nearest grid unit) - const gridUnitWidth = canvasWidth / NO_OF_GRIDS; - const gridUnits = Math.round(width / gridUnitWidth); - width = gridUnits * gridUnitWidth; - - const [x, y] = snapToGrid(canvasWidth, left, top); - return ( -
-
-
- ); -}; diff --git a/frontend/src/AppBuilder/_hooks/useGhostMoveable.js b/frontend/src/AppBuilder/_hooks/useGhostMoveable.js index eee05f6157..cea7a461cb 100644 --- a/frontend/src/AppBuilder/_hooks/useGhostMoveable.js +++ b/frontend/src/AppBuilder/_hooks/useGhostMoveable.js @@ -3,7 +3,7 @@ import { useGridStore } from '@/_stores/gridStore'; import { NO_OF_GRIDS, GRID_HEIGHT } from '@/AppBuilder/AppCanvas/appCanvasConstants'; import { snapToGrid } from '@/AppBuilder/AppCanvas/appCanvasUtils'; -export const useGhostMoveable = (canvasId) => { +export const useGhostMoveable = () => { const ghostElementRef = useRef(null); const isActiveRef = useRef(false); @@ -29,7 +29,6 @@ export const useGhostMoveable = (canvasId) => { left: 0; `; - // const container = document.querySelectorAll(`[component-id="${canvasId}"]`)[0]; const container = document.getElementById('real-canvas'); container.appendChild(ghost); ghostElementRef.current = ghost; @@ -49,7 +48,7 @@ export const useGhostMoveable = (canvasId) => { const snappedX = Math.round(relativeX / gridWidth) * gridWidth; const snappedY = Math.round(relativeY / GRID_HEIGHT) * GRID_HEIGHT; console.log(snappedX, snappedY); - ghostElementRef.current.style.transform = `translate(${snappedX}px, ${snappedY}px)`; + ghostElementRef.current.style.transform = `translate(${relativeX}px, ${relativeY}px)`; }; const activateGhost = (componentSize, mousePosition, canvasRef) => { @@ -98,8 +97,6 @@ export const useGhostMoveable = (canvasId) => { ghostElementRef.current = null; // End any active drag operation first // moveableInstance.dragEnd(); - - } catch (error) { console.warn('Failed to trigger moveable dragEnd:', error); } diff --git a/frontend/src/AppBuilder/_stores/slices/gridSlice.js b/frontend/src/AppBuilder/_stores/slices/gridSlice.js index 8b2f61bd9a..d168bd57da 100644 --- a/frontend/src/AppBuilder/_stores/slices/gridSlice.js +++ b/frontend/src/AppBuilder/_stores/slices/gridSlice.js @@ -12,6 +12,7 @@ const initialState = { containerId: null, triggerUpdate: 0, }, + shouldPreventDrop: false, }; export const createGridSlice = (set, get) => ({ @@ -99,4 +100,7 @@ export const createGridSlice = (set, get) => ({ reorderContainerChildren: { containerId, triggerUpdate: state.reorderContainerChildren.triggerUpdate + 1 }, })); }, + setShouldPreventDrop: (shouldPreventDrop) => { + set(() => ({ shouldPreventDrop })); + }, }); diff --git a/server/package-lock.json b/server/package-lock.json index fa1e6d68ba..3cef36d54f 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -20645,4 +20645,4 @@ } } } -} \ No newline at end of file +}