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-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dnd-scrolling": "^1.3.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-intl": "^6.2.10",
|
||||
"react-router-dom": "^6.8.0",
|
||||
|
@ -6551,6 +6552,14 @@
|
|||
"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": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
|
@ -7435,6 +7444,17 @@
|
|||
"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": {
|
||||
"version": "2.0.0",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
|
@ -15490,6 +15515,23 @@
|
|||
"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": {
|
||||
"version": "16.0.1",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
|
@ -23894,6 +23941,14 @@
|
|||
"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": {
|
||||
"version": "2.0.0",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
|
||||
|
@ -29561,6 +29621,18 @@
|
|||
"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": {
|
||||
"version": "16.0.1",
|
||||
"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-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dnd-scrolling": "^1.3.3",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-intl": "^6.2.10",
|
||||
"react-router-dom": "^6.8.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import { Alert, Button, CircularProgress, Grid } from "@mui/material";
|
||||
import Container from "@mui/material/Container";
|
||||
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||
import axiosConfig, { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
||||
|
||||
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 [password, setPassword] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState();
|
||||
|
||||
const handleSubmit = (e: any) => {
|
||||
const verifyToken = async () => {
|
||||
axiosConfig.get("/GetAllInstallations");
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
setLoading(true);
|
||||
loginUser(username, password).then(({ data }) => {
|
||||
// TODO change this if they return err codes from backend
|
||||
if (typeof data === "string") {
|
||||
setToken(data);
|
||||
setLoading(false);
|
||||
verifyToken()
|
||||
.then(() => {
|
||||
setToken(data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
setError(data);
|
||||
setLoading(false);
|
||||
|
|
|
@ -8,10 +8,10 @@ import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
|||
|
||||
interface I_CustomerFormProps {
|
||||
values: I_Folder;
|
||||
id: string | undefined;
|
||||
id: string;
|
||||
}
|
||||
|
||||
const updateFolder = (data: any) => {
|
||||
const updateFolder = (data: I_Folder) => {
|
||||
return axiosConfig.put("/UpdateFolder", data);
|
||||
};
|
||||
const FolderForm = (props: I_CustomerFormProps) => {
|
||||
|
@ -26,9 +26,11 @@ const FolderForm = (props: I_CustomerFormProps) => {
|
|||
information: values.information,
|
||||
},
|
||||
onSubmit: (formikValues) => {
|
||||
const idAsNumber = parseInt(id, 10);
|
||||
updateFolder({
|
||||
...values,
|
||||
...formikValues,
|
||||
id,
|
||||
id: idAsNumber,
|
||||
}).then((res) => {
|
||||
setSnackbarOpen(true);
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@ import InstallationDetail from "../Installations/Installation";
|
|||
import NavigationButtons from "../Layout/NavigationButtons";
|
||||
import Folder from "./Folder";
|
||||
import GroupTabs from "./GroupTabs";
|
||||
import GroupTree from "./GroupTree";
|
||||
import GroupTree from "./Tree/GroupTree";
|
||||
|
||||
const Groups = () => {
|
||||
return (
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { DragLayerMonitorProps } from "@minoru/react-dnd-treeview";
|
||||
import { I_Folder, I_Installation } from "../../util/types";
|
||||
import TypeIcon from "./TypeIcon";
|
||||
import { I_Installation, I_Folder } from "../../../util/types";
|
||||
import styles from "./DragPreview.module.scss";
|
||||
import TypeIcon from "./TypeIcon";
|
||||
|
||||
interface DragPreviewProps {
|
||||
monitorProps: DragLayerMonitorProps<I_Installation | I_Folder>;
|
|
@ -18,3 +18,8 @@
|
|||
.dropTarget {
|
||||
background-color: #e8f0fe;
|
||||
}
|
||||
|
||||
.treeContainer {
|
||||
height: 500px;
|
||||
overflow: auto;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_Folder, I_Installation } from "../../util/types";
|
||||
import axiosConfig from "../../../config/axiosConfig";
|
||||
import { I_Folder, I_Installation } from "../../../util/types";
|
||||
import { CircularProgress, Grid } from "@mui/material";
|
||||
import { DndProvider } from "react-dnd";
|
||||
import {
|
||||
|
@ -12,6 +12,7 @@ import {
|
|||
} from "@minoru/react-dnd-treeview";
|
||||
import TreeNode from "./TreeNode";
|
||||
import styles from "./GroupTree.module.scss";
|
||||
import withScrolling from "react-dnd-scrolling";
|
||||
import DragPreview from "./DragPreview";
|
||||
|
||||
const getTreeData = (
|
||||
|
@ -32,6 +33,7 @@ const getTreeData = (
|
|||
const GroupTree = () => {
|
||||
const [data, setData] = useState<(I_Folder | I_Installation)[]>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const ScrollingComponent = withScrolling("div");
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
|
@ -50,10 +52,15 @@ const GroupTree = () => {
|
|||
{ dropTargetId, dragSource }: DropOptions<I_Folder | I_Installation>
|
||||
) => {
|
||||
axiosConfig
|
||||
.put("/UpdateFolder", {
|
||||
...dragSource?.data,
|
||||
parentId: dropTargetId,
|
||||
})
|
||||
.put(
|
||||
dragSource?.data?.type === "Folder"
|
||||
? "/UpdateFolder"
|
||||
: "/UpdateInstallation",
|
||||
{
|
||||
...dragSource?.data,
|
||||
parentId: dropTargetId,
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
getData();
|
||||
});
|
||||
|
@ -68,35 +75,38 @@ const GroupTree = () => {
|
|||
} else if (data && data?.length > 1) {
|
||||
return (
|
||||
<DndProvider backend={MultiBackend} options={getBackendOptions()}>
|
||||
<Tree<I_Installation | I_Folder>
|
||||
tree={getTreeData(data)}
|
||||
rootId={0}
|
||||
dragPreviewRender={(monitorProps) => (
|
||||
<DragPreview monitorProps={monitorProps} />
|
||||
)}
|
||||
classes={{
|
||||
container: styles.tree,
|
||||
root: styles.treeRoot,
|
||||
draggingSource: styles.draggingSource,
|
||||
dropTarget: styles.dropTarget,
|
||||
}}
|
||||
render={(
|
||||
node: NodeModel<I_Installation | I_Folder>,
|
||||
{ depth, isOpen, onToggle, hasChild }
|
||||
) => (
|
||||
<TreeNode
|
||||
node={node}
|
||||
depth={depth}
|
||||
isOpen={isOpen}
|
||||
onToggle={onToggle}
|
||||
hasChild={hasChild}
|
||||
/>
|
||||
)}
|
||||
onDrop={(
|
||||
tree: NodeModel<I_Folder | I_Installation>[],
|
||||
options: DropOptions<I_Folder | I_Installation>
|
||||
) => handleDrop(tree, options)}
|
||||
/>
|
||||
<ScrollingComponent className={styles.treeContainer}>
|
||||
<Tree<I_Installation | I_Folder>
|
||||
tree={getTreeData(data)}
|
||||
rootId={0}
|
||||
dragPreviewRender={(monitorProps) => (
|
||||
<DragPreview monitorProps={monitorProps} />
|
||||
)}
|
||||
classes={{
|
||||
container: styles.tree,
|
||||
root: styles.treeRoot,
|
||||
draggingSource: styles.draggingSource,
|
||||
dropTarget: styles.dropTarget,
|
||||
}}
|
||||
render={(
|
||||
node: NodeModel<I_Installation | I_Folder>,
|
||||
{ depth, isOpen, onToggle, hasChild, handleRef }
|
||||
) => (
|
||||
<TreeNode
|
||||
node={node}
|
||||
depth={depth}
|
||||
isOpen={isOpen}
|
||||
onToggle={onToggle}
|
||||
hasChild={hasChild}
|
||||
handleRef={handleRef}
|
||||
/>
|
||||
)}
|
||||
onDrop={(
|
||||
tree: NodeModel<I_Folder | I_Installation>[],
|
||||
options: DropOptions<I_Folder | I_Installation>
|
||||
) => handleDrop(tree, options)}
|
||||
/>
|
||||
</ScrollingComponent>
|
||||
</DndProvider>
|
||||
);
|
||||
}
|
|
@ -25,3 +25,12 @@
|
|||
.labelGridItem {
|
||||
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 styles from "./TreeNode.module.scss";
|
||||
import { Link } from "react-router-dom";
|
||||
import routes from "../../routes.json";
|
||||
import { I_Folder, I_Installation } from "../../util/types";
|
||||
import routes from "../../../routes.json";
|
||||
import { I_Folder, I_Installation } from "../../../util/types";
|
||||
import TypeIcon from "./TypeIcon";
|
||||
import DragHandleIcon from "@mui/icons-material/DragHandle";
|
||||
|
||||
type Props = {
|
||||
node: NodeModel<I_Installation | I_Folder>;
|
||||
|
@ -14,10 +15,11 @@ type Props = {
|
|||
isOpen: boolean;
|
||||
onToggle: (id: NodeModel["id"]) => void;
|
||||
hasChild: boolean;
|
||||
handleRef: React.RefObject<any>;
|
||||
};
|
||||
|
||||
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 handleToggle = (e: React.MouseEvent) => {
|
||||
|
@ -55,6 +57,9 @@ const TreeNode: React.FC<Props> = (props) => {
|
|||
<Typography variant="body2">{node.text}</Typography>
|
||||
</div>
|
||||
</Link>
|
||||
<div className={`${styles.handle} drag-handle`} ref={handleRef}>
|
||||
<DragHandleIcon />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue