--
This commit is contained in:
parent
9a880f5b90
commit
2b38c15e3e
@ -3,9 +3,9 @@ import Cytoscape from "cytoscape";
|
||||
import CytoscapeComponent from "react-cytoscapejs";
|
||||
import popper from "cytoscape-popper";
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
|
||||
import { AnyQuizQuestion } from "@model/questionTypes/shared"
|
||||
import { useQuestionsStore } from "@root/questions/store";
|
||||
import { clearDragQuestionId } from "@root/questions/actions";
|
||||
import { clearDragQuestionId, getQuestionById, updateQuestion, updateOpenedModalSettingsId } from "@root/questions/actions";
|
||||
|
||||
import { storeToNodes } from "./helper";
|
||||
|
||||
@ -93,6 +93,7 @@ const stylesheet: Stylesheet[] = [
|
||||
Cytoscape.use(popper);
|
||||
|
||||
export const CsComponent = () => {
|
||||
console.log("Я существую")
|
||||
const quiz = useCurrentQuiz();
|
||||
|
||||
const { dragQuestionId, questions } = useQuestionsStore()
|
||||
@ -100,27 +101,53 @@ export const CsComponent = () => {
|
||||
const [startRemove, setStartRemove] = useState("");
|
||||
|
||||
const cyRef = useRef<Core | null>(null);
|
||||
const layoutsContainer = useRef<HTMLDivElement | null>(null);
|
||||
const plusesContainer = useRef<HTMLDivElement | null>(null);
|
||||
const crossesContainer = useRef<HTMLDivElement | null>(null);
|
||||
const gearsContainer = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
|
||||
|
||||
const addNode = ({ parentNodeId }: { parentNodeId: string }) => {
|
||||
const cy = cyRef?.current
|
||||
const parentNodeChildren = cy?.$('edge[source = "' + parentNodeId + '"]').length
|
||||
const targetQuestion = { ...getQuestionById(dragQuestionId) } as AnyQuizQuestion
|
||||
console.log(parentNodeChildren, parentNodeId)
|
||||
|
||||
if (targetQuestion && targetQuestion && parentNodeId && parentNodeChildren !== undefined) {
|
||||
cy?.add([
|
||||
{
|
||||
data: {
|
||||
id: targetQuestion.id,
|
||||
label: targetQuestion.title || "noname"
|
||||
}
|
||||
},
|
||||
{
|
||||
data: {
|
||||
source: parentNodeId,
|
||||
target: targetQuestion.id
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
//Если детей больше 1 - предупреждаем стор вопросов об открытии модалки ветвления
|
||||
// if (Object.keys(currentNode.children).length > 1) {
|
||||
// setOpenedModalSettings(question.index)
|
||||
// } else {
|
||||
// //Если ребёнок первый - добавляем его родителю как дефолтный
|
||||
// parentQuestion.question.content.rule.default = Object.keys(newNode)[0].split("_").pop()
|
||||
// updateQuestionsList(quiz, parentQuestion.index, parentQuestion.question);
|
||||
// }
|
||||
if (parentNodeChildren > 1) {
|
||||
updateOpenedModalSettingsId(parentNodeId)
|
||||
} else {
|
||||
//Если ребёнок первый - добавляем его родителю как дефолтный
|
||||
updateQuestion(parentNodeId, question => question.content.rule.default = targetQuestion.id)
|
||||
}
|
||||
|
||||
//предупреждаем добавленный вопрос о том, кто его родитель
|
||||
updateQuestion(targetQuestion.id, question => question.content.rule.parentId = parentNodeId)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
console.log(dragQuestionId)
|
||||
// cy?.add({
|
||||
|
||||
// })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -141,137 +168,12 @@ export const CsComponent = () => {
|
||||
useEffect(() => {
|
||||
document.querySelector("#root")?.addEventListener("mouseup", clearDragQuestionId);
|
||||
const cy = cyRef.current;
|
||||
//cy?.add(storeToNodes(questions))
|
||||
cy?.add(
|
||||
[
|
||||
{
|
||||
"data": {
|
||||
"id": "1",
|
||||
"label": "2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2",
|
||||
"label": "Вы идёте в школу"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 3",
|
||||
"label": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2 4",
|
||||
"label": "3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2 6",
|
||||
"label": "5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 3 5",
|
||||
"label": "4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 3 7",
|
||||
"label": "6"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2 6 9867874",
|
||||
"label": "7"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2 6 7398789",
|
||||
"label": "8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"id": "1 2 6 9484789",
|
||||
"label": "11"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1",
|
||||
"target": "1 2",
|
||||
"id": "c4881f18-03cf-4ed1-bbc4-1741007f11c5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1",
|
||||
"target": "1 3",
|
||||
"id": "3cc5a94a-0192-4ea2-bdc6-ce1a157b76d4"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 2",
|
||||
"target": "1 2 4",
|
||||
"id": "1baf1bc6-eb40-4c81-b137-27cdd3a15e60"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 2",
|
||||
"target": "1 2 6",
|
||||
"id": "78af38cc-7609-401c-bbff-ebdb3f67ec14"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 3",
|
||||
"target": "1 3 5",
|
||||
"id": "a1c80f9f-7c4b-455c-8ba9-ef5dce5522b5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 3",
|
||||
"target": "1 3 7",
|
||||
"id": "85ed3ee9-fdd1-4874-8e36-484db46bf1c5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 2 6",
|
||||
"target": "1 2 6 9867874",
|
||||
"id": "f139548a-abca-412b-9935-740f219a938d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 2 6",
|
||||
"target": "1 2 6 7398789",
|
||||
"id": "ec8dd60c-df49-447f-b85a-4ae00cde1ae9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"source": "1 2 6",
|
||||
"target": "1 2 6 9484789",
|
||||
"id": "9b5ecc61-d0ca-4872-a2a4-4fd72835345e"
|
||||
}
|
||||
}
|
||||
]
|
||||
)
|
||||
cy?.add(storeToNodes(questions))
|
||||
cy?.layout(ly).run()
|
||||
|
||||
return () => {
|
||||
document.querySelector("#root")?.removeEventListener("mouseup", clearDragQuestionId);
|
||||
layoutsContainer.current?.remove();
|
||||
plusesContainer.current?.remove();
|
||||
crossesContainer.current?.remove();
|
||||
gearsContainer.current?.remove();
|
||||
@ -280,6 +182,9 @@ export const CsComponent = () => {
|
||||
|
||||
|
||||
const removeButtons = (id: string) => {
|
||||
layoutsContainer.current
|
||||
?.querySelector(`.popper-layout[data-id='${id}']`)
|
||||
?.remove();
|
||||
plusesContainer.current
|
||||
?.querySelector(`.popper-plus[data-id='${id}']`)
|
||||
?.remove();
|
||||
@ -291,8 +196,99 @@ export const CsComponent = () => {
|
||||
?.remove();
|
||||
};
|
||||
|
||||
const initialCS = () => {
|
||||
const cy = cyRef.current;
|
||||
|
||||
|
||||
|
||||
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 [ly, setly] = useState<any>({
|
||||
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(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)
|
||||
if (e.data('layer') === 1)
|
||||
// console.log(e.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)
|
||||
return { x: 200 * e.data('layer'), y: (lastOffset + step) || 1 }
|
||||
} else {
|
||||
parent.data('lastChild', parent.position().y - wing)
|
||||
return { x: 200 * e.data('layer'), y: (parent.position().y - wing) || 200 }
|
||||
}
|
||||
}
|
||||
}, // 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
|
||||
})
|
||||
|
||||
|
||||
const initialPopperIcons = (e) => {
|
||||
const cy = e.cy
|
||||
|
||||
const container =
|
||||
(document.body.querySelector(
|
||||
".__________cytoscape_container"
|
||||
@ -304,6 +300,11 @@ export const CsComponent = () => {
|
||||
|
||||
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) {
|
||||
plusesContainer.current = document.createElement("div");
|
||||
plusesContainer.current.setAttribute("id", "popper-pluses");
|
||||
@ -320,11 +321,38 @@ export const CsComponent = () => {
|
||||
container.append(gearsContainer.current);
|
||||
}
|
||||
|
||||
|
||||
cy?.nodes()
|
||||
.toArray()
|
||||
?.forEach((item) => {
|
||||
const node = item as NodeSingularWithPopper;
|
||||
console.log(node)
|
||||
|
||||
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.classList.add("popper-layout");
|
||||
layoutElement.setAttribute("data-id", item.id());
|
||||
// layoutElement.addEventListener("mouseup", () =>{}
|
||||
// // setStartCreate(node.id())
|
||||
// );
|
||||
console.log(layoutsContainer.current)
|
||||
layoutsContainer.current?.appendChild(layoutElement);
|
||||
|
||||
return layoutElement;
|
||||
},
|
||||
});
|
||||
|
||||
const plusesPopper = node.popper({
|
||||
popper: {
|
||||
@ -343,10 +371,10 @@ export const CsComponent = () => {
|
||||
const plusElement = document.createElement("div");
|
||||
plusElement.classList.add("popper-plus");
|
||||
plusElement.setAttribute("data-id", item.id());
|
||||
plusElement.addEventListener("mouseup", () => {
|
||||
setStartCreate(node.id());
|
||||
});
|
||||
plusesContainer.current?.appendChild(plusElement);
|
||||
plusElement.addEventListener("mouseup", () =>
|
||||
setStartCreate(node.id())
|
||||
);
|
||||
|
||||
return plusElement;
|
||||
},
|
||||
@ -355,13 +383,7 @@ export const CsComponent = () => {
|
||||
const crossesPopper = node.popper({
|
||||
popper: {
|
||||
placement: "top-end",
|
||||
modifiers: [
|
||||
{ name: "flip", options: { boundary: node } },
|
||||
{
|
||||
name: "hide",
|
||||
options: { enabled: true },
|
||||
},
|
||||
],
|
||||
modifiers: [{ name: "flip", options: { boundary: node } }],
|
||||
},
|
||||
content: ([item]) => {
|
||||
const itemId = item.id();
|
||||
@ -376,29 +398,11 @@ export const CsComponent = () => {
|
||||
crossElement.classList.add("popper-cross");
|
||||
crossElement.setAttribute("data-id", item.id());
|
||||
crossesContainer.current?.appendChild(crossElement);
|
||||
crossElement.addEventListener("click", () => {
|
||||
|
||||
console.log('#' + node.id() + ' node', cy.edges('[source = "' + node.id() + '"]'))
|
||||
console.log('[source = "' + node.id() + '"]')
|
||||
console.log(cy?.collection)
|
||||
|
||||
// cy?.remove('[source = "'+node.id()+'"]')
|
||||
console.log("папа")
|
||||
console.log(cy?.$('[target = "' + node.id() + '"]').data().source)
|
||||
|
||||
|
||||
cy?.remove('#' + node.id())
|
||||
|
||||
// crossElement.addEventListener("click", () =>
|
||||
// setStartRemove(node.id())
|
||||
}
|
||||
|
||||
|
||||
);
|
||||
node.on('remove', evt => {
|
||||
console.log(cy.edges())
|
||||
// cy?.remove('#'+evt.target.target())
|
||||
})
|
||||
// );
|
||||
|
||||
console.log(crossElement)
|
||||
return crossElement;
|
||||
},
|
||||
});
|
||||
@ -409,10 +413,13 @@ export const CsComponent = () => {
|
||||
modifiers: [{ name: "flip", options: { boundary: node } }],
|
||||
},
|
||||
content: ([item]) => {
|
||||
console.log(item.data())
|
||||
const itemId = item.id();
|
||||
// if (item.id() === elements[0].data.id) {
|
||||
// return;
|
||||
// }
|
||||
console.log(item.data())
|
||||
console.log(item.data().lastChild)
|
||||
if (item.data().lastChild === NaN || item.data().lastChild === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const itemElement = gearsContainer.current?.querySelector(
|
||||
`.popper-gear[data-id='${itemId}']`
|
||||
@ -421,16 +428,17 @@ export const CsComponent = () => {
|
||||
return itemElement;
|
||||
}
|
||||
|
||||
const gearsElement = document.createElement("div");
|
||||
gearsElement.classList.add("popper-gear");
|
||||
gearsElement.setAttribute("data-id", item.id());
|
||||
gearsContainer.current?.appendChild(gearsElement);
|
||||
// gearsElement.addEventListener("click", () =>
|
||||
const gearElement = document.createElement("div");
|
||||
gearElement.classList.add("popper-gear");
|
||||
gearElement.setAttribute("data-id", item.id());
|
||||
gearsContainer.current?.appendChild(gearElement);
|
||||
// gearElement.addEventListener("click", () => {
|
||||
// setOpenedModalSettings(
|
||||
// findQuestionById(quiz, node.id().split("_").pop() || "").index
|
||||
// )
|
||||
// findQuestionById(quizId, node.id().split(" ").pop() || "").index
|
||||
// );
|
||||
return gearsElement;
|
||||
// });
|
||||
|
||||
return gearElement;
|
||||
},
|
||||
});
|
||||
|
||||
@ -438,6 +446,7 @@ export const CsComponent = () => {
|
||||
await plusesPopper.update();
|
||||
await crossesPopper.update();
|
||||
await gearsPopper.update();
|
||||
await layoutsPopper.update();
|
||||
};
|
||||
|
||||
const onZoom = (event: AbstractEventObject) => {
|
||||
@ -449,13 +458,24 @@ export const CsComponent = () => {
|
||||
modifiers: [
|
||||
{ name: "flip", options: { boundary: node } },
|
||||
{ name: "offset", options: { offset: [-5 * zoom, -30 * zoom] } },
|
||||
{
|
||||
name: "hide",
|
||||
options: { enabled: true },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
layoutsPopper.setOptions({
|
||||
modifiers: [
|
||||
{ name: "flip", options: { boundary: node } },
|
||||
{ name: "offset", options: { offset: [0, -130 * zoom] } },
|
||||
],
|
||||
});
|
||||
|
||||
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) => {
|
||||
@ -480,9 +500,8 @@ export const CsComponent = () => {
|
||||
?.querySelectorAll("#popper-gears > .popper-gear")
|
||||
.forEach((item) => {
|
||||
const element = item as HTMLDivElement;
|
||||
element.style.width = `${33 * zoom}px`;
|
||||
element.style.height = `${14 * zoom}px`;
|
||||
element.style.fontSize = `${24 * zoom}px`;
|
||||
element.style.width = `${60 * zoom}px`;
|
||||
element.style.height = `${40 * zoom}px`;
|
||||
});
|
||||
};
|
||||
|
||||
@ -497,79 +516,8 @@ export const CsComponent = () => {
|
||||
elements={[]}
|
||||
// elements={createGraphElements(tree, quiz)}
|
||||
style={{ height: "480px", background: "#F2F3F7" }}
|
||||
layout={{
|
||||
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 => 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(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)
|
||||
if (e.data('layer') === 1)
|
||||
console.log(e.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)
|
||||
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: 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: (e) => console.log('ready',e), // 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
|
||||
}}
|
||||
stylesheet={stylesheet}
|
||||
layout={ly}
|
||||
cy={(cy) => {
|
||||
cyRef.current = cy;
|
||||
}}
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import { Box } from "@mui/material"
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { updateDragQuestionId, updateQuestion } from "@root/questions/actions"
|
||||
import { updateRootInfo } from "@root/quizes/actions"
|
||||
import { useQuestionsStore } from "@root/questions/store"
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
export const FirstNodeField = () => {
|
||||
interface Props {
|
||||
setOpenedModalQuestionsId:(str: string|null) => void
|
||||
}
|
||||
export const FirstNodeField = ({setOpenedModalQuestionsId}:Props) => {
|
||||
const { dragQuestionId } = useQuestionsStore()
|
||||
const Container = useRef<HTMLDivElement | null>(null);
|
||||
const quiz = useCurrentQuiz();
|
||||
console.log(dragQuestionId)
|
||||
|
||||
|
||||
const newRootNode = () => {
|
||||
@ -32,6 +36,7 @@ console.log(dragQuestionId)
|
||||
|
||||
return (
|
||||
<Box
|
||||
onclick
|
||||
ref={Container}
|
||||
sx={{
|
||||
height: "100%",
|
||||
|
||||
@ -14,43 +14,22 @@ 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.id,
|
||||
label: question.title ? question.title : "noname"
|
||||
}})
|
||||
nodes.push({data:{
|
||||
id: "111",
|
||||
label: "111"
|
||||
}})
|
||||
nodes.push({data:{
|
||||
id: "222",
|
||||
label: "222"
|
||||
}})
|
||||
edges.push({data: {
|
||||
source: question.id,
|
||||
target: "111"
|
||||
}})
|
||||
nodes.push({data:{
|
||||
id: "333",
|
||||
label: "333"
|
||||
}})
|
||||
edges.push({data: {
|
||||
source: "111",
|
||||
target: "333"
|
||||
}})
|
||||
edges.push({data: {
|
||||
source: question.id,
|
||||
target: "222"
|
||||
}})
|
||||
if (question.content.rule.parentId !== "root") edges.push({data: {
|
||||
source: question.content.rule.parentId,
|
||||
target: question.id
|
||||
}})
|
||||
}
|
||||
})
|
||||
console.log([...nodes, ...edges])
|
||||
return [...nodes, ...edges];
|
||||
}
|
||||
@ -3,11 +3,13 @@ import { FirstNodeField } from "./FirstNodeField";
|
||||
import { CsComponent } from "./CsComponent";
|
||||
import { useQuestionsStore } from "@root/questions/store"
|
||||
import { useCurrentQuiz } from "@root/quizes/hooks";
|
||||
import { useState } from "react";
|
||||
|
||||
|
||||
export const BranchingMap = () => {
|
||||
const quiz = useCurrentQuiz();
|
||||
const { dragQuestionId } = useQuestionsStore()
|
||||
const [openedModalQuestionsId, setOpenedModalQuestionsId] = useState<string>()
|
||||
|
||||
return (
|
||||
<Box
|
||||
@ -28,7 +30,7 @@ export const BranchingMap = () => {
|
||||
quiz?.config.haveRoot ?
|
||||
<CsComponent />
|
||||
:
|
||||
<FirstNodeField />
|
||||
<FirstNodeField setOpenedModalQuestionsId={setOpenedModalQuestionsId} />
|
||||
|
||||
}
|
||||
</Box>
|
||||
|
||||
@ -4,6 +4,7 @@ import { ReactComponent as CheckedIcon } from "@icons/checked.svg";
|
||||
import { useQuestionsStore } from "@root/questions/store";
|
||||
import { updateDragQuestionId } from "@root/questions/actions";
|
||||
import { useEffect } from "react";
|
||||
import { AnyTypedQuizQuestion, UntypedQuizQuestion } from "@model/questionTypes/shared";
|
||||
|
||||
|
||||
const getItemStyle = (isDragging:any, draggableStyle:any) => ({
|
||||
@ -18,6 +19,7 @@ const getItemStyle = (isDragging:any, draggableStyle:any) => ({
|
||||
// styles we need to apply on draggables
|
||||
...draggableStyle
|
||||
});
|
||||
type AnyQuestion = UntypedQuizQuestion | AnyTypedQuizQuestion
|
||||
|
||||
export const QuestionsList = () => {
|
||||
const { questions } = useQuestionsStore()
|
||||
@ -49,7 +51,7 @@ export const QuestionsList = () => {
|
||||
}}
|
||||
>
|
||||
{/* тут нужно будет фильтровать с проверкой, что вопрос имеет тип*/}
|
||||
{questions.map(({ title, id, content }, index) => (
|
||||
{questions.filter((q:AnyQuestion) => q.type).map(({ title, id, content }, index) => (
|
||||
<Button
|
||||
onMouseDown={() => {//Разрешаем добавить этот вопрос если у него нет родителя (не добавляли ещё в дерево)
|
||||
if (!content.rule.parentId) updateDragQuestionId(id)
|
||||
|
||||
@ -427,6 +427,7 @@ function setProducedState<A extends string | { type: unknown; }>(
|
||||
|
||||
|
||||
export const clearDragQuestionId = () => {
|
||||
console.log("чищу чищу")
|
||||
useQuestionsStore.setState({dragQuestionId: null});
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user