fix for modal and resolve merge conflicts

This commit is contained in:
Nakul Nagargade 2025-07-02 10:48:16 +05:30
parent d315ce48e8
commit 74dada642c
5 changed files with 57 additions and 130 deletions

View file

@ -4,26 +4,18 @@ import cx from 'classnames';
import WidgetWrapper from './WidgetWrapper';
import useStore from '@/AppBuilder/_stores/store';
import { shallow } from 'zustand/shallow';
import { useDrop, useDragLayer, useDragDropManager } from 'react-dnd';
import {
addChildrenWidgetsToParent,
addNewWidgetToTheEditor,
computeViewerBackgroundColor,
getSubContainerWidthAfterPadding,
addDefaultButtonIdToForm,
} from './appCanvasUtils';
import { CANVAS_WIDTHS, NO_OF_GRIDS, WIDGETS_WITH_DEFAULT_CHILDREN, GRID_HEIGHT } from './appCanvasConstants';
import { useDrop, useDragLayer } from 'react-dnd';
import { computeViewerBackgroundColor, getSubContainerWidthAfterPadding } from './appCanvasUtils';
import { CANVAS_WIDTHS, NO_OF_GRIDS, GRID_HEIGHT } from './appCanvasConstants';
import { useGridStore } from '@/_stores/gridStore';
import NoComponentCanvasContainer from './NoComponentCanvasContainer';
import { RIGHT_SIDE_BAR_TAB } from '../RightSideBar/rightSidebarConstants';
import { isPDFSupported } from '@/_helpers/appUtils';
import toast from 'react-hot-toast';
import { ModuleContainerBlank } from '@/modules/Modules/components';
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';
import { findNewParentIdFromMousePosition } from './Grid/gridUtils';
//TODO: Revisit the logic of height (dropRef)
@ -102,14 +94,7 @@ export const Container = React.memo(
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' ? 'real-canvas' : null);
// Only update if this container is the most specific one under the mouse
const canvasId = findNewParentIdFromMousePosition(clientOffset.x, clientOffset.y, id);
if (canvasId === id) {
setCurrentDragCanvasId(id);
}
@ -117,11 +102,9 @@ export const Container = React.memo(
// Calculate width based on the app canvas's grid
let width = (appCanvasWidth * item.component?.defaultSize?.width) / NO_OF_GRIDS;
const componentSize = {
width: width,
width,
height: item.component?.defaultSize?.height,
};
// const clientOffset = monitor.getClientOffset();
if (clientOffset && id === 'canvas') {
activateGhost(componentSize, clientOffset, realCanvasRef);
}
@ -129,78 +112,6 @@ export const Container = React.memo(
drop: (item, monitor) => {
handleDrop(item, monitor, id);
},
// drop: async ({ componentType, component }, monitor) => {
// setShowModuleBorder(false);
// if (currentMode === 'view' || (appType === 'module' && componentType !== 'ModuleContainer')) return;
// const didDrop = monitor.didDrop();
// if (didDrop) return;
// const moduleInfo = component?.moduleId
// ? {
// moduleId: component.moduleId,
// versionId: component.versionId,
// environmentId: component.environmentId,
// moduleName: component.displayName,
// moduleContainer: component.moduleContainer,
// }
// : undefined;
// let addedComponent;
// if (WIDGETS_WITH_DEFAULT_CHILDREN.includes(componentType)) {
// let parentComponent = addNewWidgetToTheEditor(
// componentType,
// monitor,
// currentLayout,
// realCanvasRef,
// id,
// moduleInfo
// );
// const childComponents = addChildrenWidgetsToParent(componentType, parentComponent?.id, currentLayout);
// if (componentType === 'Form') {
// parentComponent = addDefaultButtonIdToForm(parentComponent, childComponents);
// }
// addedComponent = [parentComponent, ...childComponents];
// await addComponentToCurrentPage(addedComponent);
// } else {
// const newComponent = addNewWidgetToTheEditor(
// componentType,
// monitor,
// currentLayout,
// realCanvasRef,
// id,
// moduleInfo
// );
// addedComponent = [newComponent];
// await addComponentToCurrentPage(addedComponent);
// }
// setActiveRightSideBarTab(RIGHT_SIDE_BAR_TAB.CONFIGURATION);
// const canvas = document.querySelector('.canvas-container');
// const sidebar = document.querySelector('.editor-sidebar');
// const droppedElem = document.getElementById(addedComponent?.[0]?.id);
// if (!canvas || !sidebar || !droppedElem) return;
// const droppedRect = droppedElem.getBoundingClientRect();
// const sidebarRect = sidebar.getBoundingClientRect();
// const isOverlapping = droppedRect.right > sidebarRect.left && droppedRect.left < sidebarRect.right;
// if (isOverlapping) {
// const overlap = droppedRect.right - sidebarRect.left;
// canvas.scrollTo({
// left: canvas.scrollLeft + overlap,
// behavior: 'smooth',
// });
// }
// },
// collect: (monitor) => ({
// isOverCurrent: monitor.isOver({ shallow: true }),
// }),
});
const showEmptyContainer =

View file

@ -24,6 +24,7 @@ import {
computeScrollDeltaOnDrag,
getDraggingWidgetWidth,
positionDragGhostWidget,
findNewParentIdFromMousePosition,
} from './gridUtils';
import { dragContextBuilder, getAdjustedDropPosition } from './helpers/dragEnd';
import useStore from '@/AppBuilder/_stores/store';
@ -73,15 +74,11 @@ export default function Grid({ gridWidth, currentLayout }) {
const getTemporaryLayouts = useStore((state) => state.getTemporaryLayouts, shallow);
const updateContainerAutoHeight = useStore((state) => state.updateContainerAutoHeight, shallow);
const [canvasBounds, setCanvasBounds] = useState(CANVAS_BOUNDS);
const draggingComponentId = useGridStore((state) => state.draggingComponentId, shallow);
const resizingComponentId = useGridStore((state) => state.resizingComponentId, shallow);
const [dragParentId, setDragParentId] = useState(null);
const virtualTarget = useGridStore((state) => state.virtualTarget, shallow);
const { elementGuidelines } = useElementGudelines(
boxList,
selectedComponents,
draggingComponentId,
resizingComponentId,
dragParentId,
getResolvedValue,
virtualTarget
@ -97,6 +94,8 @@ export default function Grid({ gridWidth, currentLayout }) {
const groupedTargets = [...findHighestLevelofSelection().map((component) => '.ele-' + component.id)];
const [isVerticalExpansionRestricted, setIsVerticalExpansionRestricted] = useState(false);
const toggleRightSidebar = useStore((state) => state.toggleRightSidebar, shallow);
const draggingComponentId = useStore((state) => state.draggingComponentId, shallow);
const resizingComponentId = useStore((state) => state.resizingComponentId, shallow);
const snapContainer = useMemo(() => {
if (currentDragCanvasId) {
@ -350,6 +349,7 @@ export default function Grid({ gridWidth, currentLayout }) {
moveableRef.current.updateTarget();
}
}, [temporaryHeight]);
useEffect(() => {
reloadGrid();
// eslint-disable-next-line react-hooks/exhaustive-deps
@ -601,8 +601,8 @@ export default function Grid({ gridWidth, currentLayout }) {
const components = Array.from(document.querySelectorAll('.active-target')).filter(
(component) => !selectedComponents.includes(component.getAttribute('widgetid'))
);
const draggingOrResizing = draggingComponentId || resizingComponentId;
if (!draggingOrResizing && components.length > 0 && !virtualTarget) {
const draggingOrResizingComponentId = draggingComponentId || resizingComponentId;
if (!draggingOrResizingComponentId && components.length > 0 && !virtualTarget) {
for (const component of components) {
component?.classList?.remove('active-target');
}
@ -639,7 +639,7 @@ export default function Grid({ gridWidth, currentLayout }) {
onResize={(e) => {
const temporaryLayouts = getTemporaryLayouts();
if (resizingComponentId !== e.target.id) {
useGridStore.getState().actions.setResizingComponentId(e.target.id);
useStore.getState().setResizingComponentId(e.target.id);
showGridLines();
}
@ -715,7 +715,7 @@ export default function Grid({ gridWidth, currentLayout }) {
}}
onResizeEnd={(e) => {
try {
useGridStore.getState().actions.setResizingComponentId(null);
useStore.getState().setResizingComponentId(null);
const currentWidget = boxList.find(({ id }) => {
return id === e.target.id;
});
@ -1018,10 +1018,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;
@ -1066,16 +1066,7 @@ export default function Grid({ gridWidth, currentLayout }) {
// This block is to show grid lines on the canvas when the dragged element is over a new canvas
if (document.elementFromPoint(e.clientX, e.clientY)) {
const targetElems = document.elementsFromPoint(e.clientX, e.clientY);
const draggedOverElements = targetElems.filter(
(ele) =>
(ele.id !== e.target.id && ele.classList.contains('target')) || ele.classList.contains('real-canvas')
);
const draggedOverElem = draggedOverElements.find((ele) => ele.classList.contains('target'));
const draggedOverContainer = draggedOverElements.find((ele) => ele.classList.contains('real-canvas'));
// Determine potential new parent
let newParentId = draggedOverContainer?.getAttribute('data-parentId') || draggedOverElem?.id;
let newParentId = findNewParentIdFromMousePosition(e.clientX, e.clientY, e.target.id);
if (newParentId === e.target.id) {
newParentId = boxList.find((box) => box.id === e.target.id)?.component?.parent;

View file

@ -551,3 +551,29 @@ export const positionDragGhostWidget = (draggedElement) => {
ghostElement.style.width = `${draggedRect.width}px`;
ghostElement.style.height = `${draggedRect.height}px`;
};
/**
* Finds the new parent ID based on the current mouse position during drag operations
* @param {number} clientX - The X coordinate of the mouse position
* @param {number} clientY - The Y coordinate of the mouse position
* @param {string} currentTargetId - The ID of the currently dragged element to exclude from search
* @returns {string|null} - The new parent ID or null if no valid parent is found
*/
export const findNewParentIdFromMousePosition = (clientX, clientY, currentTargetId) => {
if (!document.elementFromPoint(clientX, clientY)) {
return null;
}
const targetElems = document.elementsFromPoint(clientX, clientY);
const draggedOverElements = targetElems.filter(
(ele) => (ele.id !== currentTargetId && ele.classList.contains('target')) || ele.classList.contains('real-canvas')
);
const draggedOverElem = draggedOverElements.find((ele) => ele.classList.contains('target'));
const draggedOverContainer = draggedOverElements.find((ele) => ele.classList.contains('real-canvas'));
// Determine potential new parent
const newParentId = draggedOverContainer?.getAttribute('data-parentId') || draggedOverElem?.id;
return newParentId || null;
};

View file

@ -1,19 +1,12 @@
import { useEffect, useState } from 'react';
import { findHighestLevelofSelection } from '../gridUtils';
import { useGridStore } from '@/_stores/gridStore';
import useStore from '@/AppBuilder/_stores/store';
export const useElementGudelines = (
boxList,
selectedComponents,
draggingComponentId,
resizingComponentId,
dragParentId,
getResolvedValue,
virtualTarget
) => {
export const useElementGudelines = (boxList, selectedComponents, dragParentId, getResolvedValue, virtualTarget) => {
const [elementGuidelines, setElementGuidelines] = useState([]);
// Get current drag canvas ID from store instead of drag layer
const draggingComponentId = useStore((state) => state.draggingComponentId);
const resizingComponentId = useStore((state) => state.resizingComponentId);
const currentDragCanvasId = useGridStore((state) => state.currentDragCanvasId);
useEffect(() => {
@ -23,6 +16,7 @@ export const useElementGudelines = (
const firstSelectedParent =
selectedComponents.length > 0 ? boxList.find((b) => b.id === selectedComponents[0])?.parent : null;
const selectedParent = dragParentId || firstSelectedParent;
const isAnyModalOpen = document.querySelector('#modal-container') ? true : false;
const guidelines = boxList
.filter((box) => {
@ -33,9 +27,13 @@ export const useElementGudelines = (
// Early return for non-visible elements
if (!isVisible) return false;
// Don't show guidelines for components which are outside the modal specially on main canvas
if (virtualTarget && isAnyModalOpen) {
if (box.parent === 'canvas' || !box.parent) return false;
}
// This block is for first time drop using react-dnd
if (virtualTarget && currentDragCanvasId !== null) {
// For main canvas (id = 'canvas'), show components with no parent or parent = 'canvas'
if (currentDragCanvasId === 'canvas') {
if (box.parent && box.parent !== 'canvas') return false;
} else {
@ -58,7 +56,6 @@ export const useElementGudelines = (
return true;
})
.map((box) => `.ele-${box.id}`);
setElementGuidelines(guidelines);
}, [
boxList,

View file

@ -10,6 +10,7 @@ const initialState = {
lastCanvasClickPosition: null,
temporaryLayouts: {},
draggingComponentId: null,
resizingComponentId: null,
reorderContainerChildren: {
containerId: null,
triggerUpdate: 0,
@ -36,6 +37,7 @@ export const createGridSlice = (set, get) => ({
get().toggleCanvasUpdater();
}, 200),
setDraggingComponentId: (id) => set(() => ({ draggingComponentId: id })),
setResizingComponentId: (id) => set(() => ({ resizingComponentId: id })),
moveComponentPosition: (direction) => {
const { setComponentLayout, currentLayout, getSelectedComponentsDefinition, debouncedToggleCanvasUpdater } = get();
let layouts = {};