[WIP] fix bug in drag and drop treeview

This commit is contained in:
Sina Blattmann 2023-03-16 16:14:06 +01:00
parent e3e03fda8b
commit 3a01a38046
5 changed files with 31 additions and 11 deletions

View File

@ -12,6 +12,8 @@ interface GroupContextProviderProps {
getError: boolean; getError: boolean;
tree: NodeModel<I_Folder | I_Installation>[]; tree: NodeModel<I_Folder | I_Installation>[];
setTree: (value: NodeModel<I_Folder | I_Installation>[]) => void; setTree: (value: NodeModel<I_Folder | I_Installation>[]) => void;
currentType: string;
setCurrentType: (value: string) => void;
} }
export const GroupContext = createContext<GroupContextProviderProps>({ export const GroupContext = createContext<GroupContextProviderProps>({
@ -23,6 +25,8 @@ export const GroupContext = createContext<GroupContextProviderProps>({
getError: false, getError: false,
tree: [], tree: [],
setTree: () => {}, setTree: () => {},
currentType: "",
setCurrentType: () => {},
}); });
const getTreeData = ( const getTreeData = (
@ -45,9 +49,9 @@ const GroupContextProvider = ({ children }: { children: ReactNode }) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [getError, setGetError] = useState(false); const [getError, setGetError] = useState(false);
const [tree, setTree] = useState<NodeModel<I_Folder | I_Installation>[]>([]); const [tree, setTree] = useState<NodeModel<I_Folder | I_Installation>[]>([]);
const [currentType, setCurrentType] = useState("");
const fetchData = useCallback(async () => { const fetchData = useCallback(async () => {
console.log("fetchData");
setLoading(true); setLoading(true);
return axiosConfig return axiosConfig
.get("/GetAllFoldersAndInstallations") .get("/GetAllFoldersAndInstallations")
@ -73,6 +77,8 @@ const GroupContextProvider = ({ children }: { children: ReactNode }) => {
getError, getError,
tree, tree,
setTree, setTree,
currentType,
setCurrentType,
}} }}
> >
{children} {children}

View File

@ -1,10 +1,9 @@
import { NodeModel } from "@minoru/react-dnd-treeview";
import { Button, CircularProgress, Grid } from "@mui/material"; import { Button, CircularProgress, Grid } from "@mui/material";
import { useFormik } from "formik"; import { useFormik } from "formik";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import axiosConfig from "../../config/axiosConfig"; import axiosConfig from "../../config/axiosConfig";
import { I_Folder, I_Installation } from "../../util/types"; import { I_Folder } from "../../util/types";
import { GroupContext } from "../Context/GroupContextProvider"; import { GroupContext } from "../Context/GroupContextProvider";
import InnovenergySnackbar from "../InnovenergySnackbar"; import InnovenergySnackbar from "../InnovenergySnackbar";
import InnovenergyTextfield from "../Layout/InnovenergyTextfield"; import InnovenergyTextfield from "../Layout/InnovenergyTextfield";

View File

@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
import routes from "../../routes.json"; import routes from "../../routes.json";
import useRouteMatch from "../../hooks/useRouteMatch"; import useRouteMatch from "../../hooks/useRouteMatch";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { GroupContext } from "../Context/GroupContextProvider";
const GroupTabs = () => { const GroupTabs = () => {
const routeMatch = useRouteMatch([ const routeMatch = useRouteMatch([
@ -16,6 +17,7 @@ const GroupTabs = () => {
const id = routeMatch?.params?.id; const id = routeMatch?.params?.id;
const intl = useIntl(); const intl = useIntl();
const { currentType } = React.useContext(GroupContext);
if (id) { if (id) {
return ( return (
@ -25,7 +27,7 @@ const GroupTabs = () => {
value={routeMatch?.pattern?.path} value={routeMatch?.pattern?.path}
aria-label="basic tabs example" aria-label="basic tabs example"
> >
{routeMatch?.pathname.includes("folder") ? ( {currentType === "Folder" ? (
<Tab <Tab
label={intl.formatMessage({ label={intl.formatMessage({
id: "folder", id: "folder",

View File

@ -1,7 +1,7 @@
import { useEffect, useState, useContext } from "react"; import { useEffect, useState, useContext, useRef } from "react";
import axiosConfig from "../../../config/axiosConfig"; import axiosConfig from "../../../config/axiosConfig";
import { I_Folder, I_Installation } from "../../../util/types"; import { I_Folder, I_Installation } from "../../../util/types";
import { Alert, CircularProgress, Grid } from "@mui/material"; import { Alert, Button, CircularProgress, Grid } from "@mui/material";
import { DndProvider } from "react-dnd"; import { DndProvider } from "react-dnd";
import { import {
MultiBackend, MultiBackend,
@ -22,6 +22,7 @@ const GroupTree = () => {
useContext(GroupContext); useContext(GroupContext);
const [putError, setPutError] = useState(false); const [putError, setPutError] = useState(false);
const [snackbarOpen, setSnackbarOpen] = useState(false); const [snackbarOpen, setSnackbarOpen] = useState(false);
const [openNodes, setOpenNodes] = useState<(string | number)[]>([]);
const ScrollingComponent = withScrolling("div"); const ScrollingComponent = withScrolling("div");
@ -66,7 +67,7 @@ const GroupTree = () => {
<ScrollingComponent className={styles.treeContainer}> <ScrollingComponent className={styles.treeContainer}>
<Tree<I_Installation | I_Folder> <Tree<I_Installation | I_Folder>
tree={tree} tree={tree}
rootId={0} rootId={-1}
dragPreviewRender={(monitorProps) => ( dragPreviewRender={(monitorProps) => (
<DragPreview monitorProps={monitorProps} /> <DragPreview monitorProps={monitorProps} />
)} )}
@ -93,6 +94,10 @@ const GroupTree = () => {
tree: NodeModel<I_Folder | I_Installation>[], tree: NodeModel<I_Folder | I_Installation>[],
options: DropOptions<I_Folder | I_Installation> options: DropOptions<I_Folder | I_Installation>
) => handleDrop(tree, options)} ) => handleDrop(tree, options)}
onChangeOpen={(nodes) => {
console.log(nodes);
setOpenNodes(nodes);
}}
/> />
</ScrollingComponent> </ScrollingComponent>
<InnovenergySnackbar <InnovenergySnackbar

View File

@ -1,4 +1,4 @@
import React from "react"; import React, { useContext, useEffect } from "react";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import ArrowRightIcon from "@mui/icons-material/ArrowRight"; import ArrowRightIcon from "@mui/icons-material/ArrowRight";
import { NodeModel } from "@minoru/react-dnd-treeview"; import { NodeModel } from "@minoru/react-dnd-treeview";
@ -9,6 +9,7 @@ import { I_Folder, I_Installation } from "../../../util/types";
import TypeIcon from "../TypeIcon"; import TypeIcon from "../TypeIcon";
import DragHandleIcon from "@mui/icons-material/DragHandle"; import DragHandleIcon from "@mui/icons-material/DragHandle";
import useRouteMatch from "../../../hooks/useRouteMatch"; import useRouteMatch from "../../../hooks/useRouteMatch";
import { GroupContext } from "../../Context/GroupContextProvider";
interface TreeNodeProps { interface TreeNodeProps {
node: NodeModel<I_Installation | I_Folder>; node: NodeModel<I_Installation | I_Folder>;
@ -23,23 +24,30 @@ const TreeNode = (props: TreeNodeProps) => {
const { node, isOpen, hasChild, onToggle, depth, handleRef } = props; const { node, isOpen, hasChild, onToggle, depth, handleRef } = props;
const indent = depth * 24; const indent = depth * 24;
const { setCurrentType } = useContext(GroupContext);
const routeMatch = useRouteMatch([ const routeMatch = useRouteMatch([
routes.groups + routes.installation + ":id", routes.groups + routes.installation + ":id",
routes.groups + routes.folder + ":id", routes.groups + routes.folder + ":id",
routes.groups + routes.users + ":id", routes.groups + routes.users + ":id",
]); ]);
const isSelected = routeMatch?.params.id === node.data?.id.toString();
const handleToggle = (e: React.MouseEvent) => { const handleToggle = (e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
onToggle(node.id); onToggle(node.id);
}; };
useEffect(() => {
if (node.data && isSelected) {
setCurrentType(node.data?.type);
}
}, [isSelected, node.data, setCurrentType]);
return ( return (
<div <div
className={`tree-node ${styles.root} ${ className={`tree-node ${styles.root} ${
routeMatch?.params.id === node.data?.id.toString() isSelected ? styles.selected : ""
? styles.selected
: ""
}`} }`}
style={{ paddingInlineStart: indent }} style={{ paddingInlineStart: indent }}
> >