From 1d6e6f057200f9805515e416872ada8aa242214b Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 13:46:08 -0500 Subject: [PATCH 01/11] hook delete group member with redux --- frontend/src/actions/group.js | 18 +++++ .../src/components/groups/MembersTable.tsx | 74 +++++++++++-------- .../groups/MembersTableUserEntry.tsx | 27 ++++++- frontend/src/reducers/group.ts | 6 +- 4 files changed, 90 insertions(+), 35 deletions(-) diff --git a/frontend/src/actions/group.js b/frontend/src/actions/group.js index 5af5e50cf..651b2f6e0 100644 --- a/frontend/src/actions/group.js +++ b/frontend/src/actions/group.js @@ -35,3 +35,21 @@ export function fetchGroupAbout(id){ }); }; } + + +export const DELETE_GROUP_MEMBER = "DELETE_GROUP_MEMBER"; +export function deleteGroupMember(groupId, username){ + return (dispatch) => { + return V2.GroupsService.removeMemberApiV2GroupsGroupIdRemoveUsernamePost(groupId, username) + .then(json => { + dispatch({ + type: DELETE_GROUP_MEMBER, + member: json, + receivedAt: Date.now(), + }); + }) + .catch(reason => { + dispatch(handleErrors(reason, deleteGroupMember(groupId, username))); + }); + }; +} diff --git a/frontend/src/components/groups/MembersTable.tsx b/frontend/src/components/groups/MembersTable.tsx index 045b8e73c..a8beb5a75 100644 --- a/frontend/src/components/groups/MembersTable.tsx +++ b/frontend/src/components/groups/MembersTable.tsx @@ -6,13 +6,14 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Paper from '@mui/material/Paper'; -import {useSelector} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import {RootState} from "../../types/data"; -import {useNavigate} from "react-router-dom"; -import {Button} from "@mui/material"; -import FolderIcon from '@mui/icons-material/Folder'; import {theme} from "../../theme"; import {MembersTableUserEntry} from "./MembersTableUserEntry"; +import {ActionModal} from "../dialog/ActionModal"; +import {useState} from "react"; +import {datasetDeleted} from "../../actions/dataset"; +import {deleteGroupMember} from "../../actions/group"; type MembersTableProps = { groupId: string | undefined, @@ -24,38 +25,49 @@ const iconStyle = { } export default function MembersTable(props: MembersTableProps) { + const dispatch = useDispatch(); + // mapStateToProps const about = useSelector((state: RootState) => state.group.about); // use history hook to redirect/navigate between routes - const history = useNavigate(); + const [deleteDatasetConfirmOpen, setDeleteDatasetConfirmOpen] = useState(false); + const groupMemberDeleted = (groupId: string, username: string) => dispatch(deleteGroupMember(groupId, username)) return ( - - - - - Name - Email - Role - - - - - { - about !== undefined && about.users !== undefined ? - (about.users.map((member) => ( - - ))) - : - <> - } - -
-
+ <> + { + setDeleteDatasetConfirmOpen(false); + }}/> + + + + + Name + Email + Role + + + + + { + about !== undefined && about.users !== undefined ? + (about.users.map((member) => ( + + ))) + : + <> + } + +
+
+ ); } diff --git a/frontend/src/components/groups/MembersTableUserEntry.tsx b/frontend/src/components/groups/MembersTableUserEntry.tsx index 075ccd289..1a49f3e65 100644 --- a/frontend/src/components/groups/MembersTableUserEntry.tsx +++ b/frontend/src/components/groups/MembersTableUserEntry.tsx @@ -1,11 +1,16 @@ -import React from "react"; +import React, {useState} from "react"; import TableRow from "@mui/material/TableRow"; import TableCell from "@mui/material/TableCell"; import PersonIcon from "@mui/icons-material/Person"; -import {Button} from "@mui/material"; +import {Button, IconButton} from "@mui/material"; import {Member} from "../../openapi/v2"; import MemberMenu from "./MemberMenu"; +import {SearchOutlined} from "@material-ui/icons"; +import DeleteIcon from "@mui/icons-material/Delete"; +import {useDispatch, useSelector} from "react-redux"; +import {RootState} from "../../types/data"; +import {ActionModal} from "../dialog/ActionModal"; type MembersTableUserEntryProps = { @@ -17,6 +22,18 @@ export function MembersTableUserEntry(props: MembersTableUserEntryProps) { const {iconStyle, member} = props; + const groupRole = useSelector((state: RootState) => state.group.role); + + const [confirmationOpen, setConfirmationOpen] = useState(false); + const [updateFileOpen, setUpdateFileOpen] = useState(false); + + + const handleClick = (event: React.MouseEvent) => { + }; + + // confirmation dialog + const dispatch = useDispatch(); + return ( {member.user.email} {member.editor !== undefined && member.editor ? "Editor" : "Member"} - + + + + + ) } diff --git a/frontend/src/reducers/group.ts b/frontend/src/reducers/group.ts index 15b097a1a..749e379e9 100644 --- a/frontend/src/reducers/group.ts +++ b/frontend/src/reducers/group.ts @@ -1,6 +1,6 @@ import { RECEIVE_GROUPS, - RECEIVE_GROUP_ABOUT, + RECEIVE_GROUP_ABOUT, DELETE_GROUP_MEMBER, } from "../actions/group"; import { RECEIVE_GROUP_ROLE @@ -23,6 +23,10 @@ const group = (state = defaultState, action: DataAction) => { return Object.assign({}, state, {about: action.about}); case RECEIVE_GROUP_ROLE: return Object.assign({}, state, {role: action.role}); + case DELETE_GROUP_MEMBER: + return Object.assign({}, state, { + about: state.about.users.filter(member => member.user.id !== action.member.id), + }); default: return state; } From bca6a17703b394e0edac73e77985e18bd2f54560 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 13:55:41 -0500 Subject: [PATCH 02/11] hook the button in now --- .../src/components/groups/MembersTable.tsx | 16 +++++++---- .../groups/MembersTableUserEntry.tsx | 28 ++++++------------- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/frontend/src/components/groups/MembersTable.tsx b/frontend/src/components/groups/MembersTable.tsx index a8beb5a75..822b26f65 100644 --- a/frontend/src/components/groups/MembersTable.tsx +++ b/frontend/src/components/groups/MembersTable.tsx @@ -12,7 +12,6 @@ import {theme} from "../../theme"; import {MembersTableUserEntry} from "./MembersTableUserEntry"; import {ActionModal} from "../dialog/ActionModal"; import {useState} from "react"; -import {datasetDeleted} from "../../actions/dataset"; import {deleteGroupMember} from "../../actions/group"; type MembersTableProps = { @@ -25,20 +24,25 @@ const iconStyle = { } export default function MembersTable(props: MembersTableProps) { - const dispatch = useDispatch(); + + const {groupId} = props; // mapStateToProps const about = useSelector((state: RootState) => state.group.about); + // dispatch + const dispatch = useDispatch(); + const groupMemberDeleted = (groupId: string|undefined, username: string|undefined) => dispatch(deleteGroupMember(groupId, username)) + // use history hook to redirect/navigate between routes const [deleteDatasetConfirmOpen, setDeleteDatasetConfirmOpen] = useState(false); - const groupMemberDeleted = (groupId: string, username: string) => dispatch(deleteGroupMember(groupId, username)) + const [selectMemberUsername, setSelectMemberUsername] = useState(); return ( <> groupMemberDeleted(groupId, selectMemberUsername)} handleActionCancel={() => { setDeleteDatasetConfirmOpen(false); }}/> @@ -60,6 +64,8 @@ export default function MembersTable(props: MembersTableProps) { iconStyle={iconStyle} member={member} key={member.user.id} + setDeleteDatasetConfirmOpen={setDeleteDatasetConfirmOpen} + setSelectMemberUsername={setSelectMemberUsername} /> ))) : diff --git a/frontend/src/components/groups/MembersTableUserEntry.tsx b/frontend/src/components/groups/MembersTableUserEntry.tsx index 1a49f3e65..38ce83b3c 100644 --- a/frontend/src/components/groups/MembersTableUserEntry.tsx +++ b/frontend/src/components/groups/MembersTableUserEntry.tsx @@ -1,38 +1,23 @@ -import React, {useState} from "react"; +import React from "react"; import TableRow from "@mui/material/TableRow"; import TableCell from "@mui/material/TableCell"; import PersonIcon from "@mui/icons-material/Person"; import {Button, IconButton} from "@mui/material"; import {Member} from "../../openapi/v2"; -import MemberMenu from "./MemberMenu"; -import {SearchOutlined} from "@material-ui/icons"; import DeleteIcon from "@mui/icons-material/Delete"; -import {useDispatch, useSelector} from "react-redux"; -import {RootState} from "../../types/data"; -import {ActionModal} from "../dialog/ActionModal"; type MembersTableUserEntryProps = { iconStyle: {} member: Member + setDeleteDatasetConfirmOpen: any + setSelectMemberUsername: any } export function MembersTableUserEntry(props: MembersTableUserEntryProps) { - const {iconStyle, member} = props; - - const groupRole = useSelector((state: RootState) => state.group.role); - - const [confirmationOpen, setConfirmationOpen] = useState(false); - const [updateFileOpen, setUpdateFileOpen] = useState(false); - - - const handleClick = (event: React.MouseEvent) => { - }; - - // confirmation dialog - const dispatch = useDispatch(); + const {iconStyle, member, setDeleteDatasetConfirmOpen, setSelectMemberUsername} = props; return ( {member.user.email} {member.editor !== undefined && member.editor ? "Editor" : "Member"} - + { + setSelectMemberUsername(member.user.email) + setDeleteDatasetConfirmOpen(true); + }}> From 731684646e6cf25ffcd186c52a6bd322277b051f Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 13:56:56 -0500 Subject: [PATCH 03/11] clear the modal --- frontend/src/components/groups/MembersTable.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/groups/MembersTable.tsx b/frontend/src/components/groups/MembersTable.tsx index 822b26f65..131c0dac9 100644 --- a/frontend/src/components/groups/MembersTable.tsx +++ b/frontend/src/components/groups/MembersTable.tsx @@ -42,7 +42,11 @@ export default function MembersTable(props: MembersTableProps) { <> groupMemberDeleted(groupId, selectMemberUsername)} + actionBtnName="Delete" + handleActionBtnClick={() => { + groupMemberDeleted(groupId, selectMemberUsername); + setDeleteDatasetConfirmOpen(false); + }} handleActionCancel={() => { setDeleteDatasetConfirmOpen(false); }}/> From 8741b84cf9378884c9db2fa069e5999adbc13fce Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 21:33:25 -0500 Subject: [PATCH 04/11] add type --- frontend/src/components/groups/MemberMenu.tsx | 59 ------------------- frontend/src/reducers/group.ts | 2 +- frontend/src/types/action.ts | 6 ++ 3 files changed, 7 insertions(+), 60 deletions(-) delete mode 100644 frontend/src/components/groups/MemberMenu.tsx diff --git a/frontend/src/components/groups/MemberMenu.tsx b/frontend/src/components/groups/MemberMenu.tsx deleted file mode 100644 index fd45f9c67..000000000 --- a/frontend/src/components/groups/MemberMenu.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import * as React from 'react'; -import Button from '@mui/material/Button'; -import Menu from '@mui/material/Menu'; -import MenuItem from '@mui/material/MenuItem'; -import MenuIcon from '@mui/icons-material/Menu'; -import {FileOut as File} from "../../openapi/v2"; -import {useState} from "react"; -import {fileDeleted, fileDownloaded} from "../../actions/file"; -import {useDispatch, useSelector} from "react-redux"; -import {ActionModal} from "../dialog/ActionModal"; -import DownloadIcon from '@mui/icons-material/Download'; -import DeleteIcon from '@mui/icons-material/Delete'; -import UploadIcon from '@mui/icons-material/Upload'; -import {Dialog, DialogTitle, ListItemIcon, ListItemText} from "@mui/material"; -import {UpdateFile} from "./UpdateFile"; -import {MoreHoriz} from "@material-ui/icons"; -import {RootState} from "../../types/data"; -import {AuthWrapper} from "../auth/AuthWrapper"; -import {Member} from "../../openapi/v2"; - -type MemberMenuProps = { - member: Member -} - -export default function MemberMenu(props: MemberMenuProps) { - const {member} = props; - const [anchorEl, setAnchorEl] = React.useState(null); - const open = Boolean(anchorEl); - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - const handleClose = () => { - setAnchorEl(null); - }; - - // confirmation dialog - const dispatch = useDispatch(); - - const groupRole = useSelector((state: RootState) => state.group.role); - - const [confirmationOpen, setConfirmationOpen] = useState(false); - const [updateFileOpen, setUpdateFileOpen] = useState(false); - - return ( -
- -
- ); -} diff --git a/frontend/src/reducers/group.ts b/frontend/src/reducers/group.ts index 749e379e9..aafb6d2e6 100644 --- a/frontend/src/reducers/group.ts +++ b/frontend/src/reducers/group.ts @@ -25,7 +25,7 @@ const group = (state = defaultState, action: DataAction) => { return Object.assign({}, state, {role: action.role}); case DELETE_GROUP_MEMBER: return Object.assign({}, state, { - about: state.about.users.filter(member => member.user.id !== action.member.id), + about: {state.about.users.filter(member => member.user.id !== action.member.id)}, }); default: return state; diff --git a/frontend/src/types/action.ts b/frontend/src/types/action.ts index 35fe7893c..5787365a0 100644 --- a/frontend/src/types/action.ts +++ b/frontend/src/types/action.ts @@ -271,6 +271,11 @@ interface RECEIVE_GROUP_ROLE{ role: RoleType; } +interface DELETE_GROUP_MEMBER{ + type: "DELETE_GROUP_MEMBER" + about: Group +} + export type DataAction = | RECEIVE_FILES_IN_DATASET | RECEIVE_FOLDERS_IN_DATASET @@ -324,4 +329,5 @@ export type DataAction = | RECEIVE_GROUPS | RECEIVE_GROUP_ABOUT | RECEIVE_GROUP_ROLE + | DELETE_GROUP_MEMBER ; From 2acbd6c74cf964e6be5836a5acda5477cf4a617f Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 21:40:28 -0500 Subject: [PATCH 05/11] fix bug --- frontend/src/components/groups/MembersTable.tsx | 1 + frontend/src/reducers/group.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/groups/MembersTable.tsx b/frontend/src/components/groups/MembersTable.tsx index 131c0dac9..1d8448ee3 100644 --- a/frontend/src/components/groups/MembersTable.tsx +++ b/frontend/src/components/groups/MembersTable.tsx @@ -50,6 +50,7 @@ export default function MembersTable(props: MembersTableProps) { handleActionCancel={() => { setDeleteDatasetConfirmOpen(false); }}/> + diff --git a/frontend/src/reducers/group.ts b/frontend/src/reducers/group.ts index aafb6d2e6..749e379e9 100644 --- a/frontend/src/reducers/group.ts +++ b/frontend/src/reducers/group.ts @@ -25,7 +25,7 @@ const group = (state = defaultState, action: DataAction) => { return Object.assign({}, state, {role: action.role}); case DELETE_GROUP_MEMBER: return Object.assign({}, state, { - about: {state.about.users.filter(member => member.user.id !== action.member.id)}, + about: state.about.users.filter(member => member.user.id !== action.member.id), }); default: return state; From 4e7995885d6e03e3a95cd32573da53381d0fb940 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 22:29:43 -0500 Subject: [PATCH 06/11] add group modal --- frontend/src/actions/group.js | 18 +++- .../src/components/groups/AddMemberModal.tsx | 97 +++++++++++++++++++ frontend/src/components/groups/Group.tsx | 65 ++++++------- frontend/src/reducers/group.ts | 4 +- 4 files changed, 149 insertions(+), 35 deletions(-) create mode 100644 frontend/src/components/groups/AddMemberModal.tsx diff --git a/frontend/src/actions/group.js b/frontend/src/actions/group.js index 651b2f6e0..f098f496f 100644 --- a/frontend/src/actions/group.js +++ b/frontend/src/actions/group.js @@ -36,7 +36,6 @@ export function fetchGroupAbout(id){ }; } - export const DELETE_GROUP_MEMBER = "DELETE_GROUP_MEMBER"; export function deleteGroupMember(groupId, username){ return (dispatch) => { @@ -53,3 +52,20 @@ export function deleteGroupMember(groupId, username){ }); }; } + +export const ADD_GROUP_MEMBER = "ADD_GROUP_MEMBER"; +export function addGroupMember(groupId, username){ + return (dispatch) => { + return V2.GroupsService.addMemberApiV2GroupsGroupIdAddUsernamePost(groupId, username) + .then(json => { + dispatch({ + type: ADD_GROUP_MEMBER, + member: json, + receivedAt: Date.now(), + }); + }) + .catch(reason => { + dispatch(handleErrors(reason, addGroupMember(groupId, username))); + }); + }; +} diff --git a/frontend/src/components/groups/AddMemberModal.tsx b/frontend/src/components/groups/AddMemberModal.tsx new file mode 100644 index 000000000..93161fdaf --- /dev/null +++ b/frontend/src/components/groups/AddMemberModal.tsx @@ -0,0 +1,97 @@ +import React, {useState} from "react"; +import { + Autocomplete, + Box, + Button, + Container, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + FormControl, + InputLabel, + MenuItem, + Select, + TextField +} from "@mui/material"; +import {addGroupMember} from "../../actions/group"; +import {useDispatch} from "react-redux"; + + +type AddMemberModalProps = { + open: boolean, + handleClose: any, + groupName: string +} + +export default function AddMemberModal(props: AddMemberModalProps) { + const { open, handleClose, groupName } = props; + + const dispatch = useDispatch(); + const groupMemberAdded = (groupId:string | undefined, username: string | undefined) => dispatch(addGroupMember(groupId, username)); + + const [email, setEmail] = useState("") + const [role, setRole] = useState("viewer") + + const onShare = () => { + handleClose(); + } + + return ( + + + Add People to {groupName} + + + { + setEmail(value) + }} + options={["abc@xyz.com"]} + renderInput={(params) => + } + /> + AS + + Status + + + + + + + + + + + ); +} diff --git a/frontend/src/components/groups/Group.tsx b/frontend/src/components/groups/Group.tsx index 3c7ce0d8f..ce8d369ba 100644 --- a/frontend/src/components/groups/Group.tsx +++ b/frontend/src/components/groups/Group.tsx @@ -1,26 +1,16 @@ import React, {useEffect, useState} from "react"; -import { - Box, - Button, - ButtonGroup, CardActionArea, - Divider, - Grid, - List, -} from "@mui/material"; +import {Box, Button} from "@mui/material"; import Layout from "../Layout"; import {RootState} from "../../types/data"; import {useDispatch, useSelector} from "react-redux"; -import {fetchGroupAbout} from "../../actions/group"; +import {addGroupMember, fetchGroupAbout} from "../../actions/group"; import {fetchGroupRole} from "../../actions/authorization"; -import {ArrowBack, ArrowForward} from "@material-ui/icons"; -import Typography from '@mui/material/Typography'; -import {theme} from "../../theme"; -import {Link, useParams} from "react-router-dom"; -import Card from "@mui/material/Card"; -import CardContent from "@mui/material/CardContent"; -import RoleChip from "../auth/RoleChip"; -import FilesTable from "../files/FilesTable"; +import Typography from "@mui/material/Typography"; +import {useParams} from "react-router-dom"; +import {AuthWrapper} from "../auth/AuthWrapper"; +import PersonAddAlt1Icon from "@mui/icons-material/PersonAddAlt1"; import MembersTable from "./MembersTable"; +import AddMemberModal from "./AddMemberModal"; export function Group() { @@ -36,6 +26,8 @@ export function Group() { const about = useSelector((state: RootState) => state.group.about); const role = useSelector((state: RootState) => state.group.role); + const [addMemberModalOpen,setAddMemberModalOpen] = useState(false); + // component did mount useEffect(() => { fetchGroupInfo(groupId); @@ -44,22 +36,29 @@ export function Group() { return ( - - {/*title*/} - - - {about !== undefined ? about.name : "Not found"} - - - - - {about.description} - - - - - - + {setAddMemberModalOpen(false);}} + groupName={about.name}/> + + + {about !== undefined ? about.name : "Not found"} + + {about.description} + + {/**/} + + {/**/} + + ); } diff --git a/frontend/src/reducers/group.ts b/frontend/src/reducers/group.ts index 749e379e9..67a96f707 100644 --- a/frontend/src/reducers/group.ts +++ b/frontend/src/reducers/group.ts @@ -1,6 +1,6 @@ import { RECEIVE_GROUPS, - RECEIVE_GROUP_ABOUT, DELETE_GROUP_MEMBER, + RECEIVE_GROUP_ABOUT, DELETE_GROUP_MEMBER, ADD_GROUP_MEMBER, } from "../actions/group"; import { RECEIVE_GROUP_ROLE @@ -27,6 +27,8 @@ const group = (state = defaultState, action: DataAction) => { return Object.assign({}, state, { about: state.about.users.filter(member => member.user.id !== action.member.id), }); + case ADD_GROUP_MEMBER: + return Object.assign({}, state, {}) default: return state; } From c7ddd7d13f4bdb288e6a31063b37b478bfe18aee Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Wed, 29 Mar 2023 22:50:37 -0500 Subject: [PATCH 07/11] add icon --- frontend/src/actions/user.js | 19 +++++++++++ .../src/components/groups/AddMemberModal.tsx | 34 +++++++++++++------ frontend/src/reducers/group.ts | 8 +++-- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/frontend/src/actions/user.js b/frontend/src/actions/user.js index f45955e92..f40a2c23f 100644 --- a/frontend/src/actions/user.js +++ b/frontend/src/actions/user.js @@ -1,6 +1,8 @@ import {V2} from "../openapi"; import Cookies from "universal-cookie"; import config from "../app.config"; +import {handleErrors} from "./common"; +import {ADD_GROUP_MEMBER} from "./group"; const cookies = new Cookies(); @@ -89,3 +91,20 @@ export function logout() { }); }; } + +export const LIST_USERS = "LIST_USERS"; +export function fetchAllUsers(skip=0, limit=21){ + return (dispatch) => { + return V2.UsersService.getUsersApiV2UsersGet(skip, limit) + .then(json => { + dispatch({ + type: LIST_USERS, + users: json, + receivedAt: Date.now(), + }); + }) + .catch(reason => { + dispatch(fetchAllUsers(skip=0, limit=21)); + }); + }; +} diff --git a/frontend/src/components/groups/AddMemberModal.tsx b/frontend/src/components/groups/AddMemberModal.tsx index 93161fdaf..492b61590 100644 --- a/frontend/src/components/groups/AddMemberModal.tsx +++ b/frontend/src/components/groups/AddMemberModal.tsx @@ -1,4 +1,4 @@ -import React, {useState} from "react"; +import React, {useEffect, useState} from "react"; import { Autocomplete, Box, @@ -15,7 +15,11 @@ import { TextField } from "@mui/material"; import {addGroupMember} from "../../actions/group"; -import {useDispatch} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; +import {fetchAllUsers} from "../../actions/user"; +import {RootState} from "../../types/data"; +import {UserOut} from "../../openapi/v2"; +import GroupsIcon from "@mui/icons-material/Groups"; type AddMemberModalProps = { @@ -28,14 +32,21 @@ export default function AddMemberModal(props: AddMemberModalProps) { const { open, handleClose, groupName } = props; const dispatch = useDispatch(); + const listAllUsers = (skip:number, limit:number) => dispatch(fetchAllUsers(skip, limit)); const groupMemberAdded = (groupId:string | undefined, username: string | undefined) => dispatch(addGroupMember(groupId, username)); + const users = useSelector((state: RootState) => state.group.users); - const [email, setEmail] = useState("") - const [role, setRole] = useState("viewer") + const [email, setEmail] = useState(""); + const [role, setRole] = useState("viewer"); + const [options, setOptions] = useState([]); - const onShare = () => { - handleClose(); - } + useEffect(() => { + listAllUsers(0, 21); + }, []) + + useEffect(() =>{ + setOptions(users.reduce((list:string[], user:UserOut) => { return [...list, user.email];}, [])); + }, [users]) return ( @@ -45,7 +56,8 @@ export default function AddMemberModal(props: AddMemberModalProps) { padding: "2em", }, }}> - Add People to {groupName} + Add People to {groupName} { setEmail(value) }} - options={["abc@xyz.com"]} + options={options} renderInput={(params) => } /> AS @@ -83,7 +95,7 @@ export default function AddMemberModal(props: AddMemberModalProps) { diff --git a/frontend/src/reducers/group.ts b/frontend/src/reducers/group.ts index 67a96f707..98e0007f4 100644 --- a/frontend/src/reducers/group.ts +++ b/frontend/src/reducers/group.ts @@ -7,12 +7,14 @@ import { } from "../actions/authorization"; import {DataAction} from "../types/action"; import {GroupState} from "../types/data"; -import {GroupOut, RoleType} from "../openapi/v2"; +import {GroupOut, RoleType, UserOut} from "../openapi/v2"; +import {LIST_USERS} from "../actions/user"; const defaultState: GroupState = { groups: [], about: {}, - role: {} + role: {}, + users: [] }; const group = (state = defaultState, action: DataAction) => { @@ -29,6 +31,8 @@ const group = (state = defaultState, action: DataAction) => { }); case ADD_GROUP_MEMBER: return Object.assign({}, state, {}) + case LIST_USERS: + return Object.assign({}, state, {users: action.users}); default: return state; } From 7950abd0e4baddab49c21d980350902b9204d659 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 30 Mar 2023 16:58:21 -0500 Subject: [PATCH 08/11] write better reducer --- .../src/components/groups/AddMemberModal.tsx | 14 ++++++++------ frontend/src/components/groups/Group.tsx | 2 +- .../src/components/groups/MembersTable.tsx | 6 +++--- frontend/src/reducers/group.ts | 11 ++++++----- frontend/src/types/action.ts | 19 ++++++++++++++++--- frontend/src/types/data.ts | 5 ++++- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/groups/AddMemberModal.tsx b/frontend/src/components/groups/AddMemberModal.tsx index 492b61590..f10697f84 100644 --- a/frontend/src/components/groups/AddMemberModal.tsx +++ b/frontend/src/components/groups/AddMemberModal.tsx @@ -29,7 +29,7 @@ type AddMemberModalProps = { } export default function AddMemberModal(props: AddMemberModalProps) { - const { open, handleClose, groupName } = props; + const { open, handleClose, groupName, groupId } = props; const dispatch = useDispatch(); const listAllUsers = (skip:number, limit:number) => dispatch(fetchAllUsers(skip, limit)); @@ -48,6 +48,10 @@ export default function AddMemberModal(props: AddMemberModalProps) { setOptions(users.reduce((list:string[], user:UserOut) => { return [...list, user.email];}, [])); }, [users]) + const handleAddButtonClick = () =>{ + groupMemberAdded(groupId, email); + handleClose(); + } return ( { setRole(event.target.value) }} > - Owner + Member Editor - Uploader - Viewer diff --git a/frontend/src/components/groups/Group.tsx b/frontend/src/components/groups/Group.tsx index ce8d369ba..e53cebab3 100644 --- a/frontend/src/components/groups/Group.tsx +++ b/frontend/src/components/groups/Group.tsx @@ -49,7 +49,7 @@ export function Group() { {about.description} - {/**/} + {/**/} + { + setEmail(value) + }} + options={options} + renderInput={(params) => + } + /> - + + diff --git a/frontend/src/components/groups/Group.tsx b/frontend/src/components/groups/Group.tsx index e53cebab3..634357ddc 100644 --- a/frontend/src/components/groups/Group.tsx +++ b/frontend/src/components/groups/Group.tsx @@ -49,14 +49,14 @@ export function Group() { {about.description} - {/**/} - - {/**/} + + + From 2dc8b1dbc2727d9ca54091bf0b8f9d3eaa6c5c34 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Thu, 30 Mar 2023 17:18:41 -0500 Subject: [PATCH 10/11] finalize the logic --- frontend/src/actions/group.js | 4 ++-- frontend/src/components/groups/AddMemberModal.tsx | 3 ++- frontend/src/components/groups/Group.tsx | 8 ++++---- frontend/src/components/groups/MembersTable.tsx | 6 +++--- frontend/src/reducers/group.ts | 9 +++------ frontend/src/types/action.ts | 4 ++-- frontend/src/types/data.ts | 2 -- 7 files changed, 16 insertions(+), 20 deletions(-) diff --git a/frontend/src/actions/group.js b/frontend/src/actions/group.js index f098f496f..e72f8b410 100644 --- a/frontend/src/actions/group.js +++ b/frontend/src/actions/group.js @@ -43,7 +43,7 @@ export function deleteGroupMember(groupId, username){ .then(json => { dispatch({ type: DELETE_GROUP_MEMBER, - member: json, + about: json, receivedAt: Date.now(), }); }) @@ -60,7 +60,7 @@ export function addGroupMember(groupId, username){ .then(json => { dispatch({ type: ADD_GROUP_MEMBER, - member: json, + about: json, receivedAt: Date.now(), }); }) diff --git a/frontend/src/components/groups/AddMemberModal.tsx b/frontend/src/components/groups/AddMemberModal.tsx index 2848c6088..16b3419ed 100644 --- a/frontend/src/components/groups/AddMemberModal.tsx +++ b/frontend/src/components/groups/AddMemberModal.tsx @@ -25,7 +25,8 @@ import GroupsIcon from "@mui/icons-material/Groups"; type AddMemberModalProps = { open: boolean, handleClose: any, - groupName: string + groupName: string, + groupId: string, } export default function AddMemberModal(props: AddMemberModalProps) { diff --git a/frontend/src/components/groups/Group.tsx b/frontend/src/components/groups/Group.tsx index 634357ddc..6f58560bc 100644 --- a/frontend/src/components/groups/Group.tsx +++ b/frontend/src/components/groups/Group.tsx @@ -23,7 +23,7 @@ export function Group() { const fetchGroupInfo = (groupId: string | undefined) => dispatch(fetchGroupAbout(groupId)); const fetchCurrentGroupRole = (groupId: string | undefined) => dispatch(fetchGroupRole(groupId)); - const about = useSelector((state: RootState) => state.group.about); + const groupAbout = useSelector((state: RootState) => state.group.about); const role = useSelector((state: RootState) => state.group.role); const [addMemberModalOpen,setAddMemberModalOpen] = useState(false); @@ -37,7 +37,7 @@ export function Group() { return ( {setAddMemberModalOpen(false);}} - groupName={about.name}/> + groupName={groupAbout.name} groupId={groupAbout.id}/> - {about !== undefined ? about.name : "Not found"} + {groupAbout !== undefined ? groupAbout.name : "Not found"} - {about.description} + {groupAbout.description} {member.user.email} @@ -35,7 +49,7 @@ export function MembersTableUserEntry(props: MembersTableUserEntryProps) { setSelectMemberUsername(member.user.email) setDeleteDatasetConfirmOpen(true); }}> - +