Merge branch 'task-136-fix/project_select_my_tasks' into 'development'

Task 136 fix/project select my tasks

See merge request !112
parents b73a244c 9530748a
......@@ -18,6 +18,7 @@
"class-validator": "^0.13.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"mongoose": "^6.7.0",
"multer": "^1.4.5-lts.1",
"nanoid": "^3.3.4",
......@@ -3329,6 +3330,14 @@
"node": ">= 0.10.0"
}
},
"node_modules/express-async-errors": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
"peerDependencies": {
"express": "^4.16.2"
}
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
......@@ -8887,6 +8896,12 @@
}
}
},
"express-async-errors": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz",
"integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==",
"requires": {}
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
......
......@@ -35,6 +35,7 @@
"class-validator": "^0.13.2",
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"mongoose": "^6.7.0",
"multer": "^1.4.5-lts.1",
"nanoid": "^3.3.4",
......
......@@ -6,6 +6,7 @@ import { priorityType, Task, taskFinishType } from "./models/Task";
import { Project } from "./models/Project";
import { Member, MemberRole } from "./models/Member";
import { DateTimeTask } from "./models/DateTimeTask";
import { PasswordRecovery } from "./models/PasswordRecovery";
function randomIntFromInterval(min:number, max:number) {
min = Math.ceil(min);
......@@ -50,6 +51,8 @@ const loadFixtures = async () => {
await repositoryProject.delete({})
const repositoryUser = myDataSource.getRepository(User);
await repositoryUser.delete({});
const repositoryPasswordRecovery = myDataSource.getRepository(PasswordRecovery);
await repositoryPasswordRecovery.delete({});
console.log('========================== ' + '\n' + 'Data Source has been cleared!' +'\n' + '==========================')
const userRoles = [{role: UserRole.SUPERUSER}, {role: UserRole.USER}, {role: UserRole.USER},{role: UserRole.USER},];
......@@ -68,6 +71,26 @@ const loadFixtures = async () => {
user.role = userRoles[i].role;
user.generateToken()
await user.save();
// начало: создание проектов "Личные дела" и "Не определелено" новому юзеру
const newProject = new Project();
newProject.title = 'Личные дела';
newProject.color= '#f595ee';
await newProject.save()
const newMember = new Member();
newMember.user = user;
newMember.project = newProject;
newMember.roleProject = MemberRole.ADMIN;
await newMember.save();
const notDefinedTaskProject = new Project();
notDefinedTaskProject.title = 'Не определено';
notDefinedTaskProject.color= '#03fcfc';
await notDefinedTaskProject.save()
const notDefinedTaskProjectMember = new Member();
notDefinedTaskProjectMember.user = user;
notDefinedTaskProjectMember.project = notDefinedTaskProject;
notDefinedTaskProjectMember.roleProject = MemberRole.ADMIN;
await notDefinedTaskProjectMember.save();
// конец
users.push(user)
}
......@@ -77,11 +100,13 @@ const loadFixtures = async () => {
for (let i = 0; i < 20; i++) {
let dateOfMonth = randomIntFromInterval(20, 30)
let currentTime = new Date()
let startdateOfMonth = randomIntFromInterval(20, 24)
let enddateOfMonth = randomIntFromInterval(25, 29)
let deadLineDateOfMonth = randomIntFromInterval(1, 10)
let startDateTime = new Date(2022, 10, dateOfMonth, randomIntFromInterval(16, 21), 0, 0);
let dueDateTime = new Date(2022, 10, dateOfMonth, randomIntFromInterval(22, 22), 0, 0);
let deadLine = new Date(2022, 11, deadLineDateOfMonth, 0, 0, 0);
let startDateTime = new Date(currentTime.getFullYear(), currentTime.getMonth()+1,startdateOfMonth , randomIntFromInterval(11, 18), 0, 0);
let dueDateTime = new Date(currentTime.getFullYear(), currentTime.getMonth()+1,startdateOfMonth, randomIntFromInterval(19, 20), 0, 0);
let deadLine = new Date(currentTime.getFullYear(), currentTime.getMonth()+2, enddateOfMonth, randomIntFromInterval(20, 22), 0, 0);
const newDateTimeTask= new DateTimeTask()
newDateTimeTask.dateTimeStart=startDateTime;
newDateTimeTask.dateTimeDue=dueDateTime;
......
import 'express-async-errors';
import express, { NextFunction, Request, Response, Router } from "express";
import { myDataSource } from "./app-data-source";
import { Task } from "./models/Task";
......@@ -59,7 +60,7 @@ export const authAuthorOrExecutorOfTask = async(req: Request,res: Response, next
}
const {executorStatus, authorStatus} = req.body
if (!executorStatus && !authorStatus) {
res.status(403).send({message:'user is not authorized'})
return res.status(403).send({message:'user is not authorized'})
}
req.body={...req.body, task:task}
next()
......
......@@ -49,18 +49,40 @@ router.get('/my',auth, async (req:Request, res:Response): Promise<Response>=> {
/**create new project */
router.post('/',auth, async (req:Request, res:Response): Promise<Response> => {
if (!req.body) return res.status(400).send({Message:'problem in incoming req.body'})
const {user, title,color}= req.body;
const member:Member = new Member;
member.user= user;
member.roleProject= MemberRole.ADMIN;
await member.save();
const project : Project= new Project()
project.title = title;
project.color = color;
project.members=[member]
await project.save()
return res.send({project})
try{
const projectCheck = await dataSource
.getRepository(Project)
.find({
where:{
title:title
}
})
if(projectCheck.length>0) {return res.status(400).send({message:"suchc Project already exists"})}
} catch(e){
return res.status(502).send({message:(e as Error).message})
}
try{
const member:Member = new Member;
member.user= user;
member.roleProject= MemberRole.ADMIN;
await member.save();
const project : Project= new Project()
project.title = title;
project.color = color;
project.members=[member]
await project.save()
return res.send({project})
} catch(e) {
return res.status(502).send({message:(e as Error).message})
}
})
/**get project with all FK & tasks with all FK, by project ID */
router.get("/:id",async (req:Request, res:Response): Promise<Response> => {
......
import 'express-async-errors';
import express,{Router, Request, Response } from 'express';
import {Task} from '../models/Task';
import {myDataSource} from '../app-data-source';
......@@ -27,6 +28,7 @@ router.get('/', async(req:Request, res:Response):Promise<Response> => {
/**create new task for table MyTask*/
router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
const {user,title,description,project,executor,dateTimeStart,dateTimeDue, dateTimeDeadLine,priority} = req.body;
console.log('dateTimeStart \n', dateTimeStart, "dateTimeDue\n", dateTimeDue, 'dateTimeDeadLine\n ', dateTimeDeadLine)
let dateTimeDueFinal = dateTimeDue
let dateTimeStartFinal = dateTimeStart
let dateTimeDeadlineFinal= dateTimeDeadLine
......@@ -34,7 +36,6 @@ router.post('/', auth, async(req:Request, res:Response):Promise<Response>=>{
dateTimeDueFinal = dateTimeDeadLine
dateTimeStartFinal = subtractHours(dateTimeDueFinal, 1)
}
console.log('datTeimeDeadLine ', dateTimeDeadLine)
const newTask = new Task();
newTask.title = title;
......@@ -112,6 +113,7 @@ router.post('/users', auth, async(req:Request, res:Response):Promise<Response>=>
const newTask = new Task();
newTask.title = title;
newTask.description = description;
const currentTime = new Date();
if (project) {
const watcherOfProject = await dataSource
.getRepository(Project)
......@@ -196,14 +198,15 @@ router.get('/user/:userId', async (req: Request, res: Response):Promise<Response
/**check tasks of current user where he is executor(works for tbl MyTasks), search by id*/
router.get('/my',auth, async (req: Request, res: Response):Promise<Response>=>{
let projectsRawId =[]
try{
const user = req.body.user
const projectsRawId = await dataSource
projectsRawId = await dataSource
.getRepository(Project)
.find({
select:{
id:true
},
where:{
title:Not(Equal("Не определено")),
members:{
......@@ -215,7 +218,7 @@ router.get('/my',auth, async (req: Request, res: Response):Promise<Response>=>{
}
}
)
const projectsList= projectsRawId.map(project=> {return project.id})
const tasks = await dataSource
.getRepository(Task)
......@@ -246,6 +249,9 @@ router.get('/my',auth, async (req: Request, res: Response):Promise<Response>=>{
}
})
return res.send({tasks, projects})
} catch(e){
return res.status(502).send({message:(e as Error).message})
}
})
......@@ -308,7 +314,7 @@ router.delete('/:taskId',async (req: Request, res: Response):Promise<Response>=>
/**change of task by task id */
router.put('/:taskId',auth,authAuthorOrExecutorOfTask,async(req:Request, res:Response)=> {
const {taskId} = req.params
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)
......@@ -385,54 +391,60 @@ router.post('/project',async (req: Request, res: Response):Promise<Response>=>{
/**check other users tasks that are related to the user through common projects, by user token*/
router.get('/users-tasks', auth,async (req: Request, res: Response):Promise<Response>=>{
const {user} = req.body
const projectsWithTasks = await dataSource
.getRepository(Project)
.find(
{ relations:{
members:true,
tasks:{
author:true,
executor:true
}
},
where:{
members:{
roleProject:Not(Equal(MemberRole.WATCHER)),
user:{
id:user.id
},
project:{
title:Not(Equal("Личные дела"))
}
}
}})
if (!projectsWithTasks) return res.status(404).send({Message:'projects not found'})
let tasks:Task[] = []
if (projectsWithTasks.length>0) {
for (let project of projectsWithTasks){
if (project?.tasks) {
tasks=tasks.concat(project.tasks)
}
}
}
const projectIds= projectsWithTasks.map(project=> {return project.id})
const projects = await dataSource
.getRepository(Project)
.find({
relations:{
members:{
user:true
}},
where:{
id:In(projectIds),
const {user} = req.body
try{
const projectsWithTasks = await dataSource
.getRepository(Project)
.find(
{ relations:{
members:true,
tasks:{
author:true,
executor:true
}
},
where:{
members:{
roleProject: Not(MemberRole.WATCHER)
roleProject:Not(Equal(MemberRole.WATCHER)),
user:{
id:user.id
},
project:{
title:Not(Equal("Личные дела"))
}
}
},
}})
})
return res.send({projects, tasks})
if (!projectsWithTasks) return res.status(404).send({Message:'projects not found'})
let tasks:Task[] = []
if (projectsWithTasks.length>0) {
for (let project of projectsWithTasks){
if (project?.tasks) {
tasks=tasks.concat(project.tasks)
}
}
}
const projectIds= projectsWithTasks.map(project=> {return project.id})
const projects = await dataSource
.getRepository(Project)
.find({
relations:{
members:{
user:true
}},
where:{
id:In(projectIds),
members:{
roleProject: Not(MemberRole.WATCHER)
}
},
})
return res.send({projects, tasks})
} catch(e){
console.log('Error: ',(e as Error).message);
return res.status(502).send({message:(e as Error).message})
}
})
......
......@@ -93,15 +93,26 @@ router.post('/', upload.single("avatar"), async (req : Request, res : Response):
user.role = role;
user.generateToken();
await user.save();
/**Создание проектов "Личные дела" и "Не определено"
* у только что созданого пользователя*/
const newProject = new Project();
newProject.title = 'Личные дела';
newProject.color= 'Green';
newProject.color= '#f595ee';
await newProject.save()
const newMember = new Member();
newMember.user = user;
newMember.project = newProject;
newMember.roleProject = MemberRole.ADMIN;
await newMember.save();
const notDefinedTaskProject = new Project();
notDefinedTaskProject.title = 'Не определено';
notDefinedTaskProject.color= '#03fcfc';
await notDefinedTaskProject.save()
const notDefinedTaskProjectMember = new Member();
notDefinedTaskProjectMember.user = user;
notDefinedTaskProjectMember.project = notDefinedTaskProject;
notDefinedTaskProjectMember.roleProject = MemberRole.ADMIN;
await notDefinedTaskProjectMember.save();
const userToFront:User|null = await dataSource.manager.findOneBy(User, {
email: user.email
......
......@@ -13,14 +13,17 @@ import {
} from "@mui/material";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AddBox, Luggage } from "@mui/icons-material";
import { AddBox
// , Luggage
} from "@mui/icons-material";
import moment from "moment";
import CustomTableCell from "./CustomTableCell";
import MaterialUIPickers from "./DateTimePicker/DateTimePicker";
import BasicSelect from "../UI/Select/Select";
import { addTask } from "../../store/actions/tasksActions";
import TaskModal from "./TaskModal/TaskModal";
import {dateToISOLikeButLocal} from '../../helpers/CalendarHelpers';
// import {dateToISOLikeButLocal} from '../../helpers/CalendarHelpers';
// import DateTimePicker from "../Calendars/UI/DateTimePicker/DateTimePicker";
export default function NewTaskForm({ projects, setAddTaskForm }) {
console.log('new task form')
......@@ -37,7 +40,7 @@ export default function NewTaskForm({ projects, setAddTaskForm }) {
dateTimeDeadLine: null,
dateTimeTasks: [],
dateTimeDue: null,
project: null,
project: projects?projects.find(project=>project.title==="Личные дела"):null,
accomplish: "opened",
priority: "B",
author: { id: user.id },
......@@ -53,6 +56,8 @@ export default function NewTaskForm({ projects, setAddTaskForm }) {
setModal(true);
};
console.log('task ', task)
const handleClose = () => {
setModal(false);
};
......
......@@ -6,11 +6,6 @@ import FormControl from "@mui/material/FormControl";
import Select from "@mui/material/Select";
export default function BasicSelect({value,label,name,onChange,task,items}) {
// console.log('select value ', value)
// console.log('select label ', label)
// console.log('select name ', name)
// console.log('select task ', task)
// console.log('select items ', items)
return (
<Box sx={{ minWidth: 60, m: 0}}>
<FormControl fullWidth>
......@@ -20,7 +15,6 @@ export default function BasicSelect({value,label,name,onChange,task,items}) {
id="demo-simple-select"
value={value}
defaultValue=''
// displayEmpty={true}
label={label}
name={name}
onChange={(e) => onChange(e, task)}
......
......@@ -40,7 +40,7 @@ export default function NewTaskForm({
dateTimeDeadLine: null,
dateTimeTasks: [],
dateTimeDue: null,
project: null,
project: projects?projects.find(project=>project.title==="Не определено"):null,
accomplish: "opened",
priority: "B",
author: { id: user.id },
......@@ -49,7 +49,6 @@ export default function NewTaskForm({
isEditMode: true,
});
const [modal, setModal] = useState(false);
console.log('NewTaskForm currentProject ', currentProject )
const onModalOpen = (event, task) => {
event.stopPropagation();
......@@ -178,7 +177,7 @@ export default function NewTaskForm({
task={task}
onChange={onExecutorChange}
name="executor"
value={task.executor?.id}
value={task?.executor?.id}
defaultValue={user.id}
/>
</TableCell>
......
import * as React from "react";
import React,{useState} from "react";
import {
TableCell,
TableRow,
......@@ -33,17 +33,20 @@ const TableRowTask= ({
deleteDateTimeTask,
onChange,
onModalOpen,
onProjectChange,
onExecutorChange,
// onProjectChange,
// onExecutorChange,
uniqueProjects,
executors,
onAuthorChange,
// executors,
onDateChange,
onToggleEditMode,
onToggleEditModeDone,
})=>{
const [open, setOpen] = React.useState(false);
const [open, setOpen] = useState(false);
const [defaultExecutor, setDefaultExecutor] = useState(task.executor?.id)
const [executors, setExecutors]=useState([])
const [currentProject, setCurrentProject] = useState(null);
const [recievedTasks, setRecievedTasks] = useState([]);
const roudHourUp =(dateIso)=>{
let m = moment(dateIso);
......@@ -61,6 +64,64 @@ const TableRowTask= ({
return weekDays[date.day()];
}
const onProjectChange = (e, task) => {
e.preventDefault()
setDefaultExecutor(user)
const projectId = e.target.value;
const project = uniqueProjects.length>0 ?uniqueProjects.find((uniqueProject) => uniqueProject.id === projectId):null;
console.log('change project ', project)
setCurrentProject(project)
let executorList=[]
if(project?.members){
for (let member of project.members){
executorList.push(member.user)
}
}
setExecutors(executorList)
// const { id } = task;
// const newTasks = recievedTasks.map((task) => {
// if (task.id === id) {
// const updated = { ...task };
// updated.project = project;
// updated.projectName =project.title? project.title:null;
// return updated;
// }
task.project = project;
task.projectName=project.title? project.title:null;
return task;
// });
// setRecievedTasks(newTasks);
};
const onExecutorChange = (e, task) => {
const executorId = e.target.value;
const executor = executors.find((executor) => executor.id === executorId);
// const { id } = task;
// const newTasks = recievedTasks.map((task) => {
// if (task.id === id) {
// const updated = { ...task };
// updated.executor = executor;
// updated.executorName = executor.displayName;
// return updated;
// }
// return task;
// });
// setRecievedTasks(newTasks);
task.executor = executor;
task.executorName = executor.displayName;
return task;
};
return (
<>
<TableRow hover key={task.id}>
......@@ -159,7 +220,7 @@ const TableRowTask= ({
task={task}
onChange={onExecutorChange}
name="executor"
value={task.executor?.id}
defaultValue={defaultExecutor?.id}
/>
</TableCell>
) : (
......@@ -180,19 +241,11 @@ const TableRowTask= ({
task,
name: "author",
value: task.author.displayName,
// onChange: onAuthorChange,
user:user
}}
/>
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
{/* <MaterialUIPickers
task={task}
name="dateTimeStart"
onChange={onDateChange}
user={user}
/> */}
{/* <TableCell> */}
<Tooltip title="Перейти в календарь">
<IconButton
onClick={(id) => { deleteHandle(task.id);}}
......@@ -200,7 +253,6 @@ const TableRowTask= ({
<CalendarMonthIcon />
</IconButton>
</Tooltip>
{/* </TableCell> */}
</TableCell>
) : (
......@@ -236,15 +288,6 @@ const TableRowTask= ({
)}
{/* <TableCell>
<MaterialUIPickers
task={task}
name="dateTimeStart"
onChange={onDateChange}
user={user}
/>
</TableCell> */}
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<MaterialUIPickers
......@@ -373,26 +416,7 @@ const TableRowTask= ({
<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 */}
......
......@@ -27,6 +27,7 @@ export default function UsersTasks() {
const user = useSelector((state) => state.users.user);
const [executors, setExecutors]=useState([])
// const [currentExecutor, setCurrentExecutor]= useState(task.executor.id?task.executor:'')
const [currentProject, setCurrentProject] = useState(null);
const [recievedTasks, setRecievedTasks] = useState([]);
const [addTaskForm, setAddTaskForm] = useState(false);
......@@ -38,6 +39,7 @@ export default function UsersTasks() {
open: false,
task: null,
});
useEffect(() => {
dispatch(fetchAllTasksByMembership());
......@@ -152,6 +154,7 @@ export default function UsersTasks() {
const onToggleEditModeDone = (id) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
console.log('toggledDone task ', task)
return {
...task,
isEditMode: false,
......
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