@lv-x-software-house/x_view 1.2.4 → 1.2.5-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1684 -815
- package/dist/index.mjs +1691 -816
- package/package.json +52 -43
package/dist/index.js
CHANGED
|
@@ -446,11 +446,18 @@ function ContextMenu({
|
|
|
446
446
|
))));
|
|
447
447
|
};
|
|
448
448
|
const renderAncestryActionsView = () => {
|
|
449
|
+
var _a2, _b2;
|
|
449
450
|
const ancestryTitle = (selectedAncestry == null ? void 0 : selectedAncestry.name) || `Ancestralidade #${selectedAncestry == null ? void 0 : selectedAncestry.ancestry_id.substring(0, 8)}`;
|
|
450
|
-
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: ancestryTitle }, ancestryTitle))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("read", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
451
|
-
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry);
|
|
451
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center justify-between gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => setMenuView("connections"), className: "p-1 rounded-full hover:bg-white/10 text-slate-400 hover:text-white flex-shrink-0" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("polyline", { points: "15 18 9 12 15 6" }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400 truncate", title: ancestryTitle }, ancestryTitle))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col gap-1" }, ability.can("read", "Ancestry") && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
452
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "full");
|
|
453
|
+
onClose();
|
|
454
|
+
}, className: baseButtonClass, title: "Renderizar Ancestralidade Completa" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" }), /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Renderizar Ancestralidade")), /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
455
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "ancestry_only");
|
|
452
456
|
onClose();
|
|
453
|
-
}, className: baseButtonClass, title: "Renderizar Ancestralidade" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("
|
|
457
|
+
}, className: baseButtonClass, title: "Renderizar apenas a \xC1rvore de Ancestralidade (Radial)" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 2v3m0 14v3m10-10h-3m-14 0H2m15.66-6.34-2.12 2.12m-9.08 9.08-2.12 2.12m13.32 0-2.12-2.12m-9.08-9.08-2.12-2.12" })), /* @__PURE__ */ import_react.default.createElement("span", null, "\xC1rvore de Ancestralidade")), ((_b2 = (_a2 = selectedAncestry == null ? void 0 : selectedAncestry.abstraction_tree) == null ? void 0 : _a2.children) == null ? void 0 : _b2.length) > 0 && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
458
|
+
onRenderAncestry == null ? void 0 : onRenderAncestry(selectedAncestry, "abstraction_only");
|
|
459
|
+
onClose();
|
|
460
|
+
}, className: baseButtonClass, title: "Renderizar apenas a \xC1rvore de Abstra\xE7\xE3o (Vertical)" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ import_react.default.createElement("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 6.5h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M10 17.5h4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M6.5 10v4" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M17.5 10v4" })), /* @__PURE__ */ import_react.default.createElement("span", null, "\xC1rvore de Abstra\xE7\xE3o"))), ability.can("update", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
454
461
|
onEditAncestry == null ? void 0 : onEditAncestry(selectedAncestry);
|
|
455
462
|
onClose();
|
|
456
463
|
}, className: baseButtonClass, title: "Editar Ancestralidade" }, /* @__PURE__ */ import_react.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 20h9" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })), /* @__PURE__ */ import_react.default.createElement("span", null, "Editar Ancestralidade")), (ability.can("update", "Ancestry") || ability.can("delete", "Ancestry")) && /* @__PURE__ */ import_react.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), ability.can("delete", "Ancestry") && /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => {
|
|
@@ -9890,7 +9897,6 @@ var GroupItem = ({
|
|
|
9890
9897
|
onPlayAncestry,
|
|
9891
9898
|
availableIds,
|
|
9892
9899
|
canEdit
|
|
9893
|
-
// [NOVO] Recebe permissão de edição
|
|
9894
9900
|
}) => {
|
|
9895
9901
|
const canIndent = index > 0;
|
|
9896
9902
|
const isPickingForThisGroup = pickingGroupId === group.id;
|
|
@@ -9905,107 +9911,126 @@ var GroupItem = ({
|
|
|
9905
9911
|
(0, import_react25.useEffect)(() => {
|
|
9906
9912
|
adjustHeight();
|
|
9907
9913
|
}, [group.text]);
|
|
9908
|
-
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
9914
|
+
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
9915
|
+
"div",
|
|
9916
|
+
{
|
|
9917
|
+
className: `
|
|
9909
9918
|
flex flex-col gap-2 py-2 px-3 transition-all duration-200
|
|
9910
9919
|
${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
|
|
9911
|
-
`
|
|
9912
|
-
|
|
9913
|
-
|
|
9914
|
-
|
|
9915
|
-
className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
|
|
9916
|
-
rows: 1,
|
|
9917
|
-
style: {
|
|
9918
|
-
minHeight: "1.5rem",
|
|
9919
|
-
maxHeight: "250px"
|
|
9920
|
-
},
|
|
9921
|
-
placeholder: canEdit ? "Escreva sobre este grupo..." : "",
|
|
9922
|
-
value: group.text,
|
|
9923
|
-
readOnly: !canEdit,
|
|
9924
|
-
onChange: (e) => {
|
|
9925
|
-
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9926
|
-
}
|
|
9927
|
-
}
|
|
9928
|
-
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9929
|
-
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9930
|
-
return /* @__PURE__ */ import_react25.default.createElement(
|
|
9931
|
-
"div",
|
|
9920
|
+
`
|
|
9921
|
+
},
|
|
9922
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
9923
|
+
"textarea",
|
|
9932
9924
|
{
|
|
9933
|
-
|
|
9934
|
-
className: `
|
|
9925
|
+
ref: textareaRef,
|
|
9926
|
+
className: `w-full bg-transparent text-sm text-slate-200 placeholder-slate-600 resize-none focus:outline-none focus:placeholder-slate-500 overflow-y-auto ${!canEdit ? "cursor-default" : ""}`,
|
|
9927
|
+
rows: 1,
|
|
9928
|
+
style: {
|
|
9929
|
+
minHeight: "1.5rem",
|
|
9930
|
+
maxHeight: "250px"
|
|
9931
|
+
},
|
|
9932
|
+
placeholder: canEdit ? "Escreva sobre este grupo..." : "",
|
|
9933
|
+
value: group.text,
|
|
9934
|
+
readOnly: !canEdit,
|
|
9935
|
+
onChange: (e) => {
|
|
9936
|
+
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9937
|
+
}
|
|
9938
|
+
}
|
|
9939
|
+
),
|
|
9940
|
+
group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9941
|
+
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9942
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
9943
|
+
"div",
|
|
9944
|
+
{
|
|
9945
|
+
key: anc.ancestry_id,
|
|
9946
|
+
className: `
|
|
9935
9947
|
flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
|
|
9936
9948
|
${isValid ? "bg-slate-800/60 border-white/10 hover:border-indigo-500/30 text-slate-200" : "bg-red-900/10 border-red-500/30 text-red-300/70 hover:bg-red-900/20"}
|
|
9937
9949
|
`,
|
|
9938
|
-
|
|
9939
|
-
|
|
9940
|
-
|
|
9941
|
-
|
|
9950
|
+
title: isValid ? "" : "Esta ancestralidade foi removida ou n\xE3o existe mais."
|
|
9951
|
+
},
|
|
9952
|
+
isValid ? (
|
|
9953
|
+
// [MANTIDO] Botão Play visível para todos
|
|
9954
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
9955
|
+
"button",
|
|
9956
|
+
{
|
|
9957
|
+
onClick: () => onPlayAncestry(anc.ancestry_id),
|
|
9958
|
+
className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
|
|
9959
|
+
title: "Renderizar no cen\xE1rio"
|
|
9960
|
+
},
|
|
9961
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
|
|
9962
|
+
)
|
|
9963
|
+
) : /* @__PURE__ */ import_react25.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiAlertTriangle, { size: 10 })),
|
|
9942
9964
|
/* @__PURE__ */ import_react25.default.createElement(
|
|
9965
|
+
"span",
|
|
9966
|
+
{
|
|
9967
|
+
className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
|
|
9968
|
+
},
|
|
9969
|
+
anc.name
|
|
9970
|
+
),
|
|
9971
|
+
canEdit && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
9972
|
+
"div",
|
|
9973
|
+
{
|
|
9974
|
+
className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
|
|
9975
|
+
}
|
|
9976
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
9943
9977
|
"button",
|
|
9944
9978
|
{
|
|
9945
|
-
onClick: () =>
|
|
9946
|
-
className: "text-
|
|
9947
|
-
title: "
|
|
9979
|
+
onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
|
|
9980
|
+
className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
|
|
9981
|
+
title: "Remover men\xE7\xE3o"
|
|
9948
9982
|
},
|
|
9949
|
-
/* @__PURE__ */ import_react25.default.createElement(import_fi19.
|
|
9950
|
-
)
|
|
9951
|
-
)
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
title: "Remover men\xE7\xE3o"
|
|
9959
|
-
},
|
|
9960
|
-
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiX, { size: 12 })
|
|
9961
|
-
))
|
|
9962
|
-
);
|
|
9963
|
-
})), canEdit && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
9964
|
-
"button",
|
|
9965
|
-
{
|
|
9966
|
-
onClick: () => onRequestPickAncestry(group.id),
|
|
9967
|
-
className: `
|
|
9983
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiX, { size: 12 })
|
|
9984
|
+
))
|
|
9985
|
+
);
|
|
9986
|
+
})),
|
|
9987
|
+
canEdit && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
9988
|
+
"button",
|
|
9989
|
+
{
|
|
9990
|
+
onClick: () => onRequestPickAncestry(group.id),
|
|
9991
|
+
className: `
|
|
9968
9992
|
flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
|
|
9969
9993
|
${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
|
|
9970
9994
|
`,
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
9995
|
+
title: "Adicionar Ancestralidade a este grupo"
|
|
9996
|
+
},
|
|
9997
|
+
isPickingForThisGroup ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiSearch, { size: 12 }),
|
|
9998
|
+
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
9999
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
10000
|
+
"button",
|
|
10001
|
+
{
|
|
10002
|
+
onClick: () => onAddSubgroup(group.id),
|
|
10003
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
10004
|
+
title: "Criar Subgrupo"
|
|
10005
|
+
},
|
|
10006
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 14 })
|
|
10007
|
+
)), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10008
|
+
"button",
|
|
10009
|
+
{
|
|
10010
|
+
onClick: () => onIndent(group.id),
|
|
10011
|
+
disabled: !canIndent,
|
|
10012
|
+
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
10013
|
+
title: "Aninhar no grupo acima"
|
|
10014
|
+
},
|
|
10015
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowRight, { size: 14 })
|
|
10016
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
10017
|
+
"button",
|
|
10018
|
+
{
|
|
10019
|
+
onClick: () => onOutdent(group.id),
|
|
10020
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
10021
|
+
title: "Desaninhar"
|
|
10022
|
+
},
|
|
10023
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiArrowLeft, { size: 14 })
|
|
10024
|
+
), /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement(
|
|
10025
|
+
"button",
|
|
10026
|
+
{
|
|
10027
|
+
onClick: () => onDelete(group.id),
|
|
10028
|
+
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
|
|
10029
|
+
title: "Remover Grupo"
|
|
10030
|
+
},
|
|
10031
|
+
/* @__PURE__ */ import_react25.default.createElement(import_fi19.FiTrash2, { size: 14 })
|
|
10032
|
+
)))
|
|
10033
|
+
), group.children && group.children.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react25.default.createElement(
|
|
10009
10034
|
GroupItem,
|
|
10010
10035
|
{
|
|
10011
10036
|
key: childGroup.id,
|
|
@@ -10214,7 +10239,9 @@ function AncestryBoard({
|
|
|
10214
10239
|
const addRecursive = (list) => {
|
|
10215
10240
|
return list.map((g) => {
|
|
10216
10241
|
if (g.id === pickingGroupId) {
|
|
10217
|
-
const exists = g.ancestries.some(
|
|
10242
|
+
const exists = g.ancestries.some(
|
|
10243
|
+
(a) => a.ancestry_id === ancestry.ancestry_id
|
|
10244
|
+
);
|
|
10218
10245
|
if (exists) return g;
|
|
10219
10246
|
return { ...g, ancestries: [...g.ancestries, ancestry] };
|
|
10220
10247
|
}
|
|
@@ -10225,12 +10252,16 @@ function AncestryBoard({
|
|
|
10225
10252
|
});
|
|
10226
10253
|
setPickingGroupId(null);
|
|
10227
10254
|
} else {
|
|
10228
|
-
const fullAncestry = availableAncestries.find(
|
|
10255
|
+
const fullAncestry = availableAncestries.find(
|
|
10256
|
+
(a) => a.ancestry_id === ancestry.ancestry_id
|
|
10257
|
+
) || ancestry;
|
|
10229
10258
|
onSelect(fullAncestry);
|
|
10230
10259
|
}
|
|
10231
10260
|
};
|
|
10232
10261
|
const handlePlayFromGroup = (ancestryId) => {
|
|
10233
|
-
const fullAncestry = availableAncestries.find(
|
|
10262
|
+
const fullAncestry = availableAncestries.find(
|
|
10263
|
+
(a) => a.ancestry_id === ancestryId
|
|
10264
|
+
);
|
|
10234
10265
|
if (fullAncestry && onSelect) {
|
|
10235
10266
|
onSelect(fullAncestry);
|
|
10236
10267
|
}
|
|
@@ -10240,7 +10271,12 @@ function AncestryBoard({
|
|
|
10240
10271
|
const removeRecursive = (list) => {
|
|
10241
10272
|
return list.map((g) => {
|
|
10242
10273
|
if (g.id === groupId) {
|
|
10243
|
-
return {
|
|
10274
|
+
return {
|
|
10275
|
+
...g,
|
|
10276
|
+
ancestries: g.ancestries.filter(
|
|
10277
|
+
(a) => a.ancestry_id !== ancestryId
|
|
10278
|
+
)
|
|
10279
|
+
};
|
|
10244
10280
|
}
|
|
10245
10281
|
return { ...g, children: removeRecursive(g.children) };
|
|
10246
10282
|
});
|
|
@@ -10261,7 +10297,13 @@ function AncestryBoard({
|
|
|
10261
10297
|
className: "bg-slate-950 border border-white/10 rounded-xl w-[98vw] h-[97vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
|
|
10262
10298
|
onClick: (e) => e.stopPropagation()
|
|
10263
10299
|
},
|
|
10264
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react25.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
10300
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react25.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
|
|
10301
|
+
import_fi19.FiLoader,
|
|
10302
|
+
{
|
|
10303
|
+
className: "animate-spin text-indigo-400",
|
|
10304
|
+
size: 12
|
|
10305
|
+
}
|
|
10306
|
+
), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react25.default.createElement(
|
|
10265
10307
|
"button",
|
|
10266
10308
|
{
|
|
10267
10309
|
onClick: handleAddRootGroup,
|
|
@@ -10277,57 +10319,75 @@ function AncestryBoard({
|
|
|
10277
10319
|
},
|
|
10278
10320
|
"\xD7"
|
|
10279
10321
|
))),
|
|
10280
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10322
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10323
|
+
"div",
|
|
10324
|
+
{
|
|
10325
|
+
className: `
|
|
10281
10326
|
flex flex-col border-r border-white/10 transition-all duration-300 flex-none
|
|
10282
10327
|
${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
|
|
10283
10328
|
min-w-[280px] max-w-[500px] bg-slate-900
|
|
10284
|
-
`
|
|
10285
|
-
|
|
10286
|
-
{
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10329
|
+
`
|
|
10330
|
+
},
|
|
10331
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react25.default.createElement(
|
|
10332
|
+
import_fi19.FiSearch,
|
|
10333
|
+
{
|
|
10334
|
+
className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
|
|
10335
|
+
}
|
|
10336
|
+
), /* @__PURE__ */ import_react25.default.createElement(
|
|
10337
|
+
"input",
|
|
10338
|
+
{
|
|
10339
|
+
type: "text",
|
|
10340
|
+
placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar ancestralidade...",
|
|
10341
|
+
className: `
|
|
10290
10342
|
w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
|
|
10291
10343
|
${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
|
|
10292
10344
|
`,
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10345
|
+
value: searchTerm,
|
|
10346
|
+
onChange: (e) => setSearchTerm(e.target.value),
|
|
10347
|
+
autoFocus: !pickingGroupId
|
|
10348
|
+
}
|
|
10349
|
+
))),
|
|
10350
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
|
|
10351
|
+
const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
|
|
10352
|
+
const isPicking = !!pickingGroupId;
|
|
10353
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
10354
|
+
"div",
|
|
10355
|
+
{
|
|
10356
|
+
key: anc.ancestry_id,
|
|
10357
|
+
onClick: () => {
|
|
10358
|
+
if (isPicking) handleSelectAncestry(anc);
|
|
10359
|
+
},
|
|
10360
|
+
className: `
|
|
10308
10361
|
group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
|
|
10309
10362
|
${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
|
|
10310
10363
|
`
|
|
10311
|
-
|
|
10312
|
-
|
|
10364
|
+
},
|
|
10365
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
10366
|
+
"div",
|
|
10367
|
+
{
|
|
10368
|
+
className: `
|
|
10313
10369
|
mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
|
|
10314
10370
|
${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
|
|
10315
|
-
`
|
|
10316
|
-
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react25.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react25.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
10317
|
-
!isPicking && /* @__PURE__ */ import_react25.default.createElement(
|
|
10318
|
-
"button",
|
|
10319
|
-
{
|
|
10320
|
-
onClick: (e) => {
|
|
10321
|
-
e.stopPropagation();
|
|
10322
|
-
handleSelectAncestry(anc);
|
|
10371
|
+
`
|
|
10323
10372
|
},
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
},
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
|
|
10330
|
-
|
|
10373
|
+
isPicking ? /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { size: 14 })
|
|
10374
|
+
),
|
|
10375
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react25.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ import_react25.default.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react25.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react25.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
10376
|
+
!isPicking && /* @__PURE__ */ import_react25.default.createElement(
|
|
10377
|
+
"button",
|
|
10378
|
+
{
|
|
10379
|
+
onClick: (e) => {
|
|
10380
|
+
e.stopPropagation();
|
|
10381
|
+
handleSelectAncestry(anc);
|
|
10382
|
+
},
|
|
10383
|
+
className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
|
|
10384
|
+
title: "Renderizar Ancestralidade"
|
|
10385
|
+
},
|
|
10386
|
+
/* @__PURE__ */ import_react25.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiPlay, { size: 14, className: "ml-0.5" }))
|
|
10387
|
+
)
|
|
10388
|
+
);
|
|
10389
|
+
}))
|
|
10390
|
+
), /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ import_react25.default.createElement(import_fi19.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react25.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react25.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react25.default.createElement(
|
|
10331
10391
|
GroupItem,
|
|
10332
10392
|
{
|
|
10333
10393
|
key: group.id,
|
|
@@ -10406,7 +10466,10 @@ var findNodePath3 = (tree, targetNodeId, currentPath = []) => {
|
|
|
10406
10466
|
}
|
|
10407
10467
|
if (tree.children) {
|
|
10408
10468
|
for (let i = 0; i < tree.children.length; i++) {
|
|
10409
|
-
const res = findNodePath3(tree.children[i], targetNodeId, [
|
|
10469
|
+
const res = findNodePath3(tree.children[i], targetNodeId, [
|
|
10470
|
+
...currentPath,
|
|
10471
|
+
i
|
|
10472
|
+
]);
|
|
10410
10473
|
if (res) return res;
|
|
10411
10474
|
}
|
|
10412
10475
|
}
|
|
@@ -10499,27 +10562,70 @@ function XViewScene({
|
|
|
10499
10562
|
const [userPermissionRole, setUserPermissionRole] = (0, import_react26.useState)(null);
|
|
10500
10563
|
const [isInitialized, setIsInitialized] = (0, import_react26.useState)(false);
|
|
10501
10564
|
const [sceneVersion, setSceneVersion] = (0, import_react26.useState)(0);
|
|
10502
|
-
const [contextMenu, setContextMenu] = (0, import_react26.useState)({
|
|
10503
|
-
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10565
|
+
const [contextMenu, setContextMenu] = (0, import_react26.useState)({
|
|
10566
|
+
visible: false,
|
|
10567
|
+
x: 0,
|
|
10568
|
+
y: 0,
|
|
10569
|
+
nodeData: null
|
|
10570
|
+
});
|
|
10571
|
+
const [multiContextMenu, setMultiContextMenu] = (0, import_react26.useState)({
|
|
10572
|
+
visible: false,
|
|
10573
|
+
x: 0,
|
|
10574
|
+
y: 0,
|
|
10575
|
+
nodeIds: null
|
|
10576
|
+
});
|
|
10577
|
+
const [relationshipMenu, setRelationshipMenu] = (0, import_react26.useState)({
|
|
10578
|
+
visible: false,
|
|
10579
|
+
x: 0,
|
|
10580
|
+
y: 0,
|
|
10581
|
+
linkObject: null
|
|
10582
|
+
});
|
|
10583
|
+
const [creationMode, setCreationMode] = (0, import_react26.useState)({
|
|
10584
|
+
isActive: false,
|
|
10585
|
+
sourceNodeData: null
|
|
10586
|
+
});
|
|
10587
|
+
const [versionMode, setVersionMode] = (0, import_react26.useState)({
|
|
10588
|
+
isActive: false,
|
|
10589
|
+
sourceNodeData: null
|
|
10590
|
+
});
|
|
10507
10591
|
const [questMode, setQuestMode] = (0, import_react26.useState)({ isActive: false });
|
|
10508
10592
|
const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react26.useState)(false);
|
|
10509
10593
|
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react26.useState)(false);
|
|
10510
|
-
const [ancestryMode, setAncestryMode] = (0, import_react26.useState)({
|
|
10594
|
+
const [ancestryMode, setAncestryMode] = (0, import_react26.useState)({
|
|
10595
|
+
isActive: false,
|
|
10596
|
+
tree: null,
|
|
10597
|
+
selectedParentId: null,
|
|
10598
|
+
isEditMode: false,
|
|
10599
|
+
currentAncestryId: null,
|
|
10600
|
+
ancestryName: "",
|
|
10601
|
+
ancestryDescription: "",
|
|
10602
|
+
ancestryDescriptionSections: [],
|
|
10603
|
+
isAddingNodes: false
|
|
10604
|
+
});
|
|
10511
10605
|
const [readingMode, setReadingMode] = (0, import_react26.useState)({
|
|
10512
10606
|
isActive: false,
|
|
10513
10607
|
ancestry: null,
|
|
10514
10608
|
branchStack: [],
|
|
10515
10609
|
autoAbstraction: false
|
|
10516
10610
|
});
|
|
10517
|
-
const [formPosition, setFormPosition] = (0, import_react26.useState)({
|
|
10611
|
+
const [formPosition, setFormPosition] = (0, import_react26.useState)({
|
|
10612
|
+
left: 16,
|
|
10613
|
+
top: 16,
|
|
10614
|
+
opacity: 0
|
|
10615
|
+
});
|
|
10518
10616
|
const [detailsNode, setDetailsNode] = (0, import_react26.useState)(null);
|
|
10519
10617
|
const [detailsLink, setDetailsLink] = (0, import_react26.useState)(null);
|
|
10520
10618
|
const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react26.useState)(null);
|
|
10521
|
-
const [imageViewer, setImageViewer] = (0, import_react26.useState)({
|
|
10522
|
-
|
|
10619
|
+
const [imageViewer, setImageViewer] = (0, import_react26.useState)({
|
|
10620
|
+
visible: false,
|
|
10621
|
+
images: [],
|
|
10622
|
+
startIndex: 0
|
|
10623
|
+
});
|
|
10624
|
+
const [editingAncestryRel, setEditingAncestryRel] = (0, import_react26.useState)({
|
|
10625
|
+
visible: false,
|
|
10626
|
+
data: null,
|
|
10627
|
+
path: null
|
|
10628
|
+
});
|
|
10523
10629
|
const [isImportModalOpen, setIsImportModalOpen] = (0, import_react26.useState)(false);
|
|
10524
10630
|
const [importSuccessMessage, setImportSuccessMessage] = (0, import_react26.useState)("");
|
|
10525
10631
|
const [highlightedNodeId, setHighlightedNodeId] = (0, import_react26.useState)(null);
|
|
@@ -10559,8 +10665,23 @@ function XViewScene({
|
|
|
10559
10665
|
ghostElements: { node: null, line: null, aura: null },
|
|
10560
10666
|
creation: { isActive: false, sourceNodeData: null },
|
|
10561
10667
|
connection: { isActive: false, sourceNodeData: null, line: null },
|
|
10562
|
-
relink: {
|
|
10563
|
-
|
|
10668
|
+
relink: {
|
|
10669
|
+
isActive: false,
|
|
10670
|
+
end: null,
|
|
10671
|
+
fixedNodeId: null,
|
|
10672
|
+
originalLine: null,
|
|
10673
|
+
line: null
|
|
10674
|
+
},
|
|
10675
|
+
ancestry: {
|
|
10676
|
+
isActive: false,
|
|
10677
|
+
tree: null,
|
|
10678
|
+
selectedParentId: null,
|
|
10679
|
+
isEditMode: false,
|
|
10680
|
+
currentAncestryId: null,
|
|
10681
|
+
ancestryName: "",
|
|
10682
|
+
ancestryDescription: "",
|
|
10683
|
+
isAddingNodes: false
|
|
10684
|
+
},
|
|
10564
10685
|
glowTexture: null,
|
|
10565
10686
|
nodeIdToParentFileMap: null,
|
|
10566
10687
|
maxAncestryRenderIndex: 0,
|
|
@@ -10569,7 +10690,11 @@ function XViewScene({
|
|
|
10569
10690
|
highlightedNodeId: null
|
|
10570
10691
|
});
|
|
10571
10692
|
const maxReadPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
10572
|
-
const {
|
|
10693
|
+
const {
|
|
10694
|
+
width: readModeWidth,
|
|
10695
|
+
isResizing: isReadModeResizing,
|
|
10696
|
+
handlePointerDown: handleReadModeResize
|
|
10697
|
+
} = useResizablePanel({
|
|
10573
10698
|
initialWidth: 700,
|
|
10574
10699
|
minWidth: 320,
|
|
10575
10700
|
maxWidth: maxReadPanelW
|
|
@@ -10586,7 +10711,9 @@ function XViewScene({
|
|
|
10586
10711
|
for (const parentFileId in allParentData) {
|
|
10587
10712
|
if (allParentData.hasOwnProperty(parentFileId)) {
|
|
10588
10713
|
const parentFile = allParentData[parentFileId];
|
|
10589
|
-
const parentDbInfo = parentDbsArray.find(
|
|
10714
|
+
const parentDbInfo = parentDbsArray.find(
|
|
10715
|
+
(db) => String(db.db_id) === String(parentFileId)
|
|
10716
|
+
);
|
|
10590
10717
|
const ownerId2 = (parentDbInfo == null ? void 0 : parentDbInfo.owner_id) || null;
|
|
10591
10718
|
const datasetName = parentFile.dataset_name || `Dataset #${parentFileId.substring(0, 6)}`;
|
|
10592
10719
|
if (parentFile.nodes && ownerId2) {
|
|
@@ -10622,7 +10749,10 @@ function XViewScene({
|
|
|
10622
10749
|
if (files.length > 0 && get_single_parent_file && save_view_data) {
|
|
10623
10750
|
for (const file of files) {
|
|
10624
10751
|
try {
|
|
10625
|
-
const parentFileData = await get_single_parent_file(
|
|
10752
|
+
const parentFileData = await get_single_parent_file(
|
|
10753
|
+
file.id,
|
|
10754
|
+
session
|
|
10755
|
+
);
|
|
10626
10756
|
if (parentFileData.success && parentFileData.data) {
|
|
10627
10757
|
parentDataRef.current = {
|
|
10628
10758
|
...parentDataRef.current,
|
|
@@ -10633,7 +10763,11 @@ function XViewScene({
|
|
|
10633
10763
|
owner_id: session.user.id
|
|
10634
10764
|
};
|
|
10635
10765
|
updatedParentDbs.push(newParentDbObject);
|
|
10636
|
-
await add_new_parent_file_to_scene_at_firebase_action(
|
|
10766
|
+
await add_new_parent_file_to_scene_at_firebase_action(
|
|
10767
|
+
sceneConfigId,
|
|
10768
|
+
session,
|
|
10769
|
+
file.id
|
|
10770
|
+
);
|
|
10637
10771
|
importedIds.push(file.id);
|
|
10638
10772
|
successCount++;
|
|
10639
10773
|
}
|
|
@@ -10645,7 +10779,10 @@ function XViewScene({
|
|
|
10645
10779
|
if (viewToImport && get_ancestry_file) {
|
|
10646
10780
|
try {
|
|
10647
10781
|
const targetViewOwnerId = ((_b2 = (_a2 = viewToImport.members) == null ? void 0 : _a2.find((m) => m.permission === "owner")) == null ? void 0 : _b2.id) || session.user.id;
|
|
10648
|
-
const ancestryResponse = await get_ancestry_file(
|
|
10782
|
+
const ancestryResponse = await get_ancestry_file(
|
|
10783
|
+
viewToImport.id,
|
|
10784
|
+
targetViewOwnerId
|
|
10785
|
+
);
|
|
10649
10786
|
if (ancestryResponse.success && Array.isArray(ancestryResponse.data)) {
|
|
10650
10787
|
const viewSpecificAncestries = ancestryResponse.data.filter(
|
|
10651
10788
|
(anc) => anc._source_file_id === viewToImport.id && !anc.is_private
|
|
@@ -10656,14 +10793,21 @@ function XViewScene({
|
|
|
10656
10793
|
_imported_from_view_owner_id: targetViewOwnerId,
|
|
10657
10794
|
_source_file_id: viewToImport.id,
|
|
10658
10795
|
_source_owner_id: targetViewOwnerId,
|
|
10659
|
-
_origin_db_ids: (viewToImport.selected_databases || []).map(
|
|
10796
|
+
_origin_db_ids: (viewToImport.selected_databases || []).map(
|
|
10797
|
+
(db) => db.db_id
|
|
10798
|
+
)
|
|
10660
10799
|
}));
|
|
10661
10800
|
const currentAncestries = ancestryDataRef.current || [];
|
|
10662
10801
|
const newAncestries = processedAncestries.filter(
|
|
10663
|
-
(newAnc) => !currentAncestries.some(
|
|
10802
|
+
(newAnc) => !currentAncestries.some(
|
|
10803
|
+
(curr) => String(curr.ancestry_id) === String(newAnc.ancestry_id)
|
|
10804
|
+
)
|
|
10664
10805
|
);
|
|
10665
10806
|
if (newAncestries.length > 0) {
|
|
10666
|
-
ancestryDataRef.current = [
|
|
10807
|
+
ancestryDataRef.current = [
|
|
10808
|
+
...currentAncestries,
|
|
10809
|
+
...newAncestries
|
|
10810
|
+
];
|
|
10667
10811
|
ancestriesWereImported = true;
|
|
10668
10812
|
}
|
|
10669
10813
|
}
|
|
@@ -10683,7 +10827,9 @@ function XViewScene({
|
|
|
10683
10827
|
if (ancestry_save_url) {
|
|
10684
10828
|
await save_view_data(ancestry_save_url, ancestryDataRef.current);
|
|
10685
10829
|
} else {
|
|
10686
|
-
console.error(
|
|
10830
|
+
console.error(
|
|
10831
|
+
"Erro: URL de salvamento de ancestralidade n\xE3o definida."
|
|
10832
|
+
);
|
|
10687
10833
|
}
|
|
10688
10834
|
}
|
|
10689
10835
|
setSceneVersion((v) => v + 1);
|
|
@@ -10691,113 +10837,136 @@ function XViewScene({
|
|
|
10691
10837
|
setImportSuccessMessage("Importa\xE7\xE3o conclu\xEDda com sucesso.");
|
|
10692
10838
|
setTimeout(() => setImportSuccessMessage(""), 5e3);
|
|
10693
10839
|
} else if (viewToImport && !ancestriesWereImported) {
|
|
10694
|
-
console.warn(
|
|
10840
|
+
console.warn(
|
|
10841
|
+
"Importa\xE7\xE3o finalizada, mas nenhum dado novo foi adicionado."
|
|
10842
|
+
);
|
|
10695
10843
|
}
|
|
10696
10844
|
},
|
|
10697
|
-
[
|
|
10845
|
+
[
|
|
10846
|
+
get_single_parent_file,
|
|
10847
|
+
get_ancestry_file,
|
|
10848
|
+
save_view_data,
|
|
10849
|
+
session,
|
|
10850
|
+
sceneSaveUrl,
|
|
10851
|
+
ancestry_save_url,
|
|
10852
|
+
sceneConfigId,
|
|
10853
|
+
add_new_parent_file_to_scene_at_firebase_action
|
|
10854
|
+
]
|
|
10698
10855
|
);
|
|
10699
10856
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
10700
10857
|
setImageViewer({ visible: true, images, startIndex });
|
|
10701
10858
|
};
|
|
10702
|
-
const tweenToTarget = (0, import_react26.useCallback)(
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10859
|
+
const tweenToTarget = (0, import_react26.useCallback)(
|
|
10860
|
+
(target, zoomFactor = 1, forcedDirection = null) => {
|
|
10861
|
+
const { camera, controls, tweenGroup } = stateRef.current;
|
|
10862
|
+
if (!camera || !controls || !tweenGroup) return;
|
|
10863
|
+
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
10864
|
+
const controlsTween = new import_tween2.Tween(controls.target).to(targetPos, 1500).easing(import_tween2.Easing.Cubic.Out);
|
|
10865
|
+
tweenGroup.add(controlsTween);
|
|
10866
|
+
controlsTween.start();
|
|
10867
|
+
let offset;
|
|
10868
|
+
if (forcedDirection) {
|
|
10869
|
+
offset = forcedDirection.clone().normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
|
|
10870
|
+
} else {
|
|
10871
|
+
offset = camera.position.clone().sub(controls.target).normalize().multiplyScalar(x_view_config.CAMERA_ZOOM_DISTANCE / zoomFactor);
|
|
10872
|
+
}
|
|
10873
|
+
const targetCameraPos = targetPos.clone().add(offset);
|
|
10874
|
+
const cameraTween = new import_tween2.Tween(camera.position).to(targetCameraPos, 1500).easing(import_tween2.Easing.Cubic.Out);
|
|
10875
|
+
tweenGroup.add(cameraTween);
|
|
10876
|
+
cameraTween.start();
|
|
10877
|
+
},
|
|
10878
|
+
[]
|
|
10879
|
+
);
|
|
10720
10880
|
const isFromUiOverlay = (event) => {
|
|
10721
10881
|
const t = event == null ? void 0 : event.target;
|
|
10722
10882
|
if (!t || typeof t.closest !== "function") return false;
|
|
10723
10883
|
return !!t.closest(".ui-overlay");
|
|
10724
10884
|
};
|
|
10725
|
-
const buildFullAncestryTree = (0, import_react26.useCallback)(
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10735
|
-
};
|
|
10736
|
-
}
|
|
10737
|
-
let nodeId = treeItem.node_id;
|
|
10738
|
-
if (!nodeId && treeItem.node) nodeId = treeItem.node.id;
|
|
10739
|
-
const fullNode = nodeMap.get(String(nodeId));
|
|
10740
|
-
const effectiveNode = fullNode || treeItem.node;
|
|
10741
|
-
let processedBranches = [];
|
|
10742
|
-
if (treeItem.parallel_branches && Array.isArray(treeItem.parallel_branches)) {
|
|
10743
|
-
processedBranches = treeItem.parallel_branches.map((branch) => {
|
|
10744
|
-
if (branch.linked_ancestry_id) {
|
|
10745
|
-
const linkedAncestry = ancestryMap.get(String(branch.linked_ancestry_id));
|
|
10746
|
-
if (linkedAncestry && linkedAncestry.tree) {
|
|
10747
|
-
const graftedTree = recursiveBuild(linkedAncestry.tree);
|
|
10748
|
-
return {
|
|
10749
|
-
...branch,
|
|
10750
|
-
name: linkedAncestry.name,
|
|
10751
|
-
description: linkedAncestry.description,
|
|
10752
|
-
description_sections: linkedAncestry.description_sections,
|
|
10753
|
-
tree: graftedTree,
|
|
10754
|
-
isLinked: true
|
|
10755
|
-
};
|
|
10756
|
-
}
|
|
10757
|
-
}
|
|
10885
|
+
const buildFullAncestryTree = (0, import_react26.useCallback)(
|
|
10886
|
+
(idTree, nodes, ancestries = []) => {
|
|
10887
|
+
if (!idTree) return null;
|
|
10888
|
+
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
10889
|
+
const ancestryMap = new Map(
|
|
10890
|
+
ancestries.map((a) => [String(a.ancestry_id), a])
|
|
10891
|
+
);
|
|
10892
|
+
const recursiveBuild = (treeItem) => {
|
|
10893
|
+
if (!treeItem) return null;
|
|
10894
|
+
if (treeItem.is_section) {
|
|
10758
10895
|
return {
|
|
10759
|
-
...
|
|
10760
|
-
|
|
10896
|
+
...treeItem,
|
|
10897
|
+
children: (treeItem.children || []).map(recursiveBuild).filter(Boolean)
|
|
10761
10898
|
};
|
|
10762
|
-
}
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
parallel_branches
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10775
|
-
|
|
10776
|
-
|
|
10777
|
-
|
|
10778
|
-
|
|
10779
|
-
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
return {
|
|
10786
|
-
...branch,
|
|
10787
|
-
name: linkedAncestry.name,
|
|
10788
|
-
description: linkedAncestry.description,
|
|
10789
|
-
description_sections: linkedAncestry.description_sections,
|
|
10790
|
-
tree: recursiveBuild(linkedAncestry.tree),
|
|
10791
|
-
isLinked: true
|
|
10792
|
-
};
|
|
10899
|
+
}
|
|
10900
|
+
let nodeId = treeItem.node_id;
|
|
10901
|
+
if (!nodeId && treeItem.node) nodeId = treeItem.node.id;
|
|
10902
|
+
const fullNode = nodeMap.get(String(nodeId));
|
|
10903
|
+
const effectiveNode = fullNode || treeItem.node;
|
|
10904
|
+
let processedBranches = [];
|
|
10905
|
+
if (treeItem.parallel_branches && Array.isArray(treeItem.parallel_branches)) {
|
|
10906
|
+
processedBranches = treeItem.parallel_branches.map((branch) => {
|
|
10907
|
+
if (branch.linked_ancestry_id) {
|
|
10908
|
+
const linkedAncestry = ancestryMap.get(
|
|
10909
|
+
String(branch.linked_ancestry_id)
|
|
10910
|
+
);
|
|
10911
|
+
if (linkedAncestry && linkedAncestry.tree) {
|
|
10912
|
+
const graftedTree = recursiveBuild(linkedAncestry.tree);
|
|
10913
|
+
return {
|
|
10914
|
+
...branch,
|
|
10915
|
+
name: linkedAncestry.name,
|
|
10916
|
+
description: linkedAncestry.description,
|
|
10917
|
+
description_sections: linkedAncestry.description_sections,
|
|
10918
|
+
tree: graftedTree,
|
|
10919
|
+
isLinked: true
|
|
10920
|
+
};
|
|
10921
|
+
}
|
|
10793
10922
|
}
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10923
|
+
return {
|
|
10924
|
+
...branch,
|
|
10925
|
+
tree: recursiveBuild(branch.tree)
|
|
10926
|
+
};
|
|
10927
|
+
});
|
|
10928
|
+
}
|
|
10929
|
+
return {
|
|
10930
|
+
...effectiveNode ? { node: effectiveNode } : { node: { id: nodeId, name: "Unknown" } },
|
|
10931
|
+
relationship: treeItem.relationship || {},
|
|
10932
|
+
children: (treeItem.children || []).map(recursiveBuild).filter(Boolean),
|
|
10933
|
+
parallel_branches: processedBranches
|
|
10934
|
+
};
|
|
10797
10935
|
};
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10936
|
+
let rootId = idTree.node_id;
|
|
10937
|
+
if (!rootId && idTree.node) rootId = idTree.node.id;
|
|
10938
|
+
if (rootId) {
|
|
10939
|
+
const rootNode = nodeMap.get(String(rootId));
|
|
10940
|
+
const effectiveRoot = rootNode || idTree.node;
|
|
10941
|
+
if (!effectiveRoot) return null;
|
|
10942
|
+
return {
|
|
10943
|
+
node: effectiveRoot,
|
|
10944
|
+
relationship: idTree.relationship || {},
|
|
10945
|
+
children: (idTree.children || []).map(recursiveBuild).filter(Boolean),
|
|
10946
|
+
parallel_branches: (idTree.parallel_branches || []).map((branch) => {
|
|
10947
|
+
if (branch.linked_ancestry_id) {
|
|
10948
|
+
const linkedAncestry = ancestryMap.get(
|
|
10949
|
+
String(branch.linked_ancestry_id)
|
|
10950
|
+
);
|
|
10951
|
+
if (linkedAncestry && linkedAncestry.tree) {
|
|
10952
|
+
return {
|
|
10953
|
+
...branch,
|
|
10954
|
+
name: linkedAncestry.name,
|
|
10955
|
+
description: linkedAncestry.description,
|
|
10956
|
+
description_sections: linkedAncestry.description_sections,
|
|
10957
|
+
tree: recursiveBuild(linkedAncestry.tree),
|
|
10958
|
+
isLinked: true
|
|
10959
|
+
};
|
|
10960
|
+
}
|
|
10961
|
+
}
|
|
10962
|
+
return { ...branch, tree: recursiveBuild(branch.tree) };
|
|
10963
|
+
})
|
|
10964
|
+
};
|
|
10965
|
+
}
|
|
10966
|
+
return recursiveBuild(idTree);
|
|
10967
|
+
},
|
|
10968
|
+
[]
|
|
10969
|
+
);
|
|
10801
10970
|
const handleActivateTimeline = (0, import_react26.useCallback)(() => {
|
|
10802
10971
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10803
10972
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
@@ -10878,10 +11047,12 @@ function XViewScene({
|
|
|
10878
11047
|
if (timelineNodes.length === 0) return;
|
|
10879
11048
|
const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
|
|
10880
11049
|
const maxTimeIndex = sortedTimePoints.length - 1;
|
|
10881
|
-
const timeToYMap = new Map(
|
|
10882
|
-
time,
|
|
10883
|
-
|
|
10884
|
-
|
|
11050
|
+
const timeToYMap = new Map(
|
|
11051
|
+
sortedTimePoints.map((time, index) => [
|
|
11052
|
+
time,
|
|
11053
|
+
(index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
|
|
11054
|
+
])
|
|
11055
|
+
);
|
|
10885
11056
|
timelineNodes.sort((a, b) => {
|
|
10886
11057
|
if (a.isUndated && b.isUndated) return 0;
|
|
10887
11058
|
if (a.isUndated) return 1;
|
|
@@ -10924,7 +11095,12 @@ function XViewScene({
|
|
|
10924
11095
|
if (type === "interval") {
|
|
10925
11096
|
const endY = timeToYMap.get(endDate.getTime());
|
|
10926
11097
|
if (endY > y) {
|
|
10927
|
-
const barGeometry = new THREE3.CylinderGeometry(
|
|
11098
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
11099
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11100
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11101
|
+
1,
|
|
11102
|
+
16
|
|
11103
|
+
);
|
|
10928
11104
|
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
10929
11105
|
color: TIMELINE_GOLD_COLOR,
|
|
10930
11106
|
emissive: 12092939,
|
|
@@ -10953,7 +11129,8 @@ function XViewScene({
|
|
|
10953
11129
|
}, []);
|
|
10954
11130
|
const handleVersionTimeline = (0, import_react26.useCallback)((sourceMesh, versionMeshes) => {
|
|
10955
11131
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10956
|
-
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
11132
|
+
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
11133
|
+
return;
|
|
10957
11134
|
versionMeshes.forEach((mesh) => {
|
|
10958
11135
|
const oldLabel = mesh.getObjectByName("timelineLabel");
|
|
10959
11136
|
if (oldLabel) {
|
|
@@ -10969,7 +11146,8 @@ function XViewScene({
|
|
|
10969
11146
|
}
|
|
10970
11147
|
if (mesh.userData.timelineEndLabel) {
|
|
10971
11148
|
timelineIntervalsGroup.remove(mesh.userData.timelineEndLabel);
|
|
10972
|
-
if (mesh.userData.timelineEndLabel.material.map)
|
|
11149
|
+
if (mesh.userData.timelineEndLabel.material.map)
|
|
11150
|
+
mesh.userData.timelineEndLabel.material.map.dispose();
|
|
10973
11151
|
mesh.userData.timelineEndLabel.material.dispose();
|
|
10974
11152
|
delete mesh.userData.timelineEndLabel;
|
|
10975
11153
|
}
|
|
@@ -11029,8 +11207,15 @@ function XViewScene({
|
|
|
11029
11207
|
});
|
|
11030
11208
|
if (timelineNodes.length === 0) return;
|
|
11031
11209
|
const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
|
|
11032
|
-
const timeToYMap = new Map(
|
|
11033
|
-
|
|
11210
|
+
const timeToYMap = new Map(
|
|
11211
|
+
sortedTimePoints.map((time, index) => [
|
|
11212
|
+
time,
|
|
11213
|
+
index * TIMELINE_LAYER_SPACING_Y
|
|
11214
|
+
])
|
|
11215
|
+
);
|
|
11216
|
+
timelineNodes.sort(
|
|
11217
|
+
(a, b) => a.startDate - b.startDate || a.endDate - b.endDate
|
|
11218
|
+
);
|
|
11034
11219
|
const baseX = sourceMesh.position.x + TIMELINE_NODE_SPACING_X;
|
|
11035
11220
|
const baseY = sourceMesh.position.y;
|
|
11036
11221
|
const maxNodeIndex = timelineNodes.length - 1;
|
|
@@ -11048,7 +11233,12 @@ function XViewScene({
|
|
|
11048
11233
|
if (type === "interval") {
|
|
11049
11234
|
const relativeEndY = timeToYMap.get(endDate.getTime()) - timeToYMap.get(startDate.getTime());
|
|
11050
11235
|
if (relativeEndY > 0) {
|
|
11051
|
-
const barGeometry = new THREE3.CylinderGeometry(
|
|
11236
|
+
const barGeometry = new THREE3.CylinderGeometry(
|
|
11237
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11238
|
+
TIMELINE_INTERVAL_BAR_RADIUS,
|
|
11239
|
+
1,
|
|
11240
|
+
16
|
|
11241
|
+
);
|
|
11052
11242
|
const barMaterial = new THREE3.MeshStandardMaterial({
|
|
11053
11243
|
color: TIMELINE_GOLD_COLOR,
|
|
11054
11244
|
emissive: 12092939,
|
|
@@ -11085,15 +11275,31 @@ function XViewScene({
|
|
|
11085
11275
|
try {
|
|
11086
11276
|
const typeStr = (viewParams == null ? void 0 : viewParams.type) || "";
|
|
11087
11277
|
const sceneType = typeStr.toLowerCase().includes("database") ? "database" : "view";
|
|
11088
|
-
const scenePromise = get_scene_view_data(
|
|
11278
|
+
const scenePromise = get_scene_view_data(
|
|
11279
|
+
configPath,
|
|
11280
|
+
ownerId2,
|
|
11281
|
+
typeStr,
|
|
11282
|
+
session,
|
|
11283
|
+
focusNodeId,
|
|
11284
|
+
focusAncestryId
|
|
11285
|
+
);
|
|
11089
11286
|
const boardPromise = get_ancestry_board_action && session ? get_ancestry_board_action(configPath, sceneType, session, ownerId2) : Promise.resolve({ success: false, data: [] });
|
|
11090
|
-
const [sceneResponse, boardResponse] = await Promise.all([
|
|
11287
|
+
const [sceneResponse, boardResponse] = await Promise.all([
|
|
11288
|
+
scenePromise,
|
|
11289
|
+
boardPromise
|
|
11290
|
+
]);
|
|
11091
11291
|
if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
|
|
11092
11292
|
if (focusNodeId) {
|
|
11093
|
-
let targetNode = sceneResponse.data.scene.nodes.find(
|
|
11293
|
+
let targetNode = sceneResponse.data.scene.nodes.find(
|
|
11294
|
+
(n) => String(n.id) === String(focusNodeId)
|
|
11295
|
+
);
|
|
11094
11296
|
if (!targetNode) {
|
|
11095
|
-
const allParentNodes = Object.values(
|
|
11096
|
-
|
|
11297
|
+
const allParentNodes = Object.values(
|
|
11298
|
+
sceneResponse.data.parent
|
|
11299
|
+
).flatMap((f) => f.nodes || []);
|
|
11300
|
+
targetNode = allParentNodes.find(
|
|
11301
|
+
(n) => String(n.id) === String(focusNodeId)
|
|
11302
|
+
);
|
|
11097
11303
|
}
|
|
11098
11304
|
if (targetNode) {
|
|
11099
11305
|
sceneResponse.data.scene.nodes = [targetNode];
|
|
@@ -11106,12 +11312,24 @@ function XViewScene({
|
|
|
11106
11312
|
sceneDataRef.current = sceneResponse.data.scene;
|
|
11107
11313
|
parentDataRef.current = sceneResponse.data.parent;
|
|
11108
11314
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
11109
|
-
console.log(
|
|
11110
|
-
|
|
11111
|
-
|
|
11315
|
+
console.log(
|
|
11316
|
+
"Console de sceneResponse.data.scene:",
|
|
11317
|
+
sceneResponse.data.scene
|
|
11318
|
+
);
|
|
11319
|
+
console.log(
|
|
11320
|
+
"Console de sceneResponse.data.parent:",
|
|
11321
|
+
sceneResponse.data.parent
|
|
11322
|
+
);
|
|
11323
|
+
console.log(
|
|
11324
|
+
"Console de sceneResponse.data.ancestry:",
|
|
11325
|
+
sceneResponse.data.ancestry
|
|
11326
|
+
);
|
|
11112
11327
|
setIsInitialized(true);
|
|
11113
11328
|
} else {
|
|
11114
|
-
console.error(
|
|
11329
|
+
console.error(
|
|
11330
|
+
"Falha ao buscar dados da cena:",
|
|
11331
|
+
(sceneResponse == null ? void 0 : sceneResponse.error) || "Resposta inv\xE1lida."
|
|
11332
|
+
);
|
|
11115
11333
|
}
|
|
11116
11334
|
if (boardResponse == null ? void 0 : boardResponse.success) {
|
|
11117
11335
|
setAncestryBoardData(boardResponse.data);
|
|
@@ -11130,7 +11348,9 @@ function XViewScene({
|
|
|
11130
11348
|
console.error("Usu\xE1rio n\xE3o autenticado. Acesso negado.");
|
|
11131
11349
|
setIsLoading(false);
|
|
11132
11350
|
} else if (!sceneConfigId && status !== "loading") {
|
|
11133
|
-
console.warn(
|
|
11351
|
+
console.warn(
|
|
11352
|
+
"Nenhum par\xE2metro de cena encontrado na URL ou falha na decripta\xE7\xE3o."
|
|
11353
|
+
);
|
|
11134
11354
|
setIsLoading(false);
|
|
11135
11355
|
}
|
|
11136
11356
|
}, [
|
|
@@ -11151,33 +11371,46 @@ function XViewScene({
|
|
|
11151
11371
|
const objs = stateRef.current.nodeObjects || {};
|
|
11152
11372
|
return !!objs[key];
|
|
11153
11373
|
}, []);
|
|
11154
|
-
const addOrUpdateNodeMesh = (0, import_react26.useCallback)(
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
tweenGroup
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11374
|
+
const addOrUpdateNodeMesh = (0, import_react26.useCallback)(
|
|
11375
|
+
(nodeData, position, suppressVersionUpdate = false) => {
|
|
11376
|
+
const {
|
|
11377
|
+
graphGroup,
|
|
11378
|
+
nodeObjects,
|
|
11379
|
+
clickableNodes,
|
|
11380
|
+
glowTexture,
|
|
11381
|
+
tweenGroup
|
|
11382
|
+
} = stateRef.current;
|
|
11383
|
+
const nodeId = String(nodeData.id);
|
|
11384
|
+
if (nodeObjects[nodeId]) {
|
|
11385
|
+
const existingMesh = nodeObjects[nodeId];
|
|
11386
|
+
if (position) {
|
|
11387
|
+
const updateTween = new import_tween2.Tween(existingMesh.position).to(position, 800).easing(import_tween2.Easing.Cubic.Out);
|
|
11388
|
+
tweenGroup.add(updateTween);
|
|
11389
|
+
updateTween.start();
|
|
11390
|
+
}
|
|
11391
|
+
return existingMesh;
|
|
11392
|
+
}
|
|
11393
|
+
const mesh = createNodeMesh(
|
|
11394
|
+
nodeData,
|
|
11395
|
+
position || new THREE3.Vector3(),
|
|
11396
|
+
glowTexture
|
|
11397
|
+
);
|
|
11398
|
+
graphGroup.add(mesh);
|
|
11399
|
+
if (mesh.userData.labelObject) {
|
|
11400
|
+
if (mesh.userData.labelOffset) {
|
|
11401
|
+
mesh.userData.labelObject.position.copy(mesh.position).add(mesh.userData.labelOffset);
|
|
11402
|
+
}
|
|
11403
|
+
graphGroup.add(mesh.userData.labelObject);
|
|
11171
11404
|
}
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
}
|
|
11179
|
-
|
|
11180
|
-
|
|
11405
|
+
nodeObjects[nodeId] = mesh;
|
|
11406
|
+
clickableNodes.push(mesh);
|
|
11407
|
+
if (!suppressVersionUpdate) {
|
|
11408
|
+
setSceneVersion((v) => v + 1);
|
|
11409
|
+
}
|
|
11410
|
+
return mesh;
|
|
11411
|
+
},
|
|
11412
|
+
[]
|
|
11413
|
+
);
|
|
11181
11414
|
(0, import_react26.useEffect)(() => {
|
|
11182
11415
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
11183
11416
|
const currentMount = mountRef.current;
|
|
@@ -11192,7 +11425,12 @@ function XViewScene({
|
|
|
11192
11425
|
const scene = new THREE3.Scene();
|
|
11193
11426
|
scene.background = new THREE3.Color(0);
|
|
11194
11427
|
stateRef.current.scene = scene;
|
|
11195
|
-
const camera = new THREE3.PerspectiveCamera(
|
|
11428
|
+
const camera = new THREE3.PerspectiveCamera(
|
|
11429
|
+
75,
|
|
11430
|
+
currentMount.clientWidth / currentMount.clientHeight,
|
|
11431
|
+
0.1,
|
|
11432
|
+
2e3
|
|
11433
|
+
);
|
|
11196
11434
|
camera.position.set(0, 60, 120);
|
|
11197
11435
|
stateRef.current.camera = camera;
|
|
11198
11436
|
const renderer = new THREE3.WebGLRenderer({ antialias: true });
|
|
@@ -11213,7 +11451,12 @@ function XViewScene({
|
|
|
11213
11451
|
directionalLight.position.set(50, 50, 50);
|
|
11214
11452
|
scene.add(directionalLight);
|
|
11215
11453
|
const renderScene = new import_RenderPass.RenderPass(scene, camera);
|
|
11216
|
-
const bloomPass = new import_UnrealBloomPass.UnrealBloomPass(
|
|
11454
|
+
const bloomPass = new import_UnrealBloomPass.UnrealBloomPass(
|
|
11455
|
+
new THREE3.Vector2(currentMount.clientWidth, currentMount.clientHeight),
|
|
11456
|
+
x_view_config.BLOOM_EFFECT.strength,
|
|
11457
|
+
x_view_config.BLOOM_EFFECT.radius,
|
|
11458
|
+
x_view_config.BLOOM_EFFECT.threshold
|
|
11459
|
+
);
|
|
11217
11460
|
const composer = new import_EffectComposer.EffectComposer(renderer);
|
|
11218
11461
|
composer.addPass(renderScene);
|
|
11219
11462
|
composer.addPass(bloomPass);
|
|
@@ -11256,8 +11499,16 @@ function XViewScene({
|
|
|
11256
11499
|
const sourceNode = nodeObjects[String(linksArray[0].source)];
|
|
11257
11500
|
const targetNode = nodeObjects[String(linksArray[0].target)];
|
|
11258
11501
|
if (sourceNode && targetNode) {
|
|
11259
|
-
const resolution = new THREE3.Vector2(
|
|
11260
|
-
|
|
11502
|
+
const resolution = new THREE3.Vector2(
|
|
11503
|
+
currentMount.clientWidth,
|
|
11504
|
+
currentMount.clientHeight
|
|
11505
|
+
);
|
|
11506
|
+
const newLinks = createMultipleLinkLines(
|
|
11507
|
+
linksArray,
|
|
11508
|
+
sourceNode,
|
|
11509
|
+
targetNode,
|
|
11510
|
+
resolution
|
|
11511
|
+
);
|
|
11261
11512
|
newLinks.forEach((line, idx) => {
|
|
11262
11513
|
const meta = linksArray[idx];
|
|
11263
11514
|
if (meta) {
|
|
@@ -11298,7 +11549,10 @@ function XViewScene({
|
|
|
11298
11549
|
function tryPickNode() {
|
|
11299
11550
|
raycaster.setFromCamera(mouse, camera);
|
|
11300
11551
|
raycaster.layers.enable(GHOST_BLOOM_LAYER);
|
|
11301
|
-
const intersects = raycaster.intersectObjects(
|
|
11552
|
+
const intersects = raycaster.intersectObjects(
|
|
11553
|
+
stateRef.current.clickableNodes,
|
|
11554
|
+
false
|
|
11555
|
+
);
|
|
11302
11556
|
return intersects.length > 0 ? intersects[0].object : null;
|
|
11303
11557
|
}
|
|
11304
11558
|
function findClosestLinkToRay() {
|
|
@@ -11310,7 +11564,10 @@ function XViewScene({
|
|
|
11310
11564
|
x: (mouse.x * 0.5 + 0.5) * clientWidth,
|
|
11311
11565
|
y: (-mouse.y * 0.5 + 0.5) * clientHeight
|
|
11312
11566
|
};
|
|
11313
|
-
const allVisibleLinks = [
|
|
11567
|
+
const allVisibleLinks = [
|
|
11568
|
+
...stateRef.current.allLinks,
|
|
11569
|
+
...stateRef.current.ancestryLinks
|
|
11570
|
+
];
|
|
11314
11571
|
const THRESH = x_view_config.LINE_HOVER_THRESHOLD_PX + 4;
|
|
11315
11572
|
const tmpP1 = new THREE3.Vector3();
|
|
11316
11573
|
const tmpP2 = new THREE3.Vector3();
|
|
@@ -11325,19 +11582,35 @@ function XViewScene({
|
|
|
11325
11582
|
const up = new THREE3.Vector3(0, 1, 0);
|
|
11326
11583
|
const normal = new THREE3.Vector3().crossVectors(dir, up).normalize();
|
|
11327
11584
|
const controlPoint = mid.add(normal.multiplyScalar(curveOffset || 0));
|
|
11328
|
-
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11585
|
+
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11586
|
+
start,
|
|
11587
|
+
controlPoint,
|
|
11588
|
+
end
|
|
11589
|
+
);
|
|
11329
11590
|
const points = curve.getPoints(x_view_config.CURVE_SEGMENTS || 32);
|
|
11330
11591
|
for (let i = 0; i < points.length - 1; i++) {
|
|
11331
11592
|
tmpP1.copy(points[i]).project(camera);
|
|
11332
11593
|
tmpP2.copy(points[i + 1]).project(camera);
|
|
11333
|
-
const p1_px = {
|
|
11334
|
-
|
|
11594
|
+
const p1_px = {
|
|
11595
|
+
x: (tmpP1.x * 0.5 + 0.5) * clientWidth,
|
|
11596
|
+
y: (-tmpP1.y * 0.5 + 0.5) * clientHeight
|
|
11597
|
+
};
|
|
11598
|
+
const p2_px = {
|
|
11599
|
+
x: (tmpP2.x * 0.5 + 0.5) * clientWidth,
|
|
11600
|
+
y: (-tmpP2.y * 0.5 + 0.5) * clientHeight
|
|
11601
|
+
};
|
|
11335
11602
|
const L2 = (p2_px.x - p1_px.x) ** 2 + (p2_px.y - p1_px.y) ** 2;
|
|
11336
11603
|
if (L2 === 0) continue;
|
|
11337
11604
|
let t = ((mousePixels.x - p1_px.x) * (p2_px.x - p1_px.x) + (mousePixels.y - p1_px.y) * (p2_px.y - p1_px.y)) / L2;
|
|
11338
11605
|
t = Math.max(0, Math.min(1, t));
|
|
11339
|
-
const closestPoint = {
|
|
11340
|
-
|
|
11606
|
+
const closestPoint = {
|
|
11607
|
+
x: p1_px.x + t * (p2_px.x - p1_px.x),
|
|
11608
|
+
y: p1_px.y + t * (p2_px.y - p1_px.y)
|
|
11609
|
+
};
|
|
11610
|
+
const dist = Math.hypot(
|
|
11611
|
+
mousePixels.x - closestPoint.x,
|
|
11612
|
+
mousePixels.y - closestPoint.y
|
|
11613
|
+
);
|
|
11341
11614
|
if (dist < THRESH && dist < minDistance) {
|
|
11342
11615
|
minDistance = dist;
|
|
11343
11616
|
closestLink = link;
|
|
@@ -11346,14 +11619,26 @@ function XViewScene({
|
|
|
11346
11619
|
} else {
|
|
11347
11620
|
const p1 = new THREE3.Vector3().copy(sourceNode.position).project(camera);
|
|
11348
11621
|
const p2 = new THREE3.Vector3().copy(targetNode.position).project(camera);
|
|
11349
|
-
const p1_px = {
|
|
11350
|
-
|
|
11622
|
+
const p1_px = {
|
|
11623
|
+
x: (p1.x * 0.5 + 0.5) * clientWidth,
|
|
11624
|
+
y: (-p1.y * 0.5 + 0.5) * clientHeight
|
|
11625
|
+
};
|
|
11626
|
+
const p2_px = {
|
|
11627
|
+
x: (p2.x * 0.5 + 0.5) * clientWidth,
|
|
11628
|
+
y: (-p2.y * 0.5 + 0.5) * clientHeight
|
|
11629
|
+
};
|
|
11351
11630
|
const L2 = (p2_px.x - p1_px.x) ** 2 + (p2_px.y - p1_px.y) ** 2;
|
|
11352
11631
|
if (L2 === 0) return;
|
|
11353
11632
|
let t = ((mousePixels.x - p1_px.x) * (p2_px.x - p1_px.x) + (mousePixels.y - p1_px.y) * (p2_px.y - p1_px.y)) / L2;
|
|
11354
11633
|
t = Math.max(0, Math.min(1, t));
|
|
11355
|
-
const closestPoint = {
|
|
11356
|
-
|
|
11634
|
+
const closestPoint = {
|
|
11635
|
+
x: p1_px.x + t * (p2_px.x - p1_px.x),
|
|
11636
|
+
y: p1_px.y + t * (p2_px.y - p1_px.y)
|
|
11637
|
+
};
|
|
11638
|
+
const dist = Math.hypot(
|
|
11639
|
+
mousePixels.x - closestPoint.x,
|
|
11640
|
+
mousePixels.y - closestPoint.y
|
|
11641
|
+
);
|
|
11357
11642
|
if (dist < THRESH && dist < minDistance) {
|
|
11358
11643
|
minDistance = dist;
|
|
11359
11644
|
closestLink = link;
|
|
@@ -11388,7 +11673,11 @@ function XViewScene({
|
|
|
11388
11673
|
if (picked && !stateRef.current.ancestry.isActive) {
|
|
11389
11674
|
stateRef.current.controls.enabled = false;
|
|
11390
11675
|
}
|
|
11391
|
-
stateRef.current.pointerDown = {
|
|
11676
|
+
stateRef.current.pointerDown = {
|
|
11677
|
+
isDown: true,
|
|
11678
|
+
x: event.clientX,
|
|
11679
|
+
y: event.clientY
|
|
11680
|
+
};
|
|
11392
11681
|
stateRef.current.dragCandidate = picked;
|
|
11393
11682
|
}
|
|
11394
11683
|
function onPointerMove(event) {
|
|
@@ -11399,7 +11688,10 @@ function XViewScene({
|
|
|
11399
11688
|
const raycaster2 = new THREE3.Raycaster();
|
|
11400
11689
|
raycaster2.setFromCamera(mouse, camera);
|
|
11401
11690
|
camera.getWorldDirection(plane.normal);
|
|
11402
|
-
plane.setFromNormalAndCoplanarPoint(
|
|
11691
|
+
plane.setFromNormalAndCoplanarPoint(
|
|
11692
|
+
plane.normal,
|
|
11693
|
+
stateRef.current.draggedNode.position
|
|
11694
|
+
);
|
|
11403
11695
|
if (raycaster2.ray.intersectPlane(plane, intersectionPoint)) {
|
|
11404
11696
|
const draggedNode = stateRef.current.draggedNode;
|
|
11405
11697
|
draggedNode.position.copy(intersectionPoint);
|
|
@@ -11408,7 +11700,8 @@ function XViewScene({
|
|
|
11408
11700
|
}
|
|
11409
11701
|
if (stateRef.current.connection.isActive || stateRef.current.relink.isActive || stateRef.current.ancestry.isActive) {
|
|
11410
11702
|
const newHoveredNode2 = tryPickNode();
|
|
11411
|
-
if (stateRef.current.hoveredNode !== newHoveredNode2)
|
|
11703
|
+
if (stateRef.current.hoveredNode !== newHoveredNode2)
|
|
11704
|
+
stateRef.current.hoveredNode = newHoveredNode2;
|
|
11412
11705
|
if (currentMount) {
|
|
11413
11706
|
let fixedId = null;
|
|
11414
11707
|
if (stateRef.current.connection.isActive) {
|
|
@@ -11439,14 +11732,20 @@ function XViewScene({
|
|
|
11439
11732
|
stateRef.current.controls.enabled = false;
|
|
11440
11733
|
if (currentMount) currentMount.style.cursor = "grabbing";
|
|
11441
11734
|
camera.getWorldDirection(plane.normal);
|
|
11442
|
-
plane.setFromNormalAndCoplanarPoint(
|
|
11735
|
+
plane.setFromNormalAndCoplanarPoint(
|
|
11736
|
+
plane.normal,
|
|
11737
|
+
stateRef.current.draggedNode.position
|
|
11738
|
+
);
|
|
11443
11739
|
}
|
|
11444
11740
|
}
|
|
11445
11741
|
const newHoveredNode = tryPickNode();
|
|
11446
11742
|
const newHoveredLink = !newHoveredNode ? findClosestLinkToRay() : null;
|
|
11447
|
-
if (stateRef.current.hoveredNode !== newHoveredNode)
|
|
11448
|
-
|
|
11449
|
-
if (
|
|
11743
|
+
if (stateRef.current.hoveredNode !== newHoveredNode)
|
|
11744
|
+
stateRef.current.hoveredNode = newHoveredNode;
|
|
11745
|
+
if (stateRef.current.hoveredLink !== newHoveredLink)
|
|
11746
|
+
stateRef.current.hoveredLink = newHoveredLink;
|
|
11747
|
+
if (currentMount)
|
|
11748
|
+
currentMount.style.cursor = newHoveredNode || newHoveredLink ? "pointer" : "grab";
|
|
11450
11749
|
}
|
|
11451
11750
|
const isNodeInTree = (tree, nodeId) => {
|
|
11452
11751
|
if (!tree) return false;
|
|
@@ -11461,7 +11760,10 @@ function XViewScene({
|
|
|
11461
11760
|
const context = actionHandlerContext;
|
|
11462
11761
|
if (connection.isActive) {
|
|
11463
11762
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(connection.sourceNodeData.id)) {
|
|
11464
|
-
await userActionHandlers.handleCompleteConnection(
|
|
11763
|
+
await userActionHandlers.handleCompleteConnection(
|
|
11764
|
+
context,
|
|
11765
|
+
hoveredNode.userData
|
|
11766
|
+
);
|
|
11465
11767
|
} else {
|
|
11466
11768
|
userActionHandlers.handleCancelConnection(context);
|
|
11467
11769
|
}
|
|
@@ -11469,7 +11771,10 @@ function XViewScene({
|
|
|
11469
11771
|
}
|
|
11470
11772
|
if (relink.isActive) {
|
|
11471
11773
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(relink.fixedNodeId)) {
|
|
11472
|
-
await userActionHandlers.handleCompleteRelink(
|
|
11774
|
+
await userActionHandlers.handleCompleteRelink(
|
|
11775
|
+
context,
|
|
11776
|
+
hoveredNode.userData
|
|
11777
|
+
);
|
|
11473
11778
|
} else {
|
|
11474
11779
|
userActionHandlers.handleCancelRelink(context);
|
|
11475
11780
|
}
|
|
@@ -11487,7 +11792,9 @@ function XViewScene({
|
|
|
11487
11792
|
const clickedNodeId = String(clickedNode.userData.id);
|
|
11488
11793
|
const parentId = String(currentSelectedParent);
|
|
11489
11794
|
if (clickedNodeId === parentId) {
|
|
11490
|
-
alert(
|
|
11795
|
+
alert(
|
|
11796
|
+
"Erro: N\xE3o \xE9 poss\xEDvel adicionar um Node como filho dele mesmo."
|
|
11797
|
+
);
|
|
11491
11798
|
return;
|
|
11492
11799
|
}
|
|
11493
11800
|
const parentInfo = stateRef.current.nodeIdToParentFileMap.get(clickedNodeId);
|
|
@@ -11497,16 +11804,33 @@ function XViewScene({
|
|
|
11497
11804
|
const addChildToNode = (current, targetParentId, childNode) => {
|
|
11498
11805
|
const currentId = current.is_section ? current.id || current.section_id : String(current.node.id);
|
|
11499
11806
|
if (String(currentId) === String(targetParentId)) {
|
|
11500
|
-
const alreadyExists = current.children.some(
|
|
11807
|
+
const alreadyExists = current.children.some(
|
|
11808
|
+
(child) => !child.is_section && String(child.node.id) === String(childNode.id)
|
|
11809
|
+
);
|
|
11501
11810
|
if (alreadyExists) return current;
|
|
11502
|
-
return {
|
|
11811
|
+
return {
|
|
11812
|
+
...current,
|
|
11813
|
+
children: [
|
|
11814
|
+
...current.children,
|
|
11815
|
+
{ node: childNode, children: [], relationship: {} }
|
|
11816
|
+
]
|
|
11817
|
+
};
|
|
11503
11818
|
}
|
|
11504
|
-
return {
|
|
11819
|
+
return {
|
|
11820
|
+
...current,
|
|
11821
|
+
children: current.children.map(
|
|
11822
|
+
(c) => addChildToNode(c, targetParentId, childNode)
|
|
11823
|
+
)
|
|
11824
|
+
};
|
|
11505
11825
|
};
|
|
11506
11826
|
setAncestryMode((prev) => {
|
|
11507
11827
|
const treeKey = isAbstraction ? "abstraction_tree" : "tree";
|
|
11508
11828
|
if (!prev[treeKey]) return prev;
|
|
11509
|
-
const newTree = addChildToNode(
|
|
11829
|
+
const newTree = addChildToNode(
|
|
11830
|
+
prev[treeKey],
|
|
11831
|
+
parentId,
|
|
11832
|
+
fullNodeData
|
|
11833
|
+
);
|
|
11510
11834
|
return { ...prev, [treeKey]: newTree };
|
|
11511
11835
|
});
|
|
11512
11836
|
}
|
|
@@ -11520,7 +11844,8 @@ function XViewScene({
|
|
|
11520
11844
|
stateRef.current.dragCandidate = null;
|
|
11521
11845
|
stateRef.current.pointerDown.isDown = false;
|
|
11522
11846
|
stateRef.current.controls.enabled = true;
|
|
11523
|
-
if (currentMount)
|
|
11847
|
+
if (currentMount)
|
|
11848
|
+
currentMount.style.cursor = stateRef.current.hoveredNode || stateRef.current.hoveredLink ? "pointer" : "grab";
|
|
11524
11849
|
return;
|
|
11525
11850
|
}
|
|
11526
11851
|
const dragDistance = Math.hypot(
|
|
@@ -11568,16 +11893,21 @@ function XViewScene({
|
|
|
11568
11893
|
}
|
|
11569
11894
|
function handleDoubleClick(event) {
|
|
11570
11895
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
11571
|
-
if (isFromUiOverlay(event) || stateRef.current.isDragging || stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11572
|
-
|
|
11896
|
+
if (isFromUiOverlay(event) || stateRef.current.isDragging || stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11897
|
+
return;
|
|
11898
|
+
if (stateRef.current.hoveredNode)
|
|
11899
|
+
tweenToTarget(stateRef.current.hoveredNode);
|
|
11573
11900
|
}
|
|
11574
11901
|
function handleContextMenu(event) {
|
|
11575
11902
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
11576
11903
|
if (isFromUiOverlay(event)) return;
|
|
11577
11904
|
event.preventDefault();
|
|
11578
|
-
if (stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11905
|
+
if (stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive)
|
|
11906
|
+
return;
|
|
11579
11907
|
setMouseFromEvent(event);
|
|
11580
|
-
setContextMenu(
|
|
11908
|
+
setContextMenu(
|
|
11909
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
11910
|
+
);
|
|
11581
11911
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
11582
11912
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
11583
11913
|
const pickedNode = tryPickNode();
|
|
@@ -11608,7 +11938,12 @@ function XViewScene({
|
|
|
11608
11938
|
return;
|
|
11609
11939
|
}
|
|
11610
11940
|
stateRef.current.selectedNodes.clear();
|
|
11611
|
-
setRelationshipMenu({
|
|
11941
|
+
setRelationshipMenu({
|
|
11942
|
+
visible: true,
|
|
11943
|
+
x: event.clientX,
|
|
11944
|
+
y: event.clientY,
|
|
11945
|
+
linkObject: pickedLink
|
|
11946
|
+
});
|
|
11612
11947
|
return;
|
|
11613
11948
|
}
|
|
11614
11949
|
stateRef.current.selectedNodes.clear();
|
|
@@ -11640,7 +11975,10 @@ function XViewScene({
|
|
|
11640
11975
|
}
|
|
11641
11976
|
});
|
|
11642
11977
|
}
|
|
11643
|
-
const allRenderedLinks = [
|
|
11978
|
+
const allRenderedLinks = [
|
|
11979
|
+
...stateRef.current.allLinks,
|
|
11980
|
+
...stateRef.current.ancestryLinks
|
|
11981
|
+
];
|
|
11644
11982
|
allRenderedLinks.forEach((line) => {
|
|
11645
11983
|
const { sourceNode, targetNode, isCurved, curveOffset } = line.userData;
|
|
11646
11984
|
if (sourceNode && targetNode) {
|
|
@@ -11652,13 +11990,20 @@ function XViewScene({
|
|
|
11652
11990
|
const up = new THREE3.Vector3(0, 1, 0);
|
|
11653
11991
|
const normal = new THREE3.Vector3().crossVectors(dir, up).normalize();
|
|
11654
11992
|
const controlPoint = mid.add(normal.multiplyScalar(curveOffset));
|
|
11655
|
-
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11993
|
+
const curve = new THREE3.QuadraticBezierCurve3(
|
|
11994
|
+
start,
|
|
11995
|
+
controlPoint,
|
|
11996
|
+
end
|
|
11997
|
+
);
|
|
11656
11998
|
const points = curve.getPoints(x_view_config.CURVE_SEGMENTS);
|
|
11657
11999
|
const positions = [];
|
|
11658
12000
|
points.forEach((p) => positions.push(p.x, p.y, p.z));
|
|
11659
12001
|
line.geometry.setPositions(positions);
|
|
11660
12002
|
} else {
|
|
11661
|
-
line.geometry.setPositions([
|
|
12003
|
+
line.geometry.setPositions([
|
|
12004
|
+
...sourceNode.position.toArray(),
|
|
12005
|
+
...targetNode.position.toArray()
|
|
12006
|
+
]);
|
|
11662
12007
|
}
|
|
11663
12008
|
}
|
|
11664
12009
|
});
|
|
@@ -11671,7 +12016,11 @@ function XViewScene({
|
|
|
11671
12016
|
const startPos = node.position;
|
|
11672
12017
|
const distance = startPos.distanceTo(endPos);
|
|
11673
12018
|
bar.scale.y = distance;
|
|
11674
|
-
const midpoint = new THREE3.Vector3().lerpVectors(
|
|
12019
|
+
const midpoint = new THREE3.Vector3().lerpVectors(
|
|
12020
|
+
startPos,
|
|
12021
|
+
endPos,
|
|
12022
|
+
0.5
|
|
12023
|
+
);
|
|
11675
12024
|
bar.position.copy(midpoint);
|
|
11676
12025
|
const direction = new THREE3.Vector3().subVectors(endPos, startPos).normalize();
|
|
11677
12026
|
const upVector = new THREE3.Vector3(0, 1, 0);
|
|
@@ -11682,7 +12031,11 @@ function XViewScene({
|
|
|
11682
12031
|
const { ghostElements, creation, connection, relink } = stateRef.current;
|
|
11683
12032
|
if (creation.isActive && ghostElements.node && ghostElements.line) {
|
|
11684
12033
|
const srcMesh = stateRef.current.nodeObjects[String(creation.sourceNodeData.id)];
|
|
11685
|
-
if (srcMesh)
|
|
12034
|
+
if (srcMesh)
|
|
12035
|
+
ghostElements.line.geometry.setPositions([
|
|
12036
|
+
...srcMesh.position.toArray(),
|
|
12037
|
+
...ghostElements.node.position.toArray()
|
|
12038
|
+
]);
|
|
11686
12039
|
}
|
|
11687
12040
|
if (connection.isActive && connection.line) {
|
|
11688
12041
|
const srcMesh = stateRef.current.nodeObjects[String(connection.sourceNodeData.id)];
|
|
@@ -11691,7 +12044,11 @@ function XViewScene({
|
|
|
11691
12044
|
raycaster2.setFromCamera(mouse, camera);
|
|
11692
12045
|
camera.getWorldDirection(plane.normal);
|
|
11693
12046
|
plane.setFromNormalAndCoplanarPoint(plane.normal, srcMesh.position);
|
|
11694
|
-
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12047
|
+
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12048
|
+
connection.line.geometry.setPositions([
|
|
12049
|
+
...srcMesh.position.toArray(),
|
|
12050
|
+
...intersectionPoint.toArray()
|
|
12051
|
+
]);
|
|
11695
12052
|
}
|
|
11696
12053
|
}
|
|
11697
12054
|
if (relink.isActive && relink.line) {
|
|
@@ -11701,7 +12058,11 @@ function XViewScene({
|
|
|
11701
12058
|
raycaster2.setFromCamera(mouse, camera);
|
|
11702
12059
|
camera.getWorldDirection(plane.normal);
|
|
11703
12060
|
plane.setFromNormalAndCoplanarPoint(plane.normal, fixedMesh.position);
|
|
11704
|
-
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12061
|
+
if (raycaster2.ray.intersectPlane(plane, intersectionPoint))
|
|
12062
|
+
relink.line.geometry.setPositions([
|
|
12063
|
+
...fixedMesh.position.toArray(),
|
|
12064
|
+
...intersectionPoint.toArray()
|
|
12065
|
+
]);
|
|
11705
12066
|
}
|
|
11706
12067
|
}
|
|
11707
12068
|
Object.values(stateRef.current.nodeObjects).forEach((node) => {
|
|
@@ -11745,11 +12106,18 @@ function XViewScene({
|
|
|
11745
12106
|
renderer.setSize(clientWidth, clientHeight);
|
|
11746
12107
|
composer.setSize(clientWidth, clientHeight);
|
|
11747
12108
|
const resVec = new THREE3.Vector2(clientWidth, clientHeight);
|
|
11748
|
-
stateRef.current.allLinks.forEach(
|
|
11749
|
-
|
|
11750
|
-
|
|
11751
|
-
|
|
11752
|
-
|
|
12109
|
+
stateRef.current.allLinks.forEach(
|
|
12110
|
+
(line) => line.material.resolution.copy(resVec)
|
|
12111
|
+
);
|
|
12112
|
+
stateRef.current.ancestryLinks.forEach(
|
|
12113
|
+
(line) => line.material.resolution.copy(resVec)
|
|
12114
|
+
);
|
|
12115
|
+
if (stateRef.current.ghostElements.line)
|
|
12116
|
+
stateRef.current.ghostElements.line.material.resolution.copy(resVec);
|
|
12117
|
+
if (stateRef.current.connection.line)
|
|
12118
|
+
stateRef.current.connection.line.material.resolution.copy(resVec);
|
|
12119
|
+
if (stateRef.current.relink.line)
|
|
12120
|
+
stateRef.current.relink.line.material.resolution.copy(resVec);
|
|
11753
12121
|
}
|
|
11754
12122
|
window.addEventListener("resize", handleResize);
|
|
11755
12123
|
return () => {
|
|
@@ -11769,14 +12137,16 @@ function XViewScene({
|
|
|
11769
12137
|
ancestryGroup.traverse((obj) => {
|
|
11770
12138
|
if (obj.geometry) obj.geometry.dispose();
|
|
11771
12139
|
if (obj.material) {
|
|
11772
|
-
if (Array.isArray(obj.material))
|
|
12140
|
+
if (Array.isArray(obj.material))
|
|
12141
|
+
obj.material.forEach((m) => m.dispose());
|
|
11773
12142
|
else obj.material.dispose();
|
|
11774
12143
|
}
|
|
11775
12144
|
});
|
|
11776
12145
|
graphGroup.traverse((obj) => {
|
|
11777
12146
|
if (obj.geometry) obj.geometry.dispose();
|
|
11778
12147
|
if (obj.material) {
|
|
11779
|
-
if (Array.isArray(obj.material))
|
|
12148
|
+
if (Array.isArray(obj.material))
|
|
12149
|
+
obj.material.forEach((m) => m.dispose());
|
|
11780
12150
|
else obj.material.dispose();
|
|
11781
12151
|
}
|
|
11782
12152
|
});
|
|
@@ -11787,9 +12157,22 @@ function XViewScene({
|
|
|
11787
12157
|
currentMount.removeChild(renderer.domElement);
|
|
11788
12158
|
}
|
|
11789
12159
|
};
|
|
11790
|
-
}, [
|
|
12160
|
+
}, [
|
|
12161
|
+
isInitialized,
|
|
12162
|
+
tweenToTarget,
|
|
12163
|
+
dbSaveUrl,
|
|
12164
|
+
isNodeInView,
|
|
12165
|
+
addOrUpdateNodeMesh,
|
|
12166
|
+
handleActivateTimeline,
|
|
12167
|
+
get_scene_view_data,
|
|
12168
|
+
save_view_data
|
|
12169
|
+
]);
|
|
11791
12170
|
const handleGhostNodeImageChange = (0, import_react26.useCallback)((useImage, imageUrl) => {
|
|
11792
|
-
const {
|
|
12171
|
+
const {
|
|
12172
|
+
node: ghostNode,
|
|
12173
|
+
line: ghostLine,
|
|
12174
|
+
aura: ghostAura
|
|
12175
|
+
} = stateRef.current.ghostElements;
|
|
11793
12176
|
const { graphGroup, glowTexture } = stateRef.current;
|
|
11794
12177
|
if (!ghostNode || !graphGroup) return;
|
|
11795
12178
|
const currentData = {
|
|
@@ -11800,13 +12183,15 @@ function XViewScene({
|
|
|
11800
12183
|
const position = ghostNode.position.clone();
|
|
11801
12184
|
if (ghostNode.userData.labelObject) {
|
|
11802
12185
|
graphGroup.remove(ghostNode.userData.labelObject);
|
|
11803
|
-
if (ghostNode.userData.labelObject.material.map)
|
|
12186
|
+
if (ghostNode.userData.labelObject.material.map)
|
|
12187
|
+
ghostNode.userData.labelObject.material.map.dispose();
|
|
11804
12188
|
ghostNode.userData.labelObject.material.dispose();
|
|
11805
12189
|
}
|
|
11806
12190
|
graphGroup.remove(ghostNode);
|
|
11807
12191
|
if (ghostNode.geometry) ghostNode.geometry.dispose();
|
|
11808
12192
|
if (ghostNode.material) {
|
|
11809
|
-
if (Array.isArray(ghostNode.material))
|
|
12193
|
+
if (Array.isArray(ghostNode.material))
|
|
12194
|
+
ghostNode.material.forEach((m) => m.dispose());
|
|
11810
12195
|
else ghostNode.material.dispose();
|
|
11811
12196
|
}
|
|
11812
12197
|
const newGhostNode = createNodeMesh(currentData, position, glowTexture);
|
|
@@ -11851,28 +12236,31 @@ function XViewScene({
|
|
|
11851
12236
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11852
12237
|
}
|
|
11853
12238
|
}, []);
|
|
11854
|
-
const handleDetailNodeIntensityChange = (0, import_react26.useCallback)(
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
borderMesh.material
|
|
12239
|
+
const handleDetailNodeIntensityChange = (0, import_react26.useCallback)(
|
|
12240
|
+
(nodeId, newIntensity) => {
|
|
12241
|
+
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
12242
|
+
if (!mesh) return;
|
|
12243
|
+
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
12244
|
+
mesh.userData.intensity = newIntensity;
|
|
12245
|
+
mesh.userData._baseEmissiveIntensity = adjustedIntensity;
|
|
12246
|
+
const isImageNode = mesh.userData.useImageAsTexture === true;
|
|
12247
|
+
if (isImageNode) {
|
|
12248
|
+
const borderMesh = mesh.getObjectByName("borderRing");
|
|
12249
|
+
if (borderMesh && borderMesh.material) {
|
|
12250
|
+
borderMesh.material.emissiveIntensity = adjustedIntensity;
|
|
12251
|
+
}
|
|
12252
|
+
} else {
|
|
12253
|
+
if (mesh.material) {
|
|
12254
|
+
mesh.material.emissiveIntensity = adjustedIntensity;
|
|
12255
|
+
}
|
|
11865
12256
|
}
|
|
11866
|
-
|
|
11867
|
-
if (
|
|
11868
|
-
|
|
12257
|
+
const aura = mesh.getObjectByName("aura");
|
|
12258
|
+
if (aura && aura.material) {
|
|
12259
|
+
aura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11869
12260
|
}
|
|
11870
|
-
}
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
aura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11874
|
-
}
|
|
11875
|
-
}, []);
|
|
12261
|
+
},
|
|
12262
|
+
[]
|
|
12263
|
+
);
|
|
11876
12264
|
const handleGhostNodeColorChange = (newColor) => {
|
|
11877
12265
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11878
12266
|
if (!ghostNode) return;
|
|
@@ -11983,7 +12371,9 @@ function XViewScene({
|
|
|
11983
12371
|
mesh.userData.size = newSize;
|
|
11984
12372
|
};
|
|
11985
12373
|
const handleStartAncestryCreation = (nodeData) => {
|
|
11986
|
-
setContextMenu(
|
|
12374
|
+
setContextMenu(
|
|
12375
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
12376
|
+
);
|
|
11987
12377
|
stateRef.current.maxAncestryRenderIndex = 0;
|
|
11988
12378
|
setAncestryMode({
|
|
11989
12379
|
isActive: true,
|
|
@@ -12008,9 +12398,12 @@ function XViewScene({
|
|
|
12008
12398
|
const newTreeStr = JSON.stringify(newTree);
|
|
12009
12399
|
let metaChanged = false;
|
|
12010
12400
|
if (extraData) {
|
|
12011
|
-
if (extraData.ancestryName !== void 0 && extraData.ancestryName !== prev.ancestryName)
|
|
12012
|
-
|
|
12013
|
-
if (extraData.
|
|
12401
|
+
if (extraData.ancestryName !== void 0 && extraData.ancestryName !== prev.ancestryName)
|
|
12402
|
+
metaChanged = true;
|
|
12403
|
+
if (extraData.ancestryDescription !== void 0 && extraData.ancestryDescription !== prev.ancestryDescription)
|
|
12404
|
+
metaChanged = true;
|
|
12405
|
+
if (extraData.ancestryDescriptionSections !== void 0 && JSON.stringify(extraData.ancestryDescriptionSections) !== JSON.stringify(prev.ancestryDescriptionSections))
|
|
12406
|
+
metaChanged = true;
|
|
12014
12407
|
}
|
|
12015
12408
|
if (prevTreeStr === newTreeStr && !metaChanged) {
|
|
12016
12409
|
return prev;
|
|
@@ -12088,13 +12481,15 @@ function XViewScene({
|
|
|
12088
12481
|
if (ghostElements.node && graphGroup) {
|
|
12089
12482
|
if (ghostElements.node.userData.labelObject) {
|
|
12090
12483
|
graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
12091
|
-
if (ghostElements.node.userData.labelObject.material.map)
|
|
12484
|
+
if (ghostElements.node.userData.labelObject.material.map)
|
|
12485
|
+
ghostElements.node.userData.labelObject.material.map.dispose();
|
|
12092
12486
|
ghostElements.node.userData.labelObject.material.dispose();
|
|
12093
12487
|
}
|
|
12094
12488
|
graphGroup.remove(ghostElements.node);
|
|
12095
12489
|
ghostElements.node.traverse((child) => {
|
|
12096
12490
|
if (child.material) {
|
|
12097
|
-
if (Array.isArray(child.material))
|
|
12491
|
+
if (Array.isArray(child.material))
|
|
12492
|
+
child.material.forEach((m) => m.dispose());
|
|
12098
12493
|
else child.material.dispose();
|
|
12099
12494
|
}
|
|
12100
12495
|
if (child.geometry) child.geometry.dispose();
|
|
@@ -12104,7 +12499,17 @@ function XViewScene({
|
|
|
12104
12499
|
setQuestMode({ isActive: false });
|
|
12105
12500
|
}, []);
|
|
12106
12501
|
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
12107
|
-
const {
|
|
12502
|
+
const {
|
|
12503
|
+
graphDataRef,
|
|
12504
|
+
sceneDataRef: sceneDataRef2,
|
|
12505
|
+
stateRef: stateRef2,
|
|
12506
|
+
setters,
|
|
12507
|
+
actions,
|
|
12508
|
+
sceneSaveUrl: sceneSaveUrl2,
|
|
12509
|
+
viewType,
|
|
12510
|
+
sceneConfigId: sceneConfigId2,
|
|
12511
|
+
ownerId: ownerId2
|
|
12512
|
+
} = context;
|
|
12108
12513
|
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
12109
12514
|
const currentCounter = sceneDataRef2.current.quest_counter || 1;
|
|
12110
12515
|
const newNode = {
|
|
@@ -12137,7 +12542,8 @@ function XViewScene({
|
|
|
12137
12542
|
const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
|
|
12138
12543
|
const { graphGroup, ghostElements } = stateRef2.current;
|
|
12139
12544
|
if (ghostElements.node && graphGroup) {
|
|
12140
|
-
if (ghostElements.node.userData.labelObject)
|
|
12545
|
+
if (ghostElements.node.userData.labelObject)
|
|
12546
|
+
graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
12141
12547
|
graphGroup.remove(ghostElements.node);
|
|
12142
12548
|
}
|
|
12143
12549
|
stateRef2.current.ghostElements = { node: null, line: null, aura: null };
|
|
@@ -12151,14 +12557,33 @@ function XViewScene({
|
|
|
12151
12557
|
}
|
|
12152
12558
|
};
|
|
12153
12559
|
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
12154
|
-
const {
|
|
12560
|
+
const {
|
|
12561
|
+
stateRef: stateRef2,
|
|
12562
|
+
graphDataRef,
|
|
12563
|
+
sceneDataRef: sceneDataRef2,
|
|
12564
|
+
sceneConfigId: sceneConfigId2,
|
|
12565
|
+
sceneSaveUrl: sceneSaveUrl2,
|
|
12566
|
+
ownerId: ownerId2
|
|
12567
|
+
} = context;
|
|
12155
12568
|
const { sourceNodeData } = stateRef2.current.connection;
|
|
12156
12569
|
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
12157
12570
|
userActionHandlers.handleCancelConnection(context);
|
|
12158
12571
|
return;
|
|
12159
12572
|
}
|
|
12160
|
-
const sourceParentInfo = getParentFileInfoForNode(
|
|
12161
|
-
|
|
12573
|
+
const sourceParentInfo = getParentFileInfoForNode(
|
|
12574
|
+
graphDataRef.current,
|
|
12575
|
+
sceneDataRef2.current,
|
|
12576
|
+
sourceNodeData.id,
|
|
12577
|
+
sceneConfigId2,
|
|
12578
|
+
ownerId2
|
|
12579
|
+
);
|
|
12580
|
+
const targetParentInfo = getParentFileInfoForNode(
|
|
12581
|
+
graphDataRef.current,
|
|
12582
|
+
sceneDataRef2.current,
|
|
12583
|
+
targetNodeData.id,
|
|
12584
|
+
sceneConfigId2,
|
|
12585
|
+
ownerId2
|
|
12586
|
+
);
|
|
12162
12587
|
let parentInfoToSave = sourceParentInfo;
|
|
12163
12588
|
const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
|
|
12164
12589
|
const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
|
|
@@ -12184,10 +12609,15 @@ function XViewScene({
|
|
|
12184
12609
|
};
|
|
12185
12610
|
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
12186
12611
|
} else {
|
|
12187
|
-
const specificParentData = JSON.parse(
|
|
12612
|
+
const specificParentData = JSON.parse(
|
|
12613
|
+
JSON.stringify(graphDataRef.current[parentFileIdToSave])
|
|
12614
|
+
);
|
|
12188
12615
|
specificParentData.links.push(newLink);
|
|
12189
12616
|
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
12190
|
-
await context.actions.save_view_data(
|
|
12617
|
+
await context.actions.save_view_data(
|
|
12618
|
+
filenameForSpecificParent,
|
|
12619
|
+
specificParentData
|
|
12620
|
+
);
|
|
12191
12621
|
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
12192
12622
|
}
|
|
12193
12623
|
addNewLinkToScene(stateRef2.current, newLink);
|
|
@@ -12199,7 +12629,9 @@ function XViewScene({
|
|
|
12199
12629
|
};
|
|
12200
12630
|
const handleClearAncestryVisuals = (0, import_react26.useCallback)((ancestryId) => {
|
|
12201
12631
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
12202
|
-
const renderIndex = renderedAncestries.findIndex(
|
|
12632
|
+
const renderIndex = renderedAncestries.findIndex(
|
|
12633
|
+
(a) => String(a.id) === String(ancestryId)
|
|
12634
|
+
);
|
|
12203
12635
|
if (renderIndex !== -1) {
|
|
12204
12636
|
const toRemove = renderedAncestries[renderIndex];
|
|
12205
12637
|
toRemove.lines.forEach((line) => {
|
|
@@ -12208,12 +12640,16 @@ function XViewScene({
|
|
|
12208
12640
|
if (line.material) line.material.dispose();
|
|
12209
12641
|
});
|
|
12210
12642
|
renderedAncestries.splice(renderIndex, 1);
|
|
12211
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
12643
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
12644
|
+
(a) => a.lines
|
|
12645
|
+
);
|
|
12212
12646
|
}
|
|
12213
12647
|
}, []);
|
|
12214
12648
|
const handleRenderAncestry = (0, import_react26.useCallback)(
|
|
12215
12649
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
12216
|
-
setContextMenu(
|
|
12650
|
+
setContextMenu(
|
|
12651
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
12652
|
+
);
|
|
12217
12653
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
12218
12654
|
return;
|
|
12219
12655
|
}
|
|
@@ -12240,14 +12676,16 @@ function XViewScene({
|
|
|
12240
12676
|
if (numId !== void 0 && normalizedAllowedIds.has(numId)) return true;
|
|
12241
12677
|
if (strId && normalizedAllowedIds.has(strId)) return true;
|
|
12242
12678
|
if (strSecId && normalizedAllowedIds.has(strSecId)) return true;
|
|
12243
|
-
if (numId !== void 0 && normalizedAllowedIds.has(String(numId)))
|
|
12679
|
+
if (numId !== void 0 && normalizedAllowedIds.has(String(numId)))
|
|
12680
|
+
return true;
|
|
12244
12681
|
return false;
|
|
12245
12682
|
};
|
|
12246
12683
|
const checkIsActive = (section, targetId) => {
|
|
12247
12684
|
if (targetId === null || targetId === void 0) return false;
|
|
12248
12685
|
const sTarget = String(targetId);
|
|
12249
12686
|
if (section.id && String(section.id) === sTarget) return true;
|
|
12250
|
-
if (section.section_id && String(section.section_id) === sTarget)
|
|
12687
|
+
if (section.section_id && String(section.section_id) === sTarget)
|
|
12688
|
+
return true;
|
|
12251
12689
|
if (section.section_numeric_id !== void 0) {
|
|
12252
12690
|
if (String(section.section_numeric_id) === sTarget) return true;
|
|
12253
12691
|
}
|
|
@@ -12263,7 +12701,9 @@ function XViewScene({
|
|
|
12263
12701
|
traverse(sectionTree);
|
|
12264
12702
|
return ids;
|
|
12265
12703
|
};
|
|
12266
|
-
const existingIndex = renderedAncestries.findIndex(
|
|
12704
|
+
const existingIndex = renderedAncestries.findIndex(
|
|
12705
|
+
(a) => String(a.id) === String(ancestryObject.ancestry_id)
|
|
12706
|
+
);
|
|
12267
12707
|
let skipGeneration = false;
|
|
12268
12708
|
let ancestryEntry = null;
|
|
12269
12709
|
if (existingIndex !== -1) {
|
|
@@ -12318,9 +12758,15 @@ function XViewScene({
|
|
|
12318
12758
|
if (line.material) line.material.dispose();
|
|
12319
12759
|
});
|
|
12320
12760
|
}
|
|
12321
|
-
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
12761
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
12762
|
+
(fileData) => fileData.nodes
|
|
12763
|
+
);
|
|
12322
12764
|
const allAncestries = ancestryDataRef.current || [];
|
|
12323
|
-
const fullTree = buildFullAncestryTree(
|
|
12765
|
+
const fullTree = buildFullAncestryTree(
|
|
12766
|
+
ancestryObject.tree,
|
|
12767
|
+
allParentNodes,
|
|
12768
|
+
allAncestries
|
|
12769
|
+
);
|
|
12324
12770
|
if (!fullTree) return;
|
|
12325
12771
|
const rootNodeId = String(ancestryObject.ancestral_node);
|
|
12326
12772
|
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
@@ -12363,7 +12809,10 @@ function XViewScene({
|
|
|
12363
12809
|
const colorIndex = stateRef.current.ancestryRenderCounter % 3;
|
|
12364
12810
|
colorHex = ANCESTRY_COLORS[colorIndex];
|
|
12365
12811
|
}
|
|
12366
|
-
const resolution = new THREE3.Vector2(
|
|
12812
|
+
const resolution = new THREE3.Vector2(
|
|
12813
|
+
renderer.domElement.clientWidth,
|
|
12814
|
+
renderer.domElement.clientHeight
|
|
12815
|
+
);
|
|
12367
12816
|
const cleanupLinesForNode = (nodeId) => {
|
|
12368
12817
|
if (!ancestryEntry || !ancestryEntry.lines) return;
|
|
12369
12818
|
const linesKeep = [];
|
|
@@ -12403,7 +12852,13 @@ function XViewScene({
|
|
|
12403
12852
|
}
|
|
12404
12853
|
if (originMesh && rootNodeMesh) {
|
|
12405
12854
|
cleanupLinesForNode(rootNodeId);
|
|
12406
|
-
const branchLine = createAncestryLinkLine(
|
|
12855
|
+
const branchLine = createAncestryLinkLine(
|
|
12856
|
+
originMesh,
|
|
12857
|
+
rootNodeMesh,
|
|
12858
|
+
resolution,
|
|
12859
|
+
{},
|
|
12860
|
+
colorHex
|
|
12861
|
+
);
|
|
12407
12862
|
ancestryGroup.add(branchLine);
|
|
12408
12863
|
ancestryEntry.lines.push(branchLine);
|
|
12409
12864
|
}
|
|
@@ -12414,8 +12869,14 @@ function XViewScene({
|
|
|
12414
12869
|
if (!children || children.length === 0) return null;
|
|
12415
12870
|
let lastRenderedMesh = null;
|
|
12416
12871
|
const numChildren = children.length;
|
|
12417
|
-
const forwardVec = new THREE3.Vector3(0, 0, 1).applyAxisAngle(
|
|
12418
|
-
|
|
12872
|
+
const forwardVec = new THREE3.Vector3(0, 0, 1).applyAxisAngle(
|
|
12873
|
+
new THREE3.Vector3(0, 1, 0),
|
|
12874
|
+
currentAngle
|
|
12875
|
+
);
|
|
12876
|
+
const rightVec = new THREE3.Vector3(1, 0, 0).applyAxisAngle(
|
|
12877
|
+
new THREE3.Vector3(0, 1, 0),
|
|
12878
|
+
currentAngle
|
|
12879
|
+
);
|
|
12419
12880
|
const angleRange = numChildren > 3 ? Math.PI : Math.PI / 1.5;
|
|
12420
12881
|
children.forEach((childItem, index) => {
|
|
12421
12882
|
if (childItem.is_section) return;
|
|
@@ -12436,14 +12897,30 @@ function XViewScene({
|
|
|
12436
12897
|
targetPositionsCache.set(sNodeId, childPosition.clone());
|
|
12437
12898
|
cleanupLinesForNode(sNodeId);
|
|
12438
12899
|
}
|
|
12439
|
-
const childMesh = addOrUpdateNodeMesh(
|
|
12900
|
+
const childMesh = addOrUpdateNodeMesh(
|
|
12901
|
+
childItem.node,
|
|
12902
|
+
childPosition,
|
|
12903
|
+
true
|
|
12904
|
+
);
|
|
12440
12905
|
allRenderedNodePositions.push(childPosition);
|
|
12441
|
-
const line = createAncestryLinkLine(
|
|
12906
|
+
const line = createAncestryLinkLine(
|
|
12907
|
+
parentMesh,
|
|
12908
|
+
childMesh,
|
|
12909
|
+
resolution,
|
|
12910
|
+
childItem.relationship,
|
|
12911
|
+
colorHex
|
|
12912
|
+
);
|
|
12442
12913
|
ancestryGroup.add(line);
|
|
12443
12914
|
ancestryEntry.lines.push(line);
|
|
12444
12915
|
lastRenderedMesh = childMesh;
|
|
12445
12916
|
if (childItem.children && childItem.children.length > 0) {
|
|
12446
|
-
const lastDescendant = renderCluster(
|
|
12917
|
+
const lastDescendant = renderCluster(
|
|
12918
|
+
childItem.children,
|
|
12919
|
+
childMesh,
|
|
12920
|
+
childPosition,
|
|
12921
|
+
level + 1,
|
|
12922
|
+
currentAngle
|
|
12923
|
+
);
|
|
12447
12924
|
if (lastDescendant) lastRenderedMesh = lastDescendant;
|
|
12448
12925
|
}
|
|
12449
12926
|
});
|
|
@@ -12457,9 +12934,13 @@ function XViewScene({
|
|
|
12457
12934
|
else looseNodes.push(child);
|
|
12458
12935
|
});
|
|
12459
12936
|
}
|
|
12460
|
-
sections.sort(
|
|
12937
|
+
sections.sort(
|
|
12938
|
+
(a, b) => (a.section_numeric_id || 0) - (b.section_numeric_id || 0)
|
|
12939
|
+
);
|
|
12461
12940
|
let combinedStartNodes = [...looseNodes];
|
|
12462
|
-
let session0Index = sections.findIndex(
|
|
12941
|
+
let session0Index = sections.findIndex(
|
|
12942
|
+
(s) => s.section_numeric_id === 0 || s.name === "Sess\xE3o 0"
|
|
12943
|
+
);
|
|
12463
12944
|
if (session0Index !== -1) {
|
|
12464
12945
|
const session0 = sections[session0Index];
|
|
12465
12946
|
if (checkShouldRender(session0) && session0.children) {
|
|
@@ -12468,7 +12949,13 @@ function XViewScene({
|
|
|
12468
12949
|
sections.splice(session0Index, 1);
|
|
12469
12950
|
}
|
|
12470
12951
|
const rootTargetPos2 = targetPositionsCache.get(rootNodeId) || rootNodeMesh.position;
|
|
12471
|
-
const lastStartMesh = renderCluster(
|
|
12952
|
+
const lastStartMesh = renderCluster(
|
|
12953
|
+
combinedStartNodes,
|
|
12954
|
+
rootNodeMesh,
|
|
12955
|
+
rootTargetPos2,
|
|
12956
|
+
1,
|
|
12957
|
+
baseRotation
|
|
12958
|
+
);
|
|
12472
12959
|
if (lastStartMesh) {
|
|
12473
12960
|
currentAnchorMesh = lastStartMesh;
|
|
12474
12961
|
}
|
|
@@ -12479,10 +12966,18 @@ function XViewScene({
|
|
|
12479
12966
|
const sectionNodes = section.children || [];
|
|
12480
12967
|
if (sectionNodes.length > 0) {
|
|
12481
12968
|
const parentAngle = nodeRotationMap.get(String(currentAnchorMesh.userData.id)) ?? baseRotation;
|
|
12482
|
-
const lastMeshOfThisSection = renderCluster(
|
|
12969
|
+
const lastMeshOfThisSection = renderCluster(
|
|
12970
|
+
sectionNodes,
|
|
12971
|
+
currentAnchorMesh,
|
|
12972
|
+
currentAnchorPosition,
|
|
12973
|
+
1,
|
|
12974
|
+
parentAngle
|
|
12975
|
+
);
|
|
12483
12976
|
if (lastMeshOfThisSection) {
|
|
12484
12977
|
currentAnchorMesh = lastMeshOfThisSection;
|
|
12485
|
-
currentAnchorPosition = targetPositionsCache.get(
|
|
12978
|
+
currentAnchorPosition = targetPositionsCache.get(
|
|
12979
|
+
String(lastMeshOfThisSection.userData.id)
|
|
12980
|
+
) || lastMeshOfThisSection.position;
|
|
12486
12981
|
}
|
|
12487
12982
|
}
|
|
12488
12983
|
}
|
|
@@ -12511,7 +13006,10 @@ function XViewScene({
|
|
|
12511
13006
|
} else {
|
|
12512
13007
|
const directChildren = fullTree.children ? fullTree.children.filter((c) => !c.is_section) : [];
|
|
12513
13008
|
if (directChildren.length > 0) {
|
|
12514
|
-
targetSectionForZone = {
|
|
13009
|
+
targetSectionForZone = {
|
|
13010
|
+
name: "In\xEDcio",
|
|
13011
|
+
children: directChildren
|
|
13012
|
+
};
|
|
12515
13013
|
}
|
|
12516
13014
|
}
|
|
12517
13015
|
} else {
|
|
@@ -12585,7 +13083,10 @@ function XViewScene({
|
|
|
12585
13083
|
stateRef.current.ancestryLinks = stateRef.current.renderedAncestries.flatMap((a) => a.lines);
|
|
12586
13084
|
focusTargetPosition = center;
|
|
12587
13085
|
focusTargetRotation = baseRotation;
|
|
12588
|
-
const desiredDistance = Math.max(
|
|
13086
|
+
const desiredDistance = Math.max(
|
|
13087
|
+
x_view_config.CAMERA_ZOOM_DISTANCE,
|
|
13088
|
+
radius * 2.8
|
|
13089
|
+
);
|
|
12589
13090
|
focusZoomFactor = x_view_config.CAMERA_ZOOM_DISTANCE / desiredDistance;
|
|
12590
13091
|
} else {
|
|
12591
13092
|
const anchorId = String(currentAnchorMesh.userData.id);
|
|
@@ -12600,13 +13101,18 @@ function XViewScene({
|
|
|
12600
13101
|
}
|
|
12601
13102
|
if (!focusTargetPosition && !allowedSectionIds) {
|
|
12602
13103
|
if (allRenderedNodePositions.length > 0) {
|
|
12603
|
-
const boundingBox = new THREE3.Box3().setFromPoints(
|
|
13104
|
+
const boundingBox = new THREE3.Box3().setFromPoints(
|
|
13105
|
+
allRenderedNodePositions
|
|
13106
|
+
);
|
|
12604
13107
|
const center = new THREE3.Vector3();
|
|
12605
13108
|
boundingBox.getCenter(center);
|
|
12606
13109
|
const size = new THREE3.Vector3();
|
|
12607
13110
|
boundingBox.getSize(size);
|
|
12608
13111
|
const maxDim = Math.max(size.x, size.y, size.z);
|
|
12609
|
-
const fitZoom = Math.min(
|
|
13112
|
+
const fitZoom = Math.min(
|
|
13113
|
+
1,
|
|
13114
|
+
x_view_config.CAMERA_ZOOM_DISTANCE / (maxDim * 1.5)
|
|
13115
|
+
);
|
|
12610
13116
|
const defaultBase = new THREE3.Vector3(-50, 40, 20);
|
|
12611
13117
|
const rotatedCinematicAngle = defaultBase.clone().applyAxisAngle(new THREE3.Vector3(0, 1, 0), baseRotation);
|
|
12612
13118
|
tweenToTarget(center, fitZoom, rotatedCinematicAngle);
|
|
@@ -12625,210 +13131,280 @@ function XViewScene({
|
|
|
12625
13131
|
tweenToTarget(targetPos, focusZoomFactor, rotatedCinematicAngle);
|
|
12626
13132
|
}
|
|
12627
13133
|
},
|
|
12628
|
-
[
|
|
13134
|
+
[
|
|
13135
|
+
addOrUpdateNodeMesh,
|
|
13136
|
+
tweenToTarget,
|
|
13137
|
+
buildFullAncestryTree,
|
|
13138
|
+
readingMode.isActive,
|
|
13139
|
+
ancestryMode.isActive
|
|
13140
|
+
]
|
|
12629
13141
|
);
|
|
12630
|
-
const handleRenderAbstractionTree = (0, import_react26.useCallback)(
|
|
12631
|
-
|
|
12632
|
-
|
|
12633
|
-
|
|
12634
|
-
|
|
12635
|
-
|
|
12636
|
-
|
|
12637
|
-
|
|
12638
|
-
|
|
12639
|
-
|
|
12640
|
-
|
|
12641
|
-
|
|
12642
|
-
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
13142
|
+
const handleRenderAbstractionTree = (0, import_react26.useCallback)(
|
|
13143
|
+
(ancestryObject, targetNodeId = null) => {
|
|
13144
|
+
setContextMenu(
|
|
13145
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13146
|
+
);
|
|
13147
|
+
if (!ancestryObject || !ancestryObject.abstraction_tree) return;
|
|
13148
|
+
const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
|
|
13149
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13150
|
+
(f) => f.nodes
|
|
13151
|
+
);
|
|
13152
|
+
let fullTree = buildFullAncestryTree(
|
|
13153
|
+
ancestryObject.abstraction_tree,
|
|
13154
|
+
allParentNodes,
|
|
13155
|
+
ancestryDataRef.current
|
|
13156
|
+
);
|
|
13157
|
+
if (!fullTree || !fullTree.node) return;
|
|
13158
|
+
if (targetNodeId) {
|
|
13159
|
+
const pruneTreeToPath = (treeNode, targetId) => {
|
|
13160
|
+
var _a2;
|
|
13161
|
+
if (!treeNode) return null;
|
|
13162
|
+
const currentId = treeNode.is_section ? treeNode.section_id : String((_a2 = treeNode.node) == null ? void 0 : _a2.id);
|
|
13163
|
+
if (String(currentId) === String(targetId)) {
|
|
13164
|
+
return { ...treeNode, children: [] };
|
|
12651
13165
|
}
|
|
12652
|
-
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
}
|
|
12658
|
-
const absId = ancestryObject.ancestry_id + "_abs";
|
|
12659
|
-
handleClearAncestryVisuals(absId);
|
|
12660
|
-
const colorHex = 9133302;
|
|
12661
|
-
const resolution = new THREE3.Vector2(renderer.domElement.clientWidth, renderer.domElement.clientHeight);
|
|
12662
|
-
const ancestryEntry = { id: absId, lines: [], isFullRender: true };
|
|
12663
|
-
renderedAncestries.push(ancestryEntry);
|
|
12664
|
-
const rootNodeId = String(fullTree.node.id);
|
|
12665
|
-
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
12666
|
-
let rootTargetPos = rootNodeMesh ? rootNodeMesh.position.clone() : new THREE3.Vector3(0, 0, 0);
|
|
12667
|
-
if (!rootNodeMesh) {
|
|
12668
|
-
rootNodeMesh = addOrUpdateNodeMesh(fullTree.node, rootTargetPos, true);
|
|
12669
|
-
}
|
|
12670
|
-
const SPACING_Y = -40;
|
|
12671
|
-
const SPACING_X = 55;
|
|
12672
|
-
const renderVertical = (treeNode, parentMesh, parentPos, level) => {
|
|
12673
|
-
if (!treeNode.children || treeNode.children.length === 0) return;
|
|
12674
|
-
const totalSiblings = treeNode.children.length;
|
|
12675
|
-
treeNode.children.forEach((childItem, i) => {
|
|
12676
|
-
if (!childItem.node) return;
|
|
12677
|
-
const childX = parentPos.x + (i - (totalSiblings - 1) / 2) * (SPACING_X / Math.max(1, level * 0.4));
|
|
12678
|
-
const childY = parentPos.y + SPACING_Y;
|
|
12679
|
-
const childPos = new THREE3.Vector3(childX, childY, parentPos.z);
|
|
12680
|
-
const childMesh = addOrUpdateNodeMesh(childItem.node, childPos, true);
|
|
12681
|
-
const line = createAncestryLinkLine(parentMesh, childMesh, resolution, {}, colorHex);
|
|
12682
|
-
ancestryGroup.add(line);
|
|
12683
|
-
ancestryEntry.lines.push(line);
|
|
12684
|
-
renderVertical(childItem, childMesh, childPos, level + 1);
|
|
12685
|
-
});
|
|
12686
|
-
};
|
|
12687
|
-
renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
|
|
12688
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
12689
|
-
tweenToTarget(rootTargetPos, 0.7);
|
|
12690
|
-
}, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
|
|
12691
|
-
const handleReadModeBranchNav = (0, import_react26.useCallback)((nodeId, action, direction = "right") => {
|
|
12692
|
-
const { ancestry, branchStack } = readingMode;
|
|
12693
|
-
if (!ancestry || !ancestry.tree) return;
|
|
12694
|
-
const allAncestries = ancestryDataRef.current || [];
|
|
12695
|
-
const fullTree = buildFullAncestryTree(ancestry.tree, Object.values(parentDataRef.current).flatMap((f) => f.nodes), allAncestries);
|
|
12696
|
-
if (action === "open") {
|
|
12697
|
-
let currentPtr = fullTree;
|
|
12698
|
-
for (const step of branchStack) {
|
|
12699
|
-
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12700
|
-
if (found && found.node.parallel_branches) {
|
|
12701
|
-
const branch = found.node.parallel_branches.find((b) => b.id === step.branchId);
|
|
12702
|
-
if (branch) currentPtr = branch.tree;
|
|
12703
|
-
}
|
|
12704
|
-
}
|
|
12705
|
-
const foundTarget = findNodePath3(currentPtr, nodeId);
|
|
12706
|
-
if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
|
|
12707
|
-
const branchToOpen = foundTarget.node.parallel_branches.find((b) => (b.direction || "right") === direction);
|
|
12708
|
-
if (!branchToOpen) return;
|
|
12709
|
-
if (branchToOpen && branchToOpen.tree) {
|
|
12710
|
-
const parentIndexToSave = stateRef.current.readMode.currentMaxIndex;
|
|
12711
|
-
const savedBranchProgress = 0;
|
|
12712
|
-
stateRef.current.readMode.currentMaxIndex = savedBranchProgress;
|
|
12713
|
-
stateRef.current.maxAncestryRenderIndex = savedBranchProgress;
|
|
12714
|
-
const newStack = [...branchStack, {
|
|
12715
|
-
nodeId,
|
|
12716
|
-
branchId: branchToOpen.id,
|
|
12717
|
-
savedMaxIndex: parentIndexToSave,
|
|
12718
|
-
entryDirection: direction
|
|
12719
|
-
}];
|
|
12720
|
-
setReadingMode((prev) => ({ ...prev, branchStack: newStack, initialSectionId: null }));
|
|
12721
|
-
const branchAncestryObj = {
|
|
12722
|
-
ancestry_id: branchToOpen.id,
|
|
12723
|
-
ancestral_node: branchToOpen.tree.node.id,
|
|
12724
|
-
name: branchToOpen.name,
|
|
12725
|
-
description: branchToOpen.description,
|
|
12726
|
-
description_sections: branchToOpen.description_sections,
|
|
12727
|
-
tree: branchToOpen.tree,
|
|
12728
|
-
_originNodeId: nodeId,
|
|
12729
|
-
_branchDirection: direction
|
|
12730
|
-
};
|
|
12731
|
-
const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
12732
|
-
const branchSections = parseDescriptionSections(branchToOpen.description || "", branchToOpen.description_sections || []);
|
|
12733
|
-
for (let i = 0; i <= savedBranchProgress; i++) {
|
|
12734
|
-
if (branchSections[i]) {
|
|
12735
|
-
if (branchSections[i].id) allowedIds.add(String(branchSections[i].id));
|
|
12736
|
-
if (branchSections[i].numericId !== void 0 && branchSections[i].numericId !== null) {
|
|
12737
|
-
allowedIds.add(branchSections[i].numericId);
|
|
12738
|
-
allowedIds.add(String(branchSections[i].numericId));
|
|
13166
|
+
if (treeNode.children && treeNode.children.length > 0) {
|
|
13167
|
+
for (let child of treeNode.children) {
|
|
13168
|
+
const prunedChild = pruneTreeToPath(child, targetId);
|
|
13169
|
+
if (prunedChild) {
|
|
13170
|
+
return { ...treeNode, children: [prunedChild] };
|
|
12739
13171
|
}
|
|
12740
13172
|
}
|
|
12741
13173
|
}
|
|
12742
|
-
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
13174
|
+
return null;
|
|
13175
|
+
};
|
|
13176
|
+
const pruned = pruneTreeToPath(fullTree, targetNodeId);
|
|
13177
|
+
if (pruned) fullTree = pruned;
|
|
13178
|
+
}
|
|
13179
|
+
const absId = ancestryObject.ancestry_id + "_abs";
|
|
13180
|
+
handleClearAncestryVisuals(absId);
|
|
13181
|
+
const colorHex = 9133302;
|
|
13182
|
+
const resolution = new THREE3.Vector2(
|
|
13183
|
+
renderer.domElement.clientWidth,
|
|
13184
|
+
renderer.domElement.clientHeight
|
|
13185
|
+
);
|
|
13186
|
+
const ancestryEntry = { id: absId, lines: [], isFullRender: true };
|
|
13187
|
+
renderedAncestries.push(ancestryEntry);
|
|
13188
|
+
const rootNodeId = String(fullTree.node.id);
|
|
13189
|
+
let rootNodeMesh = nodeObjects[rootNodeId];
|
|
13190
|
+
let rootTargetPos = rootNodeMesh ? rootNodeMesh.position.clone() : new THREE3.Vector3(0, 0, 0);
|
|
13191
|
+
if (!rootNodeMesh) {
|
|
13192
|
+
rootNodeMesh = addOrUpdateNodeMesh(fullTree.node, rootTargetPos, true);
|
|
12754
13193
|
}
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
const
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
13194
|
+
const SPACING_Y = -40;
|
|
13195
|
+
const SPACING_X = 55;
|
|
13196
|
+
const renderVertical = (treeNode, parentMesh, parentPos, level) => {
|
|
13197
|
+
if (!treeNode.children || treeNode.children.length === 0) return;
|
|
13198
|
+
const totalSiblings = treeNode.children.length;
|
|
13199
|
+
treeNode.children.forEach((childItem, i) => {
|
|
13200
|
+
if (!childItem.node) return;
|
|
13201
|
+
const childX = parentPos.x + (i - (totalSiblings - 1) / 2) * (SPACING_X / Math.max(1, level * 0.4));
|
|
13202
|
+
const childY = parentPos.y + SPACING_Y;
|
|
13203
|
+
const childPos = new THREE3.Vector3(childX, childY, parentPos.z);
|
|
13204
|
+
const childMesh = addOrUpdateNodeMesh(childItem.node, childPos, true);
|
|
13205
|
+
const line = createAncestryLinkLine(
|
|
13206
|
+
parentMesh,
|
|
13207
|
+
childMesh,
|
|
13208
|
+
resolution,
|
|
13209
|
+
{},
|
|
13210
|
+
colorHex
|
|
13211
|
+
);
|
|
13212
|
+
ancestryGroup.add(line);
|
|
13213
|
+
ancestryEntry.lines.push(line);
|
|
13214
|
+
renderVertical(childItem, childMesh, childPos, level + 1);
|
|
13215
|
+
});
|
|
13216
|
+
};
|
|
13217
|
+
renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
|
|
13218
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
13219
|
+
(a) => a.lines
|
|
13220
|
+
);
|
|
13221
|
+
tweenToTarget(rootTargetPos, 0.7);
|
|
13222
|
+
},
|
|
13223
|
+
[
|
|
13224
|
+
addOrUpdateNodeMesh,
|
|
13225
|
+
tweenToTarget,
|
|
13226
|
+
buildFullAncestryTree,
|
|
13227
|
+
handleClearAncestryVisuals
|
|
13228
|
+
]
|
|
13229
|
+
);
|
|
13230
|
+
const handleReadModeBranchNav = (0, import_react26.useCallback)(
|
|
13231
|
+
(nodeId, action, direction = "right") => {
|
|
13232
|
+
const { ancestry, branchStack } = readingMode;
|
|
13233
|
+
if (!ancestry || !ancestry.tree) return;
|
|
13234
|
+
const allAncestries = ancestryDataRef.current || [];
|
|
13235
|
+
const fullTree = buildFullAncestryTree(
|
|
13236
|
+
ancestry.tree,
|
|
13237
|
+
Object.values(parentDataRef.current).flatMap((f) => f.nodes),
|
|
13238
|
+
allAncestries
|
|
13239
|
+
);
|
|
13240
|
+
if (action === "open") {
|
|
13241
|
+
let currentPtr = fullTree;
|
|
13242
|
+
for (const step of branchStack) {
|
|
13243
|
+
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12771
13244
|
if (found && found.node.parallel_branches) {
|
|
12772
|
-
const branch = found.node.parallel_branches.find(
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
13245
|
+
const branch = found.node.parallel_branches.find(
|
|
13246
|
+
(b) => b.id === step.branchId
|
|
13247
|
+
);
|
|
13248
|
+
if (branch) currentPtr = branch.tree;
|
|
13249
|
+
}
|
|
13250
|
+
}
|
|
13251
|
+
const foundTarget = findNodePath3(currentPtr, nodeId);
|
|
13252
|
+
if (foundTarget && foundTarget.node && foundTarget.node.parallel_branches && foundTarget.node.parallel_branches.length > 0) {
|
|
13253
|
+
const branchToOpen = foundTarget.node.parallel_branches.find(
|
|
13254
|
+
(b) => (b.direction || "right") === direction
|
|
13255
|
+
);
|
|
13256
|
+
if (!branchToOpen) return;
|
|
13257
|
+
if (branchToOpen && branchToOpen.tree) {
|
|
13258
|
+
const parentIndexToSave = stateRef.current.readMode.currentMaxIndex;
|
|
13259
|
+
const savedBranchProgress = 0;
|
|
13260
|
+
stateRef.current.readMode.currentMaxIndex = savedBranchProgress;
|
|
13261
|
+
stateRef.current.maxAncestryRenderIndex = savedBranchProgress;
|
|
13262
|
+
const newStack = [
|
|
13263
|
+
...branchStack,
|
|
13264
|
+
{
|
|
13265
|
+
nodeId,
|
|
13266
|
+
branchId: branchToOpen.id,
|
|
13267
|
+
savedMaxIndex: parentIndexToSave,
|
|
13268
|
+
entryDirection: direction
|
|
13269
|
+
}
|
|
13270
|
+
];
|
|
13271
|
+
setReadingMode((prev) => ({
|
|
13272
|
+
...prev,
|
|
13273
|
+
branchStack: newStack,
|
|
13274
|
+
initialSectionId: null
|
|
13275
|
+
}));
|
|
13276
|
+
const branchAncestryObj = {
|
|
13277
|
+
ancestry_id: branchToOpen.id,
|
|
13278
|
+
ancestral_node: branchToOpen.tree.node.id,
|
|
13279
|
+
name: branchToOpen.name,
|
|
13280
|
+
description: branchToOpen.description,
|
|
13281
|
+
description_sections: branchToOpen.description_sections,
|
|
13282
|
+
tree: branchToOpen.tree,
|
|
13283
|
+
_originNodeId: nodeId,
|
|
13284
|
+
_branchDirection: direction
|
|
13285
|
+
};
|
|
13286
|
+
const allowedIds = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
13287
|
+
const branchSections = parseDescriptionSections(
|
|
13288
|
+
branchToOpen.description || "",
|
|
13289
|
+
branchToOpen.description_sections || []
|
|
13290
|
+
);
|
|
13291
|
+
for (let i = 0; i <= savedBranchProgress; i++) {
|
|
13292
|
+
if (branchSections[i]) {
|
|
13293
|
+
if (branchSections[i].id)
|
|
13294
|
+
allowedIds.add(String(branchSections[i].id));
|
|
13295
|
+
if (branchSections[i].numericId !== void 0 && branchSections[i].numericId !== null) {
|
|
13296
|
+
allowedIds.add(branchSections[i].numericId);
|
|
13297
|
+
allowedIds.add(String(branchSections[i].numericId));
|
|
13298
|
+
}
|
|
13299
|
+
}
|
|
12776
13300
|
}
|
|
13301
|
+
const rotation = newStack.reduce((acc, step) => {
|
|
13302
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13303
|
+
}, 0);
|
|
13304
|
+
const initialFocusId = "preamble";
|
|
13305
|
+
handleRenderAncestry(
|
|
13306
|
+
branchAncestryObj,
|
|
13307
|
+
allowedIds,
|
|
13308
|
+
initialFocusId,
|
|
13309
|
+
rotation,
|
|
13310
|
+
false
|
|
13311
|
+
);
|
|
12777
13312
|
}
|
|
12778
13313
|
}
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
|
|
12791
|
-
|
|
12792
|
-
|
|
12793
|
-
|
|
12794
|
-
|
|
12795
|
-
|
|
12796
|
-
|
|
12797
|
-
|
|
12798
|
-
|
|
13314
|
+
} else if (action === "back") {
|
|
13315
|
+
if (branchStack.length === 0) return;
|
|
13316
|
+
const newStack = [...branchStack];
|
|
13317
|
+
const popped = newStack.pop();
|
|
13318
|
+
if (popped && popped.branchId) {
|
|
13319
|
+
stateRef.current.readMode.progressMap[popped.branchId] = stateRef.current.readMode.currentMaxIndex;
|
|
13320
|
+
}
|
|
13321
|
+
const parentSavedIndex = popped.savedMaxIndex !== void 0 ? popped.savedMaxIndex : 0;
|
|
13322
|
+
stateRef.current.readMode.currentMaxIndex = parentSavedIndex;
|
|
13323
|
+
stateRef.current.maxAncestryRenderIndex = parentSavedIndex;
|
|
13324
|
+
let targetTreeToRender = fullTree;
|
|
13325
|
+
let targetAncestryInfo = ancestry;
|
|
13326
|
+
if (newStack.length > 0) {
|
|
13327
|
+
let ptr = fullTree;
|
|
13328
|
+
for (const step of newStack) {
|
|
13329
|
+
const found = findNodePath3(ptr, step.nodeId);
|
|
13330
|
+
if (found && found.node.parallel_branches) {
|
|
13331
|
+
const branch = found.node.parallel_branches.find(
|
|
13332
|
+
(b) => b.id === step.branchId
|
|
13333
|
+
);
|
|
13334
|
+
if (branch) {
|
|
13335
|
+
ptr = branch.tree;
|
|
13336
|
+
targetAncestryInfo = {
|
|
13337
|
+
...branch,
|
|
13338
|
+
ancestry_id: branch.id,
|
|
13339
|
+
ancestral_node: branch.tree.node.id
|
|
13340
|
+
};
|
|
13341
|
+
}
|
|
13342
|
+
}
|
|
13343
|
+
}
|
|
13344
|
+
targetTreeToRender = ptr;
|
|
13345
|
+
}
|
|
13346
|
+
const activeParentStackItem = newStack.length > 0 ? newStack[newStack.length - 1] : null;
|
|
13347
|
+
const parentAncestryObj = {
|
|
13348
|
+
...targetAncestryInfo,
|
|
13349
|
+
tree: targetTreeToRender,
|
|
13350
|
+
_originNodeId: activeParentStackItem ? activeParentStackItem.nodeId : null,
|
|
13351
|
+
_branchDirection: activeParentStackItem ? activeParentStackItem.entryDirection : null
|
|
13352
|
+
};
|
|
13353
|
+
const descriptionText = targetAncestryInfo.description || "";
|
|
13354
|
+
const savedSections = targetAncestryInfo.description_sections || [];
|
|
13355
|
+
const sections = parseDescriptionSections(
|
|
13356
|
+
descriptionText,
|
|
13357
|
+
savedSections
|
|
13358
|
+
);
|
|
13359
|
+
let focusTargetId = null;
|
|
13360
|
+
if (popped && popped.nodeId) {
|
|
13361
|
+
const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
|
|
13362
|
+
for (let i = 0; i < sections.length; i++) {
|
|
13363
|
+
if (sections[i].content && sections[i].content.includes(mentionTag)) {
|
|
13364
|
+
const section = sections[i];
|
|
13365
|
+
focusTargetId = section.numericId !== void 0 ? section.numericId : section.id;
|
|
13366
|
+
break;
|
|
13367
|
+
}
|
|
12799
13368
|
}
|
|
12800
13369
|
}
|
|
12801
|
-
|
|
12802
|
-
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
13370
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13371
|
+
allowedIds.add("preamble");
|
|
13372
|
+
allowedIds.add(0);
|
|
13373
|
+
allowedIds.add("0");
|
|
13374
|
+
for (let i = 0; i <= parentSavedIndex; i++) {
|
|
13375
|
+
if (sections[i]) {
|
|
13376
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13377
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13378
|
+
allowedIds.add(sections[i].numericId);
|
|
13379
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13380
|
+
}
|
|
12812
13381
|
}
|
|
12813
13382
|
}
|
|
12814
|
-
|
|
12815
|
-
|
|
12816
|
-
|
|
12817
|
-
|
|
12818
|
-
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
13383
|
+
const rotation = newStack.reduce((acc, step) => {
|
|
13384
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13385
|
+
}, 0);
|
|
13386
|
+
handleRenderAncestry(
|
|
13387
|
+
parentAncestryObj,
|
|
13388
|
+
allowedIds,
|
|
13389
|
+
focusTargetId,
|
|
13390
|
+
rotation,
|
|
13391
|
+
false
|
|
13392
|
+
);
|
|
13393
|
+
if (popped && popped.nodeId) {
|
|
13394
|
+
const nodeMesh = stateRef.current.nodeObjects[String(popped.nodeId)];
|
|
13395
|
+
if (nodeMesh) {
|
|
13396
|
+
tweenToTarget(nodeMesh);
|
|
13397
|
+
}
|
|
12823
13398
|
}
|
|
13399
|
+
setReadingMode((prev) => ({
|
|
13400
|
+
...prev,
|
|
13401
|
+
branchStack: newStack,
|
|
13402
|
+
initialSectionId: focusTargetId
|
|
13403
|
+
}));
|
|
12824
13404
|
}
|
|
12825
|
-
|
|
12826
|
-
|
|
12827
|
-
|
|
12828
|
-
initialSectionId: focusTargetId
|
|
12829
|
-
}));
|
|
12830
|
-
}
|
|
12831
|
-
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
|
|
13405
|
+
},
|
|
13406
|
+
[readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
|
|
13407
|
+
);
|
|
12832
13408
|
const handleReadModeHighlight = (0, import_react26.useCallback)((nodeId) => {
|
|
12833
13409
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
12834
13410
|
stateRef.current.highlightedNodeId = nodeId;
|
|
@@ -12836,7 +13412,8 @@ function XViewScene({
|
|
|
12836
13412
|
setHighlightedNodeId(nodeId);
|
|
12837
13413
|
}, []);
|
|
12838
13414
|
const activeNodeBranches = (0, import_react26.useMemo)(() => {
|
|
12839
|
-
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
|
|
13415
|
+
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
|
|
13416
|
+
return null;
|
|
12840
13417
|
const fullTree = buildFullAncestryTree(
|
|
12841
13418
|
readingMode.ancestry.tree,
|
|
12842
13419
|
Object.values(parentDataRef.current).flatMap((f) => f.nodes),
|
|
@@ -12871,7 +13448,13 @@ function XViewScene({
|
|
|
12871
13448
|
};
|
|
12872
13449
|
}
|
|
12873
13450
|
return null;
|
|
12874
|
-
}, [
|
|
13451
|
+
}, [
|
|
13452
|
+
highlightedNodeId,
|
|
13453
|
+
readingMode.ancestry,
|
|
13454
|
+
buildFullAncestryTree,
|
|
13455
|
+
readingMode.branchStack,
|
|
13456
|
+
ancestryDataRef.current
|
|
13457
|
+
]);
|
|
12875
13458
|
const backNavigationInfo = (0, import_react26.useMemo)(() => {
|
|
12876
13459
|
const { branchStack } = readingMode;
|
|
12877
13460
|
if (!branchStack || branchStack.length === 0) return null;
|
|
@@ -12907,7 +13490,9 @@ function XViewScene({
|
|
|
12907
13490
|
for (const step of branchStack) {
|
|
12908
13491
|
const found = findNodePath3(currentPtr, step.nodeId);
|
|
12909
13492
|
if (found && found.node.parallel_branches) {
|
|
12910
|
-
const branch = found.node.parallel_branches.find(
|
|
13493
|
+
const branch = found.node.parallel_branches.find(
|
|
13494
|
+
(b) => b.id === step.branchId
|
|
13495
|
+
);
|
|
12911
13496
|
if (branch) {
|
|
12912
13497
|
currentPtr = branch.tree;
|
|
12913
13498
|
currentMeta = branch;
|
|
@@ -12928,17 +13513,26 @@ function XViewScene({
|
|
|
12928
13513
|
if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
|
|
12929
13514
|
return null;
|
|
12930
13515
|
}
|
|
12931
|
-
const allNodes = Object.values(parentDataRef.current || {}).flatMap(
|
|
13516
|
+
const allNodes = Object.values(parentDataRef.current || {}).flatMap(
|
|
13517
|
+
(f) => f.nodes || []
|
|
13518
|
+
);
|
|
12932
13519
|
const allAncestries = ancestryDataRef.current || [];
|
|
12933
13520
|
return buildFullAncestryTree(
|
|
12934
13521
|
readingMode.ancestry.abstraction_tree,
|
|
12935
13522
|
allNodes,
|
|
12936
13523
|
allAncestries
|
|
12937
13524
|
);
|
|
12938
|
-
}, [
|
|
13525
|
+
}, [
|
|
13526
|
+
readingMode.isActive,
|
|
13527
|
+
readingMode.ancestry,
|
|
13528
|
+
buildFullAncestryTree,
|
|
13529
|
+
sceneVersion
|
|
13530
|
+
]);
|
|
12939
13531
|
const handleStartReadingAncestry = (0, import_react26.useCallback)(
|
|
12940
|
-
async (ancestryObject) => {
|
|
12941
|
-
setContextMenu(
|
|
13532
|
+
async (ancestryObject, renderMode = "full") => {
|
|
13533
|
+
setContextMenu(
|
|
13534
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13535
|
+
);
|
|
12942
13536
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
12943
13537
|
console.warn("Ancestralidade inv\xE1lida para leitura.");
|
|
12944
13538
|
return;
|
|
@@ -12951,14 +13545,20 @@ function XViewScene({
|
|
|
12951
13545
|
const hasDescription = ancestryObject.description && ancestryObject.description.trim() !== "";
|
|
12952
13546
|
const hasMainTreeNodes = ancestryObject.tree.children && ancestryObject.tree.children.length > 0;
|
|
12953
13547
|
const hasAbstractionNodes = ancestryObject.abstraction_tree && ancestryObject.abstraction_tree.children && ancestryObject.abstraction_tree.children.length > 0;
|
|
12954
|
-
const
|
|
13548
|
+
const isFull = renderMode === "full";
|
|
13549
|
+
const isAncestryOnly = renderMode === "ancestry_only";
|
|
13550
|
+
const isAbstractionOnly = renderMode === "abstraction_only";
|
|
13551
|
+
let shouldRenderAbstraction = isAbstractionOnly;
|
|
13552
|
+
if (isFull) {
|
|
13553
|
+
shouldRenderAbstraction = !hasDescription && !hasMainTreeNodes && hasAbstractionNodes;
|
|
13554
|
+
}
|
|
12955
13555
|
setReadingMode({
|
|
12956
|
-
isActive:
|
|
13556
|
+
isActive: isFull ? hasDescription : false,
|
|
12957
13557
|
ancestry: ancestryObject,
|
|
12958
13558
|
branchStack: [],
|
|
12959
|
-
autoAbstraction:
|
|
13559
|
+
autoAbstraction: shouldRenderAbstraction
|
|
12960
13560
|
});
|
|
12961
|
-
if (
|
|
13561
|
+
if (shouldRenderAbstraction) {
|
|
12962
13562
|
handleRenderAbstractionTree(ancestryObject, null);
|
|
12963
13563
|
} else {
|
|
12964
13564
|
const initialSections = /* @__PURE__ */ new Set(["preamble", 0, "0"]);
|
|
@@ -12971,148 +13571,190 @@ function XViewScene({
|
|
|
12971
13571
|
},
|
|
12972
13572
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
12973
13573
|
);
|
|
12974
|
-
const handleReadModeSectionChange = (0, import_react26.useCallback)(
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
|
|
13574
|
+
const handleReadModeSectionChange = (0, import_react26.useCallback)(
|
|
13575
|
+
(activeSectionId) => {
|
|
13576
|
+
const { ancestry, branchStack } = readingMode;
|
|
13577
|
+
if (!ancestry || !readingMode.isActive) return;
|
|
13578
|
+
let targetObj = ancestry;
|
|
13579
|
+
let targetTree = ancestry.tree;
|
|
13580
|
+
if (branchStack.length > 0) {
|
|
13581
|
+
const allNodes = Object.values(parentDataRef.current).flatMap(
|
|
13582
|
+
(f) => f.nodes
|
|
13583
|
+
);
|
|
13584
|
+
const fullTree = buildFullAncestryTree(
|
|
13585
|
+
ancestry.tree,
|
|
13586
|
+
allNodes,
|
|
13587
|
+
ancestryDataRef.current
|
|
13588
|
+
);
|
|
13589
|
+
let currentPtr = fullTree;
|
|
13590
|
+
for (const step of branchStack) {
|
|
13591
|
+
const found = findNodePath3(currentPtr, step.nodeId);
|
|
13592
|
+
if (found && found.node && found.node.parallel_branches) {
|
|
13593
|
+
const branch = found.node.parallel_branches.find(
|
|
13594
|
+
(b) => b.id === step.branchId
|
|
13595
|
+
);
|
|
13596
|
+
if (branch) {
|
|
13597
|
+
targetObj = branch;
|
|
13598
|
+
targetTree = branch.tree;
|
|
13599
|
+
currentPtr = branch.tree;
|
|
13600
|
+
}
|
|
12995
13601
|
}
|
|
12996
13602
|
}
|
|
12997
13603
|
}
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
allowedIds.add(String(sections[i].
|
|
13604
|
+
const descriptionText = targetObj.description || "";
|
|
13605
|
+
const savedSections = targetObj.description_sections || [];
|
|
13606
|
+
const sections = parseDescriptionSections(descriptionText, savedSections);
|
|
13607
|
+
let activeIndex = sections.findIndex(
|
|
13608
|
+
(s) => String(s.id) === String(activeSectionId)
|
|
13609
|
+
);
|
|
13610
|
+
if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
|
|
13611
|
+
activeIndex = sections.findIndex(
|
|
13612
|
+
(s) => s.numericId === parseInt(activeSectionId)
|
|
13613
|
+
);
|
|
13614
|
+
}
|
|
13615
|
+
if (activeIndex === -1) activeIndex = 0;
|
|
13616
|
+
stateRef.current.readMode.currentMaxIndex = activeIndex;
|
|
13617
|
+
stateRef.current.maxAncestryRenderIndex = activeIndex;
|
|
13618
|
+
const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
|
|
13619
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13620
|
+
allowedIds.add("preamble");
|
|
13621
|
+
allowedIds.add(0);
|
|
13622
|
+
allowedIds.add("0");
|
|
13623
|
+
for (let i = 0; i <= renderLimitIndex; i++) {
|
|
13624
|
+
if (sections[i]) {
|
|
13625
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13626
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13627
|
+
allowedIds.add(sections[i].numericId);
|
|
13628
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13629
|
+
}
|
|
13020
13630
|
}
|
|
13021
13631
|
}
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13632
|
+
const activeSection = sections[activeIndex];
|
|
13633
|
+
let focusTargetId = activeSectionId;
|
|
13634
|
+
if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
|
|
13635
|
+
focusTargetId = activeSection.numericId;
|
|
13636
|
+
}
|
|
13637
|
+
const currentStackItem = branchStack.length > 0 ? branchStack[branchStack.length - 1] : null;
|
|
13638
|
+
const renderPayload = {
|
|
13639
|
+
...targetObj,
|
|
13640
|
+
ancestry_id: targetObj.ancestry_id || targetObj.id,
|
|
13641
|
+
ancestral_node: targetTree.node ? targetTree.node.id : targetTree.node_id,
|
|
13642
|
+
tree: targetTree,
|
|
13643
|
+
_originNodeId: currentStackItem ? currentStackItem.nodeId : null,
|
|
13644
|
+
_branchDirection: currentStackItem ? currentStackItem.entryDirection : null,
|
|
13645
|
+
_forceUpdate: true
|
|
13646
|
+
};
|
|
13647
|
+
const rotation = branchStack.reduce((acc, step) => {
|
|
13648
|
+
return acc + (step.entryDirection === "left" ? -Math.PI / 2 : Math.PI / 2);
|
|
13649
|
+
}, 0);
|
|
13650
|
+
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
13651
|
+
},
|
|
13652
|
+
[
|
|
13653
|
+
readingMode,
|
|
13654
|
+
handleRenderAncestry,
|
|
13655
|
+
buildFullAncestryTree,
|
|
13656
|
+
ancestryDataRef.current
|
|
13657
|
+
]
|
|
13658
|
+
);
|
|
13043
13659
|
const handleCloseReadMode = (0, import_react26.useCallback)(() => {
|
|
13044
13660
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
13045
13661
|
}, []);
|
|
13046
|
-
const handleAncestrySectionChange = (0, import_react26.useCallback)(
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
|
|
13061
|
-
|
|
13062
|
-
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
|
|
13080
|
-
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13662
|
+
const handleAncestrySectionChange = (0, import_react26.useCallback)(
|
|
13663
|
+
(activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
13664
|
+
var _a2, _b2;
|
|
13665
|
+
const currentMode = stateRef.current.ancestry;
|
|
13666
|
+
let targetObj = ancestryOverride;
|
|
13667
|
+
if (!targetObj) {
|
|
13668
|
+
const currentAncestryId = currentMode.currentAncestryId;
|
|
13669
|
+
const ancestryObj = (ancestryDataRef.current || []).find(
|
|
13670
|
+
(a) => String(a.ancestry_id) === String(currentAncestryId)
|
|
13671
|
+
);
|
|
13672
|
+
targetObj = ancestryObj || (currentMode.isActive ? {
|
|
13673
|
+
...currentMode,
|
|
13674
|
+
ancestry_id: "temp_creating",
|
|
13675
|
+
ancestral_node: (_b2 = (_a2 = currentMode.tree) == null ? void 0 : _a2.node) == null ? void 0 : _b2.id
|
|
13676
|
+
} : null);
|
|
13677
|
+
}
|
|
13678
|
+
if (!targetObj) return;
|
|
13679
|
+
const targetId = targetObj.ancestry_id || targetObj.id;
|
|
13680
|
+
if (stateRef.current.lastRenderedAncestryId !== targetId) {
|
|
13681
|
+
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13682
|
+
stateRef.current.lastRenderedAncestryId = targetId;
|
|
13683
|
+
}
|
|
13684
|
+
const descriptionText = (ancestryOverride ? targetObj.description : currentMode.ancestryDescription) || targetObj.description || "";
|
|
13685
|
+
const savedSections = (ancestryOverride ? targetObj.description_sections : currentMode.ancestryDescriptionSections) || targetObj.description_sections || [];
|
|
13686
|
+
const sections = parseDescriptionSections(descriptionText, savedSections);
|
|
13687
|
+
let activeIndex = sections.findIndex(
|
|
13688
|
+
(s) => String(s.id) === String(activeSectionId)
|
|
13689
|
+
);
|
|
13690
|
+
if (activeIndex === -1 && !isNaN(parseInt(activeSectionId))) {
|
|
13691
|
+
activeIndex = sections.findIndex(
|
|
13692
|
+
(s) => s.numericId === parseInt(activeSectionId)
|
|
13693
|
+
);
|
|
13694
|
+
}
|
|
13695
|
+
if (activeIndex === -1) activeIndex = 0;
|
|
13696
|
+
if (stateRef.current.maxAncestryRenderIndex === void 0)
|
|
13697
|
+
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13698
|
+
stateRef.current.maxAncestryRenderIndex = activeIndex;
|
|
13699
|
+
const renderLimitIndex = stateRef.current.maxAncestryRenderIndex;
|
|
13700
|
+
const allowedIds = /* @__PURE__ */ new Set();
|
|
13701
|
+
allowedIds.add("preamble");
|
|
13702
|
+
allowedIds.add(0);
|
|
13703
|
+
allowedIds.add("0");
|
|
13704
|
+
for (let i = 0; i <= renderLimitIndex; i++) {
|
|
13705
|
+
if (sections[i]) {
|
|
13706
|
+
if (sections[i].id) allowedIds.add(String(sections[i].id));
|
|
13707
|
+
if (sections[i].numericId !== void 0 && sections[i].numericId !== null) {
|
|
13708
|
+
allowedIds.add(sections[i].numericId);
|
|
13709
|
+
allowedIds.add(String(sections[i].numericId));
|
|
13710
|
+
}
|
|
13086
13711
|
}
|
|
13087
13712
|
}
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13713
|
+
const activeSection = sections[activeIndex];
|
|
13714
|
+
let focusTargetId = activeSectionId;
|
|
13715
|
+
if (activeSection && activeSection.numericId !== void 0 && activeSection.numericId !== null) {
|
|
13716
|
+
focusTargetId = activeSection.numericId;
|
|
13717
|
+
}
|
|
13718
|
+
const treeToRender = ancestryOverride ? ancestryOverride.tree : currentMode.isActive && currentMode.tree ? currentMode.tree : targetObj.tree;
|
|
13719
|
+
const renderPayload = { ...targetObj, tree: treeToRender };
|
|
13720
|
+
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
13721
|
+
},
|
|
13722
|
+
[handleRenderAncestry]
|
|
13723
|
+
);
|
|
13098
13724
|
const handleEditAncestry = (0, import_react26.useCallback)(
|
|
13099
13725
|
async (ancestryObject) => {
|
|
13100
|
-
setContextMenu(
|
|
13726
|
+
setContextMenu(
|
|
13727
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
13728
|
+
);
|
|
13101
13729
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
13102
|
-
alert(
|
|
13730
|
+
alert(
|
|
13731
|
+
"N\xE3o foi poss\xEDvel carregar os dados desta ancestralidade para edi\xE7\xE3o."
|
|
13732
|
+
);
|
|
13103
13733
|
return;
|
|
13104
13734
|
}
|
|
13105
13735
|
stateRef.current.maxAncestryRenderIndex = 0;
|
|
13106
13736
|
const initialSections = /* @__PURE__ */ new Set(["preamble", 0]);
|
|
13107
13737
|
await handleRenderAncestry(ancestryObject, initialSections);
|
|
13108
|
-
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13738
|
+
const allParentNodes = Object.values(parentDataRef.current).flatMap(
|
|
13739
|
+
(fileData) => fileData.nodes
|
|
13740
|
+
);
|
|
13109
13741
|
const allAncestries = ancestryDataRef.current || [];
|
|
13110
|
-
const fullTree = buildFullAncestryTree(
|
|
13742
|
+
const fullTree = buildFullAncestryTree(
|
|
13743
|
+
ancestryObject.tree,
|
|
13744
|
+
allParentNodes,
|
|
13745
|
+
allAncestries
|
|
13746
|
+
);
|
|
13111
13747
|
if (!fullTree) {
|
|
13112
|
-
alert(
|
|
13748
|
+
alert(
|
|
13749
|
+
"Falha ao reconstruir a \xE1rvore de ancestralidade. Alguns Nodes podem estar faltando."
|
|
13750
|
+
);
|
|
13113
13751
|
return;
|
|
13114
13752
|
}
|
|
13115
|
-
const fullAbstractionTree = ancestryObject.abstraction_tree ? buildFullAncestryTree(
|
|
13753
|
+
const fullAbstractionTree = ancestryObject.abstraction_tree ? buildFullAncestryTree(
|
|
13754
|
+
ancestryObject.abstraction_tree,
|
|
13755
|
+
allParentNodes,
|
|
13756
|
+
allAncestries
|
|
13757
|
+
) : { node: fullTree.node, children: [] };
|
|
13116
13758
|
setAncestryMode({
|
|
13117
13759
|
isActive: true,
|
|
13118
13760
|
...ancestryObject,
|
|
@@ -13164,7 +13806,9 @@ function XViewScene({
|
|
|
13164
13806
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
13165
13807
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
13166
13808
|
if (!treeToUse || !treeToUse.node) {
|
|
13167
|
-
alert(
|
|
13809
|
+
alert(
|
|
13810
|
+
"Erro: A estrutura da ancestralidade \xE9 inv\xE1lida (Node raiz ausente)."
|
|
13811
|
+
);
|
|
13168
13812
|
return;
|
|
13169
13813
|
}
|
|
13170
13814
|
if (!save_view_data || !stateRef.current.nodeIdToParentFileMap) return;
|
|
@@ -13197,14 +13841,18 @@ function XViewScene({
|
|
|
13197
13841
|
};
|
|
13198
13842
|
};
|
|
13199
13843
|
const treeWithIds = convertTreeToIds(treeToUse);
|
|
13200
|
-
const abstractionTreeWithIds = convertTreeToIds(
|
|
13844
|
+
const abstractionTreeWithIds = convertTreeToIds(
|
|
13845
|
+
ancestryMode.abstraction_tree
|
|
13846
|
+
);
|
|
13201
13847
|
if (!treeWithIds) {
|
|
13202
13848
|
alert("Erro ao processar a \xE1rvore da ancestralidade.");
|
|
13203
13849
|
return;
|
|
13204
13850
|
}
|
|
13205
13851
|
let originalAncestryObj = null;
|
|
13206
13852
|
if (isEditMode && currentAncestryId) {
|
|
13207
|
-
originalAncestryObj = (ancestryDataRef.current || []).find(
|
|
13853
|
+
originalAncestryObj = (ancestryDataRef.current || []).find(
|
|
13854
|
+
(anc) => String(anc.ancestry_id) === String(currentAncestryId)
|
|
13855
|
+
);
|
|
13208
13856
|
}
|
|
13209
13857
|
const ancestryObjectToSave = {
|
|
13210
13858
|
ancestry_id: isEditMode && currentAncestryId ? currentAncestryId : `${import_short_uuid2.default.generate()}`,
|
|
@@ -13287,14 +13935,20 @@ function XViewScene({
|
|
|
13287
13935
|
try {
|
|
13288
13936
|
if (isExternalSave) {
|
|
13289
13937
|
try {
|
|
13290
|
-
const remoteResponse = await get_ancestry_file(
|
|
13938
|
+
const remoteResponse = await get_ancestry_file(
|
|
13939
|
+
targetFileIdForCache,
|
|
13940
|
+
targetOwnerIdForCache
|
|
13941
|
+
);
|
|
13291
13942
|
if (remoteResponse.success && Array.isArray(remoteResponse.data)) {
|
|
13292
13943
|
masterAncestryList = remoteResponse.data;
|
|
13293
13944
|
} else {
|
|
13294
13945
|
masterAncestryList = [];
|
|
13295
13946
|
}
|
|
13296
13947
|
} catch (fetchErr) {
|
|
13297
|
-
console.warn(
|
|
13948
|
+
console.warn(
|
|
13949
|
+
"Arquivo de destino n\xE3o existe ou erro ao buscar, criando novo:",
|
|
13950
|
+
fetchErr
|
|
13951
|
+
);
|
|
13298
13952
|
masterAncestryList = [];
|
|
13299
13953
|
}
|
|
13300
13954
|
} else {
|
|
@@ -13314,7 +13968,9 @@ function XViewScene({
|
|
|
13314
13968
|
const result = await save_view_data(finalSaveUrl, masterAncestryList);
|
|
13315
13969
|
if (result.success) {
|
|
13316
13970
|
const localList = [...ancestryDataRef.current || []];
|
|
13317
|
-
const localIndex = localList.findIndex(
|
|
13971
|
+
const localIndex = localList.findIndex(
|
|
13972
|
+
(a) => String(a.ancestry_id) === String(ancestryObjectToSave.ancestry_id)
|
|
13973
|
+
);
|
|
13318
13974
|
if (localIndex !== -1) {
|
|
13319
13975
|
localList[localIndex] = ancestryObjectToSave;
|
|
13320
13976
|
} else {
|
|
@@ -13342,11 +13998,29 @@ function XViewScene({
|
|
|
13342
13998
|
return;
|
|
13343
13999
|
}
|
|
13344
14000
|
if (!keepOpen) {
|
|
13345
|
-
setAncestryMode({
|
|
14001
|
+
setAncestryMode({
|
|
14002
|
+
isActive: false,
|
|
14003
|
+
tree: null,
|
|
14004
|
+
selectedParentId: null,
|
|
14005
|
+
isEditMode: false,
|
|
14006
|
+
currentAncestryId: null,
|
|
14007
|
+
ancestryName: "",
|
|
14008
|
+
ancestryDescription: "",
|
|
14009
|
+
ancestryDescriptionSections: [],
|
|
14010
|
+
isAddingNodes: false
|
|
14011
|
+
});
|
|
13346
14012
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13347
14013
|
}
|
|
13348
14014
|
},
|
|
13349
|
-
[
|
|
14015
|
+
[
|
|
14016
|
+
ancestryMode,
|
|
14017
|
+
ancestry_save_url,
|
|
14018
|
+
handleRenderAncestry,
|
|
14019
|
+
save_view_data,
|
|
14020
|
+
sceneConfigId,
|
|
14021
|
+
ownerId,
|
|
14022
|
+
get_ancestry_file
|
|
14023
|
+
]
|
|
13350
14024
|
);
|
|
13351
14025
|
const handleOpenAncestryRelEditor = (path, currentData) => {
|
|
13352
14026
|
setEditingAncestryRel({ visible: true, data: currentData, path });
|
|
@@ -13376,7 +14050,9 @@ function XViewScene({
|
|
|
13376
14050
|
if (ancestryToDelete && delete_file_action) {
|
|
13377
14051
|
const urls = extractFileUrlsFromProperties(ancestryToDelete);
|
|
13378
14052
|
if (urls.length > 0) {
|
|
13379
|
-
Promise.all(urls.map((url) => delete_file_action(url))).catch(
|
|
14053
|
+
Promise.all(urls.map((url) => delete_file_action(url))).catch(
|
|
14054
|
+
(err) => console.error("Erro ao deletar arquivos da ancestralidade:", err)
|
|
14055
|
+
);
|
|
13380
14056
|
}
|
|
13381
14057
|
}
|
|
13382
14058
|
if (!ancestryToDelete) {
|
|
@@ -13386,7 +14062,9 @@ function XViewScene({
|
|
|
13386
14062
|
const sourceFileId = ancestryToDelete._source_file_id;
|
|
13387
14063
|
const sourceOwnerId = ancestryToDelete._source_owner_id;
|
|
13388
14064
|
if (!sourceFileId || !sourceOwnerId) {
|
|
13389
|
-
alert(
|
|
14065
|
+
alert(
|
|
14066
|
+
"N\xE3o foi poss\xEDvel identificar o arquivo de origem desta ancestralidade."
|
|
14067
|
+
);
|
|
13390
14068
|
return;
|
|
13391
14069
|
}
|
|
13392
14070
|
const finalSaveUrl = `x_view_ancestry/${sourceOwnerId}/${sourceFileId}`;
|
|
@@ -13394,13 +14072,18 @@ function XViewScene({
|
|
|
13394
14072
|
(anc) => anc._source_file_id === sourceFileId && String(anc.ancestry_id) !== String(ancestryIdToDelete)
|
|
13395
14073
|
);
|
|
13396
14074
|
try {
|
|
13397
|
-
const result = await save_view_data(
|
|
14075
|
+
const result = await save_view_data(
|
|
14076
|
+
finalSaveUrl,
|
|
14077
|
+
updatedAncestriesForFile
|
|
14078
|
+
);
|
|
13398
14079
|
if (result.success) {
|
|
13399
14080
|
ancestryDataRef.current = (ancestryDataRef.current || []).filter(
|
|
13400
14081
|
(ancestry) => String(ancestry.ancestry_id) !== String(ancestryIdToDelete)
|
|
13401
14082
|
);
|
|
13402
14083
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
13403
|
-
const renderIndex = renderedAncestries.findIndex(
|
|
14084
|
+
const renderIndex = renderedAncestries.findIndex(
|
|
14085
|
+
(a) => String(a.id) === String(ancestryIdToDelete)
|
|
14086
|
+
);
|
|
13404
14087
|
if (renderIndex !== -1) {
|
|
13405
14088
|
const toRemove = renderedAncestries[renderIndex];
|
|
13406
14089
|
toRemove.lines.forEach((line) => {
|
|
@@ -13409,18 +14092,29 @@ function XViewScene({
|
|
|
13409
14092
|
if (line.material) line.material.dispose();
|
|
13410
14093
|
});
|
|
13411
14094
|
renderedAncestries.splice(renderIndex, 1);
|
|
13412
|
-
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
14095
|
+
stateRef.current.ancestryLinks = renderedAncestries.flatMap(
|
|
14096
|
+
(a) => a.lines
|
|
14097
|
+
);
|
|
13413
14098
|
}
|
|
13414
14099
|
setSceneVersion((v) => v + 1);
|
|
13415
14100
|
} else {
|
|
13416
|
-
throw new Error(
|
|
14101
|
+
throw new Error(
|
|
14102
|
+
result.error || "Ocorreu um erro desconhecido ao excluir."
|
|
14103
|
+
);
|
|
13417
14104
|
}
|
|
13418
14105
|
} catch (error) {
|
|
13419
14106
|
console.error("Falha ao excluir a ancestralidade:", error);
|
|
13420
14107
|
alert(`Erro ao excluir a ancestralidade: ${error.message}`);
|
|
13421
14108
|
return;
|
|
13422
14109
|
}
|
|
13423
|
-
setAncestryMode({
|
|
14110
|
+
setAncestryMode({
|
|
14111
|
+
isActive: false,
|
|
14112
|
+
tree: null,
|
|
14113
|
+
selectedParentId: null,
|
|
14114
|
+
isEditMode: false,
|
|
14115
|
+
currentAncestryId: null,
|
|
14116
|
+
ancestryName: ""
|
|
14117
|
+
});
|
|
13424
14118
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13425
14119
|
},
|
|
13426
14120
|
[save_view_data, delete_file_action]
|
|
@@ -13428,24 +14122,38 @@ function XViewScene({
|
|
|
13428
14122
|
const handleOpenAncestryBoard = (0, import_react26.useCallback)(() => {
|
|
13429
14123
|
setIsAncestryBoardOpen(true);
|
|
13430
14124
|
}, []);
|
|
13431
|
-
const handleSelectAncestryFromBoard = (0, import_react26.useCallback)(
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13439
|
-
|
|
13440
|
-
|
|
14125
|
+
const handleSelectAncestryFromBoard = (0, import_react26.useCallback)(
|
|
14126
|
+
(ancestry) => {
|
|
14127
|
+
setIsAncestryBoardOpen(false);
|
|
14128
|
+
setIsSidebarOpen(false);
|
|
14129
|
+
handleStartReadingAncestry(ancestry);
|
|
14130
|
+
},
|
|
14131
|
+
[handleStartReadingAncestry]
|
|
14132
|
+
);
|
|
14133
|
+
const handleSaveAncestryBoard = (0, import_react26.useCallback)(
|
|
14134
|
+
async (groups) => {
|
|
14135
|
+
if (!sceneConfigId || !viewParams || !session) return;
|
|
14136
|
+
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
14137
|
+
await save_ancestry_board_action(
|
|
14138
|
+
sceneConfigId,
|
|
14139
|
+
sceneType,
|
|
14140
|
+
groups,
|
|
14141
|
+
session,
|
|
14142
|
+
ownerId
|
|
14143
|
+
);
|
|
14144
|
+
},
|
|
14145
|
+
[sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
|
|
14146
|
+
);
|
|
13441
14147
|
const existingNodeTypes = (0, import_react26.useMemo)(() => {
|
|
13442
14148
|
if (!parentDataRef.current) {
|
|
13443
14149
|
return [];
|
|
13444
14150
|
}
|
|
13445
|
-
const allTypes = Object.values(parentDataRef.current).flatMap(
|
|
13446
|
-
|
|
13447
|
-
|
|
13448
|
-
|
|
14151
|
+
const allTypes = Object.values(parentDataRef.current).flatMap(
|
|
14152
|
+
(fileData) => fileData.nodes.flatMap((node) => {
|
|
14153
|
+
if (Array.isArray(node.type)) return node.type;
|
|
14154
|
+
return [node.type];
|
|
14155
|
+
})
|
|
14156
|
+
).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
|
|
13449
14157
|
return [...new Set(allTypes)];
|
|
13450
14158
|
}, [parentDataRef.current, sceneVersion]);
|
|
13451
14159
|
const searchableDbNodes = (0, import_react26.useMemo)(() => {
|
|
@@ -13459,7 +14167,10 @@ function XViewScene({
|
|
|
13459
14167
|
}, [parentDataRef.current, sceneVersion]);
|
|
13460
14168
|
const handleAddExistingNode = (0, import_react26.useCallback)(
|
|
13461
14169
|
(nodeId) => {
|
|
13462
|
-
return userActionHandlers.handleAddExistingNodeById(
|
|
14170
|
+
return userActionHandlers.handleAddExistingNodeById(
|
|
14171
|
+
actionHandlerContext,
|
|
14172
|
+
nodeId
|
|
14173
|
+
);
|
|
13463
14174
|
},
|
|
13464
14175
|
[actionHandlerContext]
|
|
13465
14176
|
);
|
|
@@ -13467,7 +14178,9 @@ function XViewScene({
|
|
|
13467
14178
|
var _a2, _b2, _c2;
|
|
13468
14179
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
13469
14180
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
13470
|
-
console.warn(
|
|
14181
|
+
console.warn(
|
|
14182
|
+
"N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente."
|
|
14183
|
+
);
|
|
13471
14184
|
return;
|
|
13472
14185
|
}
|
|
13473
14186
|
if (!save_view_data) return;
|
|
@@ -13504,48 +14217,68 @@ function XViewScene({
|
|
|
13504
14217
|
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
13505
14218
|
const allAvailableNodes = (0, import_react26.useMemo)(() => {
|
|
13506
14219
|
if (!parentDataRef.current) return [];
|
|
13507
|
-
return Object.values(parentDataRef.current).flatMap(
|
|
14220
|
+
return Object.values(parentDataRef.current).flatMap(
|
|
14221
|
+
(fileData) => fileData.nodes || []
|
|
14222
|
+
);
|
|
13508
14223
|
}, [sceneVersion, isInitialized]);
|
|
13509
14224
|
const allAvailableAncestries = (0, import_react26.useMemo)(() => {
|
|
13510
14225
|
return ancestryDataRef.current || [];
|
|
13511
14226
|
}, [sceneVersion, isInitialized]);
|
|
13512
|
-
const handleOpenReference = (0, import_react26.useCallback)(
|
|
13513
|
-
|
|
13514
|
-
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
14227
|
+
const handleOpenReference = (0, import_react26.useCallback)(
|
|
14228
|
+
(referenceData) => {
|
|
14229
|
+
const { type, id } = referenceData;
|
|
14230
|
+
if (type === "node") {
|
|
14231
|
+
const targetNode = allAvailableNodes.find(
|
|
14232
|
+
(n) => String(n.id) === String(id)
|
|
14233
|
+
);
|
|
14234
|
+
if (targetNode) {
|
|
14235
|
+
setAncestryLinkDetails(null);
|
|
14236
|
+
setDetailsLink(null);
|
|
14237
|
+
setDetailsNode(targetNode);
|
|
14238
|
+
const sceneMesh = stateRef.current.nodeObjects[String(id)];
|
|
14239
|
+
if (sceneMesh) {
|
|
14240
|
+
tweenToTarget(sceneMesh);
|
|
14241
|
+
}
|
|
14242
|
+
} else {
|
|
14243
|
+
alert("Node original n\xE3o encontrado neste contexto.");
|
|
14244
|
+
}
|
|
14245
|
+
} else if (type === "ancestry") {
|
|
14246
|
+
const targetAncestry = allAvailableAncestries.find(
|
|
14247
|
+
(a) => String(a.ancestry_id) === String(id)
|
|
14248
|
+
);
|
|
14249
|
+
if (targetAncestry) {
|
|
14250
|
+
setDetailsNode(null);
|
|
14251
|
+
setDetailsLink(null);
|
|
14252
|
+
setAncestryLinkDetails(null);
|
|
14253
|
+
handleEditAncestry(targetAncestry);
|
|
14254
|
+
} else {
|
|
14255
|
+
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
13523
14256
|
}
|
|
13524
|
-
} else {
|
|
13525
|
-
alert("Node original n\xE3o encontrado neste contexto.");
|
|
13526
|
-
}
|
|
13527
|
-
} else if (type === "ancestry") {
|
|
13528
|
-
const targetAncestry = allAvailableAncestries.find((a) => String(a.ancestry_id) === String(id));
|
|
13529
|
-
if (targetAncestry) {
|
|
13530
|
-
setDetailsNode(null);
|
|
13531
|
-
setDetailsLink(null);
|
|
13532
|
-
setAncestryLinkDetails(null);
|
|
13533
|
-
handleEditAncestry(targetAncestry);
|
|
13534
|
-
} else {
|
|
13535
|
-
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
13536
14257
|
}
|
|
13537
|
-
}
|
|
13538
|
-
|
|
14258
|
+
},
|
|
14259
|
+
[
|
|
14260
|
+
allAvailableNodes,
|
|
14261
|
+
allAvailableAncestries,
|
|
14262
|
+
handleEditAncestry,
|
|
14263
|
+
tweenToTarget
|
|
14264
|
+
]
|
|
14265
|
+
);
|
|
13539
14266
|
const handleToggleAncestryAddMode = (0, import_react26.useCallback)(() => {
|
|
13540
|
-
setAncestryMode((prev) => ({
|
|
14267
|
+
setAncestryMode((prev) => ({
|
|
14268
|
+
...prev,
|
|
14269
|
+
isAddingNodes: !prev.isAddingNodes
|
|
14270
|
+
}));
|
|
13541
14271
|
}, []);
|
|
13542
|
-
const handleFocusNode = (0, import_react26.useCallback)(
|
|
13543
|
-
|
|
13544
|
-
|
|
13545
|
-
|
|
13546
|
-
|
|
13547
|
-
|
|
13548
|
-
|
|
14272
|
+
const handleFocusNode = (0, import_react26.useCallback)(
|
|
14273
|
+
(nodeData) => {
|
|
14274
|
+
if (!nodeData) return;
|
|
14275
|
+
const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
|
|
14276
|
+
if (nodeMesh) {
|
|
14277
|
+
tweenToTarget(nodeMesh, 1.2);
|
|
14278
|
+
}
|
|
14279
|
+
},
|
|
14280
|
+
[tweenToTarget]
|
|
14281
|
+
);
|
|
13549
14282
|
const availableDatasets = (0, import_react26.useMemo)(() => {
|
|
13550
14283
|
if (!sceneDataRef.current || !parentDataRef.current) return [];
|
|
13551
14284
|
return sceneDataRef.current.parent_dbs.map((db) => {
|
|
@@ -13556,7 +14289,9 @@ function XViewScene({
|
|
|
13556
14289
|
};
|
|
13557
14290
|
});
|
|
13558
14291
|
}, [sceneVersion, isInitialized]);
|
|
13559
|
-
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
|
|
14292
|
+
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
|
|
14293
|
+
String(creationMode.sourceNodeData.id)
|
|
14294
|
+
)) == null ? void 0 : _b.parentFileId : null;
|
|
13560
14295
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
13561
14296
|
(0, import_react26.useEffect)(() => {
|
|
13562
14297
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
@@ -13571,11 +14306,19 @@ function XViewScene({
|
|
|
13571
14306
|
setHasFocusedInitial(true);
|
|
13572
14307
|
}
|
|
13573
14308
|
}
|
|
13574
|
-
}, [
|
|
14309
|
+
}, [
|
|
14310
|
+
isInitialized,
|
|
14311
|
+
sceneVersion,
|
|
14312
|
+
focusNodeId,
|
|
14313
|
+
hasFocusedInitial,
|
|
14314
|
+
tweenToTarget
|
|
14315
|
+
]);
|
|
13575
14316
|
(0, import_react26.useEffect)(() => {
|
|
13576
14317
|
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
13577
14318
|
const ancestries = ancestryDataRef.current || [];
|
|
13578
|
-
const targetAncestry = ancestries.find(
|
|
14319
|
+
const targetAncestry = ancestries.find(
|
|
14320
|
+
(a) => String(a.ancestry_id) === String(focusAncestryId)
|
|
14321
|
+
);
|
|
13579
14322
|
if (targetAncestry) {
|
|
13580
14323
|
setTimeout(() => {
|
|
13581
14324
|
handleStartReadingAncestry(targetAncestry);
|
|
@@ -13585,18 +14328,38 @@ function XViewScene({
|
|
|
13585
14328
|
setHasOpenedInitialAncestry(true);
|
|
13586
14329
|
}
|
|
13587
14330
|
}
|
|
13588
|
-
}, [
|
|
14331
|
+
}, [
|
|
14332
|
+
isInitialized,
|
|
14333
|
+
sceneVersion,
|
|
14334
|
+
focusAncestryId,
|
|
14335
|
+
hasOpenedInitialAncestry,
|
|
14336
|
+
handleStartReadingAncestry
|
|
14337
|
+
]);
|
|
13589
14338
|
(0, import_react26.useEffect)(() => {
|
|
13590
14339
|
function handleKeyDown(event) {
|
|
13591
14340
|
var _a2, _b2, _c2;
|
|
13592
14341
|
const context = actionHandlerContext;
|
|
13593
14342
|
if (event.key === "Escape") {
|
|
13594
|
-
if (stateRef.current.connection.isActive)
|
|
13595
|
-
|
|
13596
|
-
if (stateRef.current.
|
|
13597
|
-
|
|
14343
|
+
if (stateRef.current.connection.isActive)
|
|
14344
|
+
userActionHandlers.handleCancelConnection(context);
|
|
14345
|
+
if (stateRef.current.relink.isActive)
|
|
14346
|
+
userActionHandlers.handleCancelRelink(context);
|
|
14347
|
+
if (stateRef.current.creation.isActive)
|
|
14348
|
+
userActionHandlers.handleCancelCreation(context);
|
|
14349
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive)
|
|
14350
|
+
userActionHandlers.handleCancelVersioning(context);
|
|
13598
14351
|
if (stateRef.current.ancestry.isActive) {
|
|
13599
|
-
setAncestryMode({
|
|
14352
|
+
setAncestryMode({
|
|
14353
|
+
isActive: false,
|
|
14354
|
+
tree: null,
|
|
14355
|
+
selectedParentId: null,
|
|
14356
|
+
isEditMode: false,
|
|
14357
|
+
currentAncestryId: null,
|
|
14358
|
+
ancestryName: "",
|
|
14359
|
+
ancestryDescription: "",
|
|
14360
|
+
ancestryDescriptionSections: [],
|
|
14361
|
+
isAddingNodes: false
|
|
14362
|
+
});
|
|
13600
14363
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13601
14364
|
}
|
|
13602
14365
|
if (questMode.isActive) {
|
|
@@ -13605,7 +14368,9 @@ function XViewScene({
|
|
|
13605
14368
|
if (stateRef.current.selectedNodes.size > 0) {
|
|
13606
14369
|
stateRef.current.selectedNodes.clear();
|
|
13607
14370
|
}
|
|
13608
|
-
setContextMenu(
|
|
14371
|
+
setContextMenu(
|
|
14372
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
14373
|
+
);
|
|
13609
14374
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
13610
14375
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
13611
14376
|
}
|
|
@@ -13624,7 +14389,9 @@ function XViewScene({
|
|
|
13624
14389
|
let attempts = 0;
|
|
13625
14390
|
const MIN_CLEARANCE = 15;
|
|
13626
14391
|
while (isOccupied && attempts < 30) {
|
|
13627
|
-
isOccupied = existingNodes.some(
|
|
14392
|
+
isOccupied = existingNodes.some(
|
|
14393
|
+
(mesh) => mesh.position.distanceTo(ghostPosition) < MIN_CLEARANCE
|
|
14394
|
+
);
|
|
13628
14395
|
if (isOccupied) {
|
|
13629
14396
|
ghostPosition.x = controls.target.x + Math.cos(angle) * radius;
|
|
13630
14397
|
ghostPosition.y = controls.target.y + (Math.random() - 0.5) * 8;
|
|
@@ -13643,7 +14410,11 @@ function XViewScene({
|
|
|
13643
14410
|
intensity: 0,
|
|
13644
14411
|
type: ["quest"]
|
|
13645
14412
|
};
|
|
13646
|
-
const ghostNode = createNodeMesh(
|
|
14413
|
+
const ghostNode = createNodeMesh(
|
|
14414
|
+
ghostData,
|
|
14415
|
+
ghostPosition,
|
|
14416
|
+
glowTexture
|
|
14417
|
+
);
|
|
13647
14418
|
ghostNode.traverse((child) => {
|
|
13648
14419
|
if (child.isMesh) {
|
|
13649
14420
|
child.material.transparent = true;
|
|
@@ -13690,13 +14461,49 @@ function XViewScene({
|
|
|
13690
14461
|
return /* @__PURE__ */ import_react26.default.createElement(LoadingScreen, null);
|
|
13691
14462
|
}
|
|
13692
14463
|
if (permissionStatus === "denied") {
|
|
13693
|
-
return /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react26.default.createElement(
|
|
14464
|
+
return /* @__PURE__ */ import_react26.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react26.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react26.default.createElement(
|
|
14465
|
+
"svg",
|
|
14466
|
+
{
|
|
14467
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
14468
|
+
fill: "none",
|
|
14469
|
+
viewBox: "0 0 24 24",
|
|
14470
|
+
strokeWidth: 1.5,
|
|
14471
|
+
stroke: "currentColor",
|
|
14472
|
+
className: "w-16 h-16 mx-auto"
|
|
14473
|
+
},
|
|
14474
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14475
|
+
"path",
|
|
14476
|
+
{
|
|
14477
|
+
strokeLinecap: "round",
|
|
14478
|
+
strokeLinejoin: "round",
|
|
14479
|
+
d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
|
|
14480
|
+
}
|
|
14481
|
+
)
|
|
14482
|
+
)), /* @__PURE__ */ import_react26.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react26.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react26.default.createElement(
|
|
13694
14483
|
"button",
|
|
13695
14484
|
{
|
|
13696
14485
|
onClick: () => router.push("/dashboard/scenes"),
|
|
13697
14486
|
className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
|
|
13698
14487
|
},
|
|
13699
|
-
/* @__PURE__ */ import_react26.default.createElement(
|
|
14488
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14489
|
+
"svg",
|
|
14490
|
+
{
|
|
14491
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
14492
|
+
fill: "none",
|
|
14493
|
+
viewBox: "0 0 24 24",
|
|
14494
|
+
strokeWidth: 2,
|
|
14495
|
+
stroke: "currentColor",
|
|
14496
|
+
className: "w-5 h-5"
|
|
14497
|
+
},
|
|
14498
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14499
|
+
"path",
|
|
14500
|
+
{
|
|
14501
|
+
strokeLinecap: "round",
|
|
14502
|
+
strokeLinejoin: "round",
|
|
14503
|
+
d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"
|
|
14504
|
+
}
|
|
14505
|
+
)
|
|
14506
|
+
),
|
|
13700
14507
|
"Voltar para Scenes"
|
|
13701
14508
|
)));
|
|
13702
14509
|
}
|
|
@@ -13743,7 +14550,14 @@ function XViewScene({
|
|
|
13743
14550
|
onImageChange: handleGhostNodeImageChange,
|
|
13744
14551
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13745
14552
|
onMentionClick: handleAddExistingNode,
|
|
13746
|
-
style: {
|
|
14553
|
+
style: {
|
|
14554
|
+
position: "absolute",
|
|
14555
|
+
left: `${formPosition.left}px`,
|
|
14556
|
+
top: `${formPosition.top}px`,
|
|
14557
|
+
opacity: formPosition.opacity,
|
|
14558
|
+
zIndex: 20,
|
|
14559
|
+
transition: "opacity 200ms ease-out"
|
|
14560
|
+
},
|
|
13747
14561
|
refEl: formRef,
|
|
13748
14562
|
existingTypes: existingNodeTypes,
|
|
13749
14563
|
initialColor: (_c = creationMode.sourceNodeData) == null ? void 0 : _c.color,
|
|
@@ -13767,7 +14581,14 @@ function XViewScene({
|
|
|
13767
14581
|
onImageChange: handleGhostNodeImageChange,
|
|
13768
14582
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13769
14583
|
onMentionClick: handleAddExistingNode,
|
|
13770
|
-
style: {
|
|
14584
|
+
style: {
|
|
14585
|
+
position: "absolute",
|
|
14586
|
+
left: `${formPosition.left}px`,
|
|
14587
|
+
top: `${formPosition.top}px`,
|
|
14588
|
+
opacity: formPosition.opacity,
|
|
14589
|
+
zIndex: 20,
|
|
14590
|
+
transition: "opacity 200ms ease-out"
|
|
14591
|
+
},
|
|
13771
14592
|
refEl: formRef,
|
|
13772
14593
|
fixedType: (_e = versionMode.sourceNodeData) == null ? void 0 : _e.type,
|
|
13773
14594
|
fixedColor: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.color,
|
|
@@ -13784,7 +14605,13 @@ function XViewScene({
|
|
|
13784
14605
|
onNameChange: handleGhostNodeNameChange,
|
|
13785
14606
|
onColorChange: handleGhostNodeColorChange,
|
|
13786
14607
|
onSizeChange: handleGhostNodeSizeChange,
|
|
13787
|
-
style: {
|
|
14608
|
+
style: {
|
|
14609
|
+
position: "absolute",
|
|
14610
|
+
left: `16px`,
|
|
14611
|
+
top: `16px`,
|
|
14612
|
+
zIndex: 20,
|
|
14613
|
+
transition: "opacity 200ms ease-out"
|
|
14614
|
+
},
|
|
13788
14615
|
refEl: formRef,
|
|
13789
14616
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13790
14617
|
onMentionClick: handleAddExistingNode,
|
|
@@ -13799,7 +14626,14 @@ function XViewScene({
|
|
|
13799
14626
|
"div",
|
|
13800
14627
|
{
|
|
13801
14628
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
13802
|
-
style: {
|
|
14629
|
+
style: {
|
|
14630
|
+
top: 16,
|
|
14631
|
+
right: 16,
|
|
14632
|
+
zIndex: 1100,
|
|
14633
|
+
maxHeight: "calc(100vh - 32px)",
|
|
14634
|
+
width: `${readModeWidth}px`,
|
|
14635
|
+
maxWidth: "92vw"
|
|
14636
|
+
}
|
|
13803
14637
|
},
|
|
13804
14638
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
13805
14639
|
"div",
|
|
@@ -13857,7 +14691,16 @@ function XViewScene({
|
|
|
13857
14691
|
onSave: handleSaveAncestry,
|
|
13858
14692
|
onEditRelationship: handleOpenAncestryRelEditor,
|
|
13859
14693
|
onClose: () => {
|
|
13860
|
-
setAncestryMode({
|
|
14694
|
+
setAncestryMode({
|
|
14695
|
+
isActive: false,
|
|
14696
|
+
tree: null,
|
|
14697
|
+
selectedParentId: null,
|
|
14698
|
+
isEditMode: false,
|
|
14699
|
+
currentAncestryId: null,
|
|
14700
|
+
ancestryName: "",
|
|
14701
|
+
ancestryDescription: "",
|
|
14702
|
+
isAddingNodes: false
|
|
14703
|
+
});
|
|
13861
14704
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13862
14705
|
},
|
|
13863
14706
|
availableNodes: allAvailableNodes,
|
|
@@ -13922,7 +14765,12 @@ function XViewScene({
|
|
|
13922
14765
|
onOpenImageViewer: handleOpenImageViewer,
|
|
13923
14766
|
existingTypes: existingNodeTypes,
|
|
13924
14767
|
onImageChange: (useImage, url, currentColorOverride) => {
|
|
13925
|
-
const updatedNode = {
|
|
14768
|
+
const updatedNode = {
|
|
14769
|
+
...detailsNode,
|
|
14770
|
+
useImageAsTexture: useImage,
|
|
14771
|
+
textureImageUrl: url,
|
|
14772
|
+
color: currentColorOverride || detailsNode.color
|
|
14773
|
+
};
|
|
13926
14774
|
updateExistingNodeVisuals(stateRef.current, updatedNode);
|
|
13927
14775
|
setDetailsNode(updatedNode);
|
|
13928
14776
|
},
|
|
@@ -13996,7 +14844,9 @@ function XViewScene({
|
|
|
13996
14844
|
parentData: parentDataRef.current,
|
|
13997
14845
|
sceneData: sceneDataRef.current,
|
|
13998
14846
|
ancestryData: ancestryDataRef.current,
|
|
13999
|
-
onClose: () => setContextMenu(
|
|
14847
|
+
onClose: () => setContextMenu(
|
|
14848
|
+
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
14849
|
+
),
|
|
14000
14850
|
onStartCreation: (data) => userActionHandlers.handleStartCreation(actionHandlerContext, data),
|
|
14001
14851
|
onStartConnection: (data) => userActionHandlers.handleStartConnection(actionHandlerContext, data),
|
|
14002
14852
|
onStartVersioning: handleStartVersioning,
|
|
@@ -14004,7 +14854,11 @@ function XViewScene({
|
|
|
14004
14854
|
onDeleteNode: (data) => userActionHandlers.handleDeleteNode(actionHandlerContext, data),
|
|
14005
14855
|
onDismissNode: (data) => userActionHandlers.handleDismissNode(actionHandlerContext, data),
|
|
14006
14856
|
onDismissOtherNodes: (data) => userActionHandlers.handleDismissOtherNodes(actionHandlerContext, data),
|
|
14007
|
-
onExpandConnections: (sourceNode, links) => userActionHandlers.handleExpandConnections(
|
|
14857
|
+
onExpandConnections: (sourceNode, links) => userActionHandlers.handleExpandConnections(
|
|
14858
|
+
actionHandlerContext,
|
|
14859
|
+
sourceNode,
|
|
14860
|
+
links
|
|
14861
|
+
),
|
|
14008
14862
|
onRenderAncestry: handleStartReadingAncestry,
|
|
14009
14863
|
onEditAncestry: handleEditAncestry,
|
|
14010
14864
|
onDeleteAncestry: (ancestryId) => handleDeleteAncestry(ancestryId),
|
|
@@ -14017,9 +14871,18 @@ function XViewScene({
|
|
|
14017
14871
|
data: multiContextMenu,
|
|
14018
14872
|
userRole: userPermissionRole,
|
|
14019
14873
|
onClose: () => setMultiContextMenu((prev) => ({ ...prev, visible: false })),
|
|
14020
|
-
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
|
|
14021
|
-
|
|
14022
|
-
|
|
14874
|
+
onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
|
|
14875
|
+
actionHandlerContext,
|
|
14876
|
+
ids
|
|
14877
|
+
),
|
|
14878
|
+
onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(
|
|
14879
|
+
actionHandlerContext,
|
|
14880
|
+
ids
|
|
14881
|
+
),
|
|
14882
|
+
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(
|
|
14883
|
+
actionHandlerContext,
|
|
14884
|
+
ids
|
|
14885
|
+
)
|
|
14023
14886
|
}
|
|
14024
14887
|
),
|
|
14025
14888
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
@@ -14040,7 +14903,13 @@ function XViewScene({
|
|
|
14040
14903
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
14041
14904
|
}
|
|
14042
14905
|
),
|
|
14043
|
-
/* @__PURE__ */ import_react26.default.createElement(
|
|
14906
|
+
/* @__PURE__ */ import_react26.default.createElement(
|
|
14907
|
+
ImageViewer,
|
|
14908
|
+
{
|
|
14909
|
+
data: imageViewer,
|
|
14910
|
+
onClose: () => setImageViewer({ ...imageViewer, visible: false })
|
|
14911
|
+
}
|
|
14912
|
+
),
|
|
14044
14913
|
/* @__PURE__ */ import_react26.default.createElement(
|
|
14045
14914
|
AncestryBoard,
|
|
14046
14915
|
{
|