Commit ec1e6f5a authored by Ermolaev Timur's avatar Ermolaev Timur

Merge branch 'development' of…

Merge branch 'development' of ssh://git.attractor-school.com:30022/apollo64/crm-team-one into task-86-feature/create_e2e_tests
parents ae140696 487bdf00
...@@ -25,7 +25,14 @@ export const auth = async(req: Request,res: Response, next:NextFunction):Promise ...@@ -25,7 +25,14 @@ export const auth = async(req: Request,res: Response, next:NextFunction):Promise
/**Check if user with the given token is executor or author of task with the given Id(taskId) */ /**Check if user with the given token is executor or author of task with the given Id(taskId) */
export const authAuthorOrExecutorOfTask = async(req: Request,res: Response, next:NextFunction):Promise<void | express.Response<Response>>=>{ export const authAuthorOrExecutorOfTask = async(req: Request,res: Response, next:NextFunction):Promise<void | express.Response<Response>>=>{
const token = req.get('Authorization'); const token = req.get('Authorization');
const {taskId} = req.body let taskId = null
taskId = req.body.taskId
if (req.body?.taskId) {
taskId = req.body.taskId
} else if (req.params?.taskId){
taskId = req.params.taskId
} else return res.send({vessage:"there are no taskId found"})
if(!token) return res.status(401).send({Message:'token not exists'}) if(!token) return res.status(401).send({Message:'token not exists'})
req.body={...req.body,executorStatus:false} req.body={...req.body,executorStatus:false}
...@@ -53,15 +60,51 @@ export const authAuthorOrExecutorOfTask = async(req: Request,res: Response, next ...@@ -53,15 +60,51 @@ export const authAuthorOrExecutorOfTask = async(req: Request,res: Response, next
}, },
]}) ]})
if (!task) return res.status(404).send({message:'task with possible user involved is not found'}) if (!task) return res.status(404).send({message:'task with possible user involved is not found'})
if(task?.executor?.token === token) {
req.body={...req.body,executorStatus:true}
}
if (task?.author?.token === token ) { if (task?.author?.token === token ) {
req.body={...req.body,authorStatus:true} req.body={...req.body,authorStatus:true}
} else if(task?.executor?.token === token) {
req.body={...req.body,executorStatus:true}
} else {
} }
next() next()
}; };
/**Check if user with the given token is executor or author of task with the given dateTimeTaskId */
export const authAuthorOrExecutorOfDateTimeTask = async(req: Request,res: Response, next:NextFunction):Promise<void | express.Response<Response>>=>{
const token = req.get('Authorization');
let dateTimeTaskId = null
req.body={...req.body,executorStatus:false}
req.body={...req.body,authorStatus:false}
dateTimeTaskId = req.body.dateTimeTaskId
if (req.body?.dateTimeTaskId) {
dateTimeTaskId = req.body.dateTimeTaskId
} else if (req.params?.dateTimeTaskId){
dateTimeTaskId = req.params.dateTimeTaskId
} else return res.send({vessage:"there are no dateTimeTaskId found"})
const task = await dataSource
.createQueryBuilder()
.select(["task"])
.from(Task,"task")
.leftJoinAndSelect("task.executor","user")
.leftJoinAndSelect("task.dateTimeTasks","dateTimeTask")
.leftJoinAndSelect("task.author","users")
.where("dateTimeTask.id = :dateTimeTaskId", {dateTimeTaskId})
.getOne()
if (!task) return res.status(404).send({message:'task with possible user involved is not found'})
if(task?.executor?.token === token) {
req.body={...req.body,executorStatus:true}
}
if (task?.author?.token === token ) {
req.body={...req.body,authorStatus:true}
}
next()
}
/**task finder by id, return one task */ /**task finder by id, return one task */
export const taskFinderById = async (taskId:string):Promise<null | Task>=>{ export const taskFinderById = async (taskId:string):Promise<null | Task>=>{
const task = await dataSource const task = await dataSource
......
...@@ -5,7 +5,7 @@ import { User } from '../models/User'; ...@@ -5,7 +5,7 @@ import { User } from '../models/User';
import { Member } from '../models/Member'; import { Member } from '../models/Member';
import { In } from 'typeorm'; import { In } from 'typeorm';
import { DateTimeTask } from '../models/DateTimeTask'; import { DateTimeTask } from '../models/DateTimeTask';
import { auth, authAuthorOrExecutorOfTask } from '../helpers'; import { auth, authAuthorOrExecutorOfDateTimeTask, authAuthorOrExecutorOfTask } from '../helpers';
const router:Router = express.Router(); const router:Router = express.Router();
const dataSource = myDataSource; const dataSource = myDataSource;
...@@ -41,8 +41,9 @@ router.post("/make-copy", async(req:Request, res:Response):Promise<Response>=>{ ...@@ -41,8 +41,9 @@ router.post("/make-copy", async(req:Request, res:Response):Promise<Response>=>{
} ) } )
/** change date time of copy of task in calendar view */ /** change date time of copy of task in calendar view */
router.put("/change-copy", authAuthorOrExecutorOfTask, async(req:Request, res: Response):Promise<Response>=>{ router.put("/change-copy/:dateTimeTaskId", authAuthorOrExecutorOfTask, async(req:Request, res: Response):Promise<Response>=>{
const {dateTimeTaskId, taskId, dateTimeStart, dateTimeDue, description, title, priority} = req.body const {dateTimeTaskId} = req.params
const {executorStatus, taskId, dateTimeStart, dateTimeDue, description, title, priority} = req.body
const dateTimeTask = await dataSource const dateTimeTask = await dataSource
.createQueryBuilder() .createQueryBuilder()
.select('dateTimeTask') .select('dateTimeTask')
...@@ -63,15 +64,18 @@ router.put("/change-copy", authAuthorOrExecutorOfTask, async(req:Request, res: R ...@@ -63,15 +64,18 @@ router.put("/change-copy", authAuthorOrExecutorOfTask, async(req:Request, res: R
}) })
/**delete copyTask by dateTimeTaskId */ /**delete copyTask by dateTimeTaskId */
router.delete('/:id', authAuthorOrExecutorOfTask, async(req:Request, res:Response):Promise<Response>=>{ router.delete('/:dateTimeTaskId',authAuthorOrExecutorOfDateTimeTask, async(req:Request, res:Response):Promise<Response|void>=>{
const {id} = req.params const {executorStatus} = req.body
if(executorStatus){
const {dateTimeTaskId} = req.params
await myDataSource await myDataSource
.createQueryBuilder() .createQueryBuilder()
.delete() .delete()
.from(DateTimeTask) .from(DateTimeTask)
.where("id = :id", { id }) .where("id = :dateTimeTaskId", { dateTimeTaskId })
.execute() .execute()
return res.send({message:"delete succesfully"}) return res.send({message:"copyTask delete succesfully"})
}
} }
) )
......
...@@ -121,6 +121,7 @@ router.get('/user/:userId', async (req : Request, res : Response): Promise<Respo ...@@ -121,6 +121,7 @@ router.get('/user/:userId', async (req : Request, res : Response): Promise<Respo
router.post('/add-user/', async (req: Request, res: Response):Promise<Response>=>{ router.post('/add-user/', async (req: Request, res: Response):Promise<Response>=>{
const {userId, projectId, roleProject} = req.body; const {userId, projectId, roleProject} = req.body;
console.log("req body" + req.body)
const newMember:Member = new Member(); const newMember:Member = new Member();
try{ try{
newMember.user= userId; newMember.user= userId;
......
...@@ -157,8 +157,9 @@ router.delete('/:taskId',async (req: Request, res: Response):Promise<Response>=> ...@@ -157,8 +157,9 @@ router.delete('/:taskId',async (req: Request, res: Response):Promise<Response>=>
/**change of task by task id */ /**change of task by task id */
router.put('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> { router.put('/:taskId',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> {
const {authorStatus,executorStatus,taskId,title,description,note, archive,project,dateTimeTaskId,dateTimeStart,dateTimeDue,executor,accomplish,dateTimeDeadLine, dateTimeFactDeadLine,priority} = req.body; const {taskId} = req.params
const {authorStatus,executorStatus,title,description,note, archive,project,dateTimeTaskId,dateTimeStart,dateTimeDue,executor,accomplish,dateTimeDeadLine, dateTimeFactDeadLine,priority} = req.body;
const task = await taskFinderById(taskId) const task = await taskFinderById(taskId)
if (!task) return res.status(404).send({Message:'task not found'}) if (!task) return res.status(404).send({Message:'task not found'})
let dateTimeTask = null; let dateTimeTask = null;
......
import { Box, Button, Grid, Modal } from "@mui/material";
import { useState } from "react";
import { useSelector } from "react-redux";
import FormElement from "../UI/Form/FormElement/FormElement";
import { Typography } from "@mui/material";
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';
import Autocomplete from '@mui/material/Autocomplete';
import { useParams } from "react-router-dom";
import PersonAddIcon from '@mui/icons-material/PersonAdd';
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
p: 4,
};
const MemberForm = ({ onSubmit }) => {
const users = useSelector(state => state.users.users)
const [role, setRole] = useState([{ role: "user" }, { role: "admin" }, { role: "watcher" }])
const params = useParams()
console.log(users)
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [state, setState] = useState({
displayName: "",
roleProject: "",
userId: "",
projectId: ""
});
const submitFormHandler = (e) => {
e.preventDefault();
let idOfUser = users?.map((user) => (user.displayName === state.displayName) ? user.id : null)
let idOfUser1 = users?.map((user) => {
console.log(user)
return null
})
console.log(idOfUser1)
console.log(idOfUser)
console.log("state of submit " + state);
let members = {roleProject: state.roleProject, projectId: params.id, userId: idOfUser }
console.log(members);
onSubmit(members);
};
// const onChange = (e) => {
// const value = e.target.value;
// const name = e.target.name;
// const newState= { ...state, [name]: value };
// console.log("newState " + newState)
// console.log("e.target " + e.target)
// console.log("e " + e)
// setState(newState);
// };
const memberChangeHandler = (e, value) => {
setState(() => { return { ...state, member: value, userId: state.userId} });
console.log("memberChangeHandler" + value)
}
const roleChangeHandler = (e, value) => {
setState(() => { return { ...state, roleProject: value } });
console.log(value)
}
return (
<div >
<PersonAddIcon onClick={handleOpen} style={{marginLeft: "30px", marginTop: "-3px"}} >Добавить участника</PersonAddIcon>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<Box sx={style}>
<form onSubmit={submitFormHandler}>
<Grid container direction="column" spacing={2}>
<Typography variant="h5" style={{margin: "5px", textAlign: "center"}} >Новый участник</Typography>
<Autocomplete
id="free-solo-demo"
freeSolo
options={users?.map((user) => user.displayName)}
onChange={memberChangeHandler}
name={"userId"}
value={state.userId}
renderInput={(params) => <TextField
style={{margin: "5px"}}
label={"Участник"}
state={state}
{...params} />}
/>
<Autocomplete
id="free-solo-demo"
freeSolo
options={role?.map((role) => role.role)}
value={state.roleProject}
onChange={roleChangeHandler}
renderInput={(params) => <TextField
style={{margin: "5px"}}
name={"roleProject"}
label={"Роль в проекте"}
state={state}
{...params} />}
/>
<Grid item>
<Button
type="submit"
color="primary"
variant="contained"
>
Create
</Button>
</Grid>
</Grid>
</form>
</Box>
</Modal>
</div>
);
};
export default MemberForm;
\ No newline at end of file
...@@ -13,6 +13,7 @@ import { ...@@ -13,6 +13,7 @@ import {
} from "@mui/material"; } from "@mui/material";
import { Done, Edit } from "@mui/icons-material"; import { Done, Edit } from "@mui/icons-material";
import RemoveIcon from '@mui/icons-material/Remove';
import DeleteIcon from "@mui/icons-material/Delete"; import DeleteIcon from "@mui/icons-material/Delete";
import moment from "moment"; import moment from "moment";
import CustomTableCell from "../CustomTableCell"; import CustomTableCell from "../CustomTableCell";
...@@ -22,13 +23,15 @@ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; ...@@ -22,13 +23,15 @@ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'; import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
const weekDays = ["Вс","Пн","Вт","Ср","Чт","Пт","Сб" ];
const TableRowTask= ({ const TableRowTask= ({
user, user,
task, task,
deleteHandle, deleteHandle,
handleEditTask, handleEditTask,
deleteDateTimeTask,
// handleEditDateTimeTask,
onChange, onChange,
onModalOpen, onModalOpen,
onProjectChange, onProjectChange,
...@@ -40,16 +43,21 @@ const TableRowTask= ({ ...@@ -40,16 +43,21 @@ const TableRowTask= ({
})=>{ })=>{
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const dateTimeTransform =(dateIso)=>{
const event = new Date(dateIso); const roudHourUp =(dateIso)=>{
return event.toLocaleString('ru-KZ', { timeZone: 'UTC' }) let m = moment(dateIso);
} let roundUp = m.minute() || m.second() || m.millisecond() ? m.add(1, 'hour').startOf('hour') : m.startOf('hour');
const dateTransform =(dateIso) => { return roundUp
let date = new Date(dateIso);
return date.getDate()+'-' + (date.getMonth()+1) + '-'+ date.getFullYear().toString().slice(-2);
} }
const timeTransform = (dateIso)=>{ const timeTransform = (dateIso)=>{
return moment.utc(dateIso).format("HH:"+"00"); const exp = roudHourUp(moment.utc(dateIso)).format("HH:"+"00")
return exp;
}
const getDayOfWeek = (dateIso) => {
const date = moment.utc(dateIso);
return weekDays[date.day()];
} }
return ( return (
...@@ -298,23 +306,30 @@ const TableRowTask= ({ ...@@ -298,23 +306,30 @@ const TableRowTask= ({
<Typography variant="h6" gutterBottom component="div"> <Typography variant="h6" gutterBottom component="div">
Расписание Расписание
</Typography> </Typography>
<Table size="small" aria-label="purchases"> <Table size="small" aria-label="purchases" sx={{
backgroundColor: "#ebebeb"}}>
<TableHead> <TableHead>
<TableRow> <TableRow>
<TableCell colSpan={10} >Дата создания события</TableCell> <TableCell colSpan={10} >Дата создания</TableCell>
<TableCell align="right">дд-мм-гг</TableCell> <TableCell align="right">День недели</TableCell>
<TableCell align="right">Начало</TableCell> <TableCell align="right">Начало</TableCell>
<TableCell align="center" colSpan={1}>Окончание</TableCell> <TableCell align="center" colSpan={1}>Окончание</TableCell>
<TableCell align="center" ></TableCell>
<TableCell align="center" ></TableCell>
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
{task.dateTimeTasks.map((dateTimeTask, index) => ( {task.dateTimeTasks.map((dateTimeTask, index) => (
<TableRow key={index}> <TableRow key={index}>
<TableCell component="th" scope="row" colSpan={10}> <TableCell component="th" scope="row" colSpan={10}>
{dateTimeTransform(dateTimeTask.createdAt)} {moment(task.createdAt)
.utc()
.format("DD/MM")}
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">
{dateTransform(dateTimeTask.dateTimeStart)} {getDayOfWeek(dateTimeTask.dateTimeStart)}, {moment(dateTimeTask.dateTimeStart)
.utc()
.format("DD/MM")}
</TableCell> </TableCell>
<TableCell align="right"> <TableCell align="right">
{timeTransform(dateTimeTask.dateTimeStart)} {timeTransform(dateTimeTask.dateTimeStart)}
...@@ -322,6 +337,48 @@ const TableRowTask= ({ ...@@ -322,6 +337,48 @@ const TableRowTask= ({
<TableCell align="center" colSpan={1}> <TableCell align="center" colSpan={1}>
{timeTransform(dateTimeTask.dateTimeDue)} {timeTransform(dateTimeTask.dateTimeDue)}
</TableCell> </TableCell>
{/* Edit option datetimeTask */}
<TableCell
// style={{width:'0%'}}
>
{/* <Tooltip title="Редактировать Копию">
{task.isEditMode ? (
<IconButton
aria-label="done"
onClick={() => {
onToggleEditModeDone(dateTimeTask.id);
handleEditDateTimeTask(dateTimeTask);
}}
>
<Done />
</IconButton>
) : (
<IconButton
aria-label="edit"
onClick={() => onToggleEditMode(dateTimeTask.id)}
>
<Edit />
</IconButton>
)}
</Tooltip> */}
</TableCell >
{/* delete option datetimeTask */}
{task.author.id===user.id ?
(<TableCell style={{width:'0%'}}>
<Tooltip title="Удалить Копию">
<IconButton
onClick={(id) => {
deleteDateTimeTask(dateTimeTask.id);
}}
>
<RemoveIcon />
</IconButton>
</Tooltip>
</TableCell>):null}
</TableRow> </TableRow>
))} ))}
</TableBody> </TableBody>
......
...@@ -45,7 +45,7 @@ const ProjectForm = ({onSubmit}) => { ...@@ -45,7 +45,7 @@ const ProjectForm = ({onSubmit}) => {
return ( return (
<div > <div >
<Button onClick={handleOpen} >Add project</Button> <Button onClick={handleOpen} >Добавить проект</Button>
<Modal <Modal
open={open} open={open}
onClose={handleClose} onClose={handleClose}
...@@ -56,7 +56,7 @@ const ProjectForm = ({onSubmit}) => { ...@@ -56,7 +56,7 @@ const ProjectForm = ({onSubmit}) => {
<Box sx={style}> <Box sx={style}>
<form > <form >
<Grid container direction="column" spacing={2}> <Grid container direction="column" spacing={2}>
<Typography variant="h4">New project</Typography> <Typography variant="h4">Новый проект</Typography>
<FormElement <FormElement
onChange={inputChangeHandler} onChange={inputChangeHandler}
name={"title"} name={"title"}
...@@ -70,7 +70,7 @@ const ProjectForm = ({onSubmit}) => { ...@@ -70,7 +70,7 @@ const ProjectForm = ({onSubmit}) => {
variant="contained" variant="contained"
> >
Create Создать
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
......
...@@ -7,12 +7,12 @@ import { useDispatch, useSelector } from "react-redux"; ...@@ -7,12 +7,12 @@ import { useDispatch, useSelector } from "react-redux";
const ProjectItem = ({ title, tasks, id }) => { const ProjectItem = ({ title, tasks, id }) => {
const user = useSelector(state => state.users.user); const user = useSelector(state => state.users.user);
const dispatch = useDispatch(); const dispatch = useDispatch();
console.log(tasks) console.log(user)
return <> return <>
<Grid item xs={12} sm={12} md={6} lg={4}> <Grid item xs={12} sm={12} md={6} lg={4}>
<Card> <Card>
<CardContent> <CardContent >
<strong> <strong>
<br></br> <br></br>
Название проекта: {title} Название проекта: {title}
......
import { Card, CardActions, CardContent, Grid, IconButton } from "@mui/material"; import { Card, CardActions, CardContent, Grid, IconButton, Tooltip } from "@mui/material";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import DeleteIcon from "@mui/icons-material/Delete";
const ProjectMembersItem = ({ displayName, roleProject, id, roleProjectOfAuthor }) => {
const ProjectMembersItem = ({ displayName, id }) => { console.log(displayName)
const dispatch = useDispatch(); const dispatch = useDispatch();
const user = useSelector(state => state.users)
console.log(user)
const { projects, project } = useSelector(state => state.projects); const { projects, project } = useSelector(state => state.projects);
return <> return <>
...@@ -18,11 +21,22 @@ const ProjectMembersItem = ({ displayName, id }) => { ...@@ -18,11 +21,22 @@ const ProjectMembersItem = ({ displayName, id }) => {
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
роль: {project?.project?.members[0]?.roleProject} роль: {roleProject}
</strong> </strong>
<strong> <strong>
<br></br>
<button>delete</button> {roleProjectOfAuthor === "admin" ?
(<strong>
<Tooltip title="Удалить">
<IconButton
onClick={(id) => {
// deleteHandle(task.id);
}}
>
<DeleteIcon style={{ marginTop: "-5px" }} />
</IconButton>
</Tooltip>
</strong>) : null}
</strong> </strong>
</CardContent> </CardContent>
</Card> </Card>
......
import {Grid} from "@mui/material"; import {Grid} from "@mui/material";
import ProjectMembersItem from "../ProjectMembersItem/ProjectMembersItem"; import ProjectMembersItem from "../ProjectMembersItem/ProjectMembersItem";
const ProjectMembersList = ({users}) => { const ProjectMembersList = ({members, roleProjectOfAuthor}) => {
console.log(users) console.log("members ", members)
return ( return (
<Grid item container direction="row" spacing={1}> <Grid item container direction="column" spacing={1}>
{users?.map(user => { {members?.map(member => {
return <ProjectMembersItem return <ProjectMembersItem
displayName={user.displayName} displayName={member?.user?.displayName}
id={user.id} roleProject={member?.roleProject}
key={user.id} id={member.id}
key={member.id}
roleProjectOfAuthor={roleProjectOfAuthor}
/> />
})} })}
</Grid> </Grid>
......
...@@ -2,8 +2,9 @@ import {Grid} from "@mui/material"; ...@@ -2,8 +2,9 @@ import {Grid} from "@mui/material";
import ProjectItem from "../ProjectItem/ProjectItem"; import ProjectItem from "../ProjectItem/ProjectItem";
const ProjectsList = ({projects}) => { const ProjectsList = ({projects}) => {
console.log(projects)
return ( return (
<Grid item container direction="row" spacing={1}> <Grid item container direction="column" spacing={1}>
{projects?.map(project => { {projects?.map(project => {
return <ProjectItem return <ProjectItem
tasks={project.tasks} tasks={project.tasks}
......
import { Grid, TextField, MenuItem } from "@mui/material"; import { Grid, TextField, MenuItem } from "@mui/material";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
const FormElement = ({ name, label, state, error, onChange, select, options, type = "'text" }) => { const FormElement = ({ name, label, state, error, onChange, select, options, type = "'text", users}) => {
let inputChildren = null let inputChildren = null
if (select) { if (select) {
...@@ -19,6 +19,7 @@ const FormElement = ({ name, label, state, error, onChange, select, options, typ ...@@ -19,6 +19,7 @@ const FormElement = ({ name, label, state, error, onChange, select, options, typ
type={type} type={type}
variant="outlined" variant="outlined"
value={state?.[name]} value={state?.[name]}
users={users}
onChange={onChange} onChange={onChange}
error={!!error} error={!!error}
helperText={error} helperText={error}
......
...@@ -6,6 +6,7 @@ import { fetchProject } from "../../store/actions/projectsActions"; ...@@ -6,6 +6,7 @@ import { fetchProject } from "../../store/actions/projectsActions";
import ProjectTasksBody from "../../components/ProjectTasks/ProjectTasksBody"; import ProjectTasksBody from "../../components/ProjectTasks/ProjectTasksBody";
import { fetchUsers } from "../../store/actions/usersActions"; import { fetchUsers } from "../../store/actions/usersActions";
import ProjectMembersList from "../../components/ProjectMembersList/ProjectMembersList"; import ProjectMembersList from "../../components/ProjectMembersList/ProjectMembersList";
import NewMember from "../NewMember/NewMember";
const FullProject = () => { const FullProject = () => {
...@@ -28,7 +29,7 @@ const FullProject = () => { ...@@ -28,7 +29,7 @@ const FullProject = () => {
useEffect(() => { useEffect(() => {
dispatch(fetchProject(params.id)) dispatch(fetchProject(params.id))
}, [params.id, dispatch]); }, [params.id, dispatch]);
console.log(project); console.log("project ", project);
return <> return <>
<Grid item xs={12} sm={12} md={6} lg={4}> <Grid item xs={12} sm={12} md={6} lg={4}>
...@@ -53,9 +54,13 @@ const FullProject = () => { ...@@ -53,9 +54,13 @@ const FullProject = () => {
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
<div style={{display: 'flex', direction: 'column'}}>
Участники проекта: Участники проекта:
<NewMember members={project?.project?.members} />
<ProjectMembersList users={users} project={project}/> </div>
<ProjectMembersList users={users} project={project} members={project?.project?.members} roleProjectOfAuthor={project?.project?.members[0]?.roleProject} />
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
......
...@@ -13,7 +13,7 @@ import TaskModal from "../../components/MyTasksCompoments/TaskModal/TaskModal"; ...@@ -13,7 +13,7 @@ import TaskModal from "../../components/MyTasksCompoments/TaskModal/TaskModal";
import EnhancedTableHead from "./MyTasksHeader/MyTasksHeader"; import EnhancedTableHead from "./MyTasksHeader/MyTasksHeader";
import moment from "moment"; import moment from "moment";
import MyTaskToolBar from "../../components/MyTasksCompoments/MyTaskToolBar"; import MyTaskToolBar from "../../components/MyTasksCompoments/MyTaskToolBar";
import { fetchAllTasks, deleteTask,editTask} from "../../store/actions/tasksActions"; import { fetchAllTasks, deleteTask,editTask, deleteDateTimeTask} from "../../store/actions/tasksActions";
import NewTaskForm from "../../components/MyTasksCompoments/NewTaskForm"; import NewTaskForm from "../../components/MyTasksCompoments/NewTaskForm";
import TableRowTask from "../../components/MyTasksCompoments/TableRowTask/TableRowTask"; import TableRowTask from "../../components/MyTasksCompoments/TableRowTask/TableRowTask";
...@@ -44,7 +44,7 @@ export default function EnhancedTable() { ...@@ -44,7 +44,7 @@ export default function EnhancedTable() {
if (tasks && tasks?.length > 0) { if (tasks && tasks?.length > 0) {
setRecievedTasks(tasks); setRecievedTasks(tasks);
} }
}, [tasks?.length]); }, [dispatch, tasks?.length]);
useEffect(() => { useEffect(() => {
dispatch(fetchAllTasks()); dispatch(fetchAllTasks());
...@@ -162,6 +162,16 @@ useEffect(() => { ...@@ -162,6 +162,16 @@ useEffect(() => {
dispatch(deleteTask(id)); dispatch(deleteTask(id));
}; };
const deleteDateTimeTaskHandle=(dateTimeTaskId)=>{
console.log('delete by dateTimeTaskId ', dateTimeTaskId)
dispatch(deleteDateTimeTask(dateTimeTaskId))
}
const handleEditDateTimeTask=(dateTimeTask)=>{
console.log('edit by dateTImeTask')
// dispatch(handleEditDateTimeTask(dateTimeTask))
}
const onModalOpen = (event, task) => { const onModalOpen = (event, task) => {
event.stopPropagation(); event.stopPropagation();
...@@ -261,6 +271,8 @@ console.log('tasks', tasks) ...@@ -261,6 +271,8 @@ console.log('tasks', tasks)
task={task} task={task}
deleteHandle={deleteHandle} deleteHandle={deleteHandle}
handleEditTask ={handleEditTask} handleEditTask ={handleEditTask}
handleEditDateTimeTask={handleEditDateTimeTask}
deleteDateTimeTask={deleteDateTimeTaskHandle}
onChange={onChange} onChange={onChange}
onModalOpen={onModalOpen} onModalOpen={onModalOpen}
onProjectChange={onProjectChange} onProjectChange={onProjectChange}
......
import {useNavigate} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux";
import { useEffect } from "react";
import ProjectForm from "../../components/ProjectForm/ProjectForm";
import { createMember, createProject, fetchMembers, fetchProjects } from "../../store/actions/projectsActions";
import MemberForm from "../../components/MemberForm/MemberForm";
const NewMember = ({members}) => {
const dispatch = useDispatch();
const projects = useSelector(state => state.projects.projects);
const navigate = useNavigate();
const onSubmit = async (memberData) => {
await dispatch(createMember(memberData, navigate));
// navigate("/projects/" + memberData.id)
console.log("memberData ", memberData)
};
// useEffect(()=> {
// dispatch(fetchMembers());
// }, [dispatch])
return (
<>
<MemberForm members={members} onSubmit={onSubmit} />
</>
);
};
export default NewMember;
\ No newline at end of file
...@@ -13,7 +13,6 @@ const NewProject = () => { ...@@ -13,7 +13,6 @@ const NewProject = () => {
const onSubmit = async (projectData) => { const onSubmit = async (projectData) => {
await dispatch(createProject(projectData, navigate)); await dispatch(createProject(projectData, navigate));
console.log(projectData) console.log(projectData)
}; };
useEffect(()=> { useEffect(()=> {
......
...@@ -12,6 +12,7 @@ const Projects = () => { ...@@ -12,6 +12,7 @@ const Projects = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { projects, loading } = useSelector(state => state.projects.projects); const { projects, loading } = useSelector(state => state.projects.projects);
const {users} = useSelector(state => state.users); const {users} = useSelector(state => state.users);
const members = useSelector(state => state.projects.projects)
console.log(projects) console.log(projects)
console.log(users) console.log(users)
...@@ -32,7 +33,7 @@ const Projects = () => { ...@@ -32,7 +33,7 @@ const Projects = () => {
> >
<Grid item> <Grid item>
<Typography variant="h4"> <Typography variant="h4">
Projects Проекты
</Typography> </Typography>
</Grid> </Grid>
<HasAccess roles={["superuser", "admin", "user"]} > <HasAccess roles={["superuser", "admin", "user"]} >
...@@ -42,7 +43,7 @@ const Projects = () => { ...@@ -42,7 +43,7 @@ const Projects = () => {
</HasAccess> </HasAccess>
</Grid> </Grid>
<Loader loading={loading} /> <Loader loading={loading} />
<ProjectsList projects={projects} /> <ProjectsList projects={projects} members={members} />
</Grid> </Grid>
</>) : </>) :
<h1>Созданных проектов нет</h1> <h1>Созданных проектов нет</h1>
......
export const FETCH_PROJECTS_REQUEST = "FETCH_PROJECTS_REQUEST"; export const FETCH_PROJECTS_REQUEST = "FETCH_PROJECTS_REQUEST";
export const FETCH_PROJECTS_SUCCESS = "FETCH_PROJECTS_SUCCESS"; export const FETCH_PROJECTS_SUCCESS = "FETCH_PROJECTS_SUCCESS";
export const FETCH_PROJECTS_ERROR = "FETCH_PROJECTS_ERROR"; export const FETCH_PROJECTS_ERROR = "FETCH_PROJECTS_ERROR";
export const FETCH_PROJECT_SUCCESS = "FETCH_PROJECT_SUCCESS"; export const FETCH_PROJECT_SUCCESS = "FETCH_PROJECT_SUCCESS";
export const CREATE_PROJECT_SUCCESS = "CREATE_PROJECT_SUCCESS"; export const CREATE_PROJECT_SUCCESS = "CREATE_PROJECT_SUCCESS";
export const CREATE_MEMBER_SUCCESS = "CREATE_MEMBER_SUCCESS";
\ No newline at end of file
...@@ -21,3 +21,7 @@ export const DELETE_TASK_SUCCESS = "DELETE_TASK_SUCCESS"; ...@@ -21,3 +21,7 @@ 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"; export const EDIT_CALENDAR_TASK = "EDIT_CALENDAR_TASK";
export const DELETE_DATETIMETASK_REQUEST = "DELETE_TASK_REQUEST";
export const DELETE_DATETIMETASK_SUCCESS = "DELETE_TASK_SUCCESS";
export const DELETE_DATETIMETASK_FAILURE = "DELETE_TASK_FAILURE";
\ No newline at end of file
import axios from "../../axiosPlanner"; import axios from "../../axiosPlanner";
import { CREATE_PROJECT_SUCCESS, FETCH_PROJECTS_ERROR, FETCH_PROJECTS_REQUEST, FETCH_PROJECTS_SUCCESS, FETCH_PROJECT_SUCCESS } from "../actionTypes/projectsActionTypes"; import { CREATE_MEMBER_SUCCESS, CREATE_PROJECT_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"; import { showNotification } from "./commonActions";
const fetchProjectsRequest = () => { const fetchProjectsRequest = () => {
...@@ -8,17 +8,21 @@ const fetchProjectsRequest = () => { ...@@ -8,17 +8,21 @@ const fetchProjectsRequest = () => {
const fetchProjectsSuccess = (projects) => { const fetchProjectsSuccess = (projects) => {
return {type: FETCH_PROJECTS_SUCCESS, projects}; return {type: FETCH_PROJECTS_SUCCESS, projects};
}; };
const fetchProjectSuccess = (project) => {
return {type: FETCH_PROJECT_SUCCESS, project};
};
const fetchProjectsError = (error) => { const fetchProjectsError = (error) => {
return {type: FETCH_PROJECTS_ERROR, error}; return {type: FETCH_PROJECTS_ERROR, error};
} }
const fetchProjectSuccess = (project) => {
return {type: FETCH_PROJECT_SUCCESS, project};
};
const createProjectSuccess = () => { const createProjectSuccess = () => {
return {type: CREATE_PROJECT_SUCCESS}; return {type: CREATE_PROJECT_SUCCESS};
}; };
const createMemberSuccess = (member) => {
return {type: CREATE_MEMBER_SUCCESS, member};
};
export const fetchProjects = () => { export const fetchProjects = () => {
return async dispatch => { return async dispatch => {
dispatch(fetchProjectsRequest()); dispatch(fetchProjectsRequest());
...@@ -37,6 +41,7 @@ export const fetchProject = (id) => { ...@@ -37,6 +41,7 @@ export const fetchProject = (id) => {
try { try {
const response = await axios.get("/projects/" + id); const response = await axios.get("/projects/" + id);
dispatch(fetchProjectSuccess(response.data)); dispatch(fetchProjectSuccess(response.data));
console.log("fetch project "+response.data)
} catch (e) { } catch (e) {
dispatch(fetchProjectsError(e)); dispatch(fetchProjectsError(e));
} }
...@@ -57,3 +62,20 @@ export const createProject = (projectData, navigate) => { ...@@ -57,3 +62,20 @@ export const createProject = (projectData, navigate) => {
} }
}; };
} }
export const createMember = (memberData, navigate) => {
return async (dispatch) => {
try {
console.log(memberData)
const response = await axios.post("/projects/add-user", memberData);
dispatch(createMemberSuccess());
console.log(memberData)
navigate("/projects/")
dispatch(showNotification("Участник успешно добавлен"))
} catch (e) {
console.log(e);
dispatch(showNotification("Не удалось добавить участника", "error"))
}
};
}
...@@ -14,7 +14,10 @@ import { ...@@ -14,7 +14,10 @@ import {
FETCH_ALL_TASKS_SUCCESS, FETCH_ALL_TASKS_SUCCESS,
FETCH_TASKS_BY_PROJECT_SUCCESS, FETCH_TASKS_BY_PROJECT_SUCCESS,
FETCH_TASKS_BY_PROJECT_FAILURE, FETCH_TASKS_BY_PROJECT_FAILURE,
FETCH_TASKS_BY_PROJECT_REQUEST FETCH_TASKS_BY_PROJECT_REQUEST,
DELETE_DATETIMETASK_FAILURE,
DELETE_DATETIMETASK_SUCCESS,
DELETE_DATETIMETASK_REQUEST,
} from "../actionTypes/tasksTypes"; } from "../actionTypes/tasksTypes";
import axios from '../../axiosPlanner' import axios from '../../axiosPlanner'
...@@ -210,3 +213,30 @@ export const fetchTasksByProject = (projects) => { ...@@ -210,3 +213,30 @@ export const fetchTasksByProject = (projects) => {
} }
} }
} }
const deleteDateTimeTaskRequest = () => {
return {type: DELETE_DATETIMETASK_REQUEST}
};
const deleteDateTimeTaskSuccess = () => {
return {type: DELETE_DATETIMETASK_SUCCESS}
};
const deleteDateTimeTaskFailure = (error) => {
return {type: DELETE_DATETIMETASK_FAILURE, error}
};
export const deleteDateTimeTask = (dateTimeTaskId) => {
return async (dispatch) => {
dispatch(deleteDateTimeTaskRequest());
try {
await axios.delete(`/copy-tasks/${dateTimeTaskId}`);
dispatch(deleteDateTimeTaskSuccess())
dispatch(fetchAllTasks())
} catch (error) {
dispatch(deleteDateTimeTaskFailure(error.response.data));
}
}
}
...@@ -15,7 +15,10 @@ import { ...@@ -15,7 +15,10 @@ import {
EDIT_CALENDAR_TASK, EDIT_CALENDAR_TASK,
FETCH_TASKS_BY_PROJECT_REQUEST, FETCH_TASKS_BY_PROJECT_REQUEST,
FETCH_TASKS_BY_PROJECT_SUCCESS, FETCH_TASKS_BY_PROJECT_SUCCESS,
FETCH_TASKS_BY_PROJECT_FAILURE FETCH_TASKS_BY_PROJECT_FAILURE,
DELETE_DATETIMETASK_FAILURE,
DELETE_DATETIMETASK_SUCCESS,
DELETE_DATETIMETASK_REQUEST
} from "../actionTypes/tasksTypes"; } from "../actionTypes/tasksTypes";
const initialState = { const initialState = {
...@@ -102,6 +105,12 @@ const tasksReduсer = (state = initialState, action) => { ...@@ -102,6 +105,12 @@ const tasksReduсer = (state = initialState, action) => {
return {...state, loading: true}; return {...state, loading: true};
case DELETE_TASK_FAILURE: case DELETE_TASK_FAILURE:
return {...state, loading: false, error: action.error}; return {...state, loading: false, error: action.error};
case DELETE_DATETIMETASK_SUCCESS:
return {...state, loading: false};
case DELETE_DATETIMETASK_REQUEST:
return {...state, loading: true};
case DELETE_DATETIMETASK_FAILURE:
return {...state, loading: false, error: action.error};
default: default:
return state; return state;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment