Commit 186d716f authored by Ibadullina Inabat's avatar Ibadullina Inabat

Merge branch 'development' of…

Merge branch 'development' of ssh://git.attractor-school.com:30022/apollo64/crm-team-one into task-107-fix/add_checking_front
parents 6df87730 8827bdc4
......@@ -4,12 +4,8 @@ import {
PrimaryGeneratedColumn,
CreateDateColumn,
BaseEntity,
ManyToOne,
ManyToMany,
OneToMany,
JoinTable
} from 'typeorm';
// import {User} from './User';
import {Task} from './Task';
import {Member} from './Member';
......
......@@ -2,30 +2,33 @@ import express,{Router, Request, Response } from 'express';
import {Task} from '../models/Task';
import {myDataSource} from '../app-data-source';
import { DateTimeTask } from '../models/DateTimeTask';
import { auth, authAuthorOrExecutorOfDateTimeTask, authAuthorOrExecutorOfTask,taskFinderById } from '../helpers';
import { info } from 'console';
import { authAuthorOrExecutorOfDateTimeTask, authAuthorOrExecutorOfTask } from '../helpers';
const router:Router = express.Router();
const dataSource = myDataSource;
/** make copy of task in calendar view */
router.post("/make-copy",authAuthorOrExecutorOfTask, async(req:Request, res:Response):Promise<Response>=>{
const {taskId, dateTimeDue, dateTimeStart} = req.body;
const task = await taskFinderById(taskId);
const {taskId, dateTimeDue, dateTimeStart, authorStatus, executorStatus, task} = req.body;
if(!task) return res.status(401).send({message:'task with possible user involved is not found'})
const newDateTimeTask = new DateTimeTask();
newDateTimeTask.dateTimeStart = dateTimeStart;
newDateTimeTask.dateTimeDue = dateTimeDue;
newDateTimeTask.task = taskId;
await newDateTimeTask.save();
return res.send({task})
return res.send({task, message:"copyTask created!"})
} )
/** change date time of copy of task in calendar view */
router.put("/change-copy/:dateTimeTaskId", authAuthorOrExecutorOfTask, async(req:Request, res: Response):Promise<Response>=>{
const {dateTimeTaskId} = req.params
const {executorStatus,authorStatus, task, dateTimeStart, dateTimeDue, description, title, priority} = req.body
if(authorStatus){
task.title = title;
task.description = description;
task.priority= priority;
await task.save()
}
const dateTimeTask = await dataSource
.createQueryBuilder()
.select('dateTimeTask')
......@@ -106,12 +109,10 @@ router.delete('/:dateTimeTaskId',authAuthorOrExecutorOfDateTimeTask, async(req:R
if (dateTimeTasks.length ===1 ) {
if ( authorStatus) {
Task.remove(task)
return res.send({message:"task delete succesfully"})
} else{
return res.send({message:"not uathorized to delete task"})
}
}
}
......
......@@ -117,11 +117,6 @@ router.get('/user/:userId', async (req : Request, res : Response): Promise<Respo
return res.send({userProjects})
})
/** Add user to specific project */
router.post('/add-user/', authAdminProject, async (req: Request, res: Response):Promise<Response>=>{
......
......@@ -2,10 +2,11 @@ import express,{Router, Request, Response } from 'express';
import {Task} from '../models/Task';
import {myDataSource} from '../app-data-source';
import { User } from '../models/User';
import { Member } from '../models/Member';
import { Member, MemberRole } from '../models/Member';
import { In } from 'typeorm';
import { DateTimeTask } from '../models/DateTimeTask';
import { auth, authAuthorOrExecutorOfTask, taskFinderById } from '../helpers';
import { Project } from '../models/Project';
const router:Router = express.Router();
const dataSource = myDataSource;
......@@ -29,7 +30,56 @@ router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
const newTask = new Task();
newTask.title = title;
newTask.description = description;
if (project) {
const watcherOfProject = await dataSource
.getRepository(Project)
.findOne({
relations:{
members:true,
},
where:
{
id:project.id,
members:
{
user:{id:user.id},
roleProject:MemberRole.WATCHER,
},
}
})
console.log ('watcherOfProject ', watcherOfProject)
if (watcherOfProject) return res.send({message:"watcher could nt make tasks"})
newTask.project = project;
} else {
const personalProject = await dataSource
.getRepository(Project)
.findOne({
where:{
members:{
user:{id:user.id},
},
title:"Личные дела"
}
})
if(personalProject){
newTask.project = personalProject;
} else {
const newPersonalProject = new Project();
newPersonalProject.title="Личные дела";
newPersonalProject.color="green";
await newPersonalProject.save()
newTask.project = newPersonalProject;
const newMember = new Member();
newMember.user= user;
newMember.project=newPersonalProject;
newMember.roleProject = MemberRole.ADMIN;
await newMember.save();
console.log ('newPersonalProject ', newPersonalProject)
}
}
newTask.dateTimeDeadLine=dateTimeDeadLine;
newTask.author= user;
newTask.executor= executor;
......@@ -52,7 +102,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response
.find({
relations:{
executor:true,
author:true,
},
where:[
{
......@@ -60,11 +109,6 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response
id:userId
}
},
{
author:{
id:userId
}
},
]
})
return res.send({tasks})
......
......@@ -7,6 +7,7 @@ import path from 'path';
import {config} from "../config"
import { Project } from '../models/Project';
import { Member, MemberRole } from '../models/Member';
import { auth } from '../helpers';
const router:Router = express.Router();
const dataSource = myDataSource;
......@@ -35,6 +36,19 @@ const users = await dataSource
return res.send({users})
})
//** return displayName of user, requested by userId */
router.get('/display-name/:userId', auth, async (req : Request, res : Response):Promise<object> => {
const {userId} = req.params
const displayName = await dataSource
.createQueryBuilder()
.select(['user.displayName'])
.from(User, "user")
.where("user.id = :userId", { userId })
.getOne()
if (!displayName) return res.status(404).send({message:'displayName not found'})
return res.send(displayName)
})
//** return all users of DB */
router.get('/all-fields/', async (req : Request, res : Response):Promise<object> => {
......@@ -48,9 +62,25 @@ router.get('/all-fields/', async (req : Request, res : Response):Promise<object>
},
}
})
console.log('all fields users ', users)
return res.send({users})
})
//** return displayName of user, requested by userId */
router.get('/display-name/:userId',auth, async (req : Request, res : Response):Promise<object> => {
const {userId} =req.params
const displayName = await dataSource
.createQueryBuilder()
.select(['user.displayName'])
.from(User, "user")
.where("user.id = :userId", { userId })
.getOne()
if (!displayName) return res.status(404).send({message:'displayName not found'})
return res.send({displayName})
})
/**create new user*/
router.post('/', upload.single("avatar"), async (req : Request, res : Response):Promise<object> => {
const {name,surname,password,email, role} = req.body;
......
import {Routes, Route, Outlet, Navigate, BrowserRouter} from "react-router-dom";
import {Container} from "@mui/material";
import {useSelector} from "react-redux";
import { Routes, Route, Outlet, Navigate, BrowserRouter } from "react-router-dom";
import { Container } from "@mui/material";
import { useSelector } from "react-redux";
import AppToolbar from "./components/UI/AppToolBar/AppToolBar";
import MyTasks from './containers/MyTasks/MyTasks';
import Login from './containers/Login/Login';
......@@ -12,7 +12,7 @@ import FullProject from "./containers/FullProject/FullProject";
import NewProject from "./containers/NewProject/NewProject";
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);
if (!isAllowed && !roles?.includes(user?.role)) {
return <Navigate to={redirectUrl} />
......@@ -28,10 +28,10 @@ const App = () => {
<Routes>
<Route element={
<>
<AppToolbar/>
<AppToolbar />
<main>
<Container maxWidth={false} sx={{maxWidth:'2500px'}}>
<Outlet/>
<Container maxWidth={false} sx={{ maxWidth: '2500px' }}>
<Outlet />
</Container>
</main>
</>
......@@ -41,34 +41,43 @@ const App = () => {
isAllowed={user}
redirectUrl={"/sign-in"}
>
<Projects/>
<Projects />
</ProtectedRoute>
}/>
} />
<Route path={"/projects/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<FullProject/>
<FullProject />
</ProtectedRoute>
}/>
} />
<Route path={"/"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar/>
<WeekCalendar />
</ProtectedRoute>
}/>
} />
<Route path={"/week"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar/>
<WeekCalendar />
</ProtectedRoute>
}/>
} />
<Route path={"/week/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<WeekCalendar />
</ProtectedRoute>
} />
<Route path={"/month"} element={
<ProtectedRoute
......@@ -77,16 +86,25 @@ const App = () => {
>
<MonthCalendar></MonthCalendar>
</ProtectedRoute>
}/>
} />
<Route path={"/month/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<MonthCalendar></MonthCalendar>
</ProtectedRoute>
} />
<Route path={"/my-tasks"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<MyTasks/>
<MyTasks />
</ProtectedRoute>
}/>
} />
<Route path={"/profile/:id"} element={
<ProtectedRoute
......@@ -95,7 +113,7 @@ const App = () => {
>
<h1>profile page</h1>
</ProtectedRoute>
}/>
} />
<Route path={"/workers-tasks"} element={
<ProtectedRoute
......@@ -104,20 +122,20 @@ const App = () => {
>
<h1>workers tasks page</h1>
</ProtectedRoute>
}/>
} />
<Route path={"/sign-up"} element={
<ProtectedRoute
roles={["superuser"]}
redirectUrl={"/"}
>
<Register/>
<Register />
</ProtectedRoute>
}/>
} />
<Route path={"/sign-in"} element={<Login/>}/>
<Route path={"/forgottenpassword"} element={<ForgottenPassword/>}/>
<Route path='*' element={<h1>404</h1>}/>
<Route path={"/sign-in"} element={<Login />} />
<Route path={"/forgottenpassword"} element={<ForgottenPassword />} />
<Route path='*' element={<h1>404</h1>} />
</Route>
</Routes>
</BrowserRouter>
......
......@@ -4,7 +4,24 @@ import { priorities } from "../../../constants";
import CustomSelect from '../../UI/СustomSelect/СustomSelect'
function MonthCalendarModalContent({ title, onChangeCurrentTaskHandler, description, priority, sendNewTaskHandler, deleteTaskHandler, startHour, endHour }) {
function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, description, priority, sendNewTaskHandler, deleteTaskHandler, startHour, endHour, id }) {
const isValidate = () => {
if (title) {
const startHourInt = parseInt(startHour)
const endHourInt = parseInt(endHour)
if (startHourInt >= 8 && startHourInt <= 22) {
if (endHourInt >= 8 && endHourInt <= 22) {
if (startHourInt < endHourInt) {
return true
}
}
} else {
return false
}
}
}
return (<>
<TextField
id="task-description-title"
......@@ -55,10 +72,10 @@ function MonthCalendarModalContent({ title, onChangeCurrentTaskHandler, descript
/>
</div>
<div style={{ display: 'flex', gap: '20px', margin: '10px 0' }}>
<Button id='test_button_save_task' onClick={sendNewTaskHandler}>Сохранить</Button>
<Button onClick={deleteTaskHandler}>Удалить</Button>
<Button id='test_button_save_task' onClick={sendNewTaskHandler} disabled={!isValidate()}>Сохранить</Button>
<Button onClick={deleteTaskHandler} disabled={!id}>Удалить</Button>
</div>
</>);
}
export default memo(MonthCalendarModalContent);
\ No newline at end of file
export default memo(CalendarModalTaskContent);
\ No newline at end of file
import { Autocomplete, Button, TextField } from "@mui/material";
import { memo } from "react";
function CalendarModalWorkerContent({ allUserProjects, onChangeProjectHandler, onChangeWorkerHandler, workerInfo, workers, handleClose, onChangeCalendarUser}) {
return (<>
<Autocomplete
id="choose-project"
freeSolo
options={allUserProjects}
getOptionLabel={(item) => item.title || ""}
onChange={onChangeProjectHandler}
name={"project"}
value={workerInfo.project}
renderInput={(params) => <TextField
style={{ marginBottom: "15px" }}
label={"Проект"}
state={workerInfo.project}
{...params} />}
/>
{workerInfo.project ?
<>
<Autocomplete
id="choose-worker"
freeSolo
options={workers}
getOptionLabel={(item) => item?.user?.displayName || ""}
onChange={(e, value) => { onChangeWorkerHandler(e, value) }}
name={"worker"}
value={workerInfo.worker}
renderInput={(params) => <TextField
label={"Участник"}
state={workerInfo.worker}
{...params} />}
/>
<div style={{ display: 'flex', justifyContent: 'space-between', margin: '10px 0' }}>
<Button onClick={()=>{onChangeCalendarUser()}} >Выбрать</Button>
<Button onClick={() => handleClose()}>Отмена</Button>
</div>
</>
: null}
</>);
}
export default memo(CalendarModalWorkerContent);
\ No newline at end of file
import { Grid } from "@mui/material";
import { memo, useEffect, useState } from "react";
import DefaultTask from "../DefaultTask/DefaultTask";
import DefaultTask from "../MonthCalendar/MonthCalendarBody/DefaultTask/DefaultTask";
......
import { Grid } from "@mui/material";
import { memo, useMemo } from "react";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../CalendarStandartCell.js/CalendarStandartCell";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../../../CalendarStandartCell/CalendarStandartCell";
import CalendarTask from "../CalendarTask/CalendarTask";
import EmptyBox from "./EmptyBox/EmptyBox";
import { getBoxesInLine } from "./Helpers";
......
import { Box, FormControlLabel, Switch } from "@mui/material";
import { useState } from "react";
import CalendarRow from "./CalendarRow/CalendarRow";
import CalendarSmallCell from "./CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "./CalendarStandartCell.js/CalendarStandartCell";
import ModalTask from "../../UI/ModalTask/ModalTask";
import MonthCalendarModalContent from "../MonthCalendarModalContent/MonthCalendarModalContent";
import CalendarRow from "../../CalendarRow/CalendarRow";
import CalendarSmallCell from "../../CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../CalendarStandartCell/CalendarStandartCell";
import ModalTask from "../../../UI/ModalTask/ModalTask"
import MonthCalendarModalContent from "../../CalendarModalTaskContent/CalendarModalTaskContent";
import CalendarRowDay from "./CalendarRowDay/CalendarRowDay";
......@@ -89,6 +89,7 @@ function MonthCalendarBody({ month, year, tasks, createTaskInCellHandler, curren
title={currentTask.title}
description={currentTask.description}
priority={currentTask.priority}
id={currentTask.id}
startHour={currentTask.infoForCell?.startHour}
endHour={currentTask.infoForCell?.endHour}
onChangeCurrentTaskHandler={(e) => { onChangeCurrentTaskHandler(e) }}
......
import { Box, Typography } from '@mui/material';
import { memo } from 'react';
import ArrowDecrementButton from '../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../UI/ArrowIncrementButton/ArrowIncrementButton';
import ArrowDecrementButton from '../../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../../UI/ArrowIncrementButton/ArrowIncrementButton';
function MonthAndYearInfo({ currentMonthString, year, incrementMonth, decrementMonth }) {
return (
......@@ -12,7 +12,8 @@ function MonthAndYearInfo({ currentMonthString, year, incrementMonth, decrementM
flexGrow: 1,
display: 'flex',
alignItems: 'center',
gap: '10px'
gap: '10px',
marginBottom: '20px'
}}
id='test_month_info'
>
......@@ -21,7 +22,7 @@ function MonthAndYearInfo({ currentMonthString, year, incrementMonth, decrementM
/>
<Box sx={{ flexBasis: '150px' }}>
<Typography
variant="h6"
variant="h5"
sx={{
display: 'flex',
justifyContent: 'center',
......
import { AppBar, Button, Toolbar, Typography } from '@mui/material';
import { Box } from '@mui/system';
import MonthAndYearInfo from './MonthAndYearInfo/MonthAndYearInfo';
function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMonth, year, handleOpen, currentCalendarDisplayName, user, userId}) {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<Box>
<Typography variant="h5" sx={{ margin: "20px 0 20px 0" }}>
Календарь: {currentCalendarDisplayName}
</Typography>
<MonthAndYearInfo
currentMonthString={currentMonthString}
decrementMonth={decrementMonth}
incrementMonth={incrementMonth}
year={year}
/>
</Box>
<Button
onClick={() => { handleOpen() }}
color="inherit"
size="large"
sx={{ marginLeft: 'auto' }}
>
{user.id === userId ? 'Выбрать сотрудника' : 'Вернуться назад'}
</Button>
</Toolbar>
</AppBar>
</Box>
</>
);
}
export default MonthCalendarHeader;
\ No newline at end of file
import { useMemo } from "react";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../../../MonthCalendar/MonthCalendarBody/CalendarStandartCell.js/CalendarStandartCell";
import { getHoursInDayNumbers, getAvailableTasks, getLinesInDay, getSortedTasks } from "../../../../../helpers/CalendarHelpers";
import CalendarStandartCell from "../../../CalendarStandartCell/CalendarStandartCell";
function CalendarRowDayWeek({ hoursInDay, tasks, month, year, day, hourFormat }) {
const hours = useMemo(() => {
......
import { FormControlLabel, Grid, Switch } from "@mui/material";
import { Box } from "@mui/system";
import CalendarRow from "../../MonthCalendar/MonthCalendarBody/CalendarRow/CalendarRow";
import CalendarSmallCell from "../../MonthCalendar/MonthCalendarBody/CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../MonthCalendar/MonthCalendarBody/CalendarStandartCell.js/CalendarStandartCell";
import CalendarRow from "../../CalendarRow/CalendarRow";
import CalendarSmallCell from "../../CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "../../CalendarStandartCell/CalendarStandartCell";
import CalendarRowDayWeek from "./CalendarRowDayWeek/CalendarRowDayWeek";
import { getCurrentWeekDayString } from "./Helpers";
......
import ArrowDecrementButton from '../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../UI/ArrowIncrementButton/ArrowIncrementButton';
import ArrowDecrementButton from '../../../../UI/ArrowDecrementButton/ArrowDecrementButton';
import ArrowIncrementButton from '../../../../UI/ArrowIncrementButton/ArrowIncrementButton';
import { Box } from '@mui/system';
import { Typography } from '@mui/material';
......
import {Button, Menu, MenuItem} from "@mui/material";
import { useState, useEffect } from "react";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {NavLink, useNavigate} from "react-router-dom";
import { fetchUsersAllFields, fetchUsers, logoutUser } from "../../../store/actions/usersActions";
import { fetchUsersAllFields, logoutUser } from "../../../store/actions/usersActions";
import SwitchUserModal from "../../SwitchUserModal/SwitchUserModal";
const ProfileBlock = () => {
......@@ -30,7 +30,6 @@ const ProfileBlock = () => {
}
const switchUser=()=>{
dispatch(fetchUsersAllFields());
// dispatch(fetchUsers())
handleClose()
handleOpenSwitchUser()
}
......
import { AppBar, Toolbar } from '@mui/material';
import { Box } from '@mui/system';
import MonthAndYearInfo from './MonthAndYearInfo/MonthAndYearInfo';
import СustomSelect from '../../UI/СustomSelect/СustomSelect'
const workers = [{ value: '', text: '--выберите сотрудника--' }, { value: 'Василий', text: 'Василий' }, { value: 'Никита', text: 'Никита' }]
const types = [{ value: 'Месяц', text: 'Месяц' }, { value: 'Неделя', text: 'Неделя' }]
function MonthCalendarHeader({ currentMonthString, decrementMonth, incrementMonth, calendarType, onChangeWorkerHandler, onChangeCalendarTypeHandler, worker, year }) {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<MonthAndYearInfo
currentMonthString={currentMonthString}
decrementMonth={decrementMonth}
incrementMonth={incrementMonth}
year={year}
/>
<СustomSelect
value={worker}
onChange={(e) => { onChangeWorkerHandler(e) }}
label={'Сотрудник'}
id={'worker'}
items={workers}
/>
<div style={{ marginLeft: '20px' }}>
<СustomSelect
value={calendarType}
onChange={(e) => { onChangeCalendarTypeHandler(e) }}
label={'Календарь'}
id={'calendar-type'}
items={types}
/>
</div>
</Toolbar>
</AppBar>
</Box>
</>
);
}
export default MonthCalendarHeader;
\ No newline at end of file
......@@ -17,19 +17,20 @@ const SwitchUserForm=({submitFormHandler, users})=> {
useEffect(()=>{
if(currentUser?.members.length>0) {
let dataArray=[]
for (let member of currentUser.members ) {
const newProjectRole = {
"projectName":member.project.title,
"roleName":member.roleProject
}
setProjectsRole([...projectsRoles, newProjectRole ])
dataArray.push(newProjectRole)
}
setProjectsRole(dataArray)
}
},[ currentUser])
return (
<>
{/* <Box sx={style}> */}
{users?
<form onSubmit={(e)=>submitFormHandler(e,currentUser)}>
<Grid container direction="column" spacing={2}>
......@@ -66,15 +67,7 @@ const SwitchUserForm=({submitFormHandler, users})=> {
</Button>
</Grid>
{/* <Grid item>
<Button
onClick={()=>console.log('cancel form')}
color="primary"
variant="contained"
>
Отмена
</Button>
</Grid> */}
</Grid>
</Grid>
......@@ -82,7 +75,6 @@ const SwitchUserForm=({submitFormHandler, users})=> {
: <></>}
{/* </Box> */}
</>
)
}
......
......@@ -9,7 +9,6 @@ import Paper from '@mui/material/Paper';
const SwitchUserTable=({projectsRoles})=>{
return (
<TableContainer component={Paper}>
......@@ -31,7 +30,8 @@ const SwitchUserTable=({projectsRoles})=>{
</TableRow>
</TableHead>
<TableBody>
{projectsRoles.map((projectRole,index) => (
{projectsRoles.map((projectRole,index) =>{ return (
<TableRow
key={index}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
......@@ -41,7 +41,7 @@ const SwitchUserTable=({projectsRoles})=>{
</TableCell>
<TableCell align="right">{projectRole.roleName}</TableCell>
</TableRow>
))}
)})}
</TableBody>
</Table>
</TableContainer>
......
import * as React from 'react';
import Box from '@mui/material/Box';
import Modal from '@mui/material/Modal';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 2
};
export default function DefaultModal({ modal, handleClose, children }) {
return (
<div>
<Modal
open={modal}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
{children}
</Box>
</Modal>
</div>
);
}
\ No newline at end of file
import { useEffect, useCallback, useState, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import MonthCalendarBody from '../../components/MonthCalendar/MonthCalendarBody/MonthCalendarBody';
import MonthCalendarHeader from '../../components/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader';
import { useNavigate, useParams } from 'react-router-dom';
import CalendarModalWorkerContent from '../../components/Calendars/CalendarModalWorkerContent/CalendarModalWorkerContent';
import MonthCalendarBody from '../../components/Calendars/MonthCalendar/MonthCalendarBody/MonthCalendarBody';
import MonthCalendarHeader from '../../components/Calendars/MonthCalendar/MonthCalendarHeader/MonthCalendarHeader';
import DefaultModal from '../../components/UI/DefaultModal/DefaultModal';
import { dateToISOLikeButLocal, getCurrentMonthString, getDaysInMonth } from '../../helpers/CalendarHelpers';
import { fetchAllUserProjects, fetchProject } from '../../store/actions/projectsActions';
import { addCalendarTask, addCopyCalendarTask, deleteCalendarTask, editCalendarTask, fetchCalendarTasks } from '../../store/actions/tasksActions';
import { fetchCurrentCalendarDisplayName } from '../../store/actions/usersActions';
function MonthCalendar() {
const dispatch = useDispatch();
const navigate = useNavigate()
const { calendarTasks } = useSelector(state => state.tasks);
const user = useSelector(state => state.users?.user);
const { user, currentCalendarDisplayName } = useSelector(state => state.users);
const { allUserProjects, project } = useSelector(state => state.projects)
const params = useParams()
const [hourFormat, setHourFormat] = useState(false);
const [dateNow, setDateNow] = useState({ month: '', year: '' })
const [worker, setWorker] = useState('');
const [calendarType, setCalendarType] = useState('Месяц');
const [workerInfo, setWorkerInfo] = useState({ project: '', worker: '' });
const [currentTask, setCurrentTask] = useState({ title: '', description: '', priority: null, infoForCell: { startHour: null, endHour: null } })
const [copyTask, setCopyTask] = useState(null)
const [cellSizes, setCellSizes] = useState({})
const [userId, setUserId] = useState('')
const [modal, setModal] = useState(false)
useEffect(() => {
setDateNow({
month: new Date().getMonth(),
year: new Date().getFullYear(),
})
dispatch(fetchCalendarTasks())
if (params.id) {
setUserId(params.id)
dispatch(fetchCalendarTasks(params.id))
dispatch(fetchCurrentCalendarDisplayName(params.id))
} else {
setUserId(user.id)
dispatch(fetchCalendarTasks(user.id))
dispatch(fetchCurrentCalendarDisplayName(user.id))
}
}, [dispatch])
useEffect(() => {
if (workerInfo.project) {
dispatch(fetchProject(workerInfo.project.id))
}
}, [workerInfo.project])
const hoursInDay = useMemo(() => {
let arr
......@@ -50,12 +72,12 @@ function MonthCalendar() {
return getCurrentMonthString(dateNow.month)
}, [dateNow.month])
const onChangeWorkerHandler = useCallback((event) => {
setWorker(event.target.value);
const onChangeProjectHandler = useCallback((e, value) => {
setWorkerInfo((prevState) => { return { ...prevState, project: value } });
}, []);
const onChangeCalendarTypeHandler = useCallback((event) => {
setCalendarType(event.target.value);
const onChangeWorkerHandler = useCallback((e, value) => {
setWorkerInfo((prevState) => { return { ...prevState, worker: value } });
}, []);
const incrementMonth = useCallback(() => {
......@@ -66,6 +88,7 @@ function MonthCalendar() {
return { ...prevState, month: prevState.month + 1 }
})
}, [])
const decrementMonth = useCallback(() => {
setDateNow((prevState) => {
if (prevState.month - 1 === -1) {
......@@ -83,7 +106,7 @@ function MonthCalendar() {
...prevState,
infoForCell: {
...prevState.infoForCell,
[name]: parseInt(value)
[name]: value
}
}
});
......@@ -137,13 +160,13 @@ function MonthCalendar() {
const start = dateToISOLikeButLocal(new Date(dateNow.year, dateNow.month, dayNumber, hour, 0))
const newTask = {
...currentTask,
dateTimeTaskId: currentTask.id,
taskId: currentTask.mainTaskId,
dateTimeStart: start,
dateTimeDue: due
}
delete newTask.id
delete newTask.infoForCell
await dispatch(editCalendarTask(newTask))
await dispatch(editCalendarTask(newTask, currentTask.id, userId))
setCurrentTask({})
}
......@@ -161,18 +184,19 @@ function MonthCalendar() {
taskId: currentTask.mainTaskId
}
delete newTask.infoForCell
await dispatch(editCalendarTask(newTask, currentTask.id))
await dispatch(editCalendarTask(newTask, currentTask.id, userId))
} else {
const newTask = {
...currentTask,
dateTimeStart: start,
dateTimeDue: due,
executor: user,
executor: userId,
author: user.id,
dateTimeDeadLine: due,
}
delete newTask.infoForCell
delete newTask.id
await dispatch(addCalendarTask(newTask))
await dispatch(addCalendarTask(newTask, userId))
}
}
......@@ -194,25 +218,64 @@ function MonthCalendar() {
}
delete newTask.infoForCell
delete newTask.id
await dispatch(addCopyCalendarTask(newTask))
await dispatch(addCopyCalendarTask(newTask, userId))
setCopyTask(null)
}
const deleteTaskHandler = async (taskId) => {
dispatch(deleteCalendarTask(taskId))
dispatch(deleteCalendarTask(taskId, userId))
}
const handleClose = () => {
setModal(false)
setWorkerInfo({ project: '', worker: '' })
}
const handleOpen = async () => {
if (user.id === userId) {
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 (
<>
<DefaultModal
modal={modal}
handleClose={() => { handleClose() }}
>
<CalendarModalWorkerContent
workerInfo={workerInfo}
allUserProjects={allUserProjects}
workers={project?.project?.members}
onChangeProjectHandler={onChangeProjectHandler}
onChangeWorkerHandler={onChangeWorkerHandler}
handleClose={handleClose}
onChangeCalendarUser={onChangeCalendarUser}
/>
</DefaultModal>
<MonthCalendarHeader
year={dateNow.year}
currentMonthString={currentMonthString}
decrementMonth={decrementMonth}
incrementMonth={incrementMonth}
onChangeCalendarTypeHandler={onChangeCalendarTypeHandler}
onChangeWorkerHandler={onChangeWorkerHandler}
worker={worker}
calendarType={calendarType}
handleOpen={handleOpen}
currentCalendarDisplayName={currentCalendarDisplayName}
user={user}
userId={userId}
/>
<MonthCalendarBody
month={dateNow.month}
......
import moment from 'moment';
import { useEffect, useState, useMemo, useCallback } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import WeekCalendarBody from '../../components/WeekCalendar/WeekCalendarBody/WeekCalendarBody';
import WeekCalendarHeader from '../../components/WeekCalendar/WeekCalendarHeader/WeekCalendarHeader'
import WeekCalendarBody from '../../components/Calendars/WeekCalendar/WeekCalendarBody/WeekCalendarBody';
import WeekCalendarHeader from '../../components/Calendars/WeekCalendar/WeekCalendarHeader/WeekCalendarHeader'
import { getWeekInfoString, getWeekFromCurrentDate } from '../../helpers/CalendarHelpers';
import { fetchCalendarTasks } from '../../store/actions/tasksActions';
......@@ -19,7 +19,7 @@ function WeekCalendar() {
const month = new Date().getMonth()
const currentDay = moment().date()
setDate({ year: year, month: month, currentDay: currentDay })
dispatch(fetchCalendarTasks())
// dispatch(fetchCalendarTasks())
}, [])
const hoursInDay = useMemo(() => {
......
......@@ -10,3 +10,5 @@ export const CREATE_MEMBER_SUCCESS = "CREATE_MEMBER_SUCCESS";
export const DELETE_MEMBER_REQUEST = "DELETE_MEMBER_REQUEST";
export const DELETE_MEMBER_SUCCESS = "DELETE_MEMBER_SUCCESS";
export const DELETE_MEMBER_FAILURE = "DELETE_MEMBER_FAILURE";
export const FETCH_ALL_USER_PROJECTS_SUCCESS = "FETCH_ALL_USER_PROJECTS_SUCCESS";
\ No newline at end of file
......@@ -15,3 +15,5 @@ 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";
export const FETCH_DISPLAYNAME_SUCCESS = "FETCH_DISPLAYNAME_SUCCESS";
\ No newline at end of file
import axios from "../../axiosPlanner";
import { CREATE_MEMBER_SUCCESS, CREATE_PROJECT_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, FETCH_MEMBERS_ERROR, FETCH_MEMBERS_REQUEST, FETCH_MEMBERS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import { CREATE_MEMBER_SUCCESS, CREATE_PROJECT_SUCCESS, DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_MEMBERS_ERROR, FETCH_MEMBERS_REQUEST, FETCH_MEMBERS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import { showNotification } from "./commonActions";
const fetchProjectsRequest = () => {
......@@ -105,3 +105,19 @@ export const createMember = (memberData, navigate) => {
};
}
const fetchAllUserProjectsSuccess = (projects) => {
return {type: FETCH_ALL_USER_PROJECTS_SUCCESS, projects};
};
export const fetchAllUserProjects = () => {
return async dispatch => {
dispatch(fetchProjectsRequest());
try {
const response = await axios.get("/projects/my");
dispatch(fetchAllUserProjectsSuccess(response.data.projects));
} catch (e) {
dispatch(fetchProjectsError(e));
}
}
}
......@@ -38,11 +38,11 @@ const fetchCalendarTasksFailure = (error) => {
return {type: FETCH_CALENDAR_TASKS_FAILURE, error}
};
export const fetchCalendarTasks = () => {
export const fetchCalendarTasks = (userId) => {
return async (dispatch) => {
dispatch(fetchCalendarTasksRequest());
try {
const response = await axios.get("/tasks");
const response = await axios.get(`/tasks/user/${userId}`);
dispatch(fetchCalendarTasksSuccess(response.data.tasks))
} catch (error) {
dispatch(fetchCalendarTasksFailure(error.response.data));
......@@ -73,26 +73,26 @@ const addTaskFailure = (error) => {
return {type: ADD_NEW_TASK_FAILURE, error}
};
export const addCalendarTask = (task) => {
export const addCalendarTask = (task, userId) => {
return async (dispatch) => {
dispatch(addTaskRequest());
try {
await axios.post("/tasks", task);
dispatch(addTaskSuccess())
dispatch(fetchCalendarTasks())
dispatch(fetchCalendarTasks(userId))
} catch (error) {
dispatch(addTaskFailure(error.response.data));
}
}
}
export const addCopyCalendarTask = (task) => {
export const addCopyCalendarTask = (task, userId) => {
return async (dispatch) => {
dispatch(addTaskRequest());
try {
await axios.post("/copy-tasks/make-copy", task);
dispatch(addTaskSuccess())
dispatch(fetchCalendarTasks())
dispatch(fetchCalendarTasks(userId))
} catch (error) {
dispatch(addTaskFailure(error.response.data));
}
......@@ -137,13 +137,14 @@ export const editTask = (task) => {
}
}
export const editCalendarTask = (task, taskId) => {
export const editCalendarTask = (task, taskId, userId) => {
return async (dispatch) => {
dispatch(editTaskRequest());
try {
await axios.put(`/copy-tasks/change-copy/${taskId}`, task);
const response = await axios.put(`/copy-tasks/change-copy/${taskId}`, task);
console.log(response.data)
dispatch(editTaskSuccess())
dispatch(fetchCalendarTasks())
dispatch(fetchCalendarTasks(userId))
} catch (error) {
dispatch(editTaskFailure(error.response.data));
}
......@@ -175,13 +176,13 @@ export const deleteTask = (taskId) => {
}
}
export const deleteCalendarTask = (taskId) => {
export const deleteCalendarTask = (taskId, userId) => {
return async (dispatch) => {
dispatch(deleteTaskRequest());
try {
await axios.delete(`/copy-tasks/${taskId}`);
dispatch(deleteTaskSuccess())
dispatch(fetchCalendarTasks())
dispatch(fetchCalendarTasks(userId))
} catch (error) {
dispatch(deleteTaskFailure(error.response.data));
}
......
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,FETCH_USERS_ALL_FIELDS_REQUEST,
FETCH_USERS_ALL_FIELDS_SUCCESS,
FETCH_USERS_ALL_FIELDS_FAILURE, } from "../actionTypes/userActionTypes"
FETCH_USERS_ALL_FIELDS_FAILURE,
FETCH_DISPLAYNAME_SUCCESS, } from "../actionTypes/userActionTypes"
import { showNotification } from "./commonActions";
const registerUserRequest = () => {
......@@ -136,3 +137,20 @@ export const fetchUsersAllFields = () => {
}
};
const fetchCurrentCalendarDisplayNameSuccess = (displayName) => {
return {type: FETCH_DISPLAYNAME_SUCCESS, displayName}
}
export const fetchCurrentCalendarDisplayName = (userId) => {
return async dispatch => {
dispatch(fetchUsersAllFieldsRequest());
try {
const response = await axios.get(`/users/display-name/${userId}`);
dispatch(fetchCurrentCalendarDisplayNameSuccess(response.data.displayName));
} catch (e) {
dispatch(fetchUsersAllFieldsFailure(e.response.data));
}
}
};
import {DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import {DELETE_MEMBER_FAILURE, DELETE_MEMBER_REQUEST, DELETE_MEMBER_SUCCESS, FETCH_ALL_USER_PROJECTS_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
const initialState = {
allUserProjects: [],
projects: [],
project: "",
loading: false,
......@@ -23,6 +24,8 @@ const initialState = {
return {...state, loading: true};
case DELETE_MEMBER_FAILURE:
return {...state, loading: false, error: action.error};
case FETCH_ALL_USER_PROJECTS_SUCCESS:
return {...state, loading: false, allUserProjects: action.projects}
default:
return state;
}
......
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";
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, FETCH_DISPLAYNAME_SUCCESS } from "../actionTypes/userActionTypes";
const initialState = {
user: null,
users: [],
usersAllFields:[],
currentCalendarDisplayName: '',
registerError: null,
loginError: null,
loading: false
......@@ -30,6 +31,8 @@ const usersReducer = (state = initialState, action) => {
return {...state, loading: false, users: action.users};
case FETCH_USERS_ALL_FIELDS_SUCCESS:
return {...state, loading: false, usersAllFields: action.users};
case FETCH_DISPLAYNAME_SUCCESS:
return {...state, loading: false, currentCalendarDisplayName: action.displayName};
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