Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #242 : added search user page. #247

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions React-frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -93,6 +94,7 @@ function App() {
<PublicRoute path='/verify-email/:token' component={VerifyEmail} />
<PrivateRoute path='/admin' component={AdminPage} />
<PrivateRoute path='/list-members' exact component={MemberList} />
<PrivateRoute path='/search-user' exact component={SearchUser} />
<PrivateRoute path='/list-members/member/:id' component={SelectedMember} />
<PrivateRoute path='/task/create' exact component={CreateTask} />
<PrivateRoute path='/task/list' exact component={ShowTasks} />
Expand Down
269 changes: 269 additions & 0 deletions React-frontend/src/components/Admin/SearchMembers.js
Original file line number Diff line number Diff line change
@@ -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 (
<Container className={classes.root}>
<TextField id="outlined-basic" label="search member" variant="outlined"
fullWidth inputRef={member} onChange={handleInput}/>
<TableContainer component={Paper} style={{ marginTop: '2em'}} >
<Table className={classes.table}>
<TableHead>
<StyledTableRow>
{(columns.map((column) => {
return (
<StyledTableCell align="left" key={column.field}>{column.headerName}</StyledTableCell>
)
}))}
</StyledTableRow>
</TableHead>
<TableBody>
{
(showUser
).map((row) => (
<StyledTableRow key={row.name} style={{ cursor: 'pointer'}} onDoubleClick={() => handleCellClick(row)}>
<StyledTableCell component="th" scope="row" style={{ width: 100}} align="left">
{row.id}
</StyledTableCell>
<StyledTableCell style={{ width: 200 }} align="left">
{row.name}
</StyledTableCell>
<StyledTableCell style={{ width: 200 }} align="left">
{row.email}
</StyledTableCell>
<StyledTableCell style={{ width: 160 }} align="left">
{row.varified}
</StyledTableCell>
<StyledTableCell style={{ width: 160 }} align="left">
{row.role}
</StyledTableCell>
</StyledTableRow>
))
}

{emptyRows > 0 && (
<StyledTableRow style={{ height: 53 * emptyRows }}>
<StyledTableCell colSpan={6} />
</StyledTableRow>
)}
</TableBody>

<TableFooter>
<StyledTableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25, { label: 'All', value: -1 }]}
colSpan={5}
count={allMembers.length}
rowsPerPage={rowsPerPage}
page={page}
SelectProps={{
inputProps: { 'aria-label': 'rows per page' },
native: true,
}}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
ActionsComponent={TablePaginationActions}
/>
</StyledTableRow>
</TableFooter>

</Table>
</TableContainer>
</Container>
);
}

export default SearchMembers
2 changes: 1 addition & 1 deletion React-frontend/src/components/Sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ function Sidebar() {
// User management related list items(For Admin)
const userManagementItems = [ ['All Members', <SupervisorAccountIcon color="secondary"/>, "/list-members"],
['Add Member', <PersonAddIcon color="secondary"/>, "/create-member"],
['Search User', <SearchIcon color="secondary" />, "/"]
['Search User', <SearchIcon color="secondary" />, "/search-user"]
]

// Task Management related list items(For Admin)
Expand Down
43 changes: 43 additions & 0 deletions React-frontend/src/pages/admin/SearchUser.js
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<Layout sidebarBool={true}>
<SearchMembers
extractors={extractors}
managements={managements}
isLoading={isLoading}
isSearch={true}
/>
</Layout>
</div>
)
}
return (
<Layout sidebarBool={false}>
<HomeLogo />
</Layout>
)
}

export default SearchUser
4 changes: 2 additions & 2 deletions React-frontend/src/store/actions/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'))
}
Expand Down Expand Up @@ -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()
Expand Down
3 changes: 1 addition & 2 deletions React-frontend/src/store/actions/extractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down