diff --git a/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx b/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx index 1ad5296f..c962ad91 100644 --- a/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx +++ b/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx @@ -94,6 +94,7 @@ export const ModalTiсket = ({ const [acceptModalOpen, setAcceptModalOpen] = useState(false); const [selectTagsOpen, setSelectTagsOpen] = useState(false); const { showNotification } = useNotification(); + const [commentSendDisable, setCommentSendDisable] = useState(false); function deleteTask() { apiRequest("/task/update-task", { @@ -144,6 +145,8 @@ export const ModalTiсket = ({ } function createComment() { + if (!inputsValue.comment) return; + setCommentSendDisable(true); apiRequest("/comment/create", { method: "POST", data: { @@ -153,6 +156,7 @@ export const ModalTiсket = ({ }, }).then((res) => { let newComment = res; + setCommentSendDisable(false); newComment.created_at = new Date(); newComment.subComments = []; setInputsValue((prevValue) => ({ ...prevValue, comment: "" })); @@ -285,6 +289,7 @@ export const ModalTiсket = ({ } useEffect(() => { + initListeners(); apiRequest( `/comment/get-by-entity?entity_type=2&entity_id=${task.id}` ).then((res) => { @@ -502,15 +507,59 @@ export const ModalTiсket = ({ setAcceptModalOpen(false); } + const initListeners = () => { + document.addEventListener("click", closeByClickingOut); + }; + + const closeByClickingOut = (event) => { + const path = event.path || (event.composedPath && event.composedPath()); + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("button-add-worker") || + div.classList.contains("dropdownList")) + ) + ) { + setDropListOpen(false); + setDropListMembersOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("deadLine") || + div.classList.contains("react-datepicker-popper")) + ) + ) { + setDatePickerOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("tags") || + div.classList.contains("tags__dropDown")) + ) + ) { + setSelectTagsOpen(false); + } + }; + return (
setActive(false)} + onClick={(e) => { + if (e.target.className.includes("modal-tiket")) setActive(false); + }} > -
e.stopPropagation()} - > +

@@ -646,7 +695,11 @@ export const ModalTiсket = ({ })); }} /> - +

{comments.map((comment) => { @@ -880,7 +933,7 @@ export const ModalTiсket = ({ className="tags__select" onClick={() => setSelectTagsOpen(!selectTagsOpen)} > - Выберите тег + Выберете тег { const [selectTagsOpen, setSelectTagsOpen] = useState(false); const [correctProjectTags, setCorrectProjectTags] = useState([]); const { showNotification } = useNotification(); + const [commentSendDisable, setCommentSendDisable] = useState(false); useEffect(() => { + initListeners(); apiRequest(`/task/get-task?task_id=${ticketId.id}&expand=mark`).then( (taskInfo) => { setTaskInfo(taskInfo); @@ -217,6 +219,8 @@ export const TicketFullScreen = () => { } function createComment() { + if (!inputsValue.comment) return; + setCommentSendDisable(true); apiRequest("/comment/create", { method: "POST", data: { @@ -226,6 +230,7 @@ export const TicketFullScreen = () => { }, }).then((res) => { let newComment = res; + setCommentSendDisable(false); newComment.created_at = new Date(); newComment.subComments = []; setInputsValue((prevValue) => ({ ...prevValue, comment: "" })); @@ -525,6 +530,63 @@ export const TicketFullScreen = () => { }); } + const initListeners = () => { + document.addEventListener("click", closeByClickingOut); + }; + + const closeByClickingOut = (event) => { + const path = event.path || (event.composedPath && event.composedPath()); + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("button-add-worker") || + div.classList.contains("dropdownList")) + ) + ) { + setDropListOpen(false); + setDropListMembersOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("deadLine") || + div.classList.contains("react-datepicker-popper")) + ) + ) { + setDatePickerOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("tags") || + div.classList.contains("tags__dropDown")) + ) + ) { + setSelectTagsOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("addPerson") || + div.classList.contains("persons__list")) + ) + ) { + setPersonListOpen(false); + } + }; + return (
@@ -820,7 +882,12 @@ export const TicketFullScreen = () => { })); }} /> - send + send
{comments.map((comment) => { @@ -1059,7 +1126,7 @@ export const TicketFullScreen = () => { className="tags__select" onClick={() => setSelectTagsOpen(!selectTagsOpen)} > - Выберите тег + Выберете тег { const dispatch = useDispatch(); const projectBoard = useSelector(getProjectBoard); @@ -76,6 +78,9 @@ export const TrackerModal = ({ ); const [selectExecutorTaskOpen, setSelectExecutorTaskOpen] = useState(false); const [correctProjectUsers, setCorrectProjectUsers] = useState([]); + const [correctProjectTags, setCorrectProjectTags] = useState([]); + const [taskTags, setTaskTags] = useState([]); + const [selectTagsOpen, setSelectTagsOpen] = useState(false); const [selectColumnPriorityOpen, setSelectColumnPriorityOpen] = useState(false); const { showNotification } = useNotification(); @@ -135,6 +140,18 @@ export const TrackerModal = ({ type: "error", }); } else { + for (let i = 0; i < taskTags.length; i++) { + apiRequest("/mark/attach", { + method: "POST", + data: { + mark_id: taskTags[i].id, + entity_type: 2, + entity_id: res.id, + }, + }).then(() => { + setTaskTags([]); + }); + } if (selectedExecutorTask.user_id) { apiRequest("/task/update-task", { method: "PUT", @@ -306,6 +323,18 @@ export const TrackerModal = ({ } }, [active]); + useEffect(() => { + let tagIds = taskTags.map((tag) => tag.id); + if (projectMarks) { + setCorrectProjectTags( + projectMarks.reduce((acc, cur) => { + if (!tagIds.includes(cur.id)) acc.push(cur); + return acc; + }, []) + ); + } + }, [taskTags, projectMarks]); + return (
- Этап -
- Backlog - arrow +
+

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

+ avatar
+ {/*Этап*/} + {/*
*/} + {/* Backlog*/} + {/* arrow*/} + {/*
*/}
@@ -445,16 +485,73 @@ export const TrackerModal = ({ />
-
-

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

- avatar +
+
+
+ {taskTags.map((tag) => { + return ( +
+

{tag.slug}

+ delete + setTaskTags((prevState) => + prevState.filter( + (prevTag) => prevTag.id !== tag.id + ) + ) + } + /> +
+ ); + })} +
+
setSelectTagsOpen(!selectTagsOpen)} + > + Выберете тег + arrow +
+
+ {selectTagsOpen && ( +
+ setSelectTagsOpen(false)} + /> + {correctProjectTags.map((tag) => { + return ( +
+ setTaskTags((prevState) => [...prevState, tag]) + } + > +

{tag.slug}

+ +
+ ); + })} + {Boolean(!correctProjectTags.length) && ( +

Нет тегов

+ )} +
+ )}
diff --git a/src/components/Modal/Tracker/TrackerModal/trackerModal.scss b/src/components/Modal/Tracker/TrackerModal/trackerModal.scss index 76e26246..2f7bd14e 100644 --- a/src/components/Modal/Tracker/TrackerModal/trackerModal.scss +++ b/src/components/Modal/Tracker/TrackerModal/trackerModal.scss @@ -357,7 +357,6 @@ display: flex; align-items: center; column-gap: 9.5px; - margin-bottom: 30px; p { color: #2D4A17; font-size: 14px; @@ -371,6 +370,127 @@ } } + &__tags { + display: flex; + flex-direction: column; + position: relative; + + .tags { + &__selected { + width: 393px; + font-weight: 300; + line-height: 18px; + font-size: 15px; + margin-bottom: 17.5px; + border-radius: 8px; + display: flex; + flex-direction: column; + row-gap: 8px; + + &__name { + cursor: pointer; + display: flex; + justify-content: space-between; + padding: 5px; + border-radius: 8px; + border: 1px solid #e4e4e4; + + img { + transition: all 0.3s ease; + } + + .arrow--open { + transform: rotate(180deg); + } + } + + &__items { + display: flex; + flex-wrap: wrap; + padding: 0; + width: 100%; + gap: 8px; + max-width: 393px; + + .selectedTag { + display: flex; + padding: 3px 5px 3px 8px; + border-radius: 8px; + align-items: center; + column-gap: 8px; + + p { + font-weight: 600; + font-size: 15px; + margin: 0; + line-height: 15px; + color: white; + } + + .delete { + cursor: pointer; + width: 12px; + height: 12px; + } + } + } + } + + &__dropDown { + display: flex; + flex-direction: column; + width: 100%; + position: absolute; + border-radius: 8px; + border: 1px solid #e4e4e4; + top: 90%; + z-index: 101; + padding: 20px 10px 10px; + background: white; + row-gap: 8px; + + .close { + position: absolute; + cursor: pointer; + width: 20px; + height: 20px; + right: 5px; + top: 0; + } + + .tag__item { + display: flex; + width: 100%; + cursor: pointer; + column-gap: 8px; + padding: 5px; + border: 1px solid #ececec; + border-radius: 8px; + justify-content: space-between; + + p { + font-size: 18px; + font-weight: 500; + margin: 0; + line-height: 20px; + text-decoration: none; + } + + span { + width: 18px; + height: 18px; + border-radius: 50px; + } + } + + .noTags { + text-align: center; + font-size: 18px; + } + } + } + } + .select__executor { background: #F1F1F1; width: 393px; diff --git a/src/pages/ProjectTracker/ProjectTracker.js b/src/pages/ProjectTracker/ProjectTracker.js index 651ff383..25d95d23 100644 --- a/src/pages/ProjectTracker/ProjectTracker.js +++ b/src/pages/ProjectTracker/ProjectTracker.js @@ -90,6 +90,7 @@ export const ProjectTracker = () => { useEffect(() => { dispatch(activeLoader()); dispatch(setProjectBoardFetch(projectId.id)); + initListeners(); }, []); useEffect(() => { @@ -353,6 +354,72 @@ export const ProjectTracker = () => { }); } + const initListeners = () => { + document.addEventListener("click", closeByClickingOut); + }; + + const closeByClickingOut = (event) => { + const path = event.path || (event.composedPath && event.composedPath()); + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("addPerson") || + div.classList.contains("persons__list")) + ) + ) { + setPersonListOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("tasks__head__executor") || + div.classList.contains("tasks__head__executorDropdown")) + ) + ) { + setSelectedExecutorOpen(false); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("tasks__head__tags") || + div.classList.contains("tags__list")) + ) + ) { + setTags({ + open: false, + add: false, + edit: false, + }); + } + + if ( + event && + !path.find( + (div) => + div.classList && + (div.classList.contains("board__head__more") || + div.classList.contains("column__select")) + ) + ) { + setOpenColumnSelect((prevState) => { + const newState = {}; + for (const key in prevState) { + newState[key] = false; + } + return newState; + }); + } + }; + return (
@@ -402,6 +469,7 @@ export const ProjectTracker = () => { selectedTab={selectedTab} priorityTask={priorityTask} projectUsers={projectBoard.projectUsers} + projectMarks={projectBoard.mark} /> {loader && }