From 39379e8bda8fb4f6b785af8e91b3236cbebe7c94 Mon Sep 17 00:00:00 2001 From: Nastya Date: Wed, 27 Dec 2023 10:25:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20?= =?UTF-8?q?=D0=B4=D0=B5=D0=B9=D1=81=D1=82=D0=B2=D0=B8=D0=B9=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D0=B0=20=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D1=85=D0=BE=D0=B4=D0=B5=20=D0=B2=20=D0=A6?= =?UTF-8?q?=D0=A1=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD=D0=B5=D0=BD=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Questions/BranchingMap/CsComponent.tsx | 66 +++++----- .../Questions/BranchingMap/FirstNodeField.tsx | 1 + src/pages/Questions/BranchingMap/index.tsx | 1 + src/pages/Questions/ButtonsOptions.tsx | 61 +-------- src/pages/Questions/ButtonsOptionsAndPict.tsx | 60 +-------- .../DraggableList/DraggableListItem.tsx | 1 - .../DraggableList/QuestionPageCard.tsx | 61 +-------- .../FormDraggableList/QuestionPageCard.tsx | 2 +- .../Questions/QuestionSwitchWindowTool.tsx | 117 ++++-------------- src/pages/Questions/QuestionsPage.tsx | 14 ++- .../Questions/SwitchBranchingPanel/index.tsx | 19 +-- src/pages/startPage/EditPage.tsx | 53 +++++--- src/stores/questions/actions.ts | 40 +++--- src/stores/uiTools/actions.ts | 3 + src/stores/uiTools/store.ts | 2 + src/ui_kit/switchStepPages.tsx | 9 +- src/utils/deleteFunc.ts | 66 ++++++++++ src/utils/deleteTimeoutedQuestions.ts | 25 ++++ 18 files changed, 258 insertions(+), 343 deletions(-) create mode 100644 src/utils/deleteFunc.ts create mode 100644 src/utils/deleteTimeoutedQuestions.ts diff --git a/src/pages/Questions/BranchingMap/CsComponent.tsx b/src/pages/Questions/BranchingMap/CsComponent.tsx index 88e65537..2ab55bf6 100644 --- a/src/pages/Questions/BranchingMap/CsComponent.tsx +++ b/src/pages/Questions/BranchingMap/CsComponent.tsx @@ -56,7 +56,7 @@ function CsComponent({ }: CsComponentProps) { const quiz = useCurrentQuiz(); - const { dragQuestionContentId, desireToOpenABranchingModal, canCreatePublic } = useUiTools() + const { dragQuestionContentId, desireToOpenABranchingModal, canCreatePublic, someWorkBackend } = useUiTools() const trashQuestions = useQuestionsStore().questions const questions = trashQuestions.filter((question) => question.type !== "result" && question.type !== null && !question.deleted) const [startCreate, setStartCreate] = useState(""); @@ -87,13 +87,6 @@ function CsComponent({ gearsContainer, }); - - useEffect(() => { - return () => { - // if (!canCreatePublic) updateModalInfoWhyCantCreate(true) - } - }, []); - useLayoutEffect(() => { const cy = cyRef?.current if (desireToOpenABranchingModal) { @@ -104,11 +97,14 @@ function CsComponent({ cy?.elements().data("eroticeyeblink", false) } }, [desireToOpenABranchingModal]) + //Техническая штучка. Гарантирует не отрисовку модалки по первому входу на страничку. И очистка данных по расскоменчиванию + //Быстро просто дешево и сердито :) useLayoutEffect(() => { updateOpenedModalSettingsId() // updateRootContentId(quiz.id, "") // clearRuleForAll() }, []) + //Отлов mouseup для отрисовки ноды useEffect(() => { if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) { addNode({ parentNodeContentId: modalQuestionParentContentId, targetNodeContentId: modalQuestionTargetContentId }) @@ -188,14 +184,12 @@ function CsComponent({ }) if (!noChild) {//детей больше 1 + console.log("детей ", noChild, " открываем модалку ветвления") //- предупреждаем стор вопросов об открытии модалки ветвления updateOpenedModalSettingsId(targetQuestion.content.id) } - - } - useEffect(() => { if (startCreate) { addNode({ parentNodeContentId: startCreate }); @@ -211,26 +205,40 @@ function CsComponent({ } }, [startRemove]); + //Отработка первичного рендера странички графика + const firstRender = useRef(true) useEffect(() => { - document - .querySelector("#root") - ?.addEventListener("mouseup", cleardragQuestionContentId); - const cy = cyRef.current; - const eles = cy?.add( - storeToNodes( - questions.filter( - (question) => question.type && question.type !== "result" - ) as AnyTypedQuizQuestion[] - ) - ); - cy?.data("changed", true); - // cy.data('changed', true) - const elecs = eles?.layout(layoutOptions).run(); - cy?.on("add", () => cy.data("changed", true)); - cy?.fit(); - //cy?.layout().run() + console.log("____________ПЕРВЧИНЫЙ РЕНДЕР____________") + console.log("______someWorkBackend______", someWorkBackend) + + if (!someWorkBackend && firstRender.current) { + console.log("цс первично отрабатывает") + document + .querySelector("#root") + ?.addEventListener("mouseup", cleardragQuestionContentId); + const cy = cyRef.current; + + console.log("СПИСОК ЭЛЕМЕНТОВ ЦИТОСКЕЙПА В ПЕРВЧИНЫЙ РЕНДЕР") + console.log(cy?.elements()) + + const eles = cy?.add( + storeToNodes( + questions.filter( + (question) => question.type && question.type !== "result" + ) as AnyTypedQuizQuestion[] + ) + ); + cy?.data("changed", true); + // cy.data('changed', true) + const elecs = eles?.layout(layoutOptions).run(); + cy?.on("add", () => cy.data("changed", true)); + cy?.fit(); + //cy?.layout().run() + firstRender.current = false + } return () => { + console.log("разрендер") document .querySelector("#root") ?.removeEventListener("mouseup", cleardragQuestionContentId); @@ -239,7 +247,7 @@ function CsComponent({ crossesContainer.current?.remove(); gearsContainer.current?.remove(); }; - }, []); + }, [someWorkBackend]); return ( diff --git a/src/pages/Questions/BranchingMap/FirstNodeField.tsx b/src/pages/Questions/BranchingMap/FirstNodeField.tsx index ba14fc18..499c2ca6 100644 --- a/src/pages/Questions/BranchingMap/FirstNodeField.tsx +++ b/src/pages/Questions/BranchingMap/FirstNodeField.tsx @@ -17,6 +17,7 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon useLayoutEffect(() => { + console.log("компонент с плюсом") updateOpenedModalSettingsId() updateRootContentId(quiz.id, "") clearRuleForAll() diff --git a/src/pages/Questions/BranchingMap/index.tsx b/src/pages/Questions/BranchingMap/index.tsx index 6e6c137b..e728927e 100644 --- a/src/pages/Questions/BranchingMap/index.tsx +++ b/src/pages/Questions/BranchingMap/index.tsx @@ -8,6 +8,7 @@ import { useUiTools } from "@root/uiTools/store"; export const BranchingMap = () => { const quiz = useCurrentQuiz(); + console.log("рендер странички ветвления") const { dragQuestionContentId } = useUiTools(); const [modalQuestionParentContentId, setModalQuestionParentContentId] = useState(""); diff --git a/src/pages/Questions/ButtonsOptions.tsx b/src/pages/Questions/ButtonsOptions.tsx index 1691676b..aa89665b 100644 --- a/src/pages/Questions/ButtonsOptions.tsx +++ b/src/pages/Questions/ButtonsOptions.tsx @@ -27,6 +27,8 @@ import { updateOpenedModalSettingsId } from "@root/uiTools/actions"; import { updateRootContentId } from "@root/quizes/actions"; import { useUiTools } from "@root/uiTools/store"; import {useState} from "react"; +import { updateSomeWorkBackend } from "@root/uiTools/actions"; +import { DeleteFunction } from "@utils/deleteFunc"; interface Props { switchState: string; @@ -52,61 +54,6 @@ export default function ButtonsOptions({ updateDesireToOpenABranchingModal(question.content.id); }; - const deleteFn = () => { - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, ""); - clearRuleForAll(); - deleteQuestion(question.id); - } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[]; - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if (targetQuestion.type !== null && targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его - if (targetQuestion.type !== "result" && targetQuestion.type !== null) { - 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); - } - - deleteQuestion(question.id); - - const result = questions.find(q => q.type === "result" && q.content.rule.parentId === question.content.id) - if (result) deleteQuestion(result.id); - - } else { - deleteQuestion(question.id); - } - }; - - const buttonSetting: { icon: JSX.Element; title: string; @@ -334,7 +281,7 @@ export default function ButtonsOptions({ if(question.content.rule.parentId.length !== 0) { setOpenDelete(true) } else { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); } }} @@ -376,7 +323,7 @@ export default function ButtonsOptions({ variant="contained" sx={{ minWidth: "150px" }} onClick={() => { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); }} > Подтвердить diff --git a/src/pages/Questions/ButtonsOptionsAndPict.tsx b/src/pages/Questions/ButtonsOptionsAndPict.tsx index 67fe8f5d..0da4a9e0 100644 --- a/src/pages/Questions/ButtonsOptionsAndPict.tsx +++ b/src/pages/Questions/ButtonsOptionsAndPict.tsx @@ -29,6 +29,8 @@ import { enqueueSnackbar } from "notistack"; import { useCurrentQuiz } from "@root/quizes/hooks"; import { updateRootContentId } from "@root/quizes/actions"; import {AnyTypedQuizQuestion} from "@model/questionTypes/shared"; +import { updateSomeWorkBackend } from "@root/uiTools/actions"; +import { DeleteFunction } from "@utils/deleteFunc"; interface Props { @@ -53,60 +55,6 @@ export default function ButtonsOptionsAndPict({ const [openDelete, setOpenDelete] = useState(false); - const deleteFn = () => { - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, ""); - clearRuleForAll(); - 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 !== null && targetQuestion.type !== "result") { - 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); - } - - deleteQuestion(question.id); - - const result = questions.find(q => q.type === "result" && q.content.rule.parentId === question.content.id) - if (result) deleteQuestion(result.id); - - } else { - deleteQuestion(question.id); - } - }; - useEffect(() => { if (question.deleteTimeoutId) { clearTimeout(question.deleteTimeoutId); @@ -370,7 +318,7 @@ export default function ButtonsOptionsAndPict({ if(question.content.rule.parentId.length !== 0) { setOpenDelete(true) } else { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); } }} data-cy="delete-question" @@ -411,7 +359,7 @@ export default function ButtonsOptionsAndPict({ variant="contained" sx={{ minWidth: "150px" }} onClick={() => { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); }} > Подтвердить diff --git a/src/pages/Questions/DraggableList/DraggableListItem.tsx b/src/pages/Questions/DraggableList/DraggableListItem.tsx index 2b08eec4..956b47ba 100644 --- a/src/pages/Questions/DraggableList/DraggableListItem.tsx +++ b/src/pages/Questions/DraggableList/DraggableListItem.tsx @@ -29,7 +29,6 @@ function DraggableListItem({ question, isDragging, index }: Props) { updateEditSomeQuestion(); } }, 200); - } }, [editSomeQuestion]); diff --git a/src/pages/Questions/DraggableList/QuestionPageCard.tsx b/src/pages/Questions/DraggableList/QuestionPageCard.tsx index 7d81a89c..eb5e4830 100644 --- a/src/pages/Questions/DraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/DraggableList/QuestionPageCard.tsx @@ -55,6 +55,8 @@ import TypeQuestions from "../TypeQuestions"; import { QuestionType } from "@model/question/question"; import { useCurrentQuiz } from "@root/quizes/hooks"; import { useQuestionsStore } from "@root/questions/store"; +import { updateSomeWorkBackend } from "@root/uiTools/actions"; +import { DeleteFunction } from "@utils/deleteFunc"; interface Props { question: AnyTypedQuizQuestion | UntypedQuizQuestion; @@ -87,61 +89,6 @@ const maxLengthTextField = 225; }); }, 200); - const deleteFn = () => { - if (question.type !== null) { - if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz.id, ""); - clearRuleForAll(); - deleteQuestion(question.id); - } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[]; - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if (targetQuestion.type !== null && targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его - if (targetQuestion.type !== null && targetQuestion.type !== "result") { - 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); - } - - - deleteQuestion(question.id); - - const result = questions.find(q => q.type === "result" && q.content.rule.parentId === question.content.id) - if (result) deleteQuestion(result.id); - } else { - deleteQuestion(question.id); - } - }; - - const handleInputFocus = () => { setIsTextFieldtActive(true); }; @@ -333,7 +280,7 @@ const maxLengthTextField = 225; if (question.content.rule.parentId.length !== 0) { setOpenDelete(true); } else { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); } }} data-cy="delete-question" @@ -371,7 +318,7 @@ const maxLengthTextField = 225; variant="contained" sx={{ minWidth: "150px" }} onClick={() => { - deleteQuestionWithTimeout(question.id, deleteFn); + deleteQuestionWithTimeout(question.id, () => DeleteFunction(questions, question, quiz)); }} > Подтвердить diff --git a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx index 8c0c9a7e..d5d4663d 100644 --- a/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx +++ b/src/pages/Questions/Form/FormDraggableList/QuestionPageCard.tsx @@ -251,7 +251,7 @@ export default function QuestionsPageCard({ question, questionIndex, draggablePr margin: "0 5px 0 10px", }} onClick={() => { - deleteQuestionWithTimeout(question.id, deleteQuestion(question.id)); + deleteQuestionWithTimeout(question.id, () => deleteQuestion(question.id)); }} > diff --git a/src/pages/Questions/QuestionSwitchWindowTool.tsx b/src/pages/Questions/QuestionSwitchWindowTool.tsx index efbf9c58..10372180 100644 --- a/src/pages/Questions/QuestionSwitchWindowTool.tsx +++ b/src/pages/Questions/QuestionSwitchWindowTool.tsx @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, useLayoutEffect } from "react"; import { Box, useMediaQuery, useTheme } from "@mui/material"; import { DraggableList } from "./DraggableList"; import { SwitchBranchingPanel } from "./SwitchBranchingPanel"; @@ -7,6 +7,7 @@ import { useQuestionsStore } from "@root/questions/store"; import { useUiTools } from "@root/uiTools/store"; import { useQuestions } from "@root/questions/hooks"; import { useCurrentQuiz } from "@root/quizes/hooks"; +import { updateSomeWorkBackend } from "@root/uiTools/actions"; import { copyQuestion, @@ -19,103 +20,29 @@ import { import { updateRootContentId } from "@root/quizes/actions"; import type { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; +import { DeleteFunction } from "@utils/deleteFunc"; +import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions"; -export const QuestionSwitchWindowTool = () => { +interface Props { + openBranchingPage: boolean; + setOpenBranchingPage: (a:boolean) => void; +} + +export const QuestionSwitchWindowTool = ({ + openBranchingPage, + setOpenBranchingPage}:Props) => { const { questions } = useQuestionsStore.getState(); - const { openBranchingPanel } = useUiTools(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(600)); const quiz = useCurrentQuiz(); + console.log("Я компонент в котором отвечала") - const deleteFn = (question: AnyTypedQuizQuestion) => { - if (question.type !== null) { - if (question.content.rule.parentId === "root") { - //удалить из стора root и очистить rule всем вопросам - updateRootContentId(quiz?.id || "", ""); - clearRuleForAll(); - deleteQuestion(question.id); - } else if (question.content.rule.parentId.length > 0) { - //удалить из стора вопрос из дерева и очистить его потомков - const clearQuestions = [] as string[]; - - //записываем потомков , а их результаты удаляем - const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { - questions.forEach((targetQuestion) => { - if ( - targetQuestion.type !== null && - targetQuestion.content.rule.parentId === parentQuestion.content.id - ) { - //если у вопроса совпал родитель с родителем => он потомок, в кучу его - if ( - targetQuestion.type !== "result" && - targetQuestion.type !== null - ) { - 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); - } - - deleteQuestion(question.id); - - const result = questions.find( - (q) => - q.type === "result" && q.content.rule.parentId === question.content.id - ); - if (result) deleteQuestion(result.id); - } else { - deleteQuestion(question.id); + const openBranchingPageHC = () => { + if (!openBranchingPage) { + deleteTimeoutedQuestions(questions, quiz) } - }; - - const deleteTimeoutedQuestions = () => { - const questionsForDeletion = questions.filter( - ({ type, deleted }) => type && type !== "result" && deleted - ) as AnyTypedQuizQuestion[]; - - questionsForDeletion.forEach(deleteFn); - }; - - useEffect(() => { - if (openBranchingPanel) { - deleteTimeoutedQuestions(); - } - }, [openBranchingPanel]); + setOpenBranchingPage(!openBranchingPage) + } return ( { }} > - {openBranchingPanel ? : } + {openBranchingPage ? : } - + ); }; diff --git a/src/pages/Questions/QuestionsPage.tsx b/src/pages/Questions/QuestionsPage.tsx index 61839166..c33752a6 100755 --- a/src/pages/Questions/QuestionsPage.tsx +++ b/src/pages/Questions/QuestionsPage.tsx @@ -13,7 +13,14 @@ import { useQuestionsStore } from "@root/questions/store"; import { updateOpenBranchingPanel, updateEditSomeQuestion } from "@root/uiTools/actions"; import { useUiTools } from "@root/uiTools/store"; -export default function QuestionsPage() { +interface Props { + openBranchingPage: boolean; + setOpenBranchingPage: (a:boolean) => void; +} + +export default function QuestionsPage({ + openBranchingPage, + setOpenBranchingPage}:Props) { const theme = useTheme(); const { openedModalSettingsId, openBranchingPanel } = useUiTools(); const isMobile = useMediaQuery(theme.breakpoints.down(660)); @@ -55,7 +62,10 @@ export default function QuestionsPage() { Свернуть всё - + void; +} -export const SwitchBranchingPanel = () => { +export const SwitchBranchingPanel = ({ + openBranchingPage, + setOpenBranchingPage}:Props) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(660)); const isTablet = useMediaQuery(theme.breakpoints.down(1446)); - const { openBranchingPanel } = useUiTools(); const ref = useRef(); - return !isTablet || openBranchingPanel ? ( + return !isTablet || openBranchingPage ? ( { }} > { - updateOpenBranchingPanel(target.checked); - }} + checked={openBranchingPage} + onChange={setOpenBranchingPage} sx={{ width: 50, height: 30, @@ -92,7 +95,7 @@ export const SwitchBranchingPanel = () => { - {openBranchingPanel && } + {openBranchingPage && } ) : ( <> diff --git a/src/pages/startPage/EditPage.tsx b/src/pages/startPage/EditPage.tsx index 891d3393..09de543c 100755 --- a/src/pages/startPage/EditPage.tsx +++ b/src/pages/startPage/EditPage.tsx @@ -63,13 +63,16 @@ import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; import { ModalInfoWhyCantCreate } from "./ModalInfoWhyCantCreate"; import { ConfirmLeaveModal } from "./ConfirmLeaveModal"; import { checkQuestionHint } from "@utils/checkQuestionHint"; +import { deleteTimeoutedQuestions } from "@utils/deleteTimeoutedQuestions"; +let init:() => void export default function EditPage() { const quiz = useCurrentQuiz(); const { editQuizId } = useQuizStore(); const { questions } = useQuestionsStore(); - console.log(quiz); + console.log('quiz ',quiz); + console.log(questions); useEffect(() => { const getData = async () => { const quizes = await quizApi.getList(); @@ -78,19 +81,21 @@ export default function EditPage() { if (editQuizId) { const questions = await questionApi.getList({ quiz_id: editQuizId }); setQuestions(questions); + //Всегда должен существовать хоть 1 резулт - "line" + // console.log("сейчас будем ворошиться в этих квешенах ", questions); + + if ( + !questions?.find( + (q) => + (q.type === "result" && q.content.includes(':"line"')) || + q.content.includes(":'line'") + ) + ) { + createResult(quiz?.backendId, "line"); + console.log("Я не нашёл линейный резулт и собираюсь создать новый") + } } - //Всегда должен существовать хоть 1 резулт - "line" - console.log(questions); - - if ( - !questions?.find( - (q) => - (q.type === "result" && q.content.includes(':"line"')) || - q.content.includes(":'line'") - ) - ) - createResult(quiz?.backendId, "line"); }; getData(); }, []); @@ -110,6 +115,14 @@ export default function EditPage() { const [nextStep, setNextStep] = useState(0); const quizConfig = quiz?.config; const disableTest = quiz === undefined ? true : quiz.config.type === null; + const [openBranchingPage, setOpenBranchingPage] = useState(false); + + const openBranchingPageHC = () => { + if (!openBranchingPage) { + deleteTimeoutedQuestions(questions, quiz) + } + setOpenBranchingPage(old => !old) + } useEffect(() => { if (editQuizId === null) navigate("/list"); @@ -310,6 +323,8 @@ export default function EditPage() { quizType={quizConfig.type} quizResults={quizConfig.results} quizStartPageType={quizConfig.startpageType} + openBranchingPage={openBranchingPage} + setOpenBranchingPage={setOpenBranchingPage} /> )} @@ -344,8 +359,8 @@ export default function EditPage() { }} > updateOpenBranchingPanel(e.target.checked)} + checked={openBranchingPage} + onChange={openBranchingPageHC} sx={{ width: 50, height: 30, @@ -413,7 +428,7 @@ export default function EditPage() { }} onClick={() => Object.keys(whyCantCreatePublic).length === 0 - ? () => {} + ? () => { } : updateModalInfoWhyCantCreate(true) } > @@ -459,10 +474,10 @@ export default function EditPage() { onClick={ Object.keys(whyCantCreatePublic).length === 0 ? () => - updateQuiz(quiz?.id, (state) => { - state.status = - quiz?.status === "start" ? "stop" : "start"; - }) + updateQuiz(quiz?.id, (state) => { + state.status = + quiz?.status === "start" ? "stop" : "start"; + }) : () => updateModalInfoWhyCantCreate(true) } > diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts index 97e4b7fb..a5dcd65c 100644 --- a/src/stores/questions/actions.ts +++ b/src/stores/questions/actions.ts @@ -177,7 +177,7 @@ const REQUEST_DEBOUNCE = 200; const requestQueue = new RequestQueue(); let requestTimeoutId: ReturnType; -export const updateQuestion = ( +export const updateQuestion = async ( questionId: string, updateFn: (question: T) => void, skipQueue = false, @@ -481,20 +481,22 @@ export const getQuestionByContentId = (questionContentId: string | null) => { export const clearRuleForAll = () => { const { questions } = useQuestionsStore.getState(); - questions.forEach(question => { - if (question.type !== null && + return Promise.allSettled( + questions.map(question => { + if (question.type !== null && (question.content.rule.main.length > 0 - || question.content.rule.default.length > 0 - || question.content.rule.parentId.length > 0) - && question.type !== "result") { - - updateQuestion(question.content.id, question => { - question.content.rule.parentId = ""; - question.content.rule.main = []; - question.content.rule.default = ""; - }); - } - }); + || question.content.rule.default.length > 0 + || question.content.rule.parentId.length > 0) + && question.type !== "result") { + console.log("вызываю очистку рул вопросов") + updateQuestion(question.content.id, question => { + question.content.rule.parentId = ""; + question.content.rule.main = []; + question.content.rule.default = ""; + }); + } + }) + ) }; export const createResult = async ( @@ -506,7 +508,7 @@ export const createResult = async ( } //Мы получили запрос на создание резулта. Анализируем существует ли такой. Если да - просто делаем его активным - const question = useQuestionsStore.getState().questions.find(q=> q.type !== null && q?.content.rule.parentId === parentContentId) + const question = useQuestionsStore.getState().questions.find(q => q.type !== null && q?.content.rule.parentId === parentContentId) console.log("Получил запрос на создание результа родителю ", parentContentId) console.log("Ищу такой же результ в списке ", question) @@ -519,9 +521,9 @@ export const createResult = async ( } else {//не существует, создаём const content = JSON.parse(JSON.stringify(defaultQuestionByType["result"].content)); content.rule.parentId = parentContentId; - + try { - const createdQuestion:RawQuestion = await questionApi.create({ + const createdQuestion: RawQuestion = await questionApi.create({ quiz_id: quizId, type: "result", title: "", @@ -530,7 +532,7 @@ export const createResult = async ( required: true, content: JSON.stringify(content), }); - + setProducedState(state => { state.questions.push(rawQuestionToQuestion(createdQuestion)) }, { @@ -541,6 +543,6 @@ export const createResult = async ( devlog("Error creating question", error); enqueueSnackbar("Не удалось создать вопрос"); } - } + } }); diff --git a/src/stores/uiTools/actions.ts b/src/stores/uiTools/actions.ts index 29b63dc5..7225818e 100644 --- a/src/stores/uiTools/actions.ts +++ b/src/stores/uiTools/actions.ts @@ -39,3 +39,6 @@ export const updateCanCreatePublic = (can: boolean) => useUiTools.setState({ can export const updateModalInfoWhyCantCreate = (can: boolean) => useUiTools.setState({ openModalInfoWhyCantCreate: can }); export const updateDeleteId = (deleteNodeId: string | null = null) => useUiTools.setState({ deleteNodeId }); export const setShowConfirmLeaveModal = (showConfirmLeaveModal: boolean) => useUiTools.setState({ showConfirmLeaveModal }); + + +export const updateSomeWorkBackend = (someWorkBackend: boolean) => useUiTools.setState({ someWorkBackend }); diff --git a/src/stores/uiTools/store.ts b/src/stores/uiTools/store.ts index c7ddc9a5..baa0a444 100644 --- a/src/stores/uiTools/store.ts +++ b/src/stores/uiTools/store.ts @@ -12,6 +12,7 @@ export type UiTools = { openModalInfoWhyCantCreate: boolean; deleteNodeId: string | null; showConfirmLeaveModal: boolean; + someWorkBackend: boolean; }; export type WhyCantCreatePublic = { @@ -31,6 +32,7 @@ const initialState: UiTools = { openModalInfoWhyCantCreate: false, deleteNodeId: null, showConfirmLeaveModal: false, + someWorkBackend: false }; export const useUiTools = create()( diff --git a/src/ui_kit/switchStepPages.tsx b/src/ui_kit/switchStepPages.tsx index b89b755a..9e7a1fae 100755 --- a/src/ui_kit/switchStepPages.tsx +++ b/src/ui_kit/switchStepPages.tsx @@ -16,6 +16,8 @@ interface Props { quizType: QuizType; quizStartPageType: QuizStartpageType; quizResults: QuizResultsType; + openBranchingPage: boolean; + setOpenBranchingPage: (a:boolean) => void; } export default function SwitchStepPages({ @@ -23,6 +25,8 @@ export default function SwitchStepPages({ quizType, quizStartPageType, quizResults, + openBranchingPage, + setOpenBranchingPage }: Props) { switch (activeStep) { case 0: { @@ -30,7 +34,10 @@ export default function SwitchStepPages({ if (!quizStartPageType) return ; return ; } - case 1: return quizType === "form" ? : ; + case 1: return quizType === "form" ? : ; case 2: return ; case 3: return ; case 4: return ; diff --git a/src/utils/deleteFunc.ts b/src/utils/deleteFunc.ts new file mode 100644 index 00000000..5158f2ce --- /dev/null +++ b/src/utils/deleteFunc.ts @@ -0,0 +1,66 @@ +import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"; +import { clearRuleForAll, deleteQuestion, getQuestionByContentId, updateQuestion } from "@root/questions/actions"; +import { updateRootContentId } from "@root/quizes/actions"; + +//Всё здесь нужно сделать последовательно. И пусть весь мир ждёт. + +export const DeleteFunction = async (questions: any, question: any, quiz: any) => { + + + if (question.type !== null) { + if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам + updateRootContentId(quiz.id, ""); + await clearRuleForAll(); + console.log("очистка рулов закончилась") + await deleteQuestion(question.id); + } else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков + const clearQuestions = [] as string[]; + + //записываем потомков , а их результаты удаляем + const getChildren = (parentQuestion: AnyTypedQuizQuestion) => { + questions.forEach((targetQuestion) => { + if (targetQuestion.type !== null && targetQuestion.content.rule.parentId === parentQuestion.content.id) {//если у вопроса совпал родитель с родителем => он потомок, в кучу его + if (targetQuestion.type !== "result" && targetQuestion.type !== null) { + if (!clearQuestions.includes(targetQuestion.content.id)) clearQuestions.push(targetQuestion.content.id); + getChildren(targetQuestion); //и ищем его потомков + } + } + }); + }; + getChildren(question); + //чистим потомков от инфы ветвления + await Promise.allSettled( + clearQuestions.map((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); + + await updateQuestion(question.content.rule.parentId, (PQ) => { + PQ.content.rule = newRule; + }); + await deleteQuestion(question.id); + } + + await deleteQuestion(question.id); + + const result = questions.find(q => q.type === "result" && q.content.rule.parentId === question.content.id) + if (result) await deleteQuestion(result.id); + + } else { + await deleteQuestion(question.id); + } + +} \ No newline at end of file diff --git a/src/utils/deleteTimeoutedQuestions.ts b/src/utils/deleteTimeoutedQuestions.ts new file mode 100644 index 00000000..19c18322 --- /dev/null +++ b/src/utils/deleteTimeoutedQuestions.ts @@ -0,0 +1,25 @@ +import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "@model/questionTypes/shared"; +import { Quiz } from "@model/quiz/quiz"; +import { updateSomeWorkBackend } from "@root/uiTools/actions"; +import { DeleteFunction } from "@utils/deleteFunc"; + +type allQuestionsTypes = AnyTypedQuizQuestion | UntypedQuizQuestion + +export const deleteTimeoutedQuestions = async (questions: allQuestionsTypes[], quiz: Quiz|undefined) => { + console.log("Я отвечаю за удаление неудалёнышей при переключении. Привет, буде знакомы") + const questionsForDeletion = questions.filter( + ({ type, deleted }) => type && type !== "result" && deleted + ) as AnyTypedQuizQuestion[]; + if (questionsForDeletion.length > 0) { + console.log("меняю занятость беком на true") + updateSomeWorkBackend(true) + + + await Promise.allSettled( + questionsForDeletion.map(question => DeleteFunction(questions, question, quiz)) + ) + + console.log("______________меняю на 'можно редактировать дальше'______________") + updateSomeWorkBackend(false) + } +}; \ No newline at end of file