Finish dnd treeview, add mobile support for scrolling in dnd treeview
This commit is contained in:
parent
53346740ab
commit
8899f55bd0
|
@ -30,6 +30,7 @@
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
|
"react-dnd-scrolling": "^1.3.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-intl": "^6.2.10",
|
"react-intl": "^6.2.10",
|
||||||
"react-router-dom": "^6.8.0",
|
"react-router-dom": "^6.8.0",
|
||||||
|
@ -6551,6 +6552,14 @@
|
||||||
"wrap-ansi": "^7.0.0"
|
"wrap-ansi": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/clone": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/clsx": {
|
"node_modules/clsx": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||||
|
@ -7435,6 +7444,17 @@
|
||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/defaults": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
|
||||||
|
"dependencies": {
|
||||||
|
"clone": "^1.0.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/define-lazy-prop": {
|
"node_modules/define-lazy-prop": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||||
|
@ -12913,6 +12933,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||||
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
|
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.throttle": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
|
||||||
|
},
|
||||||
"node_modules/lodash.uniq": {
|
"node_modules/lodash.uniq": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||||
|
@ -15490,6 +15515,23 @@
|
||||||
"dnd-core": "^16.0.1"
|
"dnd-core": "^16.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-dnd-scrolling": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dnd-scrolling/-/react-dnd-scrolling-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-IEUbvK7fPWzOpPXaMvYQJR+ZGDPUtOwNpAJeEqUdTqQb0quwaytr/LfiAFGbWI87D55InsGaTUDyWkfXURyLNA==",
|
||||||
|
"dependencies": {
|
||||||
|
"defaults": "^1.0.4",
|
||||||
|
"hoist-non-react-statics": "3.x",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"prop-types": "15.x",
|
||||||
|
"raf": "^3.4.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "16.x || 17.x || 18.x",
|
||||||
|
"react-dnd": "10.x || 11.x || 14.x || 15.x || 16.x",
|
||||||
|
"react-dom": "16.x || 17.x || 18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-dnd-touch-backend": {
|
"node_modules/react-dnd-touch-backend": {
|
||||||
"version": "16.0.1",
|
"version": "16.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-16.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-16.0.1.tgz",
|
||||||
|
@ -23257,6 +23299,11 @@
|
||||||
"wrap-ansi": "^7.0.0"
|
"wrap-ansi": "^7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"clone": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="
|
||||||
|
},
|
||||||
"clsx": {
|
"clsx": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||||
|
@ -23894,6 +23941,14 @@
|
||||||
"execa": "^5.0.0"
|
"execa": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"defaults": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
|
||||||
|
"requires": {
|
||||||
|
"clone": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"define-lazy-prop": {
|
"define-lazy-prop": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
|
||||||
|
@ -27886,6 +27941,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||||
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
|
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="
|
||||||
},
|
},
|
||||||
|
"lodash.throttle": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
|
||||||
|
},
|
||||||
"lodash.uniq": {
|
"lodash.uniq": {
|
||||||
"version": "4.5.0",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||||
|
@ -29561,6 +29621,18 @@
|
||||||
"dnd-core": "^16.0.1"
|
"dnd-core": "^16.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-dnd-scrolling": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dnd-scrolling/-/react-dnd-scrolling-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-IEUbvK7fPWzOpPXaMvYQJR+ZGDPUtOwNpAJeEqUdTqQb0quwaytr/LfiAFGbWI87D55InsGaTUDyWkfXURyLNA==",
|
||||||
|
"requires": {
|
||||||
|
"defaults": "^1.0.4",
|
||||||
|
"hoist-non-react-statics": "3.x",
|
||||||
|
"lodash.throttle": "^4.1.1",
|
||||||
|
"prop-types": "15.x",
|
||||||
|
"raf": "^3.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-dnd-touch-backend": {
|
"react-dnd-touch-backend": {
|
||||||
"version": "16.0.1",
|
"version": "16.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-16.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dnd-touch-backend/-/react-dnd-touch-backend-16.0.1.tgz",
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
|
"react-dnd-scrolling": "^1.3.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-intl": "^6.2.10",
|
"react-intl": "^6.2.10",
|
||||||
"react-router-dom": "^6.8.0",
|
"react-router-dom": "^6.8.0",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Alert, Button, CircularProgress, Grid } from "@mui/material";
|
import { Alert, Button, CircularProgress, Grid } from "@mui/material";
|
||||||
import Container from "@mui/material/Container";
|
import Container from "@mui/material/Container";
|
||||||
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
import axiosConfig, { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||||
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
||||||
|
|
||||||
const loginUser = async (username: string, password: string) => {
|
const loginUser = async (username: string, password: string) => {
|
||||||
|
@ -11,18 +11,30 @@ const loginUser = async (username: string, password: string) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const Login = ({ setToken }: { setToken: any }) => {
|
const Login = ({ setToken }: { setToken: (value: string) => void }) => {
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState();
|
const [error, setError] = useState();
|
||||||
|
|
||||||
const handleSubmit = (e: any) => {
|
const verifyToken = async () => {
|
||||||
|
axiosConfig.get("/GetAllInstallations");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
loginUser(username, password).then(({ data }) => {
|
loginUser(username, password).then(({ data }) => {
|
||||||
|
// TODO change this if they return err codes from backend
|
||||||
if (typeof data === "string") {
|
if (typeof data === "string") {
|
||||||
setToken(data);
|
verifyToken()
|
||||||
setLoading(false);
|
.then(() => {
|
||||||
|
setToken(data);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
setError(err);
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
setError(data);
|
setError(data);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
|
@ -8,10 +8,10 @@ import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
||||||
|
|
||||||
interface I_CustomerFormProps {
|
interface I_CustomerFormProps {
|
||||||
values: I_Folder;
|
values: I_Folder;
|
||||||
id: string | undefined;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateFolder = (data: any) => {
|
const updateFolder = (data: I_Folder) => {
|
||||||
return axiosConfig.put("/UpdateFolder", data);
|
return axiosConfig.put("/UpdateFolder", data);
|
||||||
};
|
};
|
||||||
const FolderForm = (props: I_CustomerFormProps) => {
|
const FolderForm = (props: I_CustomerFormProps) => {
|
||||||
|
@ -26,9 +26,11 @@ const FolderForm = (props: I_CustomerFormProps) => {
|
||||||
information: values.information,
|
information: values.information,
|
||||||
},
|
},
|
||||||
onSubmit: (formikValues) => {
|
onSubmit: (formikValues) => {
|
||||||
|
const idAsNumber = parseInt(id, 10);
|
||||||
updateFolder({
|
updateFolder({
|
||||||
|
...values,
|
||||||
...formikValues,
|
...formikValues,
|
||||||
id,
|
id: idAsNumber,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
setSnackbarOpen(true);
|
setSnackbarOpen(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@ import InstallationDetail from "../Installations/Installation";
|
||||||
import NavigationButtons from "../Layout/NavigationButtons";
|
import NavigationButtons from "../Layout/NavigationButtons";
|
||||||
import Folder from "./Folder";
|
import Folder from "./Folder";
|
||||||
import GroupTabs from "./GroupTabs";
|
import GroupTabs from "./GroupTabs";
|
||||||
import GroupTree from "./GroupTree";
|
import GroupTree from "./Tree/GroupTree";
|
||||||
|
|
||||||
const Groups = () => {
|
const Groups = () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { DragLayerMonitorProps } from "@minoru/react-dnd-treeview";
|
import { DragLayerMonitorProps } from "@minoru/react-dnd-treeview";
|
||||||
import { I_Folder, I_Installation } from "../../util/types";
|
import { I_Installation, I_Folder } from "../../../util/types";
|
||||||
import TypeIcon from "./TypeIcon";
|
|
||||||
import styles from "./DragPreview.module.scss";
|
import styles from "./DragPreview.module.scss";
|
||||||
|
import TypeIcon from "./TypeIcon";
|
||||||
|
|
||||||
interface DragPreviewProps {
|
interface DragPreviewProps {
|
||||||
monitorProps: DragLayerMonitorProps<I_Installation | I_Folder>;
|
monitorProps: DragLayerMonitorProps<I_Installation | I_Folder>;
|
|
@ -18,3 +18,8 @@
|
||||||
.dropTarget {
|
.dropTarget {
|
||||||
background-color: #e8f0fe;
|
background-color: #e8f0fe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.treeContainer {
|
||||||
|
height: 500px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } 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 { CircularProgress, Grid } from "@mui/material";
|
import { CircularProgress, Grid } from "@mui/material";
|
||||||
import { DndProvider } from "react-dnd";
|
import { DndProvider } from "react-dnd";
|
||||||
import {
|
import {
|
||||||
|
@ -12,6 +12,7 @@ import {
|
||||||
} from "@minoru/react-dnd-treeview";
|
} from "@minoru/react-dnd-treeview";
|
||||||
import TreeNode from "./TreeNode";
|
import TreeNode from "./TreeNode";
|
||||||
import styles from "./GroupTree.module.scss";
|
import styles from "./GroupTree.module.scss";
|
||||||
|
import withScrolling from "react-dnd-scrolling";
|
||||||
import DragPreview from "./DragPreview";
|
import DragPreview from "./DragPreview";
|
||||||
|
|
||||||
const getTreeData = (
|
const getTreeData = (
|
||||||
|
@ -32,6 +33,7 @@ const getTreeData = (
|
||||||
const GroupTree = () => {
|
const GroupTree = () => {
|
||||||
const [data, setData] = useState<(I_Folder | I_Installation)[]>();
|
const [data, setData] = useState<(I_Folder | I_Installation)[]>();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const ScrollingComponent = withScrolling("div");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getData();
|
getData();
|
||||||
|
@ -50,10 +52,15 @@ const GroupTree = () => {
|
||||||
{ dropTargetId, dragSource }: DropOptions<I_Folder | I_Installation>
|
{ dropTargetId, dragSource }: DropOptions<I_Folder | I_Installation>
|
||||||
) => {
|
) => {
|
||||||
axiosConfig
|
axiosConfig
|
||||||
.put("/UpdateFolder", {
|
.put(
|
||||||
...dragSource?.data,
|
dragSource?.data?.type === "Folder"
|
||||||
parentId: dropTargetId,
|
? "/UpdateFolder"
|
||||||
})
|
: "/UpdateInstallation",
|
||||||
|
{
|
||||||
|
...dragSource?.data,
|
||||||
|
parentId: dropTargetId,
|
||||||
|
}
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
getData();
|
getData();
|
||||||
});
|
});
|
||||||
|
@ -68,35 +75,38 @@ const GroupTree = () => {
|
||||||
} else if (data && data?.length > 1) {
|
} else if (data && data?.length > 1) {
|
||||||
return (
|
return (
|
||||||
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
||||||
<Tree<I_Installation | I_Folder>
|
<ScrollingComponent className={styles.treeContainer}>
|
||||||
tree={getTreeData(data)}
|
<Tree<I_Installation | I_Folder>
|
||||||
rootId={0}
|
tree={getTreeData(data)}
|
||||||
dragPreviewRender={(monitorProps) => (
|
rootId={0}
|
||||||
<DragPreview monitorProps={monitorProps} />
|
dragPreviewRender={(monitorProps) => (
|
||||||
)}
|
<DragPreview monitorProps={monitorProps} />
|
||||||
classes={{
|
)}
|
||||||
container: styles.tree,
|
classes={{
|
||||||
root: styles.treeRoot,
|
container: styles.tree,
|
||||||
draggingSource: styles.draggingSource,
|
root: styles.treeRoot,
|
||||||
dropTarget: styles.dropTarget,
|
draggingSource: styles.draggingSource,
|
||||||
}}
|
dropTarget: styles.dropTarget,
|
||||||
render={(
|
}}
|
||||||
node: NodeModel<I_Installation | I_Folder>,
|
render={(
|
||||||
{ depth, isOpen, onToggle, hasChild }
|
node: NodeModel<I_Installation | I_Folder>,
|
||||||
) => (
|
{ depth, isOpen, onToggle, hasChild, handleRef }
|
||||||
<TreeNode
|
) => (
|
||||||
node={node}
|
<TreeNode
|
||||||
depth={depth}
|
node={node}
|
||||||
isOpen={isOpen}
|
depth={depth}
|
||||||
onToggle={onToggle}
|
isOpen={isOpen}
|
||||||
hasChild={hasChild}
|
onToggle={onToggle}
|
||||||
/>
|
hasChild={hasChild}
|
||||||
)}
|
handleRef={handleRef}
|
||||||
onDrop={(
|
/>
|
||||||
tree: NodeModel<I_Folder | I_Installation>[],
|
)}
|
||||||
options: DropOptions<I_Folder | I_Installation>
|
onDrop={(
|
||||||
) => handleDrop(tree, options)}
|
tree: NodeModel<I_Folder | I_Installation>[],
|
||||||
/>
|
options: DropOptions<I_Folder | I_Installation>
|
||||||
|
) => handleDrop(tree, options)}
|
||||||
|
/>
|
||||||
|
</ScrollingComponent>
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -25,3 +25,12 @@
|
||||||
.labelGridItem {
|
.labelGridItem {
|
||||||
padding-inline-start: 8px;
|
padding-inline-start: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.handle {
|
||||||
|
cursor: grab;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.handle > svg {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
|
@ -4,9 +4,10 @@ import ArrowRightIcon from "@mui/icons-material/ArrowRight";
|
||||||
import { NodeModel } from "@minoru/react-dnd-treeview";
|
import { NodeModel } from "@minoru/react-dnd-treeview";
|
||||||
import styles from "./TreeNode.module.scss";
|
import styles from "./TreeNode.module.scss";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import routes from "../../routes.json";
|
import routes from "../../../routes.json";
|
||||||
import { I_Folder, I_Installation } from "../../util/types";
|
import { I_Folder, I_Installation } from "../../../util/types";
|
||||||
import TypeIcon from "./TypeIcon";
|
import TypeIcon from "./TypeIcon";
|
||||||
|
import DragHandleIcon from "@mui/icons-material/DragHandle";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
node: NodeModel<I_Installation | I_Folder>;
|
node: NodeModel<I_Installation | I_Folder>;
|
||||||
|
@ -14,10 +15,11 @@ type Props = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onToggle: (id: NodeModel["id"]) => void;
|
onToggle: (id: NodeModel["id"]) => void;
|
||||||
hasChild: boolean;
|
hasChild: boolean;
|
||||||
|
handleRef: React.RefObject<any>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TreeNode: React.FC<Props> = (props) => {
|
const TreeNode: React.FC<Props> = (props) => {
|
||||||
const { node, isOpen, hasChild, onToggle, depth } = props;
|
const { node, isOpen, hasChild, onToggle, depth, handleRef } = props;
|
||||||
const indent = depth * 24;
|
const indent = depth * 24;
|
||||||
|
|
||||||
const handleToggle = (e: React.MouseEvent) => {
|
const handleToggle = (e: React.MouseEvent) => {
|
||||||
|
@ -55,6 +57,9 @@ const TreeNode: React.FC<Props> = (props) => {
|
||||||
<Typography variant="body2">{node.text}</Typography>
|
<Typography variant="body2">{node.text}</Typography>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
<div className={`${styles.handle} drag-handle`} ref={handleRef}>
|
||||||
|
<DragHandleIcon />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
Loading…
Reference in New Issue