Commit 2a92b77a 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-38-enhance/enhance_tasks
parents 2fc36f54 638a5a3e
......@@ -39,16 +39,7 @@ const loadFixtures = async () => {
await user.save();
users.push(user)
}
const projects:Project[] = []
for (let i = 0; i < 5; i++) {
const newProject = new Project();
newProject.title = `Project ${faker.random.words(1)}`;
newProject.color = faker.random.words(4);
newProject.admin = faker.helpers.arrayElement(users);
newProject.workers = faker.helpers.arrayElements(users, randomIntFromInterval(1, 3));
await newProject.save();
projects.push(newProject)
}
const tasks:Task[] = []
type taskFinishType = "opened" | "done" |"failed";
type priorityType = "A" | "B" |"C";
......@@ -63,7 +54,6 @@ const loadFixtures = async () => {
newTask.dateTimeDue = faker.date.soon(randomIntFromInterval(1, 15));
newTask.dateTimeStart = faker.date.recent((randomIntFromInterval(0, 8)));
newTask.author = faker.helpers.arrayElement(users);
newTask.project = faker.helpers.arrayElement(projects);
newTask.accomplish = faker.helpers.arrayElement(accomplish);
newTask.priority = faker.helpers.arrayElement(priorities);
await newTask.save();
......@@ -75,7 +65,6 @@ const loadFixtures = async () => {
newTask.executors = faker.helpers.arrayElements(users, randomIntFromInterval(0, 3));
newTask.dateTimeDue = null;
newTask.dateTimeStart = null;
newTask.project = faker.helpers.arrayElement(projects);
newTask.author = faker.helpers.arrayElement(users);
newTask.accomplish = accomplish[0];
newTask.priority = faker.helpers.arrayElement(priorities);
......@@ -83,6 +72,22 @@ const loadFixtures = async () => {
tasks.push(newTask)
}
}
const projects:Project[] = []
for (let i = 0; i < 5; i++) {
const newProject = new Project();
newProject.title = `Project ${faker.random.words(1)}`;
newProject.color = faker.random.words(1);
newProject.admin = faker.helpers.arrayElement(users);
newProject.tasks= faker.helpers.arrayElements(tasks, randomIntFromInterval(1, 3));
newProject.workers = faker.helpers.arrayElements(users, randomIntFromInterval(1, 3));
await newProject.save();
projects.push(newProject)
}
console.log('========================== ' + '\n' + 'Fixtures done!' +'\n' + '==========================')
})
......
......@@ -12,15 +12,7 @@ import {
import {User} from './User';
import {Task} from './Task';
// type IncomingData={
// title: string | null;
// color: string
// admin:User
// workers?: User[]
// tasks?: Task[]
// dateDue?:Date
// department?:boolean
// }
interface IProject{
id: string;
......@@ -36,17 +28,10 @@ import {
@Entity({ name: 'Project' })
export class Project extends BaseEntity implements IProject{
// data: IncomingData;
// constructor(data:IncomingData){
// super();
// this.data = data
// }
@PrimaryGeneratedColumn('uuid')
id!: string
// @Column({ name: 'title', type: 'varchar', length:100,nullable: false, default: this.data.title })
// title!: string
@Column({ name: 'title', type: 'varchar', length:100,nullable: false})
title!: string
......@@ -65,7 +50,7 @@ import {
@ManyToOne(() => User, (user: { projects: Project[]; }) => user.projects,{eager : true})
admin!: User;
@OneToMany(() => Task, (task: { project: Project; })=>task.project,{eager : true})
@OneToMany(() => Task, (task: { project: Project; })=>task.project)
tasks!:Task[]|null;
@ManyToMany(() => User, (user: { projects: Project[]; }) => user.projects,{eager : true,cascade: true, onUpdate:'CASCADE',onDelete: 'CASCADE'})
......
......@@ -64,10 +64,10 @@ import {
@ManyToOne(() => User, (user: { tasks: Task[]; }) => user.tasks,{eager : true})
author!: User;
@ManyToMany(() => User,{eager : true, cascade: true, onUpdate:'CASCADE',onDelete: 'CASCADE'})
@ManyToMany(() => User,{eager : true, cascade: true, onUpdate:'CASCADE'})
@JoinTable()
executors!: User[];
@ManyToOne(()=>Project,(project:{tasks: Task[]}) => project.tasks)
project!: Project | null;
@ManyToOne(()=>Project,(project:{tasks: Task[]}) => project.tasks,{eager : true,nullable: true,onUpdate:'CASCADE'})
project!: Project;
}
......@@ -12,7 +12,6 @@ router.get('/', async(req:Request, res:Response):Promise<Response> => {
.find()
return res.send({tasks})
})
export default router;
router.post('/', async(req:Request, res:Response):Promise<Response>=>{
const token = req.get('Authorization');
......@@ -38,7 +37,7 @@ router.post('/', async(req:Request, res:Response):Promise<Response>=>{
return res.send({newTask})
})
router.get('/userId/:userId', async (req: Request, res: Response):Promise<Response>=>{
router.get('/userId/:userId', async (req: Request, res: Response):Promise<Response>=>{
const userId = req.params.userId;
const tasks = await dataSource
.getRepository(Task)
......@@ -81,6 +80,7 @@ router.delete('/:taskId',async (req: Request, res: Response):Promise<Response>=>
router.put('/',async(req:Request, res:Response)=> {
const token = req.get('Authorization');
const user = await dataSource
.createQueryBuilder()
.select("user")
......@@ -95,6 +95,7 @@ router.put('/',async(req:Request, res:Response)=> {
.from(Task, "task")
.where("task.id = :id", { id })
.getOne()
if (!task) return res.status(404).send({Message:'task not found'})
task.title= title
task.description= description
......@@ -108,3 +109,6 @@ router.put('/',async(req:Request, res:Response)=> {
await task.save()
res.send({message:'update task successfully'})
})
export default router;
......@@ -35,9 +35,7 @@ return res.send({users})
router.post('/', upload.single("avatar"), async (req : Request, res : Response):Promise<object> => {
console.log(req.body)
const {name,surname,password,email, role} = req.body;
console.log(req.body)
const displayName = surname+' '+name[0]+'.'
const user = new User();
user.name = name;
......@@ -47,13 +45,10 @@ router.post('/', upload.single("avatar"), async (req : Request, res : Response):
user.email = email;
user.role = role;
user.generateToken()
console.log("user " + user)
await user.save();
console.log("saved")
const userToFront:User|null = await dataSource.manager.findOneBy(User, {
email: user.email
})
console.log("userToFront " + userToFront)
return res.send({userToFront})
})
......
......@@ -4,7 +4,7 @@ import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import MultipleSelect from '../../components/UI/MultipleSelect/MultipleSelect';
export default function MyTaskToolBar(props) {
......@@ -15,6 +15,12 @@ export default function MyTaskToolBar(props) {
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Мои задачи
</Typography>
<MultipleSelect
projects={props.projects}
onClose={props.onClose}
projectName={props.projectName}
setProjectName={props.setProjectName}
/>
<Button color="inherit" onClick={props.onClick} >Добавить задачу</Button>
</Toolbar>
</AppBar>
......
import * as React from "react";
import {
Box,
Table,
TableBody,
TableCell,
TableContainer,
TableRow,
Paper,
IconButton,
Tooltip,
Input,
} from "@mui/material";
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Done, Edit, NavigateNextOutlined } from "@mui/icons-material";
import DeleteIcon from "@mui/icons-material/Delete";
import TaskModal from "../../components/MyTasksCompoments/TaskModal/TaskModal";
import moment from "moment";
import CustomTableCell from "../../components/MyTasksCompoments/CustomTableCell";
import MaterialUIPickers from "../../components/MyTasksCompoments/DateTimePicker/DateTimePicker";
import BasicSelect from "../../components/UI/Select/Select";
import { fetchAllTasks, deleteTask,editTask,addTask } from "../../store/actions/tasksActions";
export default function NewTaskForm (props) {
// const onToggleEditModeDone = (id) => {
// const newTasks = recievedTasks.map((task) => {
// if (task.id === id) {
// return {
// ...task,
// isEditMode: false,
// readOnly: true,
// };
// }
// return task;
// });
// setRecievedTasks(newTasks);
// };
const task={
id:0,
title: "",
description: "",
createdAt: "",
dateTimeStart: null,
dateTimeDue: null,
accomplish: "",
priority: "",
author: {
name: "",
},
executors: [
{ name: "" }
],
isEditMode:false,
readOnly: true
};
const onToggleEditMode = (id) => {
console.log(task)
return {
...task,
isEditMode: true,
readOnly: false,
};
};
console.log(task)
return (
<TableRow hover key={task.id}>
<TableCell
component="th"
scope="row"
padding="none"
></TableCell>
<CustomTableCell
{...{
task,
name: "priority",
value: task.priority,
onChange:props.onChange,
}}
/>
<CustomTableCell
{...{
task,
name: "createdAt",
value: task.createdAt,
}}
/>
<CustomTableCell
{...{
task,
name: "title",
value: task.title,
onChange:props.onChange,
onModalOpen:props.onModalOpen,
}}
/>
{task.isEditMode ? (
<BasicSelect
items={["project1", "project2", "project3"]}
task={task}
onChange={props.onChange}
/>
) : (
<CustomTableCell
{...{
task,
name: "project",
value: task.project?.title,
onChange: props.onChange,
}}
/>
)}
<CustomTableCell
{...{
task,
name: "author",
value: task.author.displayName,
onChange: props.onAuthorChange,
}}
/>
<TableCell>
<MaterialUIPickers
task={task}
name="dateTimeStart"
onChange={props.onDateChange}
/>
</TableCell>
<TableCell>
<MaterialUIPickers
task={task}
name="dateTimeDue"
onChange={props.onDateChange}
/>
</TableCell>
{task.isEditMode ? (
<BasicSelect
items={["opened", "done", "failed"]}
task={task}
onChange={props.onChange}
/>
) : (
<CustomTableCell
{...{
task,
name: "accomplish",
value: task.accomplish,
}}
/>
)}
<TableCell>
{task.isEditMode ? (
<IconButton
aria-label="done"
onClick={() => {props.onToggleEditModeDone(task.id); props.HandleEditTask(task) }}
>
<Done />
</IconButton>
) : (
<IconButton
aria-label="edit"
onClick={() => onToggleEditMode(task.id)}
>
<Edit />
</IconButton>
)}
</TableCell>
<TableCell>
<Tooltip title="Delete">
<IconButton
onClick={(id) => {
props.deleteHandle(task.id);
}}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
);
}
import * as React from 'react';
import { useTheme } from '@mui/material/styles';
import OutlinedInput from '@mui/material/OutlinedInput';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';
const ITEM_HEIGHT = 48;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
PaperProps: {
style: {
maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
width: 200,
color:'#1976d2',
borderColor:'white'
},
},
};
function getStyles(name, personName, theme) {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
}
export default function MultipleSelect(props) {
const theme = useTheme();
const handleChange = (event) => {
const {
target: { value },
} = event;
props.setProjectName(
// On autofill we get a stringified value.
typeof value === 'string' ? value.split(',') : value,
);
};
return (
<div>
<FormControl sx={{ m: 1, width: 250,borderColor:'white' }}>
<InputLabel id="demo-multiple-name-label" sx={{color:'white' }}>Project</InputLabel>
<Select
labelId="demo-multiple-name-label"
id="demo-multiple-name"
multiple
value={props.projectName}
onChange={handleChange}
input={<OutlinedInput label="Name" />}
MenuProps={MenuProps}
sx={{color:'white' }}
onClose={(e)=>{props.onClose(props.projectName)}}
>
{props.projects.map((project) => (
<MenuItem
key={project}
value={project}
style={getStyles(project, props.projectName, theme)}
>
{project}
</MenuItem>
))}
</Select>
</FormControl>
</div>
);
}
\ No newline at end of file
import { FormControl, InputLabel, MenuItem, Select} from '@mui/material';
import { memo } from 'react';
function СustomSelect({value, onChange, label, variant='standard', items, id}) {
return (
......
......@@ -24,6 +24,8 @@ import CustomTableCell from "../../components/MyTasksCompoments/CustomTableCell"
import MaterialUIPickers from "../../components/MyTasksCompoments/DateTimePicker/DateTimePicker";
import BasicSelect from "../../components/UI/Select/Select";
import { fetchAllTasks, deleteTask,editTask,addTask } from "../../store/actions/tasksActions";
import NewTaskForm from "../../components/MyTasksCompoments/NewTaskForm";
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
......@@ -58,11 +60,16 @@ export default function EnhancedTable() {
useEffect(() => {
dispatch(fetchAllTasks());
}, []);
}, [dispatch]);
const tasks = useSelector((state) => state.tasks.tasks);
console.log(tasks)
const [recievedTasks, setRecievedTasks] = useState([]);
const projects=[
"project1",
"project2",
"project3"
]
const [order, setOrder] = React.useState("asc");
const [orderBy, setOrderBy] = React.useState("id");
......@@ -143,6 +150,7 @@ console.log(tasks)
};
const onToggleEditMode = (id) => {
console.log(id)
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
return {
......@@ -156,8 +164,22 @@ console.log(tasks)
setRecievedTasks(newTasks);
};
const HandleEditTask=(task)=>{
dispatch(editTask(task))
const onToggleEditModeDone = (id) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
return {
...task,
isEditMode: false,
readOnly: true,
};
}
return task;
});
setRecievedTasks(newTasks);
};
const HandleEditTask= (task)=>{
dispatch(editTask(task))
}
const addTask = () => {
......@@ -195,7 +217,31 @@ console.log(tasks)
const handleClose = () => {
setModal({ ...modal, open: false, id: null });
};
// ++++++++фильтрация по проектам+++++++++++++++
const [projectName, setProjectName] = React.useState([]);
const [filter, setFilter] = React.useState(false);
const onClose=(projectName)=>{
console.log(projectName)
setFilter(true)
}
useEffect(() => {
if (tasks && tasks?.length > 0) {
let currentTasks = [];
let i
for (i=0; i<projectName?.lenght; i++)
{currentTasks = tasks?.map((task) => {
if (task.project=projectName)
return {
...task,
};
})};
setRecievedTasks(currentTasks);
}
}, [filter==true]);
// ++++++++фильтрация по проектам+++++++++++++++
if (
tasks &&
tasks?.length > 0 &&
......@@ -209,6 +255,10 @@ console.log(tasks)
onClick={() => {
addTask();
}}
projects={projects}
onClose={onClose}
projectName={projectName}
setProjectName={setProjectName}
/>
<TableContainer>
......@@ -220,7 +270,7 @@ console.log(tasks)
rowCount={tasks.length}
/>
<TableBody>
<TableRow sx={{height:'1px',margin:0,padding:0}}>
{/* <TableRow sx={{height:'1px',margin:0,padding:0}}>
<TableCell align="left">
<Input sx={{height:'1px',margin:0,padding:0}} value={''} name="order" />
</TableCell>
......@@ -228,12 +278,24 @@ console.log(tasks)
<TableCell align="left">
<Input sx={{height:'1px',margin:0,padding:0}} value={''} name="orderBy" />
</TableCell>
</TableRow>
</TableRow> */}
{/* <NewTaskForm
onChange={onChange}
onModalOpen={onModalOpen}
onAuthorChange={onAuthorChange}
onDateChange={onDateChange}
onToggleEditMode={onToggleEditMode}
onToggleEditModeDone={onToggleEditModeDone}
HandleEditTask={HandleEditTask}
deleteHandle={deleteHandle}
/> */}
{stableSort(recievedTasks, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((task, index) => {
return (
<TableRow hover key={task.id}>
<TableCell
component="th"
......@@ -265,6 +327,23 @@ console.log(tasks)
onModalOpen,
}}
/>
{task.isEditMode ? (
<BasicSelect
items={["project1", "project2", "project3"]}
task={task}
onChange={onChange}
/>
) : (
<CustomTableCell
{...{
task,
name: "project",
value: task.project?.title,
onChange: onChange,
}}
/>
)}
<CustomTableCell
{...{
task,
......@@ -310,7 +389,7 @@ console.log(tasks)
{task.isEditMode ? (
<IconButton
aria-label="done"
onClick={() => {onToggleEditMode(task.id); HandleEditTask(task) }}
onClick={() => {onToggleEditModeDone(task.id); HandleEditTask(task) }}
>
<Done />
</IconButton>
......
......@@ -33,6 +33,12 @@ const headCells = [
disablePadding: false,
label: 'Заголовок',
},
{
id: 'project',
numeric: true,
disablePadding: false,
label: 'Проект',
},
{
id: 'authorDisplayName',
numeric: true,
......
......@@ -6,7 +6,7 @@ import { configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';
import usersReducer from './store/reducers/usersReducer';
import tasksReducer from './store/reducers/tasksReducer';
import axios from 'axios';
import axios from './axiosPlanner';
const localStorageMiddleware = ({getState}) => (next) => (action) => {
const result = next(action);
......@@ -21,13 +21,6 @@ const loadFromLocalStorage = () => {
return undefined;
};
axios.interceptors.request.use(config=>{
try{
config.headers['Authorization']=store.getState().users.user.token;
} catch(e){
}
return config;
})
const store = configureStore({
reducer: {
......@@ -38,6 +31,14 @@ const store = configureStore({
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(localStorageMiddleware)
})
axios.interceptors.request.use(config=>{
try{
config.headers['Authorization']=store.getState().users.user.token;
} catch(e){
}
return config;
})
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
......
......@@ -12,7 +12,6 @@ import {
FETCH_CALENDAR_TASKS_REQUEST,
FETCH_CALENDAR_TASKS_SUCCESS,
FETCH_ALL_TASKS_SUCCESS,
EDIT_CALENDAR_TASK,
} from "../actionTypes/tasksTypes";
import axios from '../../axiosPlanner'
......@@ -72,11 +71,7 @@ export const addTask = (task) => {
dispatch(addTaskRequest());
const token = getState().users?.user?.token;
try {
await axios.post("/tasks", task, {
headers: {
'Authorization': 'tGwVYAzqxIfIm0jJfRHBQ'
}
});
await axios.post("/tasks", task);
dispatch(addTaskSuccess())
dispatch(fetchCalendarTasks())
} catch (error) {
......@@ -100,14 +95,11 @@ const editTaskFailure = (error) => {
export const editTask = (task) => {
return async (dispatch, getState) => {
dispatch(editTaskRequest());
const token = getState().users?.user?.token;
// const token = getState().users?.user?.token;
try {
console.log(task)
const r=await axios.put("/tasks", task, {
headers: {
'Authorization': 'tGwVYAzqxIfIm0jJfRHBQ'
}
});
console.log('task' , task)
const r=await axios.put("/tasks/", task);
console.log(r)
dispatch(editTaskSuccess())
dispatch(fetchAllTasks())
dispatch(fetchCalendarTasks())
......@@ -132,13 +124,9 @@ const deleteTaskFailure = (error) => {
export const deleteTask = (taskId) => {
return async (dispatch, getState) => {
dispatch(deleteTaskRequest());
const token = getState().users?.user?.token;
// const token = getState().users?.user?.token;
try {
await axios.delete(`/tasks/${taskId}`, {
headers: {
'Authorization': 'tGwVYAzqxIfIm0jJfRHBQ'
}
});
await axios.delete(`/tasks/${taskId}`);
dispatch(deleteTaskSuccess())
dispatch(fetchCalendarTasks())
dispatch(fetchAllTasks())
......
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