Commit 6ab13d0f 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-78-fix/fix_logic_calendar_tasks
parents 923dc0c1 a09aa306
...@@ -24,32 +24,39 @@ export const auth = async(req: Request,res: Response, next:NextFunction):Promise ...@@ -24,32 +24,39 @@ export const auth = async(req: Request,res: Response, next:NextFunction):Promise
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 const {taskId} = req.body
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}
req.body={...req.body,authorStatus:false} req.body={...req.body,authorStatus:false}
const executor = await dataSource
.createQueryBuilder() const task = await dataSource
.select("user") .getRepository(Task)
.from(User, "user") .findOne({
.leftJoinAndSelect("user.tasks", "task") relations:{
.where("user.token = :token", { token: token }) executor:true,
.getOne(); author:true,
console.log('executor', executor) },
if (executor) { where:[
req.body={...req.body,executorStatus:true} {
id:taskId,
executor:{
token:token
} }
const author = await dataSource },
.createQueryBuilder() {
.select("user") id:taskId,
.from(User, "user") author:{
.leftJoinAndSelect("user.createdTasks", "task") token:token
.where("user.token = :token", { token: token }) }
.getOne(); },
console.log('author', author) ]})
if (author) { if (!task) return res.status(404).send({message:'task with possible user involved is not found'})
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 {
} }
if(!author && !executor)return res.status(401).send({Message:'user is not authorized'})
next() next()
}; };
......
...@@ -7,7 +7,8 @@ import { ...@@ -7,7 +7,8 @@ import {
ManyToOne, ManyToOne,
OneToOne, OneToOne,
JoinTable, JoinTable,
OneToMany OneToMany,
JoinColumn
} from 'typeorm'; } from 'typeorm';
import {User} from './User'; import {User} from './User';
import {Project} from './Project'; import {Project} from './Project';
...@@ -28,9 +29,9 @@ import { DateTimeTask } from './DateTimeTask'; ...@@ -28,9 +29,9 @@ import { DateTimeTask } from './DateTimeTask';
priority: priorityType | null; priority: priorityType | null;
archive:boolean, archive:boolean,
author: User; author: User;
executor:User;
project:Project|null; project:Project|null;
dateTimeTasks:DateTimeTask[]|null; dateTimeTasks:DateTimeTask[]|null;
executor:User;
} }
@Entity({ name: 'Task' }) @Entity({ name: 'Task' })
...@@ -73,8 +74,7 @@ import { DateTimeTask } from './DateTimeTask'; ...@@ -73,8 +74,7 @@ import { DateTimeTask } from './DateTimeTask';
@ManyToOne(() => User, (user: { tasks: Task[]; }) => user.tasks,{eager : true}) @ManyToOne(() => User, (user: { tasks: Task[]; }) => user.tasks,{eager : true})
author!: User; author!: User;
@ManyToOne(() =>User, (user: { tasks: Task[]}) => user.tasks,{eager : true,nullable: true, onUpdate:'CASCADE'}) @ManyToOne(() =>User, (user: { tasks: Task[]}) => user.tasks,{nullable: true,cascade: true, onUpdate:'CASCADE', eager : true,})
@JoinTable()
executor!: User; executor!: User;
@ManyToOne(()=>Project,(project:{tasks: Task[]}) => project.tasks,{eager : true,nullable: true,onUpdate:'CASCADE'}) @ManyToOne(()=>Project,(project:{tasks: Task[]}) => project.tasks,{eager : true,nullable: true,onUpdate:'CASCADE'})
......
...@@ -25,7 +25,7 @@ router.get('/', async(req:Request, res:Response):Promise<Response> => { ...@@ -25,7 +25,7 @@ router.get('/', async(req:Request, res:Response):Promise<Response> => {
/**create new task */ /**create new task */
router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{ router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
const {user,title,description,project,executor, dateTimeDeadLine,priority, dateTimeStart, dateTimeDue} = req.body; const {user,title,description,project,executor,dateTimeStart,dateTimeDue, dateTimeDeadLine,priority} = req.body;
const newTask = new Task(); const newTask = new Task();
newTask.title = title; newTask.title = title;
newTask.description = description; newTask.description = description;
...@@ -158,7 +158,7 @@ router.delete('/:taskId',async (req: Request, res: Response):Promise<Response>=> ...@@ -158,7 +158,7 @@ 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('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> {
const {authorStatus,executorStatus,taskId,title,description,note, archive,project,dateTimeTaskId,start,due,executor,accomplish,dateTimeDeadLine, dateTimeFactDeadLine,priority} = req.body; const {authorStatus,executorStatus,taskId,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;
...@@ -173,6 +173,12 @@ router.put('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> { ...@@ -173,6 +173,12 @@ router.put('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> {
dateTimeTask = dateTimeTaskData dateTimeTask = dateTimeTaskData
} }
if (dateTimeTask!==null) {
dateTimeTask.dateTimeStart = dateTimeStart
dateTimeTask.dateTimeDue = dateTimeDue
await dateTimeTask.save()
}
if (authorStatus){ if (authorStatus){
task.title = title task.title = title
task.description= description task.description= description
...@@ -182,13 +188,9 @@ router.put('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> { ...@@ -182,13 +188,9 @@ router.put('/',authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> {
task.executor=executor task.executor=executor
task.priority= priority task.priority= priority
} }
if(executorStatus && dateTimeTask!==null){ if(executorStatus){
dateTimeTask.dateTimeStart = start
dateTimeTask.dateTimeDue = due
await dateTimeTask.save()
task.note = note task.note = note
task.dateTimeFactDeadLine= dateTimeFactDeadLine task.dateTimeFactDeadLine= dateTimeFactDeadLine
} }
task.accomplish= accomplish task.accomplish= accomplish
await task.save() await task.save()
......
...@@ -51,14 +51,6 @@ const App = () => { ...@@ -51,14 +51,6 @@ const App = () => {
<FullProject/> <FullProject/>
</ProtectedRoute> </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 WorkerMenu = () => { ...@@ -10,7 +10,7 @@ const WorkerMenu = () => {
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);
}; };
......
.modal{ .modal{
width: 200px;
height: 200px;
background-color: rgb(180, 243, 243);
display: flex; display: flex;
margin:10% 20%; flex-direction: column;
padding: 30px; padding: 10px;
word-break: break-all; align-items: center;
transition-duration:0.5s; position: absolute;
top: 200px;
left: 200px;
width: 300px;
height: 300px;
background-color: white;
border: 2px solid #000;
box-shadow: 24px;
border-radius:5px
} }
.modalBox{ .modalBox{
display: flex; display: flex;
......
...@@ -2,64 +2,95 @@ import { Modal, IconButton } from "@mui/material"; ...@@ -2,64 +2,95 @@ import { Modal, IconButton } from "@mui/material";
import "./TaskModal.css"; import "./TaskModal.css";
import { Done } from "@mui/icons-material"; import { Done } from "@mui/icons-material";
import Input from "@mui/material/Input"; import Input from "@mui/material/Input";
import TextField from "@mui/material/Input";
const TaskModal = ({handleClose,open,task,onChange,user }) => { const TaskModal = ({handleClose,open,task,onChange,user }) => {
return ( return (
<Modal <Modal
aria-labelledby="transition-modal-title" aria-labelledby="modal-modal-title"
aria-describedby="transition-modal-description" aria-describedby="modal-modal-description"
className={"modal"} BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }}
closeAfterTransition closeAfterTransition
onClose={handleClose} onClose={handleClose}
open={open} open={open}
> >
{task?.isEditMode && task.author.id===user.id ? ( {task?.isEditMode && task.author.id===user.id ? (
<div className="modalBox"> <div className="modal">
<Input <Input
label="название"
color="secondary"
value={task.title} value={task.title}
name="title" name="title"
onChange={(e) => onChange(e, task)} onChange={(e) => onChange(e, task)}
style={{ style={{
width: "auto", width: "auto",
fontSize: "12px",
color: "white",
fontWeight: "600", fontWeight: "600",
height: "40px",
fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}} }}
/> />
<Input <TextField
label="описание"
value={task.description} value={task.description}
name="description" name="description"
onChange={(e) => onChange(e, task)} onChange={(e) => onChange(e, task)}
style={{ width: "auto", fontSize: "12px", color: "white" }} multiline={true}
sx={{
fontWeight: "400",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px",
height:"300px",
whiteSpace:"normal"
}}
/> />
<IconButton aria-label="done" onClick={handleClose}> <IconButton aria-label="done" onClick={handleClose}
sx={{margingBottom:"5px",marginTop:"auto"}}>
<Done /> <Done />
</IconButton> </IconButton>
</div> </div>
) : ( ) : (
<div className="modalBox"> <div className="modal">
{task && task.title && ( {task && task.title && (
<div <div
style={{ style={{
width: "200px", height: "40px",
height: "200px",
color: "white",
fontWeight: "600", fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}} }}
> >
{task.title} {task.title}
</div> </div>
)} )}
{task && task.description && ( {task && task.description && (
<div style={{ width: "200px", height: "200px", color: "white" }}> <div
style={{margin:"10px",
border: '2px solid #D3D3D3',
borderRadius:"5px",
width:"280px",
height: "200px",
margin:"10px",
padding:"5px",
}}>
{task.description} {task.description}
</div> </div>
)} )}
<IconButton <IconButton
sx={{ marginLeft: 0, color: "white" }}
aria-label="close" aria-label="close"
onClick={handleClose} onClick={handleClose}
sx={{margingBottom:"5px",marginTop:"auto"}}
> >
X X
</IconButton> </IconButton>
......
import {Button, Grid} from "@mui/material"; import {Box, Button, Grid, Modal} from "@mui/material";
import {useState} from "react"; import {useState} from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import FormElement from "../UI/Form/FormElement/FormElement"; import FormElement from "../UI/Form/FormElement/FormElement";
import {Typography} from "@mui/material";
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 ProjectForm = ({onSubmit}) => { const ProjectForm = ({onSubmit}) => {
const users = useSelector(state => state.users) const users = useSelector(state => state.users)
console.log(users) console.log(users)
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const [state, setState] = useState({ const [state, setState] = useState({
title: "", title: ""
color: ""
}); });
const submitFormHandler = (e) => { const submitFormHandler = (e) => {
e.preventDefault(); e.preventDefault();
let project = {title: state.title, color: state.color} let project = {title: state.title}
console.log(project); console.log(project);
onSubmit(project); onSubmit(project);
}; };
const inputChangeHandler = (e) => { const inputChangeHandler = (e) => {
...@@ -26,31 +42,44 @@ const ProjectForm = ({onSubmit}) => { ...@@ -26,31 +42,44 @@ const ProjectForm = ({onSubmit}) => {
}); });
}; };
return <form onSubmit={submitFormHandler}> return (
<div >
<Button onClick={handleOpen} >Add project</Button>
<Modal
open={open}
onClose={handleClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
onSubmit={submitFormHandler}
>
<Box sx={style}>
<form >
<Grid container direction="column" spacing={2}> <Grid container direction="column" spacing={2}>
<Typography variant="h4">New project</Typography>
<FormElement <FormElement
onChange={inputChangeHandler} onChange={inputChangeHandler}
name={"title"} name={"title"}
label={"Title"} label={"Title"}
state={state} state={state}
/>
<FormElement
onChange={inputChangeHandler}
name={"color"}
label={"Color"}
state={state}
/> />
<Grid item> <Grid item>
<Button <Button
type="submit" type="submit"
color="primary" color="primary"
variant="contained" variant="contained"
> >
Create Create
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
</form> </form>
</Box>
</Modal>
</div>
);
}; };
export default ProjectForm; export default ProjectForm;
\ No newline at end of file
...@@ -34,7 +34,7 @@ const FullProject = () => { ...@@ -34,7 +34,7 @@ const FullProject = () => {
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
Админ проекта: {project?.project?.members} {/* Админ проекта: {project?.project?.members} */}
</strong> </strong>
<strong> <strong>
<br></br> <br></br>
......
...@@ -388,9 +388,6 @@ console.log(tasks) ...@@ -388,9 +388,6 @@ console.log(tasks)
.format("hh:mm A"), .format("hh:mm A"),
user:user user:user
}}> }}>
{/* <span>"время завершения"+ {moment(task.dateTimeDue)
.utc()
.format("hh:mm A")}</span> */}
</CustomTableCell> </CustomTableCell>
</> </>
...@@ -475,7 +472,8 @@ console.log(tasks) ...@@ -475,7 +472,8 @@ console.log(tasks)
)} )}
</Tooltip> </Tooltip>
</TableCell> </TableCell>
<TableCell> {task.author.id===user.id ?
(<TableCell>
<Tooltip title="Удалить"> <Tooltip title="Удалить">
<IconButton <IconButton
onClick={(id) => { onClick={(id) => {
...@@ -485,7 +483,8 @@ console.log(tasks) ...@@ -485,7 +483,8 @@ console.log(tasks)
<DeleteIcon /> <DeleteIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</TableCell> </TableCell>):null}
</TableRow> </TableRow>
); );
})} })}
......
import {useNavigate} from "react-router-dom"; import {useNavigate} from "react-router-dom";
import {useDispatch, useSelector} from "react-redux"; import {useDispatch, useSelector} from "react-redux";
import {Typography} from "@mui/material";
import { useEffect } from "react"; import { useEffect } from "react";
import ProjectForm from "../../components/ProjectForm/ProjectForm"; import ProjectForm from "../../components/ProjectForm/ProjectForm";
import { createProject, fetchProjects } from "../../store/actions/projectsActions"; import { createProject, fetchProjects } from "../../store/actions/projectsActions";
...@@ -9,8 +9,12 @@ const NewProject = () => { ...@@ -9,8 +9,12 @@ const NewProject = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const projects = useSelector(state => state.projects.projects); const projects = useSelector(state => state.projects.projects);
const navigate = useNavigate(); const navigate = useNavigate();
let lastProject = projects.projects[projects.projects.length - 1];
const onSubmit = async (projectData) => { const onSubmit = async (projectData) => {
await dispatch(createProject(projectData, navigate)); await dispatch(createProject(projectData, navigate));
console.log(projectData)
console.log(lastProject)
}; };
useEffect(()=> { useEffect(()=> {
...@@ -19,7 +23,6 @@ const NewProject = () => { ...@@ -19,7 +23,6 @@ const NewProject = () => {
return ( return (
<> <>
<Typography variant="h2">New project</Typography>
<ProjectForm projects={projects} onSubmit={onSubmit} /> <ProjectForm projects={projects} onSubmit={onSubmit} />
</> </>
); );
......
...@@ -6,6 +6,7 @@ import Loader from "../../components/UI/Loader/Loader"; ...@@ -6,6 +6,7 @@ import Loader from "../../components/UI/Loader/Loader";
import HasAccess from "../../components/UI/HasAccess/HasAccess"; import HasAccess from "../../components/UI/HasAccess/HasAccess";
import { fetchProjects } from "../../store/actions/projectsActions"; import { fetchProjects } from "../../store/actions/projectsActions";
import ProjectsList from "../../components/ProjectsList/ProjectsList"; import ProjectsList from "../../components/ProjectsList/ProjectsList";
import NewProject from "../NewProject/NewProject";
const Projects = () => { const Projects = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
...@@ -34,9 +35,7 @@ const Projects = () => { ...@@ -34,9 +35,7 @@ const Projects = () => {
</Grid> </Grid>
<HasAccess roles={["superuser", "admin", "user"]} > <HasAccess roles={["superuser", "admin", "user"]} >
<Grid item> <Grid item>
<Button component={Link} to="/projects/add"> <NewProject/>
Add project
</Button>
</Grid> </Grid>
</HasAccess> </HasAccess>
</Grid> </Grid>
......
...@@ -46,9 +46,10 @@ export const fetchProject = (id) => { ...@@ -46,9 +46,10 @@ export const fetchProject = (id) => {
export const createProject = (projectData, navigate) => { export const createProject = (projectData, navigate) => {
return async (dispatch) => { return async (dispatch) => {
try { try {
await axios.post("/projects", projectData); const response = await axios.post("/projects", projectData);
dispatch(createProjectSuccess()); dispatch(createProjectSuccess());
navigate("/"); console.log(response.data)
navigate("/projects/" + response.data.project.id)
dispatch(showNotification("Проект успешно создан")) dispatch(showNotification("Проект успешно создан"))
} catch (e) { } catch (e) {
console.log(e); console.log(e);
......
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