добавление и удаление нод

This commit is contained in:
Nastya 2023-12-02 12:59:31 +03:00
parent 7dc083907f
commit fcd0f92259
8 changed files with 336 additions and 329 deletions

13
package-lock.json generated

@ -9550,6 +9550,19 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",

@ -30,6 +30,7 @@ async function getQuestionList(body?: Partial<GetQuestionListRequest>) {
} }
function editQuestion(body: EditQuestionRequest, signal?: AbortSignal) { function editQuestion(body: EditQuestionRequest, signal?: AbortSignal) {
console.log("`${baseUrl}/question/edit` start")
return makeRequest<EditQuestionRequest, EditQuestionResponse>({ return makeRequest<EditQuestionRequest, EditQuestionResponse>({
url: `${baseUrl}/question/edit`, url: `${baseUrl}/question/edit`,
body, body,

@ -19,6 +19,7 @@ import type {
ElementDefinition, ElementDefinition,
} from "cytoscape"; } from "cytoscape";
import { QuestionsList } from "../BranchingPanel/QuestionsList"; import { QuestionsList } from "../BranchingPanel/QuestionsList";
import { enqueueSnackbar } from "notistack";
type PopperItem = { type PopperItem = {
id: () => string; id: () => string;
@ -108,7 +109,6 @@ export const CsComponent = ({
setModalQuestionParentContentId, setModalQuestionParentContentId,
setModalQuestionTargetContentId setModalQuestionTargetContentId
}:Props) => { }:Props) => {
console.log("Я существую")
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { dragQuestionContentId, questions } = useQuestionsStore() const { dragQuestionContentId, questions } = useQuestionsStore()
@ -129,13 +129,13 @@ useEffect(() =>{
}, [modalQuestionTargetContentId]) }, [modalQuestionTargetContentId])
const addNode = ({ parentNodeContentId }: { parentNodeContentId: string }) => { const addNode = ({ parentNodeContentId }: { parentNodeContentId: string }) => {
console.log("dragQuestionContentId " + dragQuestionContentId)
const cy = cyRef?.current const cy = cyRef?.current
const parentNodeChildren = cy?.$('edge[source = "' + parentNodeContentId + '"]')?.length const parentNodeChildren = cy?.$('edge[source = "' + parentNodeContentId + '"]')?.length
const targetQuestion = { ...getQuestionByContentId(dragQuestionContentId) } as AnyQuizQuestion const targetQuestion = { ...getQuestionByContentId(dragQuestionContentId) } as AnyQuizQuestion
console.log(parentNodeChildren, parentNodeContentId)
if (targetQuestion && targetQuestion && parentNodeContentId && parentNodeChildren !== undefined) { if (Object.keys(targetQuestion).length !== 0 && Object.keys(targetQuestion).length !== 0 && parentNodeContentId && parentNodeChildren !== undefined) {
console.log(targetQuestion, targetQuestion, parentNodeContentId, parentNodeChildren) clearDataAfterAddNode({ parentNodeContentId, targetQuestion, parentNodeChildren })
cy?.add([ cy?.add([
{ {
data: { data: {
@ -149,19 +149,17 @@ useEffect(() =>{
target: targetQuestion.content.id target: targetQuestion.content.id
} }
} }
]) ]).layout(lyopts).run()
// clearDataAfterAddNode({ parentNodeContentId, targetQuestion, parentNodeChildren }) } else {
enqueueSnackbar("Добавляемый вопрос не найден")
} }
console.log(dragQuestionContentId)
} }
const clearDataAfterAddNode = ({ parentNodeContentId, targetQuestion, parentNodeChildren }: { parentNodeContentId: string, targetQuestion: AnyQuizQuestion, parentNodeChildren:number }) => { const clearDataAfterAddNode = ({ parentNodeContentId, targetQuestion, parentNodeChildren }: { parentNodeContentId: string, targetQuestion: AnyQuizQuestion, parentNodeChildren:number }) => {
console.log("записываю на бек ид родителя")
console.log({ parentNodeContentId, targetQuestion, parentNodeChildren })
//предупреждаем добавленный вопрос о том, кто его родитель //предупреждаем добавленный вопрос о том, кто его родитель
updateQuestion(targetQuestion.id, question => { updateQuestion(targetQuestion.content.id, question => {
question.content.rule.parentId = parentNodeContentId question.content.rule.parentId = parentNodeContentId
question.content.rule.main = [] question.content.rule.main = []
}) })
@ -174,17 +172,34 @@ useEffect(() =>{
updateQuestion(parentNodeContentId, question => question.content.rule.default = targetQuestion.content.id) updateQuestion(parentNodeContentId, question => question.content.rule.default = targetQuestion.content.id)
} }
} }
const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => { const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => {
const cy = cyRef?.current const cy = cyRef?.current
//получить можно только дочерние ноды //
console.log(cy?.$('#'+targetNodeContentId)) const parentQuestion = cy?.$('edge[target = "' + targetNodeContentId + '"]').toArray()[0].data()
console.log(cy?.$('#'+targetNodeContentId)?.data()) const targetQuestion = cy?.$('#'+targetNodeContentId)?.data()
if (targetQuestion && parentQuestion) {
clearDataAfterRemoveNode({targetQuestionId: targetQuestion.id, parentQuestionId: parentQuestion.source})
cy?.remove(cy?.$('#'+targetNodeContentId)).layout(lyopts).run()
}
}
const clearDataAfterRemoveNode = ({targetQuestionId, parentQuestionId}:{targetQuestionId:string, parentQuestionId:string}) => {
console.log({targetQuestionId, parentQuestionId})
updateQuestion(targetQuestionId, question => {
question.content.rule.parentId = ""
question.content.rule.main = []
question.content.rule.default = ""
})
updateQuestion(parentQuestionId, question => {
if (question.content.rule.parentId === parentQuestionId) question.content.rule.parentId = ""
})
} }
const clearDataAfterRemoveNode = () => {
}
useEffect(() => { useEffect(() => {
if (startCreate) { if (startCreate) {
addNode({ parentNodeContentId: startCreate }); addNode({ parentNodeContentId: startCreate });
@ -195,174 +210,228 @@ const clearDataAfterRemoveNode = () => {
useEffect(() => { useEffect(() => {
if (startRemove) { if (startRemove) {
// removeNode({ targetNodeContentId: startRemove }); removeNode({ targetNodeContentId: startRemove });
setStartRemove(""); setStartRemove("");
} }
}, [startRemove]); }, [startRemove]);
const readyLO = (e) => {
//удаляем иконки
e.cy.nodes().forEach((ele: any) => {
const data = ele.data()
data.id && removeButtons(data.id);
})
initialPopperIcons(e)
}
const lyopts = {
name: 'preset',
positions: (e) => {
const id = e.id()
const incomming = e.cy().edges(`[target="${id}"]`)
const layer = 0
e.removeData('lastChild')
if (incomming.length === 0) {
const children = e.cy().edges(`[source="${id}"]`)
e.data('layer', layer)
e.data('children', children.targets().length)
const queue = []
children.forEach(n => {
queue.push({ task: n.target(), layer: layer + 1 })
})
while (queue.length) {
const task = queue.pop()
task.task.data('layer', task.layer)
const children = e.cy().edges(`[source="${task.task.id()}"]`)
task.task.data('children', children.targets().length)
if (children.length !== 0) {
children.forEach(n => queue.push({ task: n.target(), layer: task.layer + 1 }))
}
}
queue.push({ parent: e, children: children.targets() })
while (queue.length) {
const task = queue.pop()
if (task.children.length === 0) {
task.parent.data('subtreeWidth', task.parent.height())
continue
}
const unprocessed = task?.children.filter(e => {
return (e.data('subtreeWidth') === undefined)
})
if (unprocessed.length !== 0) {
queue.push(task)
unprocessed.forEach(t => {
queue.push({ parent: t, children: t.cy().edges(`[source="${t.id()}"]`).targets() })
})
continue
}
task?.parent.data('subtreeWidth', task.children.reduce((p, n) => p + n.data('subtreeWidth'), 0))
}
return { x: 200 * e.data('layer'), y: 0 }
} else {
const parent = e.cy().edges(`[target="${e.id()}"]`)[0].source()
const wing = parent.data('subtreeWidth') / 2
const lastOffset = parent.data('lastChild')
const step = wing * 2 / (parent.data('children') - 1)
//e.removeData('subtreeWidth')
if (lastOffset !== undefined) {
parent.data('lastChild', lastOffset + step)
return { x: 200 * e.data('layer'), y: (lastOffset + step) }
} else {
parent.data('lastChild', parent.position().y - wing)
return { x: 200 * e.data('layer'), y: (parent.position().y - wing) }
}
}
}, // map of (node id) => (position obj); or function(node){ return somPos; }
zoom: undefined, // the zoom level to set (prob want fit = false if set)
pan: true, // the pan level to set (prob want fit = false if set)
fit: false, // whether to fit to viewport
padding: 30, // padding on fit
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function (node, i) { return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: readyLO, // callback on layoutready
transform: function (node, position) { return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
}
useEffect(() => { useEffect(() => {
document.querySelector("#root")?.addEventListener("mouseup", cleardragQuestionContentId); document.querySelector("#root")?.addEventListener("mouseup", cleardragQuestionContentId);
const cy = cyRef.current; const cy = cyRef.current;
cy?.add(storeToNodes(questions))
// cy?.add(storeToNodes(questions)) // cy?.add(storeToNodes(questions))
cy?.add( //cy?.on('add',()=>cy.fit())
[ // const elecs = cy?.add(
{ // [
"data": { // {
"id": "1", // "data": {
"label": "нет имени" // "id": "1",
}, // "label": "нет имени"
"position": { // }
"x": 250, // },
"y": 200 // {
} // "data": {
}, // "id": "1 2",
{ // "label": "нет имени"
"data": { // }
"id": "1 2", // },
"label": "нет имени" // {
}, // "data": {
"position": { // "id": "1 3",
"x": 500, // "label": "нет имени"
"y": 300 // }
} // },
}, // {
{ // "data": {
"data": { // "id": "1 2 4",
"id": "1 3", // "label": "нет имени"
"label": "нет имени" // }
}, // },
"position": { // {
"x": 500, // "data": {
"y": 400 // "id": "1 2 6",
} // "label": "нет имени"
}, // }
{ // },
"data": { // {
"id": "1 2 4", // "data": {
"label": "нет имени" // "id": "1 3 5",
}, // "label": "нет имени"
"position": { // }
"x": 750, // },
"y": 100 // {
} // "data": {
}, // "id": "1 3 7",
{ // "label": "нет имени"
"data": { // }
"id": "1 2 6", // },
"label": "нет имени" // {
}, // "data": {
"position": { // "id": "1 2 6 9867874",
"x": 750, // "label": "нет имени"
"y": 500 // }
} // },
}, // {
{ // "data": {
"data": { // "id": "1 2 6 7398789",
"id": "1 3 5", // "label": "нет имени"
"label": "нет имени" // }
}, // },
"position": { // {
"x": 750, // "data": {
"y": 300 // "id": "1 2 6 9484789",
} // "label": "нет имени"
}, // }
{ // },
"data": { // {
"id": "1 3 7", // "data": {
"label": "нет имени" // "source": "1",
}, // "target": "1 2"
"position": { // }
"x": 750, // },
"y": 500 // {
} // "data": {
}, // "source": "1",
{ // "target": "1 3"
"data": { // }
"id": "1 2 6 9867874", // },
"label": "нет имени" // {
}, // "data": {
"position": { // "source": "1 2",
"x": 1000, // "target": "1 2 4"
"y": 300 // }
} // },
}, // {
{ // "data": {
"data": { // "source": "1 2",
"id": "1 2 6 7398789", // "target": "1 2 6"
"label": "нет имени" // }
}, // },
"position": { // {
"x": 1000, // "data": {
"y": 500 // "source": "1 3",
} // "target": "1 3 5"
}, // }
{ // },
"data": { // {
"id": "1 2 6 9484789", // "data": {
"label": "нет имени" // "source": "1 3",
}, // "target": "1 3 7"
"position": { // }
"x": 1000, // },
"y": 700 // {
} // "data": {
}, // "source": "1 2 6",
{ // "target": "1 2 6 9867874"
"data": { // }
"source": "1", // },
"target": "1 2" // {
} // "data": {
}, // "source": "1 2 6",
{ // "target": "1 2 6 7398789"
"data": { // }
"source": "1", // },
"target": "1 3" // {
} // "data": {
}, // "source": "1 2 6",
{ // "target": "1 2 6 9484789"
"data": { // }
"source": "1 2", // }
"target": "1 2 4" // ]
} // ).layout(lyopts)
}, // elecs.run()
{
"data": { //cy?.fit()
"source": "1 2", //cy?.layout().run()
"target": "1 2 6"
}
},
{
"data": {
"source": "1 3",
"target": "1 3 5"
}
},
{
"data": {
"source": "1 3",
"target": "1 3 7"
}
},
{
"data": {
"source": "1 2 6",
"target": "1 2 6 9867874"
}
},
{
"data": {
"source": "1 2 6",
"target": "1 2 6 7398789"
}
},
{
"data": {
"source": "1 2 6",
"target": "1 2 6 9484789"
}
}
]
)
//cy?.layout(ly).run()
return () => { return () => {
document.querySelector("#root")?.removeEventListener("mouseup", cleardragQuestionContentId); document.querySelector("#root")?.removeEventListener("mouseup", cleardragQuestionContentId);
@ -390,21 +459,6 @@ const clearDataAfterRemoveNode = () => {
}; };
const readyLO = (e) => {
//удаляем иконки
e.cy.nodes().forEach((ele: any) => {
const data = ele.data()
data.id && removeButtons(data.id);
})
initialPopperIcons(e)
// console.log('ready', e)
// console.log(e.cy.nodes())
// console.log(e.cy.nodes().data())
}
const initialPopperIcons = (e) => { const initialPopperIcons = (e) => {
const cy = e.cy const cy = e.cy
@ -419,11 +473,6 @@ const clearDataAfterRemoveNode = () => {
container.style.overflow = "hidden"; container.style.overflow = "hidden";
if (!layoutsContainer.current) {
layoutsContainer.current = document.createElement("div");
layoutsContainer.current.setAttribute("id", "popper-layouts");
container.append(layoutsContainer.current);
}
if (!plusesContainer.current) { if (!plusesContainer.current) {
plusesContainer.current = document.createElement("div"); plusesContainer.current = document.createElement("div");
plusesContainer.current.setAttribute("id", "popper-pluses"); plusesContainer.current.setAttribute("id", "popper-pluses");
@ -439,12 +488,22 @@ const clearDataAfterRemoveNode = () => {
gearsContainer.current.setAttribute("id", "popper-gears"); gearsContainer.current.setAttribute("id", "popper-gears");
container.append(gearsContainer.current); container.append(gearsContainer.current);
} }
if (!layoutsContainer.current) {
layoutsContainer.current = document.createElement("div");
layoutsContainer.current.setAttribute("id", "popper-layouts");
container.append(layoutsContainer.current);
}
cy?.nodes() const ext = cy.extent()
const nodesInView = cy.nodes().filter(n => {
const bb = n.boundingBox()
return bb.x1 > ext.x1 && bb.x2 < ext.x2 && bb.y1 > ext.y1 && bb.y2 < ext.y2
})
nodesInView
.toArray() .toArray()
?.forEach((item) => { ?.forEach((item) => {
const node = item as NodeSingularWithPopper; const node = item as NodeSingularWithPopper;
//console.log(node)
const layoutsPopper = node.popper({ const layoutsPopper = node.popper({
popper: { popper: {
@ -461,12 +520,14 @@ const clearDataAfterRemoveNode = () => {
} }
const layoutElement = document.createElement("div"); const layoutElement = document.createElement("div");
layoutElement.style.zIndex="0"
layoutElement.classList.add("popper-layout"); layoutElement.classList.add("popper-layout");
layoutElement.setAttribute("data-id", item.id()); layoutElement.setAttribute("data-id", item.id());
// layoutElement.addEventListener("mouseup", () =>{} layoutElement.addEventListener("mouseup", () =>{
// // setStartCreate(node.id()) alert("layout")
// ); }
//console.log(layoutsContainer.current) // setStartCreate(node.id())
);
layoutsContainer.current?.appendChild(layoutElement); layoutsContainer.current?.appendChild(layoutElement);
return layoutElement; return layoutElement;
@ -490,6 +551,7 @@ const clearDataAfterRemoveNode = () => {
const plusElement = document.createElement("div"); const plusElement = document.createElement("div");
plusElement.classList.add("popper-plus"); plusElement.classList.add("popper-plus");
plusElement.setAttribute("data-id", item.id()); plusElement.setAttribute("data-id", item.id());
plusElement.style.zIndex="1"
plusElement.addEventListener("mouseup", () => { plusElement.addEventListener("mouseup", () => {
setStartCreate(node.id()); setStartCreate(node.id());
}); });
@ -516,12 +578,15 @@ const clearDataAfterRemoveNode = () => {
const crossElement = document.createElement("div"); const crossElement = document.createElement("div");
crossElement.classList.add("popper-cross"); crossElement.classList.add("popper-cross");
crossElement.setAttribute("data-id", item.id()); crossElement.setAttribute("data-id", item.id());
crossElement.style.zIndex="2"
crossesContainer.current?.appendChild(crossElement); crossesContainer.current?.appendChild(crossElement);
// crossElement.addEventListener("click", () => crossElement.addEventListener("mouseup", () =>{
// setStartRemove(node.id()) setStartRemove(node.id())
// );
}
);
//console.log(crossElement)
return crossElement; return crossElement;
}, },
}); });
@ -532,10 +597,7 @@ const clearDataAfterRemoveNode = () => {
modifiers: [{ name: "flip", options: { boundary: node } }], modifiers: [{ name: "flip", options: { boundary: node } }],
}, },
content: ([item]) => { content: ([item]) => {
//console.log(item.data())
const itemId = item.id(); const itemId = item.id();
//console.log(item.data())
//console.log(item.data().lastChild)
if (item.data().lastChild === NaN || item.data().lastChild === undefined) { if (item.data().lastChild === NaN || item.data().lastChild === undefined) {
return; return;
} }
@ -550,12 +612,14 @@ const clearDataAfterRemoveNode = () => {
const gearElement = document.createElement("div"); const gearElement = document.createElement("div");
gearElement.classList.add("popper-gear"); gearElement.classList.add("popper-gear");
gearElement.setAttribute("data-id", item.id()); gearElement.setAttribute("data-id", item.id());
gearElement.style.zIndex="1"
gearsContainer.current?.appendChild(gearElement); gearsContainer.current?.appendChild(gearElement);
// gearElement.addEventListener("click", () => { gearElement.addEventListener("mouseup", (e) => {
console.log("шестерня")
// setOpenedModalSettings( // setOpenedModalSettings(
// findQuestionById(quizId, node.id().split(" ").pop() || "").index // findQuestionById(quizId, node.id().split(" ").pop() || "").index
// ); // );
// }); });
return gearElement; return gearElement;
}, },
@ -636,85 +700,7 @@ const clearDataAfterRemoveNode = () => {
// elements={createGraphElements(tree, quiz)} // elements={createGraphElements(tree, quiz)}
style={{ height: "480px", background: "#F2F3F7" }} style={{ height: "480px", background: "#F2F3F7" }}
stylesheet={stylesheet} stylesheet={stylesheet}
layout={{ layout={(lyopts)}
name: 'preset',
positions: (e) => {
//console.log("идёт расчёт позиции")
const id = e.id()
const incomming = e.cy().edges(`[target="${id}"]`)
const layer = 0
e.removeData('lastChild')
if (incomming.length === 0) {
const children = e.cy().edges(`[source="${id}"]`)
e.data('layer', layer)
e.data('children', children.targets().length)
const queue = []
children.forEach(n => {
queue.push({ task: n.target(), layer: layer + 1 })
})
while (queue.length) {
const task = queue.pop()
task.task.data('layer', task.layer)
const children = e.cy().edges(`[source="${task.task.id()}"]`)
task.task.data('children', children.targets().length)
if (children.length !== 0) {
children.forEach(n => queue.push({ task: n.target(), layer: task.layer + 1 }))
}
}
queue.push({ parent: e, children: children.targets() })
while (queue.length) {
const task = queue.pop()
if (task.children.length === 0) {
task.parent.data('subtreeWidth', task.parent.height())
continue
}
const unprocessed = task?.children.filter(e => e.data('subtreeWidth') === undefined)
if (unprocessed.length !== 0) {
unprocessed.forEach(t => queue.push({ parent: t, children: t.cy().edges(`[source="${t.id()}"]`).targets() }))
continue
}
task?.parent.data('subtreeWidth', task.children.reduce((p, n) => p + n.data('subtreeWidth'), 0))
}
return { x: 200 * e.data('layer'), y: 0 }
} else {
const parent = e.cy().edges(`[target="${e.id()}"]`)[0].source()
//console.log('batya', parent)
// console.log(e.data('subtreeWidth'), e.id(),(parent.data('children')-1) )
const wing = parent.data('subtreeWidth') / 2
const lastOffset = parent.data('lastChild')
const step = wing * 2 / (parent.data('children') - 1)
console.log(parent.data('subtreeWidth'), e.id(), (parent.data('children') - 1), step, wing, e.data('layer'), parent.id(), lastOffset)
//e.removeData('subtreeWidth')
//console.log('poss', e.id(), 'children', parent.data('children'),'lo', lastOffset, 'v', wing)
if (lastOffset !== undefined) {
parent.data('lastChild', lastOffset + step)
//console.log('lastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChild')
// console.log('lastChild', lastOffset + step)
// return { x: 200 * e.data('layer'), y: (lastOffset + step) }
return { x: 200 * e.data('layer'), y: (lastOffset + step) }
} else {
parent.data('lastChild', parent.position().y - wing)
// console.log('lastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChildlastChild')
// console.log('lastChild', parent.position().y - wing)
// return { x: 200 * e.data('layer'), y: (parent.position().y - wing)}
return { x: 200 * e.data('layer'), y: (parent.position().y - wing) }
}
}
}, // map of (node id) => (position obj); or function(node){ return somPos; }
zoom: undefined, // the zoom level to set (prob want fit = false if set)
pan: undefined, // the pan level to set (prob want fit = false if set)
fit: false, // whether to fit to viewport
padding: 30, // padding on fit
animate: false, // whether to transition the node positions
animationDuration: 500, // duration of animation in ms if enabled
animationEasing: undefined, // easing of animation if enabled
animateFilter: function (node, i) { return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts
ready: readyLO, // callback on layoutready
// stop: (e) => console.log('stop', e), // callback on layoutstop
transform: function (node, position) { return position; } // transform a given node position. Useful for changing flow direction in discrete layouts
}}
cy={(cy) => { cy={(cy) => {
cyRef.current = cy; cyRef.current = cy;
}} }}

@ -4,6 +4,7 @@ interface Nodes {
data: { data: {
id: string; id: string;
label: string; label: string;
parent?: string;
} }
} }
interface Edges { interface Edges {
@ -24,6 +25,13 @@ export const storeToNodes = (questions: AnyQuizQuestion[]) => {
id: question.content.id, id: question.content.id,
label: question.title ? question.title : "noname" label: question.title ? question.title : "noname"
}}) }})
// nodes.push({
// data: {
// id: "delete" + question.content.id,
// label: "X",
// parent: question.content.id,
// }
// },)
if (question.content.rule.parentId !== "root") edges.push({data: { if (question.content.rule.parentId !== "root") edges.push({data: {
source: question.content.rule.parentId, source: question.content.rule.parentId,
target: question.content.id target: question.content.id

@ -55,7 +55,7 @@ export const QuestionsList = () => {
{questions.filter((q:AnyQuestion) => q.type).map(({ title, id, content }, index) => ( {questions.filter((q:AnyQuestion) => q.type).map(({ title, id, content }, index) => (
<Button <Button
onMouseDown={() => {//Разрешаем добавить этот вопрос если у него нет родителя (не добавляли ещё в дерево) onMouseDown={() => {//Разрешаем добавить этот вопрос если у него нет родителя (не добавляли ещё в дерево)
if (!content.rule.parentId) updateDragQuestionContentId(id) if (!content.rule.parentId) updateDragQuestionContentId(content.id)
}} }}
key={index} key={index}
sx={{ sx={{

@ -26,7 +26,6 @@ export default function QuestionsPage() {
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const [settingBranching, setSettingBranching] = useState<boolean>(false); const [settingBranching, setSettingBranching] = useState<boolean>(false);
if (!quiz) return null; if (!quiz) return null;
return ( return (
@ -102,7 +101,7 @@ export default function QuestionsPage() {
</Box> </Box>
</Box> </Box>
{createPortal(<QuizPreview />, document.body)} {createPortal(<QuizPreview />, document.body)}
{openedModalSettingsId !== null && <BranchingQuestions/>} {/* {openedModalSettingsId !== null && <BranchingQuestions/>} */}
</> </>
); );
} }

@ -126,6 +126,7 @@ export const updateQuestion = <T extends AnyTypedQuizQuestion>(
questionIndex: number, questionIndex: number,
recipe: (question: T) => void, recipe: (question: T) => void,
) => setProducedState(state => { ) => setProducedState(state => {
console.log("начинаю отправку fire квиза " )
const question = state.listQuestions[quizId][questionIndex] as T; const question = state.listQuestions[quizId][questionIndex] as T;
recipe(question); recipe(question);

@ -121,14 +121,12 @@ export const updateQuestion = (
questionId: string, questionId: string,
updateFn: (question: AnyTypedQuizQuestion) => void, updateFn: (question: AnyTypedQuizQuestion) => void,
) => { ) => {
console.log("вызвали запрос на изменение вопроса " + questionId)
setProducedState(state => { setProducedState(state => {
const question = state.questions.find(q => q.id === questionId) || state.questions.find(q => { const question = state.questions.find(q => q.id === questionId) || state.questions.find(q => q.content.id === questionId);
console.log(q)
return q.content.id === questionId
});
if (!question) return; if (!question) return;
if (question.type === null) throw new Error("Cannot update untyped question, use 'updateUntypedQuestion' instead"); if (question.type === null) throw new Error("Cannot update untyped question, use 'updateUntypedQuestion' instead");
console.log("question был найден")
updateFn(question); updateFn(question);
}, { }, {
type: "updateQuestion", type: "updateQuestion",
@ -136,12 +134,14 @@ export const updateQuestion = (
updateFn: updateFn.toString(), updateFn: updateFn.toString(),
}); });
clearTimeout(requestTimeoutId); // clearTimeout(requestTimeoutId);
requestTimeoutId = setTimeout(() => { // requestTimeoutId = setTimeout(() => {
requestQueue.enqueue(async () => { requestQueue.enqueue(async () => {
const q = useQuestionsStore.getState().questions.find(q => q.id === questionId); 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) return;
if (q.type === null) throw new Error("Cannot send update request for untyped question"); if (q.type === null) throw new Error("Cannot send update request for untyped question");
console.log(q.title)
const response = await questionApi.edit(questionToEditQuestionRequest(q)); const response = await questionApi.edit(questionToEditQuestionRequest(q));
@ -152,7 +152,7 @@ export const updateQuestion = (
devlog("Error editing question", { error, questionId }); devlog("Error editing question", { error, questionId });
enqueueSnackbar("Не удалось сохранить вопрос"); enqueueSnackbar("Не удалось сохранить вопрос");
}); });
}, REQUEST_DEBOUNCE); // }, REQUEST_DEBOUNCE);
}; };
export const addQuestionVariant = (questionId: string) => { export const addQuestionVariant = (questionId: string) => {
@ -430,7 +430,6 @@ function setProducedState<A extends string | { type: unknown; }>(
export const cleardragQuestionContentId = () => { export const cleardragQuestionContentId = () => {
console.log("чищу чищу")
useQuestionsStore.setState({dragQuestionContentId: null}); useQuestionsStore.setState({dragQuestionContentId: null});
}; };