при удалении вопросов из списка и или дерева гарантируем, что default будет заполнен оставшимися потомками. очистим main от удаляемого потомка. сломанное дерево очистится

This commit is contained in:
Nastya 2023-12-07 03:03:43 +03:00
parent 7cfb84534f
commit 1eca4195c5
5 changed files with 74 additions and 20 deletions

@ -40,6 +40,7 @@
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-easy-crop": "^5.0.0",
"react-error-boundary": "^4.0.11",
"react-image-crop": "^10.1.5",
"react-image-file-resizer": "^0.4.8",
"react-rnd": "^10.4.1",

@ -6,7 +6,8 @@ import { useCurrentQuiz } from "@root/quizes/hooks";
import { updateRootContentId } from "@root/quizes/actions"
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared"
import { useQuestionsStore } from "@root/questions/store";
import { cleardragQuestionContentId, updateQuestion, updateOpenedModalSettingsId, getQuestionByContentId } from "@root/questions/actions";
import { cleardragQuestionContentId, updateQuestion, updateOpenedModalSettingsId, getQuestionByContentId, clearRuleForAll } from "@root/questions/actions";
import { withErrorBoundary } from "react-error-boundary";
import { storeToNodes } from "./helper";
@ -21,6 +22,7 @@ import type {
} from "cytoscape";
import { QuestionsList } from "../SwitchBranchingPanel/QuestionsList";
import { enqueueSnackbar } from "notistack";
import { Typography } from "@mui/material";
type PopperItem = {
id: () => string;
@ -111,13 +113,13 @@ interface Props {
}
export const CsComponent = ({
function CsComponent ({
modalQuestionParentContentId,
modalQuestionTargetContentId,
setOpenedModalQuestions,
setModalQuestionParentContentId,
setModalQuestionTargetContentId
}: Props) => {
}: Props) {
const quiz = useCurrentQuiz();
const { dragQuestionContentId, questions, desireToOpenABranchingModal } = useQuestionsStore()
@ -131,17 +133,19 @@ export const CsComponent = ({
const gearsContainer = useRef<HTMLDivElement | null>(null);
useLayoutEffect(() => {
const cy = cyRef?.current
const cy = cyRef?.current
if (desireToOpenABranchingModal) {
setTimeout(() => {
cy?.getElementById(desireToOpenABranchingModal)?.data("eroticeyeblink", true)
}, 250)
setTimeout(() => {
cy?.getElementById(desireToOpenABranchingModal)?.data("eroticeyeblink", true)
}, 250)
} else {
cy?.elements().data("eroticeyeblink", false)
}
}, [desireToOpenABranchingModal])
useLayoutEffect(() => {
updateOpenedModalSettingsId()
// updateRootContentId(quiz.id, "")
// clearRuleForAll()
}, [])
useEffect(() => {
if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) {
@ -149,7 +153,6 @@ const cy = cyRef?.current
}
setModalQuestionParentContentId("")
setModalQuestionTargetContentId("")
}, [modalQuestionTargetContentId])
const addNode = ({ parentNodeContentId, targetNodeContentId }: { parentNodeContentId: string, targetNodeContentId?: string }) => {
@ -229,6 +232,7 @@ const cy = cyRef?.current
question.content.rule.main = []
question.content.rule.default = ""
})
clearRuleForAll()
} else {
const parentQuestionContentId = cy?.$('edge[target = "' + targetNodeContentId + '"]')?.toArray()?.[0]?.data()?.source
if (targetNodeContentId && parentQuestionContentId) {
@ -266,11 +270,21 @@ const cy = cyRef?.current
question.content.rule.default = ""
})
updateQuestion(parentQuestionContentId, question => {
//Заменяем id удаляемого вопроса либо на id одного из оставшихся, либо на пустую строку
if (question.content.rule.default === targetQuestionContentId) question.content.rule.default = ""
})
//чистим rule родителя
const parentQuestion = getQuestionByContentId(parentQuestionContentId)
const newRule = {}
newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== targetQuestionContentId) //удаляем условия перехода от родителя к этому вопросу
newRule.parentId = parentQuestion.content.rule.parentId
newRule.default = questions.filter((q) => {
return q.content.rule.parentId === parentQuestionContentId && q.content.id !== targetQuestionContentId
})[0]?.content.id || ""
//Если этот вопрос был дефолтным у родителя - чистим дефолт
//Смотрим можем ли мы заменить id на один из main
console.log(newRule)
updateQuestion(parentQuestionContentId, (PQ) => {
PQ.content.rule = newRule
})
}
@ -686,7 +700,7 @@ const cy = cyRef?.current
}}
// autolock
/>
{/* <button onClick={() => {
<button onClick={() => {
console.log("NODES____________________________")
cyRef.current?.elements().forEach((ele: any) => {
console.log(ele.data())
@ -695,7 +709,23 @@ const cy = cyRef?.current
<button onClick={() => {
console.log("ELEMENTS____________________________")
console.log(questions)
}}>elements</button> */}
}}>elements</button>
</>
);
};
function Clear () {
const quiz = useCurrentQuiz();
updateRootContentId(quiz.id, "")
clearRuleForAll()
return <></>
}
export default withErrorBoundary(CsComponent, {
fallback: <Clear/>,
onError: (error, info) => {
enqueueSnackbar("Дерево порвалось")
console.log(info)
console.log(error)
},
});

