добавление и удаление нод
This commit is contained in:
parent
7dc083907f
commit
fcd0f92259
13
package-lock.json
generated
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("записываю на бек ид родителя")
|
||||||
updateQuestion(targetQuestion.id, question => {
|
console.log({ parentNodeContentId, targetQuestion, parentNodeChildren })
|
||||||
|
//предупреждаем добавленный вопрос о том, кто его родитель
|
||||||
|
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 = () => {
|
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 = ""
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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,39 +488,51 @@ 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: {
|
||||||
placement: "left",
|
placement: "left",
|
||||||
modifiers: [{ name: "flip", options: { boundary: node } }],
|
modifiers: [{ name: "flip", options: { boundary: node } }],
|
||||||
},
|
},
|
||||||
content: ([item]) => {
|
content: ([item]) => {
|
||||||
const itemId = item.id();
|
const itemId = item.id();
|
||||||
const itemElement = layoutsContainer.current?.querySelector(
|
const itemElement = layoutsContainer.current?.querySelector(
|
||||||
`.popper-layout[data-id='${itemId}']`
|
`.popper-layout[data-id='${itemId}']`
|
||||||
);
|
);
|
||||||
if (itemElement) {
|
if (itemElement) {
|
||||||
return itemElement;
|
return itemElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
const layoutElement = document.createElement("div");
|
const layoutElement = document.createElement("div");
|
||||||
layoutElement.classList.add("popper-layout");
|
layoutElement.style.zIndex="0"
|
||||||
layoutElement.setAttribute("data-id", item.id());
|
layoutElement.classList.add("popper-layout");
|
||||||
// layoutElement.addEventListener("mouseup", () =>{}
|
layoutElement.setAttribute("data-id", item.id());
|
||||||
// // setStartCreate(node.id())
|
layoutElement.addEventListener("mouseup", () =>{
|
||||||
// );
|
alert("layout")
|
||||||
//console.log(layoutsContainer.current)
|
}
|
||||||
layoutsContainer.current?.appendChild(layoutElement);
|
// setStartCreate(node.id())
|
||||||
|
);
|
||||||
|
layoutsContainer.current?.appendChild(layoutElement);
|
||||||
|
|
||||||
return layoutElement;
|
return layoutElement;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const plusesPopper = node.popper({
|
const plusesPopper = node.popper({
|
||||||
popper: {
|
popper: {
|
||||||
@ -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) => {
|
||||||
// setOpenedModalSettings(
|
console.log("шестерня")
|
||||||
// findQuestionById(quizId, node.id().split(" ").pop() || "").index
|
// setOpenedModalSettings(
|
||||||
// );
|
// 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});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user