Ver Fonte

start of shadow placement

Fred Lefévère-Laoide há 2 semanas atrás
pai
commit
5fab224a30

+ 1 - 1
frontend/taipy-gui/jest.config.js

@@ -28,6 +28,6 @@ module.exports = {
     coverageReporters: ["json", "html", "text"],
     modulePathIgnorePatterns: ["<rootDir>/packaging/"],
     moduleNameMapper: {"react-markdown": "<rootDir>/test-config/markdown.tsx"},
-    transformIgnorePatterns: ["<rootDir>/node_modules/(?!react-jsx-parser/)"],
+    transformIgnorePatterns: ["<rootDir>/node_modules/(?!react-jsx-parser|react-dnd|dnd-core|@react-dnd|react-dnd-test-utils/)"],
     ...createJsWithTsPreset()
 };

Diff do ficheiro suprimidas por serem muito extensas
+ 411 - 199
frontend/taipy-gui/package-lock.json


+ 1 - 0
frontend/taipy-gui/package.json

@@ -118,6 +118,7 @@
     "lint-staged": "^15.0.2",
     "mock-socket": "^9.0.7",
     "mock-xmlhttprequest": "^8.2.0",
+    "react-dnd-test-utils": "^16.0.1",
     "ts-jest": "^29.0.0",
     "ts-jest-mock-import-meta": "^1.2.0",
     "ts-loader": "^9.2.6",

+ 3 - 1
frontend/taipy-gui/src/components/Taipy/Part.spec.tsx

@@ -14,12 +14,14 @@
 import React from "react";
 import {render} from "@testing-library/react";
 import "@testing-library/jest-dom";
