2024-01-05 16:48:35 +00:00
|
|
|
import { devlog } from "@frontend/kitui";
|
2023-12-20 10:46:38 +00:00
|
|
|
import { AnyTypedQuizQuestion } from "@model/questionTypes/shared";
|
2024-01-10 18:23:38 +00:00
|
|
|
import { clearRuleForAll } from "@root/questions/actions";
|
2023-11-29 15:45:15 +00:00
|
|
|
import { useQuestionsStore } from "@root/questions/store";
|
2024-01-05 16:48:35 +00:00
|
|
|
import { updateRootContentId } from "@root/quizes/actions";
|
|
|
|
|
import { useCurrentQuiz } from "@root/quizes/hooks";
|
2024-05-14 15:23:04 +00:00
|
|
|
import AddIcon from "@mui/icons-material/Add";
|
|
|
|
|
import RemoveIcon from "@mui/icons-material/Remove";
|
2023-12-20 18:38:28 +00:00
|
|
|
import {
|
2024-02-23 14:07:44 +00:00
|
|
|
cleardragQuestionContentId,
|
|
|
|
|
setModalQuestionParentContentId,
|
|
|
|
|
setModalQuestionTargetContentId,
|
2023-12-31 02:53:25 +00:00
|
|
|
updateOpenedModalSettingsId,
|
2023-12-20 18:38:28 +00:00
|
|
|
} from "@root/uiTools/actions";
|
2024-01-05 16:48:35 +00:00
|
|
|
import { useUiTools } from "@root/uiTools/store";
|
2024-01-10 18:23:38 +00:00
|
|
|
import type { Core } from "cytoscape";
|
2024-01-05 16:48:35 +00:00
|
|
|
import { enqueueSnackbar } from "notistack";
|
2024-01-10 18:23:38 +00:00
|
|
|
import { useEffect, useLayoutEffect, useMemo, useRef } from "react";
|
2024-01-05 16:48:35 +00:00
|
|
|
import CytoscapeComponent from "react-cytoscapejs";
|
|
|
|
|
import { withErrorBoundary } from "react-error-boundary";
|
|
|
|
|
import { DeleteNodeModal } from "../DeleteNodeModal";
|
2024-01-17 15:42:25 +00:00
|
|
|
import CsNodeButtons from "./CsNodeButtons";
|
2024-01-10 18:23:38 +00:00
|
|
|
import { addNode, layoutOptions, storeToNodes } from "./helper";
|
2023-12-20 17:31:51 +00:00
|
|
|
import { useRemoveNode } from "./hooks/useRemoveNode";
|
2023-12-20 18:38:28 +00:00
|
|
|
import "./style/styles.css";
|
2024-01-05 16:48:35 +00:00
|
|
|
import { stylesheet } from "./style/stylesheet";
|
2024-05-14 15:23:04 +00:00
|
|
|
import { Box, Button, useMediaQuery, useTheme } from "@mui/material";
|
|
|
|
|
import { AlignIcon } from "@icons/questionsPage/AlignIcon";
|
|
|
|
|
import { ExpandIcon } from "@icons/questionsPage/ExpandIcon";
|
2023-11-29 15:45:15 +00:00
|
|
|
|
2024-01-05 16:48:35 +00:00
|
|
|
function CsComponent() {
|
2024-05-14 15:23:04 +00:00
|
|
|
const theme = useTheme();
|
|
|
|
|
const isMobile = useMediaQuery(theme.breakpoints.down(660));
|
2024-02-23 14:07:44 +00:00
|
|
|
const desireToOpenABranchingModal = useUiTools(
|
|
|
|
|
(state) => state.desireToOpenABranchingModal,
|
2023-12-31 02:53:25 +00:00
|
|
|
);
|
2024-02-23 14:07:44 +00:00
|
|
|
const canCreatePublic = useUiTools((state) => state.canCreatePublic);
|
|
|
|
|
const modalQuestionParentContentId = useUiTools(
|
|
|
|
|
(state) => state.modalQuestionParentContentId,
|
|
|
|
|
);
|
|
|
|
|
const modalQuestionTargetContentId = useUiTools(
|
|
|
|
|
(state) => state.modalQuestionTargetContentId,
|
|
|
|
|
);
|
|
|
|
|
const trashQuestions = useQuestionsStore((state) => state.questions);
|
2023-11-29 15:45:15 +00:00
|
|
|
const cyRef = useRef<Core | null>(null);
|
2024-02-23 14:07:44 +00:00
|
|
|
const { removeNode } = useRemoveNode({ cyRef });
|
2023-12-20 17:31:51 +00:00
|
|
|
|
2024-02-23 14:07:44 +00:00
|
|
|
const csElements = useMemo(() => {
|
|
|
|
|
const questions = trashQuestions.filter(
|
|
|
|
|
(question): question is AnyTypedQuizQuestion =>
|
|
|
|
|
question.type !== null && question.type !== "result",
|
|
|
|
|
);
|
|
|
|
|
return storeToNodes(questions);
|
|
|
|
|
}, [trashQuestions]);
|
2023-12-31 10:36:30 +00:00
|
|
|
|
2023-12-05 23:34:40 +00:00
|
|
|
useLayoutEffect(() => {
|
2023-12-31 02:53:25 +00:00
|
|
|
const cy = cyRef?.current;
|
2023-12-05 23:34:40 +00:00
|
|
|
if (desireToOpenABranchingModal) {
|
2023-12-07 00:03:43 +00:00
|
|
|
setTimeout(() => {
|
2023-12-31 02:53:25 +00:00
|
|
|
cy
|
|
|
|
|
?.getElementById(desireToOpenABranchingModal)
|
|
|
|
|
?.data("eroticeyeblink", true);
|
|
|
|
|
}, 250);
|
2023-12-05 23:34:40 +00:00
|
|
|
} else {
|
2023-12-31 02:53:25 +00:00
|
|
|
cy?.elements().data("eroticeyeblink", false);
|
2023-12-05 23:34:40 +00:00
|
|
|
}
|
2023-12-31 02:53:25 +00:00
|
|
|
}, [desireToOpenABranchingModal]);
|
2024-01-05 16:48:35 +00:00
|
|
|
|
2023-12-02 13:11:57 +00:00
|
|
|
useEffect(() => {
|
2023-12-31 02:53:25 +00:00
|
|
|
if (
|
|
|
|
|
modalQuestionTargetContentId.length !== 0 &&
|
|
|
|
|
modalQuestionParentContentId.length !== 0
|
|
|
|
|
) {
|
2024-02-23 14:07:44 +00:00
|
|
|
if (!cyRef.current) return;
|
2024-01-05 16:48:35 +00:00
|
|
|
|
2023-12-31 02:53:25 +00:00
|
|
|
addNode({
|
|
|
|
|
parentNodeContentId: modalQuestionParentContentId,
|
|
|
|
|
targetNodeContentId: modalQuestionTargetContentId,
|
|
|
|
|
});
|
2023-12-02 13:11:57 +00:00
|
|
|
}
|
2023-12-31 02:53:25 +00:00
|
|
|
setModalQuestionParentContentId("");
|
|
|
|
|
setModalQuestionTargetContentId("");
|
|
|
|
|
}, [modalQuestionTargetContentId]);
|
|
|
|
|
|
2024-02-23 14:07:44 +00:00
|
|
|
useEffect(function onMount() {
|
|
|
|
|
updateOpenedModalSettingsId();
|
|
|
|
|
document.addEventListener("pointerup", cleardragQuestionContentId);
|
2023-11-29 15:45:15 +00:00
|
|
|
|
|
|
|
|
return () => {
|
2024-02-23 14:07:44 +00:00
|
|
|
document.removeEventListener("pointerup", cleardragQuestionContentId);
|
2023-11-29 15:45:15 +00:00
|
|
|
};
|
2024-02-23 14:07:44 +00:00
|
|
|
}, []);
|
2024-01-05 16:48:35 +00:00
|
|
|
|
2024-02-23 14:07:44 +00:00
|
|
|
useEffect(
|
|
|
|
|
function rerunLayout() {
|
|
|
|
|
cyRef.current?.layout(layoutOptions).run();
|
|
|
|
|
cyRef.current?.fit(undefined, 70);
|
|
|
|
|
},
|
|
|
|
|
[csElements],
|
|
|
|
|
);
|
2023-11-29 15:45:15 +00:00
|
|
|
|
|
|
|
|
return (
|
2024-05-14 15:23:04 +00:00
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
width: "100%",
|
|
|
|
|
}}
|
|
|
|
|
>
|
2024-02-23 14:07:44 +00:00
|
|
|
<CsNodeButtons csElements={csElements} cyRef={cyRef} />
|
2024-05-14 15:23:04 +00:00
|
|
|
<Box sx={{ position: "relative" }}>
|
|
|
|
|
<Box
|
2023-12-19 15:00:51 +00:00
|
|
|
sx={{
|
2024-05-14 15:23:04 +00:00
|
|
|
position: "absolute",
|
|
|
|
|
bottom: isMobile ? "15px" : "20px",
|
|
|
|
|
left: isMobile ? "15px" : "20px",
|
|
|
|
|
display: "flex",
|
|
|
|
|
gap: "10px",
|
2023-12-19 15:00:51 +00:00
|
|
|
}}
|
2024-05-14 15:23:04 +00:00
|
|
|
>
|
|
|
|
|
<Button
|
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
minWidth: "36px",
|
|
|
|
|
width: "36px",
|
|
|
|
|
height: "36px",
|
|
|
|
|
background: "#9A9AAF",
|
|
|
|
|
opacity: "0.7",
|
|
|
|
|
zIndex: 2,
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
cyRef.current?.zoom(1);
|
|
|
|
|
cyRef.current?.center();
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<ExpandIcon />
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
minWidth: "36px",
|
|
|
|
|
width: "36px",
|
|
|
|
|
height: "36px",
|
|
|
|
|
background: "#9A9AAF",
|
|
|
|
|
opacity: "0.7",
|
|
|
|
|
zIndex: 2,
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
cyRef.current?.fit(undefined, 70);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<AlignIcon />
|
|
|
|
|
</Button>
|
|
|
|
|
</Box>
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
position: "absolute",
|
|
|
|
|
bottom: isMobile ? "15px" : "20px",
|
|
|
|
|
right: isMobile ? "15px" : "20px",
|
|
|
|
|
display: "flex",
|
|
|
|
|
flexDirection: "column",
|
|
|
|
|
gap: "10px",
|
|
|
|
|
background: "#EEE4FC",
|
|
|
|
|
padding: "16px",
|
|
|
|
|
borderRadius: "8px",
|
|
|
|
|
zIndex: 2,
|
2024-02-23 14:07:44 +00:00
|
|
|
}}
|
2023-12-19 15:00:51 +00:00
|
|
|
>
|
2024-05-14 15:23:04 +00:00
|
|
|
<Button
|
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
minWidth: "36px",
|
|
|
|
|
width: "36px",
|
|
|
|
|
height: "36px",
|
|
|
|
|
background: "#7E2AEA",
|
|
|
|
|
fontSize: "16px",
|
|
|
|
|
color: "#fff",
|
|
|
|
|
zIndex: 2,
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
const currentZoom = cyRef.current?.zoom() || 1;
|
|
|
|
|
cyRef.current?.zoom(currentZoom + 0.1);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<AddIcon />
|
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
sx={{
|
|
|
|
|
display: "flex",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
minWidth: "36px",
|
|
|
|
|
width: "36px",
|
|
|
|
|
height: "36px",
|
|
|
|
|
background: "#7E2AEA",
|
|
|
|
|
fontSize: "16px",
|
|
|
|
|
color: "#fff",
|
|
|
|
|
zIndex: 2,
|
|
|
|
|
}}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
const currentZoom = cyRef.current?.zoom() || 1;
|
|
|
|
|
cyRef.current?.zoom(currentZoom - 0.1);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<RemoveIcon />
|
|
|
|
|
</Button>
|
|
|
|
|
</Box>
|
|
|
|
|
<CytoscapeComponent
|
|
|
|
|
wheelSensitivity={0.1}
|
|
|
|
|
elements={csElements}
|
|
|
|
|
style={{
|
|
|
|
|
height: isMobile ? "327px" : "481px",
|
|
|
|
|
background: "#F2F3F7",
|
|
|
|
|
overflow: "hidden",
|
|
|
|
|
borderRadius: "12px",
|
|
|
|
|
width: "100%",
|
|
|
|
|
}}
|
|
|
|
|
stylesheet={stylesheet}
|
|
|
|
|
layout={layoutOptions}
|
|
|
|
|
cy={(cy) => {
|
|
|
|
|
cyRef.current = cy;
|
|
|
|
|
}}
|
|
|
|
|
autoungrabify={true}
|
|
|
|
|
autounselectify={true}
|
|
|
|
|
boxSelectionEnabled={false}
|
|
|
|
|
/>
|
2023-12-19 15:00:51 +00:00
|
|
|
</Box>
|
2023-12-21 14:56:29 +00:00
|
|
|
<DeleteNodeModal removeNode={removeNode} />
|
2024-05-14 15:23:04 +00:00
|
|
|
</Box>
|
2023-11-29 15:45:15 +00:00
|
|
|
);
|
2023-12-31 02:53:25 +00:00
|
|
|
}
|
2023-12-07 00:03:43 +00:00
|
|
|
|
2023-12-11 10:08:54 +00:00
|
|
|
function Clear() {
|
|
|
|
|
const quiz = useCurrentQuiz();
|
2023-12-21 14:56:29 +00:00
|
|
|
if (quiz) {
|
|
|
|
|
updateRootContentId(quiz?.id, "");
|
|
|
|
|
}
|
2023-12-31 02:53:25 +00:00
|
|
|
clearRuleForAll();
|
|
|
|
|
return <></>;
|
2023-12-07 00:03:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default withErrorBoundary(CsComponent, {
|
2023-12-11 10:08:54 +00:00
|
|
|
fallback: <Clear />,
|
2023-12-07 00:03:43 +00:00
|
|
|
onError: (error, info) => {
|
2023-12-31 02:53:25 +00:00
|
|
|
enqueueSnackbar("Дерево порвалось");
|
2024-02-23 14:07:44 +00:00
|
|
|
devlog(info);
|
|
|
|
|
devlog(error);
|
2023-12-07 00:03:43 +00:00
|
|
|
},
|
2023-12-09 19:31:06 +00:00
|
|
|
});
|