From fc9d18a380bfe71f766c6f69418ff51c2f003969 Mon Sep 17 00:00:00 2001 From: Mikola Date: Wed, 25 Oct 2023 16:33:08 +0300 Subject: [PATCH] marks --- .../Modal/Tracker/ModalTicket/ModalTicket.jsx | 79 ++++++++++- .../Tracker/ModalTicket/modalTicket.scss | 125 +++++++++++++++++- src/pages/ProjectTracker/ProjectTracker.js | 86 +++++++++++- src/pages/Tracker/tracker.scss | 38 +++++- src/redux/projectsTrackerSlice.js | 4 + 5 files changed, 320 insertions(+), 12 deletions(-) diff --git a/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx b/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx index fc0d2d81..a3ee7408 100644 --- a/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx +++ b/src/components/Modal/Tracker/ModalTicket/ModalTicket.jsx @@ -39,6 +39,7 @@ import file from "assets/icons/fileModal.svg"; import link from "assets/icons/link.svg"; import send from "assets/icons/send.svg"; import watch from "assets/icons/watch.svg"; +import arrowDown from "assets/icons/arrows/selectArrow.png"; import avatarMok from "assets/images/avatarMok.png"; import { getCorrectDate } from "../../../Calendar/calendarHelper"; @@ -54,6 +55,7 @@ export const ModalTiсket = ({ projectName, projectUsers, projectOwnerId, + projectMarks }) => { const dispatch = useDispatch(); const [addSubtask, setAddSubtask] = useState(false); @@ -73,6 +75,7 @@ export const ModalTiсket = ({ const [dropListMembersOpen, setDropListMembersOpen] = useState(false); const [executor, setExecutor] = useState(task.executor); const [members, setMembers] = useState(task.taskUsers); + const [taskTags, setTaskTags] = useState(task.mark) const [users, setUsers] = useState([]); const [timerStart, setTimerStart] = useState(false); const [timerInfo, setTimerInfo] = useState({}); @@ -85,9 +88,11 @@ export const ModalTiсket = ({ const [timerId, setTimerId] = useState(null); const [taskFiles, setTaskFiles] = useState([]); const [correctProjectUsers, setCorrectProjectUsers] = useState(projectUsers); + const [correctProjectTags, setCorrectProjectTags] = useState([]) const [executorId, setExecutorId] = useState(task.executor_id); const profileInfo = useSelector(getProfileInfo); const [acceptModalOpen, setAcceptModalOpen] = useState(false); + const [selectTagsOpen, setSelectTagsOpen] = useState(false) const { showNotification } = useNotification(); function deleteTask() { @@ -347,6 +352,14 @@ export const ModalTiсket = ({ } }, []); + useEffect(() => { + let tagIds = taskTags.map((tag) => tag.id) + setCorrectProjectTags(projectMarks.reduce((acc, cur) => { + if (!tagIds.includes(cur.id)) acc.push(cur) + return acc + }, [])) + }, [taskTags]) + async function handleUpload(event) { const formData = new FormData(); formData.append("uploadFile", event.target.files[0]); @@ -454,6 +467,35 @@ export const ModalTiсket = ({ }); } + function addTagToTask(tagId) { + apiRequest("/mark/attach", { + method: "POST", + data: { + mark_id: tagId, + entity_type: 2, + entity_id: task.id + } + }).then((data) => { + setSelectTagsOpen(false) + setTaskTags((prevValue) => [...prevValue, data.mark]) + dispatch(setProjectBoardFetch(projectId)); + }) + } + + function deleteTagFromTask(tagId) { + apiRequest("/mark/detach", { + method: "DELETE", + data: { + mark_id: tagId, + entity_type: 2, + entity_id: task.id + } + }).then(() => { + setTaskTags((prevValue) => prevValue.filter((tag) => tag.id !== tagId)) + dispatch(setProjectBoardFetch(projectId)); + }) + } + function closeAcceptModal() { setAcceptModalOpen(false); } @@ -478,7 +520,6 @@ export const ModalTiсket = ({ -
{editOpen ? (
+
+
+ {taskTags.map((tag) => { + return
+

+ {tag.slug} +

+ delete deleteTagFromTask(tag.id)} /> +
+ }) + } +
+
setSelectTagsOpen(!selectTagsOpen)}> + Выберите тег + arrow +
+ {selectTagsOpen && +
+ setSelectTagsOpen(false)} className='tags__dropDown__close' src={close} alt="close" /> + {correctProjectTags.map((tag) => { + return
addTagToTask(tag.id)}> +

{tag.slug}

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

Нет тегов

+ } +
+ } +
{ diff --git a/src/components/Modal/Tracker/ModalTicket/modalTicket.scss b/src/components/Modal/Tracker/ModalTicket/modalTicket.scss index 92a9b29d..1fcbc308 100644 --- a/src/components/Modal/Tracker/ModalTicket/modalTicket.scss +++ b/src/components/Modal/Tracker/ModalTicket/modalTicket.scss @@ -971,7 +971,7 @@ } &-bottom { - padding: 20px 110px 35px 56px; + padding: 10px 110px 15px 56px; font-weight: 400; font-size: 14px; line-height: 38px; @@ -991,6 +991,129 @@ } } + .tags { + display: flex; + flex-direction: column; + position: relative; + row-gap: 5px; + padding: 5px; + border-radius: 10px; + border: 1px solid #e0e0e0; + margin-bottom: 10px; + + &__selected { + display: flex; + flex-wrap: wrap; + padding: 0; + width: 100%; + gap: 8px; + max-width: 200px; + + &__item { + display: flex; + padding: 3px 5px 3px 8px; + border-radius: 8px; + align-items: center; + column-gap: 8px; + cursor: default; + + p { + font-weight: 600; + text-decoration: none !important; + font-size: 15px; + margin: 0; + line-height: 15px; + color: white; + } + + .delete { + cursor: pointer; + width: 12px; + height: 12px; + } + } + } + + &__select { + width: 100%; + height: 25px; + border-radius: 8px; + border: 1px solid gray; + padding: 5px 8px; + display: flex; + justify-content: space-between; + + span { + font-size: 14px; + color: black; + } + + img { + transition: all 0.3s ease; + } + + .open { + transform: rotate(180deg); + } + } + + &__dropDown { + position: absolute; + padding: 15px 10px 10px; + background: white; + width: 100%; + border-radius: 8px; + border: 1px solid #e4e4e4; + top: 110%; + display: flex; + flex-direction: column; + row-gap: 4px; + z-index: 10; + + &__close { + width: 8px; + height: 8px; + position: absolute; + right: 8px; + top: 5px; + } + + .tagItem { + 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; + } + } + + &__noItem { + line-height: 20px; + font-size: 15px; + margin: 0; + font-weight: 500; + text-decoration: none !important; + cursor: default; + } + } + } + .edit { background: #52b709; border-radius: 50px; diff --git a/src/pages/ProjectTracker/ProjectTracker.js b/src/pages/ProjectTracker/ProjectTracker.js index 4816d468..2ddebac6 100644 --- a/src/pages/ProjectTracker/ProjectTracker.js +++ b/src/pages/ProjectTracker/ProjectTracker.js @@ -12,6 +12,7 @@ import { filteredParticipateTasks, getBoarderLoader, getProjectBoard, + deleteTagProject, modalToggle, movePositionProjectTask, moveProjectTask, @@ -71,6 +72,7 @@ export const ProjectTracker = () => { const [tags, setTags] = useState({ open: false, add: false, + edit: false }); const [color, setColor] = useState("#aabbcc"); const [tagInfo, setTagInfo] = useState({ description: "", name: "" }); @@ -318,6 +320,37 @@ export const ProjectTracker = () => { }); } + function editTag() { + apiRequest("/mark/update", { + method: "PUT", + data: { + mark_id: tagInfo.editMarkId, + title: tagInfo.description, + slug: tagInfo.name, + color: color + } + }).then(() => { + dispatch(setProjectBoardFetch(projectId.id)) + setTags((prevState) => ({ + ...prevState, + edit: false, + })); + }) + } + + function deleteTag(tagId) { + apiRequest("/mark/detach", { + method: "DELETE", + data: { + mark_id: tagId, + entity_type: 1, + entity_id: projectId.id, + } + }).then(() => { + dispatch(deleteTagProject(tagId)) + }) + } + return (
@@ -586,13 +619,19 @@ export const ProjectTracker = () => { className="close" alt="close" onClick={() => { - setTags((prevState) => ({ - ...prevState, + setTags({ open: false, - })); + add: false, + edit: false + }); + setTagInfo({ + description: '', + name: '' + }) + setColor("#aabbcc") }} /> - {!tags.add && ( + {!tags.add && !tags.edit && (
{projectBoard.mark.map((tag) => { return ( @@ -609,6 +648,21 @@ export const ProjectTracker = () => { style={{ background: tag.color }} />
+
+ edit { + setTags((prevState) => ({ + ...prevState, + edit: true, + })) + setTagInfo({ + description: tag.title, + name: tag.slug, + editMarkId: tag.id + }) + setColor(tag.color) + }} /> + deleteTag(tag.id)} className='delete' src={close} alt='delete' /> +
); })} @@ -626,7 +680,7 @@ export const ProjectTracker = () => {
)} - {tags.add && ( + {(tags.add || tags.edit) && (
{ setTags((prevState) => ({ ...prevState, add: false, + edit: false })); + setTagInfo({ + description: '', + name: '' + }) + setColor("#aabbcc") }} /> { />
)} @@ -695,6 +758,7 @@ export const ProjectTracker = () => { projectName={projectBoard.name} projectUsers={projectBoard.projectUsers} projectOwnerId={projectBoard.owner_id} + projectMarks={projectBoard.mark} /> )} @@ -827,6 +891,14 @@ export const ProjectTracker = () => { /> )}
+ {Boolean(task.mark.length) && +
+ {task.mark.map((tag) => { + return

{tag.slug}

+ }) + } +
+ } {task.dead_line && (

Срок исполнения:

diff --git a/src/pages/Tracker/tracker.scss b/src/pages/Tracker/tracker.scss index 7915c59d..55f344c2 100644 --- a/src/pages/Tracker/tracker.scss +++ b/src/pages/Tracker/tracker.scss @@ -386,7 +386,7 @@ .persons__list { position: absolute; - z-index: 20; + z-index: 8; display: flex; flex-direction: column; background: linear-gradient(180deg, #ffffff 0%, #ebebeb 100%); @@ -784,7 +784,7 @@ &__list { position: absolute; background: #f8f9fa; - z-index: 20; + z-index: 8; border-radius: 8px; padding: 20px 10px 10px; top: 30px; @@ -808,6 +808,7 @@ margin-top: 8px; .tagItem { + position: relative; display: flex; flex-direction: column; padding: 5px; @@ -835,6 +836,23 @@ border-radius: 50px; } } + + &__images { + position: absolute; + right: 5px; + top: 3px; + display: flex; + column-gap: 3px; + + img { + cursor: pointer; + } + + .delete { + width: 14px; + height: 14px; + } + } } } @@ -999,7 +1017,6 @@ &__item { width: 328px; - max-height: 250px; padding: 16px; position: relative; box-shadow: 0px 3px 2px -2px rgba(0, 0, 0, 0.06), @@ -1147,6 +1164,21 @@ height: 25px; } } + + &__tags { + display: flex; + flex-wrap: wrap; + column-gap: 6px; + row-gap: 3px; + margin: 5px 0 10px; + + .tagItem { + padding: 3px 10px; + border-radius: 10px; + color: white; + font-size: 12px; + } + } } .openItems { diff --git a/src/redux/projectsTrackerSlice.js b/src/redux/projectsTrackerSlice.js index 5e984c59..22771f4b 100644 --- a/src/redux/projectsTrackerSlice.js +++ b/src/redux/projectsTrackerSlice.js @@ -42,6 +42,9 @@ export const projectsTrackerSlice = createSlice({ (person) => person.user_id !== action.payload ); }, + deleteTagProject: (state, action) => { + state.projectBoard.mark = state.projectBoard.mark.filter((tag) => tag.id !== action.payload) + }, addPersonToProject: (state, action) => { state.projectBoard.projectUsers.push(action.payload); }, @@ -181,6 +184,7 @@ export const { setColumnId, setColumnPriority, deletePersonOnProject, + deleteTagProject, addPersonToProject, addNewTagToProject, filterCreatedByMe,