Merge branch 'task-94-feature/modal_switch_user' into 'development'

Task 94 feature/modal switch user

See merge request !71
parents bd6399d0 4655ba74
......@@ -12,6 +12,7 @@ router.get('/',async (req:Request, res:Response): Promise<Response>=> {
const projects:Project[] = await dataSource.manager.find(Project)
return res.send({projects})
})
/**get projects were user is member, by user token */
router.get('/my',auth, async (req:Request, res:Response): Promise<Response>=> {
const user = req.body.user
......@@ -43,6 +44,9 @@ router.get('/my',auth, async (req:Request, res:Response): Promise<Response>=> {
return res.send({projects})
})
/**create new project */
router.post('/',auth, async (req:Request, res:Response): Promise<Response> => {
if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'})
......@@ -114,6 +118,10 @@ router.get('/user/:userId', async (req : Request, res : Response): Promise<Respo
})
/** Add user to specific project */
router.post('/add-user/', authAdminProject, async (req: Request, res: Response):Promise<Response>=>{
......
......@@ -35,6 +35,22 @@ const users = await dataSource
return res.send({users})
})
//** return all users of DB */
router.get('/all-fields/', async (req : Request, res : Response):Promise<object> => {
const users = await dataSource
.getRepository(User)
.find({
relations:{
members:{
project:true,
user:true
},
}
})
return res.send({users})
})
/**create new user*/
router.post('/', upload.single("avatar"), async (req : Request, res : Response):Promise<object> => {
const {name,surname,password,email, role} = req.body;
......
......@@ -10,7 +10,7 @@ import { useParams } from "react-router-dom";
import PersonAddIcon from '@mui/icons-material/PersonAdd';
const style = {
position: 'absolute',
position: 'relative',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
......
import {Button, Menu, MenuItem} from "@mui/material";
import { useState } from "react";
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import {NavLink, useNavigate} from "react-router-dom";
import { logoutUser } from "../../../store/actions/usersActions";
import { fetchUsersAllFields, fetchUsers, logoutUser } from "../../../store/actions/usersActions";
import SwitchUserModal from "../../SwitchUserModal/SwitchUserModal";
const ProfileBlock = () => {
const dispatch = useDispatch();
......@@ -11,6 +12,9 @@ const ProfileBlock = () => {
const open = Boolean(anchorEl);
const user = useSelector(state => state.users.user)
const [openSwitchUser, setOpenSwitchUser] = useState(false);
const handleCloseSwitchUser = () => setOpenSwitchUser(false);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
......@@ -18,10 +22,20 @@ const ProfileBlock = () => {
setAnchorEl(null);
};
const handleOpenSwitchUser = () => setOpenSwitchUser(true);
const logout = () => {
dispatch(logoutUser(navigate));
handleClose()
}
const switchUser=()=>{
dispatch(fetchUsersAllFields());
// dispatch(fetchUsers())
handleClose()
handleOpenSwitchUser()
}
return <>
<Button
color="inherit"
......@@ -37,8 +51,13 @@ const ProfileBlock = () => {
>
<MenuItem component={NavLink} to="/profile/test" color="inherit" onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={()=>{switchUser()}}>Поменять юзера</MenuItem>
<MenuItem onClick={()=>{logout()}}>Logout</MenuItem>
</Menu>
<SwitchUserModal
open={openSwitchUser}
handleClose={handleCloseSwitchUser}
/>
</>
};
......
import {Box, Button, Grid, Modal} from "@mui/material";
import {useState} from "react";
import { useSelector } from "react-redux";
import FormElement from "../UI/Form/FormElement/FormElement";
import FormElement from "../../UI/Form/FormElement/FormElement";
import {Typography} from "@mui/material";
const style = {
......
......@@ -10,11 +10,11 @@ import {
Paper
} from "@mui/material";
import { useState } from "react";
import TaskModal from "../../components/MyTasksCompoments/TaskModal/TaskModal";
import TaskModal from "../../../components/MyTasksCompoments/TaskModal/TaskModal";
import moment from "moment";
import CustomTableCell from "../../components/MyTasksCompoments/CustomTableCell";
import MaterialUIPickers from "../../components/MyTasksCompoments/DateTimePicker/DateTimePicker";
import BasicSelect from "../../components/UI/Select/Select";
import CustomTableCell from "../../../components/MyTasksCompoments/CustomTableCell";
import MaterialUIPickers from "../../../components/MyTasksCompoments/DateTimePicker/DateTimePicker";
import BasicSelect from "../../../components/UI/Select/Select";
import ProjectTasksHeader from "./ProjectTasksHeader";
export default function ProjectTasksBody({ tasks }) {
......
import React,{useEffect, useState} from 'react';
import { Button, Grid ,Typography,Autocomplete, TextField} from "@mui/material";
import SwitchUserTable from '../SwitchUserTable/SwitchUserTable';
const SwitchUserForm=({submitFormHandler, users})=> {
const [currentUser, setCurrentUser] = useState(null);
const [projectsRoles, setProjectsRole] = useState([])
const onChangeHandle =(user)=>{
setCurrentUser(user)
setProjectsRole([])
}
useEffect(()=>{
if(currentUser?.members.length>0) {
for (let member of currentUser.members ) {
const newProjectRole = {
"projectName":member.project.title,
"roleName":member.roleProject
}
setProjectsRole([...projectsRoles, newProjectRole ])
}
}
},[ currentUser])
return (
<>
{/* <Box sx={style}> */}
{users?
<form onSubmit={(e)=>submitFormHandler(e,currentUser)}>
<Grid container direction="column" spacing={2}>
<Typography variant="h5" style={{margin: "5px", textAlign: "center"}} >Выберите юзера</Typography>
<Autocomplete
options={users}
onChange={(event,user)=>onChangeHandle(user) }
getOptionLabel={(option) => option.displayName}
renderInput={(params) => <TextField
style={{margin: "5px"}}
label={"Юзер"}
{...params} />}
/>
{projectsRoles.length>0?
<Grid item>
<SwitchUserTable projectsRoles={projectsRoles}/>
</Grid>
:<></>}
<Grid container direction="row" spacing={2}>
<Grid item>
<Button
type="submit"
color="primary"
variant="contained"
sx={{margin:1}}
>
ОК
</Button>
</Grid>
{/* <Grid item>
<Button
onClick={()=>console.log('cancel form')}
color="primary"
variant="contained"
>
Отмена
</Button>
</Grid> */}
</Grid>
</Grid>
</form>
: <></>}
{/* </Box> */}
</>
)
}
export default SwitchUserForm;
import React from 'react';
import Box from '@mui/material/Box';
import Modal from '@mui/material/Modal';
import { useDispatch, useSelector } from "react-redux";
import { logoutUser, loginUser } from '../../store/actions/usersActions';
import SwitchUserForm from './SwitchUserForm/SwitchUserForm';
import { useNavigate } from "react-router-dom";
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 'fit-content',
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const SwitchUserModal= ({open, handleClose})=> {
const dispatch= useDispatch();
const usersAllFields = useSelector(state => state.users.usersAllFields)
const navigate= useNavigate();
const submitFormHandler=(e, currentUser)=>{
dispatch(logoutUser(navigate))
e.preventDefault();
dispatch(loginUser({
"email": currentUser.email,
"password": "123"
}, navigate))
}
return (
<div>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<SwitchUserForm
submitFormHandler = {submitFormHandler}
users = {usersAllFields}
/>
</Box>
</Modal>
</div>
);
}
export default SwitchUserModal;
import * as React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
const SwitchUserTable=({projectsRoles})=>{
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 350 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell
sx ={{
'backgroundColor':'black',
'color': 'white'
}}
>Проекты</TableCell>
<TableCell
sx ={{
'backgroundColor':'black',
'color': 'white'
}} align="right"
>Роли</TableCell>
</TableRow>
</TableHead>
<TableBody>
{projectsRoles.map((projectRole,index) => (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell component="th" scope="row">
{projectRole.projectName}
</TableCell>
<TableCell align="right">{projectRole.roleName}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)
}
export default SwitchUserTable ;
......@@ -3,9 +3,9 @@ import { useParams } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { useEffect } from "react";
import { fetchProject } from "../../store/actions/projectsActions";
import ProjectTasksBody from "../../components/ProjectTasks/ProjectTasksBody";
import ProjectTasksBody from "../../components/ProjectComponents/ProjectTasks/ProjectTasksBody";
import { fetchUsers } from "../../store/actions/usersActions";
import ProjectMembersList from "../../components/ProjectMembersList/ProjectMembersList";
import ProjectMembersList from "../../components/ProjectComponents/ProjectMembersList/ProjectMembersList";
import NewMember from "../NewMember/NewMember";
const FullProject = () => {
......
......@@ -2,7 +2,7 @@ import {useNavigate} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import { useEffect } from "react";
import ProjectForm from "../../components/ProjectForm/ProjectForm";
import ProjectForm from "../../components/ProjectComponents/ProjectForm/ProjectForm";
import { createMember, createProject, fetchMembers, fetchProjects } from "../../store/actions/projectsActions";
import MemberForm from "../../components/MemberForm/MemberForm";
......
......@@ -2,7 +2,7 @@ import {useNavigate} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import { useEffect } from "react";
import ProjectForm from "../../components/ProjectForm/ProjectForm";
import ProjectForm from "../../components/ProjectComponents/ProjectForm/ProjectForm";
import { createProject, fetchProjects } from "../../store/actions/projectsActions";
const NewProject = () => {
......
......@@ -5,7 +5,7 @@ import { useDispatch, useSelector } from "react-redux";
import Loader from "../../components/UI/Loader/Loader";
import HasAccess from "../../components/UI/HasAccess/HasAccess";
import { fetchProjects } from "../../store/actions/projectsActions";
import ProjectsList from "../../components/ProjectsList/ProjectsList";
import ProjectsList from "../../components/ProjectComponents/ProjectsList/ProjectsList";
import NewProject from "../NewProject/NewProject";
const Projects = () => {
......
......@@ -11,3 +11,7 @@ export const LOGOUT_USER_FAILURE = "LOGOUT_USER_FAILURE";
export const FETCH_USERS_REQUEST = "FETCH_USERS_REQUEST";
export const FETCH_USERS_SUCCESS = "FETCH_USERS_SUCCESS";
export const FETCH_USERS_FAILURE = "FETCH_USERS_FAILURE";
export const FETCH_USERS_ALL_FIELDS_REQUEST = "FETCH_USERS_ALL_FIELDS_REQUEST";
export const FETCH_USERS_ALL_FIELDS_SUCCESS = "FETCH_USERS_ALL_FIELDS_SUCCESS";
export const FETCH_USERS_ALL_FIELDS_FAILURE = "FETCH_USERS_ALL_FIELDS_FAILURE";
\ No newline at end of file
import axios from "../../axiosPlanner";
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS, LOGIN_USER_FAILURE, LOGIN_USER_SUCCESS, LOGOUT_USER_FAILURE, LOGOUT_USER_SUCCESS, REGISTER_USER_FAILURE, REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS } from "../actionTypes/userActionTypes"
import { FETCH_USERS_FAILURE, FETCH_USERS_REQUEST, FETCH_USERS_SUCCESS, LOGIN_USER_FAILURE, LOGIN_USER_SUCCESS, LOGOUT_USER_FAILURE, LOGOUT_USER_SUCCESS, REGISTER_USER_FAILURE, REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS,FETCH_USERS_ALL_FIELDS_REQUEST,
FETCH_USERS_ALL_FIELDS_SUCCESS,
FETCH_USERS_ALL_FIELDS_FAILURE, } from "../actionTypes/userActionTypes"
import { showNotification } from "./commonActions";
const registerUserRequest = () => {
......@@ -24,6 +26,16 @@ const fetchUsersFailure = () => {
return {type: FETCH_USERS_FAILURE}
};
const fetchUsersAllFieldsRequest = () => {
return {type: FETCH_USERS_ALL_FIELDS_REQUEST}
};
const fetchUsersAllFieldsSuccess = (users) => {
return {type: FETCH_USERS_ALL_FIELDS_SUCCESS, users}
};
const fetchUsersAllFieldsFailure = () => {
return {type: FETCH_USERS_ALL_FIELDS_FAILURE}
};
export const registerUser = (userData, navigate) => {
return async (dispatch) => {
dispatch(registerUserRequest());
......@@ -71,7 +83,7 @@ export const loginUser = (userData, navigate) => {
export const forgottenPassword = (userData, navigate) => {
return async (dispatch) => {
try {
console.log(userData)
console.log( 'forgottenPassword userData ',userData)
const response = await axios.post("users/requestPasswordReset", userData);
// if (userData.email === response.data.email) {
......@@ -110,3 +122,17 @@ export const fetchUsers = () => {
}
}
};
export const fetchUsersAllFields = () => {
return async dispatch => {
dispatch(fetchUsersAllFieldsRequest());
try {
const response = await axios.get("/users/all-fields/");
dispatch(fetchUsersAllFieldsSuccess(response.data.users));
} catch (e) {
dispatch(fetchUsersAllFieldsFailure(e));
}
}
};
import { REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE, LOGIN_USER_SUCCESS, LOGIN_USER_FAILURE, LOGOUT_USER_SUCCESS, FETCH_USERS_SUCCESS } from "../actionTypes/userActionTypes";
import { REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE, LOGIN_USER_SUCCESS, LOGIN_USER_FAILURE, LOGOUT_USER_SUCCESS, FETCH_USERS_SUCCESS,FETCH_USERS_ALL_FIELDS_SUCCESS } from "../actionTypes/userActionTypes";
const initialState = {
user: null,
users: [],
usersAllFields:[],
registerError: null,
loginError: null,
loading: false
......@@ -27,6 +28,8 @@ const usersReducer = (state = initialState, action) => {
return {...state, user: null};
case FETCH_USERS_SUCCESS:
return {...state, loading: false, users: action.users};
case FETCH_USERS_ALL_FIELDS_SUCCESS:
return {...state, loading: false, usersAllFields: action.users};
default:
return state;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment