Merge branch 'dev' into 'staging'
fix branching graph unmount bug See merge request frontend/squiz!332
This commit is contained in:
commit
58dcba5ac8
@ -9,11 +9,9 @@ import {
|
||||
cleardragQuestionContentId,
|
||||
setModalQuestionParentContentId,
|
||||
setModalQuestionTargetContentId,
|
||||
updateModalInfoWhyCantCreate,
|
||||
updateOpenedModalSettingsId,
|
||||
} from "@root/uiTools/actions";
|
||||
import { useUiTools } from "@root/uiTools/store";
|
||||
import { ProblemIcon } from "@ui_kit/ProblemIcon";
|
||||
import type { Core } from "cytoscape";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { useEffect, useLayoutEffect, useMemo, useRef } from "react";
|
||||
@ -27,24 +25,16 @@ import "./style/styles.css";
|
||||
import { stylesheet } from "./style/stylesheet";
|
||||
|
||||
function CsComponent() {
|
||||
const desireToOpenABranchingModal = useUiTools(
|
||||
(state) => state.desireToOpenABranchingModal,
|
||||
);
|
||||
const canCreatePublic = useUiTools((state) => state.canCreatePublic);
|
||||
const modalQuestionParentContentId = useUiTools(
|
||||
(state) => state.modalQuestionParentContentId,
|
||||
);
|
||||
const modalQuestionTargetContentId = useUiTools(
|
||||
(state) => state.modalQuestionTargetContentId,
|
||||
);
|
||||
const desireToOpenABranchingModal = useUiTools((state) => state.desireToOpenABranchingModal);
|
||||
const modalQuestionParentContentId = useUiTools((state) => state.modalQuestionParentContentId);
|
||||
const modalQuestionTargetContentId = useUiTools((state) => state.modalQuestionTargetContentId);
|
||||
const trashQuestions = useQuestionsStore((state) => state.questions);
|
||||
const cyRef = useRef<Core | null>(null);
|
||||
const { removeNode } = useRemoveNode({ cyRef });
|
||||
|
||||
const csElements = useMemo(() => {
|
||||
const questions = trashQuestions.filter(
|
||||
(question): question is AnyTypedQuizQuestion =>
|
||||
question.type !== null && question.type !== "result",
|
||||
(question): question is AnyTypedQuizQuestion => question.type !== null && question.type !== "result"
|
||||
);
|
||||
|
||||
return storeToNodes(questions);
|
||||
@ -54,9 +44,7 @@ function CsComponent() {
|
||||
const cy = cyRef?.current;
|
||||
if (desireToOpenABranchingModal) {
|
||||
setTimeout(() => {
|
||||
cy
|
||||
?.getElementById(desireToOpenABranchingModal)
|
||||
?.data("eroticeyeblink", true);
|
||||
cy?.getElementById(desireToOpenABranchingModal)?.data("eroticeyeblink", true);
|
||||
}, 250);
|
||||
} else {
|
||||
cy?.elements().data("eroticeyeblink", false);
|
||||
@ -64,10 +52,7 @@ function CsComponent() {
|
||||
}, [desireToOpenABranchingModal]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
modalQuestionTargetContentId.length !== 0 &&
|
||||
modalQuestionParentContentId.length !== 0
|
||||
) {
|
||||
if (modalQuestionTargetContentId.length !== 0 && modalQuestionParentContentId.length !== 0) {
|
||||
if (!cyRef.current) return;
|
||||
|
||||
addNode({
|
||||
@ -93,12 +78,11 @@ function CsComponent() {
|
||||
cyRef.current?.layout(layoutOptions).run();
|
||||
cyRef.current?.fit(undefined, 70);
|
||||
},
|
||||
[csElements],
|
||||
[csElements]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<CsNodeButtons csElements={csElements} cyRef={cyRef} />
|
||||
<Box mb="20px">
|
||||
<Button
|
||||
sx={{
|
||||
@ -115,12 +99,19 @@ function CsComponent() {
|
||||
Выровнять
|
||||
</Button>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
position: "relative",
|
||||
height: "480px",
|
||||
background: "#F2F3F7",
|
||||
}}
|
||||
>
|
||||
<CytoscapeComponent
|
||||
wheelSensitivity={0.1}
|
||||
elements={csElements}
|
||||
style={{
|
||||
height: "480px",
|
||||
background: "#F2F3F7",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
stylesheet={stylesheet}
|
||||
@ -132,6 +123,8 @@ function CsComponent() {
|
||||
autounselectify={true}
|
||||
boxSelectionEnabled={false}
|
||||
/>
|
||||
<CsNodeButtons csElements={csElements} cyRef={cyRef} />
|
||||
</Box>
|
||||
<DeleteNodeModal removeNode={removeNode} />
|
||||
</>
|
||||
);
|
||||
|
||||
@ -8,29 +8,14 @@ import {
|
||||
updateOpenedModalSettingsId,
|
||||
} from "@root/uiTools/actions";
|
||||
import { Core, EventObject, NodeSingular } from "cytoscape";
|
||||
import {
|
||||
MutableRefObject,
|
||||
forwardRef,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import {
|
||||
addNode,
|
||||
isElementANode,
|
||||
isNodeInViewport,
|
||||
isQuestionProhibited,
|
||||
storeToNodes,
|
||||
} from "./helper";
|
||||
import { MutableRefObject, forwardRef, useEffect, useMemo, useRef } from "react";
|
||||
import { addNode, isElementANode, isNodeInViewport, isQuestionProhibited, storeToNodes } from "./helper";
|
||||
|
||||
const csButtonTypes = ["delete", "add", "settings", "select"] as const;
|
||||
|
||||
type CsButtonType = (typeof csButtonTypes)[number];
|
||||
|
||||
type CsNodeButtonsByType = Partial<
|
||||
Record<CsButtonType, HTMLButtonElement | null>
|
||||
>;
|
||||
type CsNodeButtonsByType = Partial<Record<CsButtonType, HTMLButtonElement | null>>;
|
||||
|
||||
type CsButtonsById = Record<string, CsNodeButtonsByType | undefined>;
|
||||
|
||||
@ -44,10 +29,7 @@ export default function CsNodeButtons({ csElements, cyRef }: Props) {
|
||||
|
||||
const buttons = useMemo(() => {
|
||||
const nodeElements = csElements.filter(isElementANode);
|
||||
buttonRefsById.current = nodeElements.reduce<CsButtonsById>(
|
||||
(acc, node) => ((acc[node.data.id] = {}), acc),
|
||||
{},
|
||||
);
|
||||
buttonRefsById.current = nodeElements.reduce<CsButtonsById>((acc, node) => ((acc[node.data.id] = {}), acc), {});
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@ -56,6 +38,10 @@ export default function CsNodeButtons({ csElements, cyRef }: Props) {
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
pointerEvents: "none",
|
||||
"> *": {
|
||||
pointerEvents: "auto",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{nodeElements.flatMap((csElement) => [
|
||||
@ -80,8 +66,7 @@ export default function CsNodeButtons({ csElements, cyRef }: Props) {
|
||||
cleardragQuestionContentId();
|
||||
}}
|
||||
/>,
|
||||
!csElement.data.isRoot &&
|
||||
!isQuestionProhibited(csElement.data.qtype) && (
|
||||
!csElement.data.isRoot && !isQuestionProhibited(csElement.data.qtype) && (
|
||||
<CsSettingsButton
|
||||
key={`settings-${csElement.data.id}`}
|
||||
ref={(r) => {
|
||||
@ -102,12 +87,7 @@ export default function CsNodeButtons({ csElements, cyRef }: Props) {
|
||||
}}
|
||||
onClick={() => {
|
||||
setModalQuestionParentContentId(csElement.data.id);
|
||||
setOpenedModalQuestions(
|
||||
!(
|
||||
isQuestionProhibited(csElement.data.type) &&
|
||||
csElement.data.children > 0
|
||||
),
|
||||
);
|
||||
setOpenedModalQuestions(!(isQuestionProhibited(csElement.data.type) && csElement.data.children > 0));
|
||||
}}
|
||||
/>,
|
||||
])}
|
||||
@ -150,10 +130,7 @@ export default function CsNodeButtons({ csElements, cyRef }: Props) {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const container = cyRef.current?.container();
|
||||
const buttonsPortal = container ? createPortal(buttons, container) : null;
|
||||
|
||||
return buttonsPortal;
|
||||
return buttons;
|
||||
}
|
||||
|
||||
const applyButtonStyleByType: Record<
|
||||
@ -162,10 +139,8 @@ const applyButtonStyleByType: Record<
|
||||
> = {
|
||||
delete(button, node, zoom) {
|
||||
const nodePosition = node.renderedPosition();
|
||||
const shiftX =
|
||||
node.renderedWidth() / 2 - (CLOSE_BUTTON_WIDTH / 2 + 6) * zoom;
|
||||
const shiftY =
|
||||
node.renderedHeight() / 2 - (CLOSE_BUTTON_HEIGHT / 2 + 6) * zoom;
|
||||
const shiftX = node.renderedWidth() / 2 - (CLOSE_BUTTON_WIDTH / 2 + 6) * zoom;
|
||||
const shiftY = node.renderedHeight() / 2 - (CLOSE_BUTTON_HEIGHT / 2 + 6) * zoom;
|
||||
|
||||
if (!isNodeInViewport(node, 100)) {
|
||||
return button.style.setProperty("display", "none");
|
||||
@ -176,7 +151,7 @@ const applyButtonStyleByType: Record<
|
||||
button.style.setProperty("top", `${nodePosition.y}px`);
|
||||
button.style.setProperty(
|
||||
"transform",
|
||||
`translate3d(calc(-50% + ${shiftX}px), calc(-50% - ${shiftY}px), 0) scale(${zoom})`,
|
||||
`translate3d(calc(-50% + ${shiftX}px), calc(-50% - ${shiftY}px), 0) scale(${zoom})`
|
||||
);
|
||||
},
|
||||
add(button, node, zoom) {
|
||||
@ -190,15 +165,11 @@ const applyButtonStyleByType: Record<
|
||||
button.style.setProperty("display", "flex");
|
||||
button.style.setProperty("left", `${nodePosition.x}px`);
|
||||
button.style.setProperty("top", `${nodePosition.y}px`);
|
||||
button.style.setProperty(
|
||||
"transform",
|
||||
`translate3d(calc(-50% + ${shiftX}px), -50%, 0) scale(${zoom})`,
|
||||
);
|
||||
button.style.setProperty("transform", `translate3d(calc(-50% + ${shiftX}px), -50%, 0) scale(${zoom})`);
|
||||
},
|
||||
settings(button, node, zoom) {
|
||||
const nodePosition = node.renderedPosition();
|
||||
const shiftX =
|
||||
-node.renderedWidth() / 2 - (SETTINGS_BUTTON_WIDTH / 2) * zoom;
|
||||
const shiftX = -node.renderedWidth() / 2 - (SETTINGS_BUTTON_WIDTH / 2) * zoom;
|
||||
|
||||
if (!isNodeInViewport(node, 100)) {
|
||||
return button.style.setProperty("display", "none");
|
||||
@ -207,10 +178,7 @@ const applyButtonStyleByType: Record<
|
||||
button.style.setProperty("display", "flex");
|
||||
button.style.setProperty("left", `${nodePosition.x}px`);
|
||||
button.style.setProperty("top", `${nodePosition.y}px`);
|
||||
button.style.setProperty(
|
||||
"transform",
|
||||
`translate3d(calc(-50% + ${shiftX}px), -50%, 0) scale(${zoom})`,
|
||||
);
|
||||
button.style.setProperty("transform", `translate3d(calc(-50% + ${shiftX}px), -50%, 0) scale(${zoom})`);
|
||||
},
|
||||
select(button, node, zoom) {
|
||||
const nodePosition = node.renderedPosition();
|
||||
@ -222,10 +190,7 @@ const applyButtonStyleByType: Record<
|
||||
button.style.setProperty("display", "flex");
|
||||
button.style.setProperty("left", `${nodePosition.x}px`);
|
||||
button.style.setProperty("top", `${nodePosition.y}px`);
|
||||
button.style.setProperty(
|
||||
"transform",
|
||||
`translate3d(-50%, -50%, 0) scale(${zoom})`,
|
||||
);
|
||||
button.style.setProperty("transform", `translate3d(-50%, -50%, 0) scale(${zoom})`);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -7,13 +7,10 @@ import { FirstNodeField } from "./FirstNodeField";
|
||||
|
||||
export const BranchingMap = () => {
|
||||
const quiz = useCurrentQuiz();
|
||||
const dragQuestionContentId = useUiTools(
|
||||
(state) => state.dragQuestionContentId,
|
||||
);
|
||||
const dragQuestionContentId = useUiTools((state) => state.dragQuestionContentId);
|
||||
|
||||
return (
|
||||
<Box
|
||||
id="cytoscape-container"
|
||||
sx={{
|
||||
overflow: "hidden",
|
||||
padding: "20px",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user