Commit 046e41c0 authored by Ermolaev Timur's avatar Ermolaev Timur

Merge branch 'task-149-enhance/users_tasks_table_rework' into 'development'

Task 149 enhance/users tasks table rework

See merge request !119
parents 60dc2d6f 9e60add3
......@@ -319,7 +319,7 @@ router.put('/:taskId',auth,authAuthorOrExecutorOfTask,async(req:Request, res:Res
dateTimeDue,executor,accomplish,dateTimeDeadLine, dateTimeFactDeadLine,priority} = req.body;
const task = await taskFinderById(taskId)
if (!task) return res.status(404).send({Message:'task not found'})
console.log(req.body)
console.log ('dateTimeDeadLine ', dateTimeDeadLine,'authorStatus '
,authorStatus,'executorStatus ',executorStatus)
......
......@@ -60,6 +60,7 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti
label="От"
variant="outlined"
name='startHour'
type="number"
onChange={(e) => { onChangeCurrentTaskHandler(e) }}
/>
<TextField
......@@ -68,6 +69,7 @@ function CalendarModalTaskContent({ title, onChangeCurrentTaskHandler, descripti
label="До"
variant="outlined"
name='endHour'
type="number"
onChange={(e) => { onChangeCurrentTaskHandler(e) }}
/>
</div>
......
......@@ -101,7 +101,7 @@ function CalendarWeekTask({ height, width, left, top, task, zIndex, handleOpen,
const returnTask = useMemo(() => {
if (copyModeTask?.id === task?.mainTaskId) {
return (<>
<span style={{ textOverflow: 'ellipsis', padding: '5px 0 0 5px' }}>
<span style={{ maxWidth: '80%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', padding: '5px 0 0 5px' }}>
{task.title}
</span>
<DeleteIcon
......@@ -121,7 +121,7 @@ function CalendarWeekTask({ height, width, left, top, task, zIndex, handleOpen,
</>)
} else {
return (<>
<span style={{ textOverflow: 'ellipsis', padding: '5px 0 0 5px' }}>
<span style={{ maxWidth: '80%', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', padding: '5px 0 0 5px' }}>
{task.title}
</span>
<CopyIcon
......
import { FormControl, InputLabel, MenuItem, Select } from '@mui/material';
import { memo } from 'react';
function СustomSelect({ value, onChange, label, variant = 'standard', items, id, defaultValue, name }) {
function СustomSelect({ value, onChange, label, variant = 'standard', items, id, defaultValue, name, sx}) {
return (
<>
<FormControl variant={variant} sx={{ m: 0, minWidth: 125 }}>
<FormControl variant={variant} sx={ sx?.width ? sx : { m: 0, minWidth: 125}}>
<InputLabel id={`${id}-select-label`}>{label}</InputLabel>
<Select
labelId={`${id}-select-label`}
......@@ -30,7 +29,7 @@ function СustomSelect({ value, onChange, label, variant = 'standard', items, id
}
export default memo(СustomSelect, (prevProps, nextProps) => {
if (prevProps.value !== nextProps.value) {
if (prevProps.value !== nextProps.value || prevProps.items !== nextProps.items) {
return false
} else {
return true
......
import * as React from "react";
import TableCell from "@mui/material/TableCell";
import Input from "@mui/material/Input";
import moment from "moment";
const CustomTableCell = ({
task,
name,
value,
value2,
onChange,
onModalOpen,
placeholder,
user,
colSpan
}) => {
const styles = placeholder ? { width: "100%" } : { width: "auto" };
const divStyle = {
display: "flex",
justifyContent: "space-between",
flexDirection: "column",
fontSize: "12px",
};
const duration = moment.duration(
moment(task?.dateTimeTasks[0]?.dateTimeDue).diff(
moment(task?.dateTimeTasks[0]?.dateTimeStart)
)
);
const hours = Math.round(duration.asHours());
if (task) {
return (
<>
<TableCell
colSpan={colSpan}
onClick={(e) => (onModalOpen ? onModalOpen(e, task) : null)}
align="left"
// style={styles}
>
{(task.isEditMode &&
onChange &&
name !== "author" &&
task.author?.id === user?.id) ||
placeholder ? (
<Input
placeholder={placeholder}
value={value}
name={name}
onChange={(e) => onChange(e, task)}
style={styles}
/>
) : name !== "dateTimeStart" ? (
<span>{value}</span>
) : (
<div style={divStyle}>
<span>{value}</span>
<span>{value2}</span>
<span>часы:{hours}</span>
</div>
)}
</TableCell>
</>
);
}
};
export default CustomTableCell;
import * as React from "react";
import {
Table,
TableBody,
TableCell,
TableContainer,
TableRow,
TableHead,
IconButton,
Tooltip,
Typography,
Divider,
} from "@mui/material";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AddBox } from "@mui/icons-material";
import moment from "moment";
import CustomTableCell from "./CustomTableCell";
import MaterialUIPickers from "./DateTimePicker/DateTimePicker";
import BasicSelect from "../UI/Select/Select";
import { addTaskToUserTasksTable } from "../../store/actions/tasksActions";
import TaskModal from "./TaskModal/TaskModal";
export default function NewTaskForm({
projects,
currentProject,
setCurrentProject,
setAddTaskForm,
}) {
const dispatch = useDispatch();
const user = useSelector((state) => state.users.user);
const currentDateTime = new Date();
const dateTime = moment(currentDateTime).utc().format();
const [task, setTask] = useState({
id: 0,
title: "",
description: "",
createdAt: dateTime,
dateTimeStart: null,
dateTimeDeadLine: null,
dateTimeTasks: [],
dateTimeDue: null,
project: projects?projects.find(project=>project.title==="Не определено"):null,
accomplish: "opened",
priority: "B",
author: { id: user.id },
authorDisplayName: user.displayName,
executor:null,
isEditMode: true,
});
const [modal, setModal] = useState(false);
const onModalOpen = (event, task) => {
event.stopPropagation();
setModal(true);
};
const handleClose = () => {
setModal(false);
};
const onChange = (e, task) => {
const value = e.target.value;
const name = e.target.name;
const newTask = { ...task, [name]: value };
setTask(newTask);
};
const onProjectChange = (e, task) => {
const value = e.target.value;
const project = projects.find((project) => project.id === value);
setCurrentProject(project)
const newTask = { ...task };
newTask.project = project;
setTask(newTask);
};
const onExecutorChange = (e, task) => {
const {value, name} = e.target.value;
let executorMember = null
const newTask = { ...task };
if( name==='executor' && value!==null) {
executorMember = currentProject.find((member) => member.user.id === value);
newTask.executor = executorMember?.user;
}
setTask(newTask);
};
const onDateChange = (id, value, property) => {
const newTask = {
...task,
[property]: moment.parseZone(value, "DD/MM/YYYY", true).format(),
};
setTask(newTask);
};
const handleAddTask = () => {
dispatch(addTaskToUserTasksTable(task));
setAddTaskForm();
};
return (
<>
<Divider>
<Typography variant="overline">Добавить новую задачу</Typography>
</Divider>
<TableContainer
style={{
backgroundColor: "#E8E8E8",
marginBottom: "2em",
}}
>
<Table sx={{ minWidth: 600 }} aria-labelledby="tableTitle">
<TableHead>
<TableRow>
{header.map((headCell) => (
<TableCell
key={headCell.id}
align="center"
padding={headCell.disablePadding ? "none" : "normal"}
colSpan={headCell.colSpan}
>
{headCell.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
<TableRow hover key={task.id}>
<TableCell component="th" scope="row" padding="none"></TableCell>
<TableCell>
<BasicSelect
items={[
{ value: "A", title: "A" },
{ value: "B", title: "B" },
{ value: "C", title: "C" },
]}
task={task}
value={task.priority}
onChange={onChange}
name="priority"
/>
</TableCell>
<CustomTableCell
colSpan={3}
{...{
task,
name: "title",
value: task.title,
onModalOpen,
user: user,
placeholder: "Кликните для ввода информации по задаче"
}}
/>
<TableCell>
<BasicSelect
items={projects?.map((project) => ({
value: project?.id,
title: project?.title,
}))}
task={task}
onChange={onProjectChange}
name="project"
value={task.project?.id}
/>
</TableCell>
<TableCell>
<BasicSelect
items={currentProject?currentProject?.members.map((member) => ({
value: member?.user?.id,
title: member?.user?.displayName,
})):null}
task={task}
onChange={onExecutorChange}
name="executor"
value={task?.executor?.id}
defaultValue={user.id}
/>
</TableCell>
<TableCell>
<MaterialUIPickers
task={task}
name="dateTimeDeadLine"
onChange={onDateChange}
/>
</TableCell>
<TableCell>
<Tooltip title="Добавить">
<IconButton size="large" onClick={handleAddTask}>
<AddBox fontSize="large" />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
</TableBody>
</Table>
<TaskModal
task={task}
open={modal}
handleClose={handleClose}
onChange={onChange}
user={user}
/>
</TableContainer>
<Divider />
</>
);
}
export const header = [
{
id: "id",
numeric: true,
disablePadding: true,
label: "",
},
{
id: "priority",
numeric: false,
disablePadding: true,
label: "Приоритет",
},
{
id: "title",
numeric: false,
disablePadding: false,
label: "Заголовок",
colSpan:3
},
{
id: "projectName",
numeric: true,
disablePadding: false,
label: "Проект",
},
{
id: "executorName",
numeric: false,
disablePadding: false,
label: "Исполнитель",
},
{
id: "dateTimeDeadLine",
numeric: true,
disablePadding: false,
label: "Дедлайн",
},
{
id: "add",
numeric: false,
disablePadding: false,
label: "",
},
];
import React,{useState} from "react";
import {
TableCell,
TableRow,
IconButton,
Tooltip,
Collapse,
Box,
Table,
TableBody,
TableHead,
Typography
} from "@mui/material";
import { Done, Edit } from "@mui/icons-material";
import RemoveIcon from '@mui/icons-material/Remove';
import DeleteIcon from "@mui/icons-material/Delete";
import moment from "moment";
import CustomTableCell from "../CustomTableCell";
import MaterialUIPickers from "../DateTimePicker/DateTimePicker";
import BasicSelect from "../../UI/Select/Select";
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import { TaskStatuses } from "../../../helpers/TableTasksHelpers";
const weekDays = ["Вс","Пн","Вт","Ср","Чт","Пт","Сб" ];
const TableRowTask= ({
user,
task,
deleteHandle,
handleEditTask,
deleteDateTimeTask,
onChange,
onModalOpen,
// onProjectChange,
// onExecutorChange,
uniqueProjects,
// executors,
onDateChange,
onToggleEditMode,
onToggleEditModeDone,
})=>{
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);
let roundUp = m.minute() || m.second() || m.millisecond() ? m.add(1, 'hour').startOf('hour') : m.startOf('hour');
return roundUp
}
const timeTransform = (dateIso)=>{
const exp = roudHourUp(moment.utc(dateIso)).format("HH:"+"00")
return exp;
}
const getDayOfWeek = (dateIso) => {
const date = moment.utc(dateIso);
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}>
<TableCell
component="th"
scope="row"
padding="none"
></TableCell>
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<BasicSelect
items={[
{ value: "A", title: "A" },
{ value: "B", title: "B" },
{ value: "C", title: "C" },
]}
task={task}
value={task.priority}
onChange={onChange}
name="priority"
user={user}
/>
</TableCell>
) : (
<CustomTableCell
{...{
task,
name: "priority",
value: task.priority,
user:user
}}
/>
)}
<CustomTableCell
{...{
task,
name: "createdAt",
value: moment(task.createdAt)
.utc()
.format("DD-MM-YY"),
user:user
}}
/>
<CustomTableCell
{...{
task,
name: "title",
value: task.title,
onChange,
onModalOpen,
user:user
}}
/>
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<BasicSelect
items={uniqueProjects.map((e) => ({
value: e?.id,
title: e?.title,
}))}
task={task}
onChange={onProjectChange}
name="project"
value={task.project?.id}
user={user}
/>
</TableCell>
) : (
<CustomTableCell
{...{
task,
name: "projectId",
value: task.project?.title,
user:user
}}
/>
)}
{/* executor cell display */}
{/* executor cell display */}
{/* executor cell display */}
{/* executor cell display */}
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<BasicSelect
items={executors.map((e) => ({
value: e?.id,
title: e?.displayName,
}))}
task={task}
onChange={onExecutorChange}
name="executor"
defaultValue={defaultExecutor?.id}
/>
</TableCell>
) : (
<CustomTableCell
{...{
task,
name: "executor",
value: task.executor?.displayName,
user:user
}}
/>
)}
<CustomTableCell
{...{
task,
name: "author",
value: task.author.displayName,
user:user
}}
/>
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<Tooltip title="Перейти в календарь">
<IconButton
onClick={(id) => { deleteHandle(task.id);}}
>
<CalendarMonthIcon />
</IconButton>
</Tooltip>
</TableCell>
) : (
task.dateTimeTasks.length>1 ?
<TableCell>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpen(!open)}
>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
</TableCell>
:
<CustomTableCell
{...{
task,
name: "dateTimeStart",
value: moment(task.dateTimeTasks[0]?.dateTimeStart)
.utc()
.format("DD-MM-YY "),
value2:moment(task.dateTimeTasks[0]?.dateTimeStart)
.utc()
.format("kk:mm")+" - "+
moment(task.dateTimeTasks[0]?.dateTimeDue)
.utc()
.format("kk:mm"),
user:user
}}>
</CustomTableCell>
)}
{task.isEditMode && task.author.id===user.id ? (
<TableCell>
<MaterialUIPickers
task={task}
name="dateTimeDue"
onChange={onDateChange}
user={user}
/>
</TableCell>
) : (
<CustomTableCell
{...{
task,
name: "dateTimeDeadLine",
value: moment(task.dateTimeDeadLine
)
.utc()
.format("DD-MM-YY kk:mm"),
user:user
}}
/>
)}
{task.isEditMode ? (
<TableCell>
<BasicSelect
items={[
{ value: "opened", title: "создано" },
{ value: "done", title: "выполнено" },
{ value: "failed", title: "просрочено" },
{ value: "progress", title: "в работе" },
{ value: "cancelled", title: "отменено" },
]}
task={task}
onChange={onChange}
name="accomplish"
value={task.accomplish}
user={user}
/>
</TableCell>
) : (
<CustomTableCell
{...{
task,
name: "accomplish",
value: TaskStatuses[task.accomplish],
user:user
}}
/>
)}
<TableCell>
<Tooltip title="Редактировать">
{task.isEditMode ? (
<IconButton
aria-label="done"
onClick={() => {
onToggleEditModeDone(task.id);
handleEditTask(task);
}}
>
<Done />
</IconButton>
) : (
<IconButton
aria-label="edit"
onClick={() => onToggleEditMode(task.id)}
>
<Edit />
</IconButton>
)}
</Tooltip>
</TableCell>
{task.author.id===user.id ?
(<TableCell>
<Tooltip title="Удалить">
<IconButton
onClick={(id) => {
deleteHandle(task.id);
}}
>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>):null}
</TableRow>
{task.dateTimeTasks.length>1?
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={11}>
<Collapse in={open} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
Расписание
</Typography>
<Table size="small" aria-label="purchases" sx={{
backgroundColor: "#ebebeb"}}>
<TableHead>
<TableRow>
<TableCell colSpan={10} >Дата создания</TableCell>
<TableCell align="right">День недели</TableCell>
<TableCell align="right">Начало</TableCell>
<TableCell align="center" colSpan={1}>Окончание</TableCell>
<TableCell align="center" ></TableCell>
<TableCell align="center" ></TableCell>
</TableRow>
</TableHead>
<TableBody>
{task.dateTimeTasks.map((dateTimeTask, index) => (
<TableRow key={index}>
<TableCell component="th" scope="row" colSpan={10}>
{moment(task.createdAt)
.utc()
.format("DD/MM")}
</TableCell>
<TableCell align="right">
{getDayOfWeek(dateTimeTask.dateTimeStart)}, {moment(dateTimeTask.dateTimeStart)
.utc()
.format("DD/MM")}
</TableCell>
<TableCell align="right">
{timeTransform(dateTimeTask.dateTimeStart)}
</TableCell>
<TableCell align="center" colSpan={1}>
{timeTransform(dateTimeTask.dateTimeDue)}
</TableCell>
{/* Edit option datetimeTask */}
<TableCell
// style={{width:'0%'}}
>
</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>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
:<></>}
</>
)
}
export default TableRowTask;
.modal{
display: flex;
flex-direction: column;
padding: 10px;
align-items: center;
position: absolute;
top: 200px;
left: 200px;
width: 300px;
height: 300px;
background-color: white;
border: 2px solid #000;
box-shadow: 24px;
border-radius:5px
}
.modalBox{
display: flex;
justify-content: space-around;
flex-direction: column;
}
\ No newline at end of file
import { Modal, IconButton } from "@mui/material";
import "./TaskModal.css";
import { Done } from "@mui/icons-material";
import Input from "@mui/material/Input";
import TextField from "@mui/material/Input";
const TaskModal = ({handleClose,open,task,onChange,user }) => {
return (
<Modal
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
BackdropProps={{ style: { backgroundColor: 'rgba(255,255,255, 0)' } }}
closeAfterTransition
onClose={handleClose}
open={open}
>
{task?.isEditMode && task.author.id===user.id ? (
<div className="modal">
<Input
label="название"
color="secondary"
value={task.title}
name="title"
onChange={(e) => onChange(e, task)}
style={{
width: "auto",
fontWeight: "600",
height: "40px",
fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}}
/>
<TextField
label="описание"
value={task.description}
name="description"
onChange={(e) => onChange(e, task)}
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}
sx={{margingBottom:"5px",marginTop:"auto"}}>
<Done />
</IconButton>
</div>
) : (
<div className="modal">
{task && task.title && (
<div
style={{
height: "40px",
fontWeight: "600",
width:"280px",
margin:"10px",
padding:"5px",
border: '2px solid #D3D3D3',
borderRadius:"5px"
}}
>
{task.title}
</div>
)}
{task && task.description && (
<div
style={{margin:"10px",
border: '2px solid #D3D3D3',
borderRadius:"5px",
width:"280px",
height: "200px",
margin:"10px",
padding:"5px",
}}>
{task.description}
</div>
)}
<IconButton
aria-label="close"
onClick={handleClose}
sx={{margingBottom:"5px",marginTop:"auto"}}
>
X
</IconButton>
</div>
)}
</Modal>
);
};
export default TaskModal;
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
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 '../UI/MultipleSelect/MultipleSelect';
import Add from "@mui/icons-material/Add";
import Close from "@mui/icons-material/Close";
export default function UsersTaskToolBar({projects,onClose,projectIdListForTaskSelect,setProjectIdListForTaskSelect,formStatus,onClick}) {
let projectsFilter =
<></>
if (Array.isArray(projects)) {
projectsFilter=
<MultipleSelect
projects={projects}
onClose={onClose}
projectName={projectIdListForTaskSelect}
setProjectName={setProjectIdListForTaskSelect}
/>
}
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar
>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Задачи сотрудников
</Typography>
{projectsFilter}
<Button
color={formStatus === true ? "info" : "inherit"}
style={{
backgroundColor: formStatus === true ? "white" : "inherit",
}}
onClick={onClick}
>
{formStatus === true ? (
<>
<Close />
<span style={{ lineHeight: "16px" }}>Скрыть задачу</span>
</>
) : (
<>
<Add />
<span style={{ lineHeight: "16px" }}>Добавить задачу</span>
</>
)}
</Button>
</Toolbar>
</AppBar>
</Box>
);
}
import * as React from "react";
import React from "react";
import TextField from "@mui/material/TextField";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
import { AdapterMoment } from "@mui/x-date-pickers/AdapterMoment";
import moment from "moment";
export default function MaterialUIPickers(props) {
export default function MaterialUIPickers({task, name, onChange }) {
let fullYear = new Date().getFullYear()
let month = new Date().getMonth()
let day = new Date().getDate();
return (
<LocalizationProvider
dateAdapter={AdapterMoment}
sx={{ width: "100%", fontSize: 5, fontWeight: "200" }}
adapterLocale={'ru-RU'}
>
<DateTimePicker
inputFormat="DD-MM-YY kk:mm A"
disabled={props.task.readOnly}
renderInput={(params) => (
minTime={moment({year:fullYear,month:month,day:day ,hour:11,minute:0})}
maxTime={moment({year:fullYear,month:month,day:day ,hour:20,minute:0})}
disablePast={true}
showTimeSelect={true}
minutesStep={60}
ampm={false}
ampmInClock={false}
inputFormat="DD/MM/YY HH:mm"
renderInput={(params) =>{ return (
<TextField
{...params}
sx={{ width: "auto", fontWeight: "200", fontSize: 5 }}
name={props.name}
name={name}
/>
)}
value={props.task[props.name]}
)}}
value={task.dateTimeDeadLine}
onChange={(newValue) => {
props.onChange(props.task.id, newValue, props.name);
onChange(newValue, name);
}}
/>
</LocalizationProvider>
......
import { Box, Divider, Grid, IconButton, TextField, Tooltip, Typography, } from "@mui/material";
import { styled } from '@mui/material/styles';
import { memo, useMemo } from "react";
import { priorities } from "../../../../constants";
import CustomSelect from "../../../UI/СustomSelect/СustomSelect"
import MaterialUIPickers from "../DateTimePicker/DateTimePicker";
import { Save } from "@mui/icons-material";
import { isValidate } from "./helpers";
const StyledTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} classes={{ popper: className }} />
))`
& .MuiTooltip-tooltip {
background: white;
}
`;
function NewTaskForm({ addFormStatus, onChangeNewTaskHandler, newTask, allUserProjectsForModalTask, onDateChangeHandler, createNewTaskHandler }) {
const workers = useMemo(() => {
if (newTask?.project) {
return newTask?.project?.members.map((member) => { return { value: member.user, text: member.user.displayName } })
} else {
return [{ value: '', text: 'Выберите проект' }]
}
}, [newTask?.project])
return (
<Box sx={{
height: addFormStatus ? '200px' : '0px',
transition: 'all 0.3s linear',
visibility: addFormStatus ? 'visible' : 'hidden',
transform: addFormStatus ? 'translateY(0)' : 'translateY(-20vh)'
}}>
<Box>
<Divider>
<Typography variant="overline">Добавить новую задачу</Typography>
</Divider>
<Box sx={{
backgroundColor: "#E8E8E8",
marginBottom: "2em",
}}>
<Grid container padding={2}>
<Grid item xs={1}>Приоритеты</Grid>
<Grid item xs={3.5}>Заголовок</Grid>
<Grid item xs={2}>Проект</Grid>
<Grid item xs={2}>Исполнитель</Grid>
<Grid item xs={3}>Дедлайн</Grid>
<Grid item xs={0.5}></Grid>
</Grid>
<Grid container padding={2} alignItems='center'>
<Grid item xs={1}>
<CustomSelect
defaultValue={priorities[0]?.value}
value={newTask.priority}
name={'priority'}
variant={'outlined'}
onChange={onChangeNewTaskHandler}
id={'priority-type'}
items={priorities}
sx={{ width: '90%' }}
/>
</Grid>
<Grid item xs={3.5}>
<StyledTooltip
title={<TextField
id="task-description"
value={newTask.description}
variant="outlined"
name='description'
placeholder='Описание'
sx={{ width: '300px' }}
onChange={onChangeNewTaskHandler}
multiline
rows={5}
/>}>
<TextField
id="task-title"
value={newTask.title}
variant="outlined"
name='title'
sx={{ width: '90%' }}
onChange={onChangeNewTaskHandler}
/>
</StyledTooltip>
</Grid>
<Grid item xs={2}>
<CustomSelect
value={newTask.project}
name={'project'}
variant={'outlined'}
onChange={onChangeNewTaskHandler}
id={'project'}
items={allUserProjectsForModalTask}
sx={{ width: '90%' }}
/>
</Grid>
<Grid item xs={2}>
<CustomSelect
value={newTask.executor}
name={'executor'}
variant={'outlined'}
onChange={onChangeNewTaskHandler}
id={'executor'}
items={workers}
sx={{ width: '90%' }}
/>
</Grid>
<Grid item xs={3}>
<MaterialUIPickers
task={newTask}
name="dateTimeDeadLine"
onChange={onDateChangeHandler}
/>
</Grid>
<Grid item xs={0.5} >
<IconButton disabled={!isValidate(newTask.title, newTask.description)} onClick={createNewTaskHandler}>
<Save />
</IconButton>
</Grid>
</Grid>
<Grid container></Grid>
</Box >
<Divider />
</Box>
</Box>);
}
export default memo(NewTaskForm)
\ No newline at end of file
export const isValidate = (title, description) => {
if (title.length === 0) return false
if (title.length < 50 && description.length < 100) return true
return false
}
\ No newline at end of file
import { TableCell, TextField, Tooltip } from "@mui/material";
import moment from "moment";
import { memo, useMemo } from "react";
import { accomplishStatuses, priorities } from "../../../../../../constants";
import CustomSelect from "../../../../../UI/СustomSelect/СustomSelect"
import { styled } from '@mui/material/styles';
import MaterialUIPickers from "../../../DateTimePicker/DateTimePicker";
const StyledTooltip = styled(({ className, ...props }) => (
<Tooltip {...props} classes={{ popper: className }} />
))`
& .MuiTooltip-tooltip {
background: white;
}
`;
function EditRow({ buttons, dateTimeTasks, onChangeCurrentTaskHandler, currentTask, allUserProjectsForModalTask, onDateChangeEditHandler, user }) {
const workers = useMemo(() => {
if (currentTask?.project) {
currentTask.project = allUserProjectsForModalTask.find((project) => project?.value?.id === currentTask?.project?.id)?.value
const arrUsers = currentTask?.project?.members.map((member) => { return { value: member.user, text: member.user.displayName } })
arrUsers.push({ value: '', text: 'Никто' })
return arrUsers
} else {
return [{ value: '', text: 'Выберите проект' }]
}
}, [allUserProjectsForModalTask, currentTask])
return (
<>
<TableCell sx={{ width: '4%' }}>
{user.id === currentTask.author.id ?
<CustomSelect
defaultValue={priorities[0]?.value}
value={currentTask.priority}
name={'priority'}
variant={'outlined'}
onChange={onChangeCurrentTaskHandler}
id={'priority-type'}
items={priorities}
sx={{ width: '100%' }}
/>
: currentTask.priority}
</TableCell>
<TableCell sx={{ width: '10%' }}>{moment(currentTask.createdAt).format('DD.MM.YYYY')}</TableCell>
<Tooltip title={currentTask.description}>
<TableCell sx={{ width: '25%', overflow: 'hidden', textOverflow: 'ellipsis' }}>
{user.id === currentTask.author.id ?
<StyledTooltip
title={<TextField
id="task-description"
value={currentTask.description}
variant="outlined"
name='description'
placeholder='Описание'
sx={{ width: '300px' }}
onChange={onChangeCurrentTaskHandler}
multiline
rows={5}
/>}>
<TextField
id="task-title"
value={currentTask.title}
variant="outlined"
name='title'
onChange={onChangeCurrentTaskHandler}
sx={{ width: '90%' }}
/>
</StyledTooltip>
: currentTask.title}
</TableCell>
</Tooltip>
<TableCell sx={{ width: '10%' }}>
{user.id === currentTask.author.id ?
<CustomSelect
value={currentTask.project}
name={'project'}
variant={'outlined'}
onChange={onChangeCurrentTaskHandler}
id={'project'}
items={allUserProjectsForModalTask}
sx={{ width: '100%' }}
/>
: currentTask.projectTitle}
</TableCell>
<TableCell sx={{ width: '8%' }}>
{user.id === currentTask.author.id ?
<CustomSelect
value={currentTask.executor}
name={'executor'}
variant={'outlined'}
onChange={onChangeCurrentTaskHandler}
id={'executor'}
items={workers}
sx={{ width: '100%' }}
/>
: currentTask.executorName}
</TableCell>
<TableCell sx={{ width: '8%' }}>{currentTask.authorName}</TableCell>
<TableCell sx={{ width: '15%' }}>
{dateTimeTasks}
</TableCell>
<TableCell sx={{ width: '10%' }}>
{user.id === currentTask.author.id ?
<MaterialUIPickers
task={currentTask}
name="dateTimeDeadLine"
onChange={onDateChangeEditHandler}
/>
: currentTask.dateTimeDeadLine ? moment(currentTask.dateTimeDeadLine).utc().format('DD.MM.YYYY HH:MM') : null}
</TableCell>
<TableCell sx={{ width: '7%' }}>
<CustomSelect
value={currentTask.accomplish}
name={'accomplish'}
variant={'outlined'}
onChange={onChangeCurrentTaskHandler}
id={'accomplish'}
items={accomplishStatuses}
sx={{ width: '100px' }}
/>
</TableCell>
<TableCell size='medium' sx={{ width: '5%', position: 'relative' }}>
{buttons}
</TableCell>
</>)
}
export default memo(EditRow)
\ No newline at end of file
import { Collapse, IconButton, Table, TableBody, TableCell, TableHead, TableRow, Tooltip, Typography } from "@mui/material";
import RemoveIcon from '@mui/icons-material/Remove';
import moment from "moment";
import { memo } from "react";
import { Box } from "@mui/system";
const weekDays = ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"];
function TableForCopiesTasks({ task, openCopies, user, deleteCopyTaskHandler }) {
const roudHourUp = (dateIso) => {
let m = moment(dateIso);
let roundUp = m.minute() || m.second() || m.millisecond() ? m.add(1, 'hour').startOf('hour') : m.startOf('hour');
return roundUp
}
const timeTransform = (dateIso) => {
const exp = roudHourUp(moment.utc(dateIso)).format("HH:00")
return exp;
}
const getDayOfWeek = (dateIso) => {
const date = moment.utc(dateIso);
return weekDays[date.day()];
}
return (
<TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0 }} colSpan={11}>
<Collapse in={openCopies} timeout="auto" unmountOnExit>
<Box sx={{ margin: 1 }}>
<Typography variant="h6" gutterBottom component="div">
Расписание
</Typography>
<Table size="small" aria-label="purchases" sx={{
backgroundColor: "#ebebeb"
}}>
<TableHead>
<TableRow>
<TableCell colSpan={10} >Дата создания</TableCell>
<TableCell align="right">День недели</TableCell>
<TableCell align="right">Начало</TableCell>
<TableCell align="center" colSpan={1}>Окончание</TableCell>
<TableCell align="center" ></TableCell>
<TableCell align="center" ></TableCell>
</TableRow>
</TableHead>
<TableBody>
{task.dateTimeTasks.map((dateTimeTask, index) => (
<TableRow key={index}>
<TableCell component="th" scope="row" colSpan={10}>
{moment(task.createdAt)
.utc()
.format("DD/MM")}
</TableCell>
<TableCell align="right">
{getDayOfWeek(dateTimeTask.dateTimeStart)}, {moment(dateTimeTask.dateTimeStart)
.utc()
.format("DD/MM")}
</TableCell>
<TableCell align="right">
{timeTransform(dateTimeTask.dateTimeStart)}
</TableCell>
<TableCell align="center" colSpan={1}>
{timeTransform(dateTimeTask.dateTimeDue)}
</TableCell>
{task.author.id === user.id ?
(<TableCell style={{ width: '0%' }}>
<Tooltip title="Удалить Копию">
<IconButton
onClick={() => {
deleteCopyTaskHandler(dateTimeTask.id);
}}
>
<RemoveIcon />
</IconButton>
</Tooltip>
</TableCell>) : null}
</TableRow>
))}
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>);
}
export default memo(TableForCopiesTasks)
\ No newline at end of file
import { Divider, IconButton, TableCell, TableRow, Tooltip } from "@mui/material";
import moment from "moment";
import { memo, useCallback, useMemo, useState } from "react";
import DeleteButton from "../../../../UI/DeleteButton/DeleteButton";
import { Done, Edit } from "@mui/icons-material";
import { useSelector } from "react-redux";
import CalendarMonthIcon from '@mui/icons-material/CalendarMonth';
import { Box } from "@mui/system";
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import TableForCopiesTasks from "./TableForCopiesTasks/TableForCopiesTasks";
import EditRow from "./EditRow/EditRow";
const editClass = {
cursor: 'pointer',
transition: '0.5s',
"&:hover": {
transition: '0.5s',
transform: 'scale(1.2)'
}
}
function UsersTasksRow({ row, deleteTaskHandler, calendarOpen, deleteCopyTaskHandler, currentTask, isEdit, setIsEdit, setCurrentTask, onChangeCurrentTaskHandler, allUserProjectsForModalTask, onDateChangeEditHandler, editCurrentTaskHandler }) {
const user = useSelector((state) => state.users.user);
const [openCopies, setOpenCopies] = useState(false);
const [editMode, setEditMode] = useState(false);
const dateTimeTasks = useMemo(() => {
if (row.dateTimeTasks.length === 1) {
const date = moment(row.dateTimeTasks[0].dateTimeStart).utc().format('DD.MM')
const start = moment(row.dateTimeTasks[0].dateTimeStart).utc().format('HH:mm')
const end = moment(row.dateTimeTasks[0].dateTimeDue).utc().add(1, 'minutes').format('HH:mm')
const diff = parseInt(end.split(':')[0]) - parseInt(start.split(':')[0])
return <Box sx={{ width: '90%', display: 'flex' }}>
<Tooltip title={moment(row.dateTimeTasks[0].dateTimeStart).utc().format('YYYY')}>
<Box>
{`${date} (${start} - ${end})`}
<Divider sx={{ opacity: 0 }} />
{`часы: ${diff}`}
</Box>
</Tooltip>
{user.id === row?.executor?.id ?
<Tooltip title="Перейти в календарь">
<IconButton
sx={{ marginLeft: '5px' }}
onClick={() => { calendarOpen(row) }}
>
<CalendarMonthIcon />
</IconButton>
</Tooltip>
: null
}
</Box>
} else if (row.dateTimeTasks.length > 1) {
return (<>
<IconButton
aria-label="expand row"
size="small"
onClick={() => setOpenCopies(prevState => !prevState)}
>
{openCopies ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</IconButton>
{
user.id === row?.executor?.id ?
<Tooltip title="Перейти в календарь">
<IconButton
sx={{ marginLeft: '5px' }}
onClick={() => { calendarOpen(row) }}
>
<CalendarMonthIcon />
</IconButton>
</Tooltip>
: null
}
</>)
} else if (row.dateTimeTasks.length === 0) {
return (<>
Копий нет
{
user.id === row?.executor?.id ?
<Tooltip title="Перейти в календарь">
<IconButton
sx={{ marginLeft: '5px' }}
onClick={() => { calendarOpen(row) }}
>
<CalendarMonthIcon />
</IconButton>
</Tooltip>
: null
}
</>)
}
}, [user.id, calendarOpen, row, openCopies])
const onClickEditButtonHandler = useCallback(() => {
if (!editMode) {
setCurrentTask({
...row,
project: { ...row.project },
executor: { ...row.executor }
})
} else {
editCurrentTaskHandler()
setCurrentTask({
priority: '',
title: '',
project: '',
description: '',
executor: '',
})
}
setEditMode((prevState) => !prevState)
setIsEdit((prevState) => !prevState)
}, [setIsEdit, editMode, row, setCurrentTask, editCurrentTaskHandler])
const buttons = useMemo(() => {
if (!editMode && isEdit) return null
if (editMode) {
return <Done sx={editClass} onClick={() => { onClickEditButtonHandler() }} />
} else {
if (user.id === row.author.id) {
return (<>
<Edit sx={{ ...editClass, position: 'absolute', left: -10 }} onClick={() => { onClickEditButtonHandler() }} />
<DeleteButton onClick={() => { deleteTaskHandler(row.id) }} />
</>)
} else if (user.id === row.executor.id) {
return (<Edit sx={editClass} onClick={() => { onClickEditButtonHandler() }} />)
} else {
return null
}
}
}, [deleteTaskHandler, row, user.id, editMode, isEdit, onClickEditButtonHandler])
return (<>
<TableRow
hover
key={row.id}
>
{editMode ?
<>
<EditRow
buttons={buttons}
dateTimeTasks={dateTimeTasks}
onChangeCurrentTaskHandler={(e) => { onChangeCurrentTaskHandler(e) }}
currentTask={currentTask}
allUserProjectsForModalTask={allUserProjectsForModalTask}
onDateChangeEditHandler={onDateChangeEditHandler}
user={user}
/>
</>
:
<>
<TableCell sx={{ width: '4%' }}>{row.priority ? row.priority : null}</TableCell>
<TableCell sx={{ width: '10%' }}>{moment(row.createdAt).format('DD.MM.YYYY')}</TableCell>
<Tooltip title={row.description}>
<TableCell sx={{ width: '25%' }}>
{row.title}
</TableCell>
</Tooltip>
<TableCell sx={{ width: '10%' }}>{row.projectTitle}</TableCell>
<TableCell sx={{ width: '8%' }}>{row.executorName}</TableCell>
<TableCell sx={{ width: '8%' }}>{row.authorName}</TableCell>
<TableCell sx={{ width: '15%' }}>
{dateTimeTasks}
</TableCell>
<TableCell sx={{ width: '10%' }}>{row.dateTimeDeadLine ? moment(row.dateTimeDeadLine).utc().format('DD.MM.YYYY HH:MM') : null}</TableCell>
<TableCell sx={{ width: '7%' }}>
{row.accomplishTranslate}
</TableCell>
<TableCell size='medium' sx={{ width: '5%', position: 'relative' }}>
{buttons}
</TableCell>
</>}
</TableRow>
{row.dateTimeTasks.length ? <TableForCopiesTasks
task={row}
openCopies={openCopies}
user={user}
deleteCopyTaskHandler={deleteCopyTaskHandler}
/> : null}
</>)
}
export default memo(UsersTasksRow)
\ No newline at end of file
import { TableBody} from "@mui/material";
import { memo, useState } from "react";
import { getComparator, stableSort } from "./helpers";
import UsersTasksRow from "./UsersTasksRow/UsersTasksRow";
function UsersTasksTableBody({ rows, page, rowsPerPage, order, orderBy, deleteTaskHandler, calendarOpen, deleteCopyTaskHandler, currentTask, setCurrentTask, onChangeCurrentTaskHandler, allUserProjectsForModalTask, onDateChangeEditHandler, editCurrentTaskHandler}) {
const [isEdit, setIsEdit] = useState(false)
return (<>
<TableBody>
{stableSort(rows, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((row, index) => {
return (
<UsersTasksRow
key={row.id}
deleteTaskHandler={deleteTaskHandler}
row={row}
deleteCopyTaskHandler={deleteCopyTaskHandler}
calendarOpen={calendarOpen}
isEdit={isEdit}
setIsEdit={setIsEdit}
currentTask={currentTask}
setCurrentTask={setCurrentTask}
onChangeCurrentTaskHandler={onChangeCurrentTaskHandler}
allUserProjectsForModalTask={allUserProjectsForModalTask}
onDateChangeEditHandler={onDateChangeEditHandler}
editCurrentTaskHandler={editCurrentTaskHandler}
/>)
})}
</TableBody>
</>);
}
export default memo(UsersTasksTableBody)
\ No newline at end of file
function descendingComparator(a, b, orderBy, order) {
if (!b[orderBy]) {
if (order ==='asc') {
return 1
}
return -1
}
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
export function getComparator(order, orderBy) {
return order === 'desc'
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy, order);
}
export function stableSort(array, comparator) {
const stabilizedThis = array.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) {
return order;
}
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
import {Table, TableContainer, } from "@mui/material";
import { memo } from "react";
import NewTaskForm from "./NewTaskForm/NewTaskForm";
import UsersTasksTableBody from "./UsersTasksTableBody/UsersTasksTableBody";
import UsersTasksTableHead from "./UsersTasksTableHead/UsersTasksTableHead";
function UsersTasksTableContainer({ order, orderBy, handleRequestSort, rows, page, rowsPerPage, addFormStatus, onChangeNewTaskHandler, newTask, allUserProjectsForModalTask, onDateChangeHandler, createNewTaskHandler, deleteTaskHandler, calendarOpen, deleteCopyTaskHandler, currentTask, setCurrentTask, onChangeCurrentTaskHandler, onDateChangeEditHandler, editCurrentTaskHandler}) {
return (
<TableContainer>
<NewTaskForm
addFormStatus={addFormStatus}
onChangeNewTaskHandler={(e)=>{onChangeNewTaskHandler(e)}}
newTask={newTask}
allUserProjectsForModalTask={allUserProjectsForModalTask}
onDateChangeHandler={onDateChangeHandler}
createNewTaskHandler={()=>{createNewTaskHandler()}}
/>
<Table
sx={{ minWidth: 750 }}
aria-labelledby="tableTitle"
>
<UsersTasksTableHead
order={order}
orderBy={orderBy}
handleRequestSort={handleRequestSort}
deleteTaskHandler={deleteTaskHandler}
/>
<UsersTasksTableBody
order={order}
orderBy={orderBy}
rows={rows}
page={page}
rowsPerPage={rowsPerPage}
deleteTaskHandler={deleteTaskHandler}
calendarOpen={calendarOpen}
deleteCopyTaskHandler={deleteCopyTaskHandler}
currentTask={currentTask}
setCurrentTask={setCurrentTask}
onChangeCurrentTaskHandler={onChangeCurrentTaskHandler}
allUserProjectsForModalTask={allUserProjectsForModalTask}
onDateChangeEditHandler={onDateChangeEditHandler}
editCurrentTaskHandler={editCurrentTaskHandler}
/>
</Table>
</TableContainer>
);
}
export default memo(UsersTasksTableContainer)
\ No newline at end of file
import * as React from "react";
import PropTypes from "prop-types";
import Box from "@mui/material/Box";
import TableCell from "@mui/material/TableCell";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import TableSortLabel from "@mui/material/TableSortLabel";
import { visuallyHidden } from "@mui/utils";
import { Box, TableCell, TableHead, TableRow, TableSortLabel } from "@mui/material";
import { visuallyHidden } from '@mui/utils';
import { memo } from "react";
const headCells = [
{
id: "id",
numeric: true,
disablePadding: true,
label: "",
},
{
id: "priority",
numeric: false,
disablePadding: true,
label: "Приоритет",
canSort: true,
style: {
width: '4%'
}
},
{
id: "createdAt",
numeric: true,
disablePadding: false,
label: "Дата создания",
canSort: true,
style: {
width: '10%'
}
},
{
id: "title",
numeric: true,
disablePadding: false,
label: "Заголовок",
canSort: true,
style: {
width: '25%'
}
},
{
id: "projectName",
numeric: true,
disablePadding: false,
id: "projectTitle",
label: "Проект",
canSort: true,
style: {
width: '10%'
}
},
{
id: "executorDisplayName",
numeric: true,
disablePadding: false,
id: "executorName",
label: "Исполнитель",
canSort: true,
style: {
width: '8%'
}
},
{
id: "authorDisplayName",
numeric: true,
disablePadding: false,
id: "authorName",
label: "Автор",
canSort: true,
style: {
width: '8%'
}
},
{
id: "dateTimeStart",
numeric: true,
disablePadding: false,
label: "Дата и время выполнения",
canSort: false,
style: {
width: '15%'
}
},
{
id: "dateTimeDue",
numeric: true,
disablePadding: false,
id: "dateTimeDeadLine",
label: "Дедлайн",
canSort: true,
style: {
width: '10%'
}
},
{
id: "accomplish",
numeric: true,
disablePadding: false,
id: "accomplishTranslate",
label: "Статус",
canSort: true,
style: {
width: '7%'
}
},
{
id: "change",
numeric: false,
disablePadding: false,
label: "",
},
{
id: "delete",
numeric: false,
disablePadding: false,
id: "buttons",
label: "",
canSort: false,
style: {
width: '5%'
}
},
];
export default function UsersTasksHeader({ order, orderBy, rowCount, onRequestSort }) {
function UsersTasksTableHead({ order, orderBy, handleRequestSort }) {
const createSortHandler = (property) => (event) => {
onRequestSort(event, property);
handleRequestSort(event, property);
};
return (
......@@ -95,22 +96,22 @@ export default function UsersTasksHeader({ order, orderBy, rowCount, onRequestSo
{headCells.map((headCell) => (
<TableCell
key={headCell.id}
align={"center"}
padding={headCell.disablePadding ? "none" : "normal"}
sortDirection={orderBy === headCell.id ? order : false}
sx={headCell.style}
>
<TableSortLabel
{headCell.canSort ? <TableSortLabel
active={orderBy === headCell.id}
direction={orderBy === headCell.id ? order : "asc"}
direction={orderBy === headCell.id ? order : 'asc'}
onClick={createSortHandler(headCell.id)}
>
{headCell.label}
{orderBy === headCell.id ? (
<Box component="span" sx={visuallyHidden}>
{order === "desc" ? "sorted descending" : "sorted ascending"}
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
</Box>
) : null}
</TableSortLabel>
</TableSortLabel> : headCell.label}
</TableCell>
))}
</TableRow>
......@@ -118,9 +119,4 @@ export default function UsersTasksHeader({ order, orderBy, rowCount, onRequestSo
);
}
UsersTasksHeader.propTypes = {
onRequestSort: PropTypes.func.isRequired,
order: PropTypes.oneOf(["asc", "desc"]).isRequired,
orderBy: PropTypes.string.isRequired,
rowCount: PropTypes.number.isRequired,
};
export default memo(UsersTasksTableHead)
\ No newline at end of file
import { TablePagination } from "@mui/material";
import { memo } from "react";
function UsersTasksTablePagination({count, rowsPerPage, page, handleChangePage, handleChangeRowsPerPage}) {
return (
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={count}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
);
}
export default memo(UsersTasksTablePagination)
\ No newline at end of file
import {Button} from '@mui/material';
import {Add, Close} from "@mui/icons-material";
import { memo } from 'react';
function CreateTaskFromButton({ addFormStatus, onClick }) {
return (
<Button
color={addFormStatus === true ? "info" : "inherit"}
style={{
backgroundColor: addFormStatus === true ? "white" : "inherit",
width: '250px'
}}
onClick={onClick}
>
{addFormStatus === true ? (
<>
<Close />
<span style={{ lineHeight: "16px" }}>Скрыть задачу</span>
</>
) : (
<>
<Add />
<span style={{ lineHeight: "16px" }}>Добавить задачу</span>
</>
)}
</Button>
);
}
export default memo(CreateTaskFromButton)
\ No newline at end of file
import { AppBar, Box, Typography } from "@mui/material";
import { memo } from "react";
import CreateTaskFromButton from "./CreateTaskFromButton/CreateTaskFromButton";
function UsersTasksTableToolbar({ addFormStatus, createTaskFromButtonHandler }) {
return (
<AppBar position="static" sx={{ padding: 3 }}>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Typography
sx={{ flex: '1 1 100%' }}
variant="h6"
id="tableTitle"
component="div"
>
Задачи сотрудников
</Typography>
<CreateTaskFromButton
addFormStatus={addFormStatus}
onClick={() => { createTaskFromButtonHandler() }}
/>
</Box>
</AppBar>
);
}
export default memo(UsersTasksTableToolbar)
\ No newline at end of file
......@@ -26,3 +26,11 @@ export const AllHoursOneHourFormat = ['0:00', '1:00', '2:00', '3:00', '4:00', '
export const AllHoursTwoHourFormat = ['0:00', '2:00', '4:00', '6:00', '8:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00']
export const projectRoles = [{ value: 'admin', text: 'Админ' }, { value: 'user', text: 'Юзер' }, { value: 'watcher', text: 'Наблюдатель' }]
export const accomplishStatuses = [
{ value: 'opened', text: 'Открыто' },
{ value: 'done', text: 'Выполнено' },
{ value: 'failed', text: 'Просрочено' },
{ value: 'progress', text: 'В работе' },
{ value: 'cancelled', text: 'Отменено' }
]
\ No newline at end of file
......@@ -199,6 +199,7 @@ function MonthCalendar() {
executor: userId,
author: user.id,
calendar: true,
priority: currentTask.priority === '' ? null : currentTask.priority
}
delete newTask.infoForCell
delete newTask.id
......
import * as React from "react";
import {
Box,
Table,
TableBody,
TableContainer,
TablePagination,
Paper,
} from "@mui/material";
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import TaskModal from "../../components/UsersTasksCompoments/TaskModal/TaskModal";
import moment from "moment";
import UsersTaskToolBar from "../../components/UsersTasksCompoments/UsersTaskToolBar";
import { deleteTask, editTask, deleteDateTimeTask , fetchAllTasksByMembership} from "../../store/actions/tasksActions";
import NewTaskForm from "../../components/UsersTasksCompoments/NewTaskForm";
import TableRowTask from "../../components/UsersTasksCompoments/TableRowTask/TableRowTask";
import UsersTasksHeader from "./UsersTasksHeader/UsersTasksHeader";
export default function UsersTasks() {
import Paper from '@mui/material/Paper';
import UsersTasksTableToolbar from '../../components/UsersTasksCompoments/UsersTasksTableToolbar/UsersTasksTableToolbar';
import UsersTasksTablePagination from '../../components/UsersTasksCompoments/UsersTasksTablePagination/UsersTasksTablePagination';
import UsersTasksTableContainer from '../../components/UsersTasksCompoments/UsersTasksTableContainer/UsersTasksTableContainer';
import { activateCreateCopyTasksMode, addTaskToUserTasksTable, deleteDateTimeTaskUsers, deleteTaskUsers, editTaskUsers, fetchAllTasksByMembership } from '../../store/actions/tasksActions';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { useCallback, useEffect, useState } from 'react';
import { fetchAllUserProjects } from '../../store/actions/projectsActions';
import moment from 'moment';
import { useNavigate } from 'react-router-dom';
export default function EnhancedTable() {
const dispatch = useDispatch();
const tasks = useSelector((state) => state.tasks.tasks);
const projects = useSelector((state) => state.tasks.projects);
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);
const [order, setOrder] = useState("asc");
const [orderBy, setOrderBy] = useState("id");
const navigate = useNavigate()
const { tasks } = useSelector((state) => state.tasks);
const { allUserProjectsForModalTask } = useSelector(state => state.projects, shallowEqual)
const [newTask, setNewTask] = useState({
priority: '',
title: '',
project: '',
description: '',
executor: '',
dateTimeDeadLine: null,
})
const [currentTask, setCurrentTask] = useState({
priority: '',
title: '',
project: '',
description: '',
executor: '',
dateTimeDeadLine: null,
})
const [order, setOrder] = useState('asc');
const [orderBy, setOrderBy] = useState('createdAt');
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] =useState(25);
const [modal, setModal] = useState({
open: false,
task: null,
});
const [rowsPerPage, setRowsPerPage] = useState(10);
const [addFormStatus, setAddFormStatus] = useState(false);
useEffect(() => {
dispatch(fetchAllTasksByMembership());
if (tasks && tasks?.length > 0) {
setRecievedTasks(tasks);
}
}, [dispatch,
tasks?.length,
addTaskForm, setAddTaskForm]);
const handleRequestSort = ( property) => {
const isAsc = orderBy === property && order === "asc";
setOrder(isAsc ? "desc" : "asc");
setOrderBy(property);
};
const handleChangePage = ( newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
};
const onChange = (e, task) => {
const value = e.target.value;
const name = e.target.name;
const { id } = task;
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
return { ...task, [name]: value };
}
return task;
});
setRecievedTasks(newTasks);
};
dispatch(fetchAllUserProjects())
}, [dispatch]);
const onDateChange = (id, value, property) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
const onChangeNewTaskHandler = useCallback((e) => {
const { value, name } = e.target;
setNewTask((prevState => {
return {
...task,
[property]: moment.parseZone(value, "DD/MM/YY", true).format(),
};
}
return task;
});
setRecievedTasks(newTasks);
};
const onProjectChange = (e, task) => {
const projectId = e.target.value;
const project = projects.length>0 ?projects.find((uniqueProject) => uniqueProject.id === projectId):null;
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;
}
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;
...prevState,
[name]: value
}
return task;
});
setRecievedTasks(newTasks);
};
}));
}, [])
const onToggleEditMode = (id) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
const onChangeCurrentTaskHandler = useCallback((e) => {
const { value, name } = e.target;
setCurrentTask((prevState => {
return {
...task,
isEditMode: true,
readOnly: false,
};
...prevState,
[name]: value
}
return task;
});
setRecievedTasks(newTasks);
};
}));
}, [])
const onToggleEditModeDone = (id) => {
const newTasks = recievedTasks.map((task) => {
if (task.id === id) {
console.log('toggledDone task ', task)
const onDateChangeEditHandler = useCallback((value, property) => {
const utcAvoidoffset = moment(value).utcOffset(0, true).format()
setCurrentTask((prevState => {
return {
...task,
isEditMode: false,
readOnly: true,
};
...prevState,
[property]: utcAvoidoffset
}
return task;
});
setRecievedTasks(newTasks);
};
const handleEditTask= (task)=>{
dispatch(editTask(task))
}
const deleteHandle = (id) => {
dispatch(deleteTask(id));
};
}));
}, []);
const deleteDateTimeTaskHandle=(dateTimeTaskId)=>{
console.log('delete by dateTimeTaskId ', dateTimeTaskId)
dispatch(deleteDateTimeTask(dateTimeTaskId))
const onDateChangeHandler = useCallback((value, property) => {
const utcAvoidoffset = moment(value).utcOffset(0, true).format()
setNewTask((prevState => {
return {
...prevState,
[property]: utcAvoidoffset
}
}));
}, []);
const onModalOpen = (event, task) => {
event.stopPropagation();
setModal({ ...modal, open: true, id: task.id });
};
const handleClose = () => {
setModal({ ...modal, open: false, id: null });
};
// ++++++++фильтрация по проектам+++++++++++++++
const [projectIdListForTaskSelect, setProjectIdListForTaskSelect] = React.useState([]);
const [filterProjectTumbler, setFilterProjectTumbler] = React.useState(false);
const handleRequestSort = useCallback((event, property) => {
const isAsc = orderBy === property && order === 'asc';
setOrder(isAsc ? 'desc' : 'asc');
setOrderBy(property);
}, [order, orderBy]);
const handleChangePage = useCallback((event, newPage) => {
setPage(newPage);
}, []);
const onClose=(projectIdListForTaskSelect)=>{
let tasksFilteredByProject = tasks
if (projectIdListForTaskSelect.length>0) {
tasksFilteredByProject = tasks.filter(task=>projectIdListForTaskSelect.includes(task.project?.id))
}
setRecievedTasks(tasksFilteredByProject)
setFilterProjectTumbler(true)
}
const handleChangeRowsPerPage = useCallback((event) => {
setRowsPerPage(parseInt(event.target.value, 10));
setPage(0);
}, []);
const createTaskFromButtonHandler = useCallback(() => {
if (addFormStatus) {
setNewTask({
priority: '',
title: '',
project: '',
description: '',
executor: '',
dateTimeDeadLine: null
})
}
setAddFormStatus((prevState) => { return !prevState })
}, [addFormStatus])
const createNewTaskHandler = useCallback(() => {
if (newTask.priority === '' || newTask.project === '' || newTask.executor === '') {
const task = {
...newTask,
priority: newTask.priority ? newTask.priority : null,
project: newTask.project ? newTask.project : null,
executor: newTask.executor ? newTask.executor : null,
dateTimeDeadLine: new Date(newTask.dateTimeDeadLine) instanceof Date && !isNaN(new Date(newTask.dateTimeDeadLine)) ? newTask.dateTimeDeadLine : null
}
dispatch(addTaskToUserTasksTable(task))
} else {
dispatch(addTaskToUserTasksTable(newTask))
}
setNewTask({
priority: '',
title: '',
project: '',
description: '',
executor: '',
dateTimeDeadLine: null
})
setAddFormStatus((prevState) => { return !prevState })
}, [dispatch, newTask])
const deleteTaskHandler = useCallback((id) => {
dispatch(deleteTaskUsers(id))
}, [dispatch])
const deleteCopyTaskHandler = useCallback((id) => {
dispatch(deleteDateTimeTaskUsers(id))
}, [dispatch])
const calendarOpen = (task) => {
dispatch(activateCreateCopyTasksMode(task, navigate))
}
const editCurrentTaskHandler = useCallback(() => {
if (currentTask.priority === '' || currentTask.project === '' || currentTask.executor === '' || !Object.keys(currentTask.executor).length) {
const task = {
...currentTask,
priority: currentTask.priority ? currentTask.priority : null,
project: currentTask.project ? currentTask.project : null,
executor: currentTask.executor && currentTask.executor?.id ? currentTask.executor : null,
dateTimeDeadLine: new Date(currentTask.dateTimeDeadLine) instanceof Date && !isNaN(new Date(currentTask.dateTimeDeadLine)) ? currentTask.dateTimeDeadLine : null
}
dispatch(editTaskUsers(task))
} else {
dispatch(editTaskUsers(currentTask))
}
setCurrentTask({
priority: '',
title: '',
project: '',
description: '',
executor: '',
dateTimeDeadLine: null
})
}, [dispatch, currentTask])
// if (
// tasks &&
// tasks?.length > 0 &&
// recievedTasks &&
// recievedTasks?.length > 0
// ) {
return (
<Box sx={{ width: "fullwidth" }}>
<Paper sx={{ width: "100%", mb: 2 }}>
<UsersTaskToolBar
onClick={() => setAddTaskForm(!addTaskForm)}
formStatus={addTaskForm}
projects={projects}
onClose={onClose}
projectIdListForTaskSelect={projectIdListForTaskSelect}
setProjectIdListForTaskSelect={setProjectIdListForTaskSelect}
/>
{addTaskForm ? (
<NewTaskForm
projects={projects}
setCurrentProject={setCurrentProject}
currentProject={currentProject}
setAddTaskForm={()=>setAddTaskForm(false)}
<Paper sx={{ width: '100%', mb: 2 }}>
<UsersTasksTableToolbar
addFormStatus={addFormStatus}
createTaskFromButtonHandler={createTaskFromButtonHandler}
/>
) : null}
<TableContainer>
<Table sx={{ minWidth: 600 }} aria-labelledby="tableTitle" size='small'>
<UsersTasksHeader
<UsersTasksTableContainer
order={order}
orderBy={orderBy}
onRequestSort={handleRequestSort}
rowCount={recievedTasks.length}
/>
<TableBody>
{stableSort(recievedTasks, getComparator(order, orderBy))
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
.map((task, index) => {
return (
<TableRowTask
key ={index}
user={user}
task={task}
deleteHandle={deleteHandle}
handleEditTask ={handleEditTask}
deleteDateTimeTask={deleteDateTimeTaskHandle}
onChange={onChange}
onModalOpen={onModalOpen}
onProjectChange={onProjectChange}
executors={executors}
onExecutorChange={onExecutorChange}
uniqueProjects={projects}
onDateChange={onDateChange}
onToggleEditMode={onToggleEditMode}
onToggleEditModeDone={onToggleEditModeDone}
handleRequestSort={handleRequestSort}
rows={tasks}
page={page}
rowsPerPage={rowsPerPage}
addFormStatus={addFormStatus}
onChangeNewTaskHandler={onChangeNewTaskHandler}
newTask={newTask}
allUserProjectsForModalTask={allUserProjectsForModalTask}
onDateChangeHandler={onDateChangeHandler}
createNewTaskHandler={createNewTaskHandler}
deleteTaskHandler={deleteTaskHandler}
calendarOpen={calendarOpen}
deleteCopyTaskHandler={deleteCopyTaskHandler}
currentTask={currentTask}
setCurrentTask={setCurrentTask}
onChangeCurrentTaskHandler={onChangeCurrentTaskHandler}
onDateChangeEditHandler={onDateChangeEditHandler}
editCurrentTaskHandler={editCurrentTaskHandler}
/>
);
})}
</TableBody>
</Table>
</TableContainer>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
component="div"
count={recievedTasks.length}
<UsersTasksTablePagination
count={tasks.length}
rowsPerPage={rowsPerPage}
page={page}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
handleChangePage={handleChangePage}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Paper>
<TaskModal
task={recievedTasks.find((task) => task.id === modal.id)}
open={modal.open}
handleClose={handleClose}
onChange={onChange}
user={user}
/>
</Box>
);
}
// }
function descendingComparator(a, b, orderBy) {
if (b[orderBy] < a[orderBy]) {
return -1;
}
if (b[orderBy] > a[orderBy]) {
return 1;
}
return 0;
}
function getComparator(order, orderBy) {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
}
function stableSort(array, comparator) {
const stabilizedThis = array?.map((el, index) => [el, index]);
stabilizedThis.sort((a, b) => {
const order = comparator(a[0], b[0]);
if (order !== 0) {
return order;
}
return a[1] - b[1];
});
return stabilizedThis.map((el) => el[0]);
}
......@@ -87,7 +87,7 @@ function WeekCalendar() {
}, [])
const onChangeProjectHandler = useCallback((e, value) => {
setWorkerInfo((prevState) => { return { ...prevState, project: value } });
setWorkerInfo((prevState) => { return { ...prevState, project: value.id } });
}, []);
const onChangeWorkerHandler = useCallback((e, value) => {
......@@ -178,6 +178,7 @@ function WeekCalendar() {
executor: userId,
author: user.id,
calendar: true,
priority: currentTask.priority === '' ? null : currentTask.priority
}
delete newTask.infoForCell
delete newTask.id
......
......@@ -163,12 +163,24 @@ export const editTask = (task) => {
}
}
export const editTaskUsers = (task) => {
return async (dispatch) => {
dispatch(editTaskRequest());
try {
await axios.put(`/tasks/${task.id}`, task);
dispatch(editTaskSuccess())
await dispatch(fetchAllTasksByMembership())
} catch (error) {
dispatch(editTaskFailure(error.response.data));
}
}
}
export const editCalendarTask = (task, taskId, userId) => {
return async (dispatch) => {
dispatch(editTaskRequest());
try {
const response = await axios.put(`/copy-tasks/change-copy/${taskId}`, task);
console.log(response.data)
await axios.put(`/copy-tasks/change-copy/${taskId}`, task);
dispatch(editTaskSuccess())
dispatch(fetchCalendarTasks(userId))
} catch (error) {
......@@ -202,6 +214,19 @@ export const deleteTask = (taskId) => {
}
}
export const deleteTaskUsers = (taskId) => {
return async (dispatch) => {
dispatch(deleteTaskRequest());
try {
await axios.delete(`/tasks/${taskId}`);
dispatch(deleteTaskSuccess())
await dispatch(fetchAllTasksByMembership())
} catch (error) {
dispatch(deleteTaskFailure(error.response.data));
}
}
}
export const deleteCalendarTask = (taskId, userId) => {
return async (dispatch) => {
dispatch(deleteTaskRequest());
......@@ -268,6 +293,19 @@ export const deleteDateTimeTask = (dateTimeTaskId) => {
}
}
export const deleteDateTimeTaskUsers = (dateTimeTaskId) => {
return async (dispatch) => {
dispatch(deleteDateTimeTaskRequest());
try {
await axios.delete(`/copy-tasks/${dateTimeTaskId}`);
dispatch(deleteDateTimeTaskSuccess())
dispatch(fetchAllTasksByMembership())
} catch (error) {
dispatch(deleteDateTimeTaskFailure(error.response.data));
}
}
}
/** add new task in UserTasks Table */
......
......@@ -33,7 +33,7 @@ const projectsReducer = (state = initialState, action) => {
return { ...state, loading: false, error: action.error };
case FETCH_ALL_USER_PROJECTS_SUCCESS:
const newArr = action.projects.map((project) => {
return { value: project.id, text: project.title }
return { value: project, text: project.title }
})
return { ...state, loading: false, allUserProjects: action.projects, allUserProjectsForModalTask: newArr }
case CHANGE_MEMBER_ROLE_SUCCESS:
......
import { accomplishStatuses } from "../../constants";
import {
ADD_NEW_TASK_FAILURE,
ADD_NEW_TASK_REQUEST,
......@@ -35,9 +36,9 @@ const initialState = {
};
const tasksReduсer = (state = initialState, action) => {
switch(action.type) {
switch (action.type) {
case FETCH_CALENDAR_TASKS_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
case FETCH_CALENDAR_TASKS_SUCCESS:
const newTasksWithoutInfoForCell = []
const newTasksWithInfoForCell = []
......@@ -56,7 +57,7 @@ const tasksReduсer = (state = initialState, action) => {
})
}
}
newTasksWithoutInfoForCell.forEach((task)=>{
newTasksWithoutInfoForCell.forEach((task) => {
if (task.dateTimeStart && task.dateTimeDue) {
if (new Date(task.dateTimeDue).getTime() - new Date(task.dateTimeStart).getTime() < (24 * 3600000) &&
new Date(task.dateTimeDue).getTime() - new Date(task.dateTimeStart).getTime() > 0) {
......@@ -70,7 +71,8 @@ const tasksReduсer = (state = initialState, action) => {
const timeEndHour = parseInt(timeEnd.split(':')[0])
const timeStartMinute = parseInt(timeStart.split(':')[1])
const timeEndMinute = parseInt(timeEnd.split(':')[1])
const newObj = {...task,
const newObj = {
...task,
infoForCell: {
startDay: dayStart,
startHour: timeStartHour,
......@@ -85,50 +87,63 @@ const tasksReduсer = (state = initialState, action) => {
}
}
})
return {...state, loading: false, calendarTasks: newTasksWithInfoForCell};
return { ...state, loading: false, calendarTasks: newTasksWithInfoForCell };
case FETCH_ALL_TASKS_SUCCESS:
return {...state, loading: false, tasks: action.tasks, projects:action.projects};
return { ...state, loading: false, tasks: action.tasks , projects: action.projects };
case FETCH_ALL_TASKS_BY_MEMBERSHIP_SUCCESS:
return {...state, loading: false, tasks: action.tasks, projects:action.projects};
const newArr = action.tasks.map((task)=>{
return {
...task,
authorName: task.author.displayName,
projectTitle: task.project.title,
executorName: task?.executor?.displayName || null,
accomplishTranslate: accomplishStatuses.find((status) => {
if (status.value === task.accomplish) {
return status
}
return null
}).text
}})
return { ...state, loading: false, tasks: newArr, projects: action.projects };
case FETCH_CALENDAR_TASKS_FAILURE:
return {...state, loading: false, error: action.error};
return { ...state, loading: false, error: action.error };
case ADD_NEW_TASK_SUCCESS:
return {...state, loading: false};
return { ...state, loading: false };
case ADD_NEW_TASK_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
case ADD_NEW_TASK_FAILURE:
return {...state, loading: false, error: action.error};
return { ...state, loading: false, error: action.error };
case FETCH_TASKS_BY_PROJECT_SUCCESS:
return {...state, loading: false, tasks: action.tasks};
return { ...state, loading: false, tasks: action.tasks };
case FETCH_TASKS_BY_PROJECT_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
case FETCH_TASKS_BY_PROJECT_FAILURE:
return {...state, loading: false, error: action.error};
return { ...state, loading: false, error: action.error };
case EDIT_TASK_SUCCESS:
return {...state, loading: false};
return { ...state, loading: false };
case EDIT_TASK_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
case EDIT_TASK_FAILURE:
return {...state, loading: false, error: action.error};
return { ...state, loading: false, error: action.error };
case DELETE_TASK_SUCCESS:
return {...state, loading: false};
return { ...state, loading: false };
case DELETE_TASK_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
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};
return { ...state, loading: false };
case DELETE_DATETIMETASK_REQUEST:
return {...state, loading: true};
return { ...state, loading: true };
case DELETE_DATETIMETASK_FAILURE:
return {...state, loading: false, error: action.error};
return { ...state, loading: false, error: action.error };
case ACTIVATE_CREATE_COPY_TASKS_MODE:
return {...state, copyMode: {working: true, task: action.task}}
return { ...state, copyMode: { working: true, task: action.task } }
case DEACTIVATE_CREATE_COPY_TASKS_MODE:
return {...state, copyMode: {working: false, task: null}}
return { ...state, copyMode: { working: false, task: null } }
default:
return state;
}
}
};
export default tasksReduсer;
\ No newline at end of file
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