diff --git a/src/pages/Questions/BranchingMap/CsComponent.tsx b/src/pages/Questions/BranchingMap/CsComponent.tsx index 947ca5a8..ae97e350 100644 --- a/src/pages/Questions/BranchingMap/CsComponent.tsx +++ b/src/pages/Questions/BranchingMap/CsComponent.tsx @@ -1,12 +1,16 @@ import { useEffect, useLayoutEffect, useRef, useState } from "react"; import Cytoscape from "cytoscape"; -import { Button } from "@mui/material"; import CytoscapeComponent from "react-cytoscapejs"; import popper from "cytoscape-popper"; +import { Button } from "@mui/material"; +import { withErrorBoundary } from "react-error-boundary"; +import { enqueueSnackbar } from "notistack"; + 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 { useUiTools } from "@root/uiTools/store"; import { deleteQuestion, updateQuestion, @@ -16,7 +20,6 @@ import { } from "@root/questions/actions"; import { updateOpenedModalSettingsId } from "@root/uiTools/actions"; import { cleardragQuestionContentId } from "@root/uiTools/actions"; -import { withErrorBoundary } from "react-error-boundary"; import { useRemoveNode } from "./hooks/useRemoveNode"; import { usePopper } from "./hooks/usePopper"; @@ -26,42 +29,7 @@ import { stylesheet } from "./stylesheet"; import "./styles.css"; -import type { - Stylesheet, - Core, - NodeSingular, - AbstractEventObject, - ElementDefinition, - LayoutEventObject, -} from "cytoscape"; -import { enqueueSnackbar } from "notistack"; -import { useUiTools } from "@root/uiTools/store"; - -// type PopperItem = { -// id: () => string; -// }; - -// type Modifier = { -// name: string; -// options: unknown; -// }; - -// type PopperConfig = { -// popper: { -// placement: string; -// modifiers?: Modifier[]; -// }; -// content: (items: PopperItem[]) => void; -// }; - -// type Popper = { -// update: () => Promise; -// setOptions: (modifiers: { modifiers?: Modifier[] }) => void; -// }; - -// type NodeSingularWithPopper = NodeSingular & { -// popper: (config: PopperConfig) => Popper; -// }; +import type { Core } from "cytoscape"; Cytoscape.use(popper); @@ -251,115 +219,6 @@ function CsComponent({ } }; - // const removeNode = ({ targetNodeContentId }: { targetNodeContentId: string }) => { - // console.log("старт удаление") - // const deleteNodes: string[] = [] - // const deleteEdges: any = [] - // const cy = cyRef?.current - - // const findChildrenToDelete = (node) => { - - // //Узнаём грани, идущие от этой ноды - // cy?.$('edge[source = "' + node.id() + '"]')?.toArray().forEach((edge) => { - // const edgeData = edge.data() - - // //записываем id грани для дальнейшего удаления - // deleteEdges.push(edge) - // //ищем ноду на конце грани, записываем её ID для дальнейшего удаления - // const targetNode = cy?.$("#" + edgeData.target) - // deleteNodes.push(targetNode.data().id) - // //вызываем функцию для анализа потомков уже у этой ноды - // findChildrenToDelete(targetNode) - // }) - - // } - // findChildrenToDelete(cy?.getElementById(targetNodeContentId)) - - // const targetQuestion = getQuestionByContentId(targetNodeContentId) - - // if (targetQuestion.content.rule.parentId === "root" && quiz) { - // updateRootContentId(quiz?.id, "") - // updateQuestion(targetNodeContentId, question => { - // question.content.rule.parentId = "" - // question.content.rule.main = [] - // question.content.rule.children = [] - // question.content.rule.default = "" - // }) - // trashQuestions.forEach(q => { - // if (q.type === "result") { - // deleteQuestion(q.id); - // } - // }); - // clearRuleForAll() - - // } else { - - // const parentQuestionContentId = cy?.$('edge[target = "' + targetNodeContentId + '"]')?.toArray()?.[0]?.data()?.source - // if (targetNodeContentId && parentQuestionContentId) { - // if (cy?.edges(`[source="${parentQuestionContentId}"]`).length === 0) - // createFrontResult(quiz.backendId, parentQuestionContentId) - // clearDataAfterRemoveNode({ targetQuestionContentId: targetNodeContentId, parentQuestionContentId }) - // cy?.remove(cy?.$('#' + targetNodeContentId)).layout(lyopts).run() - // } - - // } - - // //После всех манипуляций удаляем грани и ноды из CS Чистим rule потомков на беке - - // deleteNodes.forEach((nodeId) => {//Ноды - // cy?.remove(cy?.$("#" + nodeId)) - // removeButtons(nodeId) - // updateQuestion(nodeId, question => { - // question.content.rule.parentId = "" - // question.content.rule.main = [] - // question.content.rule.default = "" - // question.content.rule.children = [] - // }) - - // }) - - // deleteEdges.forEach((edge: any) => {//Грани - // cy?.remove(edge) - // }) - - // removeButtons(targetNodeContentId) - // cy?.data('changed', true) - // cy?.layout(lyopts).run() - - // //удаляем result всех потомков - // trashQuestions.forEach((qr) => { - // if (qr.type === "result") { - // if (deleteNodes.includes(qr.content.rule.parentId) || qr.content.rule.parentId === targetQuestion.content.id) { - // deleteQuestion(qr.id); - // } - // } - // }) - // } - - // const clearDataAfterRemoveNode = ({ targetQuestionContentId, parentQuestionContentId }: { targetQuestionContentId: string, parentQuestionContentId: string }) => { - - // updateQuestion(targetQuestionContentId, question => { - // question.content.rule.parentId = "" - // question.content.rule.children = [] - // question.content.rule.main = [] - // question.content.rule.default = "" - // }) - - // //чистим rule родителя - // const parentQuestion = getQuestionByContentId(parentQuestionContentId) - // const newRule = {} - // const newChildren = [...parentQuestion.content.rule.children] - // newChildren.splice(parentQuestion.content.rule.children.indexOf(targetQuestionContentId), 1); - // newRule.main = parentQuestion.content.rule.main.filter((data) => data.next !== targetQuestionContentId) //удаляем условия перехода от родителя к этому вопросу - // newRule.parentId = parentQuestion.content.rule.parentId - // newRule.default = parentQuestion.content.rule.default === targetQuestionContentId ? "" : parentQuestion.content.rule.default - // newRule.children = newChildren - - // updateQuestion(parentQuestionContentId, (PQ) => { - // PQ.content.rule = newRule - // }) - // } - useEffect(() => { if (startCreate) { addNode({ parentNodeContentId: startCreate }); @@ -375,117 +234,6 @@ function CsComponent({ } }, [startRemove]); - // const readyLO = (e) => { - // 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('changed', false) - // e.cy.removeData('firstNode') - // } - - // //удаляем иконки - // e.cy.nodes().forEach((ele: any) => { - // const data = ele.data() - // data.id && removeButtons(data.id); - // }) - // initialPopperIcons(e) - // } - - // const lyopts = { - // name: 'preset', - - // positions: (e) => { - // if (!e.cy().data('changed')) { - // return e.data('oldPos') - // } - // const id = e.id() - // const incomming = e.cy().edges(`[target="${id}"]`) - // const layer = 0 - // e.removeData('lastChild') - - // if (incomming.length === 0) { - // if (e.cy().data('firstNode') === undefined) - // e.cy().data('firstNode', 'root') - // e.data('root', true) - // const children = e.cy().edges(`[source="${id}"]`).targets() - // e.data('layer', layer) - // e.data('children', children.length) - // const queue = [] - // children.forEach(n => { - // queue.push({ task: n, layer: layer + 1 }) - // }) - // while (queue.length) { - // const task = queue.pop() - // task.task.data('layer', task.layer) - // task.task.removeData('subtreeWidth') - // const children = e.cy().edges(`[source="${task.task.id()}"]`).targets() - // task.task.data('children', children.length) - // if (children.length !== 0) { - // children.forEach(n => queue.push({ task: n, layer: task.layer + 1 })) - // } - // } - // queue.push({ parent: e, children: children }) - // while (queue.length) { - // const task = queue.pop() - // if (task.children.length === 0) { - // task.parent.data('subtreeWidth', task.parent.height() + 50) - // 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)) - // } - - // const pos = { x: 0, y: 0 } - // e.data('oldPos', pos) - - // queue.push({ task: children, parent: e }) - // while (queue.length) { - // const task = queue.pop() - // const oldPos = task.parent.data('oldPos') - // let yoffset = oldPos.y - task.parent.data('subtreeWidth') / 2 - // task.task.forEach(n => { - // const width = n.data('subtreeWidth') - - // n.data('oldPos', { x: 250 * n.data('layer'), y: yoffset + width / 2 }) - // yoffset += width - // queue.push({ task: n.cy().edges(`[source="${n.id()}"]`).targets(), parent: n }) - // }) - // } - // e.cy().data('changed', false) - // return pos - // } else { - - // const opos = e.data('oldPos') - // if (opos) { - // return opos - // } - // } - // }, // 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 false; }, // 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(() => { document .querySelector("#root") @@ -516,293 +264,6 @@ function CsComponent({ }; }, []); - // const removeButtons = (id: string) => { - // layoutsContainer.current - // ?.querySelector(`.popper-layout[data-id='${id}']`) - // ?.remove(); - // plusesContainer.current - // ?.querySelector(`.popper-plus[data-id='${id}']`) - // ?.remove(); - // crossesContainer.current - // ?.querySelector(`.popper-cross[data-id='${id}']`) - // ?.remove(); - // gearsContainer.current - // ?.querySelector(`.popper-gear[data-id='${id}']`) - // ?.remove(); - // }; - - // const initialPopperIcons = ({ cy }: LayoutEventObject) => { - // const container = - // (document.body.querySelector( - // ".__________cytoscape_container" - // ) as HTMLDivElement) || null; - - // if (!container) { - // return; - // } - - // container.style.overflow = "hidden"; - - // if (!plusesContainer.current) { - // plusesContainer.current = document.createElement("div"); - // plusesContainer.current.setAttribute("id", "popper-pluses"); - // container.append(plusesContainer.current); - // } - // if (!crossesContainer.current) { - // crossesContainer.current = document.createElement("div"); - // crossesContainer.current.setAttribute("id", "popper-crosses"); - // container.append(crossesContainer.current); - // } - // if (!gearsContainer.current) { - // gearsContainer.current = document.createElement("div"); - // gearsContainer.current.setAttribute("id", "popper-gears"); - // container.append(gearsContainer.current); - // } - // if (!layoutsContainer.current) { - // layoutsContainer.current = document.createElement("div"); - // layoutsContainer.current.setAttribute("id", "popper-layouts"); - // container.append(layoutsContainer.current); - // } - - // const ext = cy.extent(); - // const nodesInView = cy.nodes().filter((n) => { - // const bb = n.boundingBox(); - // return ( - // bb.x2 > ext.x1 && bb.x1 < ext.x2 && bb.y2 > ext.y1 && bb.y1 < ext.y2 - // ); - // }); - - // nodesInView.toArray()?.forEach((item) => { - // const node = item as NodeSingularWithPopper; - - // const layoutsPopper = node.popper({ - // popper: { - // placement: "left", - // modifiers: [{ name: "flip", options: { boundary: node } }], - // }, - // content: ([item]) => { - // const itemId = item.id(); - // const itemElement = layoutsContainer.current?.querySelector( - // `.popper-layout[data-id='${itemId}']` - // ); - // if (itemElement) { - // return itemElement; - // } - - // const layoutElement = document.createElement("div"); - // layoutElement.style.zIndex = "0"; - // layoutElement.classList.add("popper-layout"); - // layoutElement.setAttribute("data-id", item.id()); - // layoutElement.addEventListener("mouseup", () => { - // //Узнаём грани, идущие от этой ноды - // setModalQuestionParentContentId(item.id()); - // setOpenedModalQuestions(true); - // }); - // layoutsContainer.current?.appendChild(layoutElement); - - // return layoutElement; - // }, - // }); - - // const plusesPopper = node.popper({ - // popper: { - // placement: "right", - // modifiers: [{ name: "flip", options: { boundary: node } }], - // }, - // content: ([item]) => { - // const itemId = item.id(); - // const itemElement = plusesContainer.current?.querySelector( - // `.popper-plus[data-id='${itemId}']` - // ); - // if (itemElement) { - // return itemElement; - // } - - // const plusElement = document.createElement("div"); - // plusElement.classList.add("popper-plus"); - // plusElement.setAttribute("data-id", item.id()); - // plusElement.style.zIndex = "1"; - // plusElement.addEventListener("mouseup", () => { - // setStartCreate(node.id()); - // }); - - // plusesContainer.current?.appendChild(plusElement); - - // return plusElement; - // }, - // }); - - // const crossesPopper = node.popper({ - // popper: { - // placement: "top-end", - // modifiers: [{ name: "flip", options: { boundary: node } }], - // }, - // content: ([item]) => { - // const itemId = item.id(); - // const itemElement = crossesContainer.current?.querySelector( - // `.popper-cross[data-id='${itemId}']` - // ); - // if (itemElement) { - // return itemElement; - // } - - // const crossElement = document.createElement("div"); - // crossElement.classList.add("popper-cross"); - // crossElement.setAttribute("data-id", item.id()); - // crossElement.style.zIndex = "2"; - // crossesContainer.current?.appendChild(crossElement); - // crossElement.addEventListener("mouseup", () => { - // setStartRemove(node.id()); - // }); - - // return crossElement; - // }, - // }); - // let gearsPopper: Popper | null = null; - // if (node.data().root !== true) { - // gearsPopper = node.popper({ - // popper: { - // placement: "left", - // modifiers: [{ name: "flip", options: { boundary: node } }], - // }, - // content: ([item]) => { - // const itemId = item.id(); - - // const itemElement = gearsContainer.current?.querySelector( - // `.popper-gear[data-id='${itemId}']` - // ); - // if (itemElement) { - // return itemElement; - // } - - // const gearElement = document.createElement("div"); - // gearElement.classList.add("popper-gear"); - // gearElement.setAttribute("data-id", item.id()); - // gearElement.style.zIndex = "1"; - // gearsContainer.current?.appendChild(gearElement); - // gearElement.addEventListener("mouseup", (e) => { - // console.log("up"); - // updateOpenedModalSettingsId(item.id()); - // }); - - // return gearElement; - // }, - // }); - // } - // const update = async () => { - // await plusesPopper.update(); - // await crossesPopper.update(); - // await gearsPopper?.update(); - // await layoutsPopper.update(); - // }; - - // const onZoom = (event: AbstractEventObject) => { - // const zoom = event.cy.zoom(); - - // //update(); - - // crossesPopper.setOptions({ - // modifiers: [ - // { name: "flip", options: { boundary: node } }, - // { name: "offset", options: { offset: [-5 * zoom, -30 * zoom] } }, - // ], - // }); - - // layoutsPopper.setOptions({ - // modifiers: [ - // { name: "flip", options: { boundary: node } }, - // { name: "offset", options: { offset: [0, -130 * zoom] } }, - // ], - // }); - // plusesPopper.setOptions({ - // modifiers: [ - // { name: "flip", options: { boundary: node } }, - // { name: "offset", options: { offset: [0, 0 * zoom] } }, - // ], - // }); - // gearsPopper?.setOptions({ - // modifiers: [ - // { name: "flip", options: { boundary: node } }, - // { name: "offset", options: { offset: [0, 0] } }, - // ], - // }); - - // layoutsContainer.current - // ?.querySelectorAll("#popper-layouts > .popper-layout") - // .forEach((item) => { - // const element = item as HTMLDivElement; - // element.style.width = `${130 * zoom}px`; - // element.style.height = `${130 * zoom}px`; - // }); - - // plusesContainer.current - // ?.querySelectorAll("#popper-pluses > .popper-plus") - // .forEach((item) => { - // const element = item as HTMLDivElement; - // element.style.width = `${40 * zoom}px`; - // element.style.height = `${40 * zoom}px`; - // element.style.fontSize = `${40 * zoom}px`; - // element.style.borderRadius = `${6 * zoom}px`; - // }); - - // crossesContainer.current - // ?.querySelectorAll("#popper-crosses > .popper-cross") - // .forEach((item) => { - // const element = item as HTMLDivElement; - // element.style.width = `${24 * zoom}px`; - // element.style.height = `${24 * zoom}px`; - // element.style.fontSize = `${24 * zoom}px`; - // element.style.borderRadius = `${6 * zoom}px`; - // }); - - // gearsContainer?.current - // ?.querySelectorAll("#popper-gears > .popper-gear") - // .forEach((item) => { - // const element = item as HTMLDivElement; - // element.style.width = `${60 * zoom}px`; - // element.style.height = `${40 * zoom}px`; - // }); - // }; - - // //node?.on("position", update); - // let pressed = false; - // let hide = false; - // cy?.on("mousedown", () => { - // pressed = true; - // }); - // cy?.on("mouseup", () => { - // pressed = false; - // hide = false; - - // const gc = gearsContainer.current; - // if (gc) gc.style.display = "block"; - // const pc = plusesContainer.current; - // const xc = crossesContainer.current; - // const lc = layoutsContainer.current; - // if (pc) pc.style.display = "block"; - // if (xc) xc.style.display = "block"; - // if (lc) lc.style.display = "block"; - // update(); - // }); - - // cy?.on("mousemove", () => { - // if (pressed && !hide) { - // hide = true; - // const gc = gearsContainer.current; - // if (gc) gc.style.display = "none"; - // const pc = plusesContainer.current; - // const xc = crossesContainer.current; - // const lc = layoutsContainer.current; - // if (pc) pc.style.display = "none"; - // if (xc) xc.style.display = "none"; - // if (lc) lc.style.display = "block"; - // } - // }); - - // cy?.on("zoom render", onZoom); - // }); - // }; - return ( <>