diff --git a/React-frontend/src/App.js b/React-frontend/src/App.js index fb10cf9b..a88d8202 100644 --- a/React-frontend/src/App.js +++ b/React-frontend/src/App.js @@ -35,6 +35,7 @@ import ForgotPassword from './pages/ForgotPassword'; import ResetPassword from './pages/ResetPassword'; import VerifyEmail from './pages/VerifyEmail'; import ComparePage from './pages/Management/ComparePage'; +import SearchUser from './pages/admin/SearchUser'; // private route accessbile for only authenticated users @@ -93,6 +94,7 @@ function App() { + diff --git a/React-frontend/src/components/Admin/SearchMembers.js b/React-frontend/src/components/Admin/SearchMembers.js new file mode 100644 index 00000000..3c5a456f --- /dev/null +++ b/React-frontend/src/components/Admin/SearchMembers.js @@ -0,0 +1,269 @@ +/* + Functional component to search from the list + all the members(extractor and management) + of an admin. +*/ + +import React, { useEffect, useRef, useState } from 'react' +import { makeStyles, withStyles } from '@material-ui/core/styles'; +import { + TextField +} from '@material-ui/core'; +import { + Container, + TableContainer, + Paper, + Table, + TableHead, + TableBody, + TableRow, + TableCell, + TableFooter, + TablePagination +} from '@material-ui/core'; +import { useHistory } from 'react-router-dom'; +import { useDispatch } from 'react-redux'; +import { selectUser } from '../../store/actions/admin'; +import TablePaginationActions from '../Utils/TablePaginationActions'; +import { extractor_default, fetch_extracted_cases } from '../../store/actions/extractor'; + +// Columns for table representation +const columns = [ + { field: 'id', headerName: 'ID', flex: 1 }, + { field: 'name', headerName: 'Full Name', flex:1 }, + { field: 'email', headerName: 'Email', flex: 1 }, + { field: 'varified', headerName: 'Varified', flex:1}, + { field: 'role', headerName: 'Role', flex: 1}, + +] + +// custom styles +const useStyle = makeStyles((theme) => ({ + root: { + marginTop: '10vh', + height: '82.5vh', + padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`, + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start' + }, + title: { + fontWeight: 600, + }, + table: { + height: '41vh', + width: '70vw', + minWidth: '50vw', + maxWidth: '100vw', + '&:focus': { + outline: 'none', + border: 'none' + } + }, + button: { + fontSize: '.8rem', + fontWeight: 'bolder', + '&:focus': { + outline: 'none' + } + } +})) + +// Styling For cells +const StyledTableCell = withStyles((theme) => ({ + head: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + body: { + fontSize: 14, + }, +}))(TableCell); + + +// Styling For rows +const StyledTableRow = withStyles((theme) => ({ + root: { + cursor: 'pointer', + "&:nth-of-type(odd)": { + backgroundColor: theme.palette.action.hover, + }, + }, +}))(TableRow); + + +const SearchMembers = ({ extractors, managements}) => { + + // Invoking Classes + const classes = useStyle() + + // history + const history = useHistory() + + // Dispatcher + const dispatch = useDispatch() + + // State variablef for page + const [page, setPage] = useState(0); + + const [showUser, setShowUser] = useState([]); + const member = useRef(null); + + // Row definition for extractor members + const extractorRows = extractors.map((member, index) => ( + { + id: index+1, + name: member.name, + email: member.email, + varified: (member.varified) ? 'Varified': 'Not Varified', + role: member.role, + } + )) + + // Row definition for management members + const managementRows = managements.map((member, index) => ( + { + id: index+1, + name: member.name, + email: member.email, + role: member.role, + varified: (member.varified) ? 'Varified': 'Not Varified' + } + )) + + const allMembers = managementRows.concat(extractorRows).map((member, index) => ( + { + id: index+1, + name: member.name, + email: member.email, + role: member.role, + varified: (member.varified) ? 'Varified': 'Not Varified' + })) + + const sliceMembers = (page, rowsPerPage) => + allMembers.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage); + + useEffect(() => { + setShowUser(sliceMembers(page, rowsPerPage)) + },[extractors]) + + const [rowsPerPage, setRowsPerPage] = useState(5); + + // Number of empty rows + const emptyRows = rowsPerPage - Math.min(rowsPerPage, allMembers.length - page * rowsPerPage); + + // Handling page change + const handleChangePage = (event, newPage) => { + setPage(newPage) + setShowUser(sliceMembers(newPage, rowsPerPage)) + }; + + // Handling Row per page change + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + setShowUser(sliceMembers(0, event.target.value)) + }; + + // Function to handle Double click on any row + function handleCellClick(gridCellParam){ + + // Dispatch selected user + dispatch(selectUser(gridCellParam)) + + // Dispatch extracted cases + if(gridCellParam.role === "extractor"){ + dispatch(fetch_extracted_cases(gridCellParam.email)) + } + + // Dispatch management related stuff + if(gridCellParam.role === "management"){ + dispatch(extractor_default()) + } + + // Redireect to member deails + history.push('/list-members/member/'+gridCellParam.id) + } + + function handleInput() { + if (member.current.value.length === 0) { + setShowUser(sliceMembers(page, rowsPerPage)) + } else { + setShowUser(sliceMembers(page, rowsPerPage).filter(ele => { + return ele.name.startsWith(member.current.value) + })) + } + } + + return ( + + + + + + + {(columns.map((column) => { + return ( + {column.headerName} + ) + }))} + + + + { + (showUser + ).map((row) => ( + handleCellClick(row)}> + + {row.id} + + + {row.name} + + + {row.email} + + + {row.varified} + + + {row.role} + + + )) + } + + {emptyRows > 0 && ( + + + + )} + + + + + + + + +
+
+
+ ); +} + +export default SearchMembers diff --git a/React-frontend/src/components/Sidebar.js b/React-frontend/src/components/Sidebar.js index 7a59c6a5..d8480c42 100644 --- a/React-frontend/src/components/Sidebar.js +++ b/React-frontend/src/components/Sidebar.js @@ -101,7 +101,7 @@ function Sidebar() { // User management related list items(For Admin) const userManagementItems = [ ['All Members', , "/list-members"], ['Add Member', , "/create-member"], - ['Search User', , "/"] + ['Search User', , "/search-user"] ] // Task Management related list items(For Admin) diff --git a/React-frontend/src/pages/admin/SearchUser.js b/React-frontend/src/pages/admin/SearchUser.js new file mode 100644 index 00000000..bd50d27a --- /dev/null +++ b/React-frontend/src/pages/admin/SearchUser.js @@ -0,0 +1,43 @@ +/* +* Component to search the members. +*/ + +import React, { useEffect, useState } from 'react' +import Layout from '../../components/core/Layout' +import SearchMembers from '../../components/Admin/SearchMembers'; +import HomeLogo from '../../components/core/HomeLogo'; +import { useSelector, useDispatch } from 'react-redux'; +import { fetchMembers } from '../../store/actions/admin'; + +const SearchUser = () => { + // auth reducer + const auth = useSelector(state => state.auth) + const dispatch = useDispatch() + const { extractors, managements, isLoading } = useSelector(state => state.admin) + + useEffect(() => { + dispatch(fetchMembers()) + }, [dispatch]) + + if(auth && auth.isAuthenticated){ + return ( +
+ + + +
+ ) + } + return ( + + + + ) +} + +export default SearchUser diff --git a/React-frontend/src/store/actions/auth.js b/React-frontend/src/store/actions/auth.js index aced0916..ceb979ab 100644 --- a/React-frontend/src/store/actions/auth.js +++ b/React-frontend/src/store/actions/auth.js @@ -130,7 +130,7 @@ export const login = (email, password, role, remember, callback) => async dispat type: LOGIN_SUCCESSFULL, payload: {data: {auth_token: res.data.access_token}} }) - callback(false) + if (callback) callback(false) dispatch(loadUser()) dispatch(setAlert(res.data.message, 'success')) } @@ -177,7 +177,7 @@ export const signUp = (username, email, password, role, history, callback) => (d .then((res) => { if(res && (res.status === 200 || res.status === 201)){ dispatch({type: SIGNUP_SUCCESSFULL}) - callback(false) + if (callback) callback(false) history.push('/') dispatch(setAlert(res.data.message, 'success')) window.location.reload() diff --git a/React-frontend/src/store/actions/extractor.js b/React-frontend/src/store/actions/extractor.js index cb224739..a2de47d8 100644 --- a/React-frontend/src/store/actions/extractor.js +++ b/React-frontend/src/store/actions/extractor.js @@ -69,8 +69,7 @@ export const fetch_extracted_cases = (extractor_email) => (dispatch) => { // Error response const res = err.response - console.log(err.message) - if(res.data && (res.status === 404 || res.status === 409 || res.status === 401 || res.status === 403)){ + if(res && res.data && (res.status === 404 || res.status === 409 || res.status === 401 || res.status === 403)){ dispatch({ type: FETCH_EXTRACTED_CASES_FAILED, payload: {