Commit fd84e490 authored by Ermolaev Timur's avatar Ermolaev Timur

#141 реализовал драг энд дроп

parent c3e7626b
...@@ -173,6 +173,7 @@ router.delete('/remove-user/:userId', authAdminProject,async (req: Request, res: ...@@ -173,6 +173,7 @@ router.delete('/remove-user/:userId', authAdminProject,async (req: Request, res:
router.put('/change-project-role/:userId',authAdminProject, async (req: Request, res: Response):Promise<Response|void> =>{ router.put('/change-project-role/:userId',authAdminProject, async (req: Request, res: Response):Promise<Response|void> =>{
const {userId}= req.params const {userId}= req.params
const {projectId, newRoleProject} =req.body const {projectId, newRoleProject} =req.body
const member = await dataSource const member = await dataSource
.createQueryBuilder() .createQueryBuilder()
.select("member") .select("member")
...@@ -191,6 +192,7 @@ router.put('/change-project-role/:userId',authAdminProject, async (req: Request ...@@ -191,6 +192,7 @@ router.put('/change-project-role/:userId',authAdminProject, async (req: Request
return res.send({message:"failed to change role"}) return res.send({message:"failed to change role"})
} }
return res.send({message:"User's new role ", newRoleProject}) return res.send({message:"User's new role ", newRoleProject})
}) })
export default router; export default router;
...@@ -2,6 +2,7 @@ import { Box, Typography } from "@mui/material"; ...@@ -2,6 +2,7 @@ import { Box, Typography } from "@mui/material";
import moment from "moment"; import moment from "moment";
import { memo } from "react"; import { memo } from "react";
import PersonAddIcon from '@mui/icons-material/PersonAdd'; import PersonAddIcon from '@mui/icons-material/PersonAdd';
import ArrowIncrementButton from "../../UI/ArrowIncrementButton/ArrowIncrementButton";
const style = { const style = {
display: 'flex', display: 'flex',
...@@ -16,7 +17,7 @@ const styleText = { ...@@ -16,7 +17,7 @@ const styleText = {
} }
const ProjectInfo = ({ project, handleOpen, currentRoleInProject }) => { const ProjectInfo = ({ project, handleOpen, currentRoleInProject,onClickTasksHandler }) => {
return ( return (
<Box sx={style} justifyContent={'space-between'}> <Box sx={style} justifyContent={'space-between'}>
<Typography variant="h2">Проект - {project?.title} </Typography> <Typography variant="h2">Проект - {project?.title} </Typography>
...@@ -33,7 +34,7 @@ const ProjectInfo = ({ project, handleOpen, currentRoleInProject }) => { ...@@ -33,7 +34,7 @@ const ProjectInfo = ({ project, handleOpen, currentRoleInProject }) => {
Роль в проекте: {currentRoleInProject} Роль в проекте: {currentRoleInProject}
</Typography> </Typography>
<Typography variant="body1" sx={styleText}> <Typography variant="body1" sx={styleText}>
Задачи: Задачи: <ArrowIncrementButton onClick={()=>{onClickTasksHandler()}}/>
</Typography> </Typography>
{currentRoleInProject === 'admin' ? {currentRoleInProject === 'admin' ?
<Typography variant="body1" sx={styleText}> <Typography variant="body1" sx={styleText}>
......
...@@ -5,7 +5,7 @@ import { memo } from "react"; ...@@ -5,7 +5,7 @@ import { memo } from "react";
const ColumnTitle = ({ text }) => { const ColumnTitle = ({ text }) => {
return <> return <>
<Typography variant="h4" textAlign={'center'} sx={{ marginBottom: '20px' }}> <Typography variant="h4" textAlign={'center'} sx={{ height: '10%' }}>
{text} {text}
</Typography> </Typography>
</> </>
......
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { memo } from "react"; import { memo} from "react";
import ColumnTitle from "./ColumnTitle/ColumnTitle"; import ColumnTitle from "./ColumnTitle/ColumnTitle";
import UsersList from "./UsersList/UserList"; import UsersList from "./UsersList/UserList";
...@@ -13,9 +13,13 @@ const styleColumn = { ...@@ -13,9 +13,13 @@ const styleColumn = {
} }
const ProjectUsersColumn = ({ role, members, deleteMemberHandler, currentRoleInProject }) => { const ProjectUsersColumn = ({ role, members, deleteMemberHandler, currentRoleInProject, dragMemberToNewRole, setCurrentMember }) => {
return ( return (
<Box sx={styleColumn}> <Box
sx={styleColumn}
>
<ColumnTitle text={role.text} /> <ColumnTitle text={role.text} />
<UsersList <UsersList
...@@ -23,6 +27,8 @@ const ProjectUsersColumn = ({ role, members, deleteMemberHandler, currentRoleInP ...@@ -23,6 +27,8 @@ const ProjectUsersColumn = ({ role, members, deleteMemberHandler, currentRoleInP
members={members} members={members}
deleteMemberHandler={deleteMemberHandler} deleteMemberHandler={deleteMemberHandler}
currentRoleInProject={currentRoleInProject} currentRoleInProject={currentRoleInProject}
dragMemberToNewRole={dragMemberToNewRole}
setCurrentMember={setCurrentMember}
> >
</UsersList> </UsersList>
</Box> </Box>
......
...@@ -13,10 +13,40 @@ const style = { ...@@ -13,10 +13,40 @@ const style = {
alignItems: 'center' alignItems: 'center'
} }
const ProjectMembersItem = ({ user, deleteMemberHandler, currentRoleInProject }) => { const ProjectMembersItem = ({ user, deleteMemberHandler, currentRoleInProject, dragMemberToNewRole, setCurrentMember, role }) => {
const userId = useSelector(state => state.users.user.id); const userId = useSelector(state => state.users.user.id);
const dragStartHandler = (e) => {
setCurrentMember(user)
}
const dragEndHandler = (e) => {
setCurrentMember(null)
}
const dragOverHandler = (e) => {
e.preventDefault();
}
const dropHandler = (e) => {
e.preventDefault();
dragMemberToNewRole(role)
}
const dragLeaveHandler = (e) => {
e.preventDefault();
}
return <> return <>
<Grid sx={style}> <Grid sx={style}
draggable={user.id !== userId ? true : false}
onDragStart={(e) => { dragStartHandler(e) }}
onDragEnd={(e) => { dragEndHandler(e) }}
onDrop={(e) => { dropHandler(e) }}
onDragOver={(e) => { dragOverHandler(e) }}
onDragLeave={(e) => { dragLeaveHandler(e) }}
>
{user?.displayName} {user?.displayName}
{currentRoleInProject === 'admin' && user.id !== userId ? {currentRoleInProject === 'admin' && user.id !== userId ?
<DeleteIcon <DeleteIcon
......
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { memo } from "react"; import { memo, useCallback } from "react";
import UserItem from "./UserItem/UserItem"; import UserItem from "./UserItem/UserItem";
const styleList = { const styleList = {
...@@ -7,11 +7,35 @@ const styleList = { ...@@ -7,11 +7,35 @@ const styleList = {
gap: '10px', gap: '10px',
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
height: '90%',
} }
const UsersList = ({ role, members, deleteMemberHandler, currentRoleInProject }) => { const UsersList = ({ role, members, deleteMemberHandler, currentRoleInProject, dragMemberToNewRole, setCurrentMember }) => {
const dropHandler = (e) => {
e.preventDefault();
e.target.style.background = null
setCurrentMember(null)
dragMemberToNewRole(role)
}
const dragOverHandler = useCallback((e) => {
e.preventDefault();
e.target.style.background = '#d6d2d2'
}, [])
const dragLeaveHandler = useCallback((e) => {
e.preventDefault();
e.target.style.background = null
}, [])
return ( return (
<Box sx={styleList}> <Box
sx={styleList}
onDrop={(e) => { dropHandler(e) }}
onDragOver={(e) => { dragOverHandler(e) }}
onDragLeave={(e) => { dragLeaveHandler(e) }}
>
{members.map((member) => { {members.map((member) => {
if (member.roleProject === role.value) { if (member.roleProject === role.value) {
return ( return (
...@@ -19,7 +43,10 @@ const UsersList = ({ role, members, deleteMemberHandler, currentRoleInProject }) ...@@ -19,7 +43,10 @@ const UsersList = ({ role, members, deleteMemberHandler, currentRoleInProject })
key={member.id} key={member.id}
user={member?.user} user={member?.user}
deleteMemberHandler={() => { deleteMemberHandler(member?.user?.id) }} deleteMemberHandler={() => { deleteMemberHandler(member?.user?.id) }}
role={role.value}
currentRoleInProject={currentRoleInProject} currentRoleInProject={currentRoleInProject}
dragMemberToNewRole={dragMemberToNewRole}
setCurrentMember={setCurrentMember}
/> />
) )
} else { } else {
......
...@@ -13,7 +13,7 @@ const style = { ...@@ -13,7 +13,7 @@ const style = {
} }
const ProjectUsersColumnsWrapper = ({ members, deleteMemberHandler, currentRoleInProject }) => { const ProjectUsersColumnsWrapper = ({ members, deleteMemberHandler, currentRoleInProject, dragMemberToNewRole, setCurrentMember}) => {
return ( return (
<Box sx={style} justifyContent={'space-between'}> <Box sx={style} justifyContent={'space-between'}>
{projectRoles.map((role, i) => { {projectRoles.map((role, i) => {
...@@ -24,6 +24,8 @@ const ProjectUsersColumnsWrapper = ({ members, deleteMemberHandler, currentRoleI ...@@ -24,6 +24,8 @@ const ProjectUsersColumnsWrapper = ({ members, deleteMemberHandler, currentRoleI
members={members} members={members}
deleteMemberHandler={deleteMemberHandler} deleteMemberHandler={deleteMemberHandler}
currentRoleInProject={currentRoleInProject} currentRoleInProject={currentRoleInProject}
dragMemberToNewRole={dragMemberToNewRole}
setCurrentMember={setCurrentMember}
/> />
) )
})} })}
......
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import { useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux"; import { useSelector, useDispatch } from "react-redux";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { createMember, deleteMember, fetchProject } from "../../store/actions/projectsActions"; import { changeMemberRole, createMember, deleteMember, fetchProject } from "../../store/actions/projectsActions";
import { fetchUsers, fetchUsersAllFields } from "../../store/actions/usersActions"; import { fetchUsers } from "../../store/actions/usersActions";
import ProjectUsersColumnsWrapper from "../../components/ProjectComponents/ProjectUsersColumnsWrapper/ProjectUsersColumnsWrapper"; import ProjectUsersColumnsWrapper from "../../components/ProjectComponents/ProjectUsersColumnsWrapper/ProjectUsersColumnsWrapper";
import ProjectInfo from "../../components/ProjectComponents/ProjectInfo/ProjectInfo"; import ProjectInfo from "../../components/ProjectComponents/ProjectInfo/ProjectInfo";
import DefaultModal from "../../components/UI/DefaultModal/DefaultModal" import DefaultModal from "../../components/UI/DefaultModal/DefaultModal"
...@@ -16,10 +16,12 @@ const FullProject = () => { ...@@ -16,10 +16,12 @@ const FullProject = () => {
const { project } = useSelector(state => state.projects); const { project } = useSelector(state => state.projects);
const [modal, setModal] = useState(false) const [modal, setModal] = useState(false)
const [newMember, setNewMember] = useState(null) const [newMember, setNewMember] = useState(null)
const [currentMember, setCurrentMember] = useState(null)
const { user, users } = useSelector(state => state.users); const { user, users } = useSelector(state => state.users);
const dispatch = useDispatch(); const dispatch = useDispatch();
const params = useParams() const params = useParams()
const navigate = useNavigate()
useEffect(() => { useEffect(() => {
dispatch(fetchProject(params.id)) dispatch(fetchProject(params.id))
...@@ -30,10 +32,10 @@ const FullProject = () => { ...@@ -30,10 +32,10 @@ const FullProject = () => {
return project?.project?.members || [] return project?.project?.members || []
}, [project]) }, [project])
const currentRoleInProject = useMemo(()=>{ const currentRoleInProject = useMemo(() => {
return members.find((member) => member.user.id === user.id)?.roleProject return members.find((member) => member.user.id === user.id)?.roleProject
}, [members, user.id]) }, [members, user.id])
const onChangeRoleHandler = useCallback((e, value) => { const onChangeRoleHandler = useCallback((e, value) => {
setNewMember((prevState) => { return { ...prevState, roleProject: value?.value } }); setNewMember((prevState) => { return { ...prevState, roleProject: value?.value } });
}, []); }, []);
...@@ -51,16 +53,26 @@ const FullProject = () => { ...@@ -51,16 +53,26 @@ const FullProject = () => {
setNewMember(null) setNewMember(null)
}, []) }, [])
const createNewMemberHandler = useCallback(()=>{ const createNewMemberHandler = useCallback(() => {
dispatch(createMember({...newMember, projectId: project?.project?.id})) dispatch(createMember({ ...newMember, projectId: project?.project?.id }))
setModal(false) setModal(false)
setNewMember(null) setNewMember(null)
}, [dispatch, newMember, project?.project?.id]) }, [dispatch, newMember, project?.project?.id])
const deleteMemberHandler = useCallback((id)=>{ const dragMemberToNewRole = useCallback((role) => {
if (currentMember?.id) {
dispatch(changeMemberRole(currentMember?.id, { newRoleProject: role?.value, projectId: project?.project?.id }))
}
}, [currentMember, dispatch, project?.project?.id])
const deleteMemberHandler = useCallback((id) => {
dispatch(deleteMember(id, project?.project?.id)) dispatch(deleteMember(id, project?.project?.id))
}, [dispatch, project?.project?.id]) }, [dispatch, project?.project?.id])
const onClickTasksHandler = useCallback((id) => {
navigate('/workers-tasks')
}, [navigate])
return <> return <>
<Grid> <Grid>
...@@ -68,12 +80,15 @@ const FullProject = () => { ...@@ -68,12 +80,15 @@ const FullProject = () => {
project={project.project} project={project.project}
handleOpen={handleOpen} handleOpen={handleOpen}
currentRoleInProject={currentRoleInProject} currentRoleInProject={currentRoleInProject}
onClickTasksHandler={onClickTasksHandler}
/> />
<ProjectUsersColumnsWrapper <ProjectUsersColumnsWrapper
members={members} members={members}
deleteMemberHandler={deleteMemberHandler} deleteMemberHandler={deleteMemberHandler}
currentRoleInProject={currentRoleInProject} currentRoleInProject={currentRoleInProject}
dragMemberToNewRole={dragMemberToNewRole}
setCurrentMember={setCurrentMember}
/> />
<DefaultModal <DefaultModal
......
...@@ -15,4 +15,8 @@ export const FETCH_ALL_USER_PROJECTS_SUCCESS = "FETCH_ALL_USER_PROJECTS_SUCCESS" ...@@ -15,4 +15,8 @@ export const FETCH_ALL_USER_PROJECTS_SUCCESS = "FETCH_ALL_USER_PROJECTS_SUCCESS"
export const DELETE_PROJECT_REQUEST = "DELETE_PROJECT_REQUEST"; export const DELETE_PROJECT_REQUEST = "DELETE_PROJECT_REQUEST";
export const DELETE_PROJECT_SUCCESS = "DELETE_PROJECT_SUCCESS"; export const DELETE_PROJECT_SUCCESS = "DELETE_PROJECT_SUCCESS";
export const DELETE_PROJECT_FAILURE = "DELETE_PROJECT_FAILURE"; export const DELETE_PROJECT_FAILURE = "DELETE_PROJECT_FAILURE";
\ No newline at end of file
export const CHANGE_MEMBER_ROLE_REQUEST = "CHANGE_MEMBER_ROLE_REQUEST";
export const CHANGE_MEMBER_ROLE_SUCCESS = "CHANGE_MEMBER_ROLE_SUCCESS";
export const CHANGE_MEMBER_ROLE_FAILURE = "CHANGE_MEMBER_ROLE_FAILURE";
\ No newline at end of file
import axios from "../../axiosPlanner"; import axios from "../../axiosPlanner";
import { CREATE_MEMBER_SUCCESS, CREATE_PROJECT_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, DELETE_PROJECT_FAILURE, DELETE_PROJECT_REQUEST, DELETE_PROJECT_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes"; import { CHANGE_MEMBER_ROLE_FAILURE, CHANGE_MEMBER_ROLE_REQUEST, CHANGE_MEMBER_ROLE_SUCCESS, CREATE_MEMBER_SUCCESS, CREATE_PROJECT_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, DELETE_PROJECT_FAILURE, DELETE_PROJECT_REQUEST, DELETE_PROJECT_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import { showNotification } from "./commonActions"; import { showNotification } from "./commonActions";
const fetchProjectsRequest = () => { const fetchProjectsRequest = () => {
...@@ -141,3 +141,29 @@ export const fetchAllUserProjects = () => { ...@@ -141,3 +141,29 @@ export const fetchAllUserProjects = () => {
} }
} }
const changeMemberRoleFailure = (error) => {
return { type: CHANGE_MEMBER_ROLE_FAILURE, error }
};
const changeMemberRoleRequest = () => {
return { type: CHANGE_MEMBER_ROLE_REQUEST }
};
const changeMemberRoleSuccess = () => {
return { type: CHANGE_MEMBER_ROLE_SUCCESS }
};
export const changeMemberRole = (userId, data) => {
return async (dispatch) => {
dispatch(changeMemberRoleSuccess());
try {
const response = await axios.put(`/projects/change-project-role/${userId}`, data);
console.log(response.data)
dispatch(changeMemberRoleRequest());
await dispatch(fetchProject(data?.projectId))
} catch (e) {
dispatch(changeMemberRoleFailure(e));
}
}
}
import { DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, DELETE_PROJECT_FAILURE, DELETE_PROJECT_REQUEST, DELETE_PROJECT_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes"; import { CHANGE_MEMBER_ROLE_FAILURE, CHANGE_MEMBER_ROLE_REQUEST, CHANGE_MEMBER_ROLE_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, DELETE_PROJECT_FAILURE, DELETE_PROJECT_REQUEST, DELETE_PROJECT_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
const initialState = { const initialState = {
allUserProjectsForModalTask: [], allUserProjectsForModalTask: [],
...@@ -32,10 +32,16 @@ const projectsReducer = (state = initialState, action) => { ...@@ -32,10 +32,16 @@ const projectsReducer = (state = initialState, action) => {
case DELETE_PROJECT_FAILURE: case DELETE_PROJECT_FAILURE:
return { ...state, loading: false, error: action.error }; return { ...state, loading: false, error: action.error };
case FETCH_ALL_USER_PROJECTS_SUCCESS: case FETCH_ALL_USER_PROJECTS_SUCCESS:
const newArr = action.projects.map((project)=>{ const newArr = action.projects.map((project) => {
return {value: project.id, text: project.title} return { value: project.id, text: project.title }
}) })
return { ...state, loading: false, allUserProjects: action.projects, allUserProjectsForModalTask: newArr} return { ...state, loading: false, allUserProjects: action.projects, allUserProjectsForModalTask: newArr }
case CHANGE_MEMBER_ROLE_SUCCESS:
return { ...state, loading: false };
case CHANGE_MEMBER_ROLE_REQUEST:
return { ...state, loading: true };
case CHANGE_MEMBER_ROLE_FAILURE:
return { ...state, loading: false, error: action.error };
default: default:
return state; 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