при удалении корня все использованные вопросы сбрасывают rule
This commit is contained in:
commit
c3d1353a9b
93
package-lock.json
generated
93
package-lock.json
generated
@ -40,6 +40,7 @@
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-cytoscapejs": "^2.0.0",
|
||||
"react-datepicker": "^4.24.0",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^18.2.0",
|
||||
@ -61,7 +62,8 @@
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
"@types/cytoscape-popper": "^2.0.4",
|
||||
"@types/react-beautiful-dnd": "^13.1.4",
|
||||
"@types/react-cytoscapejs": "^1.2.5",
|
||||
"@types/react-cytoscapejs": "^1.2.4",
|
||||
"@types/react-datepicker": "^4.19.3",
|
||||
"craco-alias": "^3.0.1",
|
||||
"cypress": "^13.4.0"
|
||||
}
|
||||
@ -4524,6 +4526,18 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-datepicker": {
|
||||
"version": "4.19.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-datepicker/-/react-datepicker-4.19.3.tgz",
|
||||
"integrity": "sha512-85F9eKWu9fGiD9r4KVVMPYAdkJJswR3Wci9PvqplmB6T+D+VbUqPeKtifg96NZ4nEhufjehW+SX4JLrEWVplWw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"@types/react": "*",
|
||||
"date-fns": "^2.0.1",
|
||||
"react-popper": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dnd": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dnd/-/react-dnd-3.0.2.tgz",
|
||||
@ -6374,6 +6388,11 @@
|
||||
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/classnames": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
|
||||
"integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
|
||||
},
|
||||
"node_modules/clean-css": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz",
|
||||
@ -7438,6 +7457,21 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.10",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
|
||||
@ -15126,6 +15160,23 @@
|
||||
"react": ">=15.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.24.0.tgz",
|
||||
"integrity": "sha512-2QUC2pP+x4v3Jp06gnFllxKsJR0yoT/K6y86ItxEsveTXUpsx+NBkChWXjU0JsGx/PL8EQnsxN0wHl4zdA1m/g==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.30.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-onclickoutside": "^6.13.0",
|
||||
"react-popper": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17 || ^18",
|
||||
"react-dom": "^16.9.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dev-utils": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
|
||||
@ -15308,6 +15359,38 @@
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-onclickoutside": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz",
|
||||
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.5.x || ^16.x || ^17.x || ^18.x",
|
||||
"react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
|
||||
}
|
||||
},
|
||||
"node_modules/react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"dependencies": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.0.0",
|
||||
"react": "^16.8.0 || ^17 || ^18",
|
||||
"react-dom": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-popper/node_modules/react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.9",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz",
|
||||
@ -18037,6 +18120,14 @@
|
||||
"makeerror": "1.0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
|
@ -30,7 +30,6 @@ async function getQuestionList(body?: Partial<GetQuestionListRequest>) {
|
||||
}
|
||||
|
||||
function editQuestion(body: EditQuestionRequest, signal?: AbortSignal) {
|
||||
console.log("`${baseUrl}/question/edit` start")
|
||||
return makeRequest<EditQuestionRequest, EditQuestionResponse>({
|
||||
url: `${baseUrl}/question/edit`,
|
||||
body,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { MessageIcon } from "@icons/messagIcon";
|
||||
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
import TextareaAutosize from "@mui/base/TextareaAutosize";
|
||||
import {TextareaAutosize} from "@mui/base/TextareaAutosize";
|
||||
import {
|
||||
Box,
|
||||
FormControl,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
import Cytoscape from "cytoscape";
|
||||
import CytoscapeComponent from "react-cytoscapejs";
|
||||
import popper from "cytoscape-popper";
|
||||
@ -122,16 +122,21 @@ export const CsComponent = ({
|
||||
const crossesContainer = useRef<HTMLDivElement | null>(null);
|
||||
const gearsContainer = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
updateOpenedModalSettingsId()
|
||||
}, [])
|
||||
useEffect(() => {
|
||||
console.log("modalQuestionTargetContentId " + modalQuestionTargetContentId)
|
||||
if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) {
|
||||
console.log("был выбран вопрос " + modalQuestionTargetContentId)
|
||||
addNode({ parentNodeContentId:modalQuestionParentContentId, targetNodeContentId:modalQuestionTargetContentId })
|
||||
addNode({ parentNodeContentId: modalQuestionParentContentId, targetNodeContentId: modalQuestionTargetContentId })
|
||||
}
|
||||
setModalQuestionParentContentId("")
|
||||
setModalQuestionTargetContentId("")
|
||||
console.log("modalQuestionTargetContentId " + modalQuestionTargetContentId)
|
||||
|
||||
}, [modalQuestionTargetContentId])
|
||||
|
||||
const addNode = ({ parentNodeContentId, targetNodeContentId }: { parentNodeContentId: string, targetNodeContentId?: string }) => {
|
||||
console.log("dragQuestionContentId " + dragQuestionContentId)
|
||||
const cy = cyRef?.current
|
||||
const parentNodeChildren = cy?.$('edge[source = "' + parentNodeContentId + '"]')?.length
|
||||
//если есть инфо о выбранном вопросе из модалки - берём родителя из инфо модалки. Иначе из значения дропа
|
||||
@ -139,7 +144,7 @@ export const CsComponent = ({
|
||||
|
||||
if (Object.keys(targetQuestion).length !== 0 && Object.keys(targetQuestion).length !== 0 && parentNodeContentId && parentNodeChildren !== undefined) {
|
||||
clearDataAfterAddNode({ parentNodeContentId, targetQuestion, parentNodeChildren })
|
||||
cy?.data('changed',true)
|
||||
cy?.data('changed', true)
|
||||
cy?.add([
|
||||
{
|
||||
data: {
|
||||
@ -161,8 +166,6 @@ export const CsComponent = ({
|
||||
}
|
||||
|
||||
const clearDataAfterAddNode = ({ parentNodeContentId, targetQuestion, parentNodeChildren }: { parentNodeContentId: string, targetQuestion: AnyQuizQuestion, parentNodeChildren: number }) => {
|
||||
console.log("записываю на бек ид родителя")
|
||||
console.log({ parentNodeContentId, targetQuestion, parentNodeChildren })
|
||||
//предупреждаем добавленный вопрос о том, кто его родитель
|
||||
updateQuestion(targetQuestion.content.id, question => {
|
||||
question.content.rule.parentId = parentNodeContentId
|
||||
@ -170,8 +173,8 @@ export const CsComponent = ({
|
||||
})
|
||||
|
||||
//Если детей больше 1 - предупреждаем стор вопросов об открытии модалки ветвления
|
||||
if (parentNodeChildren > 1) {
|
||||
updateOpenedModalSettingsId(parentNodeContentId)
|
||||
if (parentNodeChildren >= 1) {
|
||||
updateOpenedModalSettingsId(targetQuestion.content.id)
|
||||
} else {
|
||||
//Если ребёнок первый - добавляем его родителю как дефолтный
|
||||
updateQuestion(parentNodeContentId, question => question.content.rule.default = targetQuestion.content.id)
|
||||
@ -179,9 +182,8 @@ export const CsComponent = ({
|
||||
}
|
||||
|
||||
const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => {
|
||||
const deleteNodes = [] as string[]
|
||||
const deleteEdges:any = []
|
||||
console.log("remove")
|
||||
const deleteNodes = [] as string[]
|
||||
const deleteEdges: any = []
|
||||
const cy = cyRef?.current
|
||||
|
||||
const findChildrenToDelete = (node) => {
|
||||
@ -205,60 +207,54 @@ export const CsComponent = ({
|
||||
const targetQuestion = getQuestionByContentId(targetNodeContentId)
|
||||
|
||||
if (targetQuestion.content.rule.parentId === "root" && quiz) {
|
||||
console.log("click ROOT")
|
||||
console.log("ROOT")
|
||||
console.log(quiz)
|
||||
updateRootContentId(quiz?.id, "")
|
||||
updateQuestion(targetNodeContentId, question => {
|
||||
question.content.rule.parentId = ""
|
||||
question.content.rule.main = []
|
||||
question.content.rule.default = ""
|
||||
})
|
||||
updateRootContentId(quiz?.id, false)
|
||||
console.log(quiz, getQuestionByContentId(targetNodeContentId))
|
||||
} else {
|
||||
console.log("click not ROOT")
|
||||
const parentQuestionContentId = cy?.$('edge[target = "' + targetNodeContentId + '"]')?.toArray()?.[0]?.data()?.source
|
||||
if (targetNodeContentId && parentQuestionContentId) {
|
||||
|
||||
clearDataAfterRemoveNode({ targetQuestionContentId: targetNodeContentId, parentQuestionContentId })
|
||||
cy?.remove(cy?.$('#' + targetNodeContentId)).layout(lyopts).run()
|
||||
clearDataAfterRemoveNode({ targetQuestionContentId: targetNodeContentId, parentQuestionContentId })
|
||||
cy?.remove(cy?.$('#' + targetNodeContentId)).layout(lyopts).run()
|
||||
}
|
||||
|
||||
console.log(deleteNodes, deleteEdges)
|
||||
//После всех манипуляций удаляем грани из CS и ноды из бекенда
|
||||
|
||||
deleteNodes.forEach((nodeId) => {//Ноды
|
||||
cy?.remove(cy?.$("#" + nodeId))
|
||||
removeButtons(nodeId)
|
||||
updateQuestion(nodeId, question => {
|
||||
question.content.rule.parentId = ""
|
||||
question.content.rule.main = []
|
||||
question.content.rule.default = ""
|
||||
})
|
||||
})
|
||||
|
||||
deleteEdges.forEach((edge:any) => {//Грани
|
||||
cy?.remove(edge)
|
||||
})
|
||||
|
||||
removeButtons(targetNodeContentId)
|
||||
cy?.data('changed',true)
|
||||
cy?.layout(lyopts).run()
|
||||
|
||||
}
|
||||
|
||||
//После всех манипуляций удаляем грани из CS и ноды из бекенда
|
||||
|
||||
deleteNodes.forEach((nodeId) => {//Ноды
|
||||
cy?.remove(cy?.$("#" + nodeId))
|
||||
removeButtons(nodeId)
|
||||
updateQuestion(nodeId, question => {
|
||||
question.content.rule.parentId = ""
|
||||
question.content.rule.main = []
|
||||
question.content.rule.default = ""
|
||||
})
|
||||
})
|
||||
|
||||
deleteEdges.forEach((edge: any) => {//Грани
|
||||
cy?.remove(edge)
|
||||
})
|
||||
|
||||
removeButtons(targetNodeContentId)
|
||||
cy?.data('changed', true)
|
||||
cy?.layout(lyopts).run()
|
||||
}
|
||||
const clearDataAfterRemoveNode = ({ targetQuestionContentId, parentQuestionContentId }: { targetQuestionContentId: string, parentQuestionContentId: string }) => {
|
||||
|
||||
|
||||
|
||||
console.log({ targetQuestionContentId, parentQuestionContentId })
|
||||
|
||||
updateQuestion(targetQuestionContentId, question => {
|
||||
question.content.rule.parentId = ""
|
||||
question.content.rule.main = []
|
||||
question.content.rule.default = ""
|
||||
})
|
||||
|
||||
updateQuestion(parentQuestionContentId, question => {
|
||||
console.log("parent default " + question.content.rule.default)
|
||||
console.log("target ID " + targetQuestionContentId)
|
||||
console.log(question.content.rule.default === targetQuestionContentId)
|
||||
//Заменяем id удаляемого вопроса либо на id одного из оставшихся, либо на пустую строку
|
||||
if (question.content.rule.default === targetQuestionContentId) question.content.rule.default = ""
|
||||
})
|
||||
|
||||
@ -282,22 +278,20 @@ export const CsComponent = ({
|
||||
|
||||
|
||||
const readyLO = (e) => {
|
||||
console.log(e.cy.data('firstNode'),"SKEEER",e.cy.data('changed'))
|
||||
if (e.cy.data('firstNode') === 'nonroot') {
|
||||
e.cy.data('firstNode','root')
|
||||
e.cy.nodes().sort((a,b) => (a.data('root')?1:-1)).layout(lyopts).run()
|
||||
|
||||
} else {
|
||||
e.cy.data('firstNode', 'root')
|
||||
e.cy.nodes().sort((a, b) => (a.data('root') ? 1 : -1)).layout(lyopts).run()
|
||||
|
||||
|
||||
e.cy.data('changed', false)
|
||||
e.cy.removeData('firstNode')
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
e.cy.data('changed', false)
|
||||
e.cy.removeData('firstNode')
|
||||
}
|
||||
|
||||
//удаляем иконки
|
||||
e.cy.nodes().forEach((ele: any) => {
|
||||
const data = ele.data()
|
||||
console.log(data)
|
||||
data.id && removeButtons(data.id);
|
||||
})
|
||||
initialPopperIcons(e)
|
||||
@ -307,11 +301,9 @@ console.log(e.cy.data('firstNode'),"SKEEER",e.cy.data('changed'))
|
||||
name: 'preset',
|
||||
|
||||
positions: (e) => {
|
||||
console.log('BBBBBBBBBBBBBBB', e.cy().data('changed'))
|
||||
if (!e.cy().data('changed')) {
|
||||
return e.data('oldPos')
|
||||
} else {e.removeData('oldPos')}
|
||||
console.log('POSITIIIIIIIONS')
|
||||
} else { e.removeData('oldPos') }
|
||||
const id = e.id()
|
||||
const incomming = e.cy().edges(`[target="${id}"]`)
|
||||
const layer = 0
|
||||
@ -319,7 +311,7 @@ console.log(e.cy.data('firstNode'),"SKEEER",e.cy.data('changed'))
|
||||
|
||||
if (incomming.length === 0) {
|
||||
if (e.cy().data('firstNode') === undefined)
|
||||
e.cy().data('firstNode','root')
|
||||
e.cy().data('firstNode', 'root')
|
||||
e.data('root', true)
|
||||
const children = e.cy().edges(`[source="${id}"]`).targets()
|
||||
e.data('layer', layer)
|
||||
@ -341,7 +333,6 @@ console.log(e.cy.data('firstNode'),"SKEEER",e.cy.data('changed'))
|
||||
queue.push({ parent: e, children: children })
|
||||
while (queue.length) {
|
||||
const task = queue.pop()
|
||||
console.log('WIIIING',task.parent.data(),task.children.length)
|
||||
if (task.children.length === 0) {
|
||||
task.parent.data('subtreeWidth', task.parent.height())
|
||||
continue
|
||||
@ -360,22 +351,20 @@ console.log('WIIIING',task.parent.data(),task.children.length)
|
||||
task?.parent.data('subtreeWidth', task.children.reduce((p, n) => p + n.data('subtreeWidth'), 0))
|
||||
}
|
||||
const pos = { x: 0, y: 0 }
|
||||
console.log(e.data())
|
||||
e.data('oldPos', pos)
|
||||
return pos
|
||||
} else {
|
||||
if (e.cy().data('firstNode') !== 'root') {
|
||||
e.cy().data('firstNode','nonroot')
|
||||
return {x:0,y:0}
|
||||
if (e.cy().data('firstNode') !== 'root') {
|
||||
e.cy().data('firstNode', 'nonroot')
|
||||
return { x: 0, y: 0 }
|
||||
}
|
||||
if (e.cy().data('firstNode') === undefined)
|
||||
e.cy().data('firstNode','nonroot')
|
||||
e.cy().data('firstNode', 'nonroot')
|
||||
const parent = e.cy().edges(`[target="${e.id()}"]`)[0].source()
|
||||
const wing = (parent.data('children') === 1) ? 0 : parent.data('subtreeWidth') / 2 + 50
|
||||
const lastOffset = parent.data('lastChild')
|
||||
const step = wing * 2 / (parent.data('children') - 1)
|
||||
//e.removeData('subtreeWidth')
|
||||
console.log('AAAAAAAAAAa', e.data(), lastOffset, step, parent.position().y, wing)
|
||||
if (lastOffset !== undefined) {
|
||||
parent.data('lastChild', lastOffset + step)
|
||||
const pos = { x: 250 * e.data('layer'), y: (lastOffset + step) }
|
||||
@ -386,7 +375,7 @@ if (e.cy().data('firstNode') !== 'root') {
|
||||
const pos = { x: 250 * e.data('layer'), y: (parent.position().y - wing) }
|
||||
e.data('oldPos', pos)
|
||||
return pos
|
||||
}
|
||||
}
|
||||
}
|
||||
}, // map of (node id) => (position obj); or function(node){ return somPos; }
|
||||
zoom: undefined, // the zoom level to set (prob want fit = false if set)
|
||||
@ -502,7 +491,7 @@ if (e.cy().data('firstNode') !== 'root') {
|
||||
layoutElement.classList.add("popper-layout");
|
||||
layoutElement.setAttribute("data-id", item.id());
|
||||
layoutElement.addEventListener("mouseup", () => {
|
||||
//Узнаём грани, идущие от этой ноды
|
||||
//Узнаём грани, идущие от этой ноды
|
||||
setModalQuestionParentContentId(item.id())
|
||||
setOpenedModalQuestions(true)
|
||||
});
|
||||
@ -533,7 +522,7 @@ if (e.cy().data('firstNode') !== 'root') {
|
||||
plusElement.addEventListener("mouseup", () => {
|
||||
setStartCreate(node.id());
|
||||
});
|
||||
|
||||
|
||||
plusesContainer.current?.appendChild(plusElement);
|
||||
|
||||
return plusElement;
|
||||
@ -594,7 +583,6 @@ if (e.cy().data('firstNode') !== 'root') {
|
||||
gearElement.style.zIndex = "1"
|
||||
gearsContainer.current?.appendChild(gearElement);
|
||||
gearElement.addEventListener("mouseup", (e) => {
|
||||
console.log(item.id())
|
||||
updateOpenedModalSettingsId(item.id())
|
||||
});
|
||||
|
||||
@ -672,23 +660,27 @@ if (e.cy().data('firstNode') !== 'root') {
|
||||
|
||||
return (
|
||||
<>
|
||||
<CytoscapeComponent
|
||||
wheelSensitivity={0.1}
|
||||
elements={[]}
|
||||
// elements={createGraphElements(tree, quiz)}
|
||||
style={{ height: "480px", background: "#F2F3F7" }}
|
||||
stylesheet={stylesheet}
|
||||
layout={(lyopts)}
|
||||
cy={(cy) => {
|
||||
cyRef.current = cy;
|
||||
}}
|
||||
/>
|
||||
<button onClick={() => {
|
||||
console.log("ELEMENTS____________________________")
|
||||
cyRef.current?.elements().forEach((ele:any) => {
|
||||
console.log(ele.data())
|
||||
})
|
||||
}}>elements</button>
|
||||
<CytoscapeComponent
|
||||
wheelSensitivity={0.1}
|
||||
elements={[]}
|
||||
// elements={createGraphElements(tree, quiz)}
|
||||
style={{ height: "480px", background: "#F2F3F7" }}
|
||||
stylesheet={stylesheet}
|
||||
layout={(lyopts)}
|
||||
cy={(cy) => {
|
||||
cyRef.current = cy;
|
||||
}}
|
||||
/>
|
||||
<button onClick={() => {
|
||||
console.log("NODES____________________________")
|
||||
cyRef.current?.elements().forEach((ele: any) => {
|
||||
console.log(ele.data())
|
||||
})
|
||||
}}>nodes</button>
|
||||
<button onClick={() => {
|
||||
console.log("ELEMENTS____________________________")
|
||||
console.log(questions)
|
||||
}}>elements</button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -2,8 +2,8 @@ import { Box } from "@mui/material"
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { updateDragQuestionContentId, updateQuestion } from "@root/questions/actions"
|
||||
import { updateRootContentId } from "@root/quizes/actions"
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks"
|
||||
import { useQuestionsStore } from "@root/questions/store"
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
interface Props {
|
||||
@ -11,17 +11,15 @@ interface Props {
|
||||
modalQuestionTargetContentId: string;
|
||||
}
|
||||
export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetContentId }: Props) => {
|
||||
const { dragQuestionContentId } = useQuestionsStore()
|
||||
const Container = useRef<HTMLDivElement | null>(null);
|
||||
const quiz = useCurrentQuiz();
|
||||
console.log(dragQuestionContentId)
|
||||
const { dragQuestionContentId, questions } = useQuestionsStore()
|
||||
console.log(questions)
|
||||
const Container = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const modalOpen = () => setOpenedModalQuestions(true)
|
||||
|
||||
const newRootNode = () => {
|
||||
if (quiz) {
|
||||
console.log(dragQuestionContentId)
|
||||
|
||||
if (dragQuestionContentId) {
|
||||
updateRootContentId(quiz?.id, dragQuestionContentId)
|
||||
updateQuestion(dragQuestionContentId, (question) => question.content.rule.parentId = "root")
|
||||
@ -29,6 +27,7 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon
|
||||
} else {
|
||||
enqueueSnackbar("Нет информации о взятом опроснике")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -53,6 +52,7 @@ export const FirstNodeField = ({ setOpenedModalQuestions, modalQuestionTargetCon
|
||||
|
||||
}, [modalQuestionTargetContentId])
|
||||
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={Container}
|
||||
|
@ -15,11 +15,9 @@ interface Edges {
|
||||
}
|
||||
|
||||
export const storeToNodes = (questions: AnyQuizQuestion[]) => {
|
||||
console.log(questions)
|
||||
const nodes: Nodes[] = []
|
||||
const edges: Edges[] = []
|
||||
questions.forEach((question) => {
|
||||
console.log(question)
|
||||
if (question.content.rule.parentId) {
|
||||
nodes.push({data: {
|
||||
id: question.content.id,
|
||||
@ -38,6 +36,5 @@ export const storeToNodes = (questions: AnyQuizQuestion[]) => {
|
||||
}})
|
||||
}
|
||||
})
|
||||
console.log([...nodes, ...edges])
|
||||
return [...nodes, ...edges];
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ export const BranchingMap = () => {
|
||||
const [modalQuestionTargetContentId, setModalQuestionTargetContentId] = useState<string>("")
|
||||
const [openedModalQuestions, setOpenedModalQuestions] = useState<boolean>(false)
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<Box
|
||||
id="cytoscape-container"
|
||||
|
@ -32,35 +32,38 @@ export default function BranchingQuestions() {
|
||||
|
||||
const { openedModalSettingsId } = useQuestionsStore();
|
||||
const [targetQuestion, setTargetQuestion] = useState<AnyQuizQuestion | null>(getQuestionById(openedModalSettingsId) || getQuestionByContentId(openedModalSettingsId))
|
||||
console.log(targetQuestion)
|
||||
const [parentQuestion, setParentQuestion] = useState<AnyQuizQuestion | null>(getQuestionByContentId(targetQuestion?.content.rule.parentId))
|
||||
console.log(parentQuestion)
|
||||
console.log(parentQuestion.content.rule.default)
|
||||
console.log(targetQuestion.content.id)
|
||||
console.log(parentQuestion.content.rule.default === targetQuestion.content.id)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (parentQuestion === null) return
|
||||
if (parentQuestion.content.rule.main.length === 0) updateQuestion(parentQuestion.id, question => question.content.rule.main.push({
|
||||
next: targetQuestion.content.id,
|
||||
or: true,
|
||||
rules: [{
|
||||
question: parentQuestion.content.id,
|
||||
answers: []
|
||||
if (parentQuestion.content.rule.main.length === 0) {
|
||||
let mutate = JSON.parse(JSON.stringify(parentQuestion))
|
||||
mutate.content.rule.main = [{
|
||||
next: targetQuestion.content.id,
|
||||
or: true,
|
||||
rules: [{
|
||||
question: parentQuestion.content.id,
|
||||
answers: []
|
||||
}]
|
||||
}]
|
||||
}))
|
||||
setParentQuestion(mutate)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
console.log({targetQuestion, parentQuestion})
|
||||
|
||||
if (targetQuestion === null || parentQuestion === null) {
|
||||
|
||||
console.log(openedModalSettingsId)
|
||||
enqueueSnackbar("Невозможно найти данные ветвления для этого вопроса")
|
||||
return <></>
|
||||
}
|
||||
|
||||
const saveData = () => {
|
||||
console.log(parentQuestion)
|
||||
if (parentQuestion !== null) {
|
||||
updateQuestion(parentQuestion.content.id, question => question.content = parentQuestion.content)
|
||||
updateQuestion(parentQuestion.content.id, question => question.content = parentQuestion.content)
|
||||
}
|
||||
handleClose()
|
||||
|
||||
@ -149,11 +152,11 @@ export default function BranchingQuestions() {
|
||||
marginBottom: "10px",
|
||||
cursor: "pointer"
|
||||
}}
|
||||
onClick={() => {
|
||||
const mutate = JSON.parse(JSON.stringify(parentQuestion))
|
||||
mutate.content.rule.main.push(createBranchingRuleMain(targetQuestion.content.id, parentQuestion.content.id))
|
||||
setParentQuestion(mutate)
|
||||
}}
|
||||
onClick={() => {
|
||||
const mutate = JSON.parse(JSON.stringify(parentQuestion))
|
||||
mutate.content.rule.main.push(createBranchingRuleMain(targetQuestion.content.id, parentQuestion.content.id))
|
||||
setParentQuestion(mutate)
|
||||
}}
|
||||
>
|
||||
Добавить условие
|
||||
</Link>
|
||||
@ -164,7 +167,7 @@ export default function BranchingQuestions() {
|
||||
sx={{
|
||||
margin: 0
|
||||
}}
|
||||
checked={parentQuestion.content.rule.default === targetQuestion.id}
|
||||
checked={parentQuestion.content.rule.default === targetQuestion.content.id}
|
||||
|
||||
onClick={() => {
|
||||
let mutate = JSON.parse(JSON.stringify(parentQuestion))
|
||||
|
@ -264,21 +264,43 @@ const NumberInputsType = ({ parentQuestion, targetQuestion, ruleIndex, setParent
|
||||
(Укажите один или несколько вариантов)
|
||||
</Typography>
|
||||
</Box>
|
||||
{/* <TextField
|
||||
<TextField
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
width: "100%"
|
||||
}}
|
||||
|
||||
placeholder="от"
|
||||
value={parentQuestion.content.rule.main[ruleIndex].rules[0].answers[0]}
|
||||
onChange={(event: React.FormEvent<HTMLInputElement>) => {
|
||||
|
||||
let newParentQuestion = JSON.parse(JSON.stringify(parentQuestion))
|
||||
newParentQuestion.content.rule.main[ruleIndex].rules[0].answers = [(event.target as HTMLInputElement).value.replace(/[^0-9,\s]/g, "")]
|
||||
newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[0] = Number((event.target as HTMLInputElement).value.replace(/[^0-9,\s]/g, ""))
|
||||
if (newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[1] === undefined) newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[1] = 0
|
||||
setParentQuestion(newParentQuestion)
|
||||
|
||||
}}
|
||||
/> */}
|
||||
/>
|
||||
{parentQuestion.content.chooseRange &&
|
||||
<TextField
|
||||
placeholder="до"
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
width: "100%"
|
||||
}}
|
||||
|
||||
value={parentQuestion.content.rule.main[ruleIndex].rules[0].answers[1]}
|
||||
onChange={(event: React.FormEvent<HTMLInputElement>) => {
|
||||
|
||||
let newParentQuestion = JSON.parse(JSON.stringify(parentQuestion))
|
||||
newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[1] = Number((event.target as HTMLInputElement).value.replace(/[^0-9,\s]/g, ""))
|
||||
if (newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[0] === undefined) newParentQuestion.content.rule.main[ruleIndex].rules[0].answers[0] = 0
|
||||
setParentQuestion(newParentQuestion)
|
||||
|
||||
}}
|
||||
/>
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -338,7 +360,7 @@ const TextInputsType = ({ parentQuestion, targetQuestion, ruleIndex, setParentQu
|
||||
(Укажите текст, при совпадении с которым пользователь попадёт на этот вопрос)
|
||||
</Typography>
|
||||
</Box>
|
||||
{/* <TextField
|
||||
<TextField
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
width: "100%"
|
||||
@ -351,7 +373,7 @@ const TextInputsType = ({ parentQuestion, targetQuestion, ruleIndex, setParentQu
|
||||
setParentQuestion(newParentQuestion)
|
||||
|
||||
}}
|
||||
/> */}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
|
@ -23,7 +23,6 @@ type AnyQuestion = UntypedQuizQuestion | AnyTypedQuizQuestion
|
||||
|
||||
export const QuestionsList = () => {
|
||||
const { questions } = useQuestionsStore()
|
||||
console.log(questions)
|
||||
|
||||
return (
|
||||
<Box sx={{ padding: "15px" }}>
|
||||
|
@ -1,24 +1,30 @@
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Box, Modal, Button, Typography } from "@mui/material";
|
||||
import { useQuestionsStore } from "@root/questions/store";
|
||||
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "@model/questionTypes/shared";
|
||||
|
||||
type AnyQuestion = UntypedQuizQuestion | AnyTypedQuizQuestion
|
||||
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
||||
|
||||
interface Props {
|
||||
openedModalQuestions: boolean;
|
||||
setModalQuestionTargetContentId: (contentId:string) => void;
|
||||
setOpenedModalQuestions: (open:boolean) => void;
|
||||
setModalQuestionTargetContentId: (contentId: string) => void;
|
||||
setOpenedModalQuestions: (open: boolean) => void;
|
||||
setModalQuestionParentContentId: (open: string) => void;
|
||||
}
|
||||
|
||||
export const BranchingQuestionsModal = ({ openedModalQuestions, setOpenedModalQuestions, setModalQuestionTargetContentId}:Props) => {
|
||||
const quizId = Number(useParams().quizId);
|
||||
export const BranchingQuestionsModal = ({
|
||||
openedModalQuestions,
|
||||
setOpenedModalQuestions,
|
||||
setModalQuestionTargetContentId,
|
||||
setModalQuestionParentContentId
|
||||
}: Props) => {
|
||||
const { questions } = useQuestionsStore();
|
||||
|
||||
const handleClose = () => {
|
||||
setOpenedModalQuestions(false);
|
||||
};
|
||||
|
||||
const typedQuestions: AnyTypedQuizQuestion[] = questions.filter(
|
||||
(question) => question.type && !question.content.rule.parentId
|
||||
) as AnyTypedQuizQuestion[];
|
||||
|
||||
return (
|
||||
<Modal open={openedModalQuestions} onClose={handleClose}>
|
||||
<Box
|
||||
@ -37,14 +43,11 @@ export const BranchingQuestionsModal = ({ openedModalQuestions, setOpenedModalQu
|
||||
}}
|
||||
>
|
||||
<Box sx={{ margin: "0 auto", maxWidth: "350px" }}>
|
||||
{questions.filter((q:AnyQuestion) => {
|
||||
console.log(q.content)
|
||||
if (q.content === null) return true
|
||||
return (q.type && !q.content.rule.parentId)}).map((question: AnyTypedQuizQuestion, index:number) => (
|
||||
{typedQuestions.map((question) => (
|
||||
<Button
|
||||
key={question.content.id}
|
||||
onClick={() => {
|
||||
setModalQuestionTargetContentId(question.content.id)
|
||||
setModalQuestionTargetContentId(question.content.id);
|
||||
handleClose();
|
||||
}}
|
||||
sx={{
|
||||
|
@ -20,6 +20,7 @@ import { HideIcon } from "../../assets/icons/questionsPage/hideIcon";
|
||||
import SettingIcon from "../../assets/icons/questionsPage/settingIcon";
|
||||
import type { AnyTypedQuizQuestion } from "../../model/questionTypes/shared";
|
||||
import { updateOpenedModalSettingsId } from "@root/questions/actions";
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import {enqueueSnackbar} from "notistack";
|
||||
|
||||
|
||||
@ -38,6 +39,7 @@ export default function ButtonsOptions({
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const isWrappMiniButtonSetting = useMediaQuery(theme.breakpoints.down(920));
|
||||
const quiz = useCurrentQuiz();
|
||||
|
||||
const openedModal = () => {
|
||||
updateOpenedModalSettingsId(question.id)
|
||||
@ -45,6 +47,7 @@ export default function ButtonsOptions({
|
||||
|
||||
const handleClickBranching = (_, value) => {
|
||||
const parentId = question.content.rule.parentId
|
||||
console.log(parentId)
|
||||
console.log(parentId.length)
|
||||
if (parentId.length === 0 ){
|
||||
return enqueueSnackbar("Вопрос не учавствует в ветвлении")
|
||||
@ -293,7 +296,7 @@ export default function ButtonsOptions({
|
||||
// deleteTimeoutId: newTimeoutId,
|
||||
// });
|
||||
|
||||
deleteQuestion(question.id);
|
||||
deleteQuestion(question.id, quiz.id);
|
||||
}}
|
||||
data-cy="delete-question"
|
||||
>
|
||||
|
@ -26,6 +26,7 @@ import { updateOpenedModalSettingsId } from "@root/questions/actions";
|
||||
import { updateOpenBranchingPanel } from "@root/questions/actions";
|
||||
import {useQuestionsStore} from "@root/questions/store";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
|
||||
|
||||
interface Props {
|
||||
@ -46,6 +47,7 @@ export default function ButtonsOptionsAndPict({
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const isIconMobile = useMediaQuery(theme.breakpoints.down(1050));
|
||||
const {openBranchingPanel} = useQuestionsStore.getState()
|
||||
const quiz = useCurrentQuiz();
|
||||
|
||||
useEffect(() => {
|
||||
if (question.deleteTimeoutId) {
|
||||
@ -55,6 +57,7 @@ export default function ButtonsOptionsAndPict({
|
||||
|
||||
const handleClickBranching = (_, value) => {
|
||||
const parentId = question.content.rule.parentId
|
||||
console.log(parentId)
|
||||
console.log(parentId.length)
|
||||
if (parentId.length === 0 ) {
|
||||
return enqueueSnackbar("Вопрос не учавствует в ветвлении")
|
||||
@ -336,7 +339,7 @@ export default function ButtonsOptionsAndPict({
|
||||
// deleteTimeoutId: newTimeoutId,
|
||||
// });
|
||||
|
||||
deleteQuestion(question.id);
|
||||
deleteQuestion(question.id, quiz?.id);
|
||||
}}
|
||||
data-cy="delete-question"
|
||||
>
|
||||
|
@ -39,7 +39,7 @@ import SwitchQuestionsPage from "../SwitchQuestionsPage";
|
||||
import { ChooseAnswerModal } from "./ChooseAnswerModal";
|
||||
import TypeQuestions from "../TypeQuestions";
|
||||
import { QuestionType } from "@model/question/question";
|
||||
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks"
|
||||
|
||||
interface Props {
|
||||
question: AnyTypedQuizQuestion | UntypedQuizQuestion;
|
||||
@ -55,6 +55,7 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging
|
||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const anchorRef = useRef(null);
|
||||
const quiz = useCurrentQuiz();
|
||||
|
||||
const setTitle = useDebouncedCallback((title) => {
|
||||
const updateQuestionFn = question.type === null ? updateUntypedQuestion : updateQuestion;
|
||||
@ -253,7 +254,7 @@ export default function QuestionsPageCard({ question, draggableProps, isDragging
|
||||
// deleteTimeoutId: newTimeoutId,
|
||||
// });
|
||||
|
||||
deleteQuestion(question.id);
|
||||
deleteQuestion(question.id, quiz.id);
|
||||
}}
|
||||
data-cy="delete-question"
|
||||
>
|
||||
|
@ -27,6 +27,7 @@ export default function QuestionsPage() {
|
||||
const openBranchingPanel = useQuestionsStore.getState()
|
||||
if (!quiz) return null;
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
|
@ -1,9 +1,12 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Box, Typography, Button, useTheme } from "@mui/material";
|
||||
|
||||
import { useQuizViewStore, getAnswersByQuestionId } from "@root/quizView";
|
||||
import { useQuizViewStore } from "@root/quizView";
|
||||
|
||||
import type { AnyTypedQuizQuestion, QuizQuestionBase } from "../../model/questionTypes/shared";
|
||||
import type {
|
||||
AnyTypedQuizQuestion,
|
||||
QuizQuestionBase,
|
||||
} from "../../model/questionTypes/shared";
|
||||
import { getQuestionByContentId } from "@root/questions/actions";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
@ -12,10 +15,7 @@ type FooterProps = {
|
||||
question: QuizQuestionBase;
|
||||
};
|
||||
|
||||
export const Footer = ({
|
||||
setCurrentQuestion,
|
||||
question,
|
||||
}: FooterProps) => {
|
||||
export const Footer = ({ setCurrentQuestion, question }: FooterProps) => {
|
||||
const [disabledQuestionsId, setDisabledQuestionsId] = useState<Set<string>>(
|
||||
new Set()
|
||||
);
|
||||
@ -24,60 +24,67 @@ export const Footer = ({
|
||||
|
||||
const followPreviousStep = () => {
|
||||
if (question?.content.rule.parentId !== "root") {
|
||||
const parent = getQuestionByContentId(question?.content.rule.parentId)
|
||||
const parent = getQuestionByContentId(question?.content.rule.parentId);
|
||||
if (parent) {
|
||||
setCurrentQuestion(parent)
|
||||
setCurrentQuestion(parent);
|
||||
} else {
|
||||
enqueueSnackbar("не могу получить предыдущий вопрос")
|
||||
enqueueSnackbar("не могу получить предыдущий вопрос");
|
||||
}
|
||||
} else {
|
||||
enqueueSnackbar("вы находитесь на первом вопросе")
|
||||
enqueueSnackbar("вы находитесь на первом вопросе");
|
||||
}
|
||||
};
|
||||
|
||||
const followNextStep = () => {
|
||||
const answers = getAnswersByQuestionId(question.content.id) || []
|
||||
console.log(answers)
|
||||
if (answers) {
|
||||
if (answers.length) {
|
||||
let readyBeNextQuestion = "";
|
||||
|
||||
let readyBeNextQuestion = ""
|
||||
question.content.rule.main.forEach(({ next, rules }) => {
|
||||
console.log({ next, rules })
|
||||
console.log({ next, rules });
|
||||
|
||||
console.log("[storeAnswers] ", rules[0].answers)
|
||||
console.log("[answers.answer] ", [answers.answer])
|
||||
console.log("[storeAnswers] ", rules[0].answers);
|
||||
console.log("[answers.answer] ", [answers.at(-1)?.answer]);
|
||||
|
||||
let longerArray = Math.max(rules[0].answers.length, [answers.answer].length)
|
||||
let longerArray = Math.max(
|
||||
rules[0].answers.length,
|
||||
[answers.at(-1)?.answer].length
|
||||
);
|
||||
|
||||
for (var i = 0; i < longerArray; i++) // Цикл по всем элементам бОльшего массива
|
||||
if (rules[0].answers[i] !== [answers.answer][i]) readyBeNextQuestion = next; // Если хоть один элемент отличается, массивы не равны
|
||||
|
||||
|
||||
})
|
||||
if (readyBeNextQuestion) {
|
||||
console.log("мы нашли совпадение в " + readyBeNextQuestion)
|
||||
|
||||
const nextQuestion = getQuestionByContentId(readyBeNextQuestion)
|
||||
console.log("next question ", nextQuestion)
|
||||
if (nextQuestion) {
|
||||
console.log("я устанавливаю следующий вопрос " + question.title)
|
||||
setCurrentQuestion(nextQuestion)
|
||||
return
|
||||
} else {
|
||||
enqueueSnackbar("не могу получить последующий вопрос")
|
||||
}
|
||||
} else {
|
||||
const nextQuestion = getQuestionByContentId(question.content.rule.default)
|
||||
console.log("я устанавливаю дефолтный вопрос")
|
||||
if (nextQuestion) {
|
||||
setCurrentQuestion(nextQuestion)
|
||||
} else {
|
||||
enqueueSnackbar("не могу получить последующий вопрос (дефолтный)")
|
||||
for (
|
||||
var i = 0;
|
||||
i < longerArray;
|
||||
i++ // Цикл по всем элементам бОльшего массива
|
||||
) {
|
||||
if (rules[0].answers[i] === answers.at(-1)?.answer) {
|
||||
readyBeNextQuestion = next; // Если хоть один элемент отличается, массивы не равны
|
||||
}
|
||||
}
|
||||
});
|
||||
if (readyBeNextQuestion) {
|
||||
console.log("мы нашли совпадение в " + readyBeNextQuestion);
|
||||
|
||||
const nextQuestion = getQuestionByContentId(readyBeNextQuestion);
|
||||
|
||||
console.log("next question ", nextQuestion);
|
||||
if (nextQuestion) {
|
||||
console.log("я устанавливаю следующий вопрос " + question.title);
|
||||
setCurrentQuestion(nextQuestion);
|
||||
return;
|
||||
} else {
|
||||
enqueueSnackbar("не могу получить последующий вопрос");
|
||||
}
|
||||
} else {
|
||||
const nextQuestion = getQuestionByContentId(
|
||||
question.content.rule.default
|
||||
);
|
||||
console.log("я устанавливаю дефолтный вопрос");
|
||||
if (nextQuestion) {
|
||||
setCurrentQuestion(nextQuestion);
|
||||
} else {
|
||||
enqueueSnackbar("не могу получить последующий вопрос (дефолтный)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -10,6 +10,8 @@ import { nanoid } from "nanoid";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { isAxiosCanceledError } from "../../utils/isAxiosCanceledError";
|
||||
import { RequestQueue } from "../../utils/requestQueue";
|
||||
import { updateRootContentId } from "@root/quizes/actions"
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks"
|
||||
import { QuestionsStore, useQuestionsStore } from "./store";
|
||||
|
||||
|
||||
@ -136,22 +138,20 @@ export const updateQuestion = (
|
||||
|
||||
// clearTimeout(requestTimeoutId);
|
||||
// requestTimeoutId = setTimeout(() => {
|
||||
requestQueue.enqueue(async () => {
|
||||
const q = useQuestionsStore.getState().questions.find(q => q.id === questionId) || useQuestionsStore.getState().questions.find(q => q.content.id === questionId);
|
||||
console.log("мы пытаемся найти вопрос ")
|
||||
if (!q) return;
|
||||
if (q.type === null) throw new Error("Cannot send update request for untyped question");
|
||||
console.log(q.title)
|
||||
requestQueue.enqueue(async () => {
|
||||
const q = useQuestionsStore.getState().questions.find(q => q.id === questionId) || useQuestionsStore.getState().questions.find(q => q.content.id === questionId);
|
||||
if (!q) return;
|
||||
if (q.type === null) throw new Error("Cannot send update request for untyped question");
|
||||
|
||||
const response = await questionApi.edit(questionToEditQuestionRequest(q));
|
||||
const response = await questionApi.edit(questionToEditQuestionRequest(q));
|
||||
|
||||
setQuestionBackendId(questionId, response.updated);
|
||||
}).catch(error => {
|
||||
if (isAxiosCanceledError(error)) return;
|
||||
setQuestionBackendId(questionId, response.updated);
|
||||
}).catch(error => {
|
||||
if (isAxiosCanceledError(error)) return;
|
||||
|
||||
devlog("Error editing question", { error, questionId });
|
||||
enqueueSnackbar("Не удалось сохранить вопрос");
|
||||
});
|
||||
devlog("Error editing question", { error, questionId });
|
||||
enqueueSnackbar("Не удалось сохранить вопрос");
|
||||
});
|
||||
// }, REQUEST_DEBOUNCE);
|
||||
};
|
||||
|
||||
@ -261,8 +261,10 @@ export const changeQuestionType = (
|
||||
type: QuestionType,
|
||||
) => {
|
||||
updateQuestion(questionId, question => {
|
||||
const oldId = question.content.id
|
||||
question.type = type;
|
||||
question.content = defaultQuestionByType[type].content;
|
||||
question.content.id = oldId
|
||||
});
|
||||
};
|
||||
|
||||
@ -273,7 +275,7 @@ export const createTypedQuestion = async (
|
||||
const question = useQuestionsStore.getState().questions.find(q => q.id === questionId);
|
||||
if (!question) return;
|
||||
if (question.type !== null) throw new Error("Cannot upgrade already typed question");
|
||||
|
||||
|
||||
try {
|
||||
const createdQuestion = await questionApi.create({
|
||||
quiz_id: question.quizId,
|
||||
@ -302,7 +304,8 @@ export const createTypedQuestion = async (
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteQuestion = async (questionId: string) => requestQueue.enqueue(async () => {
|
||||
export const deleteQuestion = async (questionId: string, quizId: string) => requestQueue.enqueue(async () => {
|
||||
|
||||
const question = useQuestionsStore.getState().questions.find(q => q.id === questionId);
|
||||
if (!question) return;
|
||||
|
||||
@ -312,7 +315,12 @@ export const deleteQuestion = async (questionId: string) => requestQueue.enqueue
|
||||
}
|
||||
|
||||
try {
|
||||
console.log(question.content.rule.parentId)
|
||||
await questionApi.delete(question.backendId);
|
||||
if (question.content.rule.parentId === "root") { //удалить из стора root и очистить rule всем вопросам
|
||||
updateRootContentId(quizId, "")
|
||||
clearRoleForAll()
|
||||
}
|
||||
|
||||
removeQuestion(questionId);
|
||||
} catch (error) {
|
||||
@ -325,9 +333,11 @@ export const copyQuestion = async (questionId: string, quizId: number) => reques
|
||||
const question = useQuestionsStore.getState().questions.find(q => q.id === questionId);
|
||||
if (!question) return;
|
||||
|
||||
const frontId = nanoid();
|
||||
if (question.type === null) {
|
||||
const copiedQuestion = structuredClone(question);
|
||||
copiedQuestion.id = nanoid();
|
||||
copiedQuestion.id = frontId
|
||||
copiedQuestion.content.id = frontId
|
||||
|
||||
setProducedState(state => {
|
||||
state.questions.push(copiedQuestion);
|
||||
@ -369,7 +379,7 @@ function setProducedState<A extends string | { type: unknown; }>(
|
||||
|
||||
|
||||
export const cleardragQuestionContentId = () => {
|
||||
useQuestionsStore.setState({dragQuestionContentId: null});
|
||||
useQuestionsStore.setState({ dragQuestionContentId: null });
|
||||
};
|
||||
|
||||
export const getQuestionById = (questionId: string | null) => {
|
||||
@ -377,17 +387,28 @@ export const getQuestionById = (questionId: string | null) => {
|
||||
return useQuestionsStore.getState().questions.find(q => q.id === questionId) || null;
|
||||
};
|
||||
export const getQuestionByContentId = (questionContentId: string | null) => {
|
||||
console.log("questionContentId " + questionContentId)
|
||||
if (questionContentId === null) return null;
|
||||
return useQuestionsStore.getState().questions.find(q => {
|
||||
console.log(q.content.id)
|
||||
console.log(q.content.id === questionContentId)
|
||||
return ( q.content.id === questionContentId)}) || null;
|
||||
return (q.content.id === questionContentId)
|
||||
}) || null;
|
||||
};
|
||||
|
||||
export const updateOpenedModalSettingsId = (id?: string) => useQuestionsStore.setState({openedModalSettingsId: id ? id : null});
|
||||
export const updateOpenedModalSettingsId = (id?: string) => useQuestionsStore.setState({ openedModalSettingsId: id ? id : null });
|
||||
export const updateDragQuestionContentId = (contentId?: string) => {
|
||||
console.log("contentId " + contentId)
|
||||
useQuestionsStore.setState({dragQuestionContentId: contentId ? contentId : null});
|
||||
};
|
||||
useQuestionsStore.setState({ dragQuestionContentId: contentId ? contentId : null });
|
||||
}
|
||||
|
||||
export const clearRoleForAll = () => {
|
||||
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)) {
|
||||
updateQuestion(question.content.id, question => {
|
||||
question.content.rule.parentId = ""
|
||||
question.content.rule.main = []
|
||||
question.content.rule.default = ""
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const updateOpenBranchingPanel = (value: boolean) => useQuestionsStore.setState({openBranchingPanel: !value});
|
||||
|
@ -4,7 +4,7 @@ import { devtools } from "zustand/middleware";
|
||||
|
||||
|
||||
export type QuestionsStore = {
|
||||
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion);
|
||||
questions: (AnyTypedQuizQuestion | UntypedQuizQuestion)[];
|
||||
openedModalSettingsId: string | null;
|
||||
dragQuestionContentId: string | null;
|
||||
openBranchingPanel: boolean;
|
||||
|
@ -33,9 +33,3 @@ export const updateAnswer = (questionId: string, answer: string) => {
|
||||
|
||||
useQuizViewStore.setState({ answers });
|
||||
};
|
||||
|
||||
export const getAnswersByQuestionId = (questionId: string) => {
|
||||
if (questionId === null) return null;
|
||||
const answers = [...useQuizViewStore.getState().answers];
|
||||
return answers.find(a => a.questionId === questionId) || null;
|
||||
}
|
@ -10,6 +10,7 @@ import { isAxiosCanceledError } from "../../utils/isAxiosCanceledError";
|
||||
import { RequestQueue } from "../../utils/requestQueue";
|
||||
import { QuizStore, useQuizStore } from "./store";
|
||||
import { createUntypedQuestion } from "@root/questions/actions";
|
||||
import { useCurrentQuiz } from "./hooks"
|
||||
|
||||
|
||||
export const setEditQuizId = (quizId: number | null) => setProducedState(state => {
|
||||
@ -127,6 +128,7 @@ export const updateQuiz = async (
|
||||
requestTimeoutId = setTimeout(async () => {
|
||||
requestQueue.enqueue(async () => {
|
||||
const quiz = useQuizStore.getState().quizes.find(q => q.id === quizId);
|
||||
console.log("измененный квиз", quiz)
|
||||
if (!quiz) return;
|
||||
|
||||
const response = await quizApi.edit(quizToEditQuizRequest(quiz));
|
||||
@ -178,10 +180,11 @@ export const deleteQuiz = async (quizId: string) => requestQueue.enqueue(async (
|
||||
export const updateRootContentId = (quizId: string, id:string) => updateQuiz(
|
||||
quizId,
|
||||
quiz => {
|
||||
quiz.config.haveRoot = id;
|
||||
quiz.config.haveRoot = id
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
// TODO copy quiz
|
||||
|
||||
export const uploadQuizImage = async (
|
||||
|
Loading…
Reference in New Issue
Block a user