diff --git a/src/components/UI/ModalAdd/ModalAdd.jsx b/src/components/UI/ModalAdd/ModalAdd.jsx index 1f298454..9f1e192f 100644 --- a/src/components/UI/ModalAdd/ModalAdd.jsx +++ b/src/components/UI/ModalAdd/ModalAdd.jsx @@ -162,6 +162,28 @@ export const ModalAdd = ({ active, setActive, selectedTab, defautlInput }) => { setActive(false)}> ); + case "editColumn": + return ( +
e.stopPropagation()} + > +
+

Введите новое название

+
+ setValueTiket(e.target.value)} + > +
+
+ + setActive(false)}> +
+ ); default: return null; } diff --git a/src/components/UI/ModalTicket/ModalTicket.jsx b/src/components/UI/ModalTicket/ModalTicket.jsx index 0b0d618e..04c968d2 100644 --- a/src/components/UI/ModalTicket/ModalTicket.jsx +++ b/src/components/UI/ModalTicket/ModalTicket.jsx @@ -5,8 +5,6 @@ import { apiRequest } from "../../../api/request"; import { useDispatch } from "react-redux"; import { setProjectBoardFetch } from "../../../redux/projectsTrackerSlice"; -import avatarMock1 from "../../../images/avatarMoсk1.png"; -import avatarMock2 from "../../../images/avatarMoсk2.png"; import category from "../../../images/category.png"; import watch from "../../../images/watch.png"; import file from "../../../images/fileModal.svg"; @@ -30,23 +28,6 @@ export const ModalTiсket = ({ projectName, }) => { const dispatch = useDispatch(); - const [tiket] = useState({ - name: "Разработка трекера", - code: "PR - 2245", - creator: "Василий Тарасов", - descriptions: - "На многих страницах сайта отсутствуют или некорректно заполнены метатеги Description. Это может негативно повлиять на представление сайта в результатах поиска. Необходимо исправить все страницы где есть ошибки или отсутствует Title и Description.", - }); - const [workers] = useState([ - { - name: "Дмитрий Рогов", - avatar: avatarMock2, - }, - { - name: "Марина Серова", - avatar: avatarMock1, - }, - ]); const [addSubtask, setAddSubtask] = useState(false); function deleteTask() { @@ -75,7 +56,7 @@ export const ModalTiсket = ({

Проект: {projectName} - +

@@ -86,7 +67,7 @@ export const ModalTiсket = ({

{task.description}

-

{tiket.descriptions}

+

{task.description}

@@ -116,7 +97,7 @@ export const ModalTiсket = ({ {task.title}

Создатель : {task.user?.fio}

- {workers.map((worker, index) => { + {Boolean(task.taskUsers?.length) && task.taskUsers.map((worker, index) => { return (
diff --git a/src/components/UI/ModalTicket/ModalTicket.scss b/src/components/UI/ModalTicket/ModalTicket.scss index f1a7132f..727f8f5b 100644 --- a/src/components/UI/ModalTicket/ModalTicket.scss +++ b/src/components/UI/ModalTicket/ModalTicket.scss @@ -266,6 +266,19 @@ line-height: 32px; font-weight: 500; color: #2d4a17; + display: flex; + max-width: 200px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + + span { + margin-left: 5px; + font-size: 14px; + line-height: 32px; + font-weight: 500; + display: flex; + } } .worker { diff --git a/src/components/UI/TicketFullScreen/TicketFullScreen.jsx b/src/components/UI/TicketFullScreen/TicketFullScreen.jsx index 5ff267f4..68503758 100644 --- a/src/components/UI/TicketFullScreen/TicketFullScreen.jsx +++ b/src/components/UI/TicketFullScreen/TicketFullScreen.jsx @@ -1,17 +1,16 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { ProfileHeader } from "../../ProfileHeader/ProfileHeader"; import { ProfileBreadcrumbs } from "../../ProfileBreadcrumbs/ProfileBreadcrumbs"; import { Footer } from "../../Footer/Footer"; -import { Link } from "react-router-dom"; +import { Link, useParams, useNavigate } from "react-router-dom"; import ModalAdd from "../ModalAdd/ModalAdd"; import { Navigation } from "../../Navigation/Navigation"; import { useDispatch } from "react-redux"; import { setToggleTab } from "../../../redux/projectsTrackerSlice"; +import { apiRequest } from "../../../api/request"; -import avatarMock1 from "../../../images/avatarMoсk1.png"; -import avatarMock2 from "../../../images/avatarMoсk2.png"; import project from "../../../images/trackerProject.svg"; import watch from "../../../images/watch.png"; import file from "../../../images/fileModal.svg"; @@ -35,25 +34,34 @@ export const TicketFullScreen = ({}) => { const [addSubtask, setAddSubtask] = useState(false); const [modalAddWorker, setModalAddWorker] = useState(false); const [valueTiket, setValueTiket] = useState(""); + const ticketId = useParams(); const dispatch = useDispatch(); + const navigate = useNavigate(); + const [projectInfo, setProjectInfo] = useState({}); + const [taskInfo, setTaskInfo] = useState({}); - const [tiket] = useState({ - name: "Разработка трекера", - code: "PR - 2245", - creator: "Василий Тарасов", - descriptions: - "На многих страницах сайта отсутствуют или некорректно заполнены метатеги Description. Это может негативно повлиять на представление сайта в результатах поиска. Необходимо исправить все страницы где есть ошибки или отсутствует Title и Description.", - }); - const [workers] = useState([ - { - name: "Дмитрий Рогов", - avatar: avatarMock2, - }, - { - name: "Марина Серова", - avatar: avatarMock1, - }, - ]); + useEffect(() => { + apiRequest(`/task/get-task?task_id=${ticketId.id}`).then((taskInfo) => { + setTaskInfo(taskInfo); + apiRequest(`/project/get-project?project_id=${taskInfo.project_id}`).then( + (project) => { + setProjectInfo(project); + } + ); + }); + }, []); + + function deleteTask() { + apiRequest("/task/update-task", { + method: "PUT", + data: { + task_id: ticketId.id, + status: 0, + }, + }).then((res) => { + navigate(`/tracker/project/${taskInfo.project_id}`); + }); + } const toggleTabs = (index) => { dispatch(setToggleTab(index)); @@ -104,7 +112,7 @@ export const TicketFullScreen = ({}) => {
-

Проект : Разработка трекера

+

Проект : {projectInfo.name}

@@ -156,11 +164,11 @@ export const TicketFullScreen = ({}) => {
Задача -
{tiket.code}
+
{taskInfo.title}
-

{tiket.descriptions}

+

{taskInfo.description}

-

{tiket.descriptions}

+

{taskInfo.description}

@@ -186,16 +194,19 @@ export const TicketFullScreen = ({}) => {

-

Создатель : {tiket.creator}

+

+ Создатель : {taskInfo.user?.fio} +

- {workers.map((worker, index) => { - return ( -
- -

{worker.name}

-
- ); - })} + {Boolean(taskInfo.taskUsers?.length) && + taskInfo.taskUsers.map((worker, index) => { + return ( +
+ +

{worker.name}

+
+ ); + })}
@@ -229,7 +240,7 @@ export const TicketFullScreen = ({}) => {

в архив

-
+

удалить

diff --git a/src/pages/ProjectTracker/ProjectTracker.jsx b/src/pages/ProjectTracker/ProjectTracker.js similarity index 78% rename from src/pages/ProjectTracker/ProjectTracker.jsx rename to src/pages/ProjectTracker/ProjectTracker.js index ae4c0b19..de272f97 100644 --- a/src/pages/ProjectTracker/ProjectTracker.jsx +++ b/src/pages/ProjectTracker/ProjectTracker.js @@ -1,11 +1,12 @@ import React, { useEffect, useRef, useState } from "react"; -import { Link } from "react-router-dom"; +import { Link, useParams } from "react-router-dom"; import { ProfileHeader } from "../../components/ProfileHeader/ProfileHeader"; -import { Navigation } from "../../components/Navigation/Navigation"; import { ProfileBreadcrumbs } from "../../components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { Footer } from "../../components/Footer/Footer"; +import { Navigation } from "../../components/Navigation/Navigation"; import { useDispatch, useSelector } from "react-redux"; +import { apiRequest } from "../../api/request"; import { getProjectBoard, modalToggle, @@ -25,32 +26,39 @@ import selectArrow from "../../images/select.svg"; import commentsBoard from "../../images/commentsBoard.svg"; import filesBoard from "../../images/filesBoard.svg"; import arrow from "../../images/arrowCalendar.png"; +import del from "../../images/delete.svg"; +import edit from "../../images/edit.svg"; export const ProjectTracker = () => { const dispatch = useDispatch(); - const currentUrl = useState(window.location.pathname); - const projectId = currentUrl[0].split("/").at(-1); - - useEffect(() => { - dispatch(setProjectBoardFetch(projectId)); - }, []); + const projectId = useParams(); + const [openColumnSelect, setOpenColumnSelect] = useState({}); + const [selectedTab, setSelectedTab] = useState(0); + const [wrapperHover, setWrapperHover] = useState({}); const [modalAdd, setModalAdd] = useState(false); const [modalActiveTicket, setModalActiveTicket] = useState(false); const [selectedTicket, setSelectedTicket] = useState({}); - const [selectedTab, setSelectedTab] = useState(0); - const startWrapperIndexTest = useRef({}); - const [wrapperHover, setWrapperHover] = useState([ - false, - false, - false, - false, - ]); - const projectBoard = useSelector(getProjectBoard); + useEffect(() => { + dispatch(setProjectBoardFetch(projectId.id)); + }, []); + + useEffect(() => { + if (Object.keys(projectBoard).length) { + projectBoard.columns.forEach((column) => { + setOpenColumnSelect((prevState) => ({ + ...prevState, + [column.id]: false, + })); + setWrapperHover((prevState) => ({ ...prevState, [column.id]: false })); + }); + } + }, [projectBoard]); + // function toggleMoreTasks(columnId) { // setTabTaskMok((prevArray) => // prevArray.map((elem, index) => { @@ -71,11 +79,9 @@ export const ProjectTracker = () => { } function dragEndHandler(e) { - setWrapperHover((prevArray) => - prevArray.map((elem) => { - return false; - }) - ); + setWrapperHover((prevState) => ({ + [prevState]: false, + })); e.target.classList.remove("tasks__board__item__hide"); } @@ -87,26 +93,21 @@ export const ProjectTracker = () => { if (columnId === startWrapperIndexTest.current.index) { return; } - setWrapperHover((prevArray) => - prevArray.map((elem, index) => { - if (index === columnId) { - return true; - } else { - return false; - } - }) - ); + + setWrapperHover((prevState) => ({ + [prevState]: false, + [columnId]: true, + })); } function dragDropHandler(e, columnId) { e.preventDefault(); if (startWrapperIndexTest.current.index === columnId) { return; } - setWrapperHover((prevArray) => - prevArray.map((elem) => { - return false; - }) - ); + + setWrapperHover((prevState) => ({ + [prevState]: false, + })); if (columnId !== startWrapperIndexTest.current.index) { dispatch( @@ -129,6 +130,19 @@ export const ProjectTracker = () => { setModalActiveTicket(true); } + function deleteColumn(id) { + apiRequest("/project-column/update-column", { + method: "PUT", + data: { + column_id: id, + project_id: projectBoard.id, + status: 0, + }, + }).then((res) => { + dispatch(setProjectBoardFetch(projectBoard.id)); + }); + } + return (
@@ -258,9 +272,44 @@ export const ProjectTracker = () => { > + - ... + { + setOpenColumnSelect((prevState) => ({ + ...prevState, + [column.id]: true, + })); + }} + className="more" + > + ... +
+ {openColumnSelect[column.id] && ( +
+
{ + setOpenColumnSelect((prevState) => ({ + ...prevState, + [column.id]: false, + })); + dispatch(modalToggle("editColumn")); + setModalAdd(true); + }} + > + edit + Изменить +
+
deleteColumn(column.id)} + > + delete + Удалить +
+
+ )} {column.tasks.map((task, index) => { if (index > 2) { if (!column.open) { diff --git a/src/pages/Tracker/tracker.scss b/src/pages/Tracker/tracker.scss index 344fe765..834712a9 100644 --- a/src/pages/Tracker/tracker.scss +++ b/src/pages/Tracker/tracker.scss @@ -501,6 +501,31 @@ &__more { padding-bottom: 50px; } + + .column__select { + position: absolute; + padding: 15px; + background: #e1fccf; + border-radius: 12px; + right: -75px; + z-index: 10; + row-gap: 10px; + display: flex; + flex-direction: column; + + &__item { + cursor: pointer; + display: flex; + align-content: center; + img { + margin-right: 5px; + } + + span { + font-size: 14px; + } + } + } } .board {