@lv-x-software-house/x_view 1.2.4-dev.1 → 1.2.4-dev.4
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 +671 -335
- package/dist/index.mjs +597 -261
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,9 +43,9 @@ __export(index_exports, {
|
|
|
43
43
|
module.exports = __toCommonJS(index_exports);
|
|
44
44
|
|
|
45
45
|
// src/XViewScene.jsx
|
|
46
|
-
var
|
|
46
|
+
var import_react25 = __toESM(require("react"));
|
|
47
47
|
var import_navigation = require("next/navigation");
|
|
48
|
-
var
|
|
48
|
+
var import_react26 = require("next-auth/react");
|
|
49
49
|
var import_crypto_js = __toESM(require("crypto-js"));
|
|
50
50
|
var THREE3 = __toESM(require("three"));
|
|
51
51
|
var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
|
|
@@ -7848,9 +7848,181 @@ function InSceneVersionForm({
|
|
|
7848
7848
|
));
|
|
7849
7849
|
}
|
|
7850
7850
|
|
|
7851
|
-
// src/components/
|
|
7851
|
+
// src/components/InSceneQuestForm.jsx
|
|
7852
7852
|
var import_react16 = __toESM(require("react"));
|
|
7853
7853
|
var import_fi14 = require("react-icons/fi");
|
|
7854
|
+
var QUEST_STATUS_COLORS = {
|
|
7855
|
+
"Backlog": "#64748b",
|
|
7856
|
+
// Slate (Cinza azulado)
|
|
7857
|
+
"In Progress": "#eab308",
|
|
7858
|
+
// Yellow (Amarelo)
|
|
7859
|
+
"Review": "#a855f7",
|
|
7860
|
+
// Purple (Roxo)
|
|
7861
|
+
"Done": "#22c55e"
|
|
7862
|
+
// Green (Verde)
|
|
7863
|
+
};
|
|
7864
|
+
function InSceneQuestForm({
|
|
7865
|
+
onSave,
|
|
7866
|
+
onCancel,
|
|
7867
|
+
style,
|
|
7868
|
+
refEl,
|
|
7869
|
+
onOpenImageViewer,
|
|
7870
|
+
availableNodes = [],
|
|
7871
|
+
availableAncestries = [],
|
|
7872
|
+
onMentionClick,
|
|
7873
|
+
onUploadFile
|
|
7874
|
+
}) {
|
|
7875
|
+
const [name, setName] = (0, import_react16.useState)("");
|
|
7876
|
+
const [types, setTypes] = (0, import_react16.useState)(["quest"]);
|
|
7877
|
+
const [typeInput, setTypeInput] = (0, import_react16.useState)("");
|
|
7878
|
+
const [status, setStatus] = (0, import_react16.useState)("Backlog");
|
|
7879
|
+
const [size, setSize] = (0, import_react16.useState)("medium");
|
|
7880
|
+
const [intensity, setIntensity] = (0, import_react16.useState)(0);
|
|
7881
|
+
const [description, setDescription] = (0, import_react16.useState)("");
|
|
7882
|
+
const [customProps, setCustomProps] = (0, import_react16.useState)([]);
|
|
7883
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
|
|
7884
|
+
const propsEndRef = (0, import_react16.useRef)(null);
|
|
7885
|
+
const handleAddProp = () => {
|
|
7886
|
+
const newProp = createNewCustomProperty(customProps);
|
|
7887
|
+
setCustomProps([...customProps, newProp]);
|
|
7888
|
+
setTimeout(() => {
|
|
7889
|
+
var _a;
|
|
7890
|
+
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
7891
|
+
}, 100);
|
|
7892
|
+
};
|
|
7893
|
+
const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
|
|
7894
|
+
const handleUpdateProp = (index, updatedProp) => {
|
|
7895
|
+
const newProps = [...customProps];
|
|
7896
|
+
newProps[index] = updatedProp;
|
|
7897
|
+
setCustomProps(newProps);
|
|
7898
|
+
};
|
|
7899
|
+
const handleAddType = (newType) => {
|
|
7900
|
+
const trimmed = newType.trim().toLowerCase();
|
|
7901
|
+
if (trimmed && !types.includes(trimmed)) {
|
|
7902
|
+
setTypes([...types, trimmed]);
|
|
7903
|
+
setTypeInput("");
|
|
7904
|
+
}
|
|
7905
|
+
};
|
|
7906
|
+
const handleRemoveType = (indexToRemove) => {
|
|
7907
|
+
if (types[indexToRemove] === "quest") return;
|
|
7908
|
+
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
7909
|
+
};
|
|
7910
|
+
const handleTypeInputKeyDown = (e) => {
|
|
7911
|
+
if (e.key === "Enter") {
|
|
7912
|
+
e.preventDefault();
|
|
7913
|
+
handleAddType(typeInput);
|
|
7914
|
+
} else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
|
|
7915
|
+
handleRemoveType(types.length - 1);
|
|
7916
|
+
}
|
|
7917
|
+
};
|
|
7918
|
+
const handleSubmit = (e) => {
|
|
7919
|
+
e.preventDefault();
|
|
7920
|
+
if (!name.trim()) {
|
|
7921
|
+
alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
|
|
7922
|
+
return;
|
|
7923
|
+
}
|
|
7924
|
+
const additionalData = toObjectFromCustomProps(
|
|
7925
|
+
customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
|
|
7926
|
+
);
|
|
7927
|
+
const processedSections = processDescriptionForSave(description, []);
|
|
7928
|
+
onSave({
|
|
7929
|
+
name: name.trim(),
|
|
7930
|
+
type: types,
|
|
7931
|
+
color: QUEST_STATUS_COLORS[status],
|
|
7932
|
+
// Cor atrelada ao status
|
|
7933
|
+
status,
|
|
7934
|
+
size,
|
|
7935
|
+
intensity,
|
|
7936
|
+
description: description.trim(),
|
|
7937
|
+
description_sections: processedSections,
|
|
7938
|
+
useImageAsTexture: false,
|
|
7939
|
+
textureImageUrl: null,
|
|
7940
|
+
...additionalData
|
|
7941
|
+
});
|
|
7942
|
+
};
|
|
7943
|
+
const swallow = (e) => e.stopPropagation();
|
|
7944
|
+
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
7945
|
+
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
7946
|
+
return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
|
|
7947
|
+
"div",
|
|
7948
|
+
{
|
|
7949
|
+
ref: refEl,
|
|
7950
|
+
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 w-[min(92vw,440px)] overflow-hidden",
|
|
7951
|
+
style,
|
|
7952
|
+
onPointerDown: swallow,
|
|
7953
|
+
onClick: swallow,
|
|
7954
|
+
onWheel: swallow,
|
|
7955
|
+
onContextMenu: swallow,
|
|
7956
|
+
onDoubleClick: swallow
|
|
7957
|
+
},
|
|
7958
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
7959
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova Tarefa / Objetivo")), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")),
|
|
7960
|
+
/* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement(
|
|
7961
|
+
"select",
|
|
7962
|
+
{
|
|
7963
|
+
value: status,
|
|
7964
|
+
onChange: (e) => setStatus(e.target.value),
|
|
7965
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 appearance-none cursor-pointer",
|
|
7966
|
+
style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
|
|
7967
|
+
},
|
|
7968
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Backlog" }, "Backlog"),
|
|
7969
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
7970
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Review" }, "Review"),
|
|
7971
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
|
|
7972
|
+
)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
7973
|
+
"input",
|
|
7974
|
+
{
|
|
7975
|
+
type: "text",
|
|
7976
|
+
value: typeInput,
|
|
7977
|
+
onChange: (e) => setTypeInput(e.target.value),
|
|
7978
|
+
onKeyDown: handleTypeInputKeyDown,
|
|
7979
|
+
onBlur: () => {
|
|
7980
|
+
if (typeInput.trim()) handleAddType(typeInput);
|
|
7981
|
+
},
|
|
7982
|
+
className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
|
|
7983
|
+
placeholder: "Ex.: Bugfix",
|
|
7984
|
+
autoComplete: "off"
|
|
7985
|
+
}
|
|
7986
|
+
))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(
|
|
7987
|
+
DescriptionDisplay,
|
|
7988
|
+
{
|
|
7989
|
+
description,
|
|
7990
|
+
savedSections: [],
|
|
7991
|
+
availableNodes,
|
|
7992
|
+
availableAncestries,
|
|
7993
|
+
onMentionClick,
|
|
7994
|
+
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
7995
|
+
}
|
|
7996
|
+
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 }))), !description && /* @__PURE__ */ import_react16.default.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Cen\xE1rio (Size)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ import_react16.default.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react16.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react16.default.createElement(
|
|
7997
|
+
CustomPropertyDisplay,
|
|
7998
|
+
{
|
|
7999
|
+
key: prop.id,
|
|
8000
|
+
prop,
|
|
8001
|
+
onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
|
|
8002
|
+
onRemove: () => handleRemoveProp(index),
|
|
8003
|
+
onOpenImageViewer,
|
|
8004
|
+
unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
|
|
8005
|
+
onUploadFile
|
|
8006
|
+
}
|
|
8007
|
+
)), /* @__PURE__ */ import_react16.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm" }, "Cancelar"), /* @__PURE__ */ import_react16.default.createElement("button", { type: "submit", className: "px-4 py-2 rounded-lg bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 transition-colors font-semibold text-sm shadow-[0_8px_24px_rgba(99,102,241,0.35)]" }, "Salvar Quest")))
|
|
8008
|
+
), isDescriptionModalOpen && /* @__PURE__ */ import_react16.default.createElement(
|
|
8009
|
+
DescriptionEditModal,
|
|
8010
|
+
{
|
|
8011
|
+
isOpen: isDescriptionModalOpen,
|
|
8012
|
+
title: "Editar Descri\xE7\xE3o da Quest",
|
|
8013
|
+
initialValue: description,
|
|
8014
|
+
onSave: (newDescription) => setDescription(newDescription),
|
|
8015
|
+
onClose: () => setIsDescriptionModalOpen(false),
|
|
8016
|
+
availableNodes,
|
|
8017
|
+
availableAncestries,
|
|
8018
|
+
availableImages
|
|
8019
|
+
}
|
|
8020
|
+
));
|
|
8021
|
+
}
|
|
8022
|
+
|
|
8023
|
+
// src/components/NodeDetailsPanel.jsx
|
|
8024
|
+
var import_react17 = __toESM(require("react"));
|
|
8025
|
+
var import_fi15 = require("react-icons/fi");
|
|
7854
8026
|
function NodeDetailsPanel({
|
|
7855
8027
|
node,
|
|
7856
8028
|
onClose,
|
|
@@ -7871,38 +8043,38 @@ function NodeDetailsPanel({
|
|
|
7871
8043
|
userRole,
|
|
7872
8044
|
currentDatasetName
|
|
7873
8045
|
}) {
|
|
7874
|
-
const [name, setName] = (0,
|
|
7875
|
-
const [types, setTypes] = (0,
|
|
7876
|
-
const [typeInput, setTypeInput] = (0,
|
|
7877
|
-
const [color, setColor] = (0,
|
|
7878
|
-
const [size, setSize] = (0,
|
|
7879
|
-
const [description, setDescription] = (0,
|
|
7880
|
-
const [intensity, setIntensity] = (0,
|
|
7881
|
-
const [customProps, setCustomProps] = (0,
|
|
7882
|
-
const [showTypeSuggestions, setShowTypeSuggestions] = (0,
|
|
7883
|
-
const [filteredTypes, setFilteredTypes] = (0,
|
|
7884
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0,
|
|
7885
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
7886
|
-
const [existingSections, setExistingSections] = (0,
|
|
7887
|
-
const [isSaving, setIsSaving] = (0,
|
|
7888
|
-
const [isLinkCopied, setIsLinkCopied] = (0,
|
|
7889
|
-
const [useImageAsTexture, setUseImageAsTexture] = (0,
|
|
8046
|
+
const [name, setName] = (0, import_react17.useState)((node == null ? void 0 : node.name) ?? "");
|
|
8047
|
+
const [types, setTypes] = (0, import_react17.useState)([]);
|
|
8048
|
+
const [typeInput, setTypeInput] = (0, import_react17.useState)("");
|
|
8049
|
+
const [color, setColor] = (0, import_react17.useState)((node == null ? void 0 : node.color) ?? "#8b5cf6");
|
|
8050
|
+
const [size, setSize] = (0, import_react17.useState)((node == null ? void 0 : node.size) ?? "medium");
|
|
8051
|
+
const [description, setDescription] = (0, import_react17.useState)((node == null ? void 0 : node.description) ?? "");
|
|
8052
|
+
const [intensity, setIntensity] = (0, import_react17.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8053
|
+
const [customProps, setCustomProps] = (0, import_react17.useState)(() => extractCustomPropsFromNode(node || {}));
|
|
8054
|
+
const [showTypeSuggestions, setShowTypeSuggestions] = (0, import_react17.useState)(false);
|
|
8055
|
+
const [filteredTypes, setFilteredTypes] = (0, import_react17.useState)([]);
|
|
8056
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
|
|
8057
|
+
const [isReadMode, setIsReadMode] = (0, import_react17.useState)(false);
|
|
8058
|
+
const [existingSections, setExistingSections] = (0, import_react17.useState)((node == null ? void 0 : node.description_sections) || []);
|
|
8059
|
+
const [isSaving, setIsSaving] = (0, import_react17.useState)(false);
|
|
8060
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react17.useState)(false);
|
|
8061
|
+
const [useImageAsTexture, setUseImageAsTexture] = (0, import_react17.useState)(() => {
|
|
7890
8062
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7891
8063
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
7892
8064
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
7893
8065
|
});
|
|
7894
|
-
const [selectedImageUrl, setSelectedImageUrl] = (0,
|
|
8066
|
+
const [selectedImageUrl, setSelectedImageUrl] = (0, import_react17.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
7895
8067
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
7896
8068
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
7897
8069
|
initialWidth: isReadMode ? 700 : 440,
|
|
7898
8070
|
minWidth: 320,
|
|
7899
8071
|
maxWidth: maxPanelW
|
|
7900
8072
|
});
|
|
7901
|
-
(0,
|
|
8073
|
+
(0, import_react17.useEffect)(() => {
|
|
7902
8074
|
setWidth(isReadMode ? 700 : 440);
|
|
7903
8075
|
}, [isReadMode, setWidth]);
|
|
7904
|
-
const prevNodeIdRef = (0,
|
|
7905
|
-
const propsEndRef = (0,
|
|
8076
|
+
const prevNodeIdRef = (0, import_react17.useRef)(null);
|
|
8077
|
+
const propsEndRef = (0, import_react17.useRef)(null);
|
|
7906
8078
|
const canEdit = userRole !== "viewer";
|
|
7907
8079
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
7908
8080
|
const handleImageClickFromText = (url, name2) => {
|
|
@@ -7910,7 +8082,7 @@ function NodeDetailsPanel({
|
|
|
7910
8082
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
7911
8083
|
}
|
|
7912
8084
|
};
|
|
7913
|
-
(0,
|
|
8085
|
+
(0, import_react17.useEffect)(() => {
|
|
7914
8086
|
if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
|
|
7915
8087
|
prevNodeIdRef.current = node == null ? void 0 : node.id;
|
|
7916
8088
|
setName((node == null ? void 0 : node.name) ?? "");
|
|
@@ -7932,13 +8104,13 @@ function NodeDetailsPanel({
|
|
|
7932
8104
|
}
|
|
7933
8105
|
}, [node]);
|
|
7934
8106
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
7935
|
-
(0,
|
|
8107
|
+
(0, import_react17.useEffect)(() => {
|
|
7936
8108
|
if (!hasImages && useImageAsTexture) {
|
|
7937
8109
|
setUseImageAsTexture(false);
|
|
7938
8110
|
setSelectedImageUrl(null);
|
|
7939
8111
|
}
|
|
7940
8112
|
}, [hasImages, useImageAsTexture]);
|
|
7941
|
-
(0,
|
|
8113
|
+
(0, import_react17.useEffect)(() => {
|
|
7942
8114
|
if (typeInput.trim() === "") {
|
|
7943
8115
|
setFilteredTypes(existingTypes.filter((t) => !types.includes(t)));
|
|
7944
8116
|
} else {
|
|
@@ -8110,7 +8282,7 @@ function NodeDetailsPanel({
|
|
|
8110
8282
|
onClose();
|
|
8111
8283
|
};
|
|
8112
8284
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
8113
|
-
return /* @__PURE__ */
|
|
8285
|
+
return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(
|
|
8114
8286
|
"div",
|
|
8115
8287
|
{
|
|
8116
8288
|
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 ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
@@ -8123,7 +8295,7 @@ function NodeDetailsPanel({
|
|
|
8123
8295
|
onContextMenu: swallow,
|
|
8124
8296
|
onDoubleClick: swallow
|
|
8125
8297
|
},
|
|
8126
|
-
/* @__PURE__ */
|
|
8298
|
+
/* @__PURE__ */ import_react17.default.createElement(
|
|
8127
8299
|
"div",
|
|
8128
8300
|
{
|
|
8129
8301
|
onPointerDown: (e) => {
|
|
@@ -8134,7 +8306,7 @@ function NodeDetailsPanel({
|
|
|
8134
8306
|
title: "Arraste para redimensionar"
|
|
8135
8307
|
}
|
|
8136
8308
|
),
|
|
8137
|
-
isReadMode ? /* @__PURE__ */
|
|
8309
|
+
isReadMode ? /* @__PURE__ */ import_react17.default.createElement(
|
|
8138
8310
|
DescriptionReadModePanel,
|
|
8139
8311
|
{
|
|
8140
8312
|
title: name || (node == null ? void 0 : node.name),
|
|
@@ -8155,23 +8327,23 @@ function NodeDetailsPanel({
|
|
|
8155
8327
|
onImageClick: handleImageClickFromText,
|
|
8156
8328
|
onSaveDescription: handleSaveDescriptionInline
|
|
8157
8329
|
}
|
|
8158
|
-
) : /* @__PURE__ */
|
|
8330
|
+
) : /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react17.default.createElement("div", null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react17.default.createElement(
|
|
8159
8331
|
"button",
|
|
8160
8332
|
{
|
|
8161
8333
|
onClick: handleCopyLink,
|
|
8162
8334
|
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
8163
8335
|
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
8164
8336
|
},
|
|
8165
|
-
isLinkCopied ? /* @__PURE__ */
|
|
8166
|
-
)), /* @__PURE__ */
|
|
8337
|
+
isLinkCopied ? /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLink, { size: 12 })
|
|
8338
|
+
)), /* @__PURE__ */ import_react17.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react17.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ import_react17.default.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ import_react17.default.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8167
8339
|
"button",
|
|
8168
8340
|
{
|
|
8169
8341
|
type: "button",
|
|
8170
8342
|
onClick: () => handleRemoveType(index),
|
|
8171
8343
|
className: "hover:text-white transition-colors"
|
|
8172
8344
|
},
|
|
8173
|
-
/* @__PURE__ */
|
|
8174
|
-
))), canEdit && /* @__PURE__ */
|
|
8345
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiX, { size: 12 })
|
|
8346
|
+
))), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8175
8347
|
"input",
|
|
8176
8348
|
{
|
|
8177
8349
|
type: "text",
|
|
@@ -8192,7 +8364,7 @@ function NodeDetailsPanel({
|
|
|
8192
8364
|
placeholder: types.length === 0 ? "Ex.: Cliente" : "",
|
|
8193
8365
|
autoComplete: "off"
|
|
8194
8366
|
}
|
|
8195
|
-
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */
|
|
8367
|
+
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ import_react17.default.createElement("ul", { className: "custom-scrollbar absolute top-full left-0 z-10 w-full mt-1 max-h-40 overflow-y-auto rounded-lg bg-slate-800 border border-white/10 shadow-lg" }, filteredTypes.map((suggestedType, index) => /* @__PURE__ */ import_react17.default.createElement(
|
|
8196
8368
|
"li",
|
|
8197
8369
|
{
|
|
8198
8370
|
key: index,
|
|
@@ -8203,7 +8375,7 @@ function NodeDetailsPanel({
|
|
|
8203
8375
|
}
|
|
8204
8376
|
},
|
|
8205
8377
|
suggestedType
|
|
8206
|
-
))))), /* @__PURE__ */
|
|
8378
|
+
))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ import_react17.default.createElement(
|
|
8207
8379
|
"input",
|
|
8208
8380
|
{
|
|
8209
8381
|
type: "text",
|
|
@@ -8212,7 +8384,7 @@ function NodeDetailsPanel({
|
|
|
8212
8384
|
readOnly: !canEdit,
|
|
8213
8385
|
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
|
|
8214
8386
|
}
|
|
8215
|
-
)), /* @__PURE__ */
|
|
8387
|
+
)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
8216
8388
|
DescriptionDisplay,
|
|
8217
8389
|
{
|
|
8218
8390
|
description,
|
|
@@ -8224,7 +8396,7 @@ function NodeDetailsPanel({
|
|
|
8224
8396
|
onImageClick: handleImageClickFromText,
|
|
8225
8397
|
onSaveDescription: handleSaveDescriptionInline
|
|
8226
8398
|
}
|
|
8227
|
-
), /* @__PURE__ */
|
|
8399
|
+
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
8228
8400
|
"button",
|
|
8229
8401
|
{
|
|
8230
8402
|
type: "button",
|
|
@@ -8232,8 +8404,8 @@ function NodeDetailsPanel({
|
|
|
8232
8404
|
className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
|
|
8233
8405
|
title: "Modo de Leitura"
|
|
8234
8406
|
},
|
|
8235
|
-
/* @__PURE__ */
|
|
8236
|
-
), canEdit && /* @__PURE__ */
|
|
8407
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiBookOpen, { size: 14 })
|
|
8408
|
+
), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8237
8409
|
"button",
|
|
8238
8410
|
{
|
|
8239
8411
|
type: "button",
|
|
@@ -8241,17 +8413,17 @@ function NodeDetailsPanel({
|
|
|
8241
8413
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8242
8414
|
title: "Editar descri\xE7\xE3o (Modo de Escrita)"
|
|
8243
8415
|
},
|
|
8244
|
-
/* @__PURE__ */
|
|
8245
|
-
)), canEdit && !description && /* @__PURE__ */
|
|
8416
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiEdit2, { size: 14 })
|
|
8417
|
+
)), canEdit && !description && /* @__PURE__ */ import_react17.default.createElement(
|
|
8246
8418
|
"div",
|
|
8247
8419
|
{
|
|
8248
8420
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8249
8421
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8250
8422
|
},
|
|
8251
8423
|
"Adicionar descri\xE7\xE3o..."
|
|
8252
|
-
))), /* @__PURE__ */
|
|
8424
|
+
))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
|
|
8253
8425
|
const isSelected = size === s;
|
|
8254
|
-
return /* @__PURE__ */
|
|
8426
|
+
return /* @__PURE__ */ import_react17.default.createElement(
|
|
8255
8427
|
"button",
|
|
8256
8428
|
{
|
|
8257
8429
|
key: s,
|
|
@@ -8259,10 +8431,10 @@ function NodeDetailsPanel({
|
|
|
8259
8431
|
onClick: () => canEdit && handleSizeChange(s),
|
|
8260
8432
|
className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
|
|
8261
8433
|
},
|
|
8262
|
-
/* @__PURE__ */
|
|
8263
|
-
/* @__PURE__ */
|
|
8434
|
+
/* @__PURE__ */ import_react17.default.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })),
|
|
8435
|
+
/* @__PURE__ */ import_react17.default.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
|
|
8264
8436
|
);
|
|
8265
|
-
}))), /* @__PURE__ */
|
|
8437
|
+
}))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ import_react17.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react17.default.createElement(
|
|
8266
8438
|
"input",
|
|
8267
8439
|
{
|
|
8268
8440
|
type: "checkbox",
|
|
@@ -8270,14 +8442,14 @@ function NodeDetailsPanel({
|
|
|
8270
8442
|
onChange: handleToggleImageMode,
|
|
8271
8443
|
className: "hidden"
|
|
8272
8444
|
}
|
|
8273
|
-
), /* @__PURE__ */
|
|
8445
|
+
), /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ import_react17.default.createElement(
|
|
8274
8446
|
ColorPicker,
|
|
8275
8447
|
{
|
|
8276
8448
|
color,
|
|
8277
8449
|
onChange: handleColorChange,
|
|
8278
8450
|
disabled: !canEdit || useImageAsTexture
|
|
8279
8451
|
}
|
|
8280
|
-
), /* @__PURE__ */
|
|
8452
|
+
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiSun, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement(
|
|
8281
8453
|
"input",
|
|
8282
8454
|
{
|
|
8283
8455
|
type: "range",
|
|
@@ -8290,7 +8462,7 @@ function NodeDetailsPanel({
|
|
|
8290
8462
|
className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
|
|
8291
8463
|
title: `Intensidade do brilho: ${intensity}`
|
|
8292
8464
|
}
|
|
8293
|
-
), /* @__PURE__ */
|
|
8465
|
+
), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react17.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react17.default.createElement(
|
|
8294
8466
|
CustomPropertyDisplay,
|
|
8295
8467
|
{
|
|
8296
8468
|
key: prop.id,
|
|
@@ -8305,7 +8477,7 @@ function NodeDetailsPanel({
|
|
|
8305
8477
|
onUploadFile: canEdit ? onUploadFile : void 0,
|
|
8306
8478
|
readOnly: !canEdit
|
|
8307
8479
|
}
|
|
8308
|
-
)), /* @__PURE__ */
|
|
8480
|
+
)), /* @__PURE__ */ import_react17.default.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-3 mt-4 border-t border-white/10 flex items-center justify-end gap-2 text-xs text-slate-400" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react17.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8309
8481
|
"button",
|
|
8310
8482
|
{
|
|
8311
8483
|
onClick: () => handleSave(false),
|
|
@@ -8314,10 +8486,10 @@ function NodeDetailsPanel({
|
|
|
8314
8486
|
${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 text-white"}
|
|
8315
8487
|
`
|
|
8316
8488
|
},
|
|
8317
|
-
isSaving && /* @__PURE__ */
|
|
8489
|
+
isSaving && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
|
|
8318
8490
|
isSaving ? "Salvando..." : "Salvar"
|
|
8319
8491
|
)))
|
|
8320
|
-
), isDescriptionModalOpen && canEdit && /* @__PURE__ */
|
|
8492
|
+
), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8321
8493
|
DescriptionEditModal,
|
|
8322
8494
|
{
|
|
8323
8495
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8337,7 +8509,7 @@ function NodeDetailsPanel({
|
|
|
8337
8509
|
}
|
|
8338
8510
|
|
|
8339
8511
|
// src/components/MultiNodeContextMenu.jsx
|
|
8340
|
-
var
|
|
8512
|
+
var import_react18 = __toESM(require("react"));
|
|
8341
8513
|
function MultiNodeContextMenu({
|
|
8342
8514
|
data,
|
|
8343
8515
|
userRole,
|
|
@@ -8346,12 +8518,12 @@ function MultiNodeContextMenu({
|
|
|
8346
8518
|
onDismissOtherNodes,
|
|
8347
8519
|
onDeleteNodes
|
|
8348
8520
|
}) {
|
|
8349
|
-
const menuRef = (0,
|
|
8350
|
-
const [menuPos, setMenuPos] = (0,
|
|
8351
|
-
const [isConfirmingDelete, setIsConfirmingDelete] = (0,
|
|
8521
|
+
const menuRef = (0, import_react18.useRef)(null);
|
|
8522
|
+
const [menuPos, setMenuPos] = (0, import_react18.useState)({ left: 0, top: 0 });
|
|
8523
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react18.useState)(false);
|
|
8352
8524
|
const ability = defineAbilityFor(userRole);
|
|
8353
8525
|
const canDelete = ability.can("delete", "Node");
|
|
8354
|
-
(0,
|
|
8526
|
+
(0, import_react18.useLayoutEffect)(() => {
|
|
8355
8527
|
if (!data.visible || !menuRef.current) return;
|
|
8356
8528
|
const el = menuRef.current;
|
|
8357
8529
|
const w = el.clientWidth;
|
|
@@ -8364,7 +8536,7 @@ function MultiNodeContextMenu({
|
|
|
8364
8536
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
8365
8537
|
setMenuPos({ left, top });
|
|
8366
8538
|
}, [data]);
|
|
8367
|
-
(0,
|
|
8539
|
+
(0, import_react18.useEffect)(() => {
|
|
8368
8540
|
if (data.visible) {
|
|
8369
8541
|
setIsConfirmingDelete(false);
|
|
8370
8542
|
}
|
|
@@ -8379,7 +8551,7 @@ function MultiNodeContextMenu({
|
|
|
8379
8551
|
const baseButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-indigo-500/20 text-slate-200 hover:text-white transition-colors duration-150 truncate";
|
|
8380
8552
|
const deleteButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-red-500/25 text-red-400 hover:text-red-300 transition-colors duration-150 truncate";
|
|
8381
8553
|
const nodeCount = data.nodeIds.size;
|
|
8382
|
-
return /* @__PURE__ */
|
|
8554
|
+
return /* @__PURE__ */ import_react18.default.createElement(
|
|
8383
8555
|
"div",
|
|
8384
8556
|
{
|
|
8385
8557
|
ref: menuRef,
|
|
@@ -8393,28 +8565,28 @@ function MultiNodeContextMenu({
|
|
|
8393
8565
|
onContextMenu: swallow,
|
|
8394
8566
|
onDoubleClick: swallow
|
|
8395
8567
|
},
|
|
8396
|
-
/* @__PURE__ */
|
|
8397
|
-
/* @__PURE__ */
|
|
8568
|
+
/* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
|
|
8569
|
+
/* @__PURE__ */ import_react18.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ import_react18.default.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight" }, "Esta a\xE7\xE3o \xE9 irrevers\xEDvel. Todas as conex\xF5es associadas a eles ser\xE3o apagadas.")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react18.default.createElement(
|
|
8398
8570
|
"button",
|
|
8399
8571
|
{
|
|
8400
8572
|
onClick: () => setIsConfirmingDelete(false),
|
|
8401
8573
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8402
8574
|
},
|
|
8403
8575
|
"Cancelar"
|
|
8404
|
-
), /* @__PURE__ */
|
|
8576
|
+
), /* @__PURE__ */ import_react18.default.createElement(
|
|
8405
8577
|
"button",
|
|
8406
8578
|
{
|
|
8407
8579
|
onClick: () => onDeleteNodes(data.nodeIds),
|
|
8408
8580
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
|
|
8409
8581
|
},
|
|
8410
8582
|
"Excluir"
|
|
8411
|
-
))) : /* @__PURE__ */
|
|
8583
|
+
))) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.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_react18.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.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_react18.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ import_react18.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_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
|
|
8412
8584
|
);
|
|
8413
8585
|
}
|
|
8414
8586
|
|
|
8415
8587
|
// src/components/RelationshipDetailsPanel.jsx
|
|
8416
|
-
var
|
|
8417
|
-
var
|
|
8588
|
+
var import_react19 = __toESM(require("react"));
|
|
8589
|
+
var import_fi16 = require("react-icons/fi");
|
|
8418
8590
|
function RelationshipDetailsPanel({
|
|
8419
8591
|
link,
|
|
8420
8592
|
onClose,
|
|
@@ -8428,19 +8600,19 @@ function RelationshipDetailsPanel({
|
|
|
8428
8600
|
onUploadFile,
|
|
8429
8601
|
userRole
|
|
8430
8602
|
}) {
|
|
8431
|
-
const [name, setName] = (0,
|
|
8432
|
-
const [description, setDescription] = (0,
|
|
8433
|
-
const [customProps, setCustomProps] = (0,
|
|
8434
|
-
const [existingSections, setExistingSections] = (0,
|
|
8435
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0,
|
|
8436
|
-
const [isSaving, setIsSaving] = (0,
|
|
8437
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
8438
|
-
const propsEndRef = (0,
|
|
8439
|
-
const canEdit = (0,
|
|
8603
|
+
const [name, setName] = (0, import_react19.useState)((link == null ? void 0 : link.name) ?? "");
|
|
8604
|
+
const [description, setDescription] = (0, import_react19.useState)((link == null ? void 0 : link.description) ?? "");
|
|
8605
|
+
const [customProps, setCustomProps] = (0, import_react19.useState)(() => extractCustomPropsFromNode(link || {}));
|
|
8606
|
+
const [existingSections, setExistingSections] = (0, import_react19.useState)((link == null ? void 0 : link.description_sections) || []);
|
|
8607
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react19.useState)(false);
|
|
8608
|
+
const [isSaving, setIsSaving] = (0, import_react19.useState)(false);
|
|
8609
|
+
const [isReadMode, setIsReadMode] = (0, import_react19.useState)(false);
|
|
8610
|
+
const propsEndRef = (0, import_react19.useRef)(null);
|
|
8611
|
+
const canEdit = (0, import_react19.useMemo)(() => {
|
|
8440
8612
|
const ability = defineAbilityFor(userRole);
|
|
8441
8613
|
return ability.can("update", "Connection");
|
|
8442
8614
|
}, [userRole]);
|
|
8443
|
-
(0,
|
|
8615
|
+
(0, import_react19.useEffect)(() => {
|
|
8444
8616
|
setName((link == null ? void 0 : link.name) ?? "");
|
|
8445
8617
|
setDescription((link == null ? void 0 : link.description) ?? "");
|
|
8446
8618
|
setExistingSections((link == null ? void 0 : link.description_sections) || []);
|
|
@@ -8515,7 +8687,7 @@ function RelationshipDetailsPanel({
|
|
|
8515
8687
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
8516
8688
|
}
|
|
8517
8689
|
};
|
|
8518
|
-
return /* @__PURE__ */
|
|
8690
|
+
return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
|
|
8519
8691
|
"div",
|
|
8520
8692
|
{
|
|
8521
8693
|
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 transition-all duration-300 ease-out
|
|
@@ -8530,7 +8702,7 @@ function RelationshipDetailsPanel({
|
|
|
8530
8702
|
onContextMenu: swallow,
|
|
8531
8703
|
onDoubleClick: swallow
|
|
8532
8704
|
},
|
|
8533
|
-
isReadMode ? /* @__PURE__ */
|
|
8705
|
+
isReadMode ? /* @__PURE__ */ import_react19.default.createElement(
|
|
8534
8706
|
DescriptionReadModePanel,
|
|
8535
8707
|
{
|
|
8536
8708
|
title: name || "Rela\xE7\xE3o",
|
|
@@ -8551,7 +8723,7 @@ function RelationshipDetailsPanel({
|
|
|
8551
8723
|
onImageClick: handleImageClickFromText,
|
|
8552
8724
|
onSaveDescription: handleSaveDescriptionInline
|
|
8553
8725
|
}
|
|
8554
|
-
) : /* @__PURE__ */
|
|
8726
|
+
) : /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("div", null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-teal-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("button", { onClick: onClose, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react19.default.createElement(
|
|
8555
8727
|
"input",
|
|
8556
8728
|
{
|
|
8557
8729
|
type: "text",
|
|
@@ -8563,7 +8735,7 @@ function RelationshipDetailsPanel({
|
|
|
8563
8735
|
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
8564
8736
|
`
|
|
8565
8737
|
}
|
|
8566
|
-
)), /* @__PURE__ */
|
|
8738
|
+
)), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react19.default.createElement(
|
|
8567
8739
|
DescriptionDisplay,
|
|
8568
8740
|
{
|
|
8569
8741
|
description,
|
|
@@ -8575,7 +8747,7 @@ function RelationshipDetailsPanel({
|
|
|
8575
8747
|
onImageClick: handleImageClickFromText,
|
|
8576
8748
|
onSaveDescription: handleSaveDescriptionInline
|
|
8577
8749
|
}
|
|
8578
|
-
), /* @__PURE__ */
|
|
8750
|
+
), /* @__PURE__ */ import_react19.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react19.default.createElement(
|
|
8579
8751
|
"button",
|
|
8580
8752
|
{
|
|
8581
8753
|
type: "button",
|
|
@@ -8583,8 +8755,8 @@ function RelationshipDetailsPanel({
|
|
|
8583
8755
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
|
|
8584
8756
|
title: "Modo de Leitura"
|
|
8585
8757
|
},
|
|
8586
|
-
/* @__PURE__ */
|
|
8587
|
-
), canEdit && /* @__PURE__ */
|
|
8758
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi16.FiBookOpen, { size: 14 })
|
|
8759
|
+
), canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8588
8760
|
"button",
|
|
8589
8761
|
{
|
|
8590
8762
|
type: "button",
|
|
@@ -8592,15 +8764,15 @@ function RelationshipDetailsPanel({
|
|
|
8592
8764
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8593
8765
|
title: "Editar descri\xE7\xE3o"
|
|
8594
8766
|
},
|
|
8595
|
-
/* @__PURE__ */
|
|
8596
|
-
)), !description && canEdit && /* @__PURE__ */
|
|
8767
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi16.FiEdit2, { size: 14 })
|
|
8768
|
+
)), !description && canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8597
8769
|
"div",
|
|
8598
8770
|
{
|
|
8599
8771
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8600
8772
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8601
8773
|
},
|
|
8602
8774
|
"Adicionar descri\xE7\xE3o..."
|
|
8603
|
-
))), /* @__PURE__ */
|
|
8775
|
+
))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react19.default.createElement(
|
|
8604
8776
|
CustomPropertyDisplay,
|
|
8605
8777
|
{
|
|
8606
8778
|
key: prop.id,
|
|
@@ -8612,7 +8784,7 @@ function RelationshipDetailsPanel({
|
|
|
8612
8784
|
onUploadFile,
|
|
8613
8785
|
disabled: !canEdit
|
|
8614
8786
|
}
|
|
8615
|
-
)), /* @__PURE__ */
|
|
8787
|
+
)), /* @__PURE__ */ import_react19.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react19.default.createElement("button", { onClick: onClose, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8616
8788
|
"button",
|
|
8617
8789
|
{
|
|
8618
8790
|
onClick: () => handleSave(false),
|
|
@@ -8621,10 +8793,10 @@ function RelationshipDetailsPanel({
|
|
|
8621
8793
|
${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-teal-600 to-teal-400 hover:from-teal-500 hover:to-teal-300 text-white"}
|
|
8622
8794
|
`
|
|
8623
8795
|
},
|
|
8624
|
-
isSaving && /* @__PURE__ */
|
|
8796
|
+
isSaving && /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiLoader, { className: "animate-spin" }),
|
|
8625
8797
|
isSaving ? "Salvando..." : "Salvar"
|
|
8626
8798
|
)))
|
|
8627
|
-
), isDescriptionModalOpen && /* @__PURE__ */
|
|
8799
|
+
), isDescriptionModalOpen && /* @__PURE__ */ import_react19.default.createElement(
|
|
8628
8800
|
DescriptionEditModal,
|
|
8629
8801
|
{
|
|
8630
8802
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8645,7 +8817,7 @@ function RelationshipDetailsPanel({
|
|
|
8645
8817
|
}
|
|
8646
8818
|
|
|
8647
8819
|
// src/components/RelationshipContextMenu.jsx
|
|
8648
|
-
var
|
|
8820
|
+
var import_react20 = __toESM(require("react"));
|
|
8649
8821
|
function RelationshipContextMenu({
|
|
8650
8822
|
data,
|
|
8651
8823
|
userRole,
|
|
@@ -8655,25 +8827,25 @@ function RelationshipContextMenu({
|
|
|
8655
8827
|
onDelete,
|
|
8656
8828
|
onClose
|
|
8657
8829
|
}) {
|
|
8658
|
-
const menuRef = (0,
|
|
8659
|
-
const [menuPos, setMenuPos] = (0,
|
|
8660
|
-
const [isConfirmingDelete, setIsConfirmingDelete] = (0,
|
|
8661
|
-
const ability = (0,
|
|
8662
|
-
const sourceName = (0,
|
|
8830
|
+
const menuRef = (0, import_react20.useRef)(null);
|
|
8831
|
+
const [menuPos, setMenuPos] = (0, import_react20.useState)({ left: 0, top: 0 });
|
|
8832
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react20.useState)(false);
|
|
8833
|
+
const ability = (0, import_react20.useMemo)(() => defineAbilityFor(userRole), [userRole]);
|
|
8834
|
+
const sourceName = (0, import_react20.useMemo)(
|
|
8663
8835
|
() => {
|
|
8664
8836
|
var _a, _b, _c, _d;
|
|
8665
8837
|
return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.sourceNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
|
|
8666
8838
|
},
|
|
8667
8839
|
[data == null ? void 0 : data.linkObject]
|
|
8668
8840
|
);
|
|
8669
|
-
const targetName = (0,
|
|
8841
|
+
const targetName = (0, import_react20.useMemo)(
|
|
8670
8842
|
() => {
|
|
8671
8843
|
var _a, _b, _c, _d;
|
|
8672
8844
|
return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
|
|
8673
8845
|
},
|
|
8674
8846
|
[data == null ? void 0 : data.linkObject]
|
|
8675
8847
|
);
|
|
8676
|
-
(0,
|
|
8848
|
+
(0, import_react20.useLayoutEffect)(() => {
|
|
8677
8849
|
if (!data.visible || !menuRef.current) return;
|
|
8678
8850
|
const el = menuRef.current;
|
|
8679
8851
|
const w = el.clientWidth;
|
|
@@ -8686,7 +8858,7 @@ function RelationshipContextMenu({
|
|
|
8686
8858
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
8687
8859
|
setMenuPos({ left, top });
|
|
8688
8860
|
}, [data]);
|
|
8689
|
-
(0,
|
|
8861
|
+
(0, import_react20.useEffect)(() => {
|
|
8690
8862
|
if (data.visible) {
|
|
8691
8863
|
setIsConfirmingDelete(false);
|
|
8692
8864
|
}
|
|
@@ -8702,7 +8874,7 @@ function RelationshipContextMenu({
|
|
|
8702
8874
|
const dangerButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-rose-500/20 text-rose-300 hover:text-rose-100 transition-colors duration-150 truncate";
|
|
8703
8875
|
const canUpdate = ability.can("update", "Connection");
|
|
8704
8876
|
const canDelete = ability.can("delete", "Connection");
|
|
8705
|
-
return /* @__PURE__ */
|
|
8877
|
+
return /* @__PURE__ */ import_react20.default.createElement(
|
|
8706
8878
|
"div",
|
|
8707
8879
|
{
|
|
8708
8880
|
ref: menuRef,
|
|
@@ -8716,29 +8888,29 @@ function RelationshipContextMenu({
|
|
|
8716
8888
|
onContextMenu: swallow,
|
|
8717
8889
|
onDoubleClick: swallow
|
|
8718
8890
|
},
|
|
8719
|
-
/* @__PURE__ */
|
|
8720
|
-
/* @__PURE__ */
|
|
8891
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
|
|
8892
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ import_react20.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ import_react20.default.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ import_react20.default.createElement("strong", null, targetName), ".")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
8721
8893
|
"button",
|
|
8722
8894
|
{
|
|
8723
8895
|
onClick: () => setIsConfirmingDelete(false),
|
|
8724
8896
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8725
8897
|
},
|
|
8726
8898
|
"Cancelar"
|
|
8727
|
-
), /* @__PURE__ */
|
|
8899
|
+
), /* @__PURE__ */ import_react20.default.createElement(
|
|
8728
8900
|
"button",
|
|
8729
8901
|
{
|
|
8730
8902
|
onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
|
|
8731
8903
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
|
|
8732
8904
|
},
|
|
8733
8905
|
"Excluir"
|
|
8734
|
-
))) : /* @__PURE__ */
|
|
8906
|
+
))) : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-teal-400/80 shadow-[0_0_12px_1px_rgba(45,212,191,0.5)]" }), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement(
|
|
8735
8907
|
"button",
|
|
8736
8908
|
{
|
|
8737
8909
|
onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
|
|
8738
8910
|
className: baseButtonClass,
|
|
8739
8911
|
title: "Desconectar ponta ligada ao Source"
|
|
8740
8912
|
},
|
|
8741
|
-
/* @__PURE__ */
|
|
8913
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8742
8914
|
"svg",
|
|
8743
8915
|
{
|
|
8744
8916
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8751,18 +8923,18 @@ function RelationshipContextMenu({
|
|
|
8751
8923
|
strokeLinecap: "round",
|
|
8752
8924
|
strokeLinejoin: "round"
|
|
8753
8925
|
},
|
|
8754
|
-
/* @__PURE__ */
|
|
8755
|
-
/* @__PURE__ */
|
|
8926
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }),
|
|
8927
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })
|
|
8756
8928
|
),
|
|
8757
|
-
/* @__PURE__ */
|
|
8758
|
-
), /* @__PURE__ */
|
|
8929
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
|
|
8930
|
+
), /* @__PURE__ */ import_react20.default.createElement(
|
|
8759
8931
|
"button",
|
|
8760
8932
|
{
|
|
8761
8933
|
onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
|
|
8762
8934
|
className: baseButtonClass,
|
|
8763
8935
|
title: "Desconectar ponta ligada ao Target"
|
|
8764
8936
|
},
|
|
8765
|
-
/* @__PURE__ */
|
|
8937
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8766
8938
|
"svg",
|
|
8767
8939
|
{
|
|
8768
8940
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8775,21 +8947,21 @@ function RelationshipContextMenu({
|
|
|
8775
8947
|
strokeLinecap: "round",
|
|
8776
8948
|
strokeLinejoin: "round"
|
|
8777
8949
|
},
|
|
8778
|
-
/* @__PURE__ */
|
|
8779
|
-
/* @__PURE__ */
|
|
8780
|
-
/* @__PURE__ */
|
|
8781
|
-
/* @__PURE__ */
|
|
8782
|
-
/* @__PURE__ */
|
|
8950
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "16 3 21 3 21 8" }),
|
|
8951
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
|
|
8952
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "21 16 21 21 16 21" }),
|
|
8953
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
|
|
8954
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
|
|
8783
8955
|
),
|
|
8784
|
-
/* @__PURE__ */
|
|
8785
|
-
), /* @__PURE__ */
|
|
8956
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Target (", targetName, ")")
|
|
8957
|
+
), /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ import_react20.default.createElement(
|
|
8786
8958
|
"button",
|
|
8787
8959
|
{
|
|
8788
8960
|
onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
|
|
8789
8961
|
className: baseButtonClass,
|
|
8790
8962
|
title: "Abrir detalhes da rela\xE7\xE3o"
|
|
8791
8963
|
},
|
|
8792
|
-
/* @__PURE__ */
|
|
8964
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8793
8965
|
"svg",
|
|
8794
8966
|
{
|
|
8795
8967
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8802,19 +8974,19 @@ function RelationshipContextMenu({
|
|
|
8802
8974
|
strokeLinecap: "round",
|
|
8803
8975
|
strokeLinejoin: "round"
|
|
8804
8976
|
},
|
|
8805
|
-
/* @__PURE__ */
|
|
8806
|
-
/* @__PURE__ */
|
|
8807
|
-
/* @__PURE__ */
|
|
8977
|
+
/* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8978
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
8979
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
|
|
8808
8980
|
),
|
|
8809
|
-
/* @__PURE__ */
|
|
8810
|
-
), canDelete && /* @__PURE__ */
|
|
8981
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Abrir Detalhes")
|
|
8982
|
+
), canDelete && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ import_react20.default.createElement(
|
|
8811
8983
|
"button",
|
|
8812
8984
|
{
|
|
8813
8985
|
onClick: () => setIsConfirmingDelete(true),
|
|
8814
8986
|
className: dangerButtonClass,
|
|
8815
8987
|
title: "Excluir esta conex\xE3o"
|
|
8816
8988
|
},
|
|
8817
|
-
/* @__PURE__ */
|
|
8989
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8818
8990
|
"svg",
|
|
8819
8991
|
{
|
|
8820
8992
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8827,19 +8999,19 @@ function RelationshipContextMenu({
|
|
|
8827
8999
|
strokeLinecap: "round",
|
|
8828
9000
|
strokeLinejoin: "round"
|
|
8829
9001
|
},
|
|
8830
|
-
/* @__PURE__ */
|
|
8831
|
-
/* @__PURE__ */
|
|
8832
|
-
/* @__PURE__ */
|
|
8833
|
-
/* @__PURE__ */
|
|
8834
|
-
/* @__PURE__ */
|
|
9002
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }),
|
|
9003
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
|
|
9004
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }),
|
|
9005
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }),
|
|
9006
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
|
|
8835
9007
|
),
|
|
8836
|
-
/* @__PURE__ */
|
|
9008
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
|
|
8837
9009
|
)))))
|
|
8838
9010
|
);
|
|
8839
9011
|
}
|
|
8840
9012
|
|
|
8841
9013
|
// src/components/LoadingScreen.jsx
|
|
8842
|
-
var
|
|
9014
|
+
var import_react21 = __toESM(require("react"));
|
|
8843
9015
|
var styles = {
|
|
8844
9016
|
loadingOverlay: {
|
|
8845
9017
|
position: "fixed",
|
|
@@ -8871,11 +9043,11 @@ var styles = {
|
|
|
8871
9043
|
`
|
|
8872
9044
|
};
|
|
8873
9045
|
function LoadingScreen() {
|
|
8874
|
-
return /* @__PURE__ */
|
|
9046
|
+
return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("style", null, styles.keyframes), /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.spinner })));
|
|
8875
9047
|
}
|
|
8876
9048
|
|
|
8877
9049
|
// src/components/ImportParentFileModal.jsx
|
|
8878
|
-
var
|
|
9050
|
+
var import_react22 = __toESM(require("react"));
|
|
8879
9051
|
function ImportParentFileModal({
|
|
8880
9052
|
isOpen,
|
|
8881
9053
|
onClose,
|
|
@@ -8886,12 +9058,12 @@ function ImportParentFileModal({
|
|
|
8886
9058
|
onFetchAvailableFiles,
|
|
8887
9059
|
currentViewName
|
|
8888
9060
|
}) {
|
|
8889
|
-
const [activeTab, setActiveTab] = (0,
|
|
8890
|
-
const [availableDbs, setAvailableDbs] = (0,
|
|
8891
|
-
const [availableViews, setAvailableViews] = (0,
|
|
8892
|
-
const [selectedItem, setSelectedItem] = (0,
|
|
8893
|
-
const [isLoading, setIsLoading] = (0,
|
|
8894
|
-
(0,
|
|
9061
|
+
const [activeTab, setActiveTab] = (0, import_react22.useState)("databases");
|
|
9062
|
+
const [availableDbs, setAvailableDbs] = (0, import_react22.useState)([]);
|
|
9063
|
+
const [availableViews, setAvailableViews] = (0, import_react22.useState)([]);
|
|
9064
|
+
const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
|
|
9065
|
+
const [isLoading, setIsLoading] = (0, import_react22.useState)(false);
|
|
9066
|
+
(0, import_react22.useEffect)(() => {
|
|
8895
9067
|
if (isOpen && session && onFetchAvailableFiles) {
|
|
8896
9068
|
const fetchData = async () => {
|
|
8897
9069
|
setIsLoading(true);
|
|
@@ -8927,7 +9099,7 @@ function ImportParentFileModal({
|
|
|
8927
9099
|
fetchData();
|
|
8928
9100
|
}
|
|
8929
9101
|
}, [isOpen, session, parentDbs, onFetchAvailableFiles, currentViewName]);
|
|
8930
|
-
(0,
|
|
9102
|
+
(0, import_react22.useEffect)(() => {
|
|
8931
9103
|
setSelectedItem(null);
|
|
8932
9104
|
}, [activeTab]);
|
|
8933
9105
|
if (!isOpen) {
|
|
@@ -8956,13 +9128,13 @@ function ImportParentFileModal({
|
|
|
8956
9128
|
const swallow = (e) => e.stopPropagation();
|
|
8957
9129
|
const currentList = activeTab === "databases" ? availableDbs : availableViews;
|
|
8958
9130
|
const emptyMessage = activeTab === "databases" ? "Nenhum novo arquivo parent dispon\xEDvel." : "Nenhuma view dispon\xEDvel para importa\xE7\xE3o.";
|
|
8959
|
-
return /* @__PURE__ */
|
|
9131
|
+
return /* @__PURE__ */ import_react22.default.createElement(
|
|
8960
9132
|
"div",
|
|
8961
9133
|
{
|
|
8962
9134
|
className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
|
|
8963
9135
|
onClick: onClose
|
|
8964
9136
|
},
|
|
8965
|
-
/* @__PURE__ */
|
|
9137
|
+
/* @__PURE__ */ import_react22.default.createElement(
|
|
8966
9138
|
"div",
|
|
8967
9139
|
{
|
|
8968
9140
|
className: "ui-overlay relative rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] text-white w-[min(92vw,500px)] flex flex-col max-h-[85vh]",
|
|
@@ -8974,14 +9146,14 @@ function ImportParentFileModal({
|
|
|
8974
9146
|
onContextMenu: swallow,
|
|
8975
9147
|
onDoubleClick: swallow
|
|
8976
9148
|
},
|
|
8977
|
-
/* @__PURE__ */
|
|
9149
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ import_react22.default.createElement(
|
|
8978
9150
|
"button",
|
|
8979
9151
|
{
|
|
8980
9152
|
onClick: onClose,
|
|
8981
9153
|
className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8982
9154
|
title: "Fechar"
|
|
8983
9155
|
},
|
|
8984
|
-
/* @__PURE__ */
|
|
9156
|
+
/* @__PURE__ */ import_react22.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
8985
9157
|
"path",
|
|
8986
9158
|
{
|
|
8987
9159
|
fillRule: "evenodd",
|
|
@@ -8990,14 +9162,14 @@ function ImportParentFileModal({
|
|
|
8990
9162
|
}
|
|
8991
9163
|
))
|
|
8992
9164
|
)),
|
|
8993
|
-
/* @__PURE__ */
|
|
9165
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
8994
9166
|
"button",
|
|
8995
9167
|
{
|
|
8996
9168
|
onClick: () => setActiveTab("databases"),
|
|
8997
9169
|
className: `flex-1 py-3 text-sm font-medium border-b-2 transition-colors ${activeTab === "databases" ? "border-indigo-500 text-white" : "border-transparent text-slate-400 hover:text-slate-200"}`
|
|
8998
9170
|
},
|
|
8999
9171
|
"Arquivos Parent"
|
|
9000
|
-
), /* @__PURE__ */
|
|
9172
|
+
), /* @__PURE__ */ import_react22.default.createElement(
|
|
9001
9173
|
"button",
|
|
9002
9174
|
{
|
|
9003
9175
|
onClick: () => setActiveTab("views"),
|
|
@@ -9005,24 +9177,24 @@ function ImportParentFileModal({
|
|
|
9005
9177
|
},
|
|
9006
9178
|
"Views (Ancestralidades)"
|
|
9007
9179
|
)),
|
|
9008
|
-
/* @__PURE__ */
|
|
9180
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ import_react22.default.createElement(
|
|
9009
9181
|
"div",
|
|
9010
9182
|
{
|
|
9011
9183
|
key: item.id,
|
|
9012
9184
|
onClick: () => setSelectedItem(item),
|
|
9013
9185
|
className: `px-4 py-3 rounded-lg border cursor-pointer transition-all duration-150 flex flex-col gap-1 ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "bg-indigo-600 border-indigo-500 shadow-lg" : "bg-slate-800/60 border-white/10 hover:border-white/20 hover:bg-slate-800"}`
|
|
9014
9186
|
},
|
|
9015
|
-
/* @__PURE__ */
|
|
9016
|
-
item.description && /* @__PURE__ */
|
|
9017
|
-
)) : /* @__PURE__ */
|
|
9018
|
-
/* @__PURE__ */
|
|
9187
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
|
|
9188
|
+
item.description && /* @__PURE__ */ import_react22.default.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
|
|
9189
|
+
)) : /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
|
|
9190
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "px-6 py-4 border-t border-white/10 flex justify-end gap-3 flex-shrink-0 bg-slate-900/50" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
9019
9191
|
"button",
|
|
9020
9192
|
{
|
|
9021
9193
|
onClick: onClose,
|
|
9022
9194
|
className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm text-slate-300"
|
|
9023
9195
|
},
|
|
9024
9196
|
"Cancelar"
|
|
9025
|
-
), /* @__PURE__ */
|
|
9197
|
+
), /* @__PURE__ */ import_react22.default.createElement(
|
|
9026
9198
|
"button",
|
|
9027
9199
|
{
|
|
9028
9200
|
onClick: handleConfirm,
|
|
@@ -9036,8 +9208,8 @@ function ImportParentFileModal({
|
|
|
9036
9208
|
}
|
|
9037
9209
|
|
|
9038
9210
|
// src/components/AncestryLinkDetailsPanel.jsx
|
|
9039
|
-
var
|
|
9040
|
-
var
|
|
9211
|
+
var import_react23 = __toESM(require("react"));
|
|
9212
|
+
var import_fi17 = require("react-icons/fi");
|
|
9041
9213
|
function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
|
|
9042
9214
|
var _a, _b, _c, _d;
|
|
9043
9215
|
const relationshipData = data.relationship || {};
|
|
@@ -9046,21 +9218,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9046
9218
|
const customProps = extractCustomPropsFromNode(relationshipData);
|
|
9047
9219
|
const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
|
|
9048
9220
|
const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
|
|
9049
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
9221
|
+
const [isReadMode, setIsReadMode] = (0, import_react23.useState)(false);
|
|
9050
9222
|
const swallow = (e) => e.stopPropagation();
|
|
9051
9223
|
const handleImageClickFromText = (url, name) => {
|
|
9052
9224
|
if (onOpenImageViewer) {
|
|
9053
9225
|
onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
|
|
9054
9226
|
}
|
|
9055
9227
|
};
|
|
9056
|
-
return /* @__PURE__ */
|
|
9228
|
+
return /* @__PURE__ */ import_react23.default.createElement(
|
|
9057
9229
|
"div",
|
|
9058
9230
|
{
|
|
9059
9231
|
className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
|
|
9060
9232
|
onClick: onClose,
|
|
9061
9233
|
onPointerDown: swallow
|
|
9062
9234
|
},
|
|
9063
|
-
/* @__PURE__ */
|
|
9235
|
+
/* @__PURE__ */ import_react23.default.createElement(
|
|
9064
9236
|
"div",
|
|
9065
9237
|
{
|
|
9066
9238
|
className: `relative group rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col max-h-[calc(100vh-4rem)] transition-all duration-300 ease-out
|
|
@@ -9068,7 +9240,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9068
9240
|
`,
|
|
9069
9241
|
onClick: swallow
|
|
9070
9242
|
},
|
|
9071
|
-
isReadMode ? /* @__PURE__ */
|
|
9243
|
+
isReadMode ? /* @__PURE__ */ import_react23.default.createElement(
|
|
9072
9244
|
DescriptionReadModePanel,
|
|
9073
9245
|
{
|
|
9074
9246
|
title: `${sourceName} \u2794 ${targetName}`,
|
|
@@ -9080,15 +9252,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9080
9252
|
onMentionClick,
|
|
9081
9253
|
onImageClick: handleImageClickFromText
|
|
9082
9254
|
}
|
|
9083
|
-
) : /* @__PURE__ */
|
|
9255
|
+
) : /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react23.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react23.default.createElement("div", null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react23.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ import_react23.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react23.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ import_react23.default.createElement("button", { onClick: onClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react23.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react23.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react23.default.createElement(
|
|
9084
9256
|
"button",
|
|
9085
9257
|
{
|
|
9086
9258
|
onClick: () => setIsReadMode(true),
|
|
9087
9259
|
className: "p-1 text-slate-400 hover:text-white transition-colors",
|
|
9088
9260
|
title: "Modo de Leitura"
|
|
9089
9261
|
},
|
|
9090
|
-
/* @__PURE__ */
|
|
9091
|
-
)), /* @__PURE__ */
|
|
9262
|
+
/* @__PURE__ */ import_react23.default.createElement(import_fi17.FiBookOpen, { size: 14 })
|
|
9263
|
+
)), /* @__PURE__ */ import_react23.default.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ import_react23.default.createElement(
|
|
9092
9264
|
DescriptionDisplay,
|
|
9093
9265
|
{
|
|
9094
9266
|
description,
|
|
@@ -9097,7 +9269,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9097
9269
|
onMentionClick,
|
|
9098
9270
|
onImageClick: handleImageClickFromText
|
|
9099
9271
|
}
|
|
9100
|
-
))), customProps.length > 0 && /* @__PURE__ */
|
|
9272
|
+
))), customProps.length > 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ import_react23.default.createElement(
|
|
9101
9273
|
CustomPropertyDisplay,
|
|
9102
9274
|
{
|
|
9103
9275
|
key: prop.id,
|
|
@@ -9106,14 +9278,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9106
9278
|
onOpenImageViewer,
|
|
9107
9279
|
onUploadFile
|
|
9108
9280
|
}
|
|
9109
|
-
)))), !description && customProps.length === 0 && /* @__PURE__ */
|
|
9281
|
+
)))), !description && customProps.length === 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "py-8 text-center text-slate-500 text-sm italic border border-dashed border-white/10 rounded-lg" }, "Nenhum detalhe adicional dispon\xEDvel para esta conex\xE3o."), /* @__PURE__ */ import_react23.default.createElement("div", { className: "mt-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg text-xs text-blue-200/80 text-center" }, 'Para editar esta conex\xE3o, utilize o menu "Editar Ancestralidade".')))
|
|
9110
9282
|
)
|
|
9111
9283
|
);
|
|
9112
9284
|
}
|
|
9113
9285
|
|
|
9114
9286
|
// src/components/AncestryBoard.jsx
|
|
9115
|
-
var
|
|
9116
|
-
var
|
|
9287
|
+
var import_react24 = __toESM(require("react"));
|
|
9288
|
+
var import_fi18 = require("react-icons/fi");
|
|
9117
9289
|
var GroupItem = ({
|
|
9118
9290
|
group,
|
|
9119
9291
|
index,
|
|
@@ -9133,7 +9305,7 @@ var GroupItem = ({
|
|
|
9133
9305
|
}) => {
|
|
9134
9306
|
const canIndent = index > 0;
|
|
9135
9307
|
const isPickingForThisGroup = pickingGroupId === group.id;
|
|
9136
|
-
const textareaRef = (0,
|
|
9308
|
+
const textareaRef = (0, import_react24.useRef)(null);
|
|
9137
9309
|
const adjustHeight = () => {
|
|
9138
9310
|
const textarea = textareaRef.current;
|
|
9139
9311
|
if (textarea) {
|
|
@@ -9141,13 +9313,13 @@ var GroupItem = ({
|
|
|
9141
9313
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
9142
9314
|
}
|
|
9143
9315
|
};
|
|
9144
|
-
(0,
|
|
9316
|
+
(0, import_react24.useEffect)(() => {
|
|
9145
9317
|
adjustHeight();
|
|
9146
9318
|
}, [group.text]);
|
|
9147
|
-
return /* @__PURE__ */
|
|
9319
|
+
return /* @__PURE__ */ import_react24.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_react24.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9148
9320
|
flex flex-col gap-2 py-2 px-3 transition-all duration-200
|
|
9149
9321
|
${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
|
|
9150
|
-
` }, /* @__PURE__ */
|
|
9322
|
+
` }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9151
9323
|
"textarea",
|
|
9152
9324
|
{
|
|
9153
9325
|
ref: textareaRef,
|
|
@@ -9164,9 +9336,9 @@ var GroupItem = ({
|
|
|
9164
9336
|
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9165
9337
|
}
|
|
9166
9338
|
}
|
|
9167
|
-
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */
|
|
9339
|
+
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9168
9340
|
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9169
|
-
return /* @__PURE__ */
|
|
9341
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9170
9342
|
"div",
|
|
9171
9343
|
{
|
|
9172
9344
|
key: anc.ancestry_id,
|
|
@@ -9178,28 +9350,28 @@ var GroupItem = ({
|
|
|
9178
9350
|
},
|
|
9179
9351
|
isValid ? (
|
|
9180
9352
|
// [MANTIDO] Botão Play visível para todos
|
|
9181
|
-
/* @__PURE__ */
|
|
9353
|
+
/* @__PURE__ */ import_react24.default.createElement(
|
|
9182
9354
|
"button",
|
|
9183
9355
|
{
|
|
9184
9356
|
onClick: () => onPlayAncestry(anc.ancestry_id),
|
|
9185
9357
|
className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
|
|
9186
9358
|
title: "Renderizar no cen\xE1rio"
|
|
9187
9359
|
},
|
|
9188
|
-
/* @__PURE__ */
|
|
9360
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
|
|
9189
9361
|
)
|
|
9190
|
-
) : /* @__PURE__ */
|
|
9191
|
-
/* @__PURE__ */
|
|
9192
|
-
canEdit && /* @__PURE__ */
|
|
9362
|
+
) : /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiAlertTriangle, { size: 10 })),
|
|
9363
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
|
|
9364
|
+
canEdit && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9193
9365
|
"button",
|
|
9194
9366
|
{
|
|
9195
9367
|
onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
|
|
9196
9368
|
className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
|
|
9197
9369
|
title: "Remover men\xE7\xE3o"
|
|
9198
9370
|
},
|
|
9199
|
-
/* @__PURE__ */
|
|
9371
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiX, { size: 12 })
|
|
9200
9372
|
))
|
|
9201
9373
|
);
|
|
9202
|
-
})), canEdit && /* @__PURE__ */
|
|
9374
|
+
})), canEdit && /* @__PURE__ */ import_react24.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_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9203
9375
|
"button",
|
|
9204
9376
|
{
|
|
9205
9377
|
onClick: () => onRequestPickAncestry(group.id),
|
|
@@ -9209,17 +9381,17 @@ var GroupItem = ({
|
|
|
9209
9381
|
`,
|
|
9210
9382
|
title: "Adicionar Ancestralidade a este grupo"
|
|
9211
9383
|
},
|
|
9212
|
-
isPickingForThisGroup ? /* @__PURE__ */
|
|
9384
|
+
isPickingForThisGroup ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { size: 12 }),
|
|
9213
9385
|
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
9214
|
-
), /* @__PURE__ */
|
|
9386
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9215
9387
|
"button",
|
|
9216
9388
|
{
|
|
9217
9389
|
onClick: () => onAddSubgroup(group.id),
|
|
9218
9390
|
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
9219
9391
|
title: "Criar Subgrupo"
|
|
9220
9392
|
},
|
|
9221
|
-
/* @__PURE__ */
|
|
9222
|
-
)), /* @__PURE__ */
|
|
9393
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14 })
|
|
9394
|
+
)), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9223
9395
|
"button",
|
|
9224
9396
|
{
|
|
9225
9397
|
onClick: () => onIndent(group.id),
|
|
@@ -9227,24 +9399,24 @@ var GroupItem = ({
|
|
|
9227
9399
|
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
9228
9400
|
title: "Aninhar no grupo acima"
|
|
9229
9401
|
},
|
|
9230
|
-
/* @__PURE__ */
|
|
9231
|
-
), /* @__PURE__ */
|
|
9402
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowRight, { size: 14 })
|
|
9403
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9232
9404
|
"button",
|
|
9233
9405
|
{
|
|
9234
9406
|
onClick: () => onOutdent(group.id),
|
|
9235
9407
|
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
9236
9408
|
title: "Desaninhar"
|
|
9237
9409
|
},
|
|
9238
|
-
/* @__PURE__ */
|
|
9239
|
-
), /* @__PURE__ */
|
|
9410
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowLeft, { size: 14 })
|
|
9411
|
+
), /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9240
9412
|
"button",
|
|
9241
9413
|
{
|
|
9242
9414
|
onClick: () => onDelete(group.id),
|
|
9243
9415
|
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
|
|
9244
9416
|
title: "Remover Grupo"
|
|
9245
9417
|
},
|
|
9246
|
-
/* @__PURE__ */
|
|
9247
|
-
)))), group.children && group.children.length > 0 && /* @__PURE__ */
|
|
9418
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiTrash2, { size: 14 })
|
|
9419
|
+
)))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react24.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react24.default.createElement(
|
|
9248
9420
|
GroupItem,
|
|
9249
9421
|
{
|
|
9250
9422
|
key: childGroup.id,
|
|
@@ -9276,21 +9448,21 @@ function AncestryBoard({
|
|
|
9276
9448
|
userRole
|
|
9277
9449
|
// [NOVO] Recebe a role do usuário
|
|
9278
9450
|
}) {
|
|
9279
|
-
const [searchTerm, setSearchTerm] = (0,
|
|
9280
|
-
const [groups, setGroups] = (0,
|
|
9281
|
-
const [isLoaded, setIsLoaded] = (0,
|
|
9282
|
-
const [pickingGroupId, setPickingGroupId] = (0,
|
|
9283
|
-
const [saveStatus, setSaveStatus] = (0,
|
|
9284
|
-
const canEdit = (0,
|
|
9451
|
+
const [searchTerm, setSearchTerm] = (0, import_react24.useState)("");
|
|
9452
|
+
const [groups, setGroups] = (0, import_react24.useState)([]);
|
|
9453
|
+
const [isLoaded, setIsLoaded] = (0, import_react24.useState)(false);
|
|
9454
|
+
const [pickingGroupId, setPickingGroupId] = (0, import_react24.useState)(null);
|
|
9455
|
+
const [saveStatus, setSaveStatus] = (0, import_react24.useState)("idle");
|
|
9456
|
+
const canEdit = (0, import_react24.useMemo)(() => {
|
|
9285
9457
|
return userRole !== "viewer";
|
|
9286
9458
|
}, [userRole]);
|
|
9287
|
-
(0,
|
|
9459
|
+
(0, import_react24.useEffect)(() => {
|
|
9288
9460
|
if (initialGroups && !isLoaded) {
|
|
9289
9461
|
setGroups(initialGroups);
|
|
9290
9462
|
setIsLoaded(true);
|
|
9291
9463
|
}
|
|
9292
9464
|
}, [initialGroups, isLoaded]);
|
|
9293
|
-
const nodeNamesMap = (0,
|
|
9465
|
+
const nodeNamesMap = (0, import_react24.useMemo)(() => {
|
|
9294
9466
|
const map = /* @__PURE__ */ new Map();
|
|
9295
9467
|
if (availableNodes && Array.isArray(availableNodes)) {
|
|
9296
9468
|
availableNodes.forEach((node) => {
|
|
@@ -9301,7 +9473,7 @@ function AncestryBoard({
|
|
|
9301
9473
|
}
|
|
9302
9474
|
return map;
|
|
9303
9475
|
}, [availableNodes]);
|
|
9304
|
-
const availableIds = (0,
|
|
9476
|
+
const availableIds = (0, import_react24.useMemo)(() => {
|
|
9305
9477
|
return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
|
|
9306
9478
|
}, [availableAncestries]);
|
|
9307
9479
|
const sanitizeGroups = (groupList) => {
|
|
@@ -9315,7 +9487,7 @@ function AncestryBoard({
|
|
|
9315
9487
|
children: sanitizeGroups(g.children || [])
|
|
9316
9488
|
}));
|
|
9317
9489
|
};
|
|
9318
|
-
(0,
|
|
9490
|
+
(0, import_react24.useEffect)(() => {
|
|
9319
9491
|
if (!isLoaded || !onSave) return;
|
|
9320
9492
|
const timeoutId = setTimeout(async () => {
|
|
9321
9493
|
setSaveStatus("saving");
|
|
@@ -9333,7 +9505,7 @@ function AncestryBoard({
|
|
|
9333
9505
|
}, 3e3);
|
|
9334
9506
|
return () => clearTimeout(timeoutId);
|
|
9335
9507
|
}, [groups, isLoaded, onSave]);
|
|
9336
|
-
(0,
|
|
9508
|
+
(0, import_react24.useEffect)(() => {
|
|
9337
9509
|
if (!isOpen) return;
|
|
9338
9510
|
const handleKeyDown = (e) => {
|
|
9339
9511
|
if (e.key === "Escape") {
|
|
@@ -9349,7 +9521,7 @@ function AncestryBoard({
|
|
|
9349
9521
|
window.addEventListener("keydown", handleKeyDown);
|
|
9350
9522
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
9351
9523
|
}, [isOpen, onClose, pickingGroupId]);
|
|
9352
|
-
const filtered = (0,
|
|
9524
|
+
const filtered = (0, import_react24.useMemo)(() => {
|
|
9353
9525
|
const term = searchTerm.toLowerCase().trim();
|
|
9354
9526
|
return availableAncestries.filter((a) => {
|
|
9355
9527
|
if (!term) return true;
|
|
@@ -9488,27 +9660,27 @@ function AncestryBoard({
|
|
|
9488
9660
|
});
|
|
9489
9661
|
};
|
|
9490
9662
|
if (!isOpen) return null;
|
|
9491
|
-
return /* @__PURE__ */
|
|
9663
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9492
9664
|
"div",
|
|
9493
9665
|
{
|
|
9494
9666
|
className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
|
|
9495
9667
|
onClick: onClose
|
|
9496
9668
|
},
|
|
9497
|
-
/* @__PURE__ */
|
|
9669
|
+
/* @__PURE__ */ import_react24.default.createElement(
|
|
9498
9670
|
"div",
|
|
9499
9671
|
{
|
|
9500
9672
|
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",
|
|
9501
9673
|
onClick: (e) => e.stopPropagation()
|
|
9502
9674
|
},
|
|
9503
|
-
/* @__PURE__ */
|
|
9675
|
+
/* @__PURE__ */ import_react24.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_react24.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react24.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.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_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react24.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_react24.default.createElement(
|
|
9504
9676
|
"button",
|
|
9505
9677
|
{
|
|
9506
9678
|
onClick: handleAddRootGroup,
|
|
9507
9679
|
className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
|
|
9508
9680
|
},
|
|
9509
|
-
/* @__PURE__ */
|
|
9510
|
-
/* @__PURE__ */
|
|
9511
|
-
), /* @__PURE__ */
|
|
9681
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14, className: "text-indigo-400" }),
|
|
9682
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
|
|
9683
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9512
9684
|
"button",
|
|
9513
9685
|
{
|
|
9514
9686
|
onClick: onClose,
|
|
@@ -9516,11 +9688,11 @@ function AncestryBoard({
|
|
|
9516
9688
|
},
|
|
9517
9689
|
"\xD7"
|
|
9518
9690
|
))),
|
|
9519
|
-
/* @__PURE__ */
|
|
9691
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9520
9692
|
flex flex-col border-r border-white/10 transition-all duration-300 flex-none
|
|
9521
9693
|
${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
|
|
9522
9694
|
min-w-[280px] max-w-[500px] bg-slate-900
|
|
9523
|
-
` }, /* @__PURE__ */
|
|
9695
|
+
` }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { 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"}` }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9524
9696
|
"input",
|
|
9525
9697
|
{
|
|
9526
9698
|
type: "text",
|
|
@@ -9533,10 +9705,10 @@ function AncestryBoard({
|
|
|
9533
9705
|
onChange: (e) => setSearchTerm(e.target.value),
|
|
9534
9706
|
autoFocus: !pickingGroupId
|
|
9535
9707
|
}
|
|
9536
|
-
))), /* @__PURE__ */
|
|
9708
|
+
))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
|
|
9537
9709
|
const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
|
|
9538
9710
|
const isPicking = !!pickingGroupId;
|
|
9539
|
-
return /* @__PURE__ */
|
|
9711
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9540
9712
|
"div",
|
|
9541
9713
|
{
|
|
9542
9714
|
key: anc.ancestry_id,
|
|
@@ -9548,12 +9720,12 @@ function AncestryBoard({
|
|
|
9548
9720
|
${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"}
|
|
9549
9721
|
`
|
|
9550
9722
|
},
|
|
9551
|
-
/* @__PURE__ */
|
|
9723
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9552
9724
|
mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
|
|
9553
9725
|
${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"}
|
|
9554
|
-
` }, isPicking ? /* @__PURE__ */
|
|
9555
|
-
/* @__PURE__ */
|
|
9556
|
-
!isPicking && /* @__PURE__ */
|
|
9726
|
+
` }, isPicking ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 14 })),
|
|
9727
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react24.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_react24.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_react24.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_react24.default.createElement(import_fi18.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react24.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
9728
|
+
!isPicking && /* @__PURE__ */ import_react24.default.createElement(
|
|
9557
9729
|
"button",
|
|
9558
9730
|
{
|
|
9559
9731
|
onClick: (e) => {
|
|
@@ -9563,10 +9735,10 @@ function AncestryBoard({
|
|
|
9563
9735
|
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",
|
|
9564
9736
|
title: "Renderizar Ancestralidade"
|
|
9565
9737
|
},
|
|
9566
|
-
/* @__PURE__ */
|
|
9738
|
+
/* @__PURE__ */ import_react24.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_react24.default.createElement(import_fi18.FiPlay, { size: 14, className: "ml-0.5" }))
|
|
9567
9739
|
)
|
|
9568
9740
|
);
|
|
9569
|
-
}))), /* @__PURE__ */
|
|
9741
|
+
}))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react24.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_react24.default.createElement(import_fi18.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react24.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react24.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react24.default.createElement(
|
|
9570
9742
|
GroupItem,
|
|
9571
9743
|
{
|
|
9572
9744
|
key: group.id,
|
|
@@ -9586,7 +9758,7 @@ function AncestryBoard({
|
|
|
9586
9758
|
canEdit
|
|
9587
9759
|
}
|
|
9588
9760
|
))))),
|
|
9589
|
-
/* @__PURE__ */
|
|
9761
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ import_react24.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react24.default.createElement("span", null, groups.length, " grupos raiz"))
|
|
9590
9762
|
)
|
|
9591
9763
|
);
|
|
9592
9764
|
}
|
|
@@ -9666,12 +9838,12 @@ function XViewScene({
|
|
|
9666
9838
|
check_user_permission
|
|
9667
9839
|
}) {
|
|
9668
9840
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
9669
|
-
const { data: session, status } = (0,
|
|
9841
|
+
const { data: session, status } = (0, import_react26.useSession)();
|
|
9670
9842
|
const router = (0, import_navigation.useRouter)();
|
|
9671
9843
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
9672
9844
|
const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
|
|
9673
9845
|
const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
|
|
9674
|
-
const viewParams = (0,
|
|
9846
|
+
const viewParams = (0, import_react25.useMemo)(() => {
|
|
9675
9847
|
if (encryptedConfig) {
|
|
9676
9848
|
const data = decryptData(encryptedConfig);
|
|
9677
9849
|
if (data) {
|
|
@@ -9680,7 +9852,7 @@ function XViewScene({
|
|
|
9680
9852
|
}
|
|
9681
9853
|
return null;
|
|
9682
9854
|
}, [encryptedConfig, session]);
|
|
9683
|
-
(0,
|
|
9855
|
+
(0, import_react25.useEffect)(() => {
|
|
9684
9856
|
async function verifyPermission() {
|
|
9685
9857
|
if (!viewParams || !session || !check_user_permission) return;
|
|
9686
9858
|
const { id, type, owner_id } = viewParams;
|
|
@@ -9710,64 +9882,65 @@ function XViewScene({
|
|
|
9710
9882
|
setIsLoading(false);
|
|
9711
9883
|
}
|
|
9712
9884
|
}, [viewParams, session, status, check_user_permission]);
|
|
9713
|
-
const sceneConfigId = (0,
|
|
9714
|
-
const ownerId = (0,
|
|
9715
|
-
const dbSaveUrl = (0,
|
|
9885
|
+
const sceneConfigId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
|
|
9886
|
+
const ownerId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
|
|
9887
|
+
const dbSaveUrl = (0, import_react25.useMemo)(() => {
|
|
9716
9888
|
if (ownerId && sceneConfigId) {
|
|
9717
9889
|
return `x_view_dbs/${ownerId}/${sceneConfigId}`;
|
|
9718
9890
|
}
|
|
9719
9891
|
return null;
|
|
9720
9892
|
}, [ownerId, sceneConfigId]);
|
|
9721
|
-
const sceneSaveUrl = (0,
|
|
9893
|
+
const sceneSaveUrl = (0, import_react25.useMemo)(() => {
|
|
9722
9894
|
if (ownerId && sceneConfigId) {
|
|
9723
9895
|
return `x_view_scenes/${ownerId}/${sceneConfigId}`;
|
|
9724
9896
|
}
|
|
9725
9897
|
return null;
|
|
9726
9898
|
}, [ownerId, sceneConfigId]);
|
|
9727
|
-
const ancestry_save_url = (0,
|
|
9899
|
+
const ancestry_save_url = (0, import_react25.useMemo)(() => {
|
|
9728
9900
|
if (ownerId && sceneConfigId) {
|
|
9729
9901
|
return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
|
|
9730
9902
|
}
|
|
9731
9903
|
return null;
|
|
9732
9904
|
}, [ownerId, sceneConfigId]);
|
|
9733
|
-
const sceneDataRef = (0,
|
|
9734
|
-
const parentDataRef = (0,
|
|
9735
|
-
const ancestryDataRef = (0,
|
|
9736
|
-
const [isLoading, setIsLoading] = (0,
|
|
9737
|
-
const [permissionStatus, setPermissionStatus] = (0,
|
|
9738
|
-
const [userPermissionRole, setUserPermissionRole] = (0,
|
|
9739
|
-
const [isInitialized, setIsInitialized] = (0,
|
|
9740
|
-
const [sceneVersion, setSceneVersion] = (0,
|
|
9741
|
-
const [contextMenu, setContextMenu] = (0,
|
|
9742
|
-
const [multiContextMenu, setMultiContextMenu] = (0,
|
|
9743
|
-
const [relationshipMenu, setRelationshipMenu] = (0,
|
|
9744
|
-
const [creationMode, setCreationMode] = (0,
|
|
9745
|
-
const [versionMode, setVersionMode] = (0,
|
|
9746
|
-
const [
|
|
9747
|
-
const [
|
|
9748
|
-
const [
|
|
9749
|
-
const [
|
|
9905
|
+
const sceneDataRef = (0, import_react25.useRef)(null);
|
|
9906
|
+
const parentDataRef = (0, import_react25.useRef)(null);
|
|
9907
|
+
const ancestryDataRef = (0, import_react25.useRef)(null);
|
|
9908
|
+
const [isLoading, setIsLoading] = (0, import_react25.useState)(true);
|
|
9909
|
+
const [permissionStatus, setPermissionStatus] = (0, import_react25.useState)("loading");
|
|
9910
|
+
const [userPermissionRole, setUserPermissionRole] = (0, import_react25.useState)(null);
|
|
9911
|
+
const [isInitialized, setIsInitialized] = (0, import_react25.useState)(false);
|
|
9912
|
+
const [sceneVersion, setSceneVersion] = (0, import_react25.useState)(0);
|
|
9913
|
+
const [contextMenu, setContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeData: null });
|
|
9914
|
+
const [multiContextMenu, setMultiContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
|
|
9915
|
+
const [relationshipMenu, setRelationshipMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, linkObject: null });
|
|
9916
|
+
const [creationMode, setCreationMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
|
|
9917
|
+
const [versionMode, setVersionMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
|
|
9918
|
+
const [questMode, setQuestMode] = (0, import_react25.useState)({ isActive: false });
|
|
9919
|
+
const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react25.useState)(false);
|
|
9920
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react25.useState)(false);
|
|
9921
|
+
const [ancestryMode, setAncestryMode] = (0, import_react25.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
9922
|
+
const [readingMode, setReadingMode] = (0, import_react25.useState)({
|
|
9750
9923
|
isActive: false,
|
|
9751
9924
|
ancestry: null,
|
|
9752
9925
|
branchStack: [],
|
|
9753
9926
|
autoAbstraction: false
|
|
9754
9927
|
});
|
|
9755
|
-
const [formPosition, setFormPosition] = (0,
|
|
9756
|
-
const [detailsNode, setDetailsNode] = (0,
|
|
9757
|
-
const [detailsLink, setDetailsLink] = (0,
|
|
9758
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] = (0,
|
|
9759
|
-
const [imageViewer, setImageViewer] = (0,
|
|
9760
|
-
const [editingAncestryRel, setEditingAncestryRel] = (0,
|
|
9761
|
-
const [isImportModalOpen, setIsImportModalOpen] = (0,
|
|
9762
|
-
const [importSuccessMessage, setImportSuccessMessage] = (0,
|
|
9763
|
-
const [highlightedNodeId, setHighlightedNodeId] = (0,
|
|
9764
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0,
|
|
9765
|
-
const [ancestryBoardData, setAncestryBoardData] = (0,
|
|
9766
|
-
const [isSidebarOpen, setIsSidebarOpen] = (0,
|
|
9767
|
-
const mountRef = (0,
|
|
9768
|
-
const tooltipRef = (0,
|
|
9769
|
-
const formRef = (0,
|
|
9770
|
-
const stateRef = (0,
|
|
9928
|
+
const [formPosition, setFormPosition] = (0, import_react25.useState)({ left: 16, top: 16, opacity: 0 });
|
|
9929
|
+
const [detailsNode, setDetailsNode] = (0, import_react25.useState)(null);
|
|
9930
|
+
const [detailsLink, setDetailsLink] = (0, import_react25.useState)(null);
|
|
9931
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react25.useState)(null);
|
|
9932
|
+
const [imageViewer, setImageViewer] = (0, import_react25.useState)({ visible: false, images: [], startIndex: 0 });
|
|
9933
|
+
const [editingAncestryRel, setEditingAncestryRel] = (0, import_react25.useState)({ visible: false, data: null, path: null });
|
|
9934
|
+
const [isImportModalOpen, setIsImportModalOpen] = (0, import_react25.useState)(false);
|
|
9935
|
+
const [importSuccessMessage, setImportSuccessMessage] = (0, import_react25.useState)("");
|
|
9936
|
+
const [highlightedNodeId, setHighlightedNodeId] = (0, import_react25.useState)(null);
|
|
9937
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react25.useState)(false);
|
|
9938
|
+
const [ancestryBoardData, setAncestryBoardData] = (0, import_react25.useState)([]);
|
|
9939
|
+
const [isSidebarOpen, setIsSidebarOpen] = (0, import_react25.useState)(false);
|
|
9940
|
+
const mountRef = (0, import_react25.useRef)(null);
|
|
9941
|
+
const tooltipRef = (0, import_react25.useRef)(null);
|
|
9942
|
+
const formRef = (0, import_react25.useRef)(null);
|
|
9943
|
+
const stateRef = (0, import_react25.useRef)({
|
|
9771
9944
|
readMode: {
|
|
9772
9945
|
currentMaxIndex: 0,
|
|
9773
9946
|
progressMap: {}
|
|
@@ -9812,10 +9985,10 @@ function XViewScene({
|
|
|
9812
9985
|
minWidth: 320,
|
|
9813
9986
|
maxWidth: maxReadPanelW
|
|
9814
9987
|
});
|
|
9815
|
-
(0,
|
|
9988
|
+
(0, import_react25.useEffect)(() => {
|
|
9816
9989
|
stateRef.current.ancestry = ancestryMode;
|
|
9817
9990
|
}, [ancestryMode]);
|
|
9818
|
-
(0,
|
|
9991
|
+
(0, import_react25.useEffect)(() => {
|
|
9819
9992
|
var _a2;
|
|
9820
9993
|
if (!isInitialized) return;
|
|
9821
9994
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -9836,10 +10009,10 @@ function XViewScene({
|
|
|
9836
10009
|
}
|
|
9837
10010
|
stateRef.current.nodeIdToParentFileMap = map;
|
|
9838
10011
|
}, [isInitialized, sceneVersion]);
|
|
9839
|
-
const handleNavigateBack = (0,
|
|
10012
|
+
const handleNavigateBack = (0, import_react25.useCallback)(() => {
|
|
9840
10013
|
router.push("/dashboard/scenes");
|
|
9841
10014
|
}, [router]);
|
|
9842
|
-
const handleConfirmImport = (0,
|
|
10015
|
+
const handleConfirmImport = (0, import_react25.useCallback)(
|
|
9843
10016
|
async (importPayload) => {
|
|
9844
10017
|
var _a2, _b2;
|
|
9845
10018
|
let files = [];
|
|
@@ -9937,7 +10110,7 @@ function XViewScene({
|
|
|
9937
10110
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
9938
10111
|
setImageViewer({ visible: true, images, startIndex });
|
|
9939
10112
|
};
|
|
9940
|
-
const tweenToTarget = (0,
|
|
10113
|
+
const tweenToTarget = (0, import_react25.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
|
|
9941
10114
|
const { camera, controls, tweenGroup } = stateRef.current;
|
|
9942
10115
|
if (!camera || !controls || !tweenGroup) return;
|
|
9943
10116
|
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
@@ -9960,7 +10133,7 @@ function XViewScene({
|
|
|
9960
10133
|
if (!t || typeof t.closest !== "function") return false;
|
|
9961
10134
|
return !!t.closest(".ui-overlay");
|
|
9962
10135
|
};
|
|
9963
|
-
const buildFullAncestryTree = (0,
|
|
10136
|
+
const buildFullAncestryTree = (0, import_react25.useCallback)((idTree, nodes, ancestries = []) => {
|
|
9964
10137
|
if (!idTree) return null;
|
|
9965
10138
|
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
9966
10139
|
const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
|
|
@@ -10036,7 +10209,7 @@ function XViewScene({
|
|
|
10036
10209
|
}
|
|
10037
10210
|
return recursiveBuild(idTree);
|
|
10038
10211
|
}, []);
|
|
10039
|
-
const handleActivateTimeline = (0,
|
|
10212
|
+
const handleActivateTimeline = (0, import_react25.useCallback)(() => {
|
|
10040
10213
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10041
10214
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
10042
10215
|
while (timelineIntervalsGroup.children.length > 0) {
|
|
@@ -10189,7 +10362,7 @@ function XViewScene({
|
|
|
10189
10362
|
}
|
|
10190
10363
|
});
|
|
10191
10364
|
}, []);
|
|
10192
|
-
const handleVersionTimeline = (0,
|
|
10365
|
+
const handleVersionTimeline = (0, import_react25.useCallback)((sourceMesh, versionMeshes) => {
|
|
10193
10366
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10194
10367
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
|
|
10195
10368
|
versionMeshes.forEach((mesh) => {
|
|
@@ -10312,7 +10485,7 @@ function XViewScene({
|
|
|
10312
10485
|
}
|
|
10313
10486
|
});
|
|
10314
10487
|
}, []);
|
|
10315
|
-
(0,
|
|
10488
|
+
(0, import_react25.useEffect)(() => {
|
|
10316
10489
|
async function fetchAllData(configPath, ownerId2) {
|
|
10317
10490
|
var _a2, _b2;
|
|
10318
10491
|
if (!get_scene_view_data) {
|
|
@@ -10384,12 +10557,12 @@ function XViewScene({
|
|
|
10384
10557
|
focusNodeId,
|
|
10385
10558
|
focusAncestryId
|
|
10386
10559
|
]);
|
|
10387
|
-
const isNodeInView = (0,
|
|
10560
|
+
const isNodeInView = (0, import_react25.useCallback)((id) => {
|
|
10388
10561
|
const key = String(id);
|
|
10389
10562
|
const objs = stateRef.current.nodeObjects || {};
|
|
10390
10563
|
return !!objs[key];
|
|
10391
10564
|
}, []);
|
|
10392
|
-
const addOrUpdateNodeMesh = (0,
|
|
10565
|
+
const addOrUpdateNodeMesh = (0, import_react25.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
|
|
10393
10566
|
const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
|
|
10394
10567
|
const nodeId = String(nodeData.id);
|
|
10395
10568
|
if (nodeObjects[nodeId]) {
|
|
@@ -10416,7 +10589,7 @@ function XViewScene({
|
|
|
10416
10589
|
}
|
|
10417
10590
|
return mesh;
|
|
10418
10591
|
}, []);
|
|
10419
|
-
(0,
|
|
10592
|
+
(0, import_react25.useEffect)(() => {
|
|
10420
10593
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
10421
10594
|
const currentMount = mountRef.current;
|
|
10422
10595
|
if (!currentMount) return;
|
|
@@ -10809,12 +10982,15 @@ function XViewScene({
|
|
|
10809
10982
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
10810
10983
|
}
|
|
10811
10984
|
function handleKeyDown(event) {
|
|
10985
|
+
var _a2, _b2, _c2, _d2;
|
|
10812
10986
|
const context = actionHandlerContext;
|
|
10813
10987
|
if (event.key === "Escape") {
|
|
10814
10988
|
if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
|
|
10815
10989
|
if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
|
|
10816
10990
|
if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
|
|
10991
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
|
|
10817
10992
|
if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
|
|
10993
|
+
if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
|
|
10818
10994
|
if (stateRef.current.selectedNodes.size > 0) {
|
|
10819
10995
|
stateRef.current.selectedNodes.clear();
|
|
10820
10996
|
}
|
|
@@ -10822,6 +10998,17 @@ function XViewScene({
|
|
|
10822
10998
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
10823
10999
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
10824
11000
|
}
|
|
11001
|
+
if (event.key.toLowerCase() === "q") {
|
|
11002
|
+
const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_c2 = context.versionMode) == null ? void 0 : _c2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isAncestryBoardOpen;
|
|
11003
|
+
if (isUiClear) {
|
|
11004
|
+
const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
|
|
11005
|
+
if (!isView) {
|
|
11006
|
+
alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
|
|
11007
|
+
return;
|
|
11008
|
+
}
|
|
11009
|
+
setQuestMode({ isActive: true });
|
|
11010
|
+
}
|
|
11011
|
+
}
|
|
10825
11012
|
}
|
|
10826
11013
|
function handleDoubleClick(event) {
|
|
10827
11014
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
@@ -10980,9 +11167,7 @@ function XViewScene({
|
|
|
10980
11167
|
mountEl: currentMount,
|
|
10981
11168
|
isSceneBusy: stateRef.current.isDragging || creation.isActive || connection.isActive || relink.isActive || ancestryMode.isActive,
|
|
10982
11169
|
parentData: parentDataRef.current,
|
|
10983
|
-
// <--- ADICIONADO AQUI
|
|
10984
11170
|
ancestryData: ancestryDataRef.current
|
|
10985
|
-
// <--- ADICIONADO AQUI
|
|
10986
11171
|
});
|
|
10987
11172
|
(_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
|
|
10988
11173
|
stateRef.current.controls.update();
|
|
@@ -11049,7 +11234,7 @@ function XViewScene({
|
|
|
11049
11234
|
}
|
|
11050
11235
|
};
|
|
11051
11236
|
}, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
|
|
11052
|
-
const handleGhostNodeImageChange = (0,
|
|
11237
|
+
const handleGhostNodeImageChange = (0, import_react25.useCallback)((useImage, imageUrl) => {
|
|
11053
11238
|
const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11054
11239
|
const { graphGroup, glowTexture } = stateRef.current;
|
|
11055
11240
|
if (!ghostNode || !graphGroup) return;
|
|
@@ -11091,7 +11276,7 @@ function XViewScene({
|
|
|
11091
11276
|
aura: newGhostNode.getObjectByName("aura")
|
|
11092
11277
|
};
|
|
11093
11278
|
}, []);
|
|
11094
|
-
const handleGhostNodeIntensityChange = (0,
|
|
11279
|
+
const handleGhostNodeIntensityChange = (0, import_react25.useCallback)((newIntensity) => {
|
|
11095
11280
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11096
11281
|
if (!ghostNode) return;
|
|
11097
11282
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -11112,7 +11297,7 @@ function XViewScene({
|
|
|
11112
11297
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11113
11298
|
}
|
|
11114
11299
|
}, []);
|
|
11115
|
-
const handleDetailNodeIntensityChange = (0,
|
|
11300
|
+
const handleDetailNodeIntensityChange = (0, import_react25.useCallback)((nodeId, newIntensity) => {
|
|
11116
11301
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
11117
11302
|
if (!mesh) return;
|
|
11118
11303
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -11258,7 +11443,7 @@ function XViewScene({
|
|
|
11258
11443
|
mountRef.current.style.cursor = "default";
|
|
11259
11444
|
}
|
|
11260
11445
|
};
|
|
11261
|
-
const handleAncestryTreeUpdate = (0,
|
|
11446
|
+
const handleAncestryTreeUpdate = (0, import_react25.useCallback)((newTree, extraData = null) => {
|
|
11262
11447
|
setAncestryMode((prev) => {
|
|
11263
11448
|
const prevTreeStr = JSON.stringify(prev.tree);
|
|
11264
11449
|
const newTreeStr = JSON.stringify(newTree);
|
|
@@ -11278,7 +11463,7 @@ function XViewScene({
|
|
|
11278
11463
|
};
|
|
11279
11464
|
});
|
|
11280
11465
|
}, []);
|
|
11281
|
-
const actionHandlerContext = (0,
|
|
11466
|
+
const actionHandlerContext = (0, import_react25.useMemo)(
|
|
11282
11467
|
() => {
|
|
11283
11468
|
var _a2;
|
|
11284
11469
|
return {
|
|
@@ -11288,6 +11473,16 @@ function XViewScene({
|
|
|
11288
11473
|
mountRef,
|
|
11289
11474
|
creationMode,
|
|
11290
11475
|
versionMode,
|
|
11476
|
+
questMode,
|
|
11477
|
+
// <-- Adicionado
|
|
11478
|
+
sceneSaveUrl,
|
|
11479
|
+
// <-- Adicionado
|
|
11480
|
+
sceneConfigId,
|
|
11481
|
+
// <-- Adicionado
|
|
11482
|
+
ownerId,
|
|
11483
|
+
// <-- Adicionado
|
|
11484
|
+
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11485
|
+
// <-- Adicionado
|
|
11291
11486
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
11292
11487
|
setters: {
|
|
11293
11488
|
setContextMenu,
|
|
@@ -11299,7 +11494,9 @@ function XViewScene({
|
|
|
11299
11494
|
setDetailsNode,
|
|
11300
11495
|
setDetailsLink,
|
|
11301
11496
|
setSceneVersion,
|
|
11302
|
-
setAncestryMode
|
|
11497
|
+
setAncestryMode,
|
|
11498
|
+
setQuestMode
|
|
11499
|
+
// <-- Adicionado
|
|
11303
11500
|
},
|
|
11304
11501
|
tweenToTarget,
|
|
11305
11502
|
handleVersionTimeline,
|
|
@@ -11315,8 +11512,13 @@ function XViewScene({
|
|
|
11315
11512
|
[
|
|
11316
11513
|
creationMode,
|
|
11317
11514
|
versionMode,
|
|
11318
|
-
|
|
11515
|
+
questMode,
|
|
11516
|
+
sceneSaveUrl,
|
|
11517
|
+
sceneConfigId,
|
|
11518
|
+
ownerId,
|
|
11519
|
+
viewParams == null ? void 0 : viewParams.type,
|
|
11319
11520
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11521
|
+
tweenToTarget,
|
|
11320
11522
|
handleVersionTimeline,
|
|
11321
11523
|
save_view_data,
|
|
11322
11524
|
get_single_parent_file,
|
|
@@ -11328,7 +11530,112 @@ function XViewScene({
|
|
|
11328
11530
|
const handleStartVersioning = (nodeData) => {
|
|
11329
11531
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11330
11532
|
};
|
|
11331
|
-
const
|
|
11533
|
+
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11534
|
+
const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
|
|
11535
|
+
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11536
|
+
const newNode = {
|
|
11537
|
+
id: import_short_uuid2.default.generate(),
|
|
11538
|
+
...newQuestData,
|
|
11539
|
+
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11540
|
+
};
|
|
11541
|
+
if (!graphDataRef.current[sceneConfigId2]) {
|
|
11542
|
+
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11543
|
+
}
|
|
11544
|
+
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
11545
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
11546
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((mesh) => {
|
|
11547
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = mesh.userData;
|
|
11548
|
+
return rest;
|
|
11549
|
+
});
|
|
11550
|
+
currentVisualNodes.push(newNode);
|
|
11551
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((line) => {
|
|
11552
|
+
const { sourceNode, targetNode, ...rest } = line.userData;
|
|
11553
|
+
return rest;
|
|
11554
|
+
});
|
|
11555
|
+
const sceneFileData = {
|
|
11556
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11557
|
+
nodes: currentVisualNodes,
|
|
11558
|
+
links: currentVisualLinks,
|
|
11559
|
+
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
11560
|
+
quest_links: graphDataRef.current[sceneConfigId2].links
|
|
11561
|
+
};
|
|
11562
|
+
try {
|
|
11563
|
+
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
11564
|
+
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
11565
|
+
parentFileId: sceneConfigId2,
|
|
11566
|
+
ownerId: ownerId2,
|
|
11567
|
+
datasetName: "Quests Internas (View)"
|
|
11568
|
+
});
|
|
11569
|
+
const basePosition = stateRef2.current.controls.target.clone();
|
|
11570
|
+
const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
|
|
11571
|
+
const finalPosition = basePosition.add(offset);
|
|
11572
|
+
addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
|
|
11573
|
+
context.tweenToTarget(finalPosition, 1.2);
|
|
11574
|
+
setters.setQuestMode({ isActive: false });
|
|
11575
|
+
setters.setSceneVersion((v) => v + 1);
|
|
11576
|
+
} catch (error) {
|
|
11577
|
+
console.error("Falha ao salvar Quest na View:", error);
|
|
11578
|
+
alert("Ocorreu um erro ao criar a Quest.");
|
|
11579
|
+
}
|
|
11580
|
+
};
|
|
11581
|
+
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
11582
|
+
const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2 } = context;
|
|
11583
|
+
const { sourceNodeData } = stateRef2.current.connection;
|
|
11584
|
+
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
11585
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id);
|
|
11589
|
+
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id);
|
|
11590
|
+
let parentInfoToSave = sourceParentInfo;
|
|
11591
|
+
if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
|
|
11592
|
+
parentInfoToSave = targetParentInfo;
|
|
11593
|
+
} else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
|
|
11594
|
+
parentInfoToSave = sourceParentInfo;
|
|
11595
|
+
}
|
|
11596
|
+
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11597
|
+
const newLink = {
|
|
11598
|
+
id: `link_${import_short_uuid2.default.generate()}`,
|
|
11599
|
+
source: sourceNodeData.id,
|
|
11600
|
+
target: targetNodeData.id
|
|
11601
|
+
};
|
|
11602
|
+
try {
|
|
11603
|
+
if (parentFileIdToSave === sceneConfigId2) {
|
|
11604
|
+
const specificParentData = graphDataRef.current[sceneConfigId2];
|
|
11605
|
+
specificParentData.links.push(newLink);
|
|
11606
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((m) => {
|
|
11607
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = m.userData;
|
|
11608
|
+
return rest;
|
|
11609
|
+
});
|
|
11610
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((l) => {
|
|
11611
|
+
const { sourceNode, targetNode, ...rest } = l.userData;
|
|
11612
|
+
return rest;
|
|
11613
|
+
});
|
|
11614
|
+
currentVisualLinks.push(newLink);
|
|
11615
|
+
const viewFilePayload = {
|
|
11616
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11617
|
+
nodes: currentVisualNodes,
|
|
11618
|
+
links: currentVisualLinks,
|
|
11619
|
+
quest_nodes: specificParentData.nodes,
|
|
11620
|
+
quest_links: specificParentData.links
|
|
11621
|
+
// Salva a conexão aqui!
|
|
11622
|
+
};
|
|
11623
|
+
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
11624
|
+
} else {
|
|
11625
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
11626
|
+
specificParentData.links.push(newLink);
|
|
11627
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
11628
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
11629
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
11630
|
+
}
|
|
11631
|
+
addNewLinkToScene(stateRef2.current, newLink);
|
|
11632
|
+
} catch (error) {
|
|
11633
|
+
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
11634
|
+
alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
|
|
11635
|
+
}
|
|
11636
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11637
|
+
};
|
|
11638
|
+
const handleClearAncestryVisuals = (0, import_react25.useCallback)((ancestryId) => {
|
|
11332
11639
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11333
11640
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
11334
11641
|
if (renderIndex !== -1) {
|
|
@@ -11342,7 +11649,7 @@ function XViewScene({
|
|
|
11342
11649
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
11343
11650
|
}
|
|
11344
11651
|
}, []);
|
|
11345
|
-
const handleRenderAncestry = (0,
|
|
11652
|
+
const handleRenderAncestry = (0, import_react25.useCallback)(
|
|
11346
11653
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
11347
11654
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11348
11655
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -11758,7 +12065,7 @@ function XViewScene({
|
|
|
11758
12065
|
},
|
|
11759
12066
|
[addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
|
|
11760
12067
|
);
|
|
11761
|
-
const handleRenderAbstractionTree = (0,
|
|
12068
|
+
const handleRenderAbstractionTree = (0, import_react25.useCallback)((ancestryObject, targetNodeId = null) => {
|
|
11762
12069
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11763
12070
|
if (!ancestryObject || !ancestryObject.abstraction_tree) return;
|
|
11764
12071
|
const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
|
|
@@ -11819,7 +12126,7 @@ function XViewScene({
|
|
|
11819
12126
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
11820
12127
|
tweenToTarget(rootTargetPos, 0.7);
|
|
11821
12128
|
}, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
|
|
11822
|
-
const handleReadModeBranchNav = (0,
|
|
12129
|
+
const handleReadModeBranchNav = (0, import_react25.useCallback)((nodeId, action, direction = "right") => {
|
|
11823
12130
|
const { ancestry, branchStack } = readingMode;
|
|
11824
12131
|
if (!ancestry || !ancestry.tree) return;
|
|
11825
12132
|
const allAncestries = ancestryDataRef.current || [];
|
|
@@ -11960,13 +12267,13 @@ function XViewScene({
|
|
|
11960
12267
|
}));
|
|
11961
12268
|
}
|
|
11962
12269
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
|
|
11963
|
-
const handleReadModeHighlight = (0,
|
|
12270
|
+
const handleReadModeHighlight = (0, import_react25.useCallback)((nodeId) => {
|
|
11964
12271
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
11965
12272
|
stateRef.current.highlightedNodeId = nodeId;
|
|
11966
12273
|
}
|
|
11967
12274
|
setHighlightedNodeId(nodeId);
|
|
11968
12275
|
}, []);
|
|
11969
|
-
const activeNodeBranches = (0,
|
|
12276
|
+
const activeNodeBranches = (0, import_react25.useMemo)(() => {
|
|
11970
12277
|
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree) return null;
|
|
11971
12278
|
const fullTree = buildFullAncestryTree(
|
|
11972
12279
|
readingMode.ancestry.tree,
|
|
@@ -12003,7 +12310,7 @@ function XViewScene({
|
|
|
12003
12310
|
}
|
|
12004
12311
|
return null;
|
|
12005
12312
|
}, [highlightedNodeId, readingMode.ancestry, buildFullAncestryTree, readingMode.branchStack, ancestryDataRef.current]);
|
|
12006
|
-
const backNavigationInfo = (0,
|
|
12313
|
+
const backNavigationInfo = (0, import_react25.useMemo)(() => {
|
|
12007
12314
|
const { branchStack } = readingMode;
|
|
12008
12315
|
if (!branchStack || branchStack.length === 0) return null;
|
|
12009
12316
|
const lastStep = branchStack[branchStack.length - 1];
|
|
@@ -12014,7 +12321,7 @@ function XViewScene({
|
|
|
12014
12321
|
name: "Voltar para anterior"
|
|
12015
12322
|
};
|
|
12016
12323
|
}, [readingMode.branchStack]);
|
|
12017
|
-
const getReadModeDisplayContext = (0,
|
|
12324
|
+
const getReadModeDisplayContext = (0, import_react25.useMemo)(() => {
|
|
12018
12325
|
const { ancestry, branchStack } = readingMode;
|
|
12019
12326
|
if (!ancestry) return null;
|
|
12020
12327
|
if (branchStack.length === 0) {
|
|
@@ -12055,7 +12362,7 @@ function XViewScene({
|
|
|
12055
12362
|
customProperties: branchProps
|
|
12056
12363
|
};
|
|
12057
12364
|
}, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
|
|
12058
|
-
const readModeAbstractionTree = (0,
|
|
12365
|
+
const readModeAbstractionTree = (0, import_react25.useMemo)(() => {
|
|
12059
12366
|
if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
|
|
12060
12367
|
return null;
|
|
12061
12368
|
}
|
|
@@ -12067,7 +12374,7 @@ function XViewScene({
|
|
|
12067
12374
|
allAncestries
|
|
12068
12375
|
);
|
|
12069
12376
|
}, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
|
|
12070
|
-
const handleStartReadingAncestry = (0,
|
|
12377
|
+
const handleStartReadingAncestry = (0, import_react25.useCallback)(
|
|
12071
12378
|
async (ancestryObject) => {
|
|
12072
12379
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
12073
12380
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -12102,7 +12409,7 @@ function XViewScene({
|
|
|
12102
12409
|
},
|
|
12103
12410
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
12104
12411
|
);
|
|
12105
|
-
const handleReadModeSectionChange = (0,
|
|
12412
|
+
const handleReadModeSectionChange = (0, import_react25.useCallback)((activeSectionId) => {
|
|
12106
12413
|
const { ancestry, branchStack } = readingMode;
|
|
12107
12414
|
if (!ancestry || !readingMode.isActive) return;
|
|
12108
12415
|
let targetObj = ancestry;
|
|
@@ -12171,10 +12478,10 @@ function XViewScene({
|
|
|
12171
12478
|
}, 0);
|
|
12172
12479
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
12173
12480
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
|
|
12174
|
-
const handleCloseReadMode = (0,
|
|
12481
|
+
const handleCloseReadMode = (0, import_react25.useCallback)(() => {
|
|
12175
12482
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
12176
12483
|
}, []);
|
|
12177
|
-
const handleAncestrySectionChange = (0,
|
|
12484
|
+
const handleAncestrySectionChange = (0, import_react25.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
12178
12485
|
var _a2, _b2;
|
|
12179
12486
|
const currentMode = stateRef.current.ancestry;
|
|
12180
12487
|
let targetObj = ancestryOverride;
|
|
@@ -12226,7 +12533,7 @@ function XViewScene({
|
|
|
12226
12533
|
const renderPayload = { ...targetObj, tree: treeToRender };
|
|
12227
12534
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
12228
12535
|
}, [handleRenderAncestry]);
|
|
12229
|
-
const handleEditAncestry = (0,
|
|
12536
|
+
const handleEditAncestry = (0, import_react25.useCallback)(
|
|
12230
12537
|
async (ancestryObject) => {
|
|
12231
12538
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
12232
12539
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -12265,7 +12572,7 @@ function XViewScene({
|
|
|
12265
12572
|
const handleSelectAncestryParent = (nodeId) => {
|
|
12266
12573
|
setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
|
|
12267
12574
|
};
|
|
12268
|
-
const handleRemoveFromAncestry = (0,
|
|
12575
|
+
const handleRemoveFromAncestry = (0, import_react25.useCallback)((pathToRemove) => {
|
|
12269
12576
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
|
|
12270
12577
|
console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
|
|
12271
12578
|
return;
|
|
@@ -12290,7 +12597,7 @@ function XViewScene({
|
|
|
12290
12597
|
return { ...prev, tree: newTree };
|
|
12291
12598
|
});
|
|
12292
12599
|
}, []);
|
|
12293
|
-
const handleSaveAncestry = (0,
|
|
12600
|
+
const handleSaveAncestry = (0, import_react25.useCallback)(
|
|
12294
12601
|
async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
|
|
12295
12602
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
12296
12603
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
@@ -12494,7 +12801,7 @@ function XViewScene({
|
|
|
12494
12801
|
});
|
|
12495
12802
|
setEditingAncestryRel({ visible: false, data: null, path: null });
|
|
12496
12803
|
};
|
|
12497
|
-
const handleDeleteAncestry = (0,
|
|
12804
|
+
const handleDeleteAncestry = (0, import_react25.useCallback)(
|
|
12498
12805
|
async (ancestryIdToDelete) => {
|
|
12499
12806
|
if (!ancestryIdToDelete) {
|
|
12500
12807
|
alert("ID da ancestralidade n\xE3o encontrado.");
|
|
@@ -12556,20 +12863,20 @@ function XViewScene({
|
|
|
12556
12863
|
},
|
|
12557
12864
|
[save_view_data, delete_file_action]
|
|
12558
12865
|
);
|
|
12559
|
-
const handleOpenAncestryBoard = (0,
|
|
12866
|
+
const handleOpenAncestryBoard = (0, import_react25.useCallback)(() => {
|
|
12560
12867
|
setIsAncestryBoardOpen(true);
|
|
12561
12868
|
}, []);
|
|
12562
|
-
const handleSelectAncestryFromBoard = (0,
|
|
12869
|
+
const handleSelectAncestryFromBoard = (0, import_react25.useCallback)((ancestry) => {
|
|
12563
12870
|
setIsAncestryBoardOpen(false);
|
|
12564
12871
|
setIsSidebarOpen(false);
|
|
12565
12872
|
handleStartReadingAncestry(ancestry);
|
|
12566
12873
|
}, [handleStartReadingAncestry]);
|
|
12567
|
-
const handleSaveAncestryBoard = (0,
|
|
12874
|
+
const handleSaveAncestryBoard = (0, import_react25.useCallback)(async (groups) => {
|
|
12568
12875
|
if (!sceneConfigId || !viewParams || !session) return;
|
|
12569
12876
|
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
12570
12877
|
await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
|
|
12571
12878
|
}, [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]);
|
|
12572
|
-
const existingNodeTypes = (0,
|
|
12879
|
+
const existingNodeTypes = (0, import_react25.useMemo)(() => {
|
|
12573
12880
|
if (!parentDataRef.current) {
|
|
12574
12881
|
return [];
|
|
12575
12882
|
}
|
|
@@ -12579,7 +12886,7 @@ function XViewScene({
|
|
|
12579
12886
|
})).filter(Boolean);
|
|
12580
12887
|
return [...new Set(allTypes)];
|
|
12581
12888
|
}, [parentDataRef.current, sceneVersion]);
|
|
12582
|
-
const searchableDbNodes = (0,
|
|
12889
|
+
const searchableDbNodes = (0, import_react25.useMemo)(() => {
|
|
12583
12890
|
if (!parentDataRef.current) {
|
|
12584
12891
|
return [];
|
|
12585
12892
|
}
|
|
@@ -12588,13 +12895,14 @@ function XViewScene({
|
|
|
12588
12895
|
return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
|
|
12589
12896
|
});
|
|
12590
12897
|
}, [parentDataRef.current, sceneVersion]);
|
|
12591
|
-
const handleAddExistingNode = (0,
|
|
12898
|
+
const handleAddExistingNode = (0, import_react25.useCallback)(
|
|
12592
12899
|
(nodeId) => {
|
|
12593
12900
|
return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
|
|
12594
12901
|
},
|
|
12595
12902
|
[actionHandlerContext]
|
|
12596
12903
|
);
|
|
12597
|
-
const handleSaveCurrentView = (0,
|
|
12904
|
+
const handleSaveCurrentView = (0, import_react25.useCallback)(async () => {
|
|
12905
|
+
var _a2, _b2;
|
|
12598
12906
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12599
12907
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12600
12908
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12619,22 +12927,25 @@ function XViewScene({
|
|
|
12619
12927
|
const sceneFileData = {
|
|
12620
12928
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
12621
12929
|
nodes: currentNodes,
|
|
12622
|
-
links: currentLinks
|
|
12930
|
+
links: currentLinks,
|
|
12931
|
+
// --- ADICIONE ESTAS DUAS LINHAS PARA PRESERVAR A FONTE DA VERDADE ---
|
|
12932
|
+
quest_nodes: ((_a2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _a2.nodes) || [],
|
|
12933
|
+
quest_links: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.links) || []
|
|
12623
12934
|
};
|
|
12624
12935
|
try {
|
|
12625
12936
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
12626
12937
|
} catch (error) {
|
|
12627
12938
|
console.error("Erro na chamada de save_view_data:", error);
|
|
12628
12939
|
}
|
|
12629
|
-
}, [sceneSaveUrl, save_view_data]);
|
|
12630
|
-
const allAvailableNodes = (0,
|
|
12940
|
+
}, [sceneSaveUrl, save_view_data, sceneConfigId]);
|
|
12941
|
+
const allAvailableNodes = (0, import_react25.useMemo)(() => {
|
|
12631
12942
|
if (!parentDataRef.current) return [];
|
|
12632
12943
|
return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
12633
12944
|
}, [sceneVersion, isInitialized]);
|
|
12634
|
-
const allAvailableAncestries = (0,
|
|
12945
|
+
const allAvailableAncestries = (0, import_react25.useMemo)(() => {
|
|
12635
12946
|
return ancestryDataRef.current || [];
|
|
12636
12947
|
}, [sceneVersion, isInitialized]);
|
|
12637
|
-
const handleOpenReference = (0,
|
|
12948
|
+
const handleOpenReference = (0, import_react25.useCallback)((referenceData) => {
|
|
12638
12949
|
const { type, id } = referenceData;
|
|
12639
12950
|
if (type === "node") {
|
|
12640
12951
|
const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
|
|
@@ -12661,17 +12972,17 @@ function XViewScene({
|
|
|
12661
12972
|
}
|
|
12662
12973
|
}
|
|
12663
12974
|
}, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
|
|
12664
|
-
const handleToggleAncestryAddMode = (0,
|
|
12975
|
+
const handleToggleAncestryAddMode = (0, import_react25.useCallback)(() => {
|
|
12665
12976
|
setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
|
|
12666
12977
|
}, []);
|
|
12667
|
-
const handleFocusNode = (0,
|
|
12978
|
+
const handleFocusNode = (0, import_react25.useCallback)((nodeData) => {
|
|
12668
12979
|
if (!nodeData) return;
|
|
12669
12980
|
const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
|
|
12670
12981
|
if (nodeMesh) {
|
|
12671
12982
|
tweenToTarget(nodeMesh, 1.2);
|
|
12672
12983
|
}
|
|
12673
12984
|
}, [tweenToTarget]);
|
|
12674
|
-
const availableDatasets = (0,
|
|
12985
|
+
const availableDatasets = (0, import_react25.useMemo)(() => {
|
|
12675
12986
|
if (!sceneDataRef.current || !parentDataRef.current) return [];
|
|
12676
12987
|
return sceneDataRef.current.parent_dbs.map((db) => {
|
|
12677
12988
|
var _a2;
|
|
@@ -12683,7 +12994,7 @@ function XViewScene({
|
|
|
12683
12994
|
}, [sceneVersion, isInitialized]);
|
|
12684
12995
|
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(String(creationMode.sourceNodeData.id))) == null ? void 0 : _b.parentFileId : null;
|
|
12685
12996
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
12686
|
-
(0,
|
|
12997
|
+
(0, import_react25.useEffect)(() => {
|
|
12687
12998
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
12688
12999
|
const nodeObjects = stateRef.current.nodeObjects || {};
|
|
12689
13000
|
const targetMesh = nodeObjects[String(focusNodeId)];
|
|
@@ -12697,7 +13008,7 @@ function XViewScene({
|
|
|
12697
13008
|
}
|
|
12698
13009
|
}
|
|
12699
13010
|
}, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
|
|
12700
|
-
(0,
|
|
13011
|
+
(0, import_react25.useEffect)(() => {
|
|
12701
13012
|
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
12702
13013
|
const ancestries = ancestryDataRef.current || [];
|
|
12703
13014
|
const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
|
|
@@ -12712,20 +13023,20 @@ function XViewScene({
|
|
|
12712
13023
|
}
|
|
12713
13024
|
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
12714
13025
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
12715
|
-
return /* @__PURE__ */
|
|
13026
|
+
return /* @__PURE__ */ import_react25.default.createElement(LoadingScreen, null);
|
|
12716
13027
|
}
|
|
12717
13028
|
if (permissionStatus === "denied") {
|
|
12718
|
-
return /* @__PURE__ */
|
|
13029
|
+
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react25.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_react25.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react25.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "w-16 h-16 mx-auto" }, /* @__PURE__ */ import_react25.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", 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" }))), /* @__PURE__ */ import_react25.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react25.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_react25.default.createElement(
|
|
12719
13030
|
"button",
|
|
12720
13031
|
{
|
|
12721
13032
|
onClick: () => router.push("/dashboard/scenes"),
|
|
12722
13033
|
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"
|
|
12723
13034
|
},
|
|
12724
|
-
/* @__PURE__ */
|
|
13035
|
+
/* @__PURE__ */ import_react25.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-5 h-5" }, /* @__PURE__ */ import_react25.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
|
|
12725
13036
|
"Voltar para Scenes"
|
|
12726
13037
|
)));
|
|
12727
13038
|
}
|
|
12728
|
-
return /* @__PURE__ */
|
|
13039
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
12729
13040
|
"div",
|
|
12730
13041
|
{
|
|
12731
13042
|
ref: mountRef,
|
|
@@ -12737,7 +13048,7 @@ function XViewScene({
|
|
|
12737
13048
|
cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
|
|
12738
13049
|
}
|
|
12739
13050
|
},
|
|
12740
|
-
userPermissionRole !== "link_viewer" && /* @__PURE__ */
|
|
13051
|
+
userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react25.default.createElement(
|
|
12741
13052
|
XViewSidebar,
|
|
12742
13053
|
{
|
|
12743
13054
|
dbNodes: searchableDbNodes,
|
|
@@ -12757,7 +13068,7 @@ function XViewScene({
|
|
|
12757
13068
|
userRole: userPermissionRole
|
|
12758
13069
|
}
|
|
12759
13070
|
),
|
|
12760
|
-
creationMode.isActive && /* @__PURE__ */
|
|
13071
|
+
creationMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
12761
13072
|
InSceneCreationForm,
|
|
12762
13073
|
{
|
|
12763
13074
|
onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
|
|
@@ -12782,7 +13093,7 @@ function XViewScene({
|
|
|
12782
13093
|
availableAncestries: allAvailableAncestries
|
|
12783
13094
|
}
|
|
12784
13095
|
),
|
|
12785
|
-
versionMode.isActive && /* @__PURE__ */
|
|
13096
|
+
versionMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
12786
13097
|
InSceneVersionForm,
|
|
12787
13098
|
{
|
|
12788
13099
|
onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
|
|
@@ -12801,13 +13112,27 @@ function XViewScene({
|
|
|
12801
13112
|
availableAncestries: allAvailableAncestries
|
|
12802
13113
|
}
|
|
12803
13114
|
),
|
|
12804
|
-
|
|
13115
|
+
questMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
13116
|
+
InSceneQuestForm,
|
|
13117
|
+
{
|
|
13118
|
+
onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
|
|
13119
|
+
onCancel: () => setQuestMode({ isActive: false }),
|
|
13120
|
+
style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
|
|
13121
|
+
refEl: formRef,
|
|
13122
|
+
onOpenImageViewer: handleOpenImageViewer,
|
|
13123
|
+
onMentionClick: handleAddExistingNode,
|
|
13124
|
+
onUploadFile: upload_file_action,
|
|
13125
|
+
availableNodes: allAvailableNodes,
|
|
13126
|
+
availableAncestries: allAvailableAncestries
|
|
13127
|
+
}
|
|
13128
|
+
),
|
|
13129
|
+
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react25.default.createElement(
|
|
12805
13130
|
"div",
|
|
12806
13131
|
{
|
|
12807
13132
|
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"}`,
|
|
12808
13133
|
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
|
|
12809
13134
|
},
|
|
12810
|
-
/* @__PURE__ */
|
|
13135
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12811
13136
|
"div",
|
|
12812
13137
|
{
|
|
12813
13138
|
onPointerDown: (e) => {
|
|
@@ -12818,7 +13143,7 @@ function XViewScene({
|
|
|
12818
13143
|
title: "Arraste para redimensionar"
|
|
12819
13144
|
}
|
|
12820
13145
|
),
|
|
12821
|
-
/* @__PURE__ */
|
|
13146
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12822
13147
|
DescriptionReadModePanel,
|
|
12823
13148
|
{
|
|
12824
13149
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
@@ -12853,7 +13178,7 @@ function XViewScene({
|
|
|
12853
13178
|
}
|
|
12854
13179
|
)
|
|
12855
13180
|
),
|
|
12856
|
-
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */
|
|
13181
|
+
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react25.default.createElement(
|
|
12857
13182
|
CreateAncestryPanel,
|
|
12858
13183
|
{
|
|
12859
13184
|
ancestryMode,
|
|
@@ -12880,7 +13205,7 @@ function XViewScene({
|
|
|
12880
13205
|
onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
|
|
12881
13206
|
}
|
|
12882
13207
|
),
|
|
12883
|
-
editingAncestryRel.visible && /* @__PURE__ */
|
|
13208
|
+
editingAncestryRel.visible && /* @__PURE__ */ import_react25.default.createElement(
|
|
12884
13209
|
AncestryRelationshipPanel,
|
|
12885
13210
|
{
|
|
12886
13211
|
data: editingAncestryRel.data,
|
|
@@ -12894,7 +13219,7 @@ function XViewScene({
|
|
|
12894
13219
|
onUploadFile: upload_file_action
|
|
12895
13220
|
}
|
|
12896
13221
|
),
|
|
12897
|
-
detailsNode && /* @__PURE__ */
|
|
13222
|
+
detailsNode && /* @__PURE__ */ import_react25.default.createElement(
|
|
12898
13223
|
NodeDetailsPanel,
|
|
12899
13224
|
{
|
|
12900
13225
|
node: detailsNode,
|
|
@@ -12921,7 +13246,7 @@ function XViewScene({
|
|
|
12921
13246
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
|
|
12922
13247
|
}
|
|
12923
13248
|
),
|
|
12924
|
-
detailsLink && /* @__PURE__ */
|
|
13249
|
+
detailsLink && /* @__PURE__ */ import_react25.default.createElement(
|
|
12925
13250
|
RelationshipDetailsPanel,
|
|
12926
13251
|
{
|
|
12927
13252
|
link: detailsLink,
|
|
@@ -12935,7 +13260,7 @@ function XViewScene({
|
|
|
12935
13260
|
userRole: userPermissionRole
|
|
12936
13261
|
}
|
|
12937
13262
|
),
|
|
12938
|
-
ancestryLinkDetails && /* @__PURE__ */
|
|
13263
|
+
ancestryLinkDetails && /* @__PURE__ */ import_react25.default.createElement(
|
|
12939
13264
|
AncestryLinkDetailsPanel,
|
|
12940
13265
|
{
|
|
12941
13266
|
data: ancestryLinkDetails,
|
|
@@ -12946,7 +13271,7 @@ function XViewScene({
|
|
|
12946
13271
|
onUploadFile: upload_file_action
|
|
12947
13272
|
}
|
|
12948
13273
|
),
|
|
12949
|
-
/* @__PURE__ */
|
|
13274
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12950
13275
|
"div",
|
|
12951
13276
|
{
|
|
12952
13277
|
ref: tooltipRef,
|
|
@@ -12973,7 +13298,7 @@ function XViewScene({
|
|
|
12973
13298
|
}
|
|
12974
13299
|
}
|
|
12975
13300
|
),
|
|
12976
|
-
/* @__PURE__ */
|
|
13301
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12977
13302
|
ContextMenu,
|
|
12978
13303
|
{
|
|
12979
13304
|
data: contextMenu,
|
|
@@ -12996,7 +13321,7 @@ function XViewScene({
|
|
|
12996
13321
|
onFocusNode: handleFocusNode
|
|
12997
13322
|
}
|
|
12998
13323
|
),
|
|
12999
|
-
/* @__PURE__ */
|
|
13324
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13000
13325
|
MultiNodeContextMenu,
|
|
13001
13326
|
{
|
|
13002
13327
|
data: multiContextMenu,
|
|
@@ -13007,7 +13332,7 @@ function XViewScene({
|
|
|
13007
13332
|
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
|
|
13008
13333
|
}
|
|
13009
13334
|
),
|
|
13010
|
-
/* @__PURE__ */
|
|
13335
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13011
13336
|
RelationshipContextMenu,
|
|
13012
13337
|
{
|
|
13013
13338
|
data: relationshipMenu,
|
|
@@ -13025,8 +13350,8 @@ function XViewScene({
|
|
|
13025
13350
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
13026
13351
|
}
|
|
13027
13352
|
),
|
|
13028
|
-
/* @__PURE__ */
|
|
13029
|
-
/* @__PURE__ */
|
|
13353
|
+
/* @__PURE__ */ import_react25.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
|
|
13354
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13030
13355
|
AncestryBoard,
|
|
13031
13356
|
{
|
|
13032
13357
|
isOpen: isAncestryBoardOpen,
|
|
@@ -13039,7 +13364,7 @@ function XViewScene({
|
|
|
13039
13364
|
userRole: userPermissionRole
|
|
13040
13365
|
}
|
|
13041
13366
|
),
|
|
13042
|
-
/* @__PURE__ */
|
|
13367
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13043
13368
|
ImportParentFileModal,
|
|
13044
13369
|
{
|
|
13045
13370
|
isOpen: isImportModalOpen,
|
|
@@ -13100,11 +13425,22 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13100
13425
|
);
|
|
13101
13426
|
}
|
|
13102
13427
|
}
|
|
13428
|
+
parentData[scene_config] = {
|
|
13429
|
+
dataset_name: "Quests Internas (View)",
|
|
13430
|
+
nodes: sceneData.quest_nodes || [],
|
|
13431
|
+
links: sceneData.quest_links || []
|
|
13432
|
+
};
|
|
13103
13433
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
13104
13434
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13105
13435
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
13106
13436
|
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
13107
|
-
const validatedNodes = (sceneData.nodes || []).map((sceneNode) =>
|
|
13437
|
+
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
13438
|
+
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
13439
|
+
if (nodeTypes.includes("quest")) {
|
|
13440
|
+
return sceneNode;
|
|
13441
|
+
}
|
|
13442
|
+
return parentNodeMap.get(String(sceneNode.id));
|
|
13443
|
+
}).filter(Boolean);
|
|
13108
13444
|
const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
|
|
13109
13445
|
const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
|
|
13110
13446
|
const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
|