@lv-x-software-house/x_view 1.2.6-dev.2 → 1.2.6-dev.21
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 +1029 -709
- package/dist/index.mjs +958 -646
- package/dist/server.js +480 -0
- package/dist/server.mjs +445 -0
- package/package.json +2 -10
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// src/XViewScene.jsx
|
|
2
2
|
import React30, {
|
|
3
|
-
useCallback as
|
|
3
|
+
useCallback as useCallback5,
|
|
4
4
|
useEffect as useEffect24,
|
|
5
|
-
useRef as
|
|
6
|
-
useState as
|
|
5
|
+
useRef as useRef21,
|
|
6
|
+
useState as useState29,
|
|
7
7
|
useMemo as useMemo13
|
|
8
8
|
} from "react";
|
|
9
9
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
@@ -1053,6 +1053,8 @@ var userActionHandlers = {
|
|
|
1053
1053
|
if (isCrossDataset) {
|
|
1054
1054
|
graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
|
|
1055
1055
|
}
|
|
1056
|
+
if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
|
|
1057
|
+
}
|
|
1056
1058
|
const finalPosition = stateRef.current.ghostElements.node.position.clone();
|
|
1057
1059
|
addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
|
|
1058
1060
|
stateRef.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
@@ -1251,6 +1253,9 @@ var userActionHandlers = {
|
|
|
1251
1253
|
);
|
|
1252
1254
|
}
|
|
1253
1255
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
1256
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
1257
|
+
sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
|
|
1258
|
+
}
|
|
1254
1259
|
const finalPosition = stateRef.current.ghostElements.node.position.clone();
|
|
1255
1260
|
addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
|
|
1256
1261
|
setters.setSceneVersion((v) => v + 1);
|
|
@@ -2270,8 +2275,6 @@ var userActionHandlers = {
|
|
|
2270
2275
|
milestones: sceneDataRef.current.milestones || [],
|
|
2271
2276
|
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
2272
2277
|
};
|
|
2273
|
-
sceneDataRef.current.quest_nodes = specificParentData.nodes;
|
|
2274
|
-
sceneDataRef.current.quest_links = specificParentData.links;
|
|
2275
2278
|
await context.actions.save_view_data(
|
|
2276
2279
|
context.sceneSaveUrl,
|
|
2277
2280
|
viewFilePayload
|
|
@@ -2284,6 +2287,10 @@ var userActionHandlers = {
|
|
|
2284
2287
|
);
|
|
2285
2288
|
}
|
|
2286
2289
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2290
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2291
|
+
sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
|
|
2292
|
+
sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
|
|
2293
|
+
}
|
|
2287
2294
|
updateExistingNodeVisuals(stateRef.current, nodeToSave);
|
|
2288
2295
|
setters.setSceneVersion((v) => v + 1);
|
|
2289
2296
|
if (!keepOpen) {
|
|
@@ -12943,9 +12950,9 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
12943
12950
|
}
|
|
12944
12951
|
|
|
12945
12952
|
// src/components/AncestryBoard.jsx
|
|
12946
|
-
import React28, { useState as
|
|
12953
|
+
import React28, { useState as useState27, useMemo as useMemo12, useEffect as useEffect23, useRef as useRef20 } from "react";
|
|
12947
12954
|
import {
|
|
12948
|
-
FiSearch as
|
|
12955
|
+
FiSearch as FiSearch8,
|
|
12949
12956
|
FiLayers as FiLayers7,
|
|
12950
12957
|
FiCornerUpRight as FiCornerUpRight4,
|
|
12951
12958
|
FiPlay,
|
|
@@ -12953,365 +12960,590 @@ import {
|
|
|
12953
12960
|
FiTrash2 as FiTrash23,
|
|
12954
12961
|
FiArrowLeft as FiArrowLeft3,
|
|
12955
12962
|
FiArrowRight as FiArrowRight2,
|
|
12963
|
+
FiArrowUp,
|
|
12964
|
+
FiArrowDown,
|
|
12956
12965
|
FiCheckCircle,
|
|
12957
12966
|
FiLoader as FiLoader5,
|
|
12958
12967
|
FiX as FiX8,
|
|
12959
|
-
FiAlertTriangle,
|
|
12960
|
-
FiCheckSquare as FiCheckSquare4,
|
|
12961
12968
|
FiBox as FiBox2,
|
|
12962
|
-
|
|
12969
|
+
FiCheckSquare as FiCheckSquare4,
|
|
12970
|
+
FiGitBranch as FiGitBranch4,
|
|
12971
|
+
FiFolder as FiFolder3,
|
|
12972
|
+
FiChevronRight as FiChevronRight7
|
|
12963
12973
|
} from "react-icons/fi";
|
|
12964
12974
|
import { v4 as uuidv411 } from "uuid";
|
|
12965
12975
|
|
|
12966
|
-
// src/components/
|
|
12967
|
-
import React27, {
|
|
12968
|
-
import { useEditor, EditorContent, ReactRenderer } from "@tiptap/react";
|
|
12969
|
-
import StarterKit from "@tiptap/starter-kit";
|
|
12970
|
-
import Mention from "@tiptap/extension-mention";
|
|
12971
|
-
import tippy from "tippy.js";
|
|
12976
|
+
// src/components/RichGroupEditor.jsx
|
|
12977
|
+
import React27, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useCallback as useCallback4 } from "react";
|
|
12972
12978
|
|
|
12973
|
-
// src/components/
|
|
12974
|
-
import React26, {
|
|
12975
|
-
|
|
12976
|
-
|
|
12977
|
-
|
|
12978
|
-
|
|
12979
|
-
|
|
12980
|
-
|
|
12981
|
-
|
|
12982
|
-
|
|
12983
|
-
|
|
12984
|
-
|
|
12985
|
-
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
12989
|
-
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
|
|
12993
|
-
|
|
12994
|
-
};
|
|
12995
|
-
|
|
12996
|
-
|
|
12997
|
-
(
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
|
|
13005
|
-
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
return true;
|
|
13012
|
-
}
|
|
13013
|
-
if (event.key === "ArrowDown") {
|
|
13014
|
-
downHandler();
|
|
13015
|
-
return true;
|
|
13016
|
-
}
|
|
13017
|
-
if (event.key === "Enter") {
|
|
13018
|
-
enterHandler();
|
|
13019
|
-
return true;
|
|
12979
|
+
// src/components/MentionPopover.jsx
|
|
12980
|
+
import React26, { useEffect as useEffect21, useRef as useRef18, useState as useState25, useMemo as useMemo11 } from "react";
|
|
12981
|
+
import { FiLayers as FiLayers6, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch3, FiBox } from "react-icons/fi";
|
|
12982
|
+
var TYPE_CONFIG = {
|
|
12983
|
+
ancestry: { Icon: FiLayers6, color: "text-indigo-400", label: "Ancestralidade" },
|
|
12984
|
+
quest: { Icon: FiCheckSquare3, color: "text-emerald-400", label: "Quest" },
|
|
12985
|
+
version: { Icon: FiGitBranch3, color: "text-amber-400", label: "Vers\xE3o" },
|
|
12986
|
+
node: { Icon: FiBox, color: "text-slate-400", label: "Node" }
|
|
12987
|
+
};
|
|
12988
|
+
function MentionPopover({ query, items, position, onSelect, onClose }) {
|
|
12989
|
+
const [activeIndex, setActiveIndex] = useState25(0);
|
|
12990
|
+
const listRef = useRef18(null);
|
|
12991
|
+
const filtered = useMemo11(() => {
|
|
12992
|
+
const term = (query || "").toLowerCase().trim();
|
|
12993
|
+
if (!term) return items.slice(0, 8);
|
|
12994
|
+
return items.filter(
|
|
12995
|
+
(item) => (item.searchLabel || "").toLowerCase().includes(term) || (item.searchDesc || "").toLowerCase().includes(term)
|
|
12996
|
+
).slice(0, 8);
|
|
12997
|
+
}, [items, query]);
|
|
12998
|
+
useEffect21(() => {
|
|
12999
|
+
setActiveIndex(0);
|
|
13000
|
+
}, [query]);
|
|
13001
|
+
useEffect21(() => {
|
|
13002
|
+
const handleKeyDown = (e) => {
|
|
13003
|
+
if (e.key === "ArrowDown") {
|
|
13004
|
+
e.preventDefault();
|
|
13005
|
+
setActiveIndex((i) => Math.min(i + 1, filtered.length - 1));
|
|
13006
|
+
} else if (e.key === "ArrowUp") {
|
|
13007
|
+
e.preventDefault();
|
|
13008
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
13009
|
+
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
13010
|
+
e.preventDefault();
|
|
13011
|
+
if (filtered[activeIndex]) onSelect(filtered[activeIndex]);
|
|
13012
|
+
} else if (e.key === "Escape") {
|
|
13013
|
+
e.preventDefault();
|
|
13014
|
+
e.stopPropagation();
|
|
13015
|
+
e.stopImmediatePropagation();
|
|
13016
|
+
onClose();
|
|
13020
13017
|
}
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
}
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
|
|
13047
|
-
|
|
13048
|
-
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
|
|
13057
|
-
|
|
13058
|
-
|
|
13059
|
-
|
|
13060
|
-
var MentionList_default = MentionList;
|
|
13018
|
+
};
|
|
13019
|
+
window.addEventListener("keydown", handleKeyDown, true);
|
|
13020
|
+
return () => window.removeEventListener("keydown", handleKeyDown, true);
|
|
13021
|
+
}, [filtered, activeIndex, onSelect, onClose]);
|
|
13022
|
+
useEffect21(() => {
|
|
13023
|
+
if (listRef.current) {
|
|
13024
|
+
const el = listRef.current.children[activeIndex];
|
|
13025
|
+
if (el) el.scrollIntoView({ block: "nearest" });
|
|
13026
|
+
}
|
|
13027
|
+
}, [activeIndex]);
|
|
13028
|
+
return /* @__PURE__ */ React26.createElement(
|
|
13029
|
+
"div",
|
|
13030
|
+
{
|
|
13031
|
+
style: { top: position.top, left: position.left, position: "fixed", zIndex: 9999 },
|
|
13032
|
+
className: "bg-slate-900 border border-white/10 rounded-xl shadow-2xl py-1.5 min-w-[260px] max-h-[240px] overflow-y-auto custom-scrollbar animate-in fade-in zoom-in-95 duration-100",
|
|
13033
|
+
ref: listRef,
|
|
13034
|
+
onMouseDown: (e) => e.preventDefault()
|
|
13035
|
+
},
|
|
13036
|
+
filtered.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "px-4 py-3 text-xs text-slate-500" }, "Nenhum resultado para", " ", /* @__PURE__ */ React26.createElement("span", { className: "text-slate-300 font-medium" }, '"', query, '"')) : filtered.map((item, idx) => {
|
|
13037
|
+
const config = TYPE_CONFIG[item.type] || TYPE_CONFIG.node;
|
|
13038
|
+
const { Icon } = config;
|
|
13039
|
+
return /* @__PURE__ */ React26.createElement(
|
|
13040
|
+
"div",
|
|
13041
|
+
{
|
|
13042
|
+
key: item.id,
|
|
13043
|
+
onMouseDown: (e) => {
|
|
13044
|
+
e.preventDefault();
|
|
13045
|
+
onSelect(item);
|
|
13046
|
+
},
|
|
13047
|
+
onMouseEnter: () => setActiveIndex(idx),
|
|
13048
|
+
className: `flex items-center gap-2.5 px-3 py-2 cursor-pointer text-sm transition-colors duration-100 ${idx === activeIndex ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5"}`
|
|
13049
|
+
},
|
|
13050
|
+
/* @__PURE__ */ React26.createElement(Icon, { size: 13, className: config.color }),
|
|
13051
|
+
/* @__PURE__ */ React26.createElement("span", { className: "flex-1 truncate font-medium" }, item.searchLabel || "Sem Nome"),
|
|
13052
|
+
/* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1.5 py-0.5 rounded-full bg-white/5 text-slate-500 border border-white/5 uppercase tracking-wide shrink-0" }, config.label)
|
|
13053
|
+
);
|
|
13054
|
+
})
|
|
13055
|
+
);
|
|
13056
|
+
}
|
|
13061
13057
|
|
|
13062
|
-
// src/components/
|
|
13063
|
-
var
|
|
13064
|
-
|
|
13058
|
+
// src/components/RichGroupEditor.jsx
|
|
13059
|
+
var MENTION_BASE_STYLE = "display:inline-flex;align-items:center;padding:1px 7px;border-radius:5px;margin:0 2px;font-size:0.78em;font-weight:600;cursor:pointer;white-space:nowrap;vertical-align:middle;user-select:none;line-height:1.6;";
|
|
13060
|
+
var MENTION_TYPE_STYLE = {
|
|
13061
|
+
ancestry: "background:rgba(99,102,241,0.18);color:#a5b4fc;border:1px solid rgba(99,102,241,0.35);",
|
|
13062
|
+
quest: "background:rgba(16,185,129,0.18);color:#6ee7b7;border:1px solid rgba(16,185,129,0.35);",
|
|
13063
|
+
version: "background:rgba(245,158,11,0.18);color:#fcd34d;border:1px solid rgba(245,158,11,0.35);",
|
|
13064
|
+
node: "background:rgba(100,116,139,0.18);color:#94a3b8;border:1px solid rgba(100,116,139,0.35);"
|
|
13065
|
+
};
|
|
13066
|
+
function mentionStyle(type) {
|
|
13067
|
+
return MENTION_BASE_STYLE + (MENTION_TYPE_STYLE[type] || MENTION_TYPE_STYLE.node);
|
|
13068
|
+
}
|
|
13069
|
+
function escapeHtml(str) {
|
|
13070
|
+
return String(str || "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
13071
|
+
}
|
|
13072
|
+
function contentToHTML(content) {
|
|
13073
|
+
if (!content || content.length === 0) return "";
|
|
13074
|
+
return content.map((seg) => {
|
|
13075
|
+
if (seg.type === "text") {
|
|
13076
|
+
return escapeHtml(seg.value).replace(/\n/g, "<br>");
|
|
13077
|
+
}
|
|
13078
|
+
if (seg.type === "mention") {
|
|
13079
|
+
const style = mentionStyle(seg.mentionType);
|
|
13080
|
+
return `<span contenteditable="false" data-mention="true" data-id="${escapeHtml(String(seg.id))}" data-name="${escapeHtml(seg.name || "")}" data-mention-type="${escapeHtml(seg.mentionType || "node")}" style="${style}" title="Clique para focar na cena">@${escapeHtml(seg.name || "")}</span>`;
|
|
13081
|
+
}
|
|
13082
|
+
return "";
|
|
13083
|
+
}).join("");
|
|
13084
|
+
}
|
|
13085
|
+
function domToContent(el) {
|
|
13086
|
+
const segments = [];
|
|
13087
|
+
function pushText(text) {
|
|
13088
|
+
const clean = text.replace(/\u200B/g, "");
|
|
13089
|
+
if (!clean) return;
|
|
13090
|
+
const last = segments[segments.length - 1];
|
|
13091
|
+
if (last && last.type === "text") {
|
|
13092
|
+
last.value += clean;
|
|
13093
|
+
} else {
|
|
13094
|
+
segments.push({ type: "text", value: clean });
|
|
13095
|
+
}
|
|
13096
|
+
}
|
|
13097
|
+
function walk(node) {
|
|
13065
13098
|
var _a;
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
|
|
13075
|
-
|
|
13076
|
-
|
|
13077
|
-
|
|
13099
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
13100
|
+
pushText(node.textContent);
|
|
13101
|
+
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
|
13102
|
+
if (((_a = node.dataset) == null ? void 0 : _a.mention) === "true") {
|
|
13103
|
+
segments.push({
|
|
13104
|
+
type: "mention",
|
|
13105
|
+
id: node.dataset.id,
|
|
13106
|
+
name: node.dataset.name,
|
|
13107
|
+
mentionType: node.dataset.mentionType
|
|
13108
|
+
});
|
|
13109
|
+
} else if (node.tagName === "BR") {
|
|
13110
|
+
pushText("\n");
|
|
13111
|
+
} else {
|
|
13112
|
+
if (["DIV", "P"].includes(node.tagName) && segments.length > 0) {
|
|
13113
|
+
pushText("\n");
|
|
13078
13114
|
}
|
|
13115
|
+
node.childNodes.forEach(walk);
|
|
13079
13116
|
}
|
|
13080
|
-
}
|
|
13117
|
+
}
|
|
13081
13118
|
}
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13119
|
+
el.childNodes.forEach(walk);
|
|
13120
|
+
return segments;
|
|
13121
|
+
}
|
|
13122
|
+
function RichGroupEditor({
|
|
13123
|
+
content,
|
|
13085
13124
|
onChange,
|
|
13086
|
-
|
|
13087
|
-
|
|
13088
|
-
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
const
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
};
|
|
13104
|
-
const content = useMemo11(() => parseInitialContent(initialValue), [initialValue]);
|
|
13105
|
-
const editor = useEditor({
|
|
13106
|
-
extensions: [
|
|
13107
|
-
StarterKit.configure({
|
|
13108
|
-
heading: false,
|
|
13109
|
-
bulletList: false,
|
|
13110
|
-
orderedList: false,
|
|
13111
|
-
codeBlock: false,
|
|
13112
|
-
blockquote: false
|
|
13113
|
-
}),
|
|
13114
|
-
CustomMention.configure({
|
|
13115
|
-
HTMLAttributes: {
|
|
13116
|
-
class: "mention"
|
|
13117
|
-
},
|
|
13118
|
-
suggestion: {
|
|
13119
|
-
items: ({ query }) => {
|
|
13120
|
-
return availableItems.filter(
|
|
13121
|
-
(item) => item.name.toLowerCase().includes(query.toLowerCase())
|
|
13122
|
-
).slice(0, 10);
|
|
13123
|
-
},
|
|
13124
|
-
render: () => {
|
|
13125
|
-
let component;
|
|
13126
|
-
let popup;
|
|
13127
|
-
return {
|
|
13128
|
-
onStart: (props) => {
|
|
13129
|
-
component = new ReactRenderer(MentionList_default, {
|
|
13130
|
-
props,
|
|
13131
|
-
editor: props.editor
|
|
13132
|
-
});
|
|
13133
|
-
if (!props.clientRect) {
|
|
13134
|
-
return;
|
|
13135
|
-
}
|
|
13136
|
-
popup = tippy("body", {
|
|
13137
|
-
getReferenceClientRect: props.clientRect,
|
|
13138
|
-
appendTo: () => document.body,
|
|
13139
|
-
content: component.element,
|
|
13140
|
-
showOnCreate: true,
|
|
13141
|
-
interactive: true,
|
|
13142
|
-
trigger: "manual",
|
|
13143
|
-
placement: "bottom-start"
|
|
13144
|
-
});
|
|
13145
|
-
},
|
|
13146
|
-
onUpdate(props) {
|
|
13147
|
-
component.updateProps(props);
|
|
13148
|
-
if (!props.clientRect) {
|
|
13149
|
-
return;
|
|
13150
|
-
}
|
|
13151
|
-
popup[0].setProps({
|
|
13152
|
-
getReferenceClientRect: props.clientRect
|
|
13153
|
-
});
|
|
13154
|
-
},
|
|
13155
|
-
onKeyDown(props) {
|
|
13156
|
-
var _a;
|
|
13157
|
-
if (props.event.key === "Escape") {
|
|
13158
|
-
popup[0].hide();
|
|
13159
|
-
return true;
|
|
13160
|
-
}
|
|
13161
|
-
return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
|
|
13162
|
-
},
|
|
13163
|
-
onExit() {
|
|
13164
|
-
if (popup && popup[0]) popup[0].destroy();
|
|
13165
|
-
if (component) component.destroy();
|
|
13166
|
-
}
|
|
13167
|
-
};
|
|
13168
|
-
}
|
|
13169
|
-
}
|
|
13170
|
-
})
|
|
13171
|
-
],
|
|
13172
|
-
content,
|
|
13173
|
-
editable: canEdit,
|
|
13174
|
-
onUpdate: ({ editor: editor2 }) => {
|
|
13175
|
-
const serialize = (json) => {
|
|
13176
|
-
if (!json.content) return "";
|
|
13177
|
-
return json.content.map((block) => {
|
|
13178
|
-
if (block.type === "paragraph") {
|
|
13179
|
-
const inner = block.content ? block.content.map((node) => {
|
|
13180
|
-
if (node.type === "text") return node.text;
|
|
13181
|
-
if (node.type === "mention") {
|
|
13182
|
-
return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
|
|
13183
|
-
}
|
|
13184
|
-
return "";
|
|
13185
|
-
}).join("") : "";
|
|
13186
|
-
return inner;
|
|
13187
|
-
}
|
|
13188
|
-
return "";
|
|
13189
|
-
}).join("\n").trim();
|
|
13190
|
-
};
|
|
13191
|
-
const serialized = serialize(editor2.getJSON());
|
|
13192
|
-
onChange(serialized);
|
|
13125
|
+
onMentionClick,
|
|
13126
|
+
searchItems,
|
|
13127
|
+
readOnly,
|
|
13128
|
+
placeholder
|
|
13129
|
+
}) {
|
|
13130
|
+
const editorRef = useRef19(null);
|
|
13131
|
+
const isMountedRef = useRef19(false);
|
|
13132
|
+
const dismissedTriggerRef = useRef19(null);
|
|
13133
|
+
const [mentionState, setMentionState] = useState26(null);
|
|
13134
|
+
const [isEmpty, setIsEmpty] = useState26(true);
|
|
13135
|
+
useEffect22(() => {
|
|
13136
|
+
if (!isMountedRef.current && editorRef.current) {
|
|
13137
|
+
editorRef.current.innerHTML = contentToHTML(content);
|
|
13138
|
+
const hasContent = !!editorRef.current.innerText.replace(/\u200B/g, "").trim();
|
|
13139
|
+
const hasMentions = !!editorRef.current.querySelector("[data-mention]");
|
|
13140
|
+
setIsEmpty(!hasContent && !hasMentions);
|
|
13141
|
+
isMountedRef.current = true;
|
|
13193
13142
|
}
|
|
13194
|
-
});
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13198
|
-
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13143
|
+
}, []);
|
|
13144
|
+
const getMentionContext = useCallback4(() => {
|
|
13145
|
+
const selection = window.getSelection();
|
|
13146
|
+
if (!selection || selection.rangeCount === 0) return null;
|
|
13147
|
+
const range = selection.getRangeAt(0);
|
|
13148
|
+
const node = range.startContainer;
|
|
13149
|
+
if (node.nodeType !== Node.TEXT_NODE) return null;
|
|
13150
|
+
const textBefore = node.textContent.substring(0, range.startOffset);
|
|
13151
|
+
const atIndex = textBefore.lastIndexOf("@");
|
|
13152
|
+
if (atIndex === -1) {
|
|
13153
|
+
dismissedTriggerRef.current = null;
|
|
13154
|
+
return null;
|
|
13203
13155
|
}
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13156
|
+
if (dismissedTriggerRef.current && dismissedTriggerRef.current.node === node && dismissedTriggerRef.current.atIndex === atIndex) {
|
|
13157
|
+
return null;
|
|
13158
|
+
}
|
|
13159
|
+
const query = textBefore.substring(atIndex + 1);
|
|
13160
|
+
if (query.includes(" ") || query.includes(".") || query.includes(",") || query.length > 40) {
|
|
13161
|
+
return null;
|
|
13162
|
+
}
|
|
13163
|
+
const rect = range.getBoundingClientRect();
|
|
13164
|
+
return {
|
|
13165
|
+
query,
|
|
13166
|
+
position: { top: rect.bottom + 6, left: rect.left }
|
|
13167
|
+
};
|
|
13168
|
+
}, []);
|
|
13169
|
+
const handleInput = useCallback4(() => {
|
|
13170
|
+
if (!editorRef.current) return;
|
|
13171
|
+
const serialized = domToContent(editorRef.current);
|
|
13172
|
+
onChange(serialized);
|
|
13173
|
+
const text = editorRef.current.innerText.replace(/\u200B/g, "").trim();
|
|
13174
|
+
const hasMentions = !!editorRef.current.querySelector("[data-mention]");
|
|
13175
|
+
setIsEmpty(!text && !hasMentions);
|
|
13176
|
+
const ctx = getMentionContext();
|
|
13177
|
+
setMentionState(ctx);
|
|
13178
|
+
}, [onChange, getMentionContext]);
|
|
13179
|
+
const handleKeyDown = useCallback4(
|
|
13180
|
+
(e) => {
|
|
13181
|
+
if (mentionState && ["ArrowDown", "ArrowUp", "Enter", "Tab", "Escape"].includes(e.key)) {
|
|
13182
|
+
return;
|
|
13183
|
+
}
|
|
13184
|
+
if (e.key === "Enter") {
|
|
13185
|
+
e.preventDefault();
|
|
13186
|
+
const sel = window.getSelection();
|
|
13187
|
+
const range = sel.getRangeAt(0);
|
|
13188
|
+
const br = document.createElement("br");
|
|
13189
|
+
range.deleteContents();
|
|
13190
|
+
range.insertNode(br);
|
|
13191
|
+
const afterBr = br.nextSibling || (() => {
|
|
13192
|
+
const zws = document.createTextNode("\u200B");
|
|
13193
|
+
br.parentNode.insertBefore(zws, br.nextSibling);
|
|
13194
|
+
return zws;
|
|
13195
|
+
})();
|
|
13196
|
+
const newRange = document.createRange();
|
|
13197
|
+
newRange.setStartBefore(afterBr);
|
|
13198
|
+
newRange.collapse(true);
|
|
13199
|
+
sel.removeAllRanges();
|
|
13200
|
+
sel.addRange(newRange);
|
|
13201
|
+
handleInput();
|
|
13202
|
+
}
|
|
13203
|
+
},
|
|
13204
|
+
[mentionState, handleInput]
|
|
13205
|
+
);
|
|
13206
|
+
const insertMention = useCallback4(
|
|
13207
|
+
(item) => {
|
|
13208
|
+
if (!editorRef.current) return;
|
|
13209
|
+
const sel = window.getSelection();
|
|
13210
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
13211
|
+
const range = sel.getRangeAt(0);
|
|
13212
|
+
const textNode = range.startContainer;
|
|
13213
|
+
if (textNode.nodeType !== Node.TEXT_NODE) {
|
|
13214
|
+
setMentionState(null);
|
|
13215
|
+
return;
|
|
13216
|
+
}
|
|
13217
|
+
const cursorPos = range.startOffset;
|
|
13218
|
+
const textContent = textNode.textContent;
|
|
13219
|
+
const atIndex = textContent.lastIndexOf("@", cursorPos - 1);
|
|
13220
|
+
if (atIndex === -1) {
|
|
13221
|
+
setMentionState(null);
|
|
13222
|
+
return;
|
|
13223
|
+
}
|
|
13224
|
+
const before = textContent.substring(0, atIndex);
|
|
13225
|
+
const after = textContent.substring(cursorPos);
|
|
13226
|
+
textNode.textContent = before;
|
|
13227
|
+
const parent = textNode.parentNode;
|
|
13228
|
+
const nextSib = textNode.nextSibling;
|
|
13229
|
+
const span = document.createElement("span");
|
|
13230
|
+
span.contentEditable = "false";
|
|
13231
|
+
span.dataset.mention = "true";
|
|
13232
|
+
span.dataset.id = item.id;
|
|
13233
|
+
span.dataset.name = item.searchLabel || item.name || "";
|
|
13234
|
+
span.dataset.mentionType = item.type;
|
|
13235
|
+
span.style.cssText = mentionStyle(item.type);
|
|
13236
|
+
span.title = "Clique para focar na cena";
|
|
13237
|
+
span.textContent = `@${item.searchLabel || item.name || ""}`;
|
|
13238
|
+
parent.insertBefore(span, nextSib);
|
|
13239
|
+
const trailing = document.createTextNode(after || "\u200B");
|
|
13240
|
+
parent.insertBefore(trailing, span.nextSibling);
|
|
13241
|
+
const newRange = document.createRange();
|
|
13242
|
+
newRange.setStart(trailing, after ? 0 : 1);
|
|
13243
|
+
newRange.collapse(true);
|
|
13244
|
+
sel.removeAllRanges();
|
|
13245
|
+
sel.addRange(newRange);
|
|
13246
|
+
const serialized = domToContent(editorRef.current);
|
|
13247
|
+
onChange(serialized);
|
|
13248
|
+
setMentionState(null);
|
|
13249
|
+
setIsEmpty(false);
|
|
13250
|
+
},
|
|
13251
|
+
[onChange]
|
|
13252
|
+
);
|
|
13253
|
+
const handlePaste = useCallback4(
|
|
13254
|
+
(e) => {
|
|
13255
|
+
e.preventDefault();
|
|
13256
|
+
const text = e.clipboardData.getData("text/plain");
|
|
13257
|
+
if (text) {
|
|
13258
|
+
document.execCommand("insertText", false, text);
|
|
13259
|
+
handleInput();
|
|
13260
|
+
}
|
|
13261
|
+
},
|
|
13262
|
+
[handleInput]
|
|
13263
|
+
);
|
|
13264
|
+
const handleClick = useCallback4(
|
|
13265
|
+
(e) => {
|
|
13266
|
+
const chip = e.target.closest("[data-mention='true']");
|
|
13267
|
+
if (chip && onMentionClick) {
|
|
13268
|
+
e.stopPropagation();
|
|
13269
|
+
const id = chip.dataset.id;
|
|
13270
|
+
const full = searchItems == null ? void 0 : searchItems.find((i) => String(i.id) === String(id));
|
|
13271
|
+
if (full) {
|
|
13272
|
+
onMentionClick(full);
|
|
13273
|
+
} else {
|
|
13274
|
+
onMentionClick({
|
|
13275
|
+
id,
|
|
13276
|
+
name: chip.dataset.name,
|
|
13277
|
+
type: chip.dataset.mentionType,
|
|
13278
|
+
searchLabel: chip.dataset.name
|
|
13279
|
+
});
|
|
13226
13280
|
}
|
|
13227
|
-
|
|
13228
|
-
|
|
13281
|
+
return;
|
|
13282
|
+
}
|
|
13283
|
+
setTimeout(() => {
|
|
13284
|
+
const ctx = getMentionContext();
|
|
13285
|
+
setMentionState(ctx);
|
|
13286
|
+
}, 0);
|
|
13287
|
+
},
|
|
13288
|
+
[onMentionClick, getMentionContext, searchItems]
|
|
13289
|
+
);
|
|
13290
|
+
const handleBlur = useCallback4(() => {
|
|
13291
|
+
setTimeout(() => setMentionState(null), 200);
|
|
13292
|
+
}, []);
|
|
13293
|
+
const handleMentionDismiss = useCallback4(() => {
|
|
13294
|
+
const selection = window.getSelection();
|
|
13295
|
+
if (selection && selection.rangeCount > 0) {
|
|
13296
|
+
const range = selection.getRangeAt(0);
|
|
13297
|
+
const node = range.startContainer;
|
|
13298
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
13299
|
+
const textBefore = node.textContent.substring(0, range.startOffset);
|
|
13300
|
+
const atIndex = textBefore.lastIndexOf("@");
|
|
13301
|
+
if (atIndex !== -1) {
|
|
13302
|
+
dismissedTriggerRef.current = { node, atIndex };
|
|
13229
13303
|
}
|
|
13230
|
-
|
|
13231
|
-
}
|
|
13232
|
-
|
|
13304
|
+
}
|
|
13305
|
+
}
|
|
13306
|
+
setMentionState(null);
|
|
13307
|
+
}, []);
|
|
13308
|
+
return /* @__PURE__ */ React27.createElement("div", { className: "relative" }, isEmpty && !readOnly && /* @__PURE__ */ React27.createElement("div", { className: "absolute top-0 left-0 text-sm text-slate-600 pointer-events-none select-none" }, placeholder || "Escreva sobre este grupo\u2026 ou digite @ para mencionar"), /* @__PURE__ */ React27.createElement(
|
|
13309
|
+
"div",
|
|
13310
|
+
{
|
|
13311
|
+
ref: editorRef,
|
|
13312
|
+
contentEditable: readOnly ? "false" : "true",
|
|
13313
|
+
suppressContentEditableWarning: true,
|
|
13314
|
+
onInput: handleInput,
|
|
13315
|
+
onKeyDown: handleKeyDown,
|
|
13316
|
+
onPaste: handlePaste,
|
|
13317
|
+
onClick: handleClick,
|
|
13318
|
+
onBlur: handleBlur,
|
|
13319
|
+
className: `w-full min-h-[1.5rem] max-h-[250px] overflow-y-auto text-sm text-slate-200 focus:outline-none leading-relaxed ${!readOnly ? "cursor-text" : "cursor-default"}`,
|
|
13320
|
+
style: { overflowWrap: "break-word", wordBreak: "break-word" }
|
|
13321
|
+
}
|
|
13322
|
+
), mentionState && !readOnly && /* @__PURE__ */ React27.createElement(
|
|
13323
|
+
MentionPopover,
|
|
13324
|
+
{
|
|
13325
|
+
query: mentionState.query,
|
|
13326
|
+
items: searchItems || [],
|
|
13327
|
+
position: mentionState.position,
|
|
13328
|
+
onSelect: insertMention,
|
|
13329
|
+
onClose: handleMentionDismiss
|
|
13330
|
+
}
|
|
13331
|
+
));
|
|
13332
|
+
}
|
|
13233
13333
|
|
|
13234
13334
|
// src/components/AncestryBoard.jsx
|
|
13235
|
-
var
|
|
13236
|
-
|
|
13335
|
+
var Tooltip = ({ text, children }) => {
|
|
13336
|
+
if (!text) return children;
|
|
13337
|
+
return /* @__PURE__ */ React28.createElement("div", { className: "relative group/tooltip" }, children, /* @__PURE__ */ React28.createElement("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-slate-900 border border-white/10 text-white text-[10px] rounded opacity-0 group-hover/tooltip:opacity-100 transition-opacity pointer-events-none whitespace-nowrap z-[3000] shadow-2xl" }, text));
|
|
13338
|
+
};
|
|
13339
|
+
var BoardItem = ({
|
|
13340
|
+
item,
|
|
13237
13341
|
index,
|
|
13342
|
+
prevItem,
|
|
13343
|
+
nextItem,
|
|
13238
13344
|
onUpdate,
|
|
13239
13345
|
onDelete,
|
|
13240
|
-
onAddSubgroup,
|
|
13241
13346
|
onIndent,
|
|
13347
|
+
onIndentDown,
|
|
13242
13348
|
onOutdent,
|
|
13243
|
-
|
|
13244
|
-
|
|
13349
|
+
onMoveUp,
|
|
13350
|
+
onMoveDown,
|
|
13351
|
+
searchItems,
|
|
13352
|
+
onMentionClick,
|
|
13353
|
+
onEnterFolder,
|
|
13245
13354
|
canEdit
|
|
13246
13355
|
}) => {
|
|
13247
|
-
|
|
13248
|
-
|
|
13249
|
-
|
|
13250
|
-
|
|
13251
|
-
|
|
13252
|
-
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
)
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 }),
|
|
13274
|
-
/* @__PURE__ */ React28.createElement("span", null, "Adicionar Subgrupo")
|
|
13275
|
-
)), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
|
|
13276
|
-
"button",
|
|
13277
|
-
{
|
|
13278
|
-
onClick: () => onIndent(group.id),
|
|
13279
|
-
disabled: !canIndent,
|
|
13280
|
-
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
13281
|
-
title: "Aninhar no grupo acima"
|
|
13282
|
-
},
|
|
13283
|
-
/* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
|
|
13284
|
-
), /* @__PURE__ */ React28.createElement(
|
|
13285
|
-
"button",
|
|
13286
|
-
{
|
|
13287
|
-
onClick: () => onOutdent(group.id),
|
|
13288
|
-
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
13289
|
-
title: "Desaninhar"
|
|
13290
|
-
},
|
|
13291
|
-
/* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
|
|
13292
|
-
), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
|
|
13293
|
-
"button",
|
|
13356
|
+
var _a;
|
|
13357
|
+
const isFolder = item.type === "folder";
|
|
13358
|
+
const canMoveUp = index > 0;
|
|
13359
|
+
const canMoveDown = nextItem !== void 0;
|
|
13360
|
+
const isNested = onOutdent !== void 0;
|
|
13361
|
+
const getIndentUpTooltip = () => {
|
|
13362
|
+
if (!prevItem) return null;
|
|
13363
|
+
const typeLabel = prevItem.type === "folder" ? "folder" : "text_group";
|
|
13364
|
+
return isFolder ? prevItem.type === "folder" ? "Aninhar na pasta acima" : null : `Mover para dentro do ${typeLabel} acima`;
|
|
13365
|
+
};
|
|
13366
|
+
const getIndentDownTooltip = () => {
|
|
13367
|
+
if (!nextItem) return null;
|
|
13368
|
+
const typeLabel = nextItem.type === "folder" ? "folder" : "text_group";
|
|
13369
|
+
return isFolder ? nextItem.type === "folder" ? "Aninhar na pasta abaixo" : null : `Mover para dentro do ${typeLabel} abaixo`;
|
|
13370
|
+
};
|
|
13371
|
+
const showIndentUp = !!getIndentUpTooltip();
|
|
13372
|
+
const showIndentDown = !!getIndentDownTooltip();
|
|
13373
|
+
const handleContentChange = (content) => {
|
|
13374
|
+
onUpdate(item.id, { ...item, content });
|
|
13375
|
+
};
|
|
13376
|
+
const handleNameChange = (e) => {
|
|
13377
|
+
onUpdate(item.id, { ...item, name: e.target.value });
|
|
13378
|
+
};
|
|
13379
|
+
if (isFolder) {
|
|
13380
|
+
return /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 mb-3 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement(
|
|
13381
|
+
"div",
|
|
13294
13382
|
{
|
|
13295
|
-
onClick: () =>
|
|
13296
|
-
className: "
|
|
13297
|
-
title: "Remover Grupo"
|
|
13383
|
+
onClick: () => onEnterFolder(item.id),
|
|
13384
|
+
className: "flex items-center gap-3 py-3 px-4 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 rounded-xl cursor-pointer transition-all duration-200 group/folder"
|
|
13298
13385
|
},
|
|
13299
|
-
/* @__PURE__ */ React28.createElement(
|
|
13300
|
-
|
|
13301
|
-
|
|
13302
|
-
|
|
13386
|
+
/* @__PURE__ */ React28.createElement("div", { className: "w-10 h-10 rounded-lg bg-indigo-500/10 flex items-center justify-center text-indigo-400 group-hover/folder:scale-110 transition-transform" }, /* @__PURE__ */ React28.createElement(FiFolder3, { size: 20 })),
|
|
13387
|
+
/* @__PURE__ */ React28.createElement("div", { className: "flex-1 min-w-0" }, canEdit ? /* @__PURE__ */ React28.createElement(
|
|
13388
|
+
"input",
|
|
13389
|
+
{
|
|
13390
|
+
type: "text",
|
|
13391
|
+
value: item.name,
|
|
13392
|
+
onChange: handleNameChange,
|
|
13393
|
+
onClick: (e) => e.stopPropagation(),
|
|
13394
|
+
className: "bg-transparent border-none outline-none text-sm font-medium text-slate-200 w-full focus:text-white",
|
|
13395
|
+
placeholder: "Nome da pasta..."
|
|
13396
|
+
}
|
|
13397
|
+
) : /* @__PURE__ */ React28.createElement("span", { className: "text-sm font-medium text-slate-200" }, item.name), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-2 mt-0.5" }, /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider font-semibold" }, ((_a = item.children) == null ? void 0 : _a.length) || 0, " itens"))),
|
|
13398
|
+
/* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1.5 opacity-0 group-item/item:opacity-100 group-hover/folder:opacity-100 transition-opacity" }, canEdit && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-0.5 bg-slate-900/80 backdrop-blur-sm p-1 rounded-lg border border-white/5 shadow-xl" }, /* @__PURE__ */ React28.createElement(Tooltip, { text: "Subir" }, /* @__PURE__ */ React28.createElement(
|
|
13399
|
+
"button",
|
|
13400
|
+
{
|
|
13401
|
+
onClick: (e) => {
|
|
13402
|
+
e.stopPropagation();
|
|
13403
|
+
onMoveUp(item.id);
|
|
13404
|
+
},
|
|
13405
|
+
disabled: !canMoveUp,
|
|
13406
|
+
className: `p-1.5 rounded transition-colors ${!canMoveUp ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
|
|
13407
|
+
},
|
|
13408
|
+
/* @__PURE__ */ React28.createElement(FiArrowUp, { size: 14 })
|
|
13409
|
+
)), /* @__PURE__ */ React28.createElement(Tooltip, { text: "Descer" }, /* @__PURE__ */ React28.createElement(
|
|
13410
|
+
"button",
|
|
13411
|
+
{
|
|
13412
|
+
onClick: (e) => {
|
|
13413
|
+
e.stopPropagation();
|
|
13414
|
+
onMoveDown(item.id);
|
|
13415
|
+
},
|
|
13416
|
+
disabled: !canMoveDown,
|
|
13417
|
+
className: `p-1.5 rounded transition-colors ${!canMoveDown ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
|
|
13418
|
+
},
|
|
13419
|
+
/* @__PURE__ */ React28.createElement(FiArrowDown, { size: 14 })
|
|
13420
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-0.5" }), showIndentUp && /* @__PURE__ */ React28.createElement(Tooltip, { text: getIndentUpTooltip() }, /* @__PURE__ */ React28.createElement(
|
|
13421
|
+
"button",
|
|
13422
|
+
{
|
|
13423
|
+
onClick: (e) => {
|
|
13424
|
+
e.stopPropagation();
|
|
13425
|
+
onIndent(item.id);
|
|
13426
|
+
},
|
|
13427
|
+
className: "p-1.5 text-slate-400 hover:text-white hover:bg-white/10 rounded transition-colors"
|
|
13428
|
+
},
|
|
13429
|
+
/* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
|
|
13430
|
+
)), showIndentDown && /* @__PURE__ */ React28.createElement(Tooltip, { text: getIndentDownTooltip() }, /* @__PURE__ */ React28.createElement(
|
|
13431
|
+
"button",
|
|
13432
|
+
{
|
|
13433
|
+
onClick: (e) => {
|
|
13434
|
+
e.stopPropagation();
|
|
13435
|
+
onIndentDown(item.id);
|
|
13436
|
+
},
|
|
13437
|
+
className: "p-1.5 text-slate-400 hover:text-white hover:bg-white/10 rounded transition-colors"
|
|
13438
|
+
},
|
|
13439
|
+
/* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
|
|
13440
|
+
)), (isNested || !showIndentUp && !showIndentDown) && /* @__PURE__ */ React28.createElement(Tooltip, { text: "Desaninhar / Recuar n\xEDvel" }, /* @__PURE__ */ React28.createElement(
|
|
13441
|
+
"button",
|
|
13442
|
+
{
|
|
13443
|
+
onClick: (e) => {
|
|
13444
|
+
e.stopPropagation();
|
|
13445
|
+
onOutdent(item.id);
|
|
13446
|
+
},
|
|
13447
|
+
disabled: !onOutdent,
|
|
13448
|
+
className: `p-1.5 rounded transition-colors ${!onOutdent ? "text-slate-800 cursor-not-allowed" : "text-slate-400 hover:text-white hover:bg-white/10"}`
|
|
13449
|
+
},
|
|
13450
|
+
/* @__PURE__ */ React28.createElement(FiCornerUpRight4, { size: 14 })
|
|
13451
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-0.5" }), /* @__PURE__ */ React28.createElement(Tooltip, { text: "Remover Pasta" }, /* @__PURE__ */ React28.createElement(
|
|
13452
|
+
"button",
|
|
13453
|
+
{
|
|
13454
|
+
onClick: (e) => {
|
|
13455
|
+
e.stopPropagation();
|
|
13456
|
+
onDelete(item.id);
|
|
13457
|
+
},
|
|
13458
|
+
className: "p-1.5 text-slate-500 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors"
|
|
13459
|
+
},
|
|
13460
|
+
/* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
|
|
13461
|
+
))), /* @__PURE__ */ React28.createElement(FiChevronRight7, { className: "text-slate-500 group-hover/folder:translate-x-1 transition-transform" }))
|
|
13462
|
+
));
|
|
13463
|
+
}
|
|
13464
|
+
return /* @__PURE__ */ React28.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__ */ React28.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col gap-2 py-2 px-3 transition-all duration-200 hover:bg-white/5 border-l-2 border-transparent hover:border-white/20" }, /* @__PURE__ */ React28.createElement(
|
|
13465
|
+
RichGroupEditor,
|
|
13466
|
+
{
|
|
13467
|
+
content: item.content,
|
|
13468
|
+
onChange: handleContentChange,
|
|
13469
|
+
onMentionClick,
|
|
13470
|
+
searchItems,
|
|
13471
|
+
readOnly: !canEdit,
|
|
13472
|
+
placeholder: "Escreva sobre este grupo\u2026 ou @ para mencionar"
|
|
13473
|
+
}
|
|
13474
|
+
), canEdit && /* @__PURE__ */ React28.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__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
|
|
13475
|
+
"button",
|
|
13476
|
+
{
|
|
13477
|
+
onClick: () => onAddSubgroup(item.id, "group"),
|
|
13478
|
+
className: "flex items-center gap-1 px-1.5 py-1 text-[10px] uppercase font-bold tracking-wider text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
13479
|
+
title: "Criar Subgrupo"
|
|
13480
|
+
},
|
|
13481
|
+
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 12 }),
|
|
13482
|
+
/* @__PURE__ */ React28.createElement("span", null, "Subgrupo")
|
|
13483
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(Tooltip, { text: "Subir" }, /* @__PURE__ */ React28.createElement(
|
|
13484
|
+
"button",
|
|
13485
|
+
{
|
|
13486
|
+
onClick: () => onMoveUp(item.id),
|
|
13487
|
+
disabled: !canMoveUp,
|
|
13488
|
+
className: `p-1.5 rounded transition-colors ${!canMoveUp ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
|
|
13489
|
+
},
|
|
13490
|
+
/* @__PURE__ */ React28.createElement(FiArrowUp, { size: 14 })
|
|
13491
|
+
)), /* @__PURE__ */ React28.createElement(Tooltip, { text: "Descer" }, /* @__PURE__ */ React28.createElement(
|
|
13492
|
+
"button",
|
|
13493
|
+
{
|
|
13494
|
+
onClick: () => onMoveDown(item.id),
|
|
13495
|
+
disabled: !canMoveDown,
|
|
13496
|
+
className: `p-1.5 rounded transition-colors ${!canMoveDown ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
|
|
13497
|
+
},
|
|
13498
|
+
/* @__PURE__ */ React28.createElement(FiArrowDown, { size: 14 })
|
|
13499
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), showIndentUp && /* @__PURE__ */ React28.createElement(Tooltip, { text: getIndentUpTooltip() }, /* @__PURE__ */ React28.createElement(
|
|
13500
|
+
"button",
|
|
13501
|
+
{
|
|
13502
|
+
onClick: () => onIndent(item.id),
|
|
13503
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors"
|
|
13504
|
+
},
|
|
13505
|
+
/* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
|
|
13506
|
+
)), showIndentDown && /* @__PURE__ */ React28.createElement(Tooltip, { text: getIndentDownTooltip() }, /* @__PURE__ */ React28.createElement(
|
|
13507
|
+
"button",
|
|
13303
13508
|
{
|
|
13304
|
-
|
|
13509
|
+
onClick: () => onIndentDown(item.id),
|
|
13510
|
+
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors"
|
|
13511
|
+
},
|
|
13512
|
+
/* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
|
|
13513
|
+
)), (isNested || !showIndentUp && !showIndentDown) && /* @__PURE__ */ React28.createElement(Tooltip, { text: "Desaninhar / Recuar n\xEDvel" }, /* @__PURE__ */ React28.createElement(
|
|
13514
|
+
"button",
|
|
13515
|
+
{
|
|
13516
|
+
onClick: () => onOutdent(item.id),
|
|
13517
|
+
disabled: !onOutdent,
|
|
13518
|
+
className: `p-1.5 rounded transition-colors ${!onOutdent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`
|
|
13519
|
+
},
|
|
13520
|
+
/* @__PURE__ */ React28.createElement(FiCornerUpRight4, { size: 14 })
|
|
13521
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(Tooltip, { text: "Remover Grupo" }, /* @__PURE__ */ React28.createElement(
|
|
13522
|
+
"button",
|
|
13523
|
+
{
|
|
13524
|
+
onClick: () => onDelete(item.id),
|
|
13525
|
+
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors"
|
|
13526
|
+
},
|
|
13527
|
+
/* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
|
|
13528
|
+
))))), item.children && item.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, item.children.map((child, idx) => /* @__PURE__ */ React28.createElement(
|
|
13529
|
+
BoardItem,
|
|
13530
|
+
{
|
|
13531
|
+
key: child.id,
|
|
13305
13532
|
index: idx,
|
|
13306
|
-
|
|
13307
|
-
|
|
13533
|
+
prevItem: item.children[idx - 1],
|
|
13534
|
+
nextItem: item.children[idx + 1],
|
|
13535
|
+
item: child,
|
|
13308
13536
|
onUpdate,
|
|
13309
13537
|
onDelete,
|
|
13310
13538
|
onAddSubgroup,
|
|
13311
13539
|
onIndent,
|
|
13540
|
+
onIndentDown,
|
|
13312
13541
|
onOutdent,
|
|
13313
|
-
|
|
13314
|
-
|
|
13542
|
+
onMoveUp,
|
|
13543
|
+
onMoveDown,
|
|
13544
|
+
searchItems,
|
|
13545
|
+
onMentionClick,
|
|
13546
|
+
onEnterFolder,
|
|
13315
13547
|
canEdit
|
|
13316
13548
|
}
|
|
13317
13549
|
))));
|
|
@@ -13326,140 +13558,181 @@ function AncestryBoard({
|
|
|
13326
13558
|
onSave,
|
|
13327
13559
|
userRole
|
|
13328
13560
|
}) {
|
|
13329
|
-
const [groups, setGroups] =
|
|
13330
|
-
const [isLoaded, setIsLoaded] =
|
|
13331
|
-
const [saveStatus, setSaveStatus] =
|
|
13332
|
-
const
|
|
13333
|
-
|
|
13334
|
-
|
|
13561
|
+
const [groups, setGroups] = useState27([]);
|
|
13562
|
+
const [isLoaded, setIsLoaded] = useState27(false);
|
|
13563
|
+
const [saveStatus, setSaveStatus] = useState27("idle");
|
|
13564
|
+
const [navigationStack, setNavigationStack] = useState27([]);
|
|
13565
|
+
const lastSavedGroupsRef = useRef20(null);
|
|
13566
|
+
const canEdit = useMemo12(() => userRole !== "viewer", [userRole]);
|
|
13335
13567
|
useEffect23(() => {
|
|
13336
13568
|
if (initialGroups && !isLoaded) {
|
|
13337
|
-
|
|
13569
|
+
const migrate = (list) => list.map((g) => ({
|
|
13570
|
+
id: g.id || uuidv411(),
|
|
13571
|
+
type: g.type || "group",
|
|
13572
|
+
name: g.name || "",
|
|
13573
|
+
content: Array.isArray(g.content) ? g.content : [],
|
|
13574
|
+
children: migrate(g.children || [])
|
|
13575
|
+
}));
|
|
13576
|
+
setGroups(migrate(initialGroups));
|
|
13338
13577
|
setIsLoaded(true);
|
|
13339
13578
|
}
|
|
13340
13579
|
}, [initialGroups, isLoaded]);
|
|
13341
|
-
const
|
|
13342
|
-
const
|
|
13343
|
-
|
|
13344
|
-
|
|
13345
|
-
|
|
13346
|
-
|
|
13347
|
-
|
|
13580
|
+
const allSearchableItems = useMemo12(() => {
|
|
13581
|
+
const items = [];
|
|
13582
|
+
availableAncestries.forEach((anc) => {
|
|
13583
|
+
items.push({
|
|
13584
|
+
...anc,
|
|
13585
|
+
id: String(anc.ancestry_id),
|
|
13586
|
+
type: "ancestry",
|
|
13587
|
+
searchLabel: anc.name || "",
|
|
13588
|
+
searchDesc: anc.description || ""
|
|
13348
13589
|
});
|
|
13349
|
-
}
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
const availableIds = useMemo12(() => {
|
|
13353
|
-
return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
|
|
13354
|
-
}, [availableAncestries]);
|
|
13355
|
-
const availableMentionItems = useMemo12(() => {
|
|
13356
|
-
const ancestries = availableAncestries.map((a) => ({
|
|
13357
|
-
id: String(a.ancestry_id),
|
|
13358
|
-
ancestry_id: a.ancestry_id,
|
|
13359
|
-
name: a.name,
|
|
13360
|
-
description: a.description,
|
|
13361
|
-
type: "ancestry",
|
|
13362
|
-
ancestral_node: a.ancestral_node,
|
|
13363
|
-
is_private: a.is_private
|
|
13364
|
-
}));
|
|
13365
|
-
const nodes = availableNodes.map((n) => {
|
|
13590
|
+
});
|
|
13591
|
+
availableNodes.forEach((node) => {
|
|
13592
|
+
var _a;
|
|
13366
13593
|
let type = "node";
|
|
13367
|
-
if (
|
|
13368
|
-
else if (
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
description: n.description,
|
|
13594
|
+
if (node.is_quest) type = "quest";
|
|
13595
|
+
else if ((_a = node.version_node) == null ? void 0 : _a.is_version) type = "version";
|
|
13596
|
+
items.push({
|
|
13597
|
+
...node,
|
|
13598
|
+
id: String(node.id),
|
|
13373
13599
|
type,
|
|
13374
|
-
|
|
13375
|
-
|
|
13600
|
+
searchLabel: node.name || node.raw_title || "",
|
|
13601
|
+
searchDesc: node.description || ""
|
|
13602
|
+
});
|
|
13376
13603
|
});
|
|
13377
|
-
return
|
|
13604
|
+
return items;
|
|
13378
13605
|
}, [availableAncestries, availableNodes]);
|
|
13379
|
-
const sanitizeGroups = (
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
};
|
|
13606
|
+
const sanitizeGroups = (list) => list.map((g) => ({
|
|
13607
|
+
id: g.id,
|
|
13608
|
+
type: g.type || "group",
|
|
13609
|
+
name: g.name || "",
|
|
13610
|
+
content: g.content || [],
|
|
13611
|
+
children: sanitizeGroups(g.children || [])
|
|
13612
|
+
}));
|
|
13386
13613
|
useEffect23(() => {
|
|
13387
13614
|
if (!isLoaded || !onSave) return;
|
|
13388
|
-
const
|
|
13615
|
+
const id = setTimeout(async () => {
|
|
13616
|
+
const currentSanitized = sanitizeGroups(groups);
|
|
13617
|
+
const currentJson = JSON.stringify(currentSanitized);
|
|
13618
|
+
if (currentJson === lastSavedGroupsRef.current) return;
|
|
13389
13619
|
setSaveStatus("saving");
|
|
13390
|
-
const cleanData = sanitizeGroups(groups);
|
|
13391
13620
|
try {
|
|
13392
|
-
await onSave(
|
|
13621
|
+
await onSave(currentSanitized);
|
|
13622
|
+
lastSavedGroupsRef.current = currentJson;
|
|
13393
13623
|
setSaveStatus("saved");
|
|
13394
|
-
setTimeout(() =>
|
|
13395
|
-
|
|
13396
|
-
|
|
13397
|
-
} catch (error) {
|
|
13398
|
-
console.error("Erro ao salvar board:", error);
|
|
13624
|
+
setTimeout(() => setSaveStatus("idle"), 3e3);
|
|
13625
|
+
} catch (err) {
|
|
13626
|
+
console.error("Erro ao salvar board:", err);
|
|
13399
13627
|
setSaveStatus("error");
|
|
13400
13628
|
}
|
|
13401
13629
|
}, 3e3);
|
|
13402
|
-
return () => clearTimeout(
|
|
13630
|
+
return () => clearTimeout(id);
|
|
13403
13631
|
}, [groups, isLoaded, onSave]);
|
|
13632
|
+
const triggerInstantSave = async (updatedGroups) => {
|
|
13633
|
+
if (!onSave) return;
|
|
13634
|
+
const sanitized = sanitizeGroups(updatedGroups);
|
|
13635
|
+
const sanitizedJson = JSON.stringify(sanitized);
|
|
13636
|
+
lastSavedGroupsRef.current = sanitizedJson;
|
|
13637
|
+
setSaveStatus("saving");
|
|
13638
|
+
try {
|
|
13639
|
+
await onSave(sanitized);
|
|
13640
|
+
setSaveStatus("saved");
|
|
13641
|
+
setTimeout(() => setSaveStatus("idle"), 3e3);
|
|
13642
|
+
} catch (err) {
|
|
13643
|
+
console.error("Erro ao salvar board:", err);
|
|
13644
|
+
setSaveStatus("error");
|
|
13645
|
+
}
|
|
13646
|
+
};
|
|
13404
13647
|
useEffect23(() => {
|
|
13405
13648
|
if (!isOpen) return;
|
|
13406
|
-
const
|
|
13649
|
+
const handler = (e) => {
|
|
13407
13650
|
if (e.key === "Escape") {
|
|
13408
13651
|
onClose();
|
|
13409
13652
|
e.preventDefault();
|
|
13410
13653
|
e.stopPropagation();
|
|
13411
13654
|
}
|
|
13412
13655
|
};
|
|
13413
|
-
window.addEventListener("keydown",
|
|
13414
|
-
return () => window.removeEventListener("keydown",
|
|
13656
|
+
window.addEventListener("keydown", handler);
|
|
13657
|
+
return () => window.removeEventListener("keydown", handler);
|
|
13415
13658
|
}, [isOpen, onClose]);
|
|
13416
|
-
const
|
|
13417
|
-
const
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
13421
|
-
|
|
13422
|
-
|
|
13659
|
+
const currentPath = useMemo12(() => {
|
|
13660
|
+
const path = [];
|
|
13661
|
+
let currentLevel = groups;
|
|
13662
|
+
for (const folderId of navigationStack) {
|
|
13663
|
+
const folder = currentLevel.find((f) => f.id === folderId);
|
|
13664
|
+
if (folder) {
|
|
13665
|
+
path.push(folder);
|
|
13666
|
+
currentLevel = folder.children;
|
|
13667
|
+
}
|
|
13668
|
+
}
|
|
13669
|
+
return path;
|
|
13670
|
+
}, [groups, navigationStack]);
|
|
13671
|
+
const currentGroups = useMemo12(() => {
|
|
13672
|
+
const lastFolder = currentPath[currentPath.length - 1];
|
|
13673
|
+
return lastFolder ? lastFolder.children : groups;
|
|
13674
|
+
}, [groups, currentPath]);
|
|
13675
|
+
const navigateUp = () => {
|
|
13676
|
+
setNavigationStack((prev) => prev.slice(0, -1));
|
|
13677
|
+
};
|
|
13678
|
+
const navigateTo = (folderId) => {
|
|
13679
|
+
setNavigationStack((prev) => [...prev, folderId]);
|
|
13680
|
+
};
|
|
13681
|
+
const navigateToBreadcrumb = (index) => {
|
|
13682
|
+
setNavigationStack((prev) => prev.slice(0, index + 1));
|
|
13683
|
+
};
|
|
13684
|
+
const navigateHome = () => {
|
|
13685
|
+
setNavigationStack([]);
|
|
13423
13686
|
};
|
|
13424
|
-
const
|
|
13425
|
-
const
|
|
13687
|
+
const handleAddItem = (type = "group") => {
|
|
13688
|
+
const newItem = {
|
|
13426
13689
|
id: uuidv411(),
|
|
13427
|
-
|
|
13690
|
+
type,
|
|
13691
|
+
name: type === "folder" ? "Nova Pasta" : "",
|
|
13692
|
+
content: [],
|
|
13428
13693
|
children: []
|
|
13429
13694
|
};
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
|
|
13433
|
-
|
|
13434
|
-
|
|
13435
|
-
|
|
13436
|
-
|
|
13437
|
-
|
|
13438
|
-
|
|
13695
|
+
if (navigationStack.length === 0) {
|
|
13696
|
+
setGroups((prev) => [...prev, newItem]);
|
|
13697
|
+
} else {
|
|
13698
|
+
const parentId = navigationStack[navigationStack.length - 1];
|
|
13699
|
+
const add = (list) => list.map(
|
|
13700
|
+
(g) => g.id === parentId ? { ...g, children: [...g.children, newItem] } : { ...g, children: add(g.children) }
|
|
13701
|
+
);
|
|
13702
|
+
setGroups((prev) => add(prev));
|
|
13703
|
+
}
|
|
13439
13704
|
};
|
|
13440
|
-
const
|
|
13441
|
-
const
|
|
13442
|
-
|
|
13443
|
-
if (g.
|
|
13444
|
-
|
|
13445
|
-
|
|
13446
|
-
|
|
13447
|
-
|
|
13705
|
+
const handleAddSubgroup = (parentId, type = "group") => {
|
|
13706
|
+
const add = (list) => list.map((g) => {
|
|
13707
|
+
if (g.id === parentId) {
|
|
13708
|
+
if (g.type === "group" && type === "folder") return g;
|
|
13709
|
+
const newItem = {
|
|
13710
|
+
id: uuidv411(),
|
|
13711
|
+
type,
|
|
13712
|
+
name: type === "folder" ? "Nova Pasta" : "",
|
|
13713
|
+
content: [],
|
|
13714
|
+
children: []
|
|
13715
|
+
};
|
|
13716
|
+
return { ...g, children: [...g.children, newItem] };
|
|
13717
|
+
}
|
|
13718
|
+
return { ...g, children: add(g.children) };
|
|
13719
|
+
});
|
|
13720
|
+
setGroups((prev) => add(prev));
|
|
13448
13721
|
};
|
|
13449
|
-
const
|
|
13450
|
-
const
|
|
13451
|
-
|
|
13452
|
-
|
|
13453
|
-
|
|
13454
|
-
|
|
13455
|
-
|
|
13456
|
-
|
|
13722
|
+
const handleUpdateItem = (id, newData) => {
|
|
13723
|
+
const update = (list) => list.map(
|
|
13724
|
+
(g) => g.id === id ? newData : { ...g, children: update(g.children) }
|
|
13725
|
+
);
|
|
13726
|
+
setGroups((prev) => update(prev));
|
|
13727
|
+
};
|
|
13728
|
+
const handleDeleteItem = (id) => {
|
|
13729
|
+
const del = (list) => list.filter((g) => g.id !== id).map((g) => ({ ...g, children: del(g.children) }));
|
|
13730
|
+
setGroups((prev) => del(prev));
|
|
13457
13731
|
};
|
|
13458
13732
|
const findGroupAndParent = (list, targetId, parent = null) => {
|
|
13459
13733
|
for (let i = 0; i < list.length; i++) {
|
|
13460
|
-
if (list[i].id === targetId)
|
|
13734
|
+
if (list[i].id === targetId)
|
|
13461
13735
|
return { group: list[i], parent, index: i, siblings: list };
|
|
13462
|
-
}
|
|
13463
13736
|
if (list[i].children.length > 0) {
|
|
13464
13737
|
const found = findGroupAndParent(list[i].children, targetId, list[i]);
|
|
13465
13738
|
if (found) return found;
|
|
@@ -13468,47 +13741,72 @@ function AncestryBoard({
|
|
|
13468
13741
|
return null;
|
|
13469
13742
|
};
|
|
13470
13743
|
const handleIndent = (id) => {
|
|
13471
|
-
|
|
13472
|
-
|
|
13473
|
-
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
|
|
13480
|
-
|
|
13744
|
+
const next = JSON.parse(JSON.stringify(groups));
|
|
13745
|
+
const found = findGroupAndParent(next, id);
|
|
13746
|
+
if (!found || found.index === 0) return;
|
|
13747
|
+
const { group, siblings, index } = found;
|
|
13748
|
+
const targetParent = siblings[index - 1];
|
|
13749
|
+
if (group.type === "folder" && targetParent.type === "group") {
|
|
13750
|
+
return;
|
|
13751
|
+
}
|
|
13752
|
+
siblings.splice(index, 1);
|
|
13753
|
+
targetParent.children.push(group);
|
|
13754
|
+
setGroups(next);
|
|
13755
|
+
triggerInstantSave(next);
|
|
13481
13756
|
};
|
|
13482
|
-
const
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
return newList;
|
|
13496
|
-
});
|
|
13757
|
+
const handleIndentDown = (id) => {
|
|
13758
|
+
const next = JSON.parse(JSON.stringify(groups));
|
|
13759
|
+
const found = findGroupAndParent(next, id);
|
|
13760
|
+
if (!found || found.index === found.siblings.length - 1) return;
|
|
13761
|
+
const { group, siblings, index } = found;
|
|
13762
|
+
const targetParent = siblings[index + 1];
|
|
13763
|
+
if (group.type === "folder" && targetParent.type === "group") {
|
|
13764
|
+
return;
|
|
13765
|
+
}
|
|
13766
|
+
siblings.splice(index, 1);
|
|
13767
|
+
targetParent.children.push(group);
|
|
13768
|
+
setGroups(next);
|
|
13769
|
+
triggerInstantSave(next);
|
|
13497
13770
|
};
|
|
13498
|
-
const
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13771
|
+
const handleOutdent = (id) => {
|
|
13772
|
+
const next = JSON.parse(JSON.stringify(groups));
|
|
13773
|
+
const found = findGroupAndParent(next, id);
|
|
13774
|
+
if (!found || !found.parent) return;
|
|
13775
|
+
const { group, siblings, index, parent } = found;
|
|
13776
|
+
siblings.splice(index, 1);
|
|
13777
|
+
const parentFound = findGroupAndParent(next, parent.id);
|
|
13778
|
+
if (parentFound) {
|
|
13779
|
+
parentFound.siblings.splice(parentFound.index + 1, 0, group);
|
|
13504
13780
|
} else {
|
|
13505
|
-
|
|
13506
|
-
(n) => String(n.id) === String(item.id)
|
|
13507
|
-
) || item;
|
|
13508
|
-
}
|
|
13509
|
-
if (fullItem && onSelect) {
|
|
13510
|
-
onSelect(fullItem);
|
|
13781
|
+
next.push(group);
|
|
13511
13782
|
}
|
|
13783
|
+
setGroups(next);
|
|
13784
|
+
triggerInstantSave(next);
|
|
13785
|
+
};
|
|
13786
|
+
const handleMoveUp = (id) => {
|
|
13787
|
+
const next = JSON.parse(JSON.stringify(groups));
|
|
13788
|
+
const found = findGroupAndParent(next, id);
|
|
13789
|
+
if (!found || found.index === 0) return;
|
|
13790
|
+
const { siblings, index } = found;
|
|
13791
|
+
const item = siblings[index];
|
|
13792
|
+
siblings.splice(index, 1);
|
|
13793
|
+
siblings.splice(index - 1, 0, item);
|
|
13794
|
+
setGroups(next);
|
|
13795
|
+
triggerInstantSave(next);
|
|
13796
|
+
};
|
|
13797
|
+
const handleMoveDown = (id) => {
|
|
13798
|
+
const next = JSON.parse(JSON.stringify(groups));
|
|
13799
|
+
const found = findGroupAndParent(next, id);
|
|
13800
|
+
if (!found || found.index === found.siblings.length - 1) return;
|
|
13801
|
+
const { siblings, index } = found;
|
|
13802
|
+
const item = siblings[index];
|
|
13803
|
+
siblings.splice(index, 1);
|
|
13804
|
+
siblings.splice(index + 1, 0, item);
|
|
13805
|
+
setGroups(next);
|
|
13806
|
+
triggerInstantSave(next);
|
|
13807
|
+
};
|
|
13808
|
+
const handleMentionClick = (item) => {
|
|
13809
|
+
if (onSelect) onSelect(item);
|
|
13512
13810
|
};
|
|
13513
13811
|
if (!isOpen) return null;
|
|
13514
13812
|
return /* @__PURE__ */ React28.createElement(
|
|
@@ -13520,61 +13818,85 @@ function AncestryBoard({
|
|
|
13520
13818
|
/* @__PURE__ */ React28.createElement(
|
|
13521
13819
|
"div",
|
|
13522
13820
|
{
|
|
13523
|
-
className: "bg-slate-950 border border-white/10 rounded-xl w-[
|
|
13821
|
+
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",
|
|
13524
13822
|
onClick: (e) => e.stopPropagation()
|
|
13525
13823
|
},
|
|
13526
|
-
/* @__PURE__ */ React28.createElement("div", { className: "h-14 px-
|
|
13527
|
-
|
|
13824
|
+
/* @__PURE__ */ React28.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React28.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ React28.createElement(FiLayers7, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ React28.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ React28.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__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiLoader5, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ React28.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-3" }, canEdit && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(
|
|
13825
|
+
"button",
|
|
13528
13826
|
{
|
|
13529
|
-
|
|
13530
|
-
|
|
13531
|
-
}
|
|
13532
|
-
|
|
13827
|
+
onClick: () => handleAddItem("folder"),
|
|
13828
|
+
className: "flex items-center gap-2 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 backdrop-blur-sm text-slate-200 hover:text-white rounded-md transition-all duration-200 text-xs font-medium shadow-sm"
|
|
13829
|
+
},
|
|
13830
|
+
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-amber-400" }),
|
|
13831
|
+
/* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Nova Pasta")
|
|
13832
|
+
), /* @__PURE__ */ React28.createElement(
|
|
13533
13833
|
"button",
|
|
13534
13834
|
{
|
|
13535
|
-
onClick:
|
|
13536
|
-
className: "
|
|
13835
|
+
onClick: () => handleAddItem("group"),
|
|
13836
|
+
className: "flex items-center gap-2 px-3 py-1.5 bg-white/5 hover:bg-white/10 border border-white/10 hover:border-white/20 backdrop-blur-sm text-slate-200 hover:text-white rounded-md transition-all duration-200 text-xs font-medium shadow-sm"
|
|
13537
13837
|
},
|
|
13538
13838
|
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
|
|
13539
13839
|
/* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
|
|
13540
|
-
), /* @__PURE__ */ React28.createElement(
|
|
13840
|
+
)), /* @__PURE__ */ React28.createElement(
|
|
13541
13841
|
"button",
|
|
13542
13842
|
{
|
|
13543
13843
|
onClick: onClose,
|
|
13544
13844
|
className: "w-8 h-8 rounded-lg flex items-center justify-center text-slate-400 hover:text-white hover:bg-white/10 transition-colors"
|
|
13545
13845
|
},
|
|
13546
|
-
|
|
13846
|
+
/* @__PURE__ */ React28.createElement(FiX8, { size: 16 })
|
|
13547
13847
|
))),
|
|
13548
|
-
/* @__PURE__ */ React28.createElement("div", { className: "
|
|
13848
|
+
/* @__PURE__ */ React28.createElement("div", { className: "h-10 px-6 bg-slate-900/40 border-b border-white/5 flex items-center gap-2 text-[10px] uppercase font-bold tracking-widest text-slate-500 overflow-x-auto no-scrollbar whitespace-nowrap" }, /* @__PURE__ */ React28.createElement(
|
|
13549
13849
|
"button",
|
|
13550
13850
|
{
|
|
13551
|
-
onClick:
|
|
13552
|
-
className:
|
|
13851
|
+
onClick: navigateHome,
|
|
13852
|
+
className: `hover:text-white transition-colors flex items-center gap-1 ${navigationStack.length === 0 ? "text-indigo-400" : ""}`
|
|
13553
13853
|
},
|
|
13554
|
-
"
|
|
13555
|
-
)
|
|
13556
|
-
|
|
13854
|
+
"Home"
|
|
13855
|
+
), currentPath.map((folder, idx) => /* @__PURE__ */ React28.createElement(React28.Fragment, { key: folder.id }, /* @__PURE__ */ React28.createElement(FiChevronRight7, { size: 10, className: "shrink-0" }), /* @__PURE__ */ React28.createElement(
|
|
13856
|
+
"button",
|
|
13857
|
+
{
|
|
13858
|
+
onClick: () => navigateToBreadcrumb(idx),
|
|
13859
|
+
className: `hover:text-white transition-colors ${idx === currentPath.length - 1 ? "text-indigo-400" : ""}`
|
|
13860
|
+
},
|
|
13861
|
+
folder.name || "Sem Nome"
|
|
13862
|
+
))), navigationStack.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-auto" }, /* @__PURE__ */ React28.createElement(
|
|
13863
|
+
"button",
|
|
13864
|
+
{
|
|
13865
|
+
onClick: navigateUp,
|
|
13866
|
+
className: "flex items-center gap-1 px-2 py-1 rounded bg-white/5 hover:bg-white/10 text-slate-400 hover:text-white transition-all"
|
|
13867
|
+
},
|
|
13868
|
+
/* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 10 }),
|
|
13869
|
+
/* @__PURE__ */ React28.createElement("span", null, "Voltar")
|
|
13870
|
+
))),
|
|
13871
|
+
/* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar bg-slate-950/30 p-6 space-y-4" }, currentGroups.length === 0 ? /* @__PURE__ */ React28.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 bg-slate-900/20" }, /* @__PURE__ */ React28.createElement(FiLayers7, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Esta pasta est\xE1 vazia.", /* @__PURE__ */ React28.createElement("br", null), "Use os bot\xF5es acima para criar conte\xFAdo.") : /* @__PURE__ */ React28.createElement(React28.Fragment, null, "Nenhum conte\xFAdo dispon\xEDvel nesta pasta."))) : currentGroups.map((item, index) => /* @__PURE__ */ React28.createElement(
|
|
13872
|
+
BoardItem,
|
|
13557
13873
|
{
|
|
13558
|
-
key:
|
|
13874
|
+
key: item.id,
|
|
13559
13875
|
index,
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13876
|
+
prevItem: currentGroups[index - 1],
|
|
13877
|
+
nextItem: currentGroups[index + 1],
|
|
13878
|
+
item,
|
|
13879
|
+
onUpdate: handleUpdateItem,
|
|
13880
|
+
onDelete: handleDeleteItem,
|
|
13563
13881
|
onAddSubgroup: handleAddSubgroup,
|
|
13564
13882
|
onIndent: handleIndent,
|
|
13883
|
+
onIndentDown: handleIndentDown,
|
|
13565
13884
|
onOutdent: handleOutdent,
|
|
13566
|
-
|
|
13567
|
-
|
|
13885
|
+
onMoveUp: handleMoveUp,
|
|
13886
|
+
onMoveDown: handleMoveDown,
|
|
13887
|
+
searchItems: allSearchableItems,
|
|
13888
|
+
onMentionClick: handleMentionClick,
|
|
13889
|
+
onEnterFolder: navigateTo,
|
|
13568
13890
|
canEdit
|
|
13569
13891
|
}
|
|
13570
|
-
)))
|
|
13571
|
-
/* @__PURE__ */ React28.createElement("div", { className: "px-
|
|
13892
|
+
))),
|
|
13893
|
+
/* @__PURE__ */ React28.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-end flex-shrink-0" }, /* @__PURE__ */ React28.createElement("span", null, currentGroups.length, " itens nesta visualiza\xE7\xE3o"))
|
|
13572
13894
|
)
|
|
13573
13895
|
);
|
|
13574
13896
|
}
|
|
13575
13897
|
|
|
13576
13898
|
// src/components/MilestoneManager.jsx
|
|
13577
|
-
import React29, { useState as
|
|
13899
|
+
import React29, { useState as useState28 } from "react";
|
|
13578
13900
|
import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
|
|
13579
13901
|
function MilestoneManager({
|
|
13580
13902
|
isOpen,
|
|
@@ -13583,7 +13905,7 @@ function MilestoneManager({
|
|
|
13583
13905
|
onUpdateMilestones = () => {
|
|
13584
13906
|
}
|
|
13585
13907
|
}) {
|
|
13586
|
-
const [newMilestoneName, setNewMilestoneName] =
|
|
13908
|
+
const [newMilestoneName, setNewMilestoneName] = useState28("");
|
|
13587
13909
|
const handleAddMilestone = () => {
|
|
13588
13910
|
if (!newMilestoneName.trim()) return;
|
|
13589
13911
|
const newMilestone = {
|
|
@@ -13764,7 +14086,7 @@ function XViewScene({
|
|
|
13764
14086
|
check_user_permission,
|
|
13765
14087
|
get_view_members
|
|
13766
14088
|
}) {
|
|
13767
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l
|
|
14089
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
13768
14090
|
const { data: session, status } = useSession();
|
|
13769
14091
|
const router = useRouter();
|
|
13770
14092
|
const searchParams = useSearchParams();
|
|
@@ -13836,45 +14158,45 @@ function XViewScene({
|
|
|
13836
14158
|
}
|
|
13837
14159
|
return null;
|
|
13838
14160
|
}, [ownerId, sceneConfigId]);
|
|
13839
|
-
const sceneDataRef =
|
|
13840
|
-
const parentDataRef =
|
|
13841
|
-
const ancestryDataRef =
|
|
13842
|
-
const [isLoading, setIsLoading] =
|
|
13843
|
-
const [permissionStatus, setPermissionStatus] =
|
|
13844
|
-
const [userPermissionRole, setUserPermissionRole] =
|
|
13845
|
-
const [viewMembers, setViewMembers] =
|
|
13846
|
-
const [isInitialized, setIsInitialized] =
|
|
13847
|
-
const [sceneVersion, setSceneVersion] =
|
|
13848
|
-
const [contextMenu, setContextMenu] =
|
|
14161
|
+
const sceneDataRef = useRef21(null);
|
|
14162
|
+
const parentDataRef = useRef21(null);
|
|
14163
|
+
const ancestryDataRef = useRef21(null);
|
|
14164
|
+
const [isLoading, setIsLoading] = useState29(true);
|
|
14165
|
+
const [permissionStatus, setPermissionStatus] = useState29("loading");
|
|
14166
|
+
const [userPermissionRole, setUserPermissionRole] = useState29(null);
|
|
14167
|
+
const [viewMembers, setViewMembers] = useState29([]);
|
|
14168
|
+
const [isInitialized, setIsInitialized] = useState29(false);
|
|
14169
|
+
const [sceneVersion, setSceneVersion] = useState29(0);
|
|
14170
|
+
const [contextMenu, setContextMenu] = useState29({
|
|
13849
14171
|
visible: false,
|
|
13850
14172
|
x: 0,
|
|
13851
14173
|
y: 0,
|
|
13852
14174
|
nodeData: null
|
|
13853
14175
|
});
|
|
13854
|
-
const [multiContextMenu, setMultiContextMenu] =
|
|
14176
|
+
const [multiContextMenu, setMultiContextMenu] = useState29({
|
|
13855
14177
|
visible: false,
|
|
13856
14178
|
x: 0,
|
|
13857
14179
|
y: 0,
|
|
13858
14180
|
nodeIds: null
|
|
13859
14181
|
});
|
|
13860
|
-
const [relationshipMenu, setRelationshipMenu] =
|
|
14182
|
+
const [relationshipMenu, setRelationshipMenu] = useState29({
|
|
13861
14183
|
visible: false,
|
|
13862
14184
|
x: 0,
|
|
13863
14185
|
y: 0,
|
|
13864
14186
|
linkObject: null
|
|
13865
14187
|
});
|
|
13866
|
-
const [creationMode, setCreationMode] =
|
|
14188
|
+
const [creationMode, setCreationMode] = useState29({
|
|
13867
14189
|
isActive: false,
|
|
13868
14190
|
sourceNodeData: null
|
|
13869
14191
|
});
|
|
13870
|
-
const [versionMode, setVersionMode] =
|
|
14192
|
+
const [versionMode, setVersionMode] = useState29({
|
|
13871
14193
|
isActive: false,
|
|
13872
14194
|
sourceNodeData: null
|
|
13873
14195
|
});
|
|
13874
|
-
const [questMode, setQuestMode] =
|
|
13875
|
-
const [hasFocusedInitial, setHasFocusedInitial] =
|
|
13876
|
-
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] =
|
|
13877
|
-
const [ancestryMode, setAncestryMode] =
|
|
14196
|
+
const [questMode, setQuestMode] = useState29({ isActive: false });
|
|
14197
|
+
const [hasFocusedInitial, setHasFocusedInitial] = useState29(false);
|
|
14198
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState29(false);
|
|
14199
|
+
const [ancestryMode, setAncestryMode] = useState29({
|
|
13878
14200
|
isActive: false,
|
|
13879
14201
|
tree: null,
|
|
13880
14202
|
selectedParentId: null,
|
|
@@ -13885,42 +14207,42 @@ function XViewScene({
|
|
|
13885
14207
|
ancestryDescriptionSections: [],
|
|
13886
14208
|
isAddingNodes: false
|
|
13887
14209
|
});
|
|
13888
|
-
const [readingMode, setReadingMode] =
|
|
14210
|
+
const [readingMode, setReadingMode] = useState29({
|
|
13889
14211
|
isActive: false,
|
|
13890
14212
|
ancestry: null,
|
|
13891
14213
|
branchStack: [],
|
|
13892
14214
|
autoAbstraction: false
|
|
13893
14215
|
});
|
|
13894
|
-
const [formPosition, setFormPosition] =
|
|
14216
|
+
const [formPosition, setFormPosition] = useState29({
|
|
13895
14217
|
left: 16,
|
|
13896
14218
|
top: 16,
|
|
13897
14219
|
opacity: 0
|
|
13898
14220
|
});
|
|
13899
|
-
const [detailsNode, setDetailsNode] =
|
|
13900
|
-
const [detailsLink, setDetailsLink] =
|
|
13901
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] =
|
|
13902
|
-
const [imageViewer, setImageViewer] =
|
|
14221
|
+
const [detailsNode, setDetailsNode] = useState29(null);
|
|
14222
|
+
const [detailsLink, setDetailsLink] = useState29(null);
|
|
14223
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = useState29(null);
|
|
14224
|
+
const [imageViewer, setImageViewer] = useState29({
|
|
13903
14225
|
visible: false,
|
|
13904
14226
|
images: [],
|
|
13905
14227
|
startIndex: 0
|
|
13906
14228
|
});
|
|
13907
|
-
const [editingAncestryRel, setEditingAncestryRel] =
|
|
14229
|
+
const [editingAncestryRel, setEditingAncestryRel] = useState29({
|
|
13908
14230
|
visible: false,
|
|
13909
14231
|
data: null,
|
|
13910
14232
|
path: null
|
|
13911
14233
|
});
|
|
13912
|
-
const [isImportModalOpen, setIsImportModalOpen] =
|
|
13913
|
-
const [importSuccessMessage, setImportSuccessMessage] =
|
|
13914
|
-
const [invalidTargetError, setInvalidTargetError] =
|
|
13915
|
-
const [highlightedNodeId, setHighlightedNodeId] =
|
|
13916
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] =
|
|
13917
|
-
const [ancestryBoardData, setAncestryBoardData] =
|
|
13918
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
13919
|
-
const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] =
|
|
13920
|
-
const mountRef =
|
|
13921
|
-
const tooltipRef =
|
|
13922
|
-
const formRef =
|
|
13923
|
-
const stateRef =
|
|
14234
|
+
const [isImportModalOpen, setIsImportModalOpen] = useState29(false);
|
|
14235
|
+
const [importSuccessMessage, setImportSuccessMessage] = useState29("");
|
|
14236
|
+
const [invalidTargetError, setInvalidTargetError] = useState29(null);
|
|
14237
|
+
const [highlightedNodeId, setHighlightedNodeId] = useState29(null);
|
|
14238
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState29(false);
|
|
14239
|
+
const [ancestryBoardData, setAncestryBoardData] = useState29([]);
|
|
14240
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState29(false);
|
|
14241
|
+
const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState29(false);
|
|
14242
|
+
const mountRef = useRef21(null);
|
|
14243
|
+
const tooltipRef = useRef21(null);
|
|
14244
|
+
const formRef = useRef21(null);
|
|
14245
|
+
const stateRef = useRef21({
|
|
13924
14246
|
readMode: {
|
|
13925
14247
|
currentMaxIndex: 0,
|
|
13926
14248
|
progressMap: {}
|
|
@@ -14010,10 +14332,10 @@ function XViewScene({
|
|
|
14010
14332
|
}
|
|
14011
14333
|
stateRef.current.nodeIdToParentFileMap = map;
|
|
14012
14334
|
}, [isInitialized, sceneVersion]);
|
|
14013
|
-
const handleNavigateBack =
|
|
14335
|
+
const handleNavigateBack = useCallback5(() => {
|
|
14014
14336
|
router.push("/dashboard/scenes");
|
|
14015
14337
|
}, [router]);
|
|
14016
|
-
const handleConfirmImport =
|
|
14338
|
+
const handleConfirmImport = useCallback5(
|
|
14017
14339
|
async (importPayload) => {
|
|
14018
14340
|
var _a2, _b2;
|
|
14019
14341
|
let files = [];
|
|
@@ -14141,7 +14463,7 @@ function XViewScene({
|
|
|
14141
14463
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
14142
14464
|
setImageViewer({ visible: true, images, startIndex });
|
|
14143
14465
|
};
|
|
14144
|
-
const tweenToTarget =
|
|
14466
|
+
const tweenToTarget = useCallback5(
|
|
14145
14467
|
(target, zoomFactor = 1, forcedDirection = null) => {
|
|
14146
14468
|
const { camera, controls, tweenGroup } = stateRef.current;
|
|
14147
14469
|
if (!camera || !controls || !tweenGroup) return;
|
|
@@ -14167,7 +14489,7 @@ function XViewScene({
|
|
|
14167
14489
|
if (!t || typeof t.closest !== "function") return false;
|
|
14168
14490
|
return !!t.closest(".ui-overlay");
|
|
14169
14491
|
};
|
|
14170
|
-
const buildFullAncestryTree =
|
|
14492
|
+
const buildFullAncestryTree = useCallback5(
|
|
14171
14493
|
(idTree, nodes, ancestries = []) => {
|
|
14172
14494
|
if (!idTree) return null;
|
|
14173
14495
|
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
@@ -14252,7 +14574,7 @@ function XViewScene({
|
|
|
14252
14574
|
},
|
|
14253
14575
|
[]
|
|
14254
14576
|
);
|
|
14255
|
-
const handleActivateTimeline =
|
|
14577
|
+
const handleActivateTimeline = useCallback5(() => {
|
|
14256
14578
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
14257
14579
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
14258
14580
|
while (timelineIntervalsGroup.children.length > 0) {
|
|
@@ -14412,7 +14734,7 @@ function XViewScene({
|
|
|
14412
14734
|
}
|
|
14413
14735
|
});
|
|
14414
14736
|
}, []);
|
|
14415
|
-
const handleVersionTimeline =
|
|
14737
|
+
const handleVersionTimeline = useCallback5((sourceMesh, versionMeshes) => {
|
|
14416
14738
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
14417
14739
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
14418
14740
|
return;
|
|
@@ -14654,12 +14976,12 @@ function XViewScene({
|
|
|
14654
14976
|
focusNodeId,
|
|
14655
14977
|
focusAncestryId
|
|
14656
14978
|
]);
|
|
14657
|
-
const isNodeInView =
|
|
14979
|
+
const isNodeInView = useCallback5((id) => {
|
|
14658
14980
|
const key = String(id);
|
|
14659
14981
|
const objs = stateRef.current.nodeObjects || {};
|
|
14660
14982
|
return !!objs[key];
|
|
14661
14983
|
}, []);
|
|
14662
|
-
const addOrUpdateNodeMesh =
|
|
14984
|
+
const addOrUpdateNodeMesh = useCallback5(
|
|
14663
14985
|
(nodeData, position, suppressVersionUpdate = false, forceShowQuestDate = false) => {
|
|
14664
14986
|
const {
|
|
14665
14987
|
graphGroup,
|
|
@@ -14700,7 +15022,7 @@ function XViewScene({
|
|
|
14700
15022
|
},
|
|
14701
15023
|
[]
|
|
14702
15024
|
);
|
|
14703
|
-
const handleActivateQuestLens =
|
|
15025
|
+
const handleActivateQuestLens = useCallback5(({ assigneeId, status: status2, milestoneId }) => {
|
|
14704
15026
|
var _a2;
|
|
14705
15027
|
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
14706
15028
|
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
@@ -15670,7 +15992,7 @@ function XViewScene({
|
|
|
15670
15992
|
get_scene_view_data,
|
|
15671
15993
|
save_view_data
|
|
15672
15994
|
]);
|
|
15673
|
-
const handleGhostNodeImageChange =
|
|
15995
|
+
const handleGhostNodeImageChange = useCallback5((useImage, imageUrl) => {
|
|
15674
15996
|
const {
|
|
15675
15997
|
node: ghostNode,
|
|
15676
15998
|
line: ghostLine,
|
|
@@ -15718,7 +16040,7 @@ function XViewScene({
|
|
|
15718
16040
|
aura: newGhostNode.getObjectByName("aura")
|
|
15719
16041
|
};
|
|
15720
16042
|
}, []);
|
|
15721
|
-
const handleGhostNodeIntensityChange =
|
|
16043
|
+
const handleGhostNodeIntensityChange = useCallback5((newIntensity) => {
|
|
15722
16044
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
15723
16045
|
if (!ghostNode) return;
|
|
15724
16046
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -15739,7 +16061,7 @@ function XViewScene({
|
|
|
15739
16061
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
15740
16062
|
}
|
|
15741
16063
|
}, []);
|
|
15742
|
-
const handleDetailNodeIntensityChange =
|
|
16064
|
+
const handleDetailNodeIntensityChange = useCallback5(
|
|
15743
16065
|
(nodeId, newIntensity) => {
|
|
15744
16066
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
15745
16067
|
if (!mesh) return;
|
|
@@ -15895,7 +16217,7 @@ function XViewScene({
|
|
|
15895
16217
|
mountRef.current.style.cursor = "default";
|
|
15896
16218
|
}
|
|
15897
16219
|
};
|
|
15898
|
-
const handleAncestryTreeUpdate =
|
|
16220
|
+
const handleAncestryTreeUpdate = useCallback5((newTree, extraData = null) => {
|
|
15899
16221
|
setAncestryMode((prev) => {
|
|
15900
16222
|
const prevTreeStr = JSON.stringify(prev.tree);
|
|
15901
16223
|
const newTreeStr = JSON.stringify(newTree);
|
|
@@ -15979,7 +16301,7 @@ function XViewScene({
|
|
|
15979
16301
|
const handleStartVersioning = (nodeData) => {
|
|
15980
16302
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
15981
16303
|
};
|
|
15982
|
-
const handleStartQuestQuick =
|
|
16304
|
+
const handleStartQuestQuick = useCallback5((questNode) => {
|
|
15983
16305
|
var _a2, _b2, _c2;
|
|
15984
16306
|
if (!questNode || !actionHandlerContext) return;
|
|
15985
16307
|
const allParentNodes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
@@ -16014,7 +16336,7 @@ function XViewScene({
|
|
|
16014
16336
|
}
|
|
16015
16337
|
setDetailsNode(updatedNode);
|
|
16016
16338
|
}, [session, actionHandlerContext]);
|
|
16017
|
-
const handleFinishQuestQuick =
|
|
16339
|
+
const handleFinishQuestQuick = useCallback5((questNode) => {
|
|
16018
16340
|
var _a2, _b2, _c2, _d2;
|
|
16019
16341
|
if (!questNode || !actionHandlerContext) return;
|
|
16020
16342
|
const {
|
|
@@ -16088,7 +16410,7 @@ function XViewScene({
|
|
|
16088
16410
|
setDetailsNode(null);
|
|
16089
16411
|
}
|
|
16090
16412
|
}, [session, actionHandlerContext, viewMembers, detailsNode]);
|
|
16091
|
-
const handleCancelQuest =
|
|
16413
|
+
const handleCancelQuest = useCallback5(() => {
|
|
16092
16414
|
const { graphGroup, ghostElements } = stateRef.current;
|
|
16093
16415
|
if (ghostElements.node && graphGroup) {
|
|
16094
16416
|
if (ghostElements.node.userData.labelObject) {
|
|
@@ -16147,13 +16469,15 @@ function XViewScene({
|
|
|
16147
16469
|
try {
|
|
16148
16470
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
16149
16471
|
sceneDataRef2.current.quest_counter = currentCounter + 1;
|
|
16150
|
-
sceneDataRef2.current.quest_nodes = sceneFileData.quest_nodes;
|
|
16151
|
-
sceneDataRef2.current.quest_links = sceneFileData.quest_links;
|
|
16152
16472
|
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
16153
16473
|
parentFileId: sceneConfigId2,
|
|
16154
16474
|
ownerId: ownerId2,
|
|
16155
16475
|
datasetName: "Quests Internas (View)"
|
|
16156
16476
|
});
|
|
16477
|
+
sceneDataRef2.current.quest_nodes = [...graphDataRef.current[sceneConfigId2].nodes];
|
|
16478
|
+
if (parentDataRef.current[sceneConfigId2]) {
|
|
16479
|
+
parentDataRef.current[sceneConfigId2].nodes = [...graphDataRef.current[sceneConfigId2].nodes];
|
|
16480
|
+
}
|
|
16157
16481
|
const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
|
|
16158
16482
|
const { graphGroup, ghostElements } = stateRef2.current;
|
|
16159
16483
|
if (ghostElements.node && graphGroup) {
|
|
@@ -16243,7 +16567,7 @@ function XViewScene({
|
|
|
16243
16567
|
}
|
|
16244
16568
|
userActionHandlers.handleCancelConnection(context);
|
|
16245
16569
|
};
|
|
16246
|
-
const handleClearAncestryVisuals =
|
|
16570
|
+
const handleClearAncestryVisuals = useCallback5((ancestryId) => {
|
|
16247
16571
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
16248
16572
|
const renderIndex = renderedAncestries.findIndex(
|
|
16249
16573
|
(a) => String(a.id) === String(ancestryId)
|
|
@@ -16261,7 +16585,7 @@ function XViewScene({
|
|
|
16261
16585
|
);
|
|
16262
16586
|
}
|
|
16263
16587
|
}, []);
|
|
16264
|
-
const handleRenderAncestry =
|
|
16588
|
+
const handleRenderAncestry = useCallback5(
|
|
16265
16589
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
16266
16590
|
setContextMenu(
|
|
16267
16591
|
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
@@ -16755,7 +17079,7 @@ function XViewScene({
|
|
|
16755
17079
|
ancestryMode.isActive
|
|
16756
17080
|
]
|
|
16757
17081
|
);
|
|
16758
|
-
const handleRenderAbstractionTree =
|
|
17082
|
+
const handleRenderAbstractionTree = useCallback5(
|
|
16759
17083
|
(ancestryObject, targetNodeId = null) => {
|
|
16760
17084
|
setContextMenu(
|
|
16761
17085
|
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
@@ -16843,7 +17167,7 @@ function XViewScene({
|
|
|
16843
17167
|
handleClearAncestryVisuals
|
|
16844
17168
|
]
|
|
16845
17169
|
);
|
|
16846
|
-
const handleReadModeBranchNav =
|
|
17170
|
+
const handleReadModeBranchNav = useCallback5(
|
|
16847
17171
|
(nodeId, action, direction = "right") => {
|
|
16848
17172
|
const { ancestry, branchStack } = readingMode;
|
|
16849
17173
|
if (!ancestry || !ancestry.tree) return;
|
|
@@ -17021,7 +17345,7 @@ function XViewScene({
|
|
|
17021
17345
|
},
|
|
17022
17346
|
[readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]
|
|
17023
17347
|
);
|
|
17024
|
-
const handleReadModeHighlight =
|
|
17348
|
+
const handleReadModeHighlight = useCallback5((nodeId) => {
|
|
17025
17349
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
17026
17350
|
stateRef.current.highlightedNodeId = nodeId;
|
|
17027
17351
|
}
|
|
@@ -17144,7 +17468,7 @@ function XViewScene({
|
|
|
17144
17468
|
buildFullAncestryTree,
|
|
17145
17469
|
sceneVersion
|
|
17146
17470
|
]);
|
|
17147
|
-
const handleStartReadingAncestry =
|
|
17471
|
+
const handleStartReadingAncestry = useCallback5(
|
|
17148
17472
|
async (ancestryObject, renderMode = "full") => {
|
|
17149
17473
|
setContextMenu(
|
|
17150
17474
|
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
@@ -17187,7 +17511,7 @@ function XViewScene({
|
|
|
17187
17511
|
},
|
|
17188
17512
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
17189
17513
|
);
|
|
17190
|
-
const handleReadModeSectionChange =
|
|
17514
|
+
const handleReadModeSectionChange = useCallback5(
|
|
17191
17515
|
(activeSectionId) => {
|
|
17192
17516
|
const { ancestry, branchStack } = readingMode;
|
|
17193
17517
|
if (!ancestry || !readingMode.isActive) return;
|
|
@@ -17272,10 +17596,10 @@ function XViewScene({
|
|
|
17272
17596
|
ancestryDataRef.current
|
|
17273
17597
|
]
|
|
17274
17598
|
);
|
|
17275
|
-
const handleCloseReadMode =
|
|
17599
|
+
const handleCloseReadMode = useCallback5(() => {
|
|
17276
17600
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
17277
17601
|
}, []);
|
|
17278
|
-
const handleAncestrySectionChange =
|
|
17602
|
+
const handleAncestrySectionChange = useCallback5(
|
|
17279
17603
|
(activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
17280
17604
|
var _a2, _b2;
|
|
17281
17605
|
const currentMode = stateRef.current.ancestry;
|
|
@@ -17337,7 +17661,7 @@ function XViewScene({
|
|
|
17337
17661
|
},
|
|
17338
17662
|
[handleRenderAncestry]
|
|
17339
17663
|
);
|
|
17340
|
-
const handleEditAncestry =
|
|
17664
|
+
const handleEditAncestry = useCallback5(
|
|
17341
17665
|
async (ancestryObject) => {
|
|
17342
17666
|
setContextMenu(
|
|
17343
17667
|
(prev) => prev.visible ? { ...prev, visible: false } : prev
|
|
@@ -17392,7 +17716,7 @@ function XViewScene({
|
|
|
17392
17716
|
const handleSelectAncestryParent = (nodeId) => {
|
|
17393
17717
|
setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
|
|
17394
17718
|
};
|
|
17395
|
-
const handleRemoveFromAncestry =
|
|
17719
|
+
const handleRemoveFromAncestry = useCallback5((pathToRemove) => {
|
|
17396
17720
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
|
|
17397
17721
|
console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
|
|
17398
17722
|
return;
|
|
@@ -17417,7 +17741,7 @@ function XViewScene({
|
|
|
17417
17741
|
return { ...prev, tree: newTree };
|
|
17418
17742
|
});
|
|
17419
17743
|
}, []);
|
|
17420
|
-
const handleSaveAncestry =
|
|
17744
|
+
const handleSaveAncestry = useCallback5(
|
|
17421
17745
|
async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
|
|
17422
17746
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
17423
17747
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
@@ -17653,7 +17977,7 @@ function XViewScene({
|
|
|
17653
17977
|
});
|
|
17654
17978
|
setEditingAncestryRel({ visible: false, data: null, path: null });
|
|
17655
17979
|
};
|
|
17656
|
-
const handleDeleteAncestry =
|
|
17980
|
+
const handleDeleteAncestry = useCallback5(
|
|
17657
17981
|
async (ancestryIdToDelete) => {
|
|
17658
17982
|
if (!ancestryIdToDelete) {
|
|
17659
17983
|
alert("ID da ancestralidade n\xE3o encontrado.");
|
|
@@ -17735,28 +18059,70 @@ function XViewScene({
|
|
|
17735
18059
|
},
|
|
17736
18060
|
[save_view_data, delete_file_action]
|
|
17737
18061
|
);
|
|
17738
|
-
const handleOpenAncestryBoard =
|
|
18062
|
+
const handleOpenAncestryBoard = useCallback5(() => {
|
|
17739
18063
|
setIsAncestryBoardOpen(true);
|
|
17740
18064
|
}, []);
|
|
17741
|
-
const
|
|
18065
|
+
const allAvailableNodes = useMemo13(() => {
|
|
18066
|
+
if (!parentDataRef.current) return [];
|
|
18067
|
+
return Object.values(parentDataRef.current).flatMap(
|
|
18068
|
+
(fileData) => fileData.nodes || []
|
|
18069
|
+
);
|
|
18070
|
+
}, [sceneVersion, isInitialized]);
|
|
18071
|
+
const allAvailableAncestries = useMemo13(() => {
|
|
18072
|
+
return ancestryDataRef.current || [];
|
|
18073
|
+
}, [sceneVersion, isInitialized]);
|
|
18074
|
+
const handleOpenReference = useCallback5(
|
|
18075
|
+
(referenceData) => {
|
|
18076
|
+
const { type, id } = referenceData;
|
|
18077
|
+
if (type === "node") {
|
|
18078
|
+
const targetNode = allAvailableNodes.find(
|
|
18079
|
+
(n) => String(n.id) === String(id)
|
|
18080
|
+
);
|
|
18081
|
+
if (targetNode) {
|
|
18082
|
+
setAncestryLinkDetails(null);
|
|
18083
|
+
setDetailsLink(null);
|
|
18084
|
+
setDetailsNode(targetNode);
|
|
18085
|
+
const sceneMesh = stateRef.current.nodeObjects[String(id)];
|
|
18086
|
+
if (sceneMesh) {
|
|
18087
|
+
tweenToTarget(sceneMesh);
|
|
18088
|
+
}
|
|
18089
|
+
} else {
|
|
18090
|
+
alert("Node original n\xE3o encontrado neste contexto.");
|
|
18091
|
+
}
|
|
18092
|
+
} else if (type === "ancestry") {
|
|
18093
|
+
const targetAncestry = allAvailableAncestries.find(
|
|
18094
|
+
(a) => String(a.ancestry_id) === String(id)
|
|
18095
|
+
);
|
|
18096
|
+
if (targetAncestry) {
|
|
18097
|
+
setDetailsNode(null);
|
|
18098
|
+
setDetailsLink(null);
|
|
18099
|
+
setAncestryLinkDetails(null);
|
|
18100
|
+
handleEditAncestry(targetAncestry);
|
|
18101
|
+
} else {
|
|
18102
|
+
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
18103
|
+
}
|
|
18104
|
+
}
|
|
18105
|
+
},
|
|
18106
|
+
[
|
|
18107
|
+
allAvailableNodes,
|
|
18108
|
+
allAvailableAncestries,
|
|
18109
|
+
handleEditAncestry,
|
|
18110
|
+
tweenToTarget
|
|
18111
|
+
]
|
|
18112
|
+
);
|
|
18113
|
+
const handleSelectAncestryFromBoard = useCallback5(
|
|
17742
18114
|
(item) => {
|
|
17743
18115
|
setIsAncestryBoardOpen(false);
|
|
17744
18116
|
setIsSidebarOpen(false);
|
|
17745
|
-
if (item.type === "ancestry"
|
|
18117
|
+
if (item.type === "ancestry") {
|
|
17746
18118
|
handleStartReadingAncestry(item);
|
|
17747
18119
|
} else {
|
|
17748
|
-
|
|
17749
|
-
const sceneMesh = stateRef.current.nodeObjects[nodeId];
|
|
17750
|
-
if (sceneMesh) {
|
|
17751
|
-
tweenToTarget(sceneMesh);
|
|
17752
|
-
} else {
|
|
17753
|
-
console.warn("Objeto n\xE3o encontrado na cena para foco:", nodeId);
|
|
17754
|
-
}
|
|
18120
|
+
handleOpenReference({ type: "node", id: item.id });
|
|
17755
18121
|
}
|
|
17756
18122
|
},
|
|
17757
|
-
[handleStartReadingAncestry,
|
|
18123
|
+
[handleStartReadingAncestry, handleOpenReference]
|
|
17758
18124
|
);
|
|
17759
|
-
const handleSaveAncestryBoard =
|
|
18125
|
+
const handleSaveAncestryBoard = useCallback5(
|
|
17760
18126
|
async (groups) => {
|
|
17761
18127
|
if (!sceneConfigId || !viewParams || !session) return;
|
|
17762
18128
|
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
@@ -17783,27 +18149,21 @@ function XViewScene({
|
|
|
17783
18149
|
return [...new Set(allTypes)];
|
|
17784
18150
|
}, [parentDataRef.current, sceneVersion]);
|
|
17785
18151
|
const searchableDbNodes = useMemo13(() => {
|
|
17786
|
-
var _a2;
|
|
17787
18152
|
if (!parentDataRef.current) {
|
|
17788
18153
|
return [];
|
|
17789
18154
|
}
|
|
17790
|
-
|
|
18155
|
+
return Object.entries(parentDataRef.current).flatMap(([dbId, fileData]) => {
|
|
17791
18156
|
const datasetName = fileData.dataset_name || `Dataset #${dbId.substring(0, 6)}`;
|
|
17792
18157
|
return (fileData.nodes || []).map((node) => ({
|
|
17793
18158
|
...node,
|
|
17794
18159
|
dataset_name: datasetName
|
|
17795
18160
|
}));
|
|
18161
|
+
}).filter((node) => {
|
|
18162
|
+
var _a2;
|
|
18163
|
+
return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
|
|
17796
18164
|
});
|
|
17797
|
-
|
|
17798
|
-
|
|
17799
|
-
dataset_name: "Quests Internas (View)"
|
|
17800
|
-
}));
|
|
17801
|
-
return [...datasetsPool, ...questsPool].filter((node) => {
|
|
17802
|
-
var _a3;
|
|
17803
|
-
return !((_a3 = node.version_node) == null ? void 0 : _a3.is_version);
|
|
17804
|
-
});
|
|
17805
|
-
}, [parentDataRef.current, (_b = sceneDataRef.current) == null ? void 0 : _b.quest_nodes, sceneVersion]);
|
|
17806
|
-
const handleAddExistingNode = useCallback4(
|
|
18165
|
+
}, [parentDataRef.current, sceneVersion]);
|
|
18166
|
+
const handleAddExistingNode = useCallback5(
|
|
17807
18167
|
(nodeId) => {
|
|
17808
18168
|
return userActionHandlers.handleAddExistingNodeById(
|
|
17809
18169
|
actionHandlerContext,
|
|
@@ -17812,7 +18172,7 @@ function XViewScene({
|
|
|
17812
18172
|
},
|
|
17813
18173
|
[actionHandlerContext]
|
|
17814
18174
|
);
|
|
17815
|
-
const handleUpdateMilestones =
|
|
18175
|
+
const handleUpdateMilestones = useCallback5(
|
|
17816
18176
|
async (newMilestones) => {
|
|
17817
18177
|
var _a2, _b2, _c2;
|
|
17818
18178
|
if (!sceneDataRef.current) return;
|
|
@@ -17858,7 +18218,7 @@ function XViewScene({
|
|
|
17858
18218
|
viewParams == null ? void 0 : viewParams.type
|
|
17859
18219
|
]
|
|
17860
18220
|
);
|
|
17861
|
-
const handleSaveCurrentView =
|
|
18221
|
+
const handleSaveCurrentView = useCallback5(async () => {
|
|
17862
18222
|
var _a2, _b2, _c2;
|
|
17863
18223
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
17864
18224
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
@@ -17901,61 +18261,13 @@ function XViewScene({
|
|
|
17901
18261
|
console.error("Erro na chamada de save_view_data:", error);
|
|
17902
18262
|
}
|
|
17903
18263
|
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
17904
|
-
const
|
|
17905
|
-
if (!parentDataRef.current) return [];
|
|
17906
|
-
return Object.values(parentDataRef.current).flatMap(
|
|
17907
|
-
(fileData) => fileData.nodes || []
|
|
17908
|
-
);
|
|
17909
|
-
}, [sceneVersion, isInitialized]);
|
|
17910
|
-
const allAvailableAncestries = useMemo13(() => {
|
|
17911
|
-
return ancestryDataRef.current || [];
|
|
17912
|
-
}, [sceneVersion, isInitialized]);
|
|
17913
|
-
const handleOpenReference = useCallback4(
|
|
17914
|
-
(referenceData) => {
|
|
17915
|
-
const { type, id } = referenceData;
|
|
17916
|
-
if (type === "node") {
|
|
17917
|
-
const targetNode = allAvailableNodes.find(
|
|
17918
|
-
(n) => String(n.id) === String(id)
|
|
17919
|
-
);
|
|
17920
|
-
if (targetNode) {
|
|
17921
|
-
setAncestryLinkDetails(null);
|
|
17922
|
-
setDetailsLink(null);
|
|
17923
|
-
setDetailsNode(targetNode);
|
|
17924
|
-
const sceneMesh = stateRef.current.nodeObjects[String(id)];
|
|
17925
|
-
if (sceneMesh) {
|
|
17926
|
-
tweenToTarget(sceneMesh);
|
|
17927
|
-
}
|
|
17928
|
-
} else {
|
|
17929
|
-
alert("Node original n\xE3o encontrado neste contexto.");
|
|
17930
|
-
}
|
|
17931
|
-
} else if (type === "ancestry") {
|
|
17932
|
-
const targetAncestry = allAvailableAncestries.find(
|
|
17933
|
-
(a) => String(a.ancestry_id) === String(id)
|
|
17934
|
-
);
|
|
17935
|
-
if (targetAncestry) {
|
|
17936
|
-
setDetailsNode(null);
|
|
17937
|
-
setDetailsLink(null);
|
|
17938
|
-
setAncestryLinkDetails(null);
|
|
17939
|
-
handleEditAncestry(targetAncestry);
|
|
17940
|
-
} else {
|
|
17941
|
-
alert("Ancestralidade original n\xE3o encontrada neste contexto.");
|
|
17942
|
-
}
|
|
17943
|
-
}
|
|
17944
|
-
},
|
|
17945
|
-
[
|
|
17946
|
-
allAvailableNodes,
|
|
17947
|
-
allAvailableAncestries,
|
|
17948
|
-
handleEditAncestry,
|
|
17949
|
-
tweenToTarget
|
|
17950
|
-
]
|
|
17951
|
-
);
|
|
17952
|
-
const handleToggleAncestryAddMode = useCallback4(() => {
|
|
18264
|
+
const handleToggleAncestryAddMode = useCallback5(() => {
|
|
17953
18265
|
setAncestryMode((prev) => ({
|
|
17954
18266
|
...prev,
|
|
17955
18267
|
isAddingNodes: !prev.isAddingNodes
|
|
17956
18268
|
}));
|
|
17957
18269
|
}, []);
|
|
17958
|
-
const handleFocusNode =
|
|
18270
|
+
const handleFocusNode = useCallback5(
|
|
17959
18271
|
(nodeData) => {
|
|
17960
18272
|
var _a2;
|
|
17961
18273
|
if (!nodeData) return;
|
|
@@ -17981,9 +18293,9 @@ function XViewScene({
|
|
|
17981
18293
|
};
|
|
17982
18294
|
});
|
|
17983
18295
|
}, [sceneVersion, isInitialized]);
|
|
17984
|
-
const sourceNodeDatasetId = creationMode.sourceNodeData ? (
|
|
18296
|
+
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(
|
|
17985
18297
|
String(creationMode.sourceNodeData.id)
|
|
17986
|
-
)) == null ? void 0 :
|
|
18298
|
+
)) == null ? void 0 : _b.parentFileId : null;
|
|
17987
18299
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
17988
18300
|
useEffect24(() => {
|
|
17989
18301
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
@@ -18237,7 +18549,7 @@ function XViewScene({
|
|
|
18237
18549
|
onToggle: setIsSidebarOpen,
|
|
18238
18550
|
userRole: userPermissionRole,
|
|
18239
18551
|
viewMembers,
|
|
18240
|
-
milestones: ((
|
|
18552
|
+
milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
|
|
18241
18553
|
onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
|
|
18242
18554
|
}
|
|
18243
18555
|
),
|
|
@@ -18262,8 +18574,8 @@ function XViewScene({
|
|
|
18262
18574
|
},
|
|
18263
18575
|
refEl: formRef,
|
|
18264
18576
|
existingTypes: existingNodeTypes,
|
|
18265
|
-
initialColor: (
|
|
18266
|
-
sourceTypes: (
|
|
18577
|
+
initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
|
|
18578
|
+
sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
|
|
18267
18579
|
onIntensityChange: handleGhostNodeIntensityChange,
|
|
18268
18580
|
onUploadFile: upload_file_action,
|
|
18269
18581
|
availableDatasets,
|
|
@@ -18292,8 +18604,8 @@ function XViewScene({
|
|
|
18292
18604
|
transition: "opacity 200ms ease-out"
|
|
18293
18605
|
},
|
|
18294
18606
|
refEl: formRef,
|
|
18295
|
-
fixedType: (
|
|
18296
|
-
fixedColor: (
|
|
18607
|
+
fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
|
|
18608
|
+
fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
|
|
18297
18609
|
onUploadFile: upload_file_action,
|
|
18298
18610
|
availableNodes: allAvailableNodes,
|
|
18299
18611
|
availableAncestries: allAvailableAncestries
|
|
@@ -18321,9 +18633,9 @@ function XViewScene({
|
|
|
18321
18633
|
availableNodes: allAvailableNodes,
|
|
18322
18634
|
availableAncestries: allAvailableAncestries,
|
|
18323
18635
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
|
18324
|
-
questCounter: ((
|
|
18636
|
+
questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
|
|
18325
18637
|
viewMembers,
|
|
18326
|
-
milestones: ((
|
|
18638
|
+
milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
|
|
18327
18639
|
onUpdateMilestones: handleUpdateMilestones
|
|
18328
18640
|
}
|
|
18329
18641
|
),
|
|
@@ -18458,7 +18770,7 @@ function XViewScene({
|
|
|
18458
18770
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
|
|
18459
18771
|
viewMembers,
|
|
18460
18772
|
currentUser: session == null ? void 0 : session.user,
|
|
18461
|
-
milestones: ((
|
|
18773
|
+
milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
|
|
18462
18774
|
onUpdateMilestones: handleUpdateMilestones
|
|
18463
18775
|
}
|
|
18464
18776
|
),
|
|
@@ -18642,7 +18954,7 @@ function XViewScene({
|
|
|
18642
18954
|
{
|
|
18643
18955
|
isOpen: isMilestoneManagerOpen,
|
|
18644
18956
|
onClose: () => setIsMilestoneManagerOpen(false),
|
|
18645
|
-
milestones: ((
|
|
18957
|
+
milestones: ((_k = sceneDataRef.current) == null ? void 0 : _k.milestones) || [],
|
|
18646
18958
|
onUpdateMilestones: handleUpdateMilestones
|
|
18647
18959
|
}
|
|
18648
18960
|
),
|
|
@@ -18653,7 +18965,7 @@ function XViewScene({
|
|
|
18653
18965
|
onClose: () => setIsImportModalOpen(false),
|
|
18654
18966
|
onConfirm: handleConfirmImport,
|
|
18655
18967
|
session,
|
|
18656
|
-
parentDbs: ((
|
|
18968
|
+
parentDbs: ((_l = sceneDataRef.current) == null ? void 0 : _l.parent_dbs) || [],
|
|
18657
18969
|
onFetchAvailableFiles: import_parent_file_modal_get,
|
|
18658
18970
|
currentViewName: viewParams == null ? void 0 : viewParams.name,
|
|
18659
18971
|
currentAncestries: ancestryDataRef.current || []
|