+import { wrapWithBackend } from "react-dnd-test-utils";
 
 import Part from './Part';
 
 describe("Part Component", () => {
     it("renders", async () => {
-        const {getByText} = render(<Part>bar</Part>);
+        const PartContext = wrapWithBackend(Part)
+        const {getByText} = render(<PartContext>bar</PartContext>);
         const elt = getByText("bar");
         expect(elt.tagName).toBe("DIV");
         expect(elt).toHaveClass("MuiBox-root")

+ 46 - 4
frontend/taipy-gui/src/components/Taipy/Selector.tsx

@@ -85,6 +85,7 @@ const MultipleItem = ({
     index = -1,
     lovVarName,
     targetId,
+    handleHover,
 }: ItemProps) => {
     const itemRef = useRef<HTMLDivElement>(null);
     const getDragItem = useCallback(
@@ -100,8 +101,7 @@ const MultipleItem = ({
                 isDragging: monitor.isDragging(),
             }),
             end: (item: DragItem, monitor) => {
-                const dropResult = monitor.getDropResult();
-                if (dropResult) {
+                if (monitor.getDropResult()) {
                     handleDrop?.(item.id, item.index, lovVarName || "", item.targetId);
                 }
             },
@@ -114,7 +114,10 @@ const MultipleItem = ({
             hover: (item: DragItem) => {
                 item.index = index;
                 item.targetId = targetId;
+                handleHover?.(item.id, index);
             },
+            drop: () => handleHover?.(),
+
         }),
         [dropTypes, index, targetId]
     );
@@ -192,6 +195,7 @@ const renderBoxSx = {
     width: "100%",
 } as CSSProperties;
 
+const dropItem = { id: "__TAIPY_DROP__", item: "Drop Here ..." } as LovItem;
 interface SelectorProps extends SelTreeProps {
     dropdown?: boolean;
     mode?: string;
@@ -219,6 +223,7 @@ const Selector = (props: SelectorProps) => {
     } = props;
     const [searchValue, setSearchValue] = useState("");
     const [selectedValue, setSelectedValue] = useState<string[]>([]);
+    const [lovListWithDrop, setLovListWithDrop] = useState<LovItem[]>();
     const dispatch = useDispatch();
     const module = useModule();
     const theme = useTheme();
@@ -254,7 +259,9 @@ const Selector = (props: SelectorProps) => {
             hover: (item: DragItem) => {
                 item.index = -1;
                 item.targetId = id;
+                handleHover?.(item.id, 0);
             },
+            drop: () => handleHover?.(),
         }),
         [dropTypes, id]
     );
@@ -274,8 +281,41 @@ const Selector = (props: SelectorProps) => {
         },
         [lovVarName, dispatch, module, props.onAction, id]
     );
+    const dragLeaveHandler = useCallback(() => {
+        setLovListWithDrop((oldList) => {
+            if (!oldList) {
+                return oldList;
+            }
+            return oldList.filter((item) => item.id !== dropItem.id);
+        });
+    }, []);
+    const handleHover = useCallback(
+        (_itemId?: string, dropIndex?: number) =>
+            setLovListWithDrop((oldList) => {
+                if (!oldList) {
+                    return oldList;
+                }
+                if (dropIndex === undefined) {
+                    return oldList.filter((item) => item.id !== dropItem.id);
+                }
+                const oldDropIndex = oldList.findIndex((item) => item.id === dropItem.id);
+                if (oldDropIndex !== -1) {
+                    if (dropIndex === oldDropIndex) {
+                        return oldList;
+                    }
+                    oldList.splice(oldDropIndex, 1);
+                }
+                if (dropIndex < oldList.length) {
+                    return oldList.slice(0, dropIndex).concat(dropItem).concat(oldList.slice(dropIndex));
+                }
+                return oldList.concat(dropItem);
+            }),
+        []
+    );
 
     const lovList = useLovListMemo(lov, defaultLov);
+    useEffect(() => (props.dropTypes ? setLovListWithDrop(lovList) : undefined), [lovList, props.dropTypes]);
+
     const listSx = useMemo(
         () => ({
             bgcolor: "transparent",
@@ -709,8 +749,8 @@ const Selector = (props: SelectorProps) => {
                                     />
                                 </Box>
                             ) : null}
-                            <List sx={listSx} id={id} ref={dropRef}>
-                                {lovList.map((elt, idx) =>
+                            <List sx={listSx} id={id} ref={dropRef} onDragLeave={dragLeaveHandler}>
+                                {(lovListWithDrop || lovList).map((elt, idx) =>
                                     showItem(elt, searchValue) ? (
                                         multiple ? (
                                             <MultipleItem
@@ -726,6 +766,7 @@ const Selector = (props: SelectorProps) => {
                                                 handleDrop={handleDrop}
                                                 lovVarName={lovVarName}
                                                 targetId={id}
+                                                handleHover={handleHover}
                                             />
                                         ) : (
                                             <SingleItem
@@ -741,6 +782,7 @@ const Selector = (props: SelectorProps) => {
                                                 handleDrop={handleDrop}
                                                 lovVarName={lovVarName}
                                                 targetId={id}
+                                                handleHover={handleHover}
                                             />
                                         )
                                     ) : null

+ 11 - 4
frontend/taipy-gui/src/components/Taipy/lovUtils.tsx

@@ -161,6 +161,7 @@ export interface ItemProps {
     handleDrop?: (itemId: string, dropIndex: number, targetVarName: string, targetId?: string) => void;
     lovVarName?: string;
     targetId?: string;
+    handleHover?: (itemId?: string, dropIndex?: number) => void;
 }
 
 export const SingleItem = ({
@@ -177,9 +178,13 @@ export const SingleItem = ({
     handleDrop,
     lovVarName,
     targetId,
+    handleHover,
 }: ItemProps) => {
     const itemRef = useRef<HTMLDivElement>(null);
-    const getDragItem = useCallback(() => (dragType && !disabled ? { id: value, index: -1 } : null), [dragType, disabled, value]);
+    const getDragItem = useCallback(
+        () => (dragType && !disabled ? { id: value, index: -1 } : null),
+        [dragType, disabled, value]
+    );
 
     const [{ isDragging }, drag] = useDrag(
         () => ({
@@ -189,9 +194,8 @@ export const SingleItem = ({
                 isDragging: monitor.isDragging(),
             }),
             end: (item: DragItem, monitor) => {
-                const dropResult = monitor.getDropResult();
-                if (dropResult) {
-                    handleDrop?.(item.id, item.index, lovVarName || "", item.targetId);
+                if (monitor.getDropResult()) {
+                    handleDrop?.(item.targetId || "", item.index, lovVarName || "", item.targetId);
                 }
             },
         }),
@@ -203,7 +207,10 @@ export const SingleItem = ({
             hover: (item: DragItem) => {
                 item.index = index;
                 item.targetId = targetId;
+                handleHover?.(item.id, index);
             },
+            drop: () => handleHover?.(),
+
         }),
         [dropTypes, index, targetId]
     );

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff