Commit 0fe75260 authored by Ermolaev Timur's avatar Ermolaev Timur

#103 Реализовал возможность перехода в чужой календарь и возвращения назад

parent 61d26665
...@@ -52,7 +52,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response ...@@ -52,7 +52,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response
.find({ .find({
relations:{ relations:{
executor:true, executor:true,
author:true,
}, },
where:[ where:[
{ {
...@@ -60,11 +59,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response ...@@ -60,11 +59,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response
id:userId id:userId
} }
}, },
{
author:{
id:userId
}
},
] ]
}) })
return res.send({tasks}) return res.send({tasks})
......
import {Routes, Route, Outlet, Navigate, BrowserRouter} from "react-router-dom"; import { Routes, Route, Outlet, Navigate, BrowserRouter } from "react-router-dom";
import {Container} from "@mui/material"; import { Container } from "@mui/material";
import {useSelector} from "react-redux"; import { useSelector } from "react-redux";
import AppToolbar from "./components/UI/AppToolBar/AppToolBar"; import AppToolbar from "./components/UI/AppToolBar/AppToolBar";
import MyTasks from './containers/MyTasks/MyTasks'; import MyTasks from './containers/MyTasks/MyTasks';
import Login from './containers/Login/Login'; import Login from './containers/Login/Login';
...@@ -12,116 +12,134 @@ import FullProject from "./containers/FullProject/FullProject"; ...@@ -12,116 +12,134 @@ import FullProject from "./containers/FullProject/FullProject";
import NewProject from "./containers/NewProject/NewProject"; import NewProject from "./containers/NewProject/NewProject";
import WeekCalendar from "./containers/WeekCalendar/WeekCalendar"; import WeekCalendar from "./containers/WeekCalendar/WeekCalendar";
const ProtectedRoute = ({isAllowed, roles, redirectUrl, children}) => { const ProtectedRoute = ({ isAllowed, roles, redirectUrl, children }) => {
const user = useSelector(state => state.users?.user); const user = useSelector(state => state.users?.user);
if (!isAllowed && !roles?.includes(user?.role)) { if (!isAllowed && !roles?.includes(user?.role)) {
return <Navigate to={redirectUrl} /> return <Navigate to={redirectUrl} />
} }
return children || <Outlet />; return children || <Outlet />;
}; };
const App = () => { const App = () => {
const user = useSelector(state => state.users?.user); const user = useSelector(state => state.users?.user);
return ( return (
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
<Route element={ <Route element={
<> <>
<AppToolbar/> <AppToolbar />
<main> <main>
<Container maxWidth={false} sx={{maxWidth:'2500px'}}> <Container maxWidth={false} sx={{ maxWidth: '2500px' }}>
<Outlet/> <Outlet />
</Container> </Container>
</main> </main>
</> </>
}> }>
<Route path={"/projects"} element={ <Route path={"/projects"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<Projects/> <Projects />
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/projects/:id"} element={ <Route path={"/projects/:id"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<FullProject/> <FullProject />
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/"} element={ <Route path={"/"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<WeekCalendar/> <WeekCalendar />
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/week"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar />
</ProtectedRoute>
} />
<Route path={"/week/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar />
</ProtectedRoute>
} />
<Route path={"/week"} element={ <Route path={"/month"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<WeekCalendar/> <MonthCalendar></MonthCalendar>
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/month"} element={ <Route path={"/month/:id"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<MonthCalendar></MonthCalendar> <MonthCalendar></MonthCalendar>
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/my-tasks"} element={ <Route path={"/my-tasks"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<MyTasks/> <MyTasks />
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/profile/:id"} element={ <Route path={"/profile/:id"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
redirectUrl={"/sign-in"} redirectUrl={"/sign-in"}
> >
<h1>profile page</h1> <h1>profile page</h1>
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/workers-tasks"} element={ <Route path={"/workers-tasks"} element={
<ProtectedRoute <ProtectedRoute
roles={["superuser"]} roles={["superuser"]}
redirectUrl={"/"} redirectUrl={"/"}
> >
<h1>workers tasks page</h1> <h1>workers tasks page</h1>
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/sign-up"} element={ <Route path={"/sign-up"} element={
<ProtectedRoute <ProtectedRoute
roles={["superuser"]} roles={["superuser"]}
redirectUrl={"/"} redirectUrl={"/"}
> >
<Register/> <Register />
</ProtectedRoute> </ProtectedRoute>
}/> } />
<Route path={"/sign-in"} element={<Login/>}/> <Route path={"/sign-in"} element={<Login />} />
<Route path={"/forgottenpassword"} element={<ForgottenPassword/>}/> <Route path={"/forgottenpassword"} element={<ForgottenPassword />} />
<Route path='*' element={<h1>404</h1>}/> <Route path='*' element={<h1>404</h1>} />
</Route> </Route>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
) )
}; };
export default App; export default App;
......
import { Autocomplete, TextField } from "@mui/material"; import { Autocomplete, Button, TextField } from "@mui/material";
import { memo } from "react"; import { memo } from "react";
function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, workerInfo }) { function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, onChangeWorkerHandler, workerInfo, workers, handleClose, onChangeCalendarUser}) {
console.log(workerInfo)
return (<> return (<>
<Autocomplete <Autocomplete
id="choose-project" id="choose-project"
...@@ -11,30 +10,36 @@ function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, w ...@@ -11,30 +10,36 @@ function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, w
options={allUserProjects} options={allUserProjects}
getOptionLabel={(item) => item.title || ""} getOptionLabel={(item) => item.title || ""}
onChange={onChangeProjectHandler} onChange={onChangeProjectHandler}
name={"userId"} name={"project"}
value={workerInfo.project} value={workerInfo.project}
renderInput={(params) => <TextField renderInput={(params) => <TextField
style={{ margin: "5px" }} style={{ marginBottom: "15px" }}
label={"Проект"} label={"Проект"}
state={workerInfo.project} state={workerInfo.project}
{...params} />} {...params} />}
/> />
{workerInfo.project ? {workerInfo.project ?
<Autocomplete <>
id="choose-worker" <Autocomplete
freeSolo id="choose-worker"
options={allUserProjects} freeSolo
getOptionLabel={(item) => item.title || ""} options={workers}
onChange={(e, value)=>{ onChangeProjectHandler(e, value)}} getOptionLabel={(item) => item?.user?.displayName || ""}
name={"userId"} onChange={(e, value) => { onChangeWorkerHandler(e, value) }}
value={workerInfo.project} name={"worker"}
renderInput={(params) => <TextField value={workerInfo.worker}
style={{ margin: "5px" }} renderInput={(params) => <TextField
label={"Проект"} label={"Участник"}
state={workerInfo.project} state={workerInfo.worker}
{...params} />} {...params} />}
/> />
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '10px 0' }}>
<Button onClick={()=>{onChangeCalendarUser()}} >Выбрать</Button>
<Button onClick={() => handleClose()}>Отмена</Button>
</div>
</>
: null} : null}
</>); </>);
} }
......
...@@ -2,7 +2,7 @@ import { AppBar, Button, Toolbar, Typography } from '@mui/material'; ...@@ -2,7 +2,7 @@ import { AppBar, Button, Toolbar, Typography } from '@mui/material';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import MonthAndYearInfo from './MonthAndYearInfo/MonthAndYearInfo'; import MonthAndYearInfo from './MonthAndYearInfo/MonthAndYearInfo';
function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMonth, year, handleOpen, currentCalendarDisplayName }) { function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMonth, year, handleOpen, currentCalendarDisplayName, user, userId}) {
return ( return (
<> <>
...@@ -27,7 +27,7 @@ function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMont ...@@ -27,7 +27,7 @@ function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMont
size="large" size="large"
sx={{ marginLeft: 'auto' }} sx={{ marginLeft: 'auto' }}
> >
Выбрать сотрудника {user.id === userId ? 'Выбрать сотрудника' : 'Вернуться назад'}
</Button> </Button>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
......
...@@ -13,7 +13,7 @@ const style = { ...@@ -13,7 +13,7 @@ const style = {
bgcolor: 'background.paper', bgcolor: 'background.paper',
border: '2px solid #000', border: '2px solid #000',
boxShadow: 24, boxShadow: 24,
p: 4, p: 2
}; };
export default function DefaultModal({ modal, handleClose, children }) { export default function DefaultModal({ modal, handleClose, children }) {
......
import { useEffect, useCallback, useState, useMemo } from 'react'; import { useEffect, useCallback, useState, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import CalendarModalWorkerContent from '../../components/Calendars/CalendarModalWorkerContent/CalendarModalWorkerContent'; import CalendarModalWorkerContent from '../../components/Calendars/CalendarModalWorkerContent/CalendarModalWorkerContent';
import MonthCalendarBody from '../../components/Calendars/MonthCalendar/MonthCalendarBody/MonthCalendarBody'; import MonthCalendarBody from '../../components/Calendars/MonthCalendar/MonthCalendarBody/MonthCalendarBody';
import MonthCalendarHeader from '../../components/Calendars/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader'; import MonthCalendarHeader from '../../components/Calendars/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader';
import DefaultModal from '../../components/UI/DefaultModal/DefaultModal'; import DefaultModal from '../../components/UI/DefaultModal/DefaultModal';
import { dateToISOLikeButLocal, getCurrentMonthString, getDaysInMonth } from '../../helpers/CalendarHelpers'; import { dateToISOLikeButLocal, getCurrentMonthString, getDaysInMonth } from '../../helpers/CalendarHelpers';
import { fetchAllUserProjects } from '../../store/actions/projectsActions'; import { fetchAllUserProjects, fetchProject } from '../../store/actions/projectsActions';
import { addCalendarTask, addCopyCalendarTask, deleteCalendarTask, editCalendarTask, fetchCalendarTasks } from '../../store/actions/tasksActions'; import { addCalendarTask, addCopyCalendarTask, deleteCalendarTask, editCalendarTask, fetchCalendarTasks } from '../../store/actions/tasksActions';
import { fetchCurrentCalendarDisplayName } from '../../store/actions/usersActions'; import { fetchCurrentCalendarDisplayName } from '../../store/actions/usersActions';
function MonthCalendar() { function MonthCalendar() {
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate()
const { calendarTasks } = useSelector(state => state.tasks); const { calendarTasks } = useSelector(state => state.tasks);
const { user, currentCalendarDisplayName } = useSelector(state => state.users); const { user, currentCalendarDisplayName } = useSelector(state => state.users);
const { allUserProjects } = useSelector(state => state.projects) const { allUserProjects, project } = useSelector(state => state.projects)
const params = useParams() const params = useParams()
const [hourFormat, setHourFormat] = useState(false); const [hourFormat, setHourFormat] = useState(false);
const [dateNow, setDateNow] = useState({ month: '', year: '' }) const [dateNow, setDateNow] = useState({ month: '', year: '' })
const [workerInfo, setWorkerInfo] = useState({project: '', worker: ''}); const [workerInfo, setWorkerInfo] = useState({ project: '', worker: '' });
const [currentTask, setCurrentTask] = useState({ title: '', description: '', priority: null, infoForCell: { startHour: null, endHour: null } }) const [currentTask, setCurrentTask] = useState({ title: '', description: '', priority: null, infoForCell: { startHour: null, endHour: null } })
const [copyTask, setCopyTask] = useState(null) const [copyTask, setCopyTask] = useState(null)
const [cellSizes, setCellSizes] = useState({}) const [cellSizes, setCellSizes] = useState({})
...@@ -42,6 +43,11 @@ function MonthCalendar() { ...@@ -42,6 +43,11 @@ function MonthCalendar() {
} }
}, [dispatch]) }, [dispatch])
useEffect(() => {
if (workerInfo.project) {
dispatch(fetchProject(workerInfo.project.id))
}
}, [workerInfo.project])
const hoursInDay = useMemo(() => { const hoursInDay = useMemo(() => {
let arr let arr
...@@ -67,10 +73,11 @@ function MonthCalendar() { ...@@ -67,10 +73,11 @@ function MonthCalendar() {
}, [dateNow.month]) }, [dateNow.month])
const onChangeProjectHandler = useCallback((e, value) => { const onChangeProjectHandler = useCallback((e, value) => {
setWorkerInfo((prevState)=>{return {...prevState, project: value}}); setWorkerInfo((prevState) => { return { ...prevState, project: value } });
}, []); }, []);
const onChangeWorkerHandler = useCallback((e, value) => { const onChangeWorkerHandler = useCallback((e, value) => {
setWorkerInfo((prevState)=>{return {...prevState, worker: value}}); setWorkerInfo((prevState) => { return { ...prevState, worker: value } });
}, []); }, []);
const incrementMonth = useCallback(() => { const incrementMonth = useCallback(() => {
...@@ -182,7 +189,8 @@ function MonthCalendar() { ...@@ -182,7 +189,8 @@ function MonthCalendar() {
...currentTask, ...currentTask,
dateTimeStart: start, dateTimeStart: start,
dateTimeDue: due, dateTimeDue: due,
executor: user, executor: userId,
author: user.id,
dateTimeDeadLine: due, dateTimeDeadLine: due,
} }
delete newTask.infoForCell delete newTask.infoForCell
...@@ -190,6 +198,7 @@ function MonthCalendar() { ...@@ -190,6 +198,7 @@ function MonthCalendar() {
await dispatch(addCalendarTask(newTask, userId)) await dispatch(addCalendarTask(newTask, userId))
} }
} }
console.log(userId)
const createCopyTask = async (dayNumber, hour) => { const createCopyTask = async (dayNumber, hour) => {
const hourDiff = copyTask.infoForCell.endHour - copyTask.infoForCell.startHour const hourDiff = copyTask.infoForCell.endHour - copyTask.infoForCell.startHour
...@@ -219,10 +228,26 @@ function MonthCalendar() { ...@@ -219,10 +228,26 @@ function MonthCalendar() {
const handleClose = () => { const handleClose = () => {
setModal(false) setModal(false)
setWorkerInfo({ project: '', worker: '' })
} }
const handleOpen = async () => { const handleOpen = async () => {
await dispatch(fetchAllUserProjects()) if (user.id === userId) {
setModal(true) await dispatch(fetchAllUserProjects())
setModal(true)
} else {
navigate("/month")
setWorkerInfo({ project: '', worker: '' })
setUserId(user.id)
dispatch(fetchCalendarTasks(user.id))
dispatch(fetchCurrentCalendarDisplayName(user.id))
}
}
const onChangeCalendarUser = () => {
navigate(`/month/${workerInfo.worker.user.id}`)
setModal(false)
setUserId(workerInfo.worker.user.id)
dispatch(fetchCalendarTasks(workerInfo.worker.user.id))
dispatch(fetchCurrentCalendarDisplayName(workerInfo.worker.user.id))
} }
return ( return (
...@@ -234,8 +259,11 @@ function MonthCalendar() { ...@@ -234,8 +259,11 @@ function MonthCalendar() {
<CalendarModalWorkerContent <CalendarModalWorkerContent
workerInfo={workerInfo} workerInfo={workerInfo}
allUserProjects={allUserProjects} allUserProjects={allUserProjects}
workers={project?.project?.members}
onChangeProjectHandler={onChangeProjectHandler} onChangeProjectHandler={onChangeProjectHandler}
onChangeWorkerHandler={onChangeWorkerHandler} onChangeWorkerHandler={onChangeWorkerHandler}
handleClose={handleClose}
onChangeCalendarUser={onChangeCalendarUser}
/> />
</DefaultModal> </DefaultModal>
...@@ -246,6 +274,8 @@ function MonthCalendar() { ...@@ -246,6 +274,8 @@ function MonthCalendar() {
incrementMonth={incrementMonth} incrementMonth={incrementMonth}
handleOpen={handleOpen} handleOpen={handleOpen}
currentCalendarDisplayName={currentCalendarDisplayName} currentCalendarDisplayName={currentCalendarDisplayName}
user={user}
userId={userId}
/> />
<MonthCalendarBody <MonthCalendarBody
month={dateNow.month} month={dateNow.month}
......
...@@ -53,7 +53,7 @@ export const fetchProjects = () => { ...@@ -53,7 +53,7 @@ export const fetchProjects = () => {
dispatch(fetchProjectsRequest()); dispatch(fetchProjectsRequest());
try { try {
const response = await axios.get("/projects"); const response = await axios.get("/projects");
dispatch(fetchProjectsSuccess(response.data)); dispatch(fetchProjectsSuccess(response.data));
} catch(e) { } catch(e) {
dispatch(fetchProjectsError(e)); dispatch(fetchProjectsError(e));
} }
......
...@@ -141,8 +141,7 @@ export const editCalendarTask = (task, taskId, userId) => { ...@@ -141,8 +141,7 @@ export const editCalendarTask = (task, taskId, userId) => {
return async (dispatch) => { return async (dispatch) => {
dispatch(editTaskRequest()); dispatch(editTaskRequest());
try { try {
const response = await axios.put(`/copy-tasks/change-copy/${taskId}`, task); await axios.put(`/copy-tasks/change-copy/${taskId}`, task);
console.log(response.data)
dispatch(editTaskSuccess()) dispatch(editTaskSuccess())
dispatch(fetchCalendarTasks(userId)) dispatch(fetchCalendarTasks(userId))
} catch (error) { } catch (error) {
......
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