From 5d801ab36ba4a01d9ac65173f975e9bc55c6ce02 Mon Sep 17 00:00:00 2001 From: Sina Blattmann Date: Thu, 23 Mar 2023 08:28:56 +0100 Subject: [PATCH] [WIP] add Users tab to Groups --- .../Context/GroupContextProvider.tsx | 1 - .../src/components/Groups/FolderForm.tsx | 15 ++- .../Frontend/src/components/Groups/Groups.tsx | 3 +- .../src/components/Groups/Tree/GroupTree.tsx | 32 +++++- .../src/components/Groups/Tree/MoveTree.tsx | 14 +-- .../src/components/Groups/Users/Users.tsx | 99 +++++++++++++++++++ typescript/Frontend/src/util/user.util.tsx | 12 +++ 7 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 typescript/Frontend/src/components/Groups/Users/Users.tsx create mode 100644 typescript/Frontend/src/util/user.util.tsx diff --git a/typescript/Frontend/src/components/Context/GroupContextProvider.tsx b/typescript/Frontend/src/components/Context/GroupContextProvider.tsx index ce1102a87..8032ebf48 100644 --- a/typescript/Frontend/src/components/Context/GroupContextProvider.tsx +++ b/typescript/Frontend/src/components/Context/GroupContextProvider.tsx @@ -50,7 +50,6 @@ const GroupContextProvider = ({ children }: { children: ReactNode }) => { value={{ currentType, setCurrentType, - data, setData, fetchData, diff --git a/typescript/Frontend/src/components/Groups/FolderForm.tsx b/typescript/Frontend/src/components/Groups/FolderForm.tsx index 67acfc398..4c2dc231c 100644 --- a/typescript/Frontend/src/components/Groups/FolderForm.tsx +++ b/typescript/Frontend/src/components/Groups/FolderForm.tsx @@ -1,9 +1,10 @@ import { Button, CircularProgress, Grid, InputLabel } from "@mui/material"; import { useFormik } from "formik"; -import { useState } from "react"; +import { useContext, useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; import axiosConfig from "../../config/axiosConfig"; import { I_Folder } from "../../util/types"; +import { GroupContext } from "../Context/GroupContextProvider"; import InnovenergySnackbar from "../InnovenergySnackbar"; import InnovenergyTextfield from "../Layout/InnovenergyTextfield"; import MoveTree from "./Tree/MoveTree"; @@ -20,11 +21,14 @@ const updateFolder = (data: I_Folder) => { const FolderForm = (props: I_CustomerFormProps) => { const { values, id } = props; const intl = useIntl(); + const { fetchData } = useContext(GroupContext); const [snackbarOpen, setSnackbarOpen] = useState(false); const [error, setError] = useState(); const [loading, setLoading] = useState(false); - const [selectedParentId, setSelectedParentId] = useState(); + const [selectedParentId, setSelectedParentId] = useState( + values.parentId + ); const formik = useFormik({ initialValues: { @@ -41,6 +45,8 @@ const FolderForm = (props: I_CustomerFormProps) => { id: idAsNumber, }) .then((res) => { + // TODO figure out why this isnt refreshing tree + fetchData(); setSnackbarOpen(true); setLoading(false); }) @@ -81,7 +87,10 @@ const FolderForm = (props: I_CustomerFormProps) => { - + diff --git a/typescript/Frontend/src/components/Groups/Groups.tsx b/typescript/Frontend/src/components/Groups/Groups.tsx index c405be667..e1a80f23a 100644 --- a/typescript/Frontend/src/components/Groups/Groups.tsx +++ b/typescript/Frontend/src/components/Groups/Groups.tsx @@ -8,6 +8,7 @@ import GroupTabs from "./GroupTabs"; import GroupContextProvider from "../Context/GroupContextProvider"; import GroupTree from "./Tree/GroupTree"; import NavigationButtons from "../Layout/NavigationButtons"; +import Users from "./Users/Users"; const Groups = () => { return ( @@ -22,7 +23,7 @@ const Groups = () => { } index /> - Users} /> + } /> } diff --git a/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx b/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx index 125d7c9cd..2731dbd8c 100644 --- a/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx +++ b/typescript/Frontend/src/components/Groups/Tree/GroupTree.tsx @@ -1,21 +1,32 @@ import TreeView from "@mui/lab/TreeView"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ChevronRightIcon from "@mui/icons-material/ChevronRight"; -import { ReactNode, useContext, useEffect } from "react"; +import { ReactNode, useContext, useEffect, useState } from "react"; import { TreeItem } from "@mui/lab"; import { I_Folder, I_Installation } from "../../../util/types"; import { Link } from "react-router-dom"; import routes from "../../../routes.json"; import { GroupContext } from "../../Context/GroupContextProvider"; import { instanceOfFolder } from "../../../util/group.util"; +import { Grid, CircularProgress } from "@mui/material"; const GroupTree = () => { - const { setCurrentType, fetchData, data } = useContext(GroupContext); + const { setCurrentType, fetchData, data, loading } = useContext(GroupContext); + const [openNodes, setOpenNodes] = useState([]); + const [selected, setSelected] = useState(""); useEffect(() => { fetchData(); }, [fetchData]); + /* useEffect(() => { + if (id) { + setSelected( + currentType === "Folder" ? "Folder" + id : "Installation" + id + ); + } + }, [id, currentType]); */ + const getNodes = (element: I_Folder | I_Installation): null | ReactNode => { if (instanceOfFolder(element)) { return element.children ? renderTree(element.children) : null; @@ -40,8 +51,8 @@ const GroupTree = () => { draggable={false} > setCurrentType(element.type)} > @@ -51,6 +62,13 @@ const GroupTree = () => { ); }); }; + if (loading) { + return ( + + + + ); + } if (data) { return ( { defaultCollapseIcon={} defaultExpandIcon={} sx={{ height: 300, flexGrow: 1, maxWidth: 400 }} + expanded={openNodes} + onNodeToggle={(e, ids) => { + setOpenNodes(ids); + }} + onNodeSelect={(e: any, nodeId: string) => setSelected(nodeId)} + selected={selected} > {renderTree(data)} diff --git a/typescript/Frontend/src/components/Groups/Tree/MoveTree.tsx b/typescript/Frontend/src/components/Groups/Tree/MoveTree.tsx index 80f2b1b2a..5bf71feb4 100644 --- a/typescript/Frontend/src/components/Groups/Tree/MoveTree.tsx +++ b/typescript/Frontend/src/components/Groups/Tree/MoveTree.tsx @@ -7,11 +7,12 @@ import { I_Folder, I_Installation } from "../../../util/types"; import { GroupContext } from "../../Context/GroupContextProvider"; import { instanceOfFolder } from "../../../util/group.util"; -interface GroupTreeProps { +interface MoveTreeProps { setSelectedParentId: (value: number) => void; + parentId: number; } -const GroupTree = (props: GroupTreeProps) => { +const MoveTree = (props: MoveTreeProps) => { const { data } = useContext(GroupContext); const getNodes = (element: I_Folder | I_Installation): null | ReactNode => { @@ -50,9 +51,10 @@ const GroupTree = (props: GroupTreeProps) => { overflow: "auto", overflowX: "hidden", }} - onNodeSelect={(e: any, id: string) => - props.setSelectedParentId(parseInt(id)) - } + onNodeSelect={(e: any, id: string) => { + props.setSelectedParentId(parseInt(id)); + }} + selected={props.parentId.toString()} > {renderTree(data)} @@ -61,4 +63,4 @@ const GroupTree = (props: GroupTreeProps) => { return null; }; -export default GroupTree; +export default MoveTree; diff --git a/typescript/Frontend/src/components/Groups/Users/Users.tsx b/typescript/Frontend/src/components/Groups/Users/Users.tsx new file mode 100644 index 000000000..5ec9d36a8 --- /dev/null +++ b/typescript/Frontend/src/components/Groups/Users/Users.tsx @@ -0,0 +1,99 @@ +import List from "@mui/material/List"; +import ListItemText from "@mui/material/ListItemText"; +import { CircularProgress, Divider, Grid, ListItemIcon } from "@mui/material"; +import { Fragment, useContext, useEffect, useState } from "react"; +import axiosConfig from "../../../config/axiosConfig"; +import { useParams } from "react-router-dom"; +import ListItem from "@mui/material/ListItem"; +import GroupRemoveIcon from "@mui/icons-material/GroupRemove"; +import { User } from "../../../util/user.util"; +import { GroupContext } from "../../Context/GroupContextProvider"; +import { Link } from "react-router-dom"; +import routes from "../../../routes.json"; + +const InstallationList = () => { + const [data, setData] = useState(); + const [loading, setLoading] = useState(false); + + const { id } = useParams(); + const { currentType } = useContext(GroupContext); + + useEffect(() => { + setLoading(true); + axiosConfig + .get( + currentType === "Folder" + ? "/GetUsersWithAccessToFolder" + : "/GetUsersWithAccessToInstallation", + { params: { id } } + ) + .then((res) => { + // TODO temp solution + const mappedData = res.data + .filter((element: any) => element.user) + .map((element: any) => element.user); + console.log(mappedData); + setData(mappedData); + setLoading(false); + }); + }, [currentType, id]); + + const filterDuplicateUsers = (data: any[]) => { + return data.reduce((prev: User[], curr: User) => { + const foundUser = prev.find((el) => el.id === curr.id); + if (foundUser) { + const prevIds = foundUser.folderIds ? foundUser.folderIds : []; + foundUser.folderIds = [...prevIds, curr.parentId]; + return prev; + } + curr.folderIds = [curr.parentId]; + prev.push(curr); + return prev; + }, []); + }; + + if (loading) { + return ( + + + + ); + } + if (data) { + return ( + + {filterDuplicateUsers(data).map((user: User) => { + return ( + + + + Inherited access from{" "} + + this folder + + + } + /> + + + + ); + })} + + ); + } + return null; +}; + +export default InstallationList; diff --git a/typescript/Frontend/src/util/user.util.tsx b/typescript/Frontend/src/util/user.util.tsx new file mode 100644 index 000000000..9d37fc0a7 --- /dev/null +++ b/typescript/Frontend/src/util/user.util.tsx @@ -0,0 +1,12 @@ +export interface User { + email: string; + hasWriteAccess: boolean; + id: number; + information: string; + language: string; + name: string; + parentId: number; + password: number; + type: string; + folderIds?: number[]; +}