tracker-tasks
This commit is contained in:
parent
3131fbe1ef
commit
6f534bb82b
@ -27,6 +27,7 @@ import send from "assets/icons/send.svg";
|
|||||||
import watch from "assets/icons/watch.svg";
|
import watch from "assets/icons/watch.svg";
|
||||||
|
|
||||||
import "./modalTicket.scss";
|
import "./modalTicket.scss";
|
||||||
|
import avatarMok from "assets/images/avatarMok.png";
|
||||||
|
|
||||||
export const ModalTiсket = ({
|
export const ModalTiсket = ({
|
||||||
active,
|
active,
|
||||||
@ -469,7 +470,13 @@ export const ModalTiсket = ({
|
|||||||
{executor ? (
|
{executor ? (
|
||||||
<div className="executor">
|
<div className="executor">
|
||||||
<p>Исполнитель: {executor.fio}</p>
|
<p>Исполнитель: {executor.fio}</p>
|
||||||
<img src={urlForLocal(executor.avatar)} alt="avatar" />
|
<img
|
||||||
|
src={
|
||||||
|
executor?.avatar
|
||||||
|
? urlForLocal(executor.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt="avatar" />
|
||||||
<img
|
<img
|
||||||
src={close}
|
src={close}
|
||||||
className="delete"
|
className="delete"
|
||||||
@ -500,7 +507,14 @@ export const ModalTiсket = ({
|
|||||||
onClick={() => taskExecutor(person)}
|
onClick={() => taskExecutor(person)}
|
||||||
>
|
>
|
||||||
<span>{person.user.fio}</span>
|
<span>{person.user.fio}</span>
|
||||||
<img src={urlForLocal(person.user.avatar)} />
|
<img
|
||||||
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@ -517,7 +531,14 @@ export const ModalTiсket = ({
|
|||||||
return (
|
return (
|
||||||
<div className="worker" key={member.user_id}>
|
<div className="worker" key={member.user_id}>
|
||||||
<p>{member.fio}</p>
|
<p>{member.fio}</p>
|
||||||
<img src={urlForLocal(member.avatar)} />
|
<img
|
||||||
|
src={
|
||||||
|
member?.avatar
|
||||||
|
? urlForLocal(member.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
<img
|
<img
|
||||||
src={close}
|
src={close}
|
||||||
className="delete"
|
className="delete"
|
||||||
@ -554,7 +575,14 @@ export const ModalTiсket = ({
|
|||||||
onClick={() => addMember(person)}
|
onClick={() => addMember(person)}
|
||||||
>
|
>
|
||||||
<span>{person.user.fio}</span>
|
<span>{person.user.fio}</span>
|
||||||
<img src={urlForLocal(person.user.avatar)} />
|
<img
|
||||||
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
|
@ -7,10 +7,8 @@ import { Link, useNavigate, useParams } from "react-router-dom";
|
|||||||
import {
|
import {
|
||||||
deletePersonOnProject,
|
deletePersonOnProject,
|
||||||
getBoarderLoader,
|
getBoarderLoader,
|
||||||
getProjectBoard,
|
modalToggle, setProjectBoardFetch,
|
||||||
modalToggle,
|
setToggleTab
|
||||||
setProjectBoardFetch,
|
|
||||||
setToggleTab,
|
|
||||||
} from "@redux/projectsTrackerSlice";
|
} from "@redux/projectsTrackerSlice";
|
||||||
|
|
||||||
import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
|
import { getCorrectRequestDate, urlForLocal } from "@utils/helper";
|
||||||
@ -35,7 +33,6 @@ import del from "assets/icons/delete.svg";
|
|||||||
import edit from "assets/icons/edit.svg";
|
import edit from "assets/icons/edit.svg";
|
||||||
import file from "assets/icons/fileModal.svg";
|
import file from "assets/icons/fileModal.svg";
|
||||||
import link from "assets/icons/link.svg";
|
import link from "assets/icons/link.svg";
|
||||||
import plus from "assets/icons/plus.svg";
|
|
||||||
import send from "assets/icons/send.svg";
|
import send from "assets/icons/send.svg";
|
||||||
import project from "assets/icons/trackerProject.svg";
|
import project from "assets/icons/trackerProject.svg";
|
||||||
import tasks from "assets/icons/trackerTasks.svg";
|
import tasks from "assets/icons/trackerTasks.svg";
|
||||||
@ -49,8 +46,8 @@ export const TicketFullScreen = () => {
|
|||||||
const ticketId = useParams();
|
const ticketId = useParams();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const projectBoard = useSelector(getProjectBoard);
|
|
||||||
const boardLoader = useSelector(getBoarderLoader);
|
const boardLoader = useSelector(getBoarderLoader);
|
||||||
|
const [projectInfo, setProjectInfo] = useState({})
|
||||||
const [taskInfo, setTaskInfo] = useState({});
|
const [taskInfo, setTaskInfo] = useState({});
|
||||||
const [editOpen, setEditOpen] = useState(false);
|
const [editOpen, setEditOpen] = useState(false);
|
||||||
const [inputsValue, setInputsValue] = useState({});
|
const [inputsValue, setInputsValue] = useState({});
|
||||||
@ -65,6 +62,10 @@ export const TicketFullScreen = () => {
|
|||||||
seconds: 0,
|
seconds: 0,
|
||||||
});
|
});
|
||||||
const [timerId, setTimerId] = useState(null);
|
const [timerId, setTimerId] = useState(null);
|
||||||
|
const [dropListOpen, setDropListOpen] = useState(false);
|
||||||
|
const [correctProjectUsers, setCorrectProjectUsers] = useState([]);
|
||||||
|
const [dropListMembersOpen, setDropListMembersOpen] = useState(false);
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
|
apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => {
|
||||||
@ -111,7 +112,10 @@ export const TicketFullScreen = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
dispatch(setProjectBoardFetch(taskInfo.project_id));
|
apiRequest(`/project/get-project?project_id=${taskInfo.project_id}&expand=columns`).then((res) => {
|
||||||
|
setProjectInfo(res)
|
||||||
|
setCorrectProjectUsers(res.projectUsers)
|
||||||
|
})
|
||||||
setLoader(boardLoader);
|
setLoader(boardLoader);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
@ -188,7 +192,7 @@ export const TicketFullScreen = () => {
|
|||||||
apiRequest("/project/del-user", {
|
apiRequest("/project/del-user", {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
data: {
|
data: {
|
||||||
project_id: projectBoard.id,
|
project_id: projectInfo.id,
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
},
|
},
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
@ -253,6 +257,18 @@ export const TicketFullScreen = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (taskInfo.taskUsers && projectInfo.projectUsers) {
|
||||||
|
let ids = taskInfo.taskUsers.map((user) => user.user_id);
|
||||||
|
setUsers(
|
||||||
|
projectInfo.projectUsers.reduce((acc, cur) => {
|
||||||
|
if (!ids.includes(cur.user_id)) acc.push(cur);
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [taskInfo.taskUsers, projectInfo]);
|
||||||
|
|
||||||
let updateTimerSec = currentTimerCount.seconds,
|
let updateTimerSec = currentTimerCount.seconds,
|
||||||
updateTimerMinute = currentTimerCount.minute,
|
updateTimerMinute = currentTimerCount.minute,
|
||||||
updateTimerHours = currentTimerCount.hours;
|
updateTimerHours = currentTimerCount.hours;
|
||||||
@ -280,6 +296,70 @@ export const TicketFullScreen = () => {
|
|||||||
if (time > 10) return time;
|
if (time > 10) return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deleteTaskExecutor() {
|
||||||
|
apiRequest("/task/update-task", {
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
task_id: taskInfo.id,
|
||||||
|
executor_id: 0,
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
setTaskInfo((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
executor_id: null,
|
||||||
|
executor: null
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function taskExecutor(person) {
|
||||||
|
apiRequest("/task/update-task", {
|
||||||
|
method: "PUT",
|
||||||
|
data: {
|
||||||
|
task_id: taskInfo.id,
|
||||||
|
executor_id: person.user_id,
|
||||||
|
},
|
||||||
|
}).then((res) => {
|
||||||
|
setDropListOpen(false);
|
||||||
|
setTaskInfo((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
executor_id: res.executor_id,
|
||||||
|
executor: res.executor
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteMember(person) {
|
||||||
|
apiRequest("/task/del-user", {
|
||||||
|
method: "DELETE",
|
||||||
|
data: {
|
||||||
|
task_id: taskInfo.id,
|
||||||
|
user_id: person.user_id,
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
setTaskInfo((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
taskUsers: taskInfo.taskUsers.filter((item) => item.user_id !== person.user_id)
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMember(person) {
|
||||||
|
apiRequest("/task/add-user-to-task", {
|
||||||
|
method: "POST",
|
||||||
|
data: {
|
||||||
|
task_id: taskInfo.id,
|
||||||
|
user_id: person.user_id,
|
||||||
|
},
|
||||||
|
}).then((res) => {
|
||||||
|
setDropListMembersOpen(false);
|
||||||
|
setTaskInfo((prevValue) => ({
|
||||||
|
...prevValue,
|
||||||
|
taskUsers: [...prevValue.taskUsers, res]
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="ticket-full-screen">
|
<section className="ticket-full-screen">
|
||||||
<ProfileHeader />
|
<ProfileHeader />
|
||||||
@ -329,7 +409,7 @@ export const TicketFullScreen = () => {
|
|||||||
<div className="tracker__tabs__content content-tabs">
|
<div className="tracker__tabs__content content-tabs">
|
||||||
<div className="tasks__head">
|
<div className="tasks__head">
|
||||||
<div className="tasks__head__wrapper">
|
<div className="tasks__head__wrapper">
|
||||||
<h5>Проект : {projectBoard.name}</h5>
|
<h5>Проект : {projectInfo.name}</h5>
|
||||||
|
|
||||||
<TrackerModal
|
<TrackerModal
|
||||||
active={modalAddWorker}
|
active={modalAddWorker}
|
||||||
@ -337,15 +417,15 @@ export const TicketFullScreen = () => {
|
|||||||
></TrackerModal>
|
></TrackerModal>
|
||||||
|
|
||||||
<div className="tasks__head__persons">
|
<div className="tasks__head__persons">
|
||||||
{projectBoard.projectUsers?.length > 3 && (
|
{projectInfo.projectUsers?.length > 3 && (
|
||||||
<span className="countPersons">+1...</span>
|
<span className="countPersons">+1...</span>
|
||||||
)}
|
)}
|
||||||
<div className="projectPersons">
|
<div className="projectPersons">
|
||||||
{projectBoard.projectUsers?.length &&
|
{projectInfo.projectUsers?.length &&
|
||||||
projectBoard.projectUsers
|
projectInfo.projectUsers
|
||||||
.slice(
|
.slice(
|
||||||
0,
|
0,
|
||||||
projectBoard.length > 3 ? 3 : projectBoard.length
|
3
|
||||||
)
|
)
|
||||||
.map((person) => {
|
.map((person) => {
|
||||||
return (
|
return (
|
||||||
@ -379,14 +459,14 @@ export const TicketFullScreen = () => {
|
|||||||
onClick={() => setPersonListOpen(false)}
|
onClick={() => setPersonListOpen(false)}
|
||||||
/>
|
/>
|
||||||
<div className="persons__list__count">
|
<div className="persons__list__count">
|
||||||
<span>{projectBoard.projectUsers?.length}</span>
|
<span>{projectInfo.projectUsers?.length}</span>
|
||||||
участник
|
участник
|
||||||
</div>
|
</div>
|
||||||
<div className="persons__list__info">
|
<div className="persons__list__info">
|
||||||
В проекте - <span>“{projectBoard.name}”</span>
|
В проекте - <span>“{projectInfo.name}”</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="persons__list__items">
|
<div className="persons__list__items">
|
||||||
{projectBoard.projectUsers?.map((person) => {
|
{projectInfo.projectUsers?.map((person) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="persons__list__item"
|
className="persons__list__item"
|
||||||
@ -394,7 +474,11 @@ export const TicketFullScreen = () => {
|
|||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="avatar"
|
className="avatar"
|
||||||
src={urlForLocal(person.user.avatar)}
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
/>
|
/>
|
||||||
<span>{person.user.fio}</span>
|
<span>{person.user.fio}</span>
|
||||||
@ -484,18 +568,18 @@ export const TicketFullScreen = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="content__communication">
|
<div className="content__communication">
|
||||||
<p className="tasks">
|
{/*<p className="tasks">*/}
|
||||||
<BaseButton
|
{/* <BaseButton*/}
|
||||||
onClick={() => {
|
{/* onClick={() => {*/}
|
||||||
dispatch(modalToggle("addSubtask"));
|
{/* dispatch(modalToggle("addSubtask"));*/}
|
||||||
setModalAddWorker(true);
|
{/* setModalAddWorker(true);*/}
|
||||||
}}
|
{/* }}*/}
|
||||||
styles={"button-green-add"}
|
{/* styles={"button-green-add"}*/}
|
||||||
>
|
{/* >*/}
|
||||||
<img src={plus}></img>
|
{/* <img src={plus}></img>*/}
|
||||||
Добавить под задачу
|
{/* Добавить под задачу*/}
|
||||||
</BaseButton>
|
{/* </BaseButton>*/}
|
||||||
</p>
|
{/*</p>*/}
|
||||||
<p className="file">
|
<p className="file">
|
||||||
<BaseButton styles={"button-add-file"}>
|
<BaseButton styles={"button-add-file"}>
|
||||||
<img src={file}></img>
|
<img src={file}></img>
|
||||||
@ -540,42 +624,129 @@ export const TicketFullScreen = () => {
|
|||||||
Создатель : <br />
|
Создатель : <br />
|
||||||
{taskInfo.user?.fio}
|
{taskInfo.user?.fio}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
|
||||||
{Boolean(taskInfo.taskUsers?.length) &&
|
{taskInfo.executor ? (
|
||||||
taskInfo.taskUsers.map((worker, index) => {
|
<div className="executor">
|
||||||
|
<p>Исполнитель: {taskInfo.executor.fio}</p>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
taskInfo.executor?.avatar
|
||||||
|
? urlForLocal(taskInfo.executor.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt="avatar" />
|
||||||
|
<img
|
||||||
|
src={close}
|
||||||
|
className="delete"
|
||||||
|
onClick={() => deleteTaskExecutor()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="add-worker moreItems ">
|
||||||
|
<button
|
||||||
|
className="button-add-worker"
|
||||||
|
onClick={() => setDropListOpen(true)}
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</button>
|
||||||
|
<span>Добавить исполнителя</span>
|
||||||
|
{dropListOpen && (
|
||||||
|
<div className="dropdownList">
|
||||||
|
<img
|
||||||
|
src={close}
|
||||||
|
className="dropdownList__close"
|
||||||
|
onClick={() => setDropListOpen(false)}
|
||||||
|
/>
|
||||||
|
{correctProjectUsers.map((person) => {
|
||||||
return (
|
return (
|
||||||
<div className="worker" key={index}>
|
<div
|
||||||
<img src={worker.avatar} alt="worket"></img>
|
className="dropdownList__person"
|
||||||
<p>{worker.name}</p>
|
key={person.user_id}
|
||||||
|
onClick={() => taskExecutor(person)}
|
||||||
|
>
|
||||||
|
<span>{person.user.fio}</span>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div className="add-worker moreItems">
|
|
||||||
<BaseButton
|
|
||||||
onClick={() => {
|
|
||||||
dispatch(modalToggle("addWorker"));
|
|
||||||
setModalAddWorker(true);
|
|
||||||
}}
|
|
||||||
styles={"button-add-worker"}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</BaseButton>
|
|
||||||
<span>Добавить исполнителя</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{Boolean(taskInfo.taskUsers.length) && (
|
||||||
|
<div className="members">
|
||||||
|
<p>Участники:</p>
|
||||||
|
<div className="members__list">
|
||||||
|
{taskInfo.taskUsers.map((member) => {
|
||||||
|
return (
|
||||||
|
<div className="worker" key={member.user_id}>
|
||||||
|
<p>{member.fio}</p>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
member?.avatar
|
||||||
|
? urlForLocal(member.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src={close}
|
||||||
|
className="delete"
|
||||||
|
onClick={() => deleteMember(member)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="add-worker moreItems">
|
<div className="add-worker moreItems">
|
||||||
<BaseButton
|
<button
|
||||||
onClick={() => {
|
className="button-add-worker"
|
||||||
dispatch(modalToggle("addWorker"));
|
onClick={() => setDropListMembersOpen(true)}
|
||||||
setModalAddWorker(true);
|
|
||||||
}}
|
|
||||||
styles={"button-add-worker"}
|
|
||||||
>
|
>
|
||||||
+
|
+
|
||||||
</BaseButton>
|
</button>
|
||||||
|
|
||||||
<span>Добавить участников</span>
|
<span>Добавить участников</span>
|
||||||
|
{dropListMembersOpen && (
|
||||||
|
<div className="dropdownList">
|
||||||
|
<img
|
||||||
|
src={close}
|
||||||
|
className="dropdownList__close"
|
||||||
|
onClick={() => setDropListMembersOpen(false)}
|
||||||
|
/>
|
||||||
|
{users.length ? (
|
||||||
|
users.map((person) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="dropdownList__person"
|
||||||
|
key={person.user_id}
|
||||||
|
onClick={() => addMember(person)}
|
||||||
|
>
|
||||||
|
<span>{person.user.fio}</span>
|
||||||
|
<img
|
||||||
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt='avatar'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<p className="noUsers">Нет пользователей</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ export const ProjectTracker = () => {
|
|||||||
projectBoard.projectUsers
|
projectBoard.projectUsers
|
||||||
.slice(
|
.slice(
|
||||||
0,
|
0,
|
||||||
projectBoard.length > 3 ? 3 : projectBoard.length
|
3
|
||||||
)
|
)
|
||||||
.map((person) => {
|
.map((person) => {
|
||||||
return (
|
return (
|
||||||
|
Loading…
Reference in New Issue
Block a user