@lv-x-software-house/x_view 1.2.3 → 1.2.4-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +589 -332
- package/dist/index.mjs +515 -258
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/XViewScene.jsx
|
|
2
|
-
import
|
|
2
|
+
import React24, { useCallback as useCallback4, useEffect as useEffect21, useRef as useRef18, useState as useState24, useMemo as useMemo12 } from "react";
|
|
3
3
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
4
4
|
import { useSession } from "next-auth/react";
|
|
5
5
|
import CryptoJS from "crypto-js";
|
|
@@ -3097,7 +3097,7 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
|
|
|
3097
3097
|
|
|
3098
3098
|
// src/components/CustomPropertyDisplay.jsx
|
|
3099
3099
|
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
3100
|
-
import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
|
|
3100
|
+
import { FiCheck, FiX as FiX2, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
|
|
3101
3101
|
function CustomPropertyDisplay({
|
|
3102
3102
|
prop,
|
|
3103
3103
|
onUpdate,
|
|
@@ -3388,7 +3388,7 @@ function CustomPropertyDisplay({
|
|
|
3388
3388
|
default:
|
|
3389
3389
|
return /* @__PURE__ */ React3.createElement("input", { type: "text", placeholder: "Valor", value: tempProp.value, onChange: (e) => handlePropChange("value", e.target.value), className: baseInput });
|
|
3390
3390
|
}
|
|
3391
|
-
})()), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-end items-center gap-2 pt-1" }, /* @__PURE__ */ React3.createElement("button", { onClick: handleCancel, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(
|
|
3391
|
+
})()), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-end items-center gap-2 pt-1" }, /* @__PURE__ */ React3.createElement("button", { onClick: handleCancel, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(FiX2, { className: "text-red-400" })), /* @__PURE__ */ React3.createElement("button", { onClick: handleSave, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(FiCheck, { className: "text-green-400" }))));
|
|
3392
3392
|
};
|
|
3393
3393
|
const renderDisplayView = () => /* @__PURE__ */ React3.createElement("div", { className: "w-full space-y-2 text-sm" }, /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React3.createElement("p", { className: "font-semibold text-slate-200" }, prop.key), /* @__PURE__ */ React3.createElement("span", { className: "text-xs capitalize bg-slate-700/50 px-2 py-0.5 rounded text-slate-400" }, prop.type)), /* @__PURE__ */ React3.createElement("div", { className: "text-slate-300 pl-1" }, (() => {
|
|
3394
3394
|
switch (prop.type) {
|
|
@@ -7024,7 +7024,7 @@ function CreateAncestryPanel({
|
|
|
7024
7024
|
|
|
7025
7025
|
// src/components/ImageViewer.jsx
|
|
7026
7026
|
import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
|
|
7027
|
-
import { FiX as
|
|
7027
|
+
import { FiX as FiX3, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
|
|
7028
7028
|
function ImageViewer({ data, onClose }) {
|
|
7029
7029
|
var _a;
|
|
7030
7030
|
const { images = [], startIndex = 0, visible } = data;
|
|
@@ -7109,7 +7109,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
7109
7109
|
className: "absolute top-4 right-4 z-10 w-10 h-10 flex items-center justify-center bg-white/10 hover:bg-white/20 rounded-full text-white text-2xl transition-colors",
|
|
7110
7110
|
"aria-label": "Fechar"
|
|
7111
7111
|
},
|
|
7112
|
-
/* @__PURE__ */ React11.createElement(
|
|
7112
|
+
/* @__PURE__ */ React11.createElement(FiX3, null)
|
|
7113
7113
|
),
|
|
7114
7114
|
/* @__PURE__ */ React11.createElement("div", { className: "relative max-w-full max-h-full flex items-center justify-center" }, isLoading && /* @__PURE__ */ React11.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ React11.createElement("div", { className: "h-10 w-10 border-2 border-white/40 border-t-white rounded-full animate-spin" })), loadedSrc && /* @__PURE__ */ React11.createElement(
|
|
7115
7115
|
"img",
|
|
@@ -7245,7 +7245,7 @@ function ColorPicker({ color, onChange, disabled }) {
|
|
|
7245
7245
|
}
|
|
7246
7246
|
|
|
7247
7247
|
// src/components/InSceneCreationForm.jsx
|
|
7248
|
-
import { FiPlus as FiPlus3, FiMaximize2, FiX as
|
|
7248
|
+
import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX4, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun, FiChevronDown as FiChevronDown4 } from "react-icons/fi";
|
|
7249
7249
|
function InSceneCreationForm({
|
|
7250
7250
|
onSave,
|
|
7251
7251
|
onCancel,
|
|
@@ -7463,7 +7463,7 @@ function InSceneCreationForm({
|
|
|
7463
7463
|
onClick: () => handleRemoveType(index),
|
|
7464
7464
|
className: "hover:text-white transition-colors"
|
|
7465
7465
|
},
|
|
7466
|
-
/* @__PURE__ */ React13.createElement(
|
|
7466
|
+
/* @__PURE__ */ React13.createElement(FiX4, { size: 12 })
|
|
7467
7467
|
))), /* @__PURE__ */ React13.createElement(
|
|
7468
7468
|
"input",
|
|
7469
7469
|
{
|
|
@@ -7835,9 +7835,181 @@ function InSceneVersionForm({
|
|
|
7835
7835
|
));
|
|
7836
7836
|
}
|
|
7837
7837
|
|
|
7838
|
+
// src/components/InSceneQuestForm.jsx
|
|
7839
|
+
import React15, { useState as useState16, useRef as useRef12 } from "react";
|
|
7840
|
+
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget } from "react-icons/fi";
|
|
7841
|
+
var QUEST_STATUS_COLORS = {
|
|
7842
|
+
"Backlog": "#64748b",
|
|
7843
|
+
// Slate (Cinza azulado)
|
|
7844
|
+
"In Progress": "#eab308",
|
|
7845
|
+
// Yellow (Amarelo)
|
|
7846
|
+
"Review": "#a855f7",
|
|
7847
|
+
// Purple (Roxo)
|
|
7848
|
+
"Done": "#22c55e"
|
|
7849
|
+
// Green (Verde)
|
|
7850
|
+
};
|
|
7851
|
+
function InSceneQuestForm({
|
|
7852
|
+
onSave,
|
|
7853
|
+
onCancel,
|
|
7854
|
+
style,
|
|
7855
|
+
refEl,
|
|
7856
|
+
onOpenImageViewer,
|
|
7857
|
+
availableNodes = [],
|
|
7858
|
+
availableAncestries = [],
|
|
7859
|
+
onMentionClick,
|
|
7860
|
+
onUploadFile
|
|
7861
|
+
}) {
|
|
7862
|
+
const [name, setName] = useState16("");
|
|
7863
|
+
const [types, setTypes] = useState16(["quest"]);
|
|
7864
|
+
const [typeInput, setTypeInput] = useState16("");
|
|
7865
|
+
const [status, setStatus] = useState16("Backlog");
|
|
7866
|
+
const [size, setSize] = useState16("medium");
|
|
7867
|
+
const [intensity, setIntensity] = useState16(0);
|
|
7868
|
+
const [description, setDescription] = useState16("");
|
|
7869
|
+
const [customProps, setCustomProps] = useState16([]);
|
|
7870
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
|
|
7871
|
+
const propsEndRef = useRef12(null);
|
|
7872
|
+
const handleAddProp = () => {
|
|
7873
|
+
const newProp = createNewCustomProperty(customProps);
|
|
7874
|
+
setCustomProps([...customProps, newProp]);
|
|
7875
|
+
setTimeout(() => {
|
|
7876
|
+
var _a;
|
|
7877
|
+
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
7878
|
+
}, 100);
|
|
7879
|
+
};
|
|
7880
|
+
const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
|
|
7881
|
+
const handleUpdateProp = (index, updatedProp) => {
|
|
7882
|
+
const newProps = [...customProps];
|
|
7883
|
+
newProps[index] = updatedProp;
|
|
7884
|
+
setCustomProps(newProps);
|
|
7885
|
+
};
|
|
7886
|
+
const handleAddType = (newType) => {
|
|
7887
|
+
const trimmed = newType.trim().toLowerCase();
|
|
7888
|
+
if (trimmed && !types.includes(trimmed)) {
|
|
7889
|
+
setTypes([...types, trimmed]);
|
|
7890
|
+
setTypeInput("");
|
|
7891
|
+
}
|
|
7892
|
+
};
|
|
7893
|
+
const handleRemoveType = (indexToRemove) => {
|
|
7894
|
+
if (types[indexToRemove] === "quest") return;
|
|
7895
|
+
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
7896
|
+
};
|
|
7897
|
+
const handleTypeInputKeyDown = (e) => {
|
|
7898
|
+
if (e.key === "Enter") {
|
|
7899
|
+
e.preventDefault();
|
|
7900
|
+
handleAddType(typeInput);
|
|
7901
|
+
} else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
|
|
7902
|
+
handleRemoveType(types.length - 1);
|
|
7903
|
+
}
|
|
7904
|
+
};
|
|
7905
|
+
const handleSubmit = (e) => {
|
|
7906
|
+
e.preventDefault();
|
|
7907
|
+
if (!name.trim()) {
|
|
7908
|
+
alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
|
|
7909
|
+
return;
|
|
7910
|
+
}
|
|
7911
|
+
const additionalData = toObjectFromCustomProps(
|
|
7912
|
+
customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
|
|
7913
|
+
);
|
|
7914
|
+
const processedSections = processDescriptionForSave(description, []);
|
|
7915
|
+
onSave({
|
|
7916
|
+
name: name.trim(),
|
|
7917
|
+
type: types,
|
|
7918
|
+
color: QUEST_STATUS_COLORS[status],
|
|
7919
|
+
// Cor atrelada ao status
|
|
7920
|
+
status,
|
|
7921
|
+
size,
|
|
7922
|
+
intensity,
|
|
7923
|
+
description: description.trim(),
|
|
7924
|
+
description_sections: processedSections,
|
|
7925
|
+
useImageAsTexture: false,
|
|
7926
|
+
textureImageUrl: null,
|
|
7927
|
+
...additionalData
|
|
7928
|
+
});
|
|
7929
|
+
};
|
|
7930
|
+
const swallow = (e) => e.stopPropagation();
|
|
7931
|
+
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
7932
|
+
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
7933
|
+
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(
|
|
7934
|
+
"div",
|
|
7935
|
+
{
|
|
7936
|
+
ref: refEl,
|
|
7937
|
+
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",
|
|
7938
|
+
style,
|
|
7939
|
+
onPointerDown: swallow,
|
|
7940
|
+
onClick: swallow,
|
|
7941
|
+
onWheel: swallow,
|
|
7942
|
+
onContextMenu: swallow,
|
|
7943
|
+
onDoubleClick: swallow
|
|
7944
|
+
},
|
|
7945
|
+
/* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
7946
|
+
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova Tarefa / Objetivo")), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")),
|
|
7947
|
+
/* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement(
|
|
7948
|
+
"select",
|
|
7949
|
+
{
|
|
7950
|
+
value: status,
|
|
7951
|
+
onChange: (e) => setStatus(e.target.value),
|
|
7952
|
+
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",
|
|
7953
|
+
style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
|
|
7954
|
+
},
|
|
7955
|
+
/* @__PURE__ */ React15.createElement("option", { value: "Backlog" }, "Backlog"),
|
|
7956
|
+
/* @__PURE__ */ React15.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
7957
|
+
/* @__PURE__ */ React15.createElement("option", { value: "Review" }, "Review"),
|
|
7958
|
+
/* @__PURE__ */ React15.createElement("option", { value: "Done" }, "Done")
|
|
7959
|
+
)), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.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__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.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__ */ React15.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__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX, { size: 12 })))), /* @__PURE__ */ React15.createElement(
|
|
7960
|
+
"input",
|
|
7961
|
+
{
|
|
7962
|
+
type: "text",
|
|
7963
|
+
value: typeInput,
|
|
7964
|
+
onChange: (e) => setTypeInput(e.target.value),
|
|
7965
|
+
onKeyDown: handleTypeInputKeyDown,
|
|
7966
|
+
onBlur: () => {
|
|
7967
|
+
if (typeInput.trim()) handleAddType(typeInput);
|
|
7968
|
+
},
|
|
7969
|
+
className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
|
|
7970
|
+
placeholder: "Ex.: Bugfix",
|
|
7971
|
+
autoComplete: "off"
|
|
7972
|
+
}
|
|
7973
|
+
))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ React15.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__ */ React15.createElement(
|
|
7974
|
+
DescriptionDisplay,
|
|
7975
|
+
{
|
|
7976
|
+
description,
|
|
7977
|
+
savedSections: [],
|
|
7978
|
+
availableNodes,
|
|
7979
|
+
availableAncestries,
|
|
7980
|
+
onMentionClick,
|
|
7981
|
+
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
7982
|
+
}
|
|
7983
|
+
), /* @__PURE__ */ React15.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__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.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__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Cen\xE1rio (Size)"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ React15.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ React15.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__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })), /* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ React15.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React15.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__ */ React15.createElement(FiPlus5, { size: 14 }), " Adicionar")), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React15.createElement(
|
|
7984
|
+
CustomPropertyDisplay,
|
|
7985
|
+
{
|
|
7986
|
+
key: prop.id,
|
|
7987
|
+
prop,
|
|
7988
|
+
onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
|
|
7989
|
+
onRemove: () => handleRemoveProp(index),
|
|
7990
|
+
onOpenImageViewer,
|
|
7991
|
+
unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
|
|
7992
|
+
onUploadFile
|
|
7993
|
+
}
|
|
7994
|
+
)), /* @__PURE__ */ React15.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ React15.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__ */ React15.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__ */ React15.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")))
|
|
7995
|
+
), isDescriptionModalOpen && /* @__PURE__ */ React15.createElement(
|
|
7996
|
+
DescriptionEditModal,
|
|
7997
|
+
{
|
|
7998
|
+
isOpen: isDescriptionModalOpen,
|
|
7999
|
+
title: "Editar Descri\xE7\xE3o da Quest",
|
|
8000
|
+
initialValue: description,
|
|
8001
|
+
onSave: (newDescription) => setDescription(newDescription),
|
|
8002
|
+
onClose: () => setIsDescriptionModalOpen(false),
|
|
8003
|
+
availableNodes,
|
|
8004
|
+
availableAncestries,
|
|
8005
|
+
availableImages
|
|
8006
|
+
}
|
|
8007
|
+
));
|
|
8008
|
+
}
|
|
8009
|
+
|
|
7838
8010
|
// src/components/NodeDetailsPanel.jsx
|
|
7839
|
-
import
|
|
7840
|
-
import { FiPlus as
|
|
8011
|
+
import React16, { useState as useState17, useEffect as useEffect15, useRef as useRef13 } from "react";
|
|
8012
|
+
import { FiPlus as FiPlus6, FiMaximize2 as FiMaximize23, FiX as FiX5, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
|
|
7841
8013
|
function NodeDetailsPanel({
|
|
7842
8014
|
node,
|
|
7843
8015
|
onClose,
|
|
@@ -7858,27 +8030,27 @@ function NodeDetailsPanel({
|
|
|
7858
8030
|
userRole,
|
|
7859
8031
|
currentDatasetName
|
|
7860
8032
|
}) {
|
|
7861
|
-
const [name, setName] =
|
|
7862
|
-
const [types, setTypes] =
|
|
7863
|
-
const [typeInput, setTypeInput] =
|
|
7864
|
-
const [color, setColor] =
|
|
7865
|
-
const [size, setSize] =
|
|
7866
|
-
const [description, setDescription] =
|
|
7867
|
-
const [intensity, setIntensity] =
|
|
7868
|
-
const [customProps, setCustomProps] =
|
|
7869
|
-
const [showTypeSuggestions, setShowTypeSuggestions] =
|
|
7870
|
-
const [filteredTypes, setFilteredTypes] =
|
|
7871
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
7872
|
-
const [isReadMode, setIsReadMode] =
|
|
7873
|
-
const [existingSections, setExistingSections] =
|
|
7874
|
-
const [isSaving, setIsSaving] =
|
|
7875
|
-
const [isLinkCopied, setIsLinkCopied] =
|
|
7876
|
-
const [useImageAsTexture, setUseImageAsTexture] =
|
|
8033
|
+
const [name, setName] = useState17((node == null ? void 0 : node.name) ?? "");
|
|
8034
|
+
const [types, setTypes] = useState17([]);
|
|
8035
|
+
const [typeInput, setTypeInput] = useState17("");
|
|
8036
|
+
const [color, setColor] = useState17((node == null ? void 0 : node.color) ?? "#8b5cf6");
|
|
8037
|
+
const [size, setSize] = useState17((node == null ? void 0 : node.size) ?? "medium");
|
|
8038
|
+
const [description, setDescription] = useState17((node == null ? void 0 : node.description) ?? "");
|
|
8039
|
+
const [intensity, setIntensity] = useState17((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8040
|
+
const [customProps, setCustomProps] = useState17(() => extractCustomPropsFromNode(node || {}));
|
|
8041
|
+
const [showTypeSuggestions, setShowTypeSuggestions] = useState17(false);
|
|
8042
|
+
const [filteredTypes, setFilteredTypes] = useState17([]);
|
|
8043
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
|
|
8044
|
+
const [isReadMode, setIsReadMode] = useState17(false);
|
|
8045
|
+
const [existingSections, setExistingSections] = useState17((node == null ? void 0 : node.description_sections) || []);
|
|
8046
|
+
const [isSaving, setIsSaving] = useState17(false);
|
|
8047
|
+
const [isLinkCopied, setIsLinkCopied] = useState17(false);
|
|
8048
|
+
const [useImageAsTexture, setUseImageAsTexture] = useState17(() => {
|
|
7877
8049
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7878
8050
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
7879
8051
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
7880
8052
|
});
|
|
7881
|
-
const [selectedImageUrl, setSelectedImageUrl] =
|
|
8053
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState17((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
7882
8054
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
7883
8055
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
7884
8056
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -7888,8 +8060,8 @@ function NodeDetailsPanel({
|
|
|
7888
8060
|
useEffect15(() => {
|
|
7889
8061
|
setWidth(isReadMode ? 700 : 440);
|
|
7890
8062
|
}, [isReadMode, setWidth]);
|
|
7891
|
-
const prevNodeIdRef =
|
|
7892
|
-
const propsEndRef =
|
|
8063
|
+
const prevNodeIdRef = useRef13(null);
|
|
8064
|
+
const propsEndRef = useRef13(null);
|
|
7893
8065
|
const canEdit = userRole !== "viewer";
|
|
7894
8066
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
7895
8067
|
const handleImageClickFromText = (url, name2) => {
|
|
@@ -8097,7 +8269,7 @@ function NodeDetailsPanel({
|
|
|
8097
8269
|
onClose();
|
|
8098
8270
|
};
|
|
8099
8271
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
8100
|
-
return /* @__PURE__ */
|
|
8272
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
|
|
8101
8273
|
"div",
|
|
8102
8274
|
{
|
|
8103
8275
|
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"}`,
|
|
@@ -8110,7 +8282,7 @@ function NodeDetailsPanel({
|
|
|
8110
8282
|
onContextMenu: swallow,
|
|
8111
8283
|
onDoubleClick: swallow
|
|
8112
8284
|
},
|
|
8113
|
-
/* @__PURE__ */
|
|
8285
|
+
/* @__PURE__ */ React16.createElement(
|
|
8114
8286
|
"div",
|
|
8115
8287
|
{
|
|
8116
8288
|
onPointerDown: (e) => {
|
|
@@ -8121,7 +8293,7 @@ function NodeDetailsPanel({
|
|
|
8121
8293
|
title: "Arraste para redimensionar"
|
|
8122
8294
|
}
|
|
8123
8295
|
),
|
|
8124
|
-
isReadMode ? /* @__PURE__ */
|
|
8296
|
+
isReadMode ? /* @__PURE__ */ React16.createElement(
|
|
8125
8297
|
DescriptionReadModePanel,
|
|
8126
8298
|
{
|
|
8127
8299
|
title: name || (node == null ? void 0 : node.name),
|
|
@@ -8142,23 +8314,23 @@ function NodeDetailsPanel({
|
|
|
8142
8314
|
onImageClick: handleImageClickFromText,
|
|
8143
8315
|
onSaveDescription: handleSaveDescriptionInline
|
|
8144
8316
|
}
|
|
8145
|
-
) : /* @__PURE__ */
|
|
8317
|
+
) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ React16.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React16.createElement("div", null, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React16.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__ */ React16.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ React16.createElement(
|
|
8146
8318
|
"button",
|
|
8147
8319
|
{
|
|
8148
8320
|
onClick: handleCopyLink,
|
|
8149
8321
|
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
8150
8322
|
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
8151
8323
|
},
|
|
8152
|
-
isLinkCopied ? /* @__PURE__ */
|
|
8153
|
-
)), /* @__PURE__ */
|
|
8324
|
+
isLinkCopied ? /* @__PURE__ */ React16.createElement(FiCheck10, { size: 12 }) : /* @__PURE__ */ React16.createElement(FiLink5, { size: 12 })
|
|
8325
|
+
)), /* @__PURE__ */ React16.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ React16.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__ */ React16.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ React16.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__ */ React16.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__ */ React16.createElement(
|
|
8154
8326
|
"button",
|
|
8155
8327
|
{
|
|
8156
8328
|
type: "button",
|
|
8157
8329
|
onClick: () => handleRemoveType(index),
|
|
8158
8330
|
className: "hover:text-white transition-colors"
|
|
8159
8331
|
},
|
|
8160
|
-
/* @__PURE__ */
|
|
8161
|
-
))), canEdit && /* @__PURE__ */
|
|
8332
|
+
/* @__PURE__ */ React16.createElement(FiX5, { size: 12 })
|
|
8333
|
+
))), canEdit && /* @__PURE__ */ React16.createElement(
|
|
8162
8334
|
"input",
|
|
8163
8335
|
{
|
|
8164
8336
|
type: "text",
|
|
@@ -8179,7 +8351,7 @@ function NodeDetailsPanel({
|
|
|
8179
8351
|
placeholder: types.length === 0 ? "Ex.: Cliente" : "",
|
|
8180
8352
|
autoComplete: "off"
|
|
8181
8353
|
}
|
|
8182
|
-
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */
|
|
8354
|
+
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ React16.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__ */ React16.createElement(
|
|
8183
8355
|
"li",
|
|
8184
8356
|
{
|
|
8185
8357
|
key: index,
|
|
@@ -8190,7 +8362,7 @@ function NodeDetailsPanel({
|
|
|
8190
8362
|
}
|
|
8191
8363
|
},
|
|
8192
8364
|
suggestedType
|
|
8193
|
-
))))), /* @__PURE__ */
|
|
8365
|
+
))))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ React16.createElement(
|
|
8194
8366
|
"input",
|
|
8195
8367
|
{
|
|
8196
8368
|
type: "text",
|
|
@@ -8199,7 +8371,7 @@ function NodeDetailsPanel({
|
|
|
8199
8371
|
readOnly: !canEdit,
|
|
8200
8372
|
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"}`
|
|
8201
8373
|
}
|
|
8202
|
-
)), /* @__PURE__ */
|
|
8374
|
+
)), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React16.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__ */ React16.createElement(
|
|
8203
8375
|
DescriptionDisplay,
|
|
8204
8376
|
{
|
|
8205
8377
|
description,
|
|
@@ -8211,7 +8383,7 @@ function NodeDetailsPanel({
|
|
|
8211
8383
|
onImageClick: handleImageClickFromText,
|
|
8212
8384
|
onSaveDescription: handleSaveDescriptionInline
|
|
8213
8385
|
}
|
|
8214
|
-
), /* @__PURE__ */
|
|
8386
|
+
), /* @__PURE__ */ React16.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__ */ React16.createElement(
|
|
8215
8387
|
"button",
|
|
8216
8388
|
{
|
|
8217
8389
|
type: "button",
|
|
@@ -8219,8 +8391,8 @@ function NodeDetailsPanel({
|
|
|
8219
8391
|
className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
|
|
8220
8392
|
title: "Modo de Leitura"
|
|
8221
8393
|
},
|
|
8222
|
-
/* @__PURE__ */
|
|
8223
|
-
), canEdit && /* @__PURE__ */
|
|
8394
|
+
/* @__PURE__ */ React16.createElement(FiBookOpen3, { size: 14 })
|
|
8395
|
+
), canEdit && /* @__PURE__ */ React16.createElement(
|
|
8224
8396
|
"button",
|
|
8225
8397
|
{
|
|
8226
8398
|
type: "button",
|
|
@@ -8228,17 +8400,17 @@ function NodeDetailsPanel({
|
|
|
8228
8400
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8229
8401
|
title: "Editar descri\xE7\xE3o (Modo de Escrita)"
|
|
8230
8402
|
},
|
|
8231
|
-
/* @__PURE__ */
|
|
8232
|
-
)), canEdit && !description && /* @__PURE__ */
|
|
8403
|
+
/* @__PURE__ */ React16.createElement(FiEdit27, { size: 14 })
|
|
8404
|
+
)), canEdit && !description && /* @__PURE__ */ React16.createElement(
|
|
8233
8405
|
"div",
|
|
8234
8406
|
{
|
|
8235
8407
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8236
8408
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8237
8409
|
},
|
|
8238
8410
|
"Adicionar descri\xE7\xE3o..."
|
|
8239
|
-
))), /* @__PURE__ */
|
|
8411
|
+
))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
|
|
8240
8412
|
const isSelected = size === s;
|
|
8241
|
-
return /* @__PURE__ */
|
|
8413
|
+
return /* @__PURE__ */ React16.createElement(
|
|
8242
8414
|
"button",
|
|
8243
8415
|
{
|
|
8244
8416
|
key: s,
|
|
@@ -8246,10 +8418,10 @@ function NodeDetailsPanel({
|
|
|
8246
8418
|
onClick: () => canEdit && handleSizeChange(s),
|
|
8247
8419
|
className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
|
|
8248
8420
|
},
|
|
8249
|
-
/* @__PURE__ */
|
|
8250
|
-
/* @__PURE__ */
|
|
8421
|
+
/* @__PURE__ */ React16.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__ */ React16.createElement(FiCheck10, { size: 12, className: "text-white" })),
|
|
8422
|
+
/* @__PURE__ */ React16.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
|
|
8251
8423
|
);
|
|
8252
|
-
}))), /* @__PURE__ */
|
|
8424
|
+
}))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ React16.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ React16.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__ */ React16.createElement(FiCheck10, { size: 12, className: "text-white" })), /* @__PURE__ */ React16.createElement(
|
|
8253
8425
|
"input",
|
|
8254
8426
|
{
|
|
8255
8427
|
type: "checkbox",
|
|
@@ -8257,14 +8429,14 @@ function NodeDetailsPanel({
|
|
|
8257
8429
|
onChange: handleToggleImageMode,
|
|
8258
8430
|
className: "hidden"
|
|
8259
8431
|
}
|
|
8260
|
-
), /* @__PURE__ */
|
|
8432
|
+
), /* @__PURE__ */ React16.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ React16.createElement(
|
|
8261
8433
|
ColorPicker,
|
|
8262
8434
|
{
|
|
8263
8435
|
color,
|
|
8264
8436
|
onChange: handleColorChange,
|
|
8265
8437
|
disabled: !canEdit || useImageAsTexture
|
|
8266
8438
|
}
|
|
8267
|
-
), /* @__PURE__ */
|
|
8439
|
+
), /* @__PURE__ */ React16.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ React16.createElement(FiSun2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React16.createElement(
|
|
8268
8440
|
"input",
|
|
8269
8441
|
{
|
|
8270
8442
|
type: "range",
|
|
@@ -8277,7 +8449,7 @@ function NodeDetailsPanel({
|
|
|
8277
8449
|
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"}`,
|
|
8278
8450
|
title: `Intensidade do brilho: ${intensity}`
|
|
8279
8451
|
}
|
|
8280
|
-
), /* @__PURE__ */
|
|
8452
|
+
), /* @__PURE__ */ React16.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ React16.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__ */ React16.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React16.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React16.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React16.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__ */ React16.createElement(FiPlus6, { size: 14 }), " Adicionar")), /* @__PURE__ */ React16.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React16.createElement(
|
|
8281
8453
|
CustomPropertyDisplay,
|
|
8282
8454
|
{
|
|
8283
8455
|
key: prop.id,
|
|
@@ -8292,7 +8464,7 @@ function NodeDetailsPanel({
|
|
|
8292
8464
|
onUploadFile: canEdit ? onUploadFile : void 0,
|
|
8293
8465
|
readOnly: !canEdit
|
|
8294
8466
|
}
|
|
8295
|
-
)), /* @__PURE__ */
|
|
8467
|
+
)), /* @__PURE__ */ React16.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ React16.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__ */ React16.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ React16.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ React16.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__ */ React16.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__ */ React16.createElement(
|
|
8296
8468
|
"button",
|
|
8297
8469
|
{
|
|
8298
8470
|
onClick: () => handleSave(false),
|
|
@@ -8301,10 +8473,10 @@ function NodeDetailsPanel({
|
|
|
8301
8473
|
${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"}
|
|
8302
8474
|
`
|
|
8303
8475
|
},
|
|
8304
|
-
isSaving && /* @__PURE__ */
|
|
8476
|
+
isSaving && /* @__PURE__ */ React16.createElement(FiLoader2, { className: "animate-spin" }),
|
|
8305
8477
|
isSaving ? "Salvando..." : "Salvar"
|
|
8306
8478
|
)))
|
|
8307
|
-
), isDescriptionModalOpen && canEdit && /* @__PURE__ */
|
|
8479
|
+
), isDescriptionModalOpen && canEdit && /* @__PURE__ */ React16.createElement(
|
|
8308
8480
|
DescriptionEditModal,
|
|
8309
8481
|
{
|
|
8310
8482
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8324,7 +8496,7 @@ function NodeDetailsPanel({
|
|
|
8324
8496
|
}
|
|
8325
8497
|
|
|
8326
8498
|
// src/components/MultiNodeContextMenu.jsx
|
|
8327
|
-
import
|
|
8499
|
+
import React17, { useLayoutEffect as useLayoutEffect3, useRef as useRef14, useState as useState18, useEffect as useEffect16 } from "react";
|
|
8328
8500
|
function MultiNodeContextMenu({
|
|
8329
8501
|
data,
|
|
8330
8502
|
userRole,
|
|
@@ -8333,9 +8505,9 @@ function MultiNodeContextMenu({
|
|
|
8333
8505
|
onDismissOtherNodes,
|
|
8334
8506
|
onDeleteNodes
|
|
8335
8507
|
}) {
|
|
8336
|
-
const menuRef =
|
|
8337
|
-
const [menuPos, setMenuPos] =
|
|
8338
|
-
const [isConfirmingDelete, setIsConfirmingDelete] =
|
|
8508
|
+
const menuRef = useRef14(null);
|
|
8509
|
+
const [menuPos, setMenuPos] = useState18({ left: 0, top: 0 });
|
|
8510
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = useState18(false);
|
|
8339
8511
|
const ability = defineAbilityFor(userRole);
|
|
8340
8512
|
const canDelete = ability.can("delete", "Node");
|
|
8341
8513
|
useLayoutEffect3(() => {
|
|
@@ -8366,7 +8538,7 @@ function MultiNodeContextMenu({
|
|
|
8366
8538
|
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";
|
|
8367
8539
|
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";
|
|
8368
8540
|
const nodeCount = data.nodeIds.size;
|
|
8369
|
-
return /* @__PURE__ */
|
|
8541
|
+
return /* @__PURE__ */ React17.createElement(
|
|
8370
8542
|
"div",
|
|
8371
8543
|
{
|
|
8372
8544
|
ref: menuRef,
|
|
@@ -8380,28 +8552,28 @@ function MultiNodeContextMenu({
|
|
|
8380
8552
|
onContextMenu: swallow,
|
|
8381
8553
|
onDoubleClick: swallow
|
|
8382
8554
|
},
|
|
8383
|
-
/* @__PURE__ */
|
|
8384
|
-
/* @__PURE__ */
|
|
8555
|
+
/* @__PURE__ */ React17.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
|
|
8556
|
+
/* @__PURE__ */ React17.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React17.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ React17.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__ */ React17.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React17.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__ */ React17.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ React17.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ React17.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__ */ React17.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React17.createElement(
|
|
8385
8557
|
"button",
|
|
8386
8558
|
{
|
|
8387
8559
|
onClick: () => setIsConfirmingDelete(false),
|
|
8388
8560
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8389
8561
|
},
|
|
8390
8562
|
"Cancelar"
|
|
8391
|
-
), /* @__PURE__ */
|
|
8563
|
+
), /* @__PURE__ */ React17.createElement(
|
|
8392
8564
|
"button",
|
|
8393
8565
|
{
|
|
8394
8566
|
onClick: () => onDeleteNodes(data.nodeIds),
|
|
8395
8567
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
|
|
8396
8568
|
},
|
|
8397
8569
|
"Excluir"
|
|
8398
|
-
))) : /* @__PURE__ */
|
|
8570
|
+
))) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React17.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__ */ React17.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ React17.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React17.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React17.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__ */ React17.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React17.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__ */ React17.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__ */ React17.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React17.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ React17.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React17.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__ */ React17.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React17.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React17.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React17.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React17.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React17.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React17.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ React17.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__ */ React17.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React17.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__ */ React17.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React17.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React17.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
|
|
8399
8571
|
);
|
|
8400
8572
|
}
|
|
8401
8573
|
|
|
8402
8574
|
// src/components/RelationshipDetailsPanel.jsx
|
|
8403
|
-
import
|
|
8404
|
-
import { FiPlus as
|
|
8575
|
+
import React18, { useState as useState19, useEffect as useEffect17, useRef as useRef15, useMemo as useMemo9 } from "react";
|
|
8576
|
+
import { FiPlus as FiPlus7, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4 } from "react-icons/fi";
|
|
8405
8577
|
function RelationshipDetailsPanel({
|
|
8406
8578
|
link,
|
|
8407
8579
|
onClose,
|
|
@@ -8415,14 +8587,14 @@ function RelationshipDetailsPanel({
|
|
|
8415
8587
|
onUploadFile,
|
|
8416
8588
|
userRole
|
|
8417
8589
|
}) {
|
|
8418
|
-
const [name, setName] =
|
|
8419
|
-
const [description, setDescription] =
|
|
8420
|
-
const [customProps, setCustomProps] =
|
|
8421
|
-
const [existingSections, setExistingSections] =
|
|
8422
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] =
|
|
8423
|
-
const [isSaving, setIsSaving] =
|
|
8424
|
-
const [isReadMode, setIsReadMode] =
|
|
8425
|
-
const propsEndRef =
|
|
8590
|
+
const [name, setName] = useState19((link == null ? void 0 : link.name) ?? "");
|
|
8591
|
+
const [description, setDescription] = useState19((link == null ? void 0 : link.description) ?? "");
|
|
8592
|
+
const [customProps, setCustomProps] = useState19(() => extractCustomPropsFromNode(link || {}));
|
|
8593
|
+
const [existingSections, setExistingSections] = useState19((link == null ? void 0 : link.description_sections) || []);
|
|
8594
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState19(false);
|
|
8595
|
+
const [isSaving, setIsSaving] = useState19(false);
|
|
8596
|
+
const [isReadMode, setIsReadMode] = useState19(false);
|
|
8597
|
+
const propsEndRef = useRef15(null);
|
|
8426
8598
|
const canEdit = useMemo9(() => {
|
|
8427
8599
|
const ability = defineAbilityFor(userRole);
|
|
8428
8600
|
return ability.can("update", "Connection");
|
|
@@ -8502,7 +8674,7 @@ function RelationshipDetailsPanel({
|
|
|
8502
8674
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
8503
8675
|
}
|
|
8504
8676
|
};
|
|
8505
|
-
return /* @__PURE__ */
|
|
8677
|
+
return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement(
|
|
8506
8678
|
"div",
|
|
8507
8679
|
{
|
|
8508
8680
|
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
|
|
@@ -8517,7 +8689,7 @@ function RelationshipDetailsPanel({
|
|
|
8517
8689
|
onContextMenu: swallow,
|
|
8518
8690
|
onDoubleClick: swallow
|
|
8519
8691
|
},
|
|
8520
|
-
isReadMode ? /* @__PURE__ */
|
|
8692
|
+
isReadMode ? /* @__PURE__ */ React18.createElement(
|
|
8521
8693
|
DescriptionReadModePanel,
|
|
8522
8694
|
{
|
|
8523
8695
|
title: name || "Rela\xE7\xE3o",
|
|
@@ -8538,7 +8710,7 @@ function RelationshipDetailsPanel({
|
|
|
8538
8710
|
onImageClick: handleImageClickFromText,
|
|
8539
8711
|
onSaveDescription: handleSaveDescriptionInline
|
|
8540
8712
|
}
|
|
8541
|
-
) : /* @__PURE__ */
|
|
8713
|
+
) : /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ React18.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React18.createElement("div", null, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React18.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__ */ React18.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ React18.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ React18.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__ */ React18.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React18.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React18.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ React18.createElement(
|
|
8542
8714
|
"input",
|
|
8543
8715
|
{
|
|
8544
8716
|
type: "text",
|
|
@@ -8550,7 +8722,7 @@ function RelationshipDetailsPanel({
|
|
|
8550
8722
|
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
8551
8723
|
`
|
|
8552
8724
|
}
|
|
8553
|
-
)), /* @__PURE__ */
|
|
8725
|
+
)), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React18.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React18.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__ */ React18.createElement(
|
|
8554
8726
|
DescriptionDisplay,
|
|
8555
8727
|
{
|
|
8556
8728
|
description,
|
|
@@ -8562,7 +8734,7 @@ function RelationshipDetailsPanel({
|
|
|
8562
8734
|
onImageClick: handleImageClickFromText,
|
|
8563
8735
|
onSaveDescription: handleSaveDescriptionInline
|
|
8564
8736
|
}
|
|
8565
|
-
), /* @__PURE__ */
|
|
8737
|
+
), /* @__PURE__ */ React18.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__ */ React18.createElement(
|
|
8566
8738
|
"button",
|
|
8567
8739
|
{
|
|
8568
8740
|
type: "button",
|
|
@@ -8570,8 +8742,8 @@ function RelationshipDetailsPanel({
|
|
|
8570
8742
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
|
|
8571
8743
|
title: "Modo de Leitura"
|
|
8572
8744
|
},
|
|
8573
|
-
/* @__PURE__ */
|
|
8574
|
-
), canEdit && /* @__PURE__ */
|
|
8745
|
+
/* @__PURE__ */ React18.createElement(FiBookOpen4, { size: 14 })
|
|
8746
|
+
), canEdit && /* @__PURE__ */ React18.createElement(
|
|
8575
8747
|
"button",
|
|
8576
8748
|
{
|
|
8577
8749
|
type: "button",
|
|
@@ -8579,15 +8751,15 @@ function RelationshipDetailsPanel({
|
|
|
8579
8751
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8580
8752
|
title: "Editar descri\xE7\xE3o"
|
|
8581
8753
|
},
|
|
8582
|
-
/* @__PURE__ */
|
|
8583
|
-
)), !description && canEdit && /* @__PURE__ */
|
|
8754
|
+
/* @__PURE__ */ React18.createElement(FiEdit28, { size: 14 })
|
|
8755
|
+
)), !description && canEdit && /* @__PURE__ */ React18.createElement(
|
|
8584
8756
|
"div",
|
|
8585
8757
|
{
|
|
8586
8758
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8587
8759
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8588
8760
|
},
|
|
8589
8761
|
"Adicionar descri\xE7\xE3o..."
|
|
8590
|
-
))), /* @__PURE__ */
|
|
8762
|
+
))), /* @__PURE__ */ React18.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ React18.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__ */ React18.createElement(FiPlus7, { size: 14 }), " Adicionar")), /* @__PURE__ */ React18.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ React18.createElement(
|
|
8591
8763
|
CustomPropertyDisplay,
|
|
8592
8764
|
{
|
|
8593
8765
|
key: prop.id,
|
|
@@ -8599,7 +8771,7 @@ function RelationshipDetailsPanel({
|
|
|
8599
8771
|
onUploadFile,
|
|
8600
8772
|
disabled: !canEdit
|
|
8601
8773
|
}
|
|
8602
|
-
)), /* @__PURE__ */
|
|
8774
|
+
)), /* @__PURE__ */ React18.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ React18.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__ */ React18.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__ */ React18.createElement(
|
|
8603
8775
|
"button",
|
|
8604
8776
|
{
|
|
8605
8777
|
onClick: () => handleSave(false),
|
|
@@ -8608,10 +8780,10 @@ function RelationshipDetailsPanel({
|
|
|
8608
8780
|
${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"}
|
|
8609
8781
|
`
|
|
8610
8782
|
},
|
|
8611
|
-
isSaving && /* @__PURE__ */
|
|
8783
|
+
isSaving && /* @__PURE__ */ React18.createElement(FiLoader3, { className: "animate-spin" }),
|
|
8612
8784
|
isSaving ? "Salvando..." : "Salvar"
|
|
8613
8785
|
)))
|
|
8614
|
-
), isDescriptionModalOpen && /* @__PURE__ */
|
|
8786
|
+
), isDescriptionModalOpen && /* @__PURE__ */ React18.createElement(
|
|
8615
8787
|
DescriptionEditModal,
|
|
8616
8788
|
{
|
|
8617
8789
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8632,7 +8804,7 @@ function RelationshipDetailsPanel({
|
|
|
8632
8804
|
}
|
|
8633
8805
|
|
|
8634
8806
|
// src/components/RelationshipContextMenu.jsx
|
|
8635
|
-
import
|
|
8807
|
+
import React19, { useLayoutEffect as useLayoutEffect4, useRef as useRef16, useState as useState20, useEffect as useEffect18, useMemo as useMemo10 } from "react";
|
|
8636
8808
|
function RelationshipContextMenu({
|
|
8637
8809
|
data,
|
|
8638
8810
|
userRole,
|
|
@@ -8642,9 +8814,9 @@ function RelationshipContextMenu({
|
|
|
8642
8814
|
onDelete,
|
|
8643
8815
|
onClose
|
|
8644
8816
|
}) {
|
|
8645
|
-
const menuRef =
|
|
8646
|
-
const [menuPos, setMenuPos] =
|
|
8647
|
-
const [isConfirmingDelete, setIsConfirmingDelete] =
|
|
8817
|
+
const menuRef = useRef16(null);
|
|
8818
|
+
const [menuPos, setMenuPos] = useState20({ left: 0, top: 0 });
|
|
8819
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = useState20(false);
|
|
8648
8820
|
const ability = useMemo10(() => defineAbilityFor(userRole), [userRole]);
|
|
8649
8821
|
const sourceName = useMemo10(
|
|
8650
8822
|
() => {
|
|
@@ -8689,7 +8861,7 @@ function RelationshipContextMenu({
|
|
|
8689
8861
|
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";
|
|
8690
8862
|
const canUpdate = ability.can("update", "Connection");
|
|
8691
8863
|
const canDelete = ability.can("delete", "Connection");
|
|
8692
|
-
return /* @__PURE__ */
|
|
8864
|
+
return /* @__PURE__ */ React19.createElement(
|
|
8693
8865
|
"div",
|
|
8694
8866
|
{
|
|
8695
8867
|
ref: menuRef,
|
|
@@ -8703,29 +8875,29 @@ function RelationshipContextMenu({
|
|
|
8703
8875
|
onContextMenu: swallow,
|
|
8704
8876
|
onDoubleClick: swallow
|
|
8705
8877
|
},
|
|
8706
|
-
/* @__PURE__ */
|
|
8707
|
-
/* @__PURE__ */
|
|
8878
|
+
/* @__PURE__ */ React19.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
|
|
8879
|
+
/* @__PURE__ */ React19.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ React19.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ React19.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__ */ React19.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React19.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ React19.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ React19.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ React19.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ React19.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ React19.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ React19.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ React19.createElement("strong", null, targetName), ".")), /* @__PURE__ */ React19.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ React19.createElement(
|
|
8708
8880
|
"button",
|
|
8709
8881
|
{
|
|
8710
8882
|
onClick: () => setIsConfirmingDelete(false),
|
|
8711
8883
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8712
8884
|
},
|
|
8713
8885
|
"Cancelar"
|
|
8714
|
-
), /* @__PURE__ */
|
|
8886
|
+
), /* @__PURE__ */ React19.createElement(
|
|
8715
8887
|
"button",
|
|
8716
8888
|
{
|
|
8717
8889
|
onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
|
|
8718
8890
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
|
|
8719
8891
|
},
|
|
8720
8892
|
"Excluir"
|
|
8721
|
-
))) : /* @__PURE__ */
|
|
8893
|
+
))) : /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React19.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__ */ React19.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
|
|
8722
8894
|
"button",
|
|
8723
8895
|
{
|
|
8724
8896
|
onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
|
|
8725
8897
|
className: baseButtonClass,
|
|
8726
8898
|
title: "Desconectar ponta ligada ao Source"
|
|
8727
8899
|
},
|
|
8728
|
-
/* @__PURE__ */
|
|
8900
|
+
/* @__PURE__ */ React19.createElement(
|
|
8729
8901
|
"svg",
|
|
8730
8902
|
{
|
|
8731
8903
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8738,18 +8910,18 @@ function RelationshipContextMenu({
|
|
|
8738
8910
|
strokeLinecap: "round",
|
|
8739
8911
|
strokeLinejoin: "round"
|
|
8740
8912
|
},
|
|
8741
|
-
/* @__PURE__ */
|
|
8742
|
-
/* @__PURE__ */
|
|
8913
|
+
/* @__PURE__ */ React19.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" }),
|
|
8914
|
+
/* @__PURE__ */ React19.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" })
|
|
8743
8915
|
),
|
|
8744
|
-
/* @__PURE__ */
|
|
8745
|
-
), /* @__PURE__ */
|
|
8916
|
+
/* @__PURE__ */ React19.createElement("span", null, "Desconectar Source (", sourceName, ")")
|
|
8917
|
+
), /* @__PURE__ */ React19.createElement(
|
|
8746
8918
|
"button",
|
|
8747
8919
|
{
|
|
8748
8920
|
onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
|
|
8749
8921
|
className: baseButtonClass,
|
|
8750
8922
|
title: "Desconectar ponta ligada ao Target"
|
|
8751
8923
|
},
|
|
8752
|
-
/* @__PURE__ */
|
|
8924
|
+
/* @__PURE__ */ React19.createElement(
|
|
8753
8925
|
"svg",
|
|
8754
8926
|
{
|
|
8755
8927
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8762,21 +8934,21 @@ function RelationshipContextMenu({
|
|
|
8762
8934
|
strokeLinecap: "round",
|
|
8763
8935
|
strokeLinejoin: "round"
|
|
8764
8936
|
},
|
|
8765
|
-
/* @__PURE__ */
|
|
8766
|
-
/* @__PURE__ */
|
|
8767
|
-
/* @__PURE__ */
|
|
8768
|
-
/* @__PURE__ */
|
|
8769
|
-
/* @__PURE__ */
|
|
8937
|
+
/* @__PURE__ */ React19.createElement("polyline", { points: "16 3 21 3 21 8" }),
|
|
8938
|
+
/* @__PURE__ */ React19.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
|
|
8939
|
+
/* @__PURE__ */ React19.createElement("polyline", { points: "21 16 21 21 16 21" }),
|
|
8940
|
+
/* @__PURE__ */ React19.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
|
|
8941
|
+
/* @__PURE__ */ React19.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
|
|
8770
8942
|
),
|
|
8771
|
-
/* @__PURE__ */
|
|
8772
|
-
), /* @__PURE__ */
|
|
8943
|
+
/* @__PURE__ */ React19.createElement("span", null, "Desconectar Target (", targetName, ")")
|
|
8944
|
+
), /* @__PURE__ */ React19.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ React19.createElement(
|
|
8773
8945
|
"button",
|
|
8774
8946
|
{
|
|
8775
8947
|
onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
|
|
8776
8948
|
className: baseButtonClass,
|
|
8777
8949
|
title: "Abrir detalhes da rela\xE7\xE3o"
|
|
8778
8950
|
},
|
|
8779
|
-
/* @__PURE__ */
|
|
8951
|
+
/* @__PURE__ */ React19.createElement(
|
|
8780
8952
|
"svg",
|
|
8781
8953
|
{
|
|
8782
8954
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8789,19 +8961,19 @@ function RelationshipContextMenu({
|
|
|
8789
8961
|
strokeLinecap: "round",
|
|
8790
8962
|
strokeLinejoin: "round"
|
|
8791
8963
|
},
|
|
8792
|
-
/* @__PURE__ */
|
|
8793
|
-
/* @__PURE__ */
|
|
8794
|
-
/* @__PURE__ */
|
|
8964
|
+
/* @__PURE__ */ React19.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
8965
|
+
/* @__PURE__ */ React19.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
8966
|
+
/* @__PURE__ */ React19.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
|
|
8795
8967
|
),
|
|
8796
|
-
/* @__PURE__ */
|
|
8797
|
-
), canDelete && /* @__PURE__ */
|
|
8968
|
+
/* @__PURE__ */ React19.createElement("span", null, "Abrir Detalhes")
|
|
8969
|
+
), canDelete && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ React19.createElement(
|
|
8798
8970
|
"button",
|
|
8799
8971
|
{
|
|
8800
8972
|
onClick: () => setIsConfirmingDelete(true),
|
|
8801
8973
|
className: dangerButtonClass,
|
|
8802
8974
|
title: "Excluir esta conex\xE3o"
|
|
8803
8975
|
},
|
|
8804
|
-
/* @__PURE__ */
|
|
8976
|
+
/* @__PURE__ */ React19.createElement(
|
|
8805
8977
|
"svg",
|
|
8806
8978
|
{
|
|
8807
8979
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8814,19 +8986,19 @@ function RelationshipContextMenu({
|
|
|
8814
8986
|
strokeLinecap: "round",
|
|
8815
8987
|
strokeLinejoin: "round"
|
|
8816
8988
|
},
|
|
8817
|
-
/* @__PURE__ */
|
|
8818
|
-
/* @__PURE__ */
|
|
8819
|
-
/* @__PURE__ */
|
|
8820
|
-
/* @__PURE__ */
|
|
8821
|
-
/* @__PURE__ */
|
|
8989
|
+
/* @__PURE__ */ React19.createElement("polyline", { points: "3 6 5 6 21 6" }),
|
|
8990
|
+
/* @__PURE__ */ React19.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
|
|
8991
|
+
/* @__PURE__ */ React19.createElement("path", { d: "M10 11v6" }),
|
|
8992
|
+
/* @__PURE__ */ React19.createElement("path", { d: "M14 11v6" }),
|
|
8993
|
+
/* @__PURE__ */ React19.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
|
|
8822
8994
|
),
|
|
8823
|
-
/* @__PURE__ */
|
|
8995
|
+
/* @__PURE__ */ React19.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
|
|
8824
8996
|
)))))
|
|
8825
8997
|
);
|
|
8826
8998
|
}
|
|
8827
8999
|
|
|
8828
9000
|
// src/components/LoadingScreen.jsx
|
|
8829
|
-
import
|
|
9001
|
+
import React20 from "react";
|
|
8830
9002
|
var styles = {
|
|
8831
9003
|
loadingOverlay: {
|
|
8832
9004
|
position: "fixed",
|
|
@@ -8858,11 +9030,11 @@ var styles = {
|
|
|
8858
9030
|
`
|
|
8859
9031
|
};
|
|
8860
9032
|
function LoadingScreen() {
|
|
8861
|
-
return /* @__PURE__ */
|
|
9033
|
+
return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement("style", null, styles.keyframes), /* @__PURE__ */ React20.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ React20.createElement("div", { style: styles.spinner })));
|
|
8862
9034
|
}
|
|
8863
9035
|
|
|
8864
9036
|
// src/components/ImportParentFileModal.jsx
|
|
8865
|
-
import
|
|
9037
|
+
import React21, { useEffect as useEffect19, useState as useState21 } from "react";
|
|
8866
9038
|
function ImportParentFileModal({
|
|
8867
9039
|
isOpen,
|
|
8868
9040
|
onClose,
|
|
@@ -8873,11 +9045,11 @@ function ImportParentFileModal({
|
|
|
8873
9045
|
onFetchAvailableFiles,
|
|
8874
9046
|
currentViewName
|
|
8875
9047
|
}) {
|
|
8876
|
-
const [activeTab, setActiveTab] =
|
|
8877
|
-
const [availableDbs, setAvailableDbs] =
|
|
8878
|
-
const [availableViews, setAvailableViews] =
|
|
8879
|
-
const [selectedItem, setSelectedItem] =
|
|
8880
|
-
const [isLoading, setIsLoading] =
|
|
9048
|
+
const [activeTab, setActiveTab] = useState21("databases");
|
|
9049
|
+
const [availableDbs, setAvailableDbs] = useState21([]);
|
|
9050
|
+
const [availableViews, setAvailableViews] = useState21([]);
|
|
9051
|
+
const [selectedItem, setSelectedItem] = useState21(null);
|
|
9052
|
+
const [isLoading, setIsLoading] = useState21(false);
|
|
8881
9053
|
useEffect19(() => {
|
|
8882
9054
|
if (isOpen && session && onFetchAvailableFiles) {
|
|
8883
9055
|
const fetchData = async () => {
|
|
@@ -8943,13 +9115,13 @@ function ImportParentFileModal({
|
|
|
8943
9115
|
const swallow = (e) => e.stopPropagation();
|
|
8944
9116
|
const currentList = activeTab === "databases" ? availableDbs : availableViews;
|
|
8945
9117
|
const emptyMessage = activeTab === "databases" ? "Nenhum novo arquivo parent dispon\xEDvel." : "Nenhuma view dispon\xEDvel para importa\xE7\xE3o.";
|
|
8946
|
-
return /* @__PURE__ */
|
|
9118
|
+
return /* @__PURE__ */ React21.createElement(
|
|
8947
9119
|
"div",
|
|
8948
9120
|
{
|
|
8949
9121
|
className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
|
|
8950
9122
|
onClick: onClose
|
|
8951
9123
|
},
|
|
8952
|
-
/* @__PURE__ */
|
|
9124
|
+
/* @__PURE__ */ React21.createElement(
|
|
8953
9125
|
"div",
|
|
8954
9126
|
{
|
|
8955
9127
|
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]",
|
|
@@ -8961,14 +9133,14 @@ function ImportParentFileModal({
|
|
|
8961
9133
|
onContextMenu: swallow,
|
|
8962
9134
|
onDoubleClick: swallow
|
|
8963
9135
|
},
|
|
8964
|
-
/* @__PURE__ */
|
|
9136
|
+
/* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ React21.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ React21.createElement(
|
|
8965
9137
|
"button",
|
|
8966
9138
|
{
|
|
8967
9139
|
onClick: onClose,
|
|
8968
9140
|
className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8969
9141
|
title: "Fechar"
|
|
8970
9142
|
},
|
|
8971
|
-
/* @__PURE__ */
|
|
9143
|
+
/* @__PURE__ */ React21.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React21.createElement(
|
|
8972
9144
|
"path",
|
|
8973
9145
|
{
|
|
8974
9146
|
fillRule: "evenodd",
|
|
@@ -8977,14 +9149,14 @@ function ImportParentFileModal({
|
|
|
8977
9149
|
}
|
|
8978
9150
|
))
|
|
8979
9151
|
)),
|
|
8980
|
-
/* @__PURE__ */
|
|
9152
|
+
/* @__PURE__ */ React21.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ React21.createElement(
|
|
8981
9153
|
"button",
|
|
8982
9154
|
{
|
|
8983
9155
|
onClick: () => setActiveTab("databases"),
|
|
8984
9156
|
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"}`
|
|
8985
9157
|
},
|
|
8986
9158
|
"Arquivos Parent"
|
|
8987
|
-
), /* @__PURE__ */
|
|
9159
|
+
), /* @__PURE__ */ React21.createElement(
|
|
8988
9160
|
"button",
|
|
8989
9161
|
{
|
|
8990
9162
|
onClick: () => setActiveTab("views"),
|
|
@@ -8992,24 +9164,24 @@ function ImportParentFileModal({
|
|
|
8992
9164
|
},
|
|
8993
9165
|
"Views (Ancestralidades)"
|
|
8994
9166
|
)),
|
|
8995
|
-
/* @__PURE__ */
|
|
9167
|
+
/* @__PURE__ */ React21.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ React21.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ React21.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ React21.createElement(
|
|
8996
9168
|
"div",
|
|
8997
9169
|
{
|
|
8998
9170
|
key: item.id,
|
|
8999
9171
|
onClick: () => setSelectedItem(item),
|
|
9000
9172
|
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"}`
|
|
9001
9173
|
},
|
|
9002
|
-
/* @__PURE__ */
|
|
9003
|
-
item.description && /* @__PURE__ */
|
|
9004
|
-
)) : /* @__PURE__ */
|
|
9005
|
-
/* @__PURE__ */
|
|
9174
|
+
/* @__PURE__ */ React21.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React21.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ React21.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
|
|
9175
|
+
item.description && /* @__PURE__ */ React21.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
|
|
9176
|
+
)) : /* @__PURE__ */ React21.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
|
|
9177
|
+
/* @__PURE__ */ React21.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__ */ React21.createElement(
|
|
9006
9178
|
"button",
|
|
9007
9179
|
{
|
|
9008
9180
|
onClick: onClose,
|
|
9009
9181
|
className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm text-slate-300"
|
|
9010
9182
|
},
|
|
9011
9183
|
"Cancelar"
|
|
9012
|
-
), /* @__PURE__ */
|
|
9184
|
+
), /* @__PURE__ */ React21.createElement(
|
|
9013
9185
|
"button",
|
|
9014
9186
|
{
|
|
9015
9187
|
onClick: handleConfirm,
|
|
@@ -9023,7 +9195,7 @@ function ImportParentFileModal({
|
|
|
9023
9195
|
}
|
|
9024
9196
|
|
|
9025
9197
|
// src/components/AncestryLinkDetailsPanel.jsx
|
|
9026
|
-
import
|
|
9198
|
+
import React22, { useState as useState22 } from "react";
|
|
9027
9199
|
import { FiBookOpen as FiBookOpen5 } from "react-icons/fi";
|
|
9028
9200
|
function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
|
|
9029
9201
|
var _a, _b, _c, _d;
|
|
@@ -9033,21 +9205,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9033
9205
|
const customProps = extractCustomPropsFromNode(relationshipData);
|
|
9034
9206
|
const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
|
|
9035
9207
|
const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
|
|
9036
|
-
const [isReadMode, setIsReadMode] =
|
|
9208
|
+
const [isReadMode, setIsReadMode] = useState22(false);
|
|
9037
9209
|
const swallow = (e) => e.stopPropagation();
|
|
9038
9210
|
const handleImageClickFromText = (url, name) => {
|
|
9039
9211
|
if (onOpenImageViewer) {
|
|
9040
9212
|
onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
|
|
9041
9213
|
}
|
|
9042
9214
|
};
|
|
9043
|
-
return /* @__PURE__ */
|
|
9215
|
+
return /* @__PURE__ */ React22.createElement(
|
|
9044
9216
|
"div",
|
|
9045
9217
|
{
|
|
9046
9218
|
className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
|
|
9047
9219
|
onClick: onClose,
|
|
9048
9220
|
onPointerDown: swallow
|
|
9049
9221
|
},
|
|
9050
|
-
/* @__PURE__ */
|
|
9222
|
+
/* @__PURE__ */ React22.createElement(
|
|
9051
9223
|
"div",
|
|
9052
9224
|
{
|
|
9053
9225
|
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
|
|
@@ -9055,7 +9227,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9055
9227
|
`,
|
|
9056
9228
|
onClick: swallow
|
|
9057
9229
|
},
|
|
9058
|
-
isReadMode ? /* @__PURE__ */
|
|
9230
|
+
isReadMode ? /* @__PURE__ */ React22.createElement(
|
|
9059
9231
|
DescriptionReadModePanel,
|
|
9060
9232
|
{
|
|
9061
9233
|
title: `${sourceName} \u2794 ${targetName}`,
|
|
@@ -9067,15 +9239,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9067
9239
|
onMentionClick,
|
|
9068
9240
|
onImageClick: handleImageClickFromText
|
|
9069
9241
|
}
|
|
9070
|
-
) : /* @__PURE__ */
|
|
9242
|
+
) : /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ React22.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React22.createElement("div", null, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React22.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__ */ React22.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ React22.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ React22.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ React22.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ React22.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ React22.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__ */ React22.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ React22.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React22.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React22.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ React22.createElement(
|
|
9071
9243
|
"button",
|
|
9072
9244
|
{
|
|
9073
9245
|
onClick: () => setIsReadMode(true),
|
|
9074
9246
|
className: "p-1 text-slate-400 hover:text-white transition-colors",
|
|
9075
9247
|
title: "Modo de Leitura"
|
|
9076
9248
|
},
|
|
9077
|
-
/* @__PURE__ */
|
|
9078
|
-
)), /* @__PURE__ */
|
|
9249
|
+
/* @__PURE__ */ React22.createElement(FiBookOpen5, { size: 14 })
|
|
9250
|
+
)), /* @__PURE__ */ React22.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ React22.createElement(
|
|
9079
9251
|
DescriptionDisplay,
|
|
9080
9252
|
{
|
|
9081
9253
|
description,
|
|
@@ -9084,7 +9256,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9084
9256
|
onMentionClick,
|
|
9085
9257
|
onImageClick: handleImageClickFromText
|
|
9086
9258
|
}
|
|
9087
|
-
))), customProps.length > 0 && /* @__PURE__ */
|
|
9259
|
+
))), customProps.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React22.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ React22.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ React22.createElement(
|
|
9088
9260
|
CustomPropertyDisplay,
|
|
9089
9261
|
{
|
|
9090
9262
|
key: prop.id,
|
|
@@ -9093,25 +9265,25 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9093
9265
|
onOpenImageViewer,
|
|
9094
9266
|
onUploadFile
|
|
9095
9267
|
}
|
|
9096
|
-
)))), !description && customProps.length === 0 && /* @__PURE__ */
|
|
9268
|
+
)))), !description && customProps.length === 0 && /* @__PURE__ */ React22.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__ */ React22.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".')))
|
|
9097
9269
|
)
|
|
9098
9270
|
);
|
|
9099
9271
|
}
|
|
9100
9272
|
|
|
9101
9273
|
// src/components/AncestryBoard.jsx
|
|
9102
|
-
import
|
|
9274
|
+
import React23, { useState as useState23, useMemo as useMemo11, useEffect as useEffect20, useRef as useRef17 } from "react";
|
|
9103
9275
|
import {
|
|
9104
9276
|
FiSearch as FiSearch4,
|
|
9105
9277
|
FiLayers as FiLayers6,
|
|
9106
9278
|
FiCornerUpRight as FiCornerUpRight4,
|
|
9107
9279
|
FiPlay,
|
|
9108
|
-
FiPlus as
|
|
9280
|
+
FiPlus as FiPlus8,
|
|
9109
9281
|
FiTrash2 as FiTrash23,
|
|
9110
9282
|
FiArrowLeft as FiArrowLeft3,
|
|
9111
9283
|
FiArrowRight,
|
|
9112
9284
|
FiCheckCircle,
|
|
9113
9285
|
FiLoader as FiLoader4,
|
|
9114
|
-
FiX as
|
|
9286
|
+
FiX as FiX6,
|
|
9115
9287
|
FiAlertTriangle
|
|
9116
9288
|
} from "react-icons/fi";
|
|
9117
9289
|
var GroupItem = ({
|
|
@@ -9133,7 +9305,7 @@ var GroupItem = ({
|
|
|
9133
9305
|
}) => {
|
|
9134
9306
|
const canIndent = index > 0;
|
|
9135
9307
|
const isPickingForThisGroup = pickingGroupId === group.id;
|
|
9136
|
-
const textareaRef =
|
|
9308
|
+
const textareaRef = useRef17(null);
|
|
9137
9309
|
const adjustHeight = () => {
|
|
9138
9310
|
const textarea = textareaRef.current;
|
|
9139
9311
|
if (textarea) {
|
|
@@ -9144,10 +9316,10 @@ var GroupItem = ({
|
|
|
9144
9316
|
useEffect20(() => {
|
|
9145
9317
|
adjustHeight();
|
|
9146
9318
|
}, [group.text]);
|
|
9147
|
-
return /* @__PURE__ */
|
|
9319
|
+
return /* @__PURE__ */ React23.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__ */ React23.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.createElement(FiPlay, { size: 10, className: "ml-0.5 fill-current" })
|
|
9189
9361
|
)
|
|
9190
|
-
) : /* @__PURE__ */
|
|
9191
|
-
/* @__PURE__ */
|
|
9192
|
-
canEdit && /* @__PURE__ */
|
|
9362
|
+
) : /* @__PURE__ */ React23.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React23.createElement(FiAlertTriangle, { size: 10 })),
|
|
9363
|
+
/* @__PURE__ */ React23.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
|
|
9364
|
+
canEdit && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ React23.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__ */ React23.createElement(FiX6, { size: 12 })
|
|
9200
9372
|
))
|
|
9201
9373
|
);
|
|
9202
|
-
})), canEdit && /* @__PURE__ */
|
|
9374
|
+
})), canEdit && /* @__PURE__ */ React23.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__ */ React23.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React23.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__ */ React23.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React23.createElement(FiSearch4, { size: 12 }),
|
|
9213
9385
|
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
9214
|
-
), /* @__PURE__ */
|
|
9386
|
+
), /* @__PURE__ */ React23.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__ */ React23.createElement(FiPlus8, { size: 14 })
|
|
9394
|
+
)), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React23.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__ */ React23.createElement(FiArrowRight, { size: 14 })
|
|
9403
|
+
), /* @__PURE__ */ React23.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__ */ React23.createElement(FiArrowLeft3, { size: 14 })
|
|
9411
|
+
), /* @__PURE__ */ React23.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React23.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__ */ React23.createElement(FiTrash23, { size: 14 })
|
|
9419
|
+
)))), group.children && group.children.length > 0 && /* @__PURE__ */ React23.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React23.createElement(
|
|
9248
9420
|
GroupItem,
|
|
9249
9421
|
{
|
|
9250
9422
|
key: childGroup.id,
|
|
@@ -9276,11 +9448,11 @@ function AncestryBoard({
|
|
|
9276
9448
|
userRole
|
|
9277
9449
|
// [NOVO] Recebe a role do usuário
|
|
9278
9450
|
}) {
|
|
9279
|
-
const [searchTerm, setSearchTerm] =
|
|
9280
|
-
const [groups, setGroups] =
|
|
9281
|
-
const [isLoaded, setIsLoaded] =
|
|
9282
|
-
const [pickingGroupId, setPickingGroupId] =
|
|
9283
|
-
const [saveStatus, setSaveStatus] =
|
|
9451
|
+
const [searchTerm, setSearchTerm] = useState23("");
|
|
9452
|
+
const [groups, setGroups] = useState23([]);
|
|
9453
|
+
const [isLoaded, setIsLoaded] = useState23(false);
|
|
9454
|
+
const [pickingGroupId, setPickingGroupId] = useState23(null);
|
|
9455
|
+
const [saveStatus, setSaveStatus] = useState23("idle");
|
|
9284
9456
|
const canEdit = useMemo11(() => {
|
|
9285
9457
|
return userRole !== "viewer";
|
|
9286
9458
|
}, [userRole]);
|
|
@@ -9488,27 +9660,27 @@ function AncestryBoard({
|
|
|
9488
9660
|
});
|
|
9489
9661
|
};
|
|
9490
9662
|
if (!isOpen) return null;
|
|
9491
|
-
return /* @__PURE__ */
|
|
9663
|
+
return /* @__PURE__ */ React23.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__ */ React23.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__ */ React23.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React23.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React23.createElement(FiLayers6, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React23.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React23.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__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(FiLoader4, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React23.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React23.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ React23.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ React23.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__ */ React23.createElement(FiPlus8, { size: 14, className: "text-indigo-400" }),
|
|
9682
|
+
/* @__PURE__ */ React23.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
|
|
9683
|
+
), /* @__PURE__ */ React23.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__ */ React23.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ React23.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__ */ React23.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ React23.createElement("div", { className: "relative group" }, /* @__PURE__ */ React23.createElement(FiSearch4, { 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__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.createElement(FiPlus8, { size: 16 }) : /* @__PURE__ */ React23.createElement(FiLayers6, { size: 14 })),
|
|
9727
|
+
/* @__PURE__ */ React23.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React23.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React23.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__ */ React23.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__ */ React23.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__ */ React23.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React23.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ React23.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
9728
|
+
!isPicking && /* @__PURE__ */ React23.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__ */ React23.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React23.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
|
|
9567
9739
|
)
|
|
9568
9740
|
);
|
|
9569
|
-
}))), /* @__PURE__ */
|
|
9741
|
+
}))), /* @__PURE__ */ React23.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React23.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React23.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__ */ React23.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React23.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React23.createElement(React23.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React23.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React23.createElement(React23.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React23.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__ */ React23.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__ */ React23.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ React23.createElement("span", null, groups.length, " grupos raiz"))
|
|
9590
9762
|
)
|
|
9591
9763
|
);
|
|
9592
9764
|
}
|
|
@@ -9730,44 +9902,45 @@ function XViewScene({
|
|
|
9730
9902
|
}
|
|
9731
9903
|
return null;
|
|
9732
9904
|
}, [ownerId, sceneConfigId]);
|
|
9733
|
-
const sceneDataRef =
|
|
9734
|
-
const parentDataRef =
|
|
9735
|
-
const ancestryDataRef =
|
|
9736
|
-
const [isLoading, setIsLoading] =
|
|
9737
|
-
const [permissionStatus, setPermissionStatus] =
|
|
9738
|
-
const [userPermissionRole, setUserPermissionRole] =
|
|
9739
|
-
const [isInitialized, setIsInitialized] =
|
|
9740
|
-
const [sceneVersion, setSceneVersion] =
|
|
9741
|
-
const [contextMenu, setContextMenu] =
|
|
9742
|
-
const [multiContextMenu, setMultiContextMenu] =
|
|
9743
|
-
const [relationshipMenu, setRelationshipMenu] =
|
|
9744
|
-
const [creationMode, setCreationMode] =
|
|
9745
|
-
const [versionMode, setVersionMode] =
|
|
9746
|
-
const [
|
|
9747
|
-
const [
|
|
9748
|
-
const [
|
|
9749
|
-
const [
|
|
9905
|
+
const sceneDataRef = useRef18(null);
|
|
9906
|
+
const parentDataRef = useRef18(null);
|
|
9907
|
+
const ancestryDataRef = useRef18(null);
|
|
9908
|
+
const [isLoading, setIsLoading] = useState24(true);
|
|
9909
|
+
const [permissionStatus, setPermissionStatus] = useState24("loading");
|
|
9910
|
+
const [userPermissionRole, setUserPermissionRole] = useState24(null);
|
|
9911
|
+
const [isInitialized, setIsInitialized] = useState24(false);
|
|
9912
|
+
const [sceneVersion, setSceneVersion] = useState24(0);
|
|
9913
|
+
const [contextMenu, setContextMenu] = useState24({ visible: false, x: 0, y: 0, nodeData: null });
|
|
9914
|
+
const [multiContextMenu, setMultiContextMenu] = useState24({ visible: false, x: 0, y: 0, nodeIds: null });
|
|
9915
|
+
const [relationshipMenu, setRelationshipMenu] = useState24({ visible: false, x: 0, y: 0, linkObject: null });
|
|
9916
|
+
const [creationMode, setCreationMode] = useState24({ isActive: false, sourceNodeData: null });
|
|
9917
|
+
const [versionMode, setVersionMode] = useState24({ isActive: false, sourceNodeData: null });
|
|
9918
|
+
const [questMode, setQuestMode] = useState24({ isActive: false });
|
|
9919
|
+
const [hasFocusedInitial, setHasFocusedInitial] = useState24(false);
|
|
9920
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState24(false);
|
|
9921
|
+
const [ancestryMode, setAncestryMode] = useState24({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
9922
|
+
const [readingMode, setReadingMode] = useState24({
|
|
9750
9923
|
isActive: false,
|
|
9751
9924
|
ancestry: null,
|
|
9752
9925
|
branchStack: [],
|
|
9753
9926
|
autoAbstraction: false
|
|
9754
9927
|
});
|
|
9755
|
-
const [formPosition, setFormPosition] =
|
|
9756
|
-
const [detailsNode, setDetailsNode] =
|
|
9757
|
-
const [detailsLink, setDetailsLink] =
|
|
9758
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] =
|
|
9759
|
-
const [imageViewer, setImageViewer] =
|
|
9760
|
-
const [editingAncestryRel, setEditingAncestryRel] =
|
|
9761
|
-
const [isImportModalOpen, setIsImportModalOpen] =
|
|
9762
|
-
const [importSuccessMessage, setImportSuccessMessage] =
|
|
9763
|
-
const [highlightedNodeId, setHighlightedNodeId] =
|
|
9764
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] =
|
|
9765
|
-
const [ancestryBoardData, setAncestryBoardData] =
|
|
9766
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
9767
|
-
const mountRef =
|
|
9768
|
-
const tooltipRef =
|
|
9769
|
-
const formRef =
|
|
9770
|
-
const stateRef =
|
|
9928
|
+
const [formPosition, setFormPosition] = useState24({ left: 16, top: 16, opacity: 0 });
|
|
9929
|
+
const [detailsNode, setDetailsNode] = useState24(null);
|
|
9930
|
+
const [detailsLink, setDetailsLink] = useState24(null);
|
|
9931
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = useState24(null);
|
|
9932
|
+
const [imageViewer, setImageViewer] = useState24({ visible: false, images: [], startIndex: 0 });
|
|
9933
|
+
const [editingAncestryRel, setEditingAncestryRel] = useState24({ visible: false, data: null, path: null });
|
|
9934
|
+
const [isImportModalOpen, setIsImportModalOpen] = useState24(false);
|
|
9935
|
+
const [importSuccessMessage, setImportSuccessMessage] = useState24("");
|
|
9936
|
+
const [highlightedNodeId, setHighlightedNodeId] = useState24(null);
|
|
9937
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState24(false);
|
|
9938
|
+
const [ancestryBoardData, setAncestryBoardData] = useState24([]);
|
|
9939
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState24(false);
|
|
9940
|
+
const mountRef = useRef18(null);
|
|
9941
|
+
const tooltipRef = useRef18(null);
|
|
9942
|
+
const formRef = useRef18(null);
|
|
9943
|
+
const stateRef = useRef18({
|
|
9771
9944
|
readMode: {
|
|
9772
9945
|
currentMaxIndex: 0,
|
|
9773
9946
|
progressMap: {}
|
|
@@ -10699,6 +10872,20 @@ function XViewScene({
|
|
|
10699
10872
|
const context = actionHandlerContext;
|
|
10700
10873
|
if (connection.isActive) {
|
|
10701
10874
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(connection.sourceNodeData.id)) {
|
|
10875
|
+
const sourceId = String(connection.sourceNodeData.id);
|
|
10876
|
+
const targetId = String(hoveredNode.userData.id);
|
|
10877
|
+
let parentInfo = stateRef.current.nodeIdToParentFileMap.get(sourceId);
|
|
10878
|
+
if (!parentInfo || !parentInfo.ownerId) {
|
|
10879
|
+
parentInfo = stateRef.current.nodeIdToParentFileMap.get(targetId);
|
|
10880
|
+
if (parentInfo && parentInfo.ownerId) {
|
|
10881
|
+
stateRef.current.nodeIdToParentFileMap.set(sourceId, parentInfo);
|
|
10882
|
+
} else {
|
|
10883
|
+
console.error("Nenhum dos Nodes possui um Dataset pai v\xE1lido para salvar a conex\xE3o.");
|
|
10884
|
+
alert("N\xE3o \xE9 poss\xEDvel conectar dois Nodes de Quest diretamente sem um Dataset pai, ou ocorreu um erro.");
|
|
10885
|
+
userActionHandlers.handleCancelConnection(context);
|
|
10886
|
+
return;
|
|
10887
|
+
}
|
|
10888
|
+
}
|
|
10702
10889
|
await userActionHandlers.handleCompleteConnection(context, hoveredNode.userData);
|
|
10703
10890
|
} else {
|
|
10704
10891
|
userActionHandlers.handleCancelConnection(context);
|
|
@@ -10809,12 +10996,15 @@ function XViewScene({
|
|
|
10809
10996
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
10810
10997
|
}
|
|
10811
10998
|
function handleKeyDown(event) {
|
|
10999
|
+
var _a2, _b2, _c2, _d2;
|
|
10812
11000
|
const context = actionHandlerContext;
|
|
10813
11001
|
if (event.key === "Escape") {
|
|
10814
11002
|
if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
|
|
10815
11003
|
if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
|
|
10816
11004
|
if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
|
|
11005
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
|
|
10817
11006
|
if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
|
|
11007
|
+
if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
|
|
10818
11008
|
if (stateRef.current.selectedNodes.size > 0) {
|
|
10819
11009
|
stateRef.current.selectedNodes.clear();
|
|
10820
11010
|
}
|
|
@@ -10822,6 +11012,17 @@ function XViewScene({
|
|
|
10822
11012
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
10823
11013
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
10824
11014
|
}
|
|
11015
|
+
if (event.key.toLowerCase() === "q") {
|
|
11016
|
+
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;
|
|
11017
|
+
if (isUiClear) {
|
|
11018
|
+
const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
|
|
11019
|
+
if (!isView) {
|
|
11020
|
+
alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
|
|
11021
|
+
return;
|
|
11022
|
+
}
|
|
11023
|
+
setQuestMode({ isActive: true });
|
|
11024
|
+
}
|
|
11025
|
+
}
|
|
10825
11026
|
}
|
|
10826
11027
|
function handleDoubleClick(event) {
|
|
10827
11028
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
@@ -10980,9 +11181,7 @@ function XViewScene({
|
|
|
10980
11181
|
mountEl: currentMount,
|
|
10981
11182
|
isSceneBusy: stateRef.current.isDragging || creation.isActive || connection.isActive || relink.isActive || ancestryMode.isActive,
|
|
10982
11183
|
parentData: parentDataRef.current,
|
|
10983
|
-
// <--- ADICIONADO AQUI
|
|
10984
11184
|
ancestryData: ancestryDataRef.current
|
|
10985
|
-
// <--- ADICIONADO AQUI
|
|
10986
11185
|
});
|
|
10987
11186
|
(_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
|
|
10988
11187
|
stateRef.current.controls.update();
|
|
@@ -11288,6 +11487,12 @@ function XViewScene({
|
|
|
11288
11487
|
mountRef,
|
|
11289
11488
|
creationMode,
|
|
11290
11489
|
versionMode,
|
|
11490
|
+
questMode,
|
|
11491
|
+
// <-- Adicionado
|
|
11492
|
+
sceneSaveUrl,
|
|
11493
|
+
// <-- Adicionado
|
|
11494
|
+
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11495
|
+
// <-- Adicionado
|
|
11291
11496
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
11292
11497
|
setters: {
|
|
11293
11498
|
setContextMenu,
|
|
@@ -11299,7 +11504,9 @@ function XViewScene({
|
|
|
11299
11504
|
setDetailsNode,
|
|
11300
11505
|
setDetailsLink,
|
|
11301
11506
|
setSceneVersion,
|
|
11302
|
-
setAncestryMode
|
|
11507
|
+
setAncestryMode,
|
|
11508
|
+
setQuestMode
|
|
11509
|
+
// <-- Adicionado
|
|
11303
11510
|
},
|
|
11304
11511
|
tweenToTarget,
|
|
11305
11512
|
handleVersionTimeline,
|
|
@@ -11315,6 +11522,9 @@ function XViewScene({
|
|
|
11315
11522
|
[
|
|
11316
11523
|
creationMode,
|
|
11317
11524
|
versionMode,
|
|
11525
|
+
questMode,
|
|
11526
|
+
sceneSaveUrl,
|
|
11527
|
+
viewParams == null ? void 0 : viewParams.type,
|
|
11318
11528
|
tweenToTarget,
|
|
11319
11529
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11320
11530
|
handleVersionTimeline,
|
|
@@ -11328,6 +11538,33 @@ function XViewScene({
|
|
|
11328
11538
|
const handleStartVersioning = (nodeData) => {
|
|
11329
11539
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11330
11540
|
};
|
|
11541
|
+
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11542
|
+
const { sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType } = context;
|
|
11543
|
+
if (!sceneDataRef2.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11544
|
+
const newNode = {
|
|
11545
|
+
id: short2.generate(),
|
|
11546
|
+
...newQuestData,
|
|
11547
|
+
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11548
|
+
};
|
|
11549
|
+
const updatedSceneData = {
|
|
11550
|
+
...sceneDataRef2.current,
|
|
11551
|
+
nodes: [...sceneDataRef2.current.nodes, newNode]
|
|
11552
|
+
};
|
|
11553
|
+
try {
|
|
11554
|
+
await actions.save_view_data(sceneSaveUrl2, updatedSceneData);
|
|
11555
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
11556
|
+
const basePosition = stateRef2.current.controls.target.clone();
|
|
11557
|
+
const offset = new THREE3.Vector3((Math.random() - 0.5) * 10, (Math.random() - 0.5) * 5, (Math.random() - 0.5) * 10);
|
|
11558
|
+
const finalPosition = basePosition.add(offset);
|
|
11559
|
+
addOrUpdateNodeMesh(newNode, finalPosition);
|
|
11560
|
+
context.tweenToTarget(finalPosition, 1.2);
|
|
11561
|
+
setters.setQuestMode({ isActive: false });
|
|
11562
|
+
setters.setSceneVersion((v) => v + 1);
|
|
11563
|
+
} catch (error) {
|
|
11564
|
+
console.error("Falha ao salvar a Quest na View:", error);
|
|
11565
|
+
alert("Ocorreu um erro ao criar a Quest.");
|
|
11566
|
+
}
|
|
11567
|
+
};
|
|
11331
11568
|
const handleClearAncestryVisuals = useCallback4((ancestryId) => {
|
|
11332
11569
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11333
11570
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
@@ -12712,20 +12949,20 @@ function XViewScene({
|
|
|
12712
12949
|
}
|
|
12713
12950
|
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
12714
12951
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
12715
|
-
return /* @__PURE__ */
|
|
12952
|
+
return /* @__PURE__ */ React24.createElement(LoadingScreen, null);
|
|
12716
12953
|
}
|
|
12717
12954
|
if (permissionStatus === "denied") {
|
|
12718
|
-
return /* @__PURE__ */
|
|
12955
|
+
return /* @__PURE__ */ React24.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React24.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React24.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React24.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__ */ React24.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__ */ React24.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React24.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__ */ React24.createElement(
|
|
12719
12956
|
"button",
|
|
12720
12957
|
{
|
|
12721
12958
|
onClick: () => router.push("/dashboard/scenes"),
|
|
12722
12959
|
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
12960
|
},
|
|
12724
|
-
/* @__PURE__ */
|
|
12961
|
+
/* @__PURE__ */ React24.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__ */ React24.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
|
|
12725
12962
|
"Voltar para Scenes"
|
|
12726
12963
|
)));
|
|
12727
12964
|
}
|
|
12728
|
-
return /* @__PURE__ */
|
|
12965
|
+
return /* @__PURE__ */ React24.createElement(
|
|
12729
12966
|
"div",
|
|
12730
12967
|
{
|
|
12731
12968
|
ref: mountRef,
|
|
@@ -12737,7 +12974,7 @@ function XViewScene({
|
|
|
12737
12974
|
cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
|
|
12738
12975
|
}
|
|
12739
12976
|
},
|
|
12740
|
-
userPermissionRole !== "link_viewer" && /* @__PURE__ */
|
|
12977
|
+
userPermissionRole !== "link_viewer" && /* @__PURE__ */ React24.createElement(
|
|
12741
12978
|
XViewSidebar,
|
|
12742
12979
|
{
|
|
12743
12980
|
dbNodes: searchableDbNodes,
|
|
@@ -12757,7 +12994,7 @@ function XViewScene({
|
|
|
12757
12994
|
userRole: userPermissionRole
|
|
12758
12995
|
}
|
|
12759
12996
|
),
|
|
12760
|
-
creationMode.isActive && /* @__PURE__ */
|
|
12997
|
+
creationMode.isActive && /* @__PURE__ */ React24.createElement(
|
|
12761
12998
|
InSceneCreationForm,
|
|
12762
12999
|
{
|
|
12763
13000
|
onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
|
|
@@ -12782,7 +13019,7 @@ function XViewScene({
|
|
|
12782
13019
|
availableAncestries: allAvailableAncestries
|
|
12783
13020
|
}
|
|
12784
13021
|
),
|
|
12785
|
-
versionMode.isActive && /* @__PURE__ */
|
|
13022
|
+
versionMode.isActive && /* @__PURE__ */ React24.createElement(
|
|
12786
13023
|
InSceneVersionForm,
|
|
12787
13024
|
{
|
|
12788
13025
|
onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
|
|
@@ -12801,13 +13038,27 @@ function XViewScene({
|
|
|
12801
13038
|
availableAncestries: allAvailableAncestries
|
|
12802
13039
|
}
|
|
12803
13040
|
),
|
|
12804
|
-
|
|
13041
|
+
questMode.isActive && /* @__PURE__ */ React24.createElement(
|
|
13042
|
+
InSceneQuestForm,
|
|
13043
|
+
{
|
|
13044
|
+
onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
|
|
13045
|
+
onCancel: () => setQuestMode({ isActive: false }),
|
|
13046
|
+
style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
|
|
13047
|
+
refEl: formRef,
|
|
13048
|
+
onOpenImageViewer: handleOpenImageViewer,
|
|
13049
|
+
onMentionClick: handleAddExistingNode,
|
|
13050
|
+
onUploadFile: upload_file_action,
|
|
13051
|
+
availableNodes: allAvailableNodes,
|
|
13052
|
+
availableAncestries: allAvailableAncestries
|
|
13053
|
+
}
|
|
13054
|
+
),
|
|
13055
|
+
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React24.createElement(
|
|
12805
13056
|
"div",
|
|
12806
13057
|
{
|
|
12807
13058
|
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
13059
|
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
|
|
12809
13060
|
},
|
|
12810
|
-
/* @__PURE__ */
|
|
13061
|
+
/* @__PURE__ */ React24.createElement(
|
|
12811
13062
|
"div",
|
|
12812
13063
|
{
|
|
12813
13064
|
onPointerDown: (e) => {
|
|
@@ -12818,7 +13069,7 @@ function XViewScene({
|
|
|
12818
13069
|
title: "Arraste para redimensionar"
|
|
12819
13070
|
}
|
|
12820
13071
|
),
|
|
12821
|
-
/* @__PURE__ */
|
|
13072
|
+
/* @__PURE__ */ React24.createElement(
|
|
12822
13073
|
DescriptionReadModePanel,
|
|
12823
13074
|
{
|
|
12824
13075
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
@@ -12853,7 +13104,7 @@ function XViewScene({
|
|
|
12853
13104
|
}
|
|
12854
13105
|
)
|
|
12855
13106
|
),
|
|
12856
|
-
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */
|
|
13107
|
+
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React24.createElement(
|
|
12857
13108
|
CreateAncestryPanel,
|
|
12858
13109
|
{
|
|
12859
13110
|
ancestryMode,
|
|
@@ -12880,7 +13131,7 @@ function XViewScene({
|
|
|
12880
13131
|
onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
|
|
12881
13132
|
}
|
|
12882
13133
|
),
|
|
12883
|
-
editingAncestryRel.visible && /* @__PURE__ */
|
|
13134
|
+
editingAncestryRel.visible && /* @__PURE__ */ React24.createElement(
|
|
12884
13135
|
AncestryRelationshipPanel,
|
|
12885
13136
|
{
|
|
12886
13137
|
data: editingAncestryRel.data,
|
|
@@ -12894,7 +13145,7 @@ function XViewScene({
|
|
|
12894
13145
|
onUploadFile: upload_file_action
|
|
12895
13146
|
}
|
|
12896
13147
|
),
|
|
12897
|
-
detailsNode && /* @__PURE__ */
|
|
13148
|
+
detailsNode && /* @__PURE__ */ React24.createElement(
|
|
12898
13149
|
NodeDetailsPanel,
|
|
12899
13150
|
{
|
|
12900
13151
|
node: detailsNode,
|
|
@@ -12921,7 +13172,7 @@ function XViewScene({
|
|
|
12921
13172
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
|
|
12922
13173
|
}
|
|
12923
13174
|
),
|
|
12924
|
-
detailsLink && /* @__PURE__ */
|
|
13175
|
+
detailsLink && /* @__PURE__ */ React24.createElement(
|
|
12925
13176
|
RelationshipDetailsPanel,
|
|
12926
13177
|
{
|
|
12927
13178
|
link: detailsLink,
|
|
@@ -12935,7 +13186,7 @@ function XViewScene({
|
|
|
12935
13186
|
userRole: userPermissionRole
|
|
12936
13187
|
}
|
|
12937
13188
|
),
|
|
12938
|
-
ancestryLinkDetails && /* @__PURE__ */
|
|
13189
|
+
ancestryLinkDetails && /* @__PURE__ */ React24.createElement(
|
|
12939
13190
|
AncestryLinkDetailsPanel,
|
|
12940
13191
|
{
|
|
12941
13192
|
data: ancestryLinkDetails,
|
|
@@ -12946,7 +13197,7 @@ function XViewScene({
|
|
|
12946
13197
|
onUploadFile: upload_file_action
|
|
12947
13198
|
}
|
|
12948
13199
|
),
|
|
12949
|
-
/* @__PURE__ */
|
|
13200
|
+
/* @__PURE__ */ React24.createElement(
|
|
12950
13201
|
"div",
|
|
12951
13202
|
{
|
|
12952
13203
|
ref: tooltipRef,
|
|
@@ -12973,7 +13224,7 @@ function XViewScene({
|
|
|
12973
13224
|
}
|
|
12974
13225
|
}
|
|
12975
13226
|
),
|
|
12976
|
-
/* @__PURE__ */
|
|
13227
|
+
/* @__PURE__ */ React24.createElement(
|
|
12977
13228
|
ContextMenu,
|
|
12978
13229
|
{
|
|
12979
13230
|
data: contextMenu,
|
|
@@ -12996,7 +13247,7 @@ function XViewScene({
|
|
|
12996
13247
|
onFocusNode: handleFocusNode
|
|
12997
13248
|
}
|
|
12998
13249
|
),
|
|
12999
|
-
/* @__PURE__ */
|
|
13250
|
+
/* @__PURE__ */ React24.createElement(
|
|
13000
13251
|
MultiNodeContextMenu,
|
|
13001
13252
|
{
|
|
13002
13253
|
data: multiContextMenu,
|
|
@@ -13007,7 +13258,7 @@ function XViewScene({
|
|
|
13007
13258
|
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
|
|
13008
13259
|
}
|
|
13009
13260
|
),
|
|
13010
|
-
/* @__PURE__ */
|
|
13261
|
+
/* @__PURE__ */ React24.createElement(
|
|
13011
13262
|
RelationshipContextMenu,
|
|
13012
13263
|
{
|
|
13013
13264
|
data: relationshipMenu,
|
|
@@ -13025,8 +13276,8 @@ function XViewScene({
|
|
|
13025
13276
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
13026
13277
|
}
|
|
13027
13278
|
),
|
|
13028
|
-
/* @__PURE__ */
|
|
13029
|
-
/* @__PURE__ */
|
|
13279
|
+
/* @__PURE__ */ React24.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
|
|
13280
|
+
/* @__PURE__ */ React24.createElement(
|
|
13030
13281
|
AncestryBoard,
|
|
13031
13282
|
{
|
|
13032
13283
|
isOpen: isAncestryBoardOpen,
|
|
@@ -13039,7 +13290,7 @@ function XViewScene({
|
|
|
13039
13290
|
userRole: userPermissionRole
|
|
13040
13291
|
}
|
|
13041
13292
|
),
|
|
13042
|
-
/* @__PURE__ */
|
|
13293
|
+
/* @__PURE__ */ React24.createElement(
|
|
13043
13294
|
ImportParentFileModal,
|
|
13044
13295
|
{
|
|
13045
13296
|
isOpen: isImportModalOpen,
|
|
@@ -13104,7 +13355,13 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13104
13355
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13105
13356
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
13106
13357
|
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
13107
|
-
const validatedNodes = (sceneData.nodes || []).map((sceneNode) =>
|
|
13358
|
+
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
13359
|
+
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
13360
|
+
if (nodeTypes.includes("quest")) {
|
|
13361
|
+
return sceneNode;
|
|
13362
|
+
}
|
|
13363
|
+
return parentNodeMap.get(String(sceneNode.id));
|
|
13364
|
+
}).filter(Boolean);
|
|
13108
13365
|
const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
|
|
13109
13366
|
const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
|
|
13110
13367
|
const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
|