diff --git a/src/pages/Questions/ButtonsOptions.tsx b/src/pages/Questions/ButtonsOptions.tsx index 62a776e4..8a467c8a 100644 --- a/src/pages/Questions/ButtonsOptions.tsx +++ b/src/pages/Questions/ButtonsOptions.tsx @@ -11,7 +11,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import { copyQuestion, deleteQuestion, updateOpenBranchingPanel, updateDesireToOpenABranchingModal } from "@root/questions/actions"; +import { copyQuestion, deleteQuestion, updateOpenBranchingPanel, updateDesireToOpenABranchingModal, deleteQuestionWithTimeout } from "@root/questions/actions"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import { CopyIcon } from "../../assets/icons/questionsPage/CopyIcon"; import Branching from "../../assets/icons/questionsPage/branching"; @@ -40,10 +40,10 @@ export default function ButtonsOptions({ const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920)); const quiz = useCurrentQuiz(); - const { openBranchingPanel } = useQuestionsStore.getState() + const { openBranchingPanel } = useQuestionsStore.getState(); const openedModal = () => { - updateOpenedModalSettingsId(question.id) + updateOpenedModalSettingsId(question.id); }; @@ -84,8 +84,8 @@ export default function ButtonsOptions({ title: "Ветвление", value: "branching", myFunc: (question) => { - updateOpenBranchingPanel(true) - updateDesireToOpenABranchingModal(question.content.id) + updateOpenBranchingPanel(true); + updateDesireToOpenABranchingModal(question.content.id); } }, ]; @@ -161,7 +161,7 @@ export default function ButtonsOptions({ { - openedModal() + openedModal(); // SSHC(value); // myFunc(question); }} @@ -269,76 +269,64 @@ export default function ButtonsOptions({ { // TODO - // const removedId = question.id; - // if (question.deleteTimeoutId) { - // clearTimeout(question.deleteTimeoutId); - // } - - // removeQuestion(quizId, totalIndex); - - // const newTimeoutId = window.setTimeout(() => { - // removeQuestionForce(quizId, removedId); - // }, 5000); - - // updateQuestionsList(quizId, totalIndex, { - // ...question, - // deleteTimeoutId: newTimeoutId, - // }); - - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, "") - clearRuleForAll() - questions.forEach(q => { - if (q.type === "result") { - deleteQuestion(q.id); - } - }); - deleteQuestion(question.id); - } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[] - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его - if (targetQuestion.type === "result") { - deleteQuestion(targetQuestion.id); - } else { - if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id) - getChildren(targetQuestion) //и ищем его потомков - } + onClick={() => { + const deleteFn = () => { + if (question.type !== null) { + if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам + updateRootContentId(quiz.id, ""); + clearRuleForAll(); + questions.forEach(q => { + if (q.type === "result") { + deleteQuestion(q.id); } - }) + }); + deleteQuestion(question.id); + } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков + const clearQuestions = [] as string[]; + + //записываем потомков , а их результаты удаляем + const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { + questions.forEach((targetQuestion) => { + if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его + if (targetQuestion.type === "result") { + deleteQuestion(targetQuestion.id); + } else { + if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id); + getChildren(targetQuestion); //и ищем его потомков + } + } + }); + }; + getChildren(question); + //чистим потомков от инфы ветвления + clearQuestions.forEach((id) => { + updateQuestion(id, question => { + question.content.rule.parentId = ""; + question.content.rule.main = []; + question.content.rule.default = ""; + }); + }); + + //чистим rule родителя + const parentQuestion = getQuestionByContentId(question.content.rule.parentId); + const newRule = {}; + newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id); //удаляем условия перехода от родителя к этому вопросу + newRule.parentId = parentQuestion.content.rule.parentId; + newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId; + newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); + + updateQuestion(question.content.rule.parentId, (PQ) => { + PQ.content.rule = newRule; + }); + deleteQuestion(question.id); } - getChildren(question) - //чистим потомков от инфы ветвления - clearQuestions.forEach((id) => { - updateQuestion(id, question => { - question.content.rule.parentId = "" - question.content.rule.main = [] - question.content.rule.default = "" - }) - }) - //чистим rule родителя - const parentQuestion = getQuestionByContentId(question.content.rule.parentId) - const newRule = {} - newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id) //удаляем условия перехода от родителя к этому вопросу - newRule.parentId = parentQuestion.content.rule.parentId - newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId - newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); + deleteQuestion(question.id); - updateQuestion(question.content.rule.parentId, (PQ) => { - PQ.content.rule = newRule - }) - deleteQuestion(question.id) } + }; - deleteQuestion(question.id) - - } + deleteQuestionWithTimeout(question.id, deleteFn); }} data-cy="delete-question" > diff --git a/src/pages/Questions/ButtonsOptionsAndPict.tsx b/src/pages/Questions/ButtonsOptionsAndPict.tsx index 11b109bf..b7657a68 100644 --- a/src/pages/Questions/ButtonsOptionsAndPict.tsx +++ b/src/pages/Questions/ButtonsOptionsAndPict.tsx @@ -10,7 +10,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import { copyQuestion, deleteQuestion, updateQuestion, clearRuleForAll, getQuestionByContentId } from "@root/questions/actions"; +import { copyQuestion, deleteQuestion, updateQuestion, clearRuleForAll, getQuestionByContentId, deleteQuestionWithTimeout } from "@root/questions/actions"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; import { ReallyChangingModal } from "@ui_kit/Modal/ReallyChangingModal/ReallyChangingModal"; import { useEffect, useState } from "react"; @@ -47,7 +47,7 @@ export default function ButtonsOptionsAndPict({ const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); const isIconMobile = useMediaQuery(theme.breakpoints.down(1050)); - const { questions } = useQuestionsStore.getState() + const { questions } = useQuestionsStore.getState(); const quiz = useCurrentQuiz(); useEffect(() => { @@ -191,8 +191,8 @@ export default function ButtonsOptionsAndPict({ onMouseEnter={() => setButtonHover("branching")} onMouseLeave={() => setButtonHover("")} onClick={() => { - updateOpenBranchingPanel(true) - updateDesireToOpenABranchingModal(question.content.id) + updateOpenBranchingPanel(true); + updateDesireToOpenABranchingModal(question.content.id); }} sx={{ height: "30px", @@ -307,76 +307,64 @@ export default function ButtonsOptionsAndPict({ { // TODO - // const removedId = question.id; - // if (question.deleteTimeoutId) { - // clearTimeout(question.deleteTimeoutId); - // } - - // removeQuestion(quizId, totalIndex); - - // const newTimeoutId = window.setTimeout(() => { - // removeQuestionForce(quizId, removedId); - // }, 5000); - - // updateQuestionsList(quizId, totalIndex, { - // ...question, - // deleteTimeoutId: newTimeoutId, - // }); - - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, "") - clearRuleForAll() - questions.forEach(q => { - if (q.type === "result") { - deleteQuestion(q.id); - } - }); - deleteQuestion(question.id); - } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[] - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его - if (targetQuestion.type === "result") { - deleteQuestion(targetQuestion.id); - } else { - if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id) - getChildren(targetQuestion) //и ищем его потомков - } + onClick={() => { + const deleteFn = () => { + if (question.type !== null) { + if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам + updateRootContentId(quiz.id, ""); + clearRuleForAll(); + questions.forEach(q => { + if (q.type === "result") { + deleteQuestion(q.id); } - }) + }); + deleteQuestion(question.id); + } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков + const clearQuestions = [] as string[]; + + //записываем потомков , а их результаты удаляем + const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { + questions.forEach((targetQuestion) => { + if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его + if (targetQuestion.type === "result") { + deleteQuestion(targetQuestion.id); + } else { + if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id); + getChildren(targetQuestion); //и ищем его потомков + } + } + }); + }; + getChildren(question); + //чистим потомков от инфы ветвления + clearQuestions.forEach((id) => { + updateQuestion(id, question => { + question.content.rule.parentId = ""; + question.content.rule.main = []; + question.content.rule.default = ""; + }); + }); + + //чистим rule родителя + const parentQuestion = getQuestionByContentId(question.content.rule.parentId); + const newRule = {}; + newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id); //удаляем условия перехода от родителя к этому вопросу + newRule.parentId = parentQuestion.content.rule.parentId; + newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId; + newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); + + updateQuestion(question.content.rule.parentId, (PQ) => { + PQ.content.rule = newRule; + }); + deleteQuestion(question.id); } - getChildren(question) - //чистим потомков от инфы ветвления - clearQuestions.forEach((id) => { - updateQuestion(id, question => { - question.content.rule.parentId = "" - question.content.rule.main = [] - question.content.rule.default = "" - }) - }) - //чистим rule родителя - const parentQuestion = getQuestionByContentId(question.content.rule.parentId) - const newRule = {} - newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id) //удаляем условия перехода от родителя к этому вопросу - newRule.parentId = parentQuestion.content.rule.parentId - newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId - newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); + deleteQuestion(question.id); - updateQuestion(question.content.rule.parentId, (PQ) => { - PQ.content.rule = newRule - }) - deleteQuestion(question.id) } + }; - deleteQuestion(question.id) - - } + deleteQuestionWithTimeout(question.id, deleteFn); }} data-cy="delete-question" > diff --git a/src/pages/Questions/DraggableList/DraggableListItem.tsx b/src/pages/Questions/DraggableList/DraggableListItem.tsx index 788ba01f..5f0f0347 100644 --- a/src/pages/Questions/DraggableList/DraggableListItem.tsx +++ b/src/pages/Questions/DraggableList/DraggableListItem.tsx @@ -3,8 +3,8 @@ import { Box, ListItem, Typography, useTheme } from "@mui/material"; import { memo, useEffect } from "react"; import { Draggable } from "react-beautiful-dnd"; import QuestionsPageCard from "./QuestionPageCard"; -import { updateEditSomeQuestion } from "@root/questions/actions" -import { useQuestionsStore } from "@root/questions/store" +import { cancelQuestionDeletion, updateEditSomeQuestion } from "@root/questions/actions"; +import { useQuestionsStore } from "@root/questions/store"; type Props = { @@ -15,21 +15,21 @@ type Props = { function DraggableListItem({ question, isDragging, index }: Props) { const theme = useTheme(); - const { editSomeQuestion } = useQuestionsStore() + const { editSomeQuestion } = useQuestionsStore(); useEffect(() => { if (editSomeQuestion !== null) { const setI = setInterval(() => { - let comp = document.getElementById(editSomeQuestion) - if(comp !== null) { - clearInterval(setI) - comp.scrollIntoView({behavior: 'instant'}) - updateEditSomeQuestion() - } - }, 200) + let comp = document.getElementById(editSomeQuestion); + if (comp !== null) { + clearInterval(setI); + comp.scrollIntoView({ behavior: 'instant' }); + updateEditSomeQuestion(); + } + }, 200); } - }, [editSomeQuestion]) + }, [editSomeQuestion]); return ( @@ -60,11 +60,8 @@ function DraggableListItem({ question, isDragging, index }: Props) { Вопрос удалён. { // TODO - // updateQuestionsList(quizId, index, { - // ...questionData, - // deleted: false, - // }); + onClick={() => { + cancelQuestionDeletion(question.id); }} sx={{ cursor: "pointer", diff --git a/src/pages/Questions/DraggableList/QuestionPageCard.tsx b/src/pages/Questions/DraggableList/QuestionPageCard.tsx index ede1de71..65c4fc86 100644 --- a/src/pages/Questions/DraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/DraggableList/QuestionPageCard.tsx @@ -29,7 +29,7 @@ import { useMediaQuery, useTheme, } from "@mui/material"; -import { copyQuestion, createUntypedQuestion, deleteQuestion, clearRuleForAll, toggleExpandQuestion, updateQuestion, updateUntypedQuestion, getQuestionByContentId } from "@root/questions/actions"; +import { copyQuestion, createUntypedQuestion, deleteQuestion, clearRuleForAll, toggleExpandQuestion, updateQuestion, updateUntypedQuestion, getQuestionByContentId, deleteQuestionWithTimeout } from "@root/questions/actions"; import { updateRootContentId } from "@root/quizes/actions"; import { useRef, useState } from "react"; import type { DraggableProvidedDragHandleProps } from "react-beautiful-dnd"; @@ -51,7 +51,7 @@ interface Props { } export default function QuestionsPageCard({ question, draggableProps, isDragging, index }: Props) { - const { questions } = useQuestionsStore() + const { questions } = useQuestionsStore(); const [plusVisible, setPlusVisible] = useState(false); const [open, setOpen] = useState(false); const theme = useTheme(); @@ -241,79 +241,67 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging padding: "0", margin: "0 5px 0 10px", }} - onClick={() => { // TODO - const removedId = question.id; - // if (question.deleteTimeoutId) { - // clearTimeout(question.deleteTimeoutId); - // } - - // removeQuestion(quizId, totalIndex); - - // const newTimeoutId = window.setTimeout(() => { - // removeQuestionForce(quizId, removedId); - // }, 5000); - - // updateQuestionsList(quizId, totalIndex, { - // ...question, - // deleteTimeoutId: newTimeoutId, - // }); -console.log(question.type) - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, "") - clearRuleForAll() - deleteQuestion(question.id); - questions.forEach(q => { - if (q.type === "result") { - deleteQuestion(q.id); - } - }); - } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[] - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его - if (targetQuestion.type === "result") { - deleteQuestion(targetQuestion.id); - } else { - if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id) - getChildren(targetQuestion) //и ищем его потомков - } + onClick={() => { + const deleteFn = () => { + if (question.type !== null) { + if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам + updateRootContentId(quiz.id, ""); + clearRuleForAll(); + deleteQuestion(question.id); + questions.forEach(q => { + if (q.type === "result") { + deleteQuestion(q.id); } - }) + }); + } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков + const clearQuestions = [] as string[]; + + //записываем потомков , а их результаты удаляем + const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { + questions.forEach((targetQuestion) => { + if (targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его + if (targetQuestion.type === "result") { + deleteQuestion(targetQuestion.id); + } else { + if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id); + getChildren(targetQuestion); //и ищем его потомков + } + } + }); + }; + getChildren(question); + //чистим потомков от инфы ветвления + clearQuestions.forEach((id) => { + updateQuestion(id, question => { + question.content.rule.parentId = ""; + question.content.rule.main = []; + question.content.rule.default = ""; + }); + }); + + //чистим rule родителя + const parentQuestion = getQuestionByContentId(question.content.rule.parentId); + const newRule = {}; + newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id); //удаляем условия перехода от родителя к этому вопросу + newRule.parentId = parentQuestion.content.rule.parentId; + newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId; + newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); + + updateQuestion(question.content.rule.parentId, (PQ) => { + PQ.content.rule = newRule; + }); + deleteQuestion(question.id); } - getChildren(question) - //чистим потомков от инфы ветвления - clearQuestions.forEach((id) => { - updateQuestion(id, question => { - question.content.rule.parentId = "" - question.content.rule.main = [] - question.content.rule.default = "" - }) - }) - //чистим rule родителя - const parentQuestion = getQuestionByContentId(question.content.rule.parentId) - const newRule = {} - newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== question.content.id) //удаляем условия перехода от родителя к этому вопросу - newRule.parentId = parentQuestion.content.rule.parentId - newRule.default = parentQuestion.content.rule.parentId === question.content.id ? "" : parentQuestion.content.rule.parentId - newRule.children = [...parentQuestion.content.rule.children].splice(parentQuestion.content.rule.children.indexOf(question.content.id), 1); - updateQuestion(question.content.rule.parentId, (PQ) => { - PQ.content.rule = newRule - }) - deleteQuestion(question.id) + deleteQuestion(question.id); + } else { + console.log("удаляю безтипогово"); + deleteQuestion(question.id); } + }; - - deleteQuestion(question.id) - } else { - console.log("удаляю безтипогово") - deleteQuestion(question.id) - } + deleteQuestionWithTimeout(question.id, deleteFn); }} data-cy="delete-question" > diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts index b29b4b4a..c920d781 100644 --- a/src/stores/questions/actions.ts +++ b/src/stores/questions/actions.ts @@ -140,6 +140,37 @@ export const collapseAllQuestions = () => setProducedState(state => { state.questions.forEach(question => question.expanded = false); }, "collapseAllQuestions"); +const DELETE_TIMEOUT = 5000; + +export const deleteQuestionWithTimeout = (questionId: string, deleteFn: (questionId: string) => void) => setProducedState(state => { + const question = state.questions.find(q => q.id === questionId); + if (!question) return; + if (question.type === null || question.type === "result") { + deleteFn(questionId); + return; + } + + question.deleted = true; + clearTimeout(question.deleteTimeoutId); + question.deleteTimeoutId = window.setTimeout(() => { + deleteFn(questionId); + }, DELETE_TIMEOUT); +}, { + type: "deleteQuestionWithTimeout", + questionId, +}); + +export const cancelQuestionDeletion = (questionId: string) => setProducedState(state => { + const question = state.questions.find(q => q.id === questionId); + if (!question || question.type === null || question.type === "result") return; + + question.deleted = false; + clearTimeout(question.deleteTimeoutId); +}, { + type: "cancelQuestionDeletion", + questionId, +}); + const REQUEST_DEBOUNCE = 200; const requestQueue = new RequestQueue();