mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 09:28:31 +00:00
Refactor
This commit is contained in:
parent
74dada642c
commit
7198427ff9
5 changed files with 113 additions and 58 deletions
|
|
@ -12,8 +12,7 @@ import NoComponentCanvasContainer from './NoComponentCanvasContainer';
|
|||
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 { useDropVirtualMoveableGhost } from '@/AppBuilder/_hooks/useDropVirtualMoveableGhost';
|
||||
import { useCanvasDropHandler } from './useCanvasDropHandler';
|
||||
import { findNewParentIdFromMousePosition } from './Grid/gridUtils';
|
||||
|
||||
|
|
@ -37,33 +36,25 @@ export const Container = React.memo(
|
|||
columns,
|
||||
darkMode,
|
||||
canvasMaxWidth,
|
||||
isViewerSidebarPinned,
|
||||
pageSidebarStyle,
|
||||
pagePositionType,
|
||||
componentType,
|
||||
appType,
|
||||
}) => {
|
||||
const { moduleId } = useModuleContext();
|
||||
const realCanvasRef = useRef(null);
|
||||
const components = useStore((state) => state.getContainerChildrenMapping(id, moduleId), shallow);
|
||||
|
||||
const addComponentToCurrentPage = useStore((state) => state.addComponentToCurrentPage, shallow);
|
||||
const setActiveRightSideBarTab = useStore((state) => state.setActiveRightSideBarTab, shallow);
|
||||
const setLastCanvasClickPosition = useStore((state) => state.setLastCanvasClickPosition, shallow);
|
||||
const canvasBgColor = useStore(
|
||||
(state) => (id === 'canvas' ? state.getCanvasBackgroundColor('canvas', darkMode) : ''),
|
||||
shallow
|
||||
);
|
||||
const isPagesSidebarHidden = useStore((state) => state.getPagesSidebarVisibility('canvas'), shallow);
|
||||
const currentMode = useStore((state) => state.modeStore.modules[moduleId].currentMode, shallow);
|
||||
const currentLayout = useStore((state) => state.currentLayout, shallow);
|
||||
const setFocusedParentId = useStore((state) => state.setFocusedParentId, shallow);
|
||||
const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop;
|
||||
|
||||
// Initialize ghost moveable hook
|
||||
const { activateGhost, deactivateGhost } = useGhostMoveable(id);
|
||||
const { activateMoveableGhost, deactivateMoveableGhost } = useDropVirtualMoveableGhost();
|
||||
|
||||
// Monitor drag layer to update ghost position continuously
|
||||
// // Monitor drag layer to update ghost position continuously
|
||||
const { isDragging } = useDragLayer((monitor) => ({
|
||||
isDragging: monitor.isDragging(),
|
||||
}));
|
||||
|
|
@ -71,9 +62,9 @@ export const Container = React.memo(
|
|||
// // // Cleanup ghost when drag ends
|
||||
useEffect(() => {
|
||||
if (!isDragging) {
|
||||
deactivateGhost();
|
||||
deactivateMoveableGhost();
|
||||
}
|
||||
}, [id, isDragging, deactivateGhost]);
|
||||
}, [id, isDragging, deactivateMoveableGhost]);
|
||||
|
||||
const isContainerReadOnly = useMemo(() => {
|
||||
return (index !== 0 && (componentType === 'Listview' || componentType === 'Kanban')) || currentMode === 'view';
|
||||
|
|
@ -81,8 +72,7 @@ export const Container = React.memo(
|
|||
|
||||
const setCurrentDragCanvasId = useGridStore((state) => state.actions.setCurrentDragCanvasId);
|
||||
|
||||
// Get the drop handler from the new hook
|
||||
const handleDrop = useCanvasDropHandler({
|
||||
const { handleDrop } = useCanvasDropHandler({
|
||||
appType,
|
||||
});
|
||||
|
||||
|
|
@ -106,7 +96,7 @@ export const Container = React.memo(
|
|||
height: item.component?.defaultSize?.height,
|
||||
};
|
||||
if (clientOffset && id === 'canvas') {
|
||||
activateGhost(componentSize, clientOffset, realCanvasRef);
|
||||
activateMoveableGhost(componentSize, clientOffset, realCanvasRef);
|
||||
}
|
||||
},
|
||||
drop: (item, monitor) => {
|
||||
|
|
@ -136,29 +126,6 @@ export const Container = React.memo(
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [canvasWidth, listViewMode, columns]);
|
||||
|
||||
const getCanvasWidth = useCallback(() => {
|
||||
// if (
|
||||
// id === 'canvas' &&
|
||||
// !isPagesSidebarHidden &&
|
||||
// isViewerSidebarPinned &&
|
||||
// currentLayout !== 'mobile' &&
|
||||
// pagePositionType == 'side' &&
|
||||
// appType !== 'module'
|
||||
// ) {
|
||||
// return `calc(100% - ${pageSidebarStyle === 'icon' ? '85px' : '226px'})`;
|
||||
// }
|
||||
// if (
|
||||
// id === 'canvas' &&
|
||||
// !isPagesSidebarHidden &&
|
||||
// !isViewerSidebarPinned &&
|
||||
// currentLayout !== 'mobile' &&
|
||||
// pagePositionType == 'side'
|
||||
// ) {
|
||||
// return `calc(100% - ${'44px'})`;
|
||||
// }
|
||||
return '100%';
|
||||
}, [id, isPagesSidebarHidden, isViewerSidebarPinned, currentLayout, pagePositionType, pageSidebarStyle]);
|
||||
|
||||
const handleCanvasClick = useCallback(
|
||||
(e) => {
|
||||
const realCanvas = e.target.closest('.real-canvas');
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ export function snapToGrid(canvasWidth, x, y) {
|
|||
//TODO: componentTypes should be a key value pair and get the definition directly by passing the componentType
|
||||
export const addNewWidgetToTheEditor = (
|
||||
componentType,
|
||||
eventMonitorObject,
|
||||
currentLayout,
|
||||
realCanvasRef,
|
||||
parentId,
|
||||
|
|
@ -46,13 +45,12 @@ export const addNewWidgetToTheEditor = (
|
|||
const { e } = useGridStore.getState().getGhostDragPosition();
|
||||
const subContainerWidth = canvasBoundingRect?.width;
|
||||
|
||||
const { left: left3, top: top3 } = getMouseDistanceFromParentDiv(
|
||||
const { left: _left, top: _top } = getMouseDistanceFromParentDiv(
|
||||
e,
|
||||
parentId === 'canvas' ? 'real-canvas' : parentId,
|
||||
parentCanvasType
|
||||
);
|
||||
// [left, top] = snapToGrid(subContainerWidth, left, top);
|
||||
let [left, top] = snapToGrid(subContainerWidth, left3, top3);
|
||||
let [left, top] = snapToGrid(subContainerWidth, _left, _top);
|
||||
|
||||
const gridWidth = subContainerWidth / NO_OF_GRIDS;
|
||||
left = Math.round(left / gridWidth);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ 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';
|
||||
import { handleDeactivateTargets, hideGridLines } from '../AppCanvas/Grid/gridUtils';
|
||||
|
||||
export const useCanvasDropHandler = ({ appType }) => {
|
||||
|
|
@ -24,15 +23,13 @@ export const useCanvasDropHandler = ({ appType }) => {
|
|||
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 handleDrop = async ({ componentType: draggedComponentType, component }, monitor, canvasId) => {
|
||||
const realCanvasRef =
|
||||
!canvasId || canvasId === 'canvas'
|
||||
? document.getElementById(`real-canvas`)
|
||||
: document.getElementById(`canvas-${canvasId}`);
|
||||
|
||||
// Ensure ghost is deactivated before processing drop
|
||||
deactivateGhost();
|
||||
handleDeactivateTargets();
|
||||
hideGridLines();
|
||||
|
||||
|
|
@ -42,11 +39,6 @@ export const useCanvasDropHandler = ({ appType }) => {
|
|||
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.'
|
||||
|
|
@ -70,7 +62,6 @@ export const useCanvasDropHandler = ({ appType }) => {
|
|||
if (WIDGETS_WITH_DEFAULT_CHILDREN.includes(draggedComponentType)) {
|
||||
let parentComponent = addNewWidgetToTheEditor(
|
||||
draggedComponentType,
|
||||
monitor,
|
||||
currentLayout,
|
||||
realCanvasRef,
|
||||
canvasId,
|
||||
|
|
@ -85,7 +76,6 @@ export const useCanvasDropHandler = ({ appType }) => {
|
|||
} else {
|
||||
const newComponent = addNewWidgetToTheEditor(
|
||||
draggedComponentType,
|
||||
monitor,
|
||||
currentLayout,
|
||||
realCanvasRef,
|
||||
canvasId,
|
||||
|
|
@ -119,5 +109,5 @@ export const useCanvasDropHandler = ({ appType }) => {
|
|||
setCurrentDragCanvasId(null);
|
||||
};
|
||||
|
||||
return handleDrop;
|
||||
return { handleDrop };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => {
|
|||
const isRightSidebarPinned = useStore((state) => state.isRightSidebarPinned);
|
||||
const { isModuleEditor } = useModuleContext();
|
||||
const setShowModuleBorder = useStore((state) => state.setShowModuleBorder, shallow) || noop;
|
||||
const handleDrop = useCanvasDropHandler({ appType: isModuleTab ? 'module' : 'app' }) || noop;
|
||||
const { handleDrop } = useCanvasDropHandler({ appType: isModuleTab ? 'module' : 'app' }) || noop;
|
||||
|
||||
const [{ isDragging }, drag, preview] = useDrag(
|
||||
() => ({
|
||||
|
|
@ -59,7 +59,6 @@ export const DragLayer = ({ index, component, isModuleTab = false }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{/* {isDragging && <CustomDragLayer size={size} />} */}
|
||||
<div ref={drag} className="draggable-box" style={{ height: '100%', width: isModuleTab && '100%' }}>
|
||||
{isModuleTab ? <ModuleWidgetBox module={component} /> : <WidgetBox index={index} component={component} />}
|
||||
</div>
|
||||
|
|
|
|||
101
frontend/src/AppBuilder/_hooks/useDropVirtualMoveableGhost.js
Normal file
101
frontend/src/AppBuilder/_hooks/useDropVirtualMoveableGhost.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import { useRef } from 'react';
|
||||
import { useGridStore } from '@/_stores/gridStore';
|
||||
|
||||
export const useDropVirtualMoveableGhost = () => {
|
||||
const ghostElementRef = useRef(null);
|
||||
const isActiveRef = useRef(false);
|
||||
|
||||
const getMoveableRef = useGridStore((state) => state.moveableRef);
|
||||
const setVirtualTarget = useGridStore((state) => state.actions.setVirtualTarget);
|
||||
|
||||
const createGhostMoveElement = (componentSize) => {
|
||||
if (ghostElementRef.current) return;
|
||||
|
||||
const ghost = document.createElement('div');
|
||||
ghost.id = 'moveable-ghost-element';
|
||||
ghost.className = 'moveable-ghost target';
|
||||
ghost.style.cssText = `
|
||||
position: absolute;
|
||||
width: ${componentSize.width || 100}px;
|
||||
height: ${componentSize.height || 40}px;
|
||||
background: #D9E2FC;
|
||||
opacity: 0.7;
|
||||
pointer-events: none;
|
||||
z-index: 9998;
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
left: 0;
|
||||
`;
|
||||
|
||||
const container = document.getElementById('real-canvas');
|
||||
container.appendChild(ghost);
|
||||
ghostElementRef.current = ghost;
|
||||
|
||||
return ghost;
|
||||
};
|
||||
|
||||
const updateMoveableGhostPosition = (mousePosition, canvasRef) => {
|
||||
if (!ghostElementRef.current || !canvasRef?.current || !mousePosition) return;
|
||||
|
||||
const canvasRect = canvasRef.current.getBoundingClientRect();
|
||||
const relativeX = mousePosition.x - canvasRect.left;
|
||||
const relativeY = mousePosition.y - canvasRect.top;
|
||||
|
||||
ghostElementRef.current.style.transform = `translate(${relativeX}px, ${relativeY}px)`;
|
||||
};
|
||||
|
||||
const activateMoveableGhost = (componentSize, mousePosition, canvasRef) => {
|
||||
if (isActiveRef.current) return;
|
||||
|
||||
isActiveRef.current = true;
|
||||
|
||||
const ghost = createGhostMoveElement(componentSize, canvasRef);
|
||||
if (ghost && mousePosition) {
|
||||
updateMoveableGhostPosition(mousePosition, canvasRef);
|
||||
|
||||
// Trigger moveable drag on the ghost element to show guidelines
|
||||
const moveableInstance = getMoveableRef;
|
||||
if (moveableInstance && ghost) {
|
||||
try {
|
||||
const fakeEvent = new MouseEvent('mousedown', {
|
||||
clientX: mousePosition.x,
|
||||
clientY: mousePosition.y,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
view: window,
|
||||
button: 0,
|
||||
buttons: 1,
|
||||
});
|
||||
moveableInstance.waitToChangeTarget().then((e) => {
|
||||
moveableInstance.dragStart(fakeEvent, ghost);
|
||||
});
|
||||
setVirtualTarget(ghost);
|
||||
} catch (error) {
|
||||
console.warn('Failed to trigger moveable dragStart:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const deactivateMoveableGhost = () => {
|
||||
if (!isActiveRef.current) return;
|
||||
|
||||
isActiveRef.current = false;
|
||||
|
||||
const moveableInstance = getMoveableRef;
|
||||
if (moveableInstance && ghostElementRef.current) {
|
||||
try {
|
||||
setVirtualTarget(null);
|
||||
ghostElementRef.current.remove();
|
||||
ghostElementRef.current = null;
|
||||
} catch (error) {
|
||||
console.warn('Failed to trigger moveable dragEnd:', error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
activateMoveableGhost,
|
||||
deactivateMoveableGhost,
|
||||
};
|
||||
};
|
||||
Loading…
Reference in a new issue