commit
6751a655ee
@ -1 +1,4 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"><g><g><image width="16" height="16" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAfUlEQVQ4jeXSMQrCUBCE4S9tII1HsU7hyXIQD+EZPEDwLIJi9Yg2+1QQMftaB/5iB3bYgeWlTaDBA1OQ9vYouCcpsWvB0HDBgJtI+9btl3euAcdGSg3YNXJ9rwDbYO38rFB1CNbOHwH/fEEnrw4XOGGWf6I5dvUY5Z9oRP8AEMJY2tGN6tUAAAAASUVORK5CYII="/></g></g></svg>
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M1411.824 0c31.17 0 56.47 25.3 56.47 56.471v56.47h169.412c93.403 0 169.412 76.01 169.412 169.412V1920H113V282.353c0-93.402 76.009-169.412 169.412-169.412h169.41v-56.47c0-31.172 25.3-56.47 56.472-56.47s56.47 25.298 56.47 56.47v56.47h790.589v-56.47c0-31.172 25.299-56.47 56.47-56.47Zm282.352 564.705H225.942v1242.353h1468.234V564.705Zm-1016.47 677.648v338.824H338.882v-338.824h338.824Zm451.765 0v338.824H790.647v-338.824h338.824Zm451.764 0v338.824h-338.823v-338.824h338.823Zm-1016.47 112.941H451.824v112.941h112.941v-112.941Zm451.764 0H903.588v112.941h112.941v-112.941Zm451.765 0h-112.941v112.941h112.941v-112.941ZM677.706 790.588v338.824H338.882V790.588h338.824Zm451.765 0v338.824H790.647V790.588h338.824Zm451.764 0v338.824h-338.823V790.588h338.823ZM564.765 903.53H451.824v112.941h112.941V903.53Zm451.764 0H903.588v112.941h112.941V903.53Zm451.765 0h-112.941v112.941h112.941V903.53ZM451.823 225.882H282.412c-31.06 0-56.47 25.3-56.47 56.471v169.412h1468.234V282.353c0-31.172-25.411-56.47-56.47-56.47h-169.412v56.47c0 31.172-25.3 56.471-56.47 56.471-31.172 0-56.471-25.299-56.471-56.47v-56.472H564.765v56.471c0 31.172-25.3 56.471-56.471 56.471-31.171 0-56.471-25.299-56.471-56.47v-56.472Z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 457 B After Width: | Height: | Size: 1.4 KiB |
@ -160,12 +160,17 @@
|
|||||||
|
|
||||||
a {
|
a {
|
||||||
color: black;
|
color: black;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
margin: 0 10px 0 0;
|
margin: 0 5px 0 0;
|
||||||
|
|
||||||
@media (max-width: 968px) {
|
@media (max-width: 968px) {
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
|
@ -25,6 +25,7 @@ import file from "assets/icons/fileModal.svg";
|
|||||||
import link from "assets/icons/link.svg";
|
import link from "assets/icons/link.svg";
|
||||||
import send from "assets/icons/send.svg";
|
import send from "assets/icons/send.svg";
|
||||||
import watch from "assets/icons/watch.svg";
|
import watch from "assets/icons/watch.svg";
|
||||||
|
import avatarMok from "assets/images/avatarMok.png";
|
||||||
|
|
||||||
import "./modalTicket.scss";
|
import "./modalTicket.scss";
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ export const ModalTiсket = ({
|
|||||||
task_id: task.id,
|
task_id: task.id,
|
||||||
status: 0,
|
status: 0,
|
||||||
},
|
},
|
||||||
}).then((res) => {
|
}).then(() => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
dispatch(setProjectBoardFetch(projectId));
|
dispatch(setProjectBoardFetch(projectId));
|
||||||
});
|
});
|
||||||
@ -334,9 +335,9 @@ export const ModalTiсket = ({
|
|||||||
);
|
);
|
||||||
}, [members]);
|
}, [members]);
|
||||||
|
|
||||||
function copyProjectLink() {
|
function copyTicketLink() {
|
||||||
navigator.clipboard.writeText(
|
navigator.clipboard.writeText(
|
||||||
`https://itguild.info/tracker/project/${projectId}`
|
`https://itguild.info/tracker/task/${task.id}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +470,12 @@ 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 +506,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 +530,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 +574,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>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
@ -620,7 +647,7 @@ export const ModalTiсket = ({
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img src={link}></img>
|
<img src={link}></img>
|
||||||
<p onClick={copyProjectLink}>ссылка на проект</p>
|
<p onClick={copyTicketLink}>ссылка на задачу</p>
|
||||||
</div>
|
</div>
|
||||||
<div onClick={deleteTask}>
|
<div onClick={deleteTask}>
|
||||||
<img src={archive}></img>
|
<img src={archive}></img>
|
||||||
|
@ -129,6 +129,10 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
.ck-editor {
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
&__subComment {
|
&__subComment {
|
||||||
&:before {
|
&:before {
|
||||||
content: "";
|
content: "";
|
||||||
@ -251,6 +255,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.comment__edit--open {
|
||||||
|
&:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +517,6 @@
|
|||||||
|
|
||||||
&__creator {
|
&__creator {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 32px;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #2d4a17;
|
color: #2d4a17;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||||
|
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
@ -5,7 +7,6 @@ import { Link, useNavigate, useParams } from "react-router-dom";
|
|||||||
import {
|
import {
|
||||||
deletePersonOnProject,
|
deletePersonOnProject,
|
||||||
getBoarderLoader,
|
getBoarderLoader,
|
||||||
getProjectBoard,
|
|
||||||
modalToggle,
|
modalToggle,
|
||||||
setProjectBoardFetch,
|
setProjectBoardFetch,
|
||||||
setToggleTab,
|
setToggleTab,
|
||||||
@ -27,17 +28,17 @@ import TrackerTaskComment from "@components/TrackerTaskComment/TrackerTaskCommen
|
|||||||
import archive from "assets/icons/archive.svg";
|
import archive from "assets/icons/archive.svg";
|
||||||
import archive2 from "assets/icons/archive.svg";
|
import archive2 from "assets/icons/archive.svg";
|
||||||
import arrow from "assets/icons/arrows/arrowCalendar.png";
|
import arrow from "assets/icons/arrows/arrowCalendar.png";
|
||||||
import arrow2 from "assets/icons/arrows/arrowStart.png";
|
import arrowStart from "assets/icons/arrows/arrowStart.png";
|
||||||
import close from "assets/icons/close.png";
|
import close from "assets/icons/close.png";
|
||||||
import del from "assets/icons/delete.svg";
|
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";
|
||||||
import watch from "assets/icons/watch.svg";
|
import watch from "assets/icons/watch.svg";
|
||||||
|
import avatarMok from "assets/images/avatarMok.png";
|
||||||
|
|
||||||
import "./ticketFullScreen.scss";
|
import "./ticketFullScreen.scss";
|
||||||
|
|
||||||
@ -46,8 +47,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({});
|
||||||
@ -56,6 +57,16 @@ export const TicketFullScreen = () => {
|
|||||||
const [personListOpen, setPersonListOpen] = useState(false);
|
const [personListOpen, setPersonListOpen] = useState(false);
|
||||||
const [timerStart, setTimerStart] = useState(false);
|
const [timerStart, setTimerStart] = useState(false);
|
||||||
const [timerInfo, setTimerInfo] = useState({});
|
const [timerInfo, setTimerInfo] = useState({});
|
||||||
|
const [currentTimerCount, setCurrentTimerCount] = useState({
|
||||||
|
hours: 0,
|
||||||
|
minute: 0,
|
||||||
|
seconds: 0,
|
||||||
|
});
|
||||||
|
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) => {
|
||||||
@ -80,13 +91,34 @@ export const TicketFullScreen = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
setComments(comments);
|
setComments(comments);
|
||||||
});
|
});
|
||||||
taskInfo.timers.forEach((time) => {
|
apiRequest(
|
||||||
if (!time.stopped_at) {
|
`/timer/get-by-entity?entity_type=2&entity_id=${taskInfo.id}`
|
||||||
setTimerStart(true);
|
).then((res) => {
|
||||||
setTimerInfo(time);
|
let timerSeconds = 0;
|
||||||
}
|
res.length &&
|
||||||
|
res.forEach((time) => {
|
||||||
|
timerSeconds += time.deltaSeconds;
|
||||||
|
setCurrentTimerCount({
|
||||||
|
hours: Math.floor(timerSeconds / 60 / 60),
|
||||||
|
minute: Math.floor((timerSeconds / 60) % 60),
|
||||||
|
seconds: timerSeconds % 60,
|
||||||
|
});
|
||||||
|
updateTimerHours = Math.floor(timerSeconds / 60 / 60);
|
||||||
|
updateTimerMinute = Math.floor((timerSeconds / 60) % 60);
|
||||||
|
updateTimerSec = timerSeconds % 60;
|
||||||
|
if (!time.stopped_at) {
|
||||||
|
setTimerStart(true);
|
||||||
|
startTimer();
|
||||||
|
setTimerInfo(time);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
apiRequest(
|
||||||
|
`/project/get-project?project_id=${taskInfo.project_id}&expand=columns`
|
||||||
|
).then((res) => {
|
||||||
|
setProjectInfo(res);
|
||||||
|
setCorrectProjectUsers(res.projectUsers);
|
||||||
});
|
});
|
||||||
dispatch(setProjectBoardFetch(taskInfo.project_id));
|
|
||||||
setLoader(boardLoader);
|
setLoader(boardLoader);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
@ -142,6 +174,7 @@ export const TicketFullScreen = () => {
|
|||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
setTimerStart(true);
|
setTimerStart(true);
|
||||||
setTimerInfo(res);
|
setTimerInfo(res);
|
||||||
|
startTimer();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,14 +185,17 @@ export const TicketFullScreen = () => {
|
|||||||
timer_id: timerInfo.id,
|
timer_id: timerInfo.id,
|
||||||
stopped_at: getCorrectRequestDate(new Date()),
|
stopped_at: getCorrectRequestDate(new Date()),
|
||||||
},
|
},
|
||||||
}).then(() => setTimerStart(false));
|
}).then(() => {
|
||||||
|
setTimerStart(false);
|
||||||
|
clearInterval(timerId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function deletePerson(userId) {
|
function deletePerson(userId) {
|
||||||
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(() => {
|
||||||
@ -216,6 +252,119 @@ export const TicketFullScreen = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function startTimer() {
|
||||||
|
setTimerId(
|
||||||
|
setInterval(() => {
|
||||||
|
run();
|
||||||
|
}, 1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
updateTimerMinute = currentTimerCount.minute,
|
||||||
|
updateTimerHours = currentTimerCount.hours;
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
updateTimerSec++;
|
||||||
|
if (updateTimerSec > 60) {
|
||||||
|
updateTimerMinute++;
|
||||||
|
updateTimerSec = 0;
|
||||||
|
}
|
||||||
|
if (updateTimerMinute === 60) {
|
||||||
|
updateTimerMinute = 0;
|
||||||
|
updateTimerHours++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setCurrentTimerCount({
|
||||||
|
hours: updateTimerHours,
|
||||||
|
minute: updateTimerMinute,
|
||||||
|
seconds: updateTimerSec,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function correctTimerTime(time) {
|
||||||
|
if (time < 10) return `0${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 />
|
||||||
@ -265,7 +414,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}
|
||||||
@ -273,9 +422,25 @@ export const TicketFullScreen = () => {
|
|||||||
></TrackerModal>
|
></TrackerModal>
|
||||||
|
|
||||||
<div className="tasks__head__persons">
|
<div className="tasks__head__persons">
|
||||||
<span className="countPersons">
|
{projectInfo.projectUsers?.length > 3 && (
|
||||||
{projectBoard.projectUsers?.length}
|
<span className="countPersons">+1...</span>
|
||||||
</span>
|
)}
|
||||||
|
<div className="projectPersons">
|
||||||
|
{projectInfo.projectUsers?.length &&
|
||||||
|
projectInfo.projectUsers.slice(0, 3).map((person) => {
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
key={person.user_id}
|
||||||
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
|
alt="avatar"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
<span
|
<span
|
||||||
className="addPerson"
|
className="addPerson"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -294,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"
|
||||||
@ -309,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>
|
||||||
@ -365,32 +534,52 @@ export const TicketFullScreen = () => {
|
|||||||
)}
|
)}
|
||||||
<div className="content__description">
|
<div className="content__description">
|
||||||
{editOpen ? (
|
{editOpen ? (
|
||||||
<input
|
<CKEditor
|
||||||
value={inputsValue.description}
|
editor={ClassicEditor}
|
||||||
onChange={(e) => {
|
data={inputsValue.description}
|
||||||
|
config={{
|
||||||
|
removePlugins: [
|
||||||
|
"CKFinderUploadAdapter",
|
||||||
|
"CKFinder",
|
||||||
|
"EasyImage",
|
||||||
|
"Image",
|
||||||
|
"ImageCaption",
|
||||||
|
"ImageStyle",
|
||||||
|
"ImageToolbar",
|
||||||
|
"ImageUpload",
|
||||||
|
"MediaEmbed",
|
||||||
|
"BlockQuote",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
onChange={(event, editor) => {
|
||||||
|
const data = editor.getData();
|
||||||
setInputsValue((prevValue) => ({
|
setInputsValue((prevValue) => ({
|
||||||
...prevValue,
|
...prevValue,
|
||||||
description: e.target.value,
|
description: data,
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<p>{inputsValue.description}</p>
|
<p
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: inputsValue.description,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</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>
|
||||||
@ -430,58 +619,159 @@ export const TicketFullScreen = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="workers">
|
<div className="workers">
|
||||||
<div className="workers_box">
|
<div className="workers_box task__info">
|
||||||
<p className="workers__creator">
|
<p className="workers__creator">
|
||||||
Создатель : <span>{taskInfo.user?.fio}</span>
|
Создатель : <br />
|
||||||
|
{taskInfo.user?.fio}
|
||||||
</p>
|
</p>
|
||||||
<div>
|
|
||||||
{Boolean(taskInfo.taskUsers?.length) &&
|
|
||||||
taskInfo.taskUsers.map((worker, index) => {
|
|
||||||
return (
|
|
||||||
<div className="worker" key={index}>
|
|
||||||
<img src={worker.avatar} alt="worket"></img>
|
|
||||||
<p>{worker.name}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
{taskInfo.executor ? (
|
||||||
|
<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 (
|
||||||
|
<div
|
||||||
|
className="dropdownList__person"
|
||||||
|
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>
|
||||||
|
)}
|
||||||
|
{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>
|
|
||||||
</div>
|
|
||||||
<div className="add-worker moreItems">
|
|
||||||
<BaseButton
|
|
||||||
onClick={() => {
|
|
||||||
dispatch(modalToggle("addWorker"));
|
|
||||||
setModalAddWorker(true);
|
|
||||||
}}
|
|
||||||
styles={"button-add-worker"}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</BaseButton>
|
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<div className="workers_box-middle">
|
<div className="workers_box-middle">
|
||||||
<div className="time">
|
<div className="time">
|
||||||
<img src={watch} alt="watch"></img>
|
<img src={watch}></img>
|
||||||
<span>Длительность : </span>
|
<span>Длительность : </span>
|
||||||
<p>{"0:00:00"}</p>
|
<p>
|
||||||
|
{correctTimerTime(currentTimerCount.hours)}:
|
||||||
|
{correctTimerTime(currentTimerCount.minute)}:
|
||||||
|
{correctTimerTime(currentTimerCount.seconds)}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{timerStart ? (
|
{timerStart ? (
|
||||||
<button className="stop" onClick={() => stopTaskTimer()}>
|
<button
|
||||||
|
className={
|
||||||
|
taskInfo.executor_id ===
|
||||||
|
Number(localStorage.getItem("id"))
|
||||||
|
? "stop"
|
||||||
|
: "stop disable"
|
||||||
|
}
|
||||||
|
onClick={() => stopTaskTimer()}
|
||||||
|
>
|
||||||
Остановить
|
Остановить
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
@ -494,7 +784,8 @@ export const TicketFullScreen = () => {
|
|||||||
}
|
}
|
||||||
onClick={() => startTaskTimer()}
|
onClick={() => startTaskTimer()}
|
||||||
>
|
>
|
||||||
Начать делать <img src={arrow2} alt="arrow"></img>
|
Начать делать
|
||||||
|
<img src={arrowStart}></img>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||||
|
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
@ -25,6 +27,7 @@ import BaseButton from "@components/Common/BaseButton/BaseButton";
|
|||||||
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
|
import ModalLayout from "@components/Common/ModalLayout/ModalLayout";
|
||||||
|
|
||||||
import arrowDown from "assets/icons/arrows/selectArrow.png";
|
import arrowDown from "assets/icons/arrows/selectArrow.png";
|
||||||
|
import avatarMok from "assets/images/avatarMok.png";
|
||||||
|
|
||||||
import "./trackerModal.scss";
|
import "./trackerModal.scss";
|
||||||
|
|
||||||
@ -50,7 +53,7 @@ export const TrackerModal = ({
|
|||||||
const [valueColumn, setValueColumn] = useState("");
|
const [valueColumn, setValueColumn] = useState("");
|
||||||
const [nameProject, setNameProject] = useState("");
|
const [nameProject, setNameProject] = useState("");
|
||||||
const [valueTiket, setValueTiket] = useState("");
|
const [valueTiket, setValueTiket] = useState("");
|
||||||
const [descriptionTicket, setDescriptionTicket] = useState("");
|
const [descriptionTicket, setDescriptionTicket] = useState("Описание задачи");
|
||||||
const [workers, setWorkers] = useState([]);
|
const [workers, setWorkers] = useState([]);
|
||||||
const [selectWorkersOpen, setSelectWorkersOpen] = useState(false);
|
const [selectWorkersOpen, setSelectWorkersOpen] = useState(false);
|
||||||
const [selectedWorker, setSelectedWorker] = useState(null);
|
const [selectedWorker, setSelectedWorker] = useState(null);
|
||||||
@ -114,13 +117,13 @@ export const TrackerModal = ({
|
|||||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||||
setActive(false);
|
setActive(false);
|
||||||
setValueTiket("");
|
setValueTiket("");
|
||||||
setDescriptionTicket("");
|
setDescriptionTicket("Описание задачи");
|
||||||
setSelectedExecutorTask("Выберите исполнителя задачи");
|
setSelectedExecutorTask("Выберите исполнителя задачи");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
setValueTiket("");
|
setValueTiket("");
|
||||||
setDescriptionTicket("");
|
setDescriptionTicket("Описание задачи");
|
||||||
dispatch(setProjectBoardFetch(projectBoard.id));
|
dispatch(setProjectBoardFetch(projectBoard.id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -337,14 +340,27 @@ export const TrackerModal = ({
|
|||||||
placeholder="Название задачи"
|
placeholder="Название задачи"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-container">
|
<CKEditor
|
||||||
<input
|
editor={ClassicEditor}
|
||||||
className="name-project"
|
data={descriptionTicket}
|
||||||
value={descriptionTicket}
|
config={{
|
||||||
onChange={(e) => setDescriptionTicket(e.target.value)}
|
toolbar: [
|
||||||
placeholder="Описание задачи"
|
"heading",
|
||||||
/>
|
"|",
|
||||||
</div>
|
"bold",
|
||||||
|
"italic",
|
||||||
|
"link",
|
||||||
|
"bulletedList",
|
||||||
|
"numberedList",
|
||||||
|
"blockQuote",
|
||||||
|
],
|
||||||
|
removePlugins: ["BlockQuote"],
|
||||||
|
}}
|
||||||
|
onChange={(event, editor) => {
|
||||||
|
const data = editor.getData();
|
||||||
|
setDescriptionTicket(data);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<div
|
<div
|
||||||
onClick={() => setSelectExecutorTaskOpen(!selectExecutorTaskOpen)}
|
onClick={() => setSelectExecutorTaskOpen(!selectExecutorTaskOpen)}
|
||||||
className={
|
className={
|
||||||
@ -381,7 +397,11 @@ export const TrackerModal = ({
|
|||||||
<span>{person.user.fio}</span>
|
<span>{person.user.fio}</span>
|
||||||
<img
|
<img
|
||||||
className="avatar"
|
className="avatar"
|
||||||
src={urlForLocal(person.user.avatar)}
|
src={
|
||||||
|
person.user?.avatar
|
||||||
|
? urlForLocal(person.user.avatar)
|
||||||
|
: avatarMok
|
||||||
|
}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: 0 0 15px 0;
|
margin: 0 0 15px 0;
|
||||||
|
row-gap: 5px;
|
||||||
|
|
||||||
.select-priority {
|
.select-priority {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@ -78,7 +79,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.input-container {
|
.input-container {
|
||||||
width: 287px;
|
width: 320px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -89,8 +90,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ck-editor {
|
||||||
|
max-width: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
.select__executor {
|
.select__executor {
|
||||||
width: 287px;
|
width: 320px;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
|
||||||
|
import { CKEditor } from "@ckeditor/ckeditor5-react";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { urlForLocal } from "@utils/helper";
|
import { urlForLocal } from "@utils/helper";
|
||||||
@ -76,6 +78,7 @@ export const TrackerTaskComment = ({
|
|||||||
? "comments__list__item__main"
|
? "comments__list__item__main"
|
||||||
: "",
|
: "",
|
||||||
"comments__list__item",
|
"comments__list__item",
|
||||||
|
commentsEditOpen ? "comment__edit--open" : "",
|
||||||
comment.parent_id ? "comments__list__item__subComment" : "",
|
comment.parent_id ? "comments__list__item__subComment" : "",
|
||||||
].join(" ")}
|
].join(" ")}
|
||||||
>
|
>
|
||||||
@ -106,17 +109,35 @@ export const TrackerTaskComment = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{commentsEditOpen ? (
|
{commentsEditOpen ? (
|
||||||
<input
|
<CKEditor
|
||||||
className="comments__list__item__text"
|
editor={ClassicEditor}
|
||||||
value={commentsEditText}
|
data={commentsEditText}
|
||||||
onChange={(e) => {
|
config={{
|
||||||
setCommentsEditText(e.target.value);
|
removePlugins: [
|
||||||
|
"CKFinderUploadAdapter",
|
||||||
|
"CKFinder",
|
||||||
|
"EasyImage",
|
||||||
|
"Image",
|
||||||
|
"ImageCaption",
|
||||||
|
"ImageStyle",
|
||||||
|
"ImageToolbar",
|
||||||
|
"ImageUpload",
|
||||||
|
"MediaEmbed",
|
||||||
|
"BlockQuote",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
onChange={(event, editor) => {
|
||||||
|
const data = editor.getData();
|
||||||
|
setCommentsEditText(data);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<p className="comments__list__item__text">{commentsEditText}</p>
|
<p
|
||||||
|
dangerouslySetInnerHTML={{ __html: commentsEditText }}
|
||||||
|
className="comments__list__item__text"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{!comment.parent_id && (
|
{!comment.parent_id && !commentsEditOpen && (
|
||||||
<>
|
<>
|
||||||
{subCommentsCreateOpen ? (
|
{subCommentsCreateOpen ? (
|
||||||
<div className="comments__list__item__answer__new">
|
<div className="comments__list__item__answer__new">
|
||||||
|
@ -322,29 +322,24 @@ export const ProjectTracker = () => {
|
|||||||
<p>добавить колонку</p>
|
<p>добавить колонку</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="tasks__head__persons">
|
<div className="tasks__head__persons">
|
||||||
<span className="countPersons">
|
{projectBoard.projectUsers?.length > 3 && (
|
||||||
{projectBoard.projectUsers?.length}
|
<span className="countPersons">+1...</span>
|
||||||
</span>
|
)}
|
||||||
<div className="projectPersons">
|
<div className="projectPersons">
|
||||||
{projectBoard.projectUsers?.length &&
|
{projectBoard.projectUsers?.length &&
|
||||||
projectBoard.projectUsers
|
projectBoard.projectUsers.slice(0, 3).map((person) => {
|
||||||
.slice(
|
return (
|
||||||
0,
|
<img
|
||||||
projectBoard.length > 3 ? 3 : projectBoard.length
|
key={person.user_id}
|
||||||
)
|
src={
|
||||||
.map((person) => {
|
person.user?.avatar
|
||||||
return (
|
? urlForLocal(person.user.avatar)
|
||||||
<img
|
: avatarMok
|
||||||
key={person.user_id}
|
}
|
||||||
src={
|
alt="avatar"
|
||||||
person.user?.avatar
|
/>
|
||||||
? urlForLocal(person.user.avatar)
|
);
|
||||||
: avatarMok
|
})}
|
||||||
}
|
|
||||||
alt="avatar"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className="addPerson"
|
className="addPerson"
|
||||||
@ -379,7 +374,11 @@ export const ProjectTracker = () => {
|
|||||||
>
|
>
|
||||||
<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>
|
||||||
@ -462,7 +461,13 @@ export const ProjectTracker = () => {
|
|||||||
<span
|
<span
|
||||||
className="add"
|
className="add"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
selectedTabTask(column.id, column.tasks.length)
|
selectedTabTask(
|
||||||
|
column.id,
|
||||||
|
projectBoard?.columns
|
||||||
|
? projectBoard?.columns[0].tasks.at(-1)
|
||||||
|
.priority + 1
|
||||||
|
: 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
+
|
+
|
||||||
|
@ -295,7 +295,7 @@
|
|||||||
color: #252c32;
|
color: #252c32;
|
||||||
border: 1px solid #dde2e4;
|
border: 1px solid #dde2e4;
|
||||||
background: white;
|
background: white;
|
||||||
left: -5px;
|
left: -6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addPerson {
|
.addPerson {
|
||||||
@ -329,9 +329,11 @@
|
|||||||
&__close {
|
&__close {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 20px;
|
right: 25px;
|
||||||
top: 15px;
|
top: 25px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__count {
|
&__count {
|
||||||
@ -356,7 +358,7 @@
|
|||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
color: #263238;
|
color: #263238;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin: 13px 0 32px;
|
margin: 13px 0 10px;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
Loading…
Reference in New Issue
Block a user