@ -1,6 +1,6 @@
import { Box } from "@mui/material";
import { FirstNodeField } from "./FirstNodeField";
import { CsComponent } from "./CsComponent";
import CsComponent from "./CsComponent";
import { useQuestionsStore } from "@root/questions/store"
import { useCurrentQuiz } from "@root/quizes/hooks";
import { useState } from "react";

@ -1,3 +1,4 @@
import { questionApi } from "@api/question";
import { quizApi } from "@api/quiz";
import { devlog } from "@frontend/kitui";
@ -13,6 +14,7 @@ import { RequestQueue } from "../../utils/requestQueue";
import { updateRootContentId } from "@root/quizes/actions"
import { useCurrentQuiz } from "@root/quizes/hooks"
import { QuestionsStore, useQuestionsStore } from "./store";
import { withErrorBoundary } from "react-error-boundary";
export const setQuestions = (questions: RawQuestion[] | null) => setProducedState(state => {
@ -321,8 +323,8 @@ export const deleteQuestion = async (questionId: string, quizId: string) => requ
await questionApi.delete(question.backendId);
if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам
updateRootContentId(quizId, "")
clearRoleForAll()
} else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очищаем его потомков
clearRuleForAll()
} else if (question.content.rule.parentId.length > 0) { //удалить из стора вопрос из дерева и очистить его потомков
const clearQuestions = [] as string[]
const getChildren = (parentQuestion: AnyTypedQuizQuestion) => {
@ -343,8 +345,22 @@ export const deleteQuestion = async (questionId: string, quizId: string) => requ
})
})
}
//чистим 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 = questions.filter((q) => {
return q.content.rule.parentId === question.content.rule.parentId && q.content.id !== question.content.id
})[0]?.content.id || ""
//Если этот вопрос был дефолтным у родителя - чистим дефолт
//Смотрим можем ли мы заменить id на один из main
console.log(newRule)
updateQuestion(question.content.rule.parentId, (PQ) => {
PQ.content.rule = newRule
})
}
removeQuestion(questionId);
} catch (error) {
devlog("Error deleting question", error);
@ -425,7 +441,7 @@ export const updateDragQuestionContentId = (contentId?: string) => {
useQuestionsStore.setState({ dragQuestionContentId: contentId ? contentId : null });
}
export const clearRoleForAll = () => {
export const clearRuleForAll = () => {
const { questions } = useQuestionsStore.getState()
questions.forEach(question => {
if (question.type !== null && (question.content.rule.main.length > 0 || question.content.rule.default.length > 0 || question.content.rule.parentId.length > 0)) {
@ -454,4 +470,4 @@ export const clearDesireToOpenABranchingModal = () => {
}
export const updateEditSomeQuestion = (contentId?: string) => {
useQuestionsStore.setState({ editSomeQuestion: contentId === undefined ? null : contentId })
}
}

@ -8628,6 +8628,13 @@ react-easy-crop@^5.0.0:
normalize-wheel "^1.0.1"
tslib "2.0.1"
react-error-boundary@^4.0.11:
version "4.0.11"
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.11.tgz#36bf44de7746714725a814630282fee83a7c9a1c"
integrity sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==
dependencies:
"@babel/runtime" "^7.12.5"
react-error-overlay@^6.0.11:
version "6.0.11"
resolved "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz"