Commit d82cc5c0 authored by Нелли Ибрагимова's avatar Нелли Ибрагимова

доработалла селект по проектам при редактировании, написала компонент NewTask и…

доработалла селект по проектам при редактировании, написала компонент NewTask и функцию добавления задачи, расшифровала пропсы во всех компонентах, поправила формат дат, добавила плейсхолдеры
parents 6fcaa7f7 5bbfca5e
...@@ -16,6 +16,7 @@ router.get('/',async (req:Request, res:Response): Promise<Response>=> { ...@@ -16,6 +16,7 @@ router.get('/',async (req:Request, res:Response): Promise<Response>=> {
router.post('/', async (req:Request, res:Response): Promise<Response> => { router.post('/', async (req:Request, res:Response): Promise<Response> => {
if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'}) if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'})
const token = req.get('Authorization'); const token = req.get('Authorization');
console.log("token:" + token)
const {title, dateDue,color,department,workers,tasks}= req.body; const {title, dateDue,color,department,workers,tasks}= req.body;
const user = await dataSource const user = await dataSource
.createQueryBuilder() .createQueryBuilder()
...@@ -36,7 +37,7 @@ router.post('/', async (req:Request, res:Response): Promise<Response> => { ...@@ -36,7 +37,7 @@ router.post('/', async (req:Request, res:Response): Promise<Response> => {
return res.send({project}) return res.send({project})
}) })
router.get("/id/:id",async (req:Request, res:Response): Promise<Response> => { router.get("/:id",async (req:Request, res:Response): Promise<Response> => {
const project = await dataSource const project = await dataSource
.createQueryBuilder() .createQueryBuilder()
.select("project") .select("project")
......
...@@ -2,6 +2,7 @@ import express,{Router, Request, Response} from 'express'; ...@@ -2,6 +2,7 @@ import express,{Router, Request, Response} from 'express';
import {Task} from '../models/Task'; import {Task} from '../models/Task';
import {myDataSource} from '../app-data-source'; import {myDataSource} from '../app-data-source';
import { User } from '../models/User'; import { User } from '../models/User';
import { Project } from '../models/Project';
const router:Router = express.Router(); const router:Router = express.Router();
const dataSource = myDataSource; const dataSource = myDataSource;
...@@ -37,7 +38,7 @@ router.post('/', async(req:Request, res:Response):Promise<Response>=>{ ...@@ -37,7 +38,7 @@ router.post('/', async(req:Request, res:Response):Promise<Response>=>{
return res.send({newTask}) return res.send({newTask})
}) })
router.get('/userId/:userId', async (req: Request, res: Response):Promise<Response>=>{ router.get('/:userId', async (req: Request, res: Response):Promise<Response>=>{
const userId = req.params.userId; const userId = req.params.userId;
const tasks = await dataSource const tasks = await dataSource
.getRepository(Task) .getRepository(Task)
...@@ -111,4 +112,53 @@ router.put('/',async(req:Request, res:Response)=> { ...@@ -111,4 +112,53 @@ router.put('/',async(req:Request, res:Response)=> {
}) })
router.post('/project',async (req: Request, res: Response):Promise<Response>=>{
let projectArray :string[]= req.body;
console.log('projectArray ', projectArray)
if (projectArray.length===0) {
const rawTasks = await
dataSource
.getRepository(Task)
.find({
relations:{
executors:true,
author:true,
project:true
}
})
const tasks:object[]= rawTasks.filter(task=>task.project===null)
return res.send({tasks})
}
const tasks = await
dataSource
.getRepository(Task)
.createQueryBuilder('task')
.innerJoinAndSelect( 'task.project', 'project')
.where('task.project IN(:...projects)', {projects:projectArray})
.getMany()
return res.send({tasks})
})
// router.post('/projects',async (req: Request, res: Response):Promise<Response>=>{
// let projectArray :string[]= req.body;
// console.log('projectArray ', projectArray)
// if (projectArray.length===0) {
// const tasks = await
// dataSource
// .getRepository(Task)
// .createQueryBuilder('task')
// // .innerJoinAndSelect('task.executors', 'user')
// .innerJoinAndSelect('task.executors AND task.author', 'user')
// .where('task.project IS NULL')
// .getMany()
// return res.send({tasks})
// }
// ///ssome code
// return res.send({message:"some other staff"})
// })
export default router; export default router;
...@@ -7,6 +7,9 @@ import Login from './containers/Login/Login'; ...@@ -7,6 +7,9 @@ import Login from './containers/Login/Login';
import Register from './containers/Register/Register'; import Register from './containers/Register/Register';
import MonthCalendar from './containers/MonthCalendar/MonthCalendar'; import MonthCalendar from './containers/MonthCalendar/MonthCalendar';
import ForgottenPassword from "./containers/ForgottenPassword/ForgottenPassword"; import ForgottenPassword from "./containers/ForgottenPassword/ForgottenPassword";
import Projects from "./containers/Projects/Projects";
import FullProject from "./containers/FullProject/FullProject";
import NewProject from "./containers/NewProject/NewProject";
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);
...@@ -18,6 +21,7 @@ const ProtectedRoute = ({isAllowed, roles, redirectUrl, children}) => { ...@@ -18,6 +21,7 @@ const ProtectedRoute = ({isAllowed, roles, redirectUrl, children}) => {
const App = () => { const App = () => {
const user = useSelector(state => state.users?.user); const user = useSelector(state => state.users?.user);
return ( return (
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
...@@ -31,7 +35,30 @@ const App = () => { ...@@ -31,7 +35,30 @@ const App = () => {
</main> </main>
</> </>
}> }>
<Route path={"/projects"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<Projects/>
</ProtectedRoute>
}/>
<Route path={"/projects/:id"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<FullProject/>
</ProtectedRoute>
}/>
<Route path={"/projects/add"} element={
<ProtectedRoute
isAllowed={user}
redirectUrl={"/sign-in"}
>
<NewProject/>
</ProtectedRoute>
}/>
<Route path={"/"} element={ <Route path={"/"} element={
<ProtectedRoute <ProtectedRoute
isAllowed={user} isAllowed={user}
......
...@@ -10,7 +10,7 @@ const AdminMenu = () => { ...@@ -10,7 +10,7 @@ const AdminMenu = () => {
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
const user = useSelector(state => state.users.user) const user = useSelector(state => state.users.user)
console.log(user)
const handleClick = (event) => { const handleClick = (event) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
}; };
...@@ -23,6 +23,14 @@ const AdminMenu = () => { ...@@ -23,6 +23,14 @@ const AdminMenu = () => {
handleClose() handleClose()
} }
return <> return <>
<Button
component={NavLink}
to="/projects"
color="inherit"
size="large"
>
Проекты
</Button>
<Button <Button
component={NavLink} component={NavLink}
to="/week" to="/week"
......
import { Button, Menu, MenuItem } from "@mui/material";
import { useState } from "react";
import { useDispatch } from "react-redux";
import { NavLink, useNavigate } from "react-router-dom";
import { logoutUser } from "../../../store/actions/usersActions";
import HasAccess from "../../UI/HasAccess/HasAccess";
const UserMenu = ({ user }) => {
const dispatch = useDispatch();
const navigate = useNavigate()
const [anchorEl, setAnchorEl] = useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const logout = () => {
dispatch(logoutUser(navigate));
handleClose()
}
return <>
<Button
color="inherit"
onClick={handleClick}
>
Hello, {user?.displayName}
</Button>
{/* <HasAccess roles={["admin"]}>
<Button
component={NavLink}
color="inherit"
to="/admin"
>
Admin panel
</Button>
</HasAccess> */}
<Menu
anchorEl={anchorEl}
open={open}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={logout}>Logout</MenuItem>
</Menu>
</>
};
export default UserMenu;
\ No newline at end of file
...@@ -23,6 +23,14 @@ const WorkerMenu = () => { ...@@ -23,6 +23,14 @@ const WorkerMenu = () => {
handleClose() handleClose()
} }
return <> return <>
<Button
component={NavLink}
to="/projects"
color="inherit"
size="large"
>
Проекты
</Button>
<Button <Button
component={NavLink} component={NavLink}
to="/week" to="/week"
......
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import { memo } from "react";
const CalendarRow = ({children}) => { const CalendarRow = ({children}) => {
return <> return <>
...@@ -13,6 +12,6 @@ const CalendarRow = ({children}) => { ...@@ -13,6 +12,6 @@ const CalendarRow = ({children}) => {
</> </>
}; };
export default memo(CalendarRow); export default CalendarRow;
import { Grid } from "@mui/material";
import { memo, useMemo } from "react";
import CalendarStandartCell from "../CalendarStandartCell.js/CalendarStandartCell";
import CalendarTask from "../CalendarTask/CalendarTask";
const CalendarRowDay = ({xs, hoursInDay, createTaskInCellHandler, currentTask, handleOpen, modal, setCurrentTask, year, month, tasks, day, hourFormat}) => {
const hours = useMemo(()=>{
return hoursInDay.map((hour)=>parseInt(hour.split(':')[0]))},
[hoursInDay])
const availableTasks = useMemo(() => {
const tasksInDay = tasks.filter((task)=> {
if (year === task.infoForCell.startYear) {
if (month + 1 === task.infoForCell.startMonth) {
if (day.dayNumber === task.infoForCell.startDay) {
return task
} else {return false}
} else {return false}
} else {return false}
})
return tasksInDay
}, [tasks, month, year, day.dayNumber])
const sortedTasks = useMemo(() => {
if (availableTasks.length) {
const newSortedArr = [...availableTasks].sort(function(a,b){
const durattionFirstDate = new Date(a.dateTimeDue).getTime() - new Date(a.dateTimeStart).getTime()
const durattionSecondDate = new Date(b.dateTimeDue).getTime() - new Date(b.dateTimeStart).getTime()
return durattionSecondDate - durattionFirstDate;
})
return newSortedArr
}
}, [availableTasks])
const linesInDay = useMemo(() => {
let hourDiff
let hourDiffEnd
const lines = []
if (hourFormat) {
hourDiff = 1
hourDiffEnd = 0
} else {
hourDiff = 2
hourDiffEnd = 1
}
if (availableTasks.length) {
lines.push(hoursInDay.map((hour)=>parseInt(hour.split(':')[0])))
for (let k = 0; k < sortedTasks.length; k++) {
let skipLine = false
for (let j = 0; j < lines.length; j++) {
const line = lines[j]
const task = sortedTasks[k]
if (skipLine) {
skipLine = false
break;
}
for (let i = 0; i < line.length; i++) {
const hour = hours[i]
let havePlace = true
if (((task.infoForCell.endHour <= hour || task.infoForCell.startHour <= hour) && (task.infoForCell.endHour > hour))
|| (!hourFormat && task.infoForCell.startHour >= hour && task.infoForCell.endHour < hour + hourDiff)
|| (!hourFormat && task.infoForCell.startHour === hour + hourDiffEnd && task.infoForCell.endHour > hour)
|| (task.infoForCell.endMinute <= 59 && task.infoForCell.endHour === hour)) {
if (!isNaN(line[i])) {
for (let a = 0; a < hours.length; a++) {
const hour = hours[a]
if ((task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour + hourDiffEnd) || (!hourFormat && task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour)) {
if (isNaN(line[a])) {
havePlace = false
break;
}
}
}
if (!havePlace) {
havePlace = true
break;
}
line[i] += `-${k}`
if ((task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour + hourDiffEnd) || (!hourFormat && task.infoForCell.endMinute === 59 && task.infoForCell.endHour === hour)) {
skipLine = true
break;
}
} else {
if (j + 1 === lines.length) {
lines.push(hoursInDay.map((hour)=>parseInt(hour.split(':')[0])))
}
break;
}
}
}
}
}
}
return lines
}, [availableTasks.length, hourFormat, hours, hoursInDay, sortedTasks])
const getBoxesInLine = (line) => {
if (line) {
let xs = 12/hoursInDay.length
const boxes = []
for (let i = 0; i < line.length; i++) {
if (!isNaN(line[i])) {
if (boxes[boxes.length -1]?.task === null) {
boxes[boxes.length -1].xs += xs
} else {
boxes.push({xs: xs, task: null})
}
} else {
const task = sortedTasks[line[i].split('-')[1]]
const taskIsThere = boxes.find((taskFind)=>{
if (taskFind?.task?.id === task.id) return taskFind
})
if (taskIsThere) {
taskIsThere.xs +=xs
} else {
boxes.push({xs: xs, task: sortedTasks[line[i].split('-')[1]]})
}
}
}
return boxes
}
}
return <>
<Grid
container
item
xs={10.8}
align='center'
>
{hoursInDay.map((hour, i)=>{
return (
<CalendarStandartCell
key={i}
item xs={xs}
createTaskInCellHandler={createTaskInCellHandler}
hours={hour}
dayNumber={day.dayNumber}
currentTask={currentTask}
handleOpen={handleOpen}
modal={modal}
>
</CalendarStandartCell>
)
})}
{linesInDay?.map((line, i)=>{
const boxes = getBoxesInLine(line)
return(
<Grid key={i} container sx={{height: '35px', backgroundColor: 'rgb(0,0,0,0)', marginTop: i === 0 ? '-35px' : 0, marginBottom: '5px'}}>
{boxes.map((box)=>{
if (box.task) {
return (<Grid item xs={box.xs} sx={{height: '35px', marginBottom: '5px'}}>
<CalendarTask
task={box.task}
setCurrentTask={setCurrentTask}
handleOpen={handleOpen}
/>
</Grid>)
} else {
return (<Grid item xs={box.xs} sx={{height: '35px', backgroundColor: 'rgb(0,0,0,0)'}}>
</Grid>)
}
})}
</Grid>)
})}
</Grid>
</>
};
export default memo(CalendarRowDay);
\ No newline at end of file
import { Grid, TextField, Typography } from "@mui/material"; import { Grid} from "@mui/material";
import { memo, useEffect, useState } from "react"; import { memo, useEffect, useState } from "react";
const CalendarStandartCell = ({children, xs, hours, dayNumber, createTaskInCellHandler, handleOpen, modal}) => { const CalendarStandartCell = ({children, xs, hours, dayNumber, createTaskInCellHandler, handleOpen, modal, divRef }) => {
const [isThisCell, setIsThisCell] = useState(false) const [isThisCell, setIsThisCell] = useState(false)
useEffect(()=>{ useEffect(()=>{
if(!modal) { if(!modal) {
setIsThisCell(false); setIsThisCell(false);
} }
}, [modal]) }, [modal])
return <> return <>
<Grid <Grid
item xs={xs} item xs={xs}
sx={{borderRight: '1px solid black'}} sx={{position: 'relative', height: '35px'}}
onClick={(e)=>{createTaskInCellHandler(dayNumber, hours); setIsThisCell(true); handleOpen(e)}}> onClick={(e)=>{createTaskInCellHandler(dayNumber, hours); setIsThisCell(true); handleOpen(e)}}
>
{children} {children}
{isThisCell ? {isThisCell ?
<Grid <Grid
sx={{backgroundColor: 'lightgreen', padding: '10px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis'}} sx={{ position: 'relative', height: '29px', backgroundColor: 'lightgreen', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', borderRadius: '10px', margin: '3px 10px', display: 'flex', justifyContent: 'flex-start', alignItems: 'center', paddingLeft: '5px', zIndex: '5'}}
> >
<span> <span>
Задача Задача
</span> </span>
</Grid> : null} </Grid> : null}
<div style={{position: 'absolute', height: children ? divRef : 0, width: '1px', backgroundColor: 'black', right: '0', top: '0', zIndex: '3'}}>
</div>
</Grid> </Grid>
</> </>
}; };
......
import { Grid, TextField, Typography } from "@mui/material"; import { Grid} from "@mui/material";
import React, { memo, useState, useEffect} from "react"; import React, { memo} from "react";
const CalendarTask = ({year, month, tasks, day, hours, setCurrentTask, hourFormat, handleOpen, currentTask}) => {
const [thisCellCurrentTask, setThisCellCurrentTask] = useState({})
const getTaskInDayCell = (tasks, day, hours) => {
const hour = parseInt(hours.split(':')[0])
let hourDiffEnd
if (hourFormat) {
hourDiffEnd = hour + 1
} else {
hourDiffEnd = hour + 2
}
const tasksCell = tasks.filter(task=> {
if (year === task.infoForCell.startYear) {
if (month + 1 === task.infoForCell.startMonth) {
if (day.dayNumber === task.infoForCell.startDay) {
if (((task.infoForCell.endHour <= hour || task.infoForCell.startHour <= hour) && (task.infoForCell.endHour > hour))
|| (task.infoForCell.startHour >= hour && task.infoForCell.endHour < hourDiffEnd)
|| (task.infoForCell.endMinute <= 59 && task.infoForCell.endHour === hour)) {
return task
}
}
}
}
})
return tasksCell
}
const tasksCell = getTaskInDayCell(tasks, day, hours)
useEffect(()=>{
if (!currentTask.title) {
setThisCellCurrentTask({})
}
}, [currentTask])
const CalendarTask = ({setCurrentTask, handleOpen, task}) => {
const onClickTaskHandler = (e, task) => {
e.stopPropagation();
setCurrentTask(task);
handleOpen(e)
}
return (<> return (<>
{tasksCell.length ? tasksCell.map((task, i)=>
{
return (
<Grid <Grid
key={task.id} sx={{ position: 'relative', height: '30px', backgroundColor: 'lightgreen', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', borderRadius: '10px', margin: '5px 10px', display: 'flex', justifyContent: 'flex-start', alignItems: 'center', paddingLeft: '5px', zIndex: '5'}}
sx={{backgroundColor: 'lightgreen', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', padding: '10px', borderBottom: '1px solid rgb(29, 161, 51);;'}} onClick={(e)=>{onClickTaskHandler(e, task)}}
onClick={(e)=>{e.stopPropagation(); setCurrentTask(task); handleOpen(e)}}
> >
<span>
{task.title} {task.title}
</span>
</Grid> </Grid>
)}
)
: null}
</>) </>)
}; };
......
import { FormControlLabel, Switch} from "@mui/material"; import { FormControlLabel, Switch} from "@mui/material";
import { memo, useEffect, useState } from "react"; import { useEffect, useRef, useState } from "react";
import CalendarRow from "./CalendarRow/CalendarRow"; import CalendarRow from "./CalendarRow/CalendarRow";
import CalendarSmallCell from "./CalendarSmallCell/CalendarSmallCell"; import CalendarSmallCell from "./CalendarSmallCell/CalendarSmallCell";
import CalendarStandartCell from "./CalendarStandartCell.js/CalendarStandartCell"; import CalendarStandartCell from "./CalendarStandartCell.js/CalendarStandartCell";
import CalendarTask from "./CalendarTask/CalendarTask";
import ModalTask from "../UI/ModalTask/ModalTask"; import ModalTask from "../UI/ModalTask/ModalTask";
import MonthCalendarModalContent from "../MonthCalendarModalContent/MonthCalendarModalContent"; import MonthCalendarModalContent from "../MonthCalendarModalContent/MonthCalendarModalContent";
import CalendarRowDay from "./CalendarRowDay/CalendarRowDay";
function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, currentTask, setCurrentTask, hourFormat, setHourFormat, onChangeCurrentTaskHandler, sendNewTaskHandler, deleteTaskHandler, cellSizes, hoursInDay, daysInMonth}) { function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, currentTask, setCurrentTask, hourFormat, setHourFormat, onChangeCurrentTaskHandler, sendNewTaskHandler, deleteTaskHandler, cellSizes, hoursInDay, daysInMonth}) {
...@@ -25,11 +25,18 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current ...@@ -25,11 +25,18 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current
setModal({...modal, open: false}) setModal({...modal, open: false})
setCurrentTask({}) setCurrentTask({})
}; };
const divRef = useRef(null)
const [divHeight, setDivHeight] = useState('')
useEffect(() => {
if (divRef) {
setDivHeight(()=>{
return divRef.current?.offsetHeight
})
}
}, [divRef.current?.offsetHeight, hourFormat, month, tasks]);
return ( return (
<> <div ref={divRef} style={{marginBottom: '30px'}}>
<CalendarRow <CalendarRow
> >
<CalendarSmallCell xs={1.2}> <CalendarSmallCell xs={1.2}>
...@@ -41,7 +48,7 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current ...@@ -41,7 +48,7 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current
</CalendarSmallCell> </CalendarSmallCell>
{hoursInDay?.map((hours, i)=>{ {hoursInDay?.map((hours, i)=>{
return ( return (
<CalendarStandartCell key={i} xs={cellSizes.standarCell}> <CalendarStandartCell key={i} xs={cellSizes.standarCell} divRef={divHeight}>
{hours} {hours}
</CalendarStandartCell> </CalendarStandartCell>
) )
...@@ -54,32 +61,20 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current ...@@ -54,32 +61,20 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current
> >
<CalendarSmallCell xs={cellSizes.smallCell}>{day.dayNumber}</CalendarSmallCell> <CalendarSmallCell xs={cellSizes.smallCell}>{day.dayNumber}</CalendarSmallCell>
<CalendarSmallCell xs={cellSizes.smallCell}>{day.dayOfWeek}</CalendarSmallCell> <CalendarSmallCell xs={cellSizes.smallCell}>{day.dayOfWeek}</CalendarSmallCell>
{hoursInDay.map((hours, i)=>{ <CalendarRowDay
return ( xs={cellSizes.dayCell}
<CalendarStandartCell
key={i}
item xs={cellSizes.standarCell}
createTaskInCellHandler={createTaskInCellHandler} createTaskInCellHandler={createTaskInCellHandler}
hours={hours} hoursInDay={hoursInDay}
dayNumber={day.dayNumber}
currentTask={currentTask} currentTask={currentTask}
handleOpen={handleOpen} handleOpen={handleOpen}
modal={modal.open} modal={modal.open}
>
<CalendarTask
setCurrentTask={setCurrentTask} setCurrentTask={setCurrentTask}
year={year} year={year}
month={month} month={month}
tasks={tasks} tasks={tasks}
day={day} day={day}
hours={hours}
hourFormat={hourFormat} hourFormat={hourFormat}
handleOpen={handleOpen}
currentTask={currentTask}
/> />
</CalendarStandartCell>
)
})}
</CalendarRow> </CalendarRow>
) )
})} })}
...@@ -96,7 +91,7 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current ...@@ -96,7 +91,7 @@ function MonthCalendarBody({month, year, tasks, createTaskInCellHandler, current
deleteTaskHandler={()=>{deleteTaskHandler(currentTask.id); handleClose()}} deleteTaskHandler={()=>{deleteTaskHandler(currentTask.id); handleClose()}}
/> />
</ModalTask> </ModalTask>
</> </div>
); );
} }
......
...@@ -2,7 +2,13 @@ import * as React from "react"; ...@@ -2,7 +2,13 @@ import * as React from "react";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
import Input from "@mui/material/Input"; import Input from "@mui/material/Input";
const CustomTableCell = ({ task, name, value, onChange, onModalOpen }) => { const CustomTableCell = ({task,
name,
value,
onChange,
onModalOpen,
placeholder,
}) => {
const styles = { width: "auto", height: "10px"}; const styles = { width: "auto", height: "10px"};
if (task) { if (task) {
...@@ -15,6 +21,7 @@ const CustomTableCell = ({ task, name, value, onChange, onModalOpen }) => { ...@@ -15,6 +21,7 @@ const CustomTableCell = ({ task, name, value, onChange, onModalOpen }) => {
> >
{task.isEditMode && onChange ? ( {task.isEditMode && onChange ? (
<Input <Input
placeholder={placeholder}
value={value} value={value}
name={name} name={name}
onChange={(e) => onChange(e, task)} onChange={(e) => onChange(e, task)}
......
...@@ -4,6 +4,7 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; ...@@ -4,6 +4,7 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker"; import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment"; import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
export default function MaterialUIPickers(props) { export default function MaterialUIPickers(props) {
return ( return (
<LocalizationProvider <LocalizationProvider
...@@ -11,6 +12,7 @@ export default function MaterialUIPickers(props) { ...@@ -11,6 +12,7 @@ export default function MaterialUIPickers(props) {
sx={{ width: "auto", fontSize: 5, fontWeight: "200" }} sx={{ width: "auto", fontSize: 5, fontWeight: "200" }}
> >
<DateTimePicker <DateTimePicker
inputFormat="DD-MM-YYYY hh:mm A"
disabled={props.task.readOnly} disabled={props.task.readOnly}
renderInput={(params) => ( renderInput={(params) => (
<TextField <TextField
......
...@@ -5,25 +5,58 @@ import Toolbar from '@mui/material/Toolbar'; ...@@ -5,25 +5,58 @@ import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button'; import Button from '@mui/material/Button';
import MultipleSelect from '../../components/UI/MultipleSelect/MultipleSelect'; import MultipleSelect from '../../components/UI/MultipleSelect/MultipleSelect';
import Add from "@mui/icons-material/Add";
import Close from "@mui/icons-material/Close";
export default function MyTaskToolBar(props) { export default function MyTaskToolBar({projects,onClose,projectName,setProjectName,formStatus,onClick}) {
let projectsFilter =
<></>
if (projects) {
projectsFilter=
<MultipleSelect
projects={projects}
onClose={onClose}
projectName={projectName}
setProjectName={setProjectName}
/>
}
return ( return (
<Box sx={{ flexGrow: 1 }}> <Box sx={{ flexGrow: 1 }}>
<AppBar position="static"> <AppBar position="static">
<Toolbar> <Toolbar>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Мои задачи Мои задачи
</Typography> </Typography>
<MultipleSelect {projectsFilter}
projects={props.projects}
onClose={props.onClose} <Button
projectName={props.projectName} color={formStatus === true ? "info" : "inherit"}
setProjectName={props.setProjectName} style={{
/> backgroundColor: formStatus === true ? "white" : "inherit",
<Button color="inherit" onClick={props.onClick} >Добавить задачу</Button> }}
onClick={onClick}
>
{formStatus === true ? (
<>
<Close />
<span style={{ lineHeight: "16px" }}>Скрыть задачу</span>
</>
) : (
<>
<Add />
<span style={{ lineHeight: "16px" }}>Добавить задачу</span>
</>
)}
</Button>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
</Box> </Box>
); );
} }
import {Button, Grid} from "@mui/material";
import {useState} from "react";
import { useSelector } from "react-redux";
import FormElement from "../UI/Form/FormElement/FormElement";
const ProjectForm = ({onSubmit}) => {
const users = useSelector(state => state.users)
console.log(users)
const [state, setState] = useState({
title: "",
color: ""
});
const submitFormHandler = (e) => {
e.preventDefault();
let project = {title: state.title, color: state.color}
console.log(project);
onSubmit(project);
};
const inputChangeHandler = (e) => {
const {name, value} = e.target;
setState(prevState => {
return {...prevState, [name]: value};
});
};
return <form onSubmit={submitFormHandler}>
<Grid container direction="column" spacing={2}>
<FormElement
onChange={inputChangeHandler}
name={"title"}
label={"Title"}
state={state}
/>
<FormElement
onChange={inputChangeHandler}
name={"color"}
label={"Color"}
state={state}
/>
<Grid item>
<Button
type="submit"
color="primary"
variant="contained"
>
Create
</Button>
</Grid>
</Grid>
</form>
};
export default ProjectForm;
\ No newline at end of file
import { Card, CardActions, CardContent, Grid, IconButton } from "@mui/material";
import { Link } from "react-router-dom";
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
import { useDispatch, useSelector } from "react-redux";
const ProjectItem = ({ title, tasks, id }) => {
const user = useSelector(state => state.users.user);
const dispatch = useDispatch();
console.log(tasks)
return <>
<Grid item xs={12} sm={12} md={6} lg={4}>
<Card>
<CardContent>
<strong>
<br></br>
Название проекта: {title}
</strong>
<strong>
<br></br>
{/* Задачи: {tasks} */}
</strong>
</CardContent>
<CardActions>
<IconButton component={Link} to={"/projects/" + id}>
<ArrowForwardIcon />
</IconButton>
</CardActions>
</Card>
</Grid>
</>
};
export default ProjectItem;
import {Grid} from "@mui/material";
import ProjectItem from "../ProjectItem/ProjectItem";
const ProjectsList = ({projects}) => {
return (
<Grid item container direction="row" spacing={1}>
{projects?.map(project => {
return <ProjectItem
tasks={project.tasks}
workers={project.workers}
title={project.title}
createdAt={project.createdAt}
dateDue={project.dateDue}
admin={project.admin}
id={project.id}
key={project.id}
/>
})}
</Grid>
);
};
export default ProjectsList;
\ No newline at end of file
...@@ -5,7 +5,7 @@ const FormElement = ({ name, label, state, error, onChange, select, options, typ ...@@ -5,7 +5,7 @@ const FormElement = ({ name, label, state, error, onChange, select, options, typ
let inputChildren = null let inputChildren = null
if (select) { if (select) {
inputChildren = options.map(option => { inputChildren = options?.map(option => {
return <MenuItem key={option._id} value={option._id}> return <MenuItem key={option._id} value={option._id}>
{option.name} {option.name}
</MenuItem> </MenuItem>
......
...@@ -28,16 +28,15 @@ function getStyles(name, personName, theme) { ...@@ -28,16 +28,15 @@ function getStyles(name, personName, theme) {
}; };
} }
export default function MultipleSelect(props) { export default function MultipleSelect({projects,projectName,onClose,setProjectName}) {
const theme = useTheme(); const theme = useTheme();
const handleChange = (event) => { const handleChange = (event) => {
const { const {
target: { value }, target: { value },
} = event; } = event;
props.setProjectName( setProjectName(
// On autofill we get a stringified value. // On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value, typeof value === 'string' ? value.split(',') : value,
); );
...@@ -46,23 +45,25 @@ export default function MultipleSelect(props) { ...@@ -46,23 +45,25 @@ export default function MultipleSelect(props) {
return ( return (
<div> <div>
<FormControl sx={{ m: 1, width: 250,borderColor:'white' }}> <FormControl sx={{ m: 1, width: 250,borderColor:'white' }}>
<InputLabel id="demo-multiple-name-label" sx={{color:'white' }}>Project</InputLabel> <InputLabel placeholder='Choose Project' label='I am a really really long green TextField label' id="demo-multiple-name-label" sx={{color:'white', padding:'1' }}>Project</InputLabel>
<Select <Select
labelId="demo-multiple-name-label" labelId="demo-multiple-name-label"
label='Choose Project'
name='Choose Project'
id="demo-multiple-name" id="demo-multiple-name"
multiple multiple
value={props.projectName} value={projectName}
onChange={handleChange} onChange={handleChange}
input={<OutlinedInput label="Name" />} input={<OutlinedInput label="Name" />}
MenuProps={MenuProps} MenuProps={MenuProps}
sx={{color:'white' }} sx={{color:'white' }}
onClose={(e)=>{props.onClose(props.projectName)}} onClose={(e)=>{onClose(projectName)}}
> >
{props.projects.map((project) => ( {projects?.map((project) => (
<MenuItem <MenuItem
key={project} key={project}
value={project} value={project}
style={getStyles(project, props.projectName, theme)} style={getStyles(project, projectName, theme)}
> >
{project} {project}
</MenuItem> </MenuItem>
......
...@@ -5,7 +5,8 @@ import MenuItem from "@mui/material/MenuItem"; ...@@ -5,7 +5,8 @@ import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl"; import FormControl from "@mui/material/FormControl";
import Select from "@mui/material/Select"; import Select from "@mui/material/Select";
export default function BasicSelect(props) { export default function BasicSelect({value,label,name,onChange,task,items}) {
return ( return (
<Box sx={{ minWidth: 60 }}> <Box sx={{ minWidth: 60 }}>
<FormControl fullWidth> <FormControl fullWidth>
...@@ -13,17 +14,19 @@ export default function BasicSelect(props) { ...@@ -13,17 +14,19 @@ export default function BasicSelect(props) {
<Select <Select
labelId="demo-simple-select-label" labelId="demo-simple-select-label"
id="demo-simple-select" id="demo-simple-select"
value={props.task.accomplish} value={value}
label="" label={label}
name={"accomplish"} name={name}
onChange={(e) => props.onChange(e, props.task)} onChange={(e) => onChange(e, task)}
sx={{ marginTop: 2 }}
> >
{props.items.map((item) => ( {items.map((item) => (
<MenuItem value={item}>{item}</MenuItem> <MenuItem key={item.value} value={item.value}>
{item.title}
</MenuItem>
))} ))}
</Select> </Select>
</FormControl> </FormControl>
</Box> </Box>
); );
} }
...@@ -6,10 +6,10 @@ function СustomSelect({value, onChange, label, variant='standard', items, id}) ...@@ -6,10 +6,10 @@ function СustomSelect({value, onChange, label, variant='standard', items, id})
return ( return (
<> <>
<FormControl variant={variant} sx={{ m: 1, minWidth: 120 }}> <FormControl variant={variant} sx={{ m: 1, minWidth: 120 }}>
<InputLabel id={id + '-select' + '-label'}>{label}</InputLabel> <InputLabel id={`${id}-select-label`}>{label}</InputLabel>
<Select <Select
labelId={id + '-select'+ '-label'} labelId={`${id}-select-label`}
id={id + '-select'} id={`${id}-select`}
value={value} value={value}
onChange={onChange} onChange={onChange}
label={label} label={label}
......
import { Card, CardActions, CardContent, Grid } from "@mui/material";
import { useLocation, useParams } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { useEffect } from "react";
import { fetchProject } from "../../store/actions/projectsActions";
const FullProject = () => {
const { projects, project } = useSelector(state => state.projects);
const dispatch = useDispatch();
console.log(projects);
let location = useLocation();
let point = location.pathname
console.log(point.includes("admin"))
const params = useParams()
useEffect(() => {
dispatch(fetchProject(params.id))
}, [params.id, dispatch]);
console.log(project)
return <>
<Grid item xs={12} sm={12} md={6} lg={4}>
<Card>
<h2>Проект - {project?.project?.title}</h2>
<CardContent>
<strong>
<br></br>
Дата создания проекта: {project?.project?.createdAt}
</strong>
<strong>
<br></br>
Цвет: {project?.project?.color}
</strong>
<strong>
<br></br>
Админ проекта: {project?.project?.admin.name}
</strong>
<strong>
<br></br>
Задачи: {projects?.projects?.tasks?.map(task => {
return <>
<strong><br></br>Задача проекта: {task.title} </strong>
</>
})}
</strong>
</CardContent>
<CardActions>
</CardActions>
</Card>
</Grid>
</>
};
export default FullProject;
...@@ -13,7 +13,6 @@ function MonthCalendar() { ...@@ -13,7 +13,6 @@ function MonthCalendar() {
const [worker, setWorker] = useState(''); const [worker, setWorker] = useState('');
const [calendarType, setCalendarType] = useState('Месяц'); const [calendarType, setCalendarType] = useState('Месяц');
const [currentTask, setCurrentTask] = useState({title: '', description: '', priority: ''}) const [currentTask, setCurrentTask] = useState({title: '', description: '', priority: ''})
const [cellSizes, setCellSizes] = useState({}) const [cellSizes, setCellSizes] = useState({})
useEffect(()=>{ useEffect(()=>{
...@@ -31,7 +30,7 @@ function MonthCalendar() { ...@@ -31,7 +30,7 @@ function MonthCalendar() {
const cells = arr.length const cells = arr.length
const xs = 10.8/cells const xs = 10.8/cells
setCellSizes(()=>{ setCellSizes(()=>{
return {smallCell: 0.6, standarCell: xs} return {smallCell: 0.6, standarCell: xs, dayCell: 12/cells}
}) })
return arr return arr
} else { } else {
...@@ -39,7 +38,7 @@ function MonthCalendar() { ...@@ -39,7 +38,7 @@ function MonthCalendar() {
const cells = arr.length const cells = arr.length
const xs = 10.8/cells const xs = 10.8/cells
setCellSizes(()=>{ setCellSizes(()=>{
return {smallCell: 0.6, standarCell: xs} return {smallCell: 0.6, standarCell: xs, dayCell: 12/cells}
}) })
return arr return arr
} }
...@@ -122,12 +121,13 @@ function MonthCalendar() { ...@@ -122,12 +121,13 @@ function MonthCalendar() {
const sendNewTaskHandler = async () => { const sendNewTaskHandler = async () => {
if (currentTask.id) { if (currentTask.id) {
delete currentTask.infoForCell
console.log(currentTask)
setCurrentTask(() => { setCurrentTask(() => {
return{ return{
...currentTask, ...currentTask,
}} }}
) )
delete currentTask.infoForCell
await dispatch(editTask(currentTask)) await dispatch(editTask(currentTask))
} else { } else {
setCurrentTask(() => { setCurrentTask(() => {
...@@ -135,7 +135,6 @@ function MonthCalendar() { ...@@ -135,7 +135,6 @@ function MonthCalendar() {
...currentTask, ...currentTask,
}} }}
) )
console.log(currentTask)
delete currentTask.infoForCell delete currentTask.infoForCell
await dispatch(addTask(currentTask)) await dispatch(addTask(currentTask))
} }
......
import * as React from 'react'; import * as React from "react";
import PropTypes from 'prop-types'; import PropTypes from "prop-types";
import Box from '@mui/material/Box'; import Box from "@mui/material/Box";
import TableCell from '@mui/material/TableCell'; import TableCell from "@mui/material/TableCell";
import TableHead from '@mui/material/TableHead'; import TableHead from "@mui/material/TableHead";
import TableRow from '@mui/material/TableRow'; import TableRow from "@mui/material/TableRow";
import TableSortLabel from '@mui/material/TableSortLabel'; import TableSortLabel from "@mui/material/TableSortLabel";
import { visuallyHidden } from '@mui/utils'; import { visuallyHidden } from "@mui/utils";
const headCells = [ const headCells = [
{ {
id: 'id', id: "id",
numeric: true, numeric: true,
disablePadding: true, disablePadding: true,
label: '', label: "",
}, },
{ {
id: 'priority', id: "priority",
numeric: false, numeric: false,
disablePadding: true, disablePadding: true,
label: 'Приоритет', label: "Приоритет",
}, },
{ {
id: 'createdAt', id: "createdAt",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Дата создания', label: "Дата создания",
}, },
{ {
id: 'title', id: "title",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Заголовок', label: "Заголовок",
}, },
{ {
id: 'project', id: "projectName",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Проект', label: "Проект",
}, },
{ {
id: 'authorDisplayName', id: "authorDisplayName",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Автор', label: "Автор",
}, },
{ {
id: 'dateTimeStart', id: "dateTimeStart",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Дата начала', label: "Дата начала",
}, },
{ {
id: 'dateTimeDue', id: "dateTimeDue",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Дата завершения', label: "Дата завершения",
}, },
{ {
id: 'accomplish', id: "accomplish",
numeric: true, numeric: true,
disablePadding: false, disablePadding: false,
label: 'Статус', label: "Статус",
}, },
{ {
id: 'change', id: "change",
numeric: false, numeric: false,
disablePadding: false, disablePadding: false,
label: '', label: "",
}, },
{ {
id: 'delete', id: "delete",
numeric: false, numeric: false,
disablePadding: false, disablePadding: false,
label: '', label: "",
}, },
]; ];
export default function EnhancedTableHead(props) { export default function EnhancedTableHead({ order, orderBy, rowCount, onRequestSort }) {
const { order, orderBy, rowCount, onRequestSort } =
props;
const createSortHandler = (property) => (event) => { const createSortHandler = (property) => (event) => {
onRequestSort(event, property); onRequestSort(event, property);
}; };
...@@ -88,23 +86,22 @@ export default function EnhancedTableHead(props) { ...@@ -88,23 +86,22 @@ export default function EnhancedTableHead(props) {
return ( return (
<TableHead> <TableHead>
<TableRow> <TableRow>
{headCells.map((headCell) => ( {headCells.map((headCell) => (
<TableCell <TableCell
key={headCell.id} key={headCell.id}
align={'center'} align={"center"}
padding={headCell.disablePadding ? 'none' : 'normal'} padding={headCell.disablePadding ? "none" : "normal"}
sortDirection={orderBy === headCell.id ? order : false} sortDirection={orderBy === headCell.id ? order : false}
> >
<TableSortLabel <TableSortLabel
active={orderBy === headCell.id} active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : 'asc'} direction={orderBy === headCell.id ? order : "asc"}
onClick={createSortHandler(headCell.id)} onClick={createSortHandler(headCell.id)}
> >
{headCell.label} {headCell.label}
{orderBy === headCell.id ? ( {orderBy === headCell.id ? (
<Box component="span" sx={visuallyHidden}> <Box component="span" sx={visuallyHidden}>
{order === 'desc' ? 'sorted descending' : 'sorted ascending'} {order === "desc" ? "sorted descending" : "sorted ascending"}
</Box> </Box>
) : null} ) : null}
</TableSortLabel> </TableSortLabel>
...@@ -117,7 +114,7 @@ export default function EnhancedTableHead(props) { ...@@ -117,7 +114,7 @@ export default function EnhancedTableHead(props) {
EnhancedTableHead.propTypes = { EnhancedTableHead.propTypes = {
onRequestSort: PropTypes.func.isRequired, onRequestSort: PropTypes.func.isRequired,
order: PropTypes.oneOf(['asc', 'desc']).isRequired, order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired, orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired, rowCount: PropTypes.number.isRequired,
}; };
import {useNavigate} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import {Typography} from "@mui/material";
import { useEffect } from "react";
import ProjectForm from "../../components/ProjectForm/ProjectForm";
import { createProject, fetchProjects } from "../../store/actions/projectsActions";
const NewProject = () => {
const dispatch = useDispatch();
const projects = useSelector(state => state.projects.projects);
const navigate = useNavigate();
const onSubmit = async (projectData) => {
await dispatch(createProject(projectData, navigate));
};
useEffect(()=> {
dispatch(fetchProjects());
}, [dispatch])
return (
<>
<Typography variant="h2">New project</Typography>
<ProjectForm projects={projects} onSubmit={onSubmit} />
</>
);
};
export default NewProject;
\ No newline at end of file
import { Grid, Typography, Button } from "@mui/material";
import { Link } from "react-router-dom";
import { useEffect } from "react";
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";
const Projects = () => {
const dispatch = useDispatch();
const { projects, loading } = useSelector(state => state.projects.projects);
console.log(projects)
console.log(loading)
useEffect(() => {
dispatch(fetchProjects())
}, [dispatch]);
return <>
{projects?.length > 0 ? (<>
<Grid container direction="column" spacing={2}>
<Grid
container
item
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item>
<Typography variant="h4">
Projects
</Typography>
</Grid>
<HasAccess roles={["superuser", "admin", "user"]} >
<Grid item>
<Button component={Link} to="/projects/add">
Add project
</Button>
</Grid>
</HasAccess>
</Grid>
<Loader loading={loading} />
<ProjectsList projects={projects} />
</Grid>
</>) :
<h1>Созданных проектов нет</h1>
}
</>
};
export default Projects;
\ No newline at end of file
...@@ -7,6 +7,7 @@ import { Provider } from 'react-redux'; ...@@ -7,6 +7,7 @@ import { Provider } from 'react-redux';
import usersReducer from './store/reducers/usersReducer'; import usersReducer from './store/reducers/usersReducer';
import tasksReducer from './store/reducers/tasksReducer'; import tasksReducer from './store/reducers/tasksReducer';
import axios from './axiosPlanner'; import axios from './axiosPlanner';
import projectsReducer from './store/reducers/projectsReducer';
const localStorageMiddleware = ({getState}) => (next) => (action) => { const localStorageMiddleware = ({getState}) => (next) => (action) => {
const result = next(action); const result = next(action);
...@@ -25,7 +26,8 @@ const loadFromLocalStorage = () => { ...@@ -25,7 +26,8 @@ const loadFromLocalStorage = () => {
const store = configureStore({ const store = configureStore({
reducer: { reducer: {
users: usersReducer, users: usersReducer,
tasks: tasksReducer tasks: tasksReducer,
projects: projectsReducer
}, },
preloadedState: loadFromLocalStorage(), preloadedState: loadFromLocalStorage(),
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(localStorageMiddleware) middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(localStorageMiddleware)
......
export const FETCH_PROJECTS_REQUEST = "FETCH_PROJECTS_REQUEST";
export const FETCH_PROJECTS_SUCCESS = "FETCH_PROJECTS_SUCCESS";
export const FETCH_PROJECTS_ERROR = "FETCH_PROJECTS_ERROR";
export const FETCH_PROJECT_SUCCESS = "FETCH_PROJECT_SUCCESS";
export const CREATE_PROJECT_SUCCESS = "CREATE_PROJECT_SUCCESS";
...@@ -8,6 +8,10 @@ export const ADD_NEW_TASK_REQUEST = "ADD_NEW_TASK_REQUEST"; ...@@ -8,6 +8,10 @@ export const ADD_NEW_TASK_REQUEST = "ADD_NEW_TASK_REQUEST";
export const ADD_NEW_TASK_SUCCESS = "ADD_NEW_TASK_SUCCESS"; export const ADD_NEW_TASK_SUCCESS = "ADD_NEW_TASK_SUCCESS";
export const ADD_NEW_TASK_FAILURE = "ADD_NEW_TASK_FAILURE"; export const ADD_NEW_TASK_FAILURE = "ADD_NEW_TASK_FAILURE";
export const FETCH_TASKS_BY_PROJECT_REQUEST = "FETCH_TASKS_BY_PROJECT_REQUEST";
export const FETCH_TASKS_BY_PROJECT_SUCCESS = "FETCH_TASKS_BY_PROJECT_SUCCESS";
export const FETCH_TASKS_BY_PROJECT_FAILURE = "FETCH_TASKS_BY_PROJECT_FAILURE";
export const EDIT_TASK_REQUEST = "EDIT_TASK_REQUEST"; export const EDIT_TASK_REQUEST = "EDIT_TASK_REQUEST";
export const EDIT_TASK_SUCCESS = "EDIT_TASK_SUCCESS"; export const EDIT_TASK_SUCCESS = "EDIT_TASK_SUCCESS";
export const EDIT_TASK_FAILURE = "EDIT_TASK_FAILURE"; export const EDIT_TASK_FAILURE = "EDIT_TASK_FAILURE";
...@@ -15,3 +19,5 @@ export const EDIT_TASK_FAILURE = "EDIT_TASK_FAILURE"; ...@@ -15,3 +19,5 @@ export const EDIT_TASK_FAILURE = "EDIT_TASK_FAILURE";
export const DELETE_TASK_REQUEST = "DELETE_TASK_REQUEST"; export const DELETE_TASK_REQUEST = "DELETE_TASK_REQUEST";
export const DELETE_TASK_SUCCESS = "DELETE_TASK_SUCCESS"; export const DELETE_TASK_SUCCESS = "DELETE_TASK_SUCCESS";
export const DELETE_TASK_FAILURE = "DELETE_TASK_FAILURE"; export const DELETE_TASK_FAILURE = "DELETE_TASK_FAILURE";
export const EDIT_CALENDAR_TASK = "EDIT_CALENDAR_TASK";
\ No newline at end of file
import axios from "../../axiosPlanner";
import { CREATE_PROJECT_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
import { showNotification } from "./commonActions";
const fetchProjectsRequest = () => {
return {type: FETCH_PROJECTS_REQUEST}
};
const fetchProjectsSuccess = (projects) => {
return {type: FETCH_PROJECTS_SUCCESS, projects};
};
const fetchProjectSuccess = (project) => {
return {type: FETCH_PROJECT_SUCCESS, project};
};
const fetchProjectsError = (error) => {
return {type: FETCH_PROJECTS_ERROR, error};
}
const createProjectSuccess = () => {
return {type: CREATE_PROJECT_SUCCESS};
};
export const fetchProjects = () => {
return async dispatch => {
dispatch(fetchProjectsRequest());
try {
const response = await axios.get("/projects");
dispatch(fetchProjectsSuccess(response.data));
} catch(e) {
dispatch(fetchProjectsError(e));
}
};
};
export const fetchProject = (id) => {
return async dispatch => {
dispatch(fetchProjectsRequest());
try {
const response = await axios.get("/projects/" + id);
dispatch(fetchProjectSuccess(response.data));
} catch (e) {
dispatch(fetchProjectsError(e));
}
}
};
export const createProject = (projectData, navigate) => {
return async (dispatch) => {
try {
await axios.post("/projects", projectData);
dispatch(createProjectSuccess());
navigate("/");
dispatch(showNotification("Проект успешно создан"))
} catch (e) {
console.log(e);
dispatch(showNotification("Не удалось создать проект", "error"))
}
};
}
\ No newline at end of file
...@@ -11,7 +11,11 @@ import { ...@@ -11,7 +11,11 @@ import {
FETCH_CALENDAR_TASKS_FAILURE, FETCH_CALENDAR_TASKS_FAILURE,
FETCH_CALENDAR_TASKS_REQUEST, FETCH_CALENDAR_TASKS_REQUEST,
FETCH_CALENDAR_TASKS_SUCCESS, FETCH_CALENDAR_TASKS_SUCCESS,
FETCH_ALL_TASKS_SUCCESS} from "../actionTypes/tasksTypes"; FETCH_ALL_TASKS_SUCCESS,
FETCH_TASKS_BY_PROJECT_SUCCESS,
FETCH_TASKS_BY_PROJECT_FAILURE,
FETCH_TASKS_BY_PROJECT_REQUEST
} from "../actionTypes/tasksTypes";
import axios from '../../axiosPlanner' import axios from '../../axiosPlanner'
const fetchCalendarTasksRequest = () => { const fetchCalendarTasksRequest = () => {
...@@ -65,13 +69,33 @@ const addTaskFailure = (error) => { ...@@ -65,13 +69,33 @@ const addTaskFailure = (error) => {
return {type: ADD_NEW_TASK_FAILURE, error} return {type: ADD_NEW_TASK_FAILURE, error}
}; };
// export const addTask = (task) => {
// return async (dispatch, getState) => {
// dispatch(addTaskRequest());
// const token = getState().users?.user?.token;
// try {
// await axios.post("/tasks", task, {
// headers: {
// Authorization: token,
// },
// });
// dispatch(addTaskSuccess());
// dispatch(fetchCalendarTasks());
// } catch (error) {
// dispatch(addTaskFailure(error.response.data));
// }
// };
// };
export const addTask = (task) => { export const addTask = (task) => {
return async (dispatch, getState) => { return async (dispatch, getState) => {
dispatch(addTaskRequest()); dispatch(addTaskRequest());
const token = getState().users?.user?.token; // const token = getState().users?.user?.token;
try { try {
await axios.post("/tasks", task); await axios.post("/tasks", task);
dispatch(addTaskSuccess()) dispatch(addTaskSuccess())
dispatch(fetchAllTasks())
dispatch(fetchCalendarTasks()) dispatch(fetchCalendarTasks())
} catch (error) { } catch (error) {
dispatch(addTaskFailure(error.response.data)); dispatch(addTaskFailure(error.response.data));
...@@ -96,9 +120,7 @@ export const editTask = (task) => { ...@@ -96,9 +120,7 @@ export const editTask = (task) => {
dispatch(editTaskRequest()); dispatch(editTaskRequest());
// const token = getState().users?.user?.token; // const token = getState().users?.user?.token;
try { try {
console.log('task' , task) await axios.put("/tasks/", task);
const r=await axios.put("/tasks/", task);
console.log(r)
dispatch(editTaskSuccess()) dispatch(editTaskSuccess())
dispatch(fetchAllTasks()) dispatch(fetchAllTasks())
dispatch(fetchCalendarTasks()) dispatch(fetchCalendarTasks())
...@@ -134,3 +156,28 @@ export const deleteTask = (taskId) => { ...@@ -134,3 +156,28 @@ export const deleteTask = (taskId) => {
} }
} }
} }
const fetchTasksByProjectRequest = () => {
return {type: FETCH_TASKS_BY_PROJECT_REQUEST}
};
const fetchTasksByProjectSuccess = () => {
return {type: FETCH_TASKS_BY_PROJECT_SUCCESS}
};
const fetchTasksByProjectFailure = (error) => {
return {type: FETCH_TASKS_BY_PROJECT_FAILURE, error}
};
export const fetchTasksByProject = (projects) => {
return async (dispatch) => {
dispatch(fetchTasksByProjectRequest());
try {
const response =await axios.post("/tasks/project", projects);
dispatch(fetchTasksByProjectSuccess(response.data.tasks))
} catch (error) {
dispatch(fetchTasksByProjectFailure(error.response.data));
}
}
}
\ No newline at end of file
import axios from "../../axiosPlanner"; import axios from "../../axiosPlanner";
import { LOGIN_USER_FAILURE, LOGIN_USER_SUCCESS, LOGOUT_USER_FAILURE, LOGOUT_USER_SUCCESS, REGISTER_USER_FAILURE, REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS } from "../actionTypes/actionTypes" import { 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 { showNotification } from "./commonActions"; import { showNotification } from "./commonActions";
const registerUserRequest = () => { const registerUserRequest = () => {
...@@ -18,9 +18,7 @@ export const registerUser = (userData, navigate) => { ...@@ -18,9 +18,7 @@ export const registerUser = (userData, navigate) => {
return async (dispatch) => { return async (dispatch) => {
dispatch(registerUserRequest()); dispatch(registerUserRequest());
try { try {
console.log("register " + userData)
const response = await axios.post("/users", userData); const response = await axios.post("/users", userData);
console.log(response)
dispatch(registerUserSuccess()) dispatch(registerUserSuccess())
navigate("/") navigate("/")
} catch (error) { } catch (error) {
...@@ -51,9 +49,7 @@ const logoutUserFailure = (error) => { ...@@ -51,9 +49,7 @@ const logoutUserFailure = (error) => {
export const loginUser = (userData, navigate) => { export const loginUser = (userData, navigate) => {
return async (dispatch) => { return async (dispatch) => {
try { try {
console.log(userData)
const response = await axios.post("users/sessions", userData); const response = await axios.post("users/sessions", userData);
console.log(response)
dispatch(loginUserSuccess(response.data.user)); dispatch(loginUserSuccess(response.data.user));
navigate("/") navigate("/")
} catch (e) { } catch (e) {
......
import {FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes";
const initialState = {
projects: [],
project: "",
loading: false,
error: null
};
const projectsReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_PROJECTS_REQUEST:
return {...state, loading: true};
case FETCH_PROJECTS_SUCCESS:
return {...state, loading: false, projects: action.projects};
case FETCH_PROJECTS_ERROR:
return {...state, loading: false, error: action.error};
case FETCH_PROJECT_SUCCESS:
return {...state, loading: false, project: action.project}
default:
return state;
}
};
export default projectsReducer;
\ No newline at end of file
...@@ -11,7 +11,12 @@ import { ...@@ -11,7 +11,12 @@ import {
DELETE_TASK_SUCCESS, DELETE_TASK_SUCCESS,
DELETE_TASK_REQUEST, DELETE_TASK_REQUEST,
DELETE_TASK_FAILURE, DELETE_TASK_FAILURE,
FETCH_ALL_TASKS_SUCCESS} from "../actionTypes/tasksTypes"; FETCH_ALL_TASKS_SUCCESS,
EDIT_CALENDAR_TASK,
FETCH_TASKS_BY_PROJECT_REQUEST,
FETCH_TASKS_BY_PROJECT_SUCCESS,
FETCH_TASKS_BY_PROJECT_FAILURE
} from "../actionTypes/tasksTypes";
const initialState = { const initialState = {
calendarTasks: [], calendarTasks: [],
...@@ -38,7 +43,8 @@ const tasksReduсer = (state = initialState, action) => { ...@@ -38,7 +43,8 @@ const tasksReduсer = (state = initialState, action) => {
const timeEndHour = parseInt(timeEnd.split(':')[0]) const timeEndHour = parseInt(timeEnd.split(':')[0])
const timeStartMinute = parseInt(timeStart.split(':')[1]) const timeStartMinute = parseInt(timeStart.split(':')[1])
const timeEndMinute = parseInt(timeEnd.split(':')[1]) const timeEndMinute = parseInt(timeEnd.split(':')[1])
newArr.push({...task, infoForCell: { const newObj = {...task,
infoForCell: {
startDay: dayStart, startDay: dayStart,
startHour: timeStartHour, startHour: timeStartHour,
startMonth: monthStartNumber, startMonth: monthStartNumber,
...@@ -47,7 +53,8 @@ const tasksReduсer = (state = initialState, action) => { ...@@ -47,7 +53,8 @@ const tasksReduсer = (state = initialState, action) => {
endHour: timeEndHour, endHour: timeEndHour,
endMinute: timeEndMinute, endMinute: timeEndMinute,
} }
} ) }
newArr.push(newObj)
} }
} }
}) })
...@@ -62,6 +69,12 @@ const tasksReduсer = (state = initialState, action) => { ...@@ -62,6 +69,12 @@ const tasksReduсer = (state = initialState, action) => {
return {...state, loading: true}; return {...state, loading: true};
case ADD_NEW_TASK_FAILURE: case ADD_NEW_TASK_FAILURE:
return {...state, loading: false, error: action.error}; return {...state, loading: false, error: action.error};
case FETCH_TASKS_BY_PROJECT_SUCCESS:
return {...state, loading: false, tasks: action.tasks};
case FETCH_TASKS_BY_PROJECT_REQUEST:
return {...state, loading: true};
case FETCH_TASKS_BY_PROJECT_FAILURE:
return {...state, loading: false, error: action.error};
case EDIT_TASK_SUCCESS: case EDIT_TASK_SUCCESS:
return {...state, loading: false}; return {...state, loading: false};
case EDIT_TASK_REQUEST: case EDIT_TASK_REQUEST:
......
import { REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE, LOGIN_USER_SUCCESS, LOGIN_USER_FAILURE, LOGOUT_USER_SUCCESS } from "../actionTypes/actionTypes"; import { REGISTER_USER_REQUEST, REGISTER_USER_SUCCESS, REGISTER_USER_FAILURE, LOGIN_USER_SUCCESS, LOGIN_USER_FAILURE, LOGOUT_USER_SUCCESS } from "../actionTypes/userActionTypes";
const initialState = { const initialState = {
user: null, user: null,
......
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