@lv-x-software-house/x_view 1.2.6-dev.1 → 1.2.6-dev.3
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 +571 -1017
- package/dist/index.mjs +540 -964
- package/dist/server.js +480 -0
- package/dist/server.mjs +445 -0
- package/package.json +24 -5
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
// src/XViewScene.jsx
|
|
2
|
-
import
|
|
4
|
+
import React30, {
|
|
3
5
|
useCallback as useCallback4,
|
|
4
|
-
useEffect as
|
|
6
|
+
useEffect as useEffect24,
|
|
5
7
|
useRef as useRef19,
|
|
6
|
-
useState as
|
|
7
|
-
useMemo as
|
|
8
|
+
useState as useState28,
|
|
9
|
+
useMemo as useMemo13
|
|
8
10
|
} from "react";
|
|
9
11
|
import { useRouter, useSearchParams } from "next/navigation";
|
|
10
12
|
import { useSession } from "next-auth/react";
|
|
@@ -79,55 +81,7 @@ function defineAbilityFor(role) {
|
|
|
79
81
|
|
|
80
82
|
// src/logic/x_view_utils.js
|
|
81
83
|
import { useState, useCallback } from "react";
|
|
82
|
-
|
|
83
|
-
// node_modules/uuid/dist/esm-node/rng.js
|
|
84
|
-
import crypto from "crypto";
|
|
85
|
-
var rnds8Pool = new Uint8Array(256);
|
|
86
|
-
var poolPtr = rnds8Pool.length;
|
|
87
|
-
function rng() {
|
|
88
|
-
if (poolPtr > rnds8Pool.length - 16) {
|
|
89
|
-
crypto.randomFillSync(rnds8Pool);
|
|
90
|
-
poolPtr = 0;
|
|
91
|
-
}
|
|
92
|
-
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// node_modules/uuid/dist/esm-node/stringify.js
|
|
96
|
-
var byteToHex = [];
|
|
97
|
-
for (let i = 0; i < 256; ++i) {
|
|
98
|
-
byteToHex.push((i + 256).toString(16).slice(1));
|
|
99
|
-
}
|
|
100
|
-
function unsafeStringify(arr, offset = 0) {
|
|
101
|
-
return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// node_modules/uuid/dist/esm-node/native.js
|
|
105
|
-
import crypto2 from "crypto";
|
|
106
|
-
var native_default = {
|
|
107
|
-
randomUUID: crypto2.randomUUID
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
// node_modules/uuid/dist/esm-node/v4.js
|
|
111
|
-
function v4(options, buf, offset) {
|
|
112
|
-
if (native_default.randomUUID && !buf && !options) {
|
|
113
|
-
return native_default.randomUUID();
|
|
114
|
-
}
|
|
115
|
-
options = options || {};
|
|
116
|
-
const rnds = options.random || (options.rng || rng)();
|
|
117
|
-
rnds[6] = rnds[6] & 15 | 64;
|
|
118
|
-
rnds[8] = rnds[8] & 63 | 128;
|
|
119
|
-
if (buf) {
|
|
120
|
-
offset = offset || 0;
|
|
121
|
-
for (let i = 0; i < 16; ++i) {
|
|
122
|
-
buf[offset + i] = rnds[i];
|
|
123
|
-
}
|
|
124
|
-
return buf;
|
|
125
|
-
}
|
|
126
|
-
return unsafeStringify(rnds);
|
|
127
|
-
}
|
|
128
|
-
var v4_default = v4;
|
|
129
|
-
|
|
130
|
-
// src/logic/x_view_utils.js
|
|
84
|
+
import { v4 as uuidv4 } from "uuid";
|
|
131
85
|
import * as THREE2 from "three";
|
|
132
86
|
|
|
133
87
|
// src/logic/x_view_config.js
|
|
@@ -2480,15 +2434,15 @@ function createNewCustomProperty(existingProps = []) {
|
|
|
2480
2434
|
switch (nextType) {
|
|
2481
2435
|
case "links":
|
|
2482
2436
|
nextKey = "Links";
|
|
2483
|
-
nextValue = [{ id:
|
|
2437
|
+
nextValue = [{ id: uuidv4(), name: "", value: "" }];
|
|
2484
2438
|
break;
|
|
2485
2439
|
case "images":
|
|
2486
2440
|
nextKey = "Images";
|
|
2487
|
-
nextValue = [{ id:
|
|
2441
|
+
nextValue = [{ id: uuidv4(), name: "1", value: "" }];
|
|
2488
2442
|
break;
|
|
2489
2443
|
case "documents":
|
|
2490
2444
|
nextKey = "Documents";
|
|
2491
|
-
nextValue = [{ id:
|
|
2445
|
+
nextValue = [{ id: uuidv4(), name: "1", value: "" }];
|
|
2492
2446
|
break;
|
|
2493
2447
|
case "date":
|
|
2494
2448
|
nextKey = "Date";
|
|
@@ -2498,14 +2452,14 @@ function createNewCustomProperty(existingProps = []) {
|
|
|
2498
2452
|
nextValue = 0;
|
|
2499
2453
|
break;
|
|
2500
2454
|
case "list":
|
|
2501
|
-
nextValue = [{ id:
|
|
2455
|
+
nextValue = [{ id: uuidv4(), name: "", value: "" }];
|
|
2502
2456
|
break;
|
|
2503
2457
|
default:
|
|
2504
2458
|
nextValue = "";
|
|
2505
2459
|
break;
|
|
2506
2460
|
}
|
|
2507
2461
|
return {
|
|
2508
|
-
id:
|
|
2462
|
+
id: uuidv4(),
|
|
2509
2463
|
key: nextKey,
|
|
2510
2464
|
type: nextType,
|
|
2511
2465
|
value: nextValue,
|
|
@@ -2750,7 +2704,7 @@ function extractCustomPropsFromNode(node) {
|
|
|
2750
2704
|
if (val && typeof val === "object") {
|
|
2751
2705
|
if ("date_interval" in val) {
|
|
2752
2706
|
return {
|
|
2753
|
-
id:
|
|
2707
|
+
id: uuidv4(),
|
|
2754
2708
|
key,
|
|
2755
2709
|
type: "date",
|
|
2756
2710
|
value: {
|
|
@@ -2762,7 +2716,7 @@ function extractCustomPropsFromNode(node) {
|
|
|
2762
2716
|
}
|
|
2763
2717
|
if ("year" in val) {
|
|
2764
2718
|
return {
|
|
2765
|
-
id:
|
|
2719
|
+
id: uuidv4(),
|
|
2766
2720
|
key,
|
|
2767
2721
|
type: "date",
|
|
2768
2722
|
value: { type: "Ano", value: val.year || "" }
|
|
@@ -2770,7 +2724,7 @@ function extractCustomPropsFromNode(node) {
|
|
|
2770
2724
|
}
|
|
2771
2725
|
if ("date" in val) {
|
|
2772
2726
|
return {
|
|
2773
|
-
id:
|
|
2727
|
+
id: uuidv4(),
|
|
2774
2728
|
key,
|
|
2775
2729
|
type: "date",
|
|
2776
2730
|
value: { type: "Data", value: val.date || "" }
|
|
@@ -2778,7 +2732,7 @@ function extractCustomPropsFromNode(node) {
|
|
|
2778
2732
|
}
|
|
2779
2733
|
}
|
|
2780
2734
|
return {
|
|
2781
|
-
id:
|
|
2735
|
+
id: uuidv4(),
|
|
2782
2736
|
key,
|
|
2783
2737
|
type: "date",
|
|
2784
2738
|
value: { type: "Data", value: "" }
|
|
@@ -2786,14 +2740,14 @@ function extractCustomPropsFromNode(node) {
|
|
|
2786
2740
|
}
|
|
2787
2741
|
if (t === "list" || t === "links" || t === "images" || t === "documents") {
|
|
2788
2742
|
const safeList = (val || []).map((item) => ({
|
|
2789
|
-
id: item.id ||
|
|
2743
|
+
id: item.id || uuidv4(),
|
|
2790
2744
|
name: item.name ?? "",
|
|
2791
2745
|
value: item.value ?? ""
|
|
2792
2746
|
}));
|
|
2793
|
-
return { id:
|
|
2747
|
+
return { id: uuidv4(), key, type: t, value: safeList };
|
|
2794
2748
|
}
|
|
2795
2749
|
return {
|
|
2796
|
-
id:
|
|
2750
|
+
id: uuidv4(),
|
|
2797
2751
|
key,
|
|
2798
2752
|
type: t,
|
|
2799
2753
|
value: t === "number" ? Number(val) || 0 : String(val ?? "")
|
|
@@ -3066,16 +3020,16 @@ var processDescriptionForSave = (text, existingSections = []) => {
|
|
|
3066
3020
|
if (existingMatch) {
|
|
3067
3021
|
finalUuid = existingMatch.id;
|
|
3068
3022
|
} else {
|
|
3069
|
-
finalUuid =
|
|
3023
|
+
finalUuid = uuidv4();
|
|
3070
3024
|
}
|
|
3071
3025
|
} else {
|
|
3072
3026
|
finalUuid = numericMap.get(numStr);
|
|
3073
3027
|
if (!finalUuid) {
|
|
3074
|
-
finalUuid =
|
|
3028
|
+
finalUuid = uuidv4();
|
|
3075
3029
|
}
|
|
3076
3030
|
}
|
|
3077
3031
|
if (usedIds.has(finalUuid)) {
|
|
3078
|
-
finalUuid =
|
|
3032
|
+
finalUuid = uuidv4();
|
|
3079
3033
|
}
|
|
3080
3034
|
usedIds.add(finalUuid);
|
|
3081
3035
|
processedSections.push({
|
|
@@ -3186,18 +3140,18 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
|
|
|
3186
3140
|
function createTimelineEntry(actorId, description, type = "comment", extras = {}) {
|
|
3187
3141
|
const { links = [], images = [], metadata = {} } = extras;
|
|
3188
3142
|
return {
|
|
3189
|
-
id:
|
|
3143
|
+
id: uuidv4(),
|
|
3190
3144
|
type,
|
|
3191
3145
|
timestamp: Date.now(),
|
|
3192
3146
|
actorId,
|
|
3193
3147
|
description,
|
|
3194
3148
|
links: links.map((l) => ({
|
|
3195
|
-
id: l.id ||
|
|
3149
|
+
id: l.id || uuidv4(),
|
|
3196
3150
|
name: l.name || "",
|
|
3197
3151
|
value: l.value || ""
|
|
3198
3152
|
})),
|
|
3199
3153
|
images: images.map((img) => ({
|
|
3200
|
-
id: img.id ||
|
|
3154
|
+
id: img.id || uuidv4(),
|
|
3201
3155
|
name: img.name || "",
|
|
3202
3156
|
value: img.value || ""
|
|
3203
3157
|
}))
|
|
@@ -4424,6 +4378,7 @@ function XViewSidebar({
|
|
|
4424
4378
|
|
|
4425
4379
|
// src/components/AncestryRelationshipPanel.jsx
|
|
4426
4380
|
import React8, { useState as useState9, useEffect as useEffect8, useRef as useRef7 } from "react";
|
|
4381
|
+
import { v4 as uuidv43 } from "uuid";
|
|
4427
4382
|
|
|
4428
4383
|
// src/components/CustomPropertyDisplay.jsx
|
|
4429
4384
|
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
@@ -5183,6 +5138,7 @@ function SectionImportModal({ isOpen, onClose, onSelect, availableNodes = [], av
|
|
|
5183
5138
|
}
|
|
5184
5139
|
|
|
5185
5140
|
// src/components/DescriptionEditModal.jsx
|
|
5141
|
+
import { v4 as uuidv42 } from "uuid";
|
|
5186
5142
|
var getNextSectionNumber = (currentText) => {
|
|
5187
5143
|
const regex = /\*\/\s*(\d+)(?::[a-zA-Z0-9-]+)?\s*\//g;
|
|
5188
5144
|
let max = 0;
|
|
@@ -5314,7 +5270,7 @@ function DescriptionEditModal({
|
|
|
5314
5270
|
const el = textareaRef.current;
|
|
5315
5271
|
if (!el) return;
|
|
5316
5272
|
const nextNum = getNextSectionNumber(text);
|
|
5317
|
-
const uniqueSuffix =
|
|
5273
|
+
const uniqueSuffix = uuidv42().slice(0, 4);
|
|
5318
5274
|
insertAtCursor(`*/${nextNum}:${uniqueSuffix}/ `);
|
|
5319
5275
|
};
|
|
5320
5276
|
const handleImportSelect = (tags) => {
|
|
@@ -5325,7 +5281,7 @@ function DescriptionEditModal({
|
|
|
5325
5281
|
let currentNum = getNextSectionNumber(currentText);
|
|
5326
5282
|
let blockToInsert = "";
|
|
5327
5283
|
tagsArray.forEach((tag) => {
|
|
5328
|
-
const uniqueSuffix =
|
|
5284
|
+
const uniqueSuffix = uuidv42().slice(0, 4);
|
|
5329
5285
|
blockToInsert += `
|
|
5330
5286
|
*/${currentNum}:${uniqueSuffix}/ ${tag}
|
|
5331
5287
|
`;
|
|
@@ -6685,6 +6641,7 @@ import {
|
|
|
6685
6641
|
FiLink as FiLink4,
|
|
6686
6642
|
FiTrash2 as FiTrash22
|
|
6687
6643
|
} from "react-icons/fi";
|
|
6644
|
+
import { v4 as uuidv44 } from "uuid";
|
|
6688
6645
|
|
|
6689
6646
|
// src/components/AncestryPickerModal.jsx
|
|
6690
6647
|
import React9, { useState as useState10, useMemo as useMemo7, useEffect as useEffect9 } from "react";
|
|
@@ -7721,7 +7678,7 @@ function CreateAncestryPanel({
|
|
|
7721
7678
|
const nodeData = availableNodes.find((n) => String(n.id) === String(nodeId));
|
|
7722
7679
|
const dirSuffix = direction === "left" ? "(Esq)" : "(Dir)";
|
|
7723
7680
|
branch = {
|
|
7724
|
-
id:
|
|
7681
|
+
id: uuidv44(),
|
|
7725
7682
|
name: `Ramifica\xE7\xE3o ${dirSuffix} de ${(nodeData == null ? void 0 : nodeData.name) || "Node"}`,
|
|
7726
7683
|
description: "",
|
|
7727
7684
|
description_sections: [],
|
|
@@ -8500,6 +8457,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
8500
8457
|
|
|
8501
8458
|
// src/components/InSceneCreationForm.jsx
|
|
8502
8459
|
import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
|
|
8460
|
+
import { v4 as uuidv45 } from "uuid";
|
|
8503
8461
|
|
|
8504
8462
|
// src/components/ColorPicker.jsx
|
|
8505
8463
|
import React12, { useState as useState13, useEffect as useEffect12, useRef as useRef9 } from "react";
|
|
@@ -9084,6 +9042,7 @@ function InSceneCreationForm({
|
|
|
9084
9042
|
|
|
9085
9043
|
// src/components/InSceneVersionForm.jsx
|
|
9086
9044
|
import React14, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
|
|
9045
|
+
import { v4 as uuidv46 } from "uuid";
|
|
9087
9046
|
import { FiPlus as FiPlus4, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
|
|
9088
9047
|
function InSceneVersionForm({
|
|
9089
9048
|
onSave,
|
|
@@ -9106,7 +9065,7 @@ function InSceneVersionForm({
|
|
|
9106
9065
|
const [description, setDescription] = useState15("");
|
|
9107
9066
|
const [customProps, setCustomProps] = useState15([
|
|
9108
9067
|
{
|
|
9109
|
-
id:
|
|
9068
|
+
id: uuidv46(),
|
|
9110
9069
|
key: "Date",
|
|
9111
9070
|
type: "date",
|
|
9112
9071
|
value: { type: "Data", value: "" },
|
|
@@ -9399,6 +9358,7 @@ function InSceneVersionForm({
|
|
|
9399
9358
|
|
|
9400
9359
|
// src/components/InSceneQuestForm.jsx
|
|
9401
9360
|
import React16, { useState as useState17, useRef as useRef12 } from "react";
|
|
9361
|
+
import { v4 as uuidv47 } from "uuid";
|
|
9402
9362
|
import {
|
|
9403
9363
|
FiPlus as FiPlus6,
|
|
9404
9364
|
FiCheck as FiCheck9,
|
|
@@ -10323,6 +10283,7 @@ function InSceneQuestForm({
|
|
|
10323
10283
|
|
|
10324
10284
|
// src/components/NodeDetailsPanel.jsx
|
|
10325
10285
|
import React17, { useState as useState18, useEffect as useEffect15, useRef as useRef13 } from "react";
|
|
10286
|
+
import { v4 as uuidv48 } from "uuid";
|
|
10326
10287
|
import { FiPlus as FiPlus7, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
|
|
10327
10288
|
function NodeDetailsPanel({
|
|
10328
10289
|
node,
|
|
@@ -10837,6 +10798,7 @@ function NodeDetailsPanel({
|
|
|
10837
10798
|
|
|
10838
10799
|
// src/components/QuestDetailsPanel.jsx
|
|
10839
10800
|
import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
|
|
10801
|
+
import { v4 as uuidv49 } from "uuid";
|
|
10840
10802
|
import { FiPlus as FiPlus8, FiX as FiX7, FiCheck as FiCheck11, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4, FiLink as FiLink7, FiTarget as FiTarget3, FiChevronDown as FiChevronDown7, FiUser as FiUser3, FiSearch as FiSearch7, FiRepeat as FiRepeat2, FiCalendar as FiCalendar2, FiImage as FiImage4 } from "react-icons/fi";
|
|
10841
10803
|
|
|
10842
10804
|
// src/components/QuestTimeline.jsx
|
|
@@ -11287,7 +11249,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11287
11249
|
}, 100);
|
|
11288
11250
|
};
|
|
11289
11251
|
const addLinkToNote = () => {
|
|
11290
|
-
setNoteLinks([...noteLinks, { id:
|
|
11252
|
+
setNoteLinks([...noteLinks, { id: uuidv49(), name: "", value: "" }]);
|
|
11291
11253
|
};
|
|
11292
11254
|
const removeLinkFromNote = (id) => {
|
|
11293
11255
|
setNoteLinks(noteLinks.filter((l) => l.id !== id));
|
|
@@ -11296,7 +11258,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11296
11258
|
setNoteLinks(noteLinks.map((l) => l.id === id ? { ...l, [field]: val } : l));
|
|
11297
11259
|
};
|
|
11298
11260
|
const addImageToNote = () => {
|
|
11299
|
-
setNoteImages([...noteImages, { id:
|
|
11261
|
+
setNoteImages([...noteImages, { id: uuidv49(), name: "Image", value: "" }]);
|
|
11300
11262
|
};
|
|
11301
11263
|
const removeImageFromNote = (id) => {
|
|
11302
11264
|
setNoteImages(noteImages.filter((img) => img.id !== id));
|
|
@@ -12173,6 +12135,7 @@ function MultiNodeContextMenu({
|
|
|
12173
12135
|
|
|
12174
12136
|
// src/components/RelationshipDetailsPanel.jsx
|
|
12175
12137
|
import React21, { useState as useState21, useEffect as useEffect18, useRef as useRef16, useMemo as useMemo9 } from "react";
|
|
12138
|
+
import { v4 as uuidv410 } from "uuid";
|
|
12176
12139
|
import { FiPlus as FiPlus9, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
|
|
12177
12140
|
function RelationshipDetailsPanel({
|
|
12178
12141
|
link,
|
|
@@ -12982,10 +12945,10 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
12982
12945
|
}
|
|
12983
12946
|
|
|
12984
12947
|
// src/components/AncestryBoard.jsx
|
|
12985
|
-
import
|
|
12948
|
+
import React28, { useState as useState26, useMemo as useMemo12, useEffect as useEffect23, useRef as useRef18 } from "react";
|
|
12986
12949
|
import {
|
|
12987
|
-
FiSearch as
|
|
12988
|
-
FiLayers as
|
|
12950
|
+
FiSearch as FiSearch9,
|
|
12951
|
+
FiLayers as FiLayers7,
|
|
12989
12952
|
FiCornerUpRight as FiCornerUpRight4,
|
|
12990
12953
|
FiPlay,
|
|
12991
12954
|
FiPlus as FiPlus10,
|
|
@@ -12996,151 +12959,384 @@ import {
|
|
|
12996
12959
|
FiLoader as FiLoader5,
|
|
12997
12960
|
FiX as FiX8,
|
|
12998
12961
|
FiAlertTriangle,
|
|
12962
|
+
FiCheckSquare as FiCheckSquare4,
|
|
12963
|
+
FiBox as FiBox2,
|
|
12964
|
+
FiGitBranch as FiGitBranch4
|
|
12965
|
+
} from "react-icons/fi";
|
|
12966
|
+
import { v4 as uuidv411 } from "uuid";
|
|
12967
|
+
|
|
12968
|
+
// src/components/MentionEditor.jsx
|
|
12969
|
+
import React27, { useMemo as useMemo11, useEffect as useEffect22 } from "react";
|
|
12970
|
+
import { useEditor, EditorContent, ReactRenderer } from "@tiptap/react";
|
|
12971
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
12972
|
+
import Mention from "@tiptap/extension-mention";
|
|
12973
|
+
import tippy from "tippy.js";
|
|
12974
|
+
|
|
12975
|
+
// src/components/MentionList.jsx
|
|
12976
|
+
import React26, {
|
|
12977
|
+
forwardRef,
|
|
12978
|
+
useEffect as useEffect21,
|
|
12979
|
+
useImperativeHandle,
|
|
12980
|
+
useState as useState25
|
|
12981
|
+
} from "react";
|
|
12982
|
+
import {
|
|
12983
|
+
FiLayers as FiLayers6,
|
|
12999
12984
|
FiCheckSquare as FiCheckSquare3,
|
|
13000
12985
|
FiBox,
|
|
13001
|
-
FiGitBranch as FiGitBranch3
|
|
12986
|
+
FiGitBranch as FiGitBranch3,
|
|
12987
|
+
FiSearch as FiSearch8
|
|
13002
12988
|
} from "react-icons/fi";
|
|
12989
|
+
var MentionList = forwardRef((props, ref) => {
|
|
12990
|
+
const [selectedIndex, setSelectedIndex] = useState25(0);
|
|
12991
|
+
const selectItem = (index) => {
|
|
12992
|
+
const item = props.items[index];
|
|
12993
|
+
if (item) {
|
|
12994
|
+
props.command({ id: item.id, label: item.name, type: item.type });
|
|
12995
|
+
}
|
|
12996
|
+
};
|
|
12997
|
+
const upHandler = () => {
|
|
12998
|
+
setSelectedIndex(
|
|
12999
|
+
(selectedIndex + props.items.length - 1) % props.items.length
|
|
13000
|
+
);
|
|
13001
|
+
};
|
|
13002
|
+
const downHandler = () => {
|
|
13003
|
+
setSelectedIndex((selectedIndex + 1) % props.items.length);
|
|
13004
|
+
};
|
|
13005
|
+
const enterHandler = () => {
|
|
13006
|
+
selectItem(selectedIndex);
|
|
13007
|
+
};
|
|
13008
|
+
useEffect21(() => setSelectedIndex(0), [props.items]);
|
|
13009
|
+
useImperativeHandle(ref, () => ({
|
|
13010
|
+
onKeyDown: ({ event }) => {
|
|
13011
|
+
if (event.key === "ArrowUp") {
|
|
13012
|
+
upHandler();
|
|
13013
|
+
return true;
|
|
13014
|
+
}
|
|
13015
|
+
if (event.key === "ArrowDown") {
|
|
13016
|
+
downHandler();
|
|
13017
|
+
return true;
|
|
13018
|
+
}
|
|
13019
|
+
if (event.key === "Enter") {
|
|
13020
|
+
enterHandler();
|
|
13021
|
+
return true;
|
|
13022
|
+
}
|
|
13023
|
+
return false;
|
|
13024
|
+
}
|
|
13025
|
+
}));
|
|
13026
|
+
return /* @__PURE__ */ React26.createElement("div", { className: "z-[3000] bg-slate-900 border border-white/10 rounded-lg shadow-2xl overflow-hidden min-w-[280px] max-w-[400px] animate-in fade-in zoom-in-95 duration-200" }, /* @__PURE__ */ React26.createElement("div", { className: "p-2 border-b border-white/5 bg-slate-950/50 flex items-center gap-2" }, /* @__PURE__ */ React26.createElement(FiSearch8, { className: "text-indigo-400", size: 14 }), /* @__PURE__ */ React26.createElement("span", { className: "text-[10px] uppercase tracking-wider font-bold text-slate-500" }, "Mencionar Recurso")), /* @__PURE__ */ React26.createElement("div", { className: "p-1 max-h-[300px] overflow-y-auto custom-scrollbar" }, props.items.length ? props.items.map((item, index) => {
|
|
13027
|
+
const isQuest = item.type === "quest";
|
|
13028
|
+
const isVersion = item.type === "version";
|
|
13029
|
+
const isNode = item.type === "node";
|
|
13030
|
+
let Icon = FiLayers6;
|
|
13031
|
+
let colorClass = "text-indigo-400";
|
|
13032
|
+
let badgeText = "Ancestralidade";
|
|
13033
|
+
if (isQuest) {
|
|
13034
|
+
Icon = FiCheckSquare3;
|
|
13035
|
+
colorClass = "text-amber-400";
|
|
13036
|
+
badgeText = "Quest";
|
|
13037
|
+
} else if (isVersion) {
|
|
13038
|
+
Icon = FiGitBranch3;
|
|
13039
|
+
colorClass = "text-purple-400";
|
|
13040
|
+
badgeText = "Vers\xE3o";
|
|
13041
|
+
} else if (isNode) {
|
|
13042
|
+
Icon = FiBox;
|
|
13043
|
+
colorClass = "text-emerald-400";
|
|
13044
|
+
badgeText = "Node";
|
|
13045
|
+
}
|
|
13046
|
+
return /* @__PURE__ */ React26.createElement(
|
|
13047
|
+
"button",
|
|
13048
|
+
{
|
|
13049
|
+
className: `
|
|
13050
|
+
w-full flex items-center gap-3 px-3 py-2 text-left rounded-md transition-all
|
|
13051
|
+
${index === selectedIndex ? "bg-indigo-500/20 border border-indigo-500/30 text-white" : "text-slate-400 hover:bg-white/5 border border-transparent"}
|
|
13052
|
+
`,
|
|
13053
|
+
key: item.id,
|
|
13054
|
+
onClick: () => selectItem(index)
|
|
13055
|
+
},
|
|
13056
|
+
/* @__PURE__ */ React26.createElement("div", { className: `shrink-0 w-8 h-8 rounded border border-white/5 flex items-center justify-center bg-slate-800/50 ${colorClass}` }, /* @__PURE__ */ React26.createElement(Icon, { size: 14 })),
|
|
13057
|
+
/* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("span", { className: "text-sm font-medium truncate" }, item.name), /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded border border-current opacity-60 ${colorClass}` }, badgeText)))
|
|
13058
|
+
);
|
|
13059
|
+
}) : /* @__PURE__ */ React26.createElement("div", { className: "p-4 text-center text-slate-500 text-sm italic" }, "Nenhum resultado encontrado...")));
|
|
13060
|
+
});
|
|
13061
|
+
MentionList.displayName = "MentionList";
|
|
13062
|
+
var MentionList_default = MentionList;
|
|
13063
|
+
|
|
13064
|
+
// src/components/MentionEditor.jsx
|
|
13065
|
+
var CustomMention = Mention.extend({
|
|
13066
|
+
addAttributes() {
|
|
13067
|
+
var _a;
|
|
13068
|
+
return {
|
|
13069
|
+
...(_a = this.parent) == null ? void 0 : _a.call(this),
|
|
13070
|
+
type: {
|
|
13071
|
+
default: null,
|
|
13072
|
+
parseHTML: (element) => element.getAttribute("data-mention-type"),
|
|
13073
|
+
renderHTML: (attributes) => {
|
|
13074
|
+
if (!attributes.type) {
|
|
13075
|
+
return {};
|
|
13076
|
+
}
|
|
13077
|
+
return {
|
|
13078
|
+
"data-mention-type": attributes.type
|
|
13079
|
+
};
|
|
13080
|
+
}
|
|
13081
|
+
},
|
|
13082
|
+
label: {
|
|
13083
|
+
default: null,
|
|
13084
|
+
parseHTML: (element) => element.getAttribute("data-label"),
|
|
13085
|
+
renderHTML: (attributes) => {
|
|
13086
|
+
if (!attributes.label) {
|
|
13087
|
+
return {};
|
|
13088
|
+
}
|
|
13089
|
+
return {
|
|
13090
|
+
"data-label": attributes.label
|
|
13091
|
+
};
|
|
13092
|
+
}
|
|
13093
|
+
}
|
|
13094
|
+
};
|
|
13095
|
+
}
|
|
13096
|
+
});
|
|
13097
|
+
var MentionEditor = ({
|
|
13098
|
+
initialValue = "",
|
|
13099
|
+
onChange,
|
|
13100
|
+
onPlay,
|
|
13101
|
+
availableItems = [],
|
|
13102
|
+
canEdit = true,
|
|
13103
|
+
placeholder = "Escreva algo... use @ para mencionar"
|
|
13104
|
+
}) => {
|
|
13105
|
+
const parseInitialContent = (text) => {
|
|
13106
|
+
if (!text) return "<p></p>";
|
|
13107
|
+
const parts = text.split(/(\[\[MENTION:[^\]]+\]\])/g);
|
|
13108
|
+
return parts.map((part) => {
|
|
13109
|
+
const match = part.match(/\[\[MENTION:([^:]+):([^:]+):([^\]]+)\]\]/);
|
|
13110
|
+
if (match) {
|
|
13111
|
+
const [, type, id, label] = match;
|
|
13112
|
+
return `<span data-type="mention" data-id="${id}" data-mention-type="${type}" data-label="${label}">@${label}</span>`;
|
|
13113
|
+
}
|
|
13114
|
+
return part;
|
|
13115
|
+
}).join("");
|
|
13116
|
+
};
|
|
13117
|
+
const content = useMemo11(() => parseInitialContent(initialValue), [initialValue]);
|
|
13118
|
+
const editor = useEditor({
|
|
13119
|
+
extensions: [
|
|
13120
|
+
StarterKit.configure({
|
|
13121
|
+
heading: false,
|
|
13122
|
+
bulletList: false,
|
|
13123
|
+
orderedList: false,
|
|
13124
|
+
codeBlock: false,
|
|
13125
|
+
blockquote: false
|
|
13126
|
+
}),
|
|
13127
|
+
CustomMention.configure({
|
|
13128
|
+
HTMLAttributes: {
|
|
13129
|
+
class: "mention"
|
|
13130
|
+
},
|
|
13131
|
+
suggestion: {
|
|
13132
|
+
items: ({ query }) => {
|
|
13133
|
+
return availableItems.filter(
|
|
13134
|
+
(item) => item.name.toLowerCase().includes(query.toLowerCase())
|
|
13135
|
+
).slice(0, 10);
|
|
13136
|
+
},
|
|
13137
|
+
render: () => {
|
|
13138
|
+
let component;
|
|
13139
|
+
let popup;
|
|
13140
|
+
return {
|
|
13141
|
+
onStart: (props) => {
|
|
13142
|
+
component = new ReactRenderer(MentionList_default, {
|
|
13143
|
+
props,
|
|
13144
|
+
editor: props.editor
|
|
13145
|
+
});
|
|
13146
|
+
if (!props.clientRect) {
|
|
13147
|
+
return;
|
|
13148
|
+
}
|
|
13149
|
+
popup = tippy("body", {
|
|
13150
|
+
getReferenceClientRect: props.clientRect,
|
|
13151
|
+
appendTo: () => document.body,
|
|
13152
|
+
content: component.element,
|
|
13153
|
+
showOnCreate: true,
|
|
13154
|
+
interactive: true,
|
|
13155
|
+
trigger: "manual",
|
|
13156
|
+
placement: "bottom-start",
|
|
13157
|
+
theme: "x-view-dark"
|
|
13158
|
+
});
|
|
13159
|
+
},
|
|
13160
|
+
onUpdate(props) {
|
|
13161
|
+
component.updateProps(props);
|
|
13162
|
+
if (!props.clientRect) {
|
|
13163
|
+
return;
|
|
13164
|
+
}
|
|
13165
|
+
popup[0].setProps({
|
|
13166
|
+
getReferenceClientRect: props.clientRect
|
|
13167
|
+
});
|
|
13168
|
+
},
|
|
13169
|
+
onKeyDown(props) {
|
|
13170
|
+
var _a;
|
|
13171
|
+
if (props.event.key === "Escape") {
|
|
13172
|
+
popup[0].hide();
|
|
13173
|
+
return true;
|
|
13174
|
+
}
|
|
13175
|
+
return (_a = component == null ? void 0 : component.ref) == null ? void 0 : _a.onKeyDown(props);
|
|
13176
|
+
},
|
|
13177
|
+
onExit() {
|
|
13178
|
+
if (popup && popup[0]) popup[0].destroy();
|
|
13179
|
+
if (component) component.destroy();
|
|
13180
|
+
}
|
|
13181
|
+
};
|
|
13182
|
+
}
|
|
13183
|
+
}
|
|
13184
|
+
})
|
|
13185
|
+
],
|
|
13186
|
+
content,
|
|
13187
|
+
editable: canEdit,
|
|
13188
|
+
onUpdate: ({ editor: editor2 }) => {
|
|
13189
|
+
const serialize = (json) => {
|
|
13190
|
+
if (!json.content) return "";
|
|
13191
|
+
return json.content.map((block) => {
|
|
13192
|
+
if (block.type === "paragraph") {
|
|
13193
|
+
const inner = block.content ? block.content.map((node) => {
|
|
13194
|
+
if (node.type === "text") return node.text;
|
|
13195
|
+
if (node.type === "mention") {
|
|
13196
|
+
return `[[MENTION:${node.attrs.type}:${node.attrs.id}:${node.attrs.label}]]`;
|
|
13197
|
+
}
|
|
13198
|
+
return "";
|
|
13199
|
+
}).join("") : "";
|
|
13200
|
+
return inner;
|
|
13201
|
+
}
|
|
13202
|
+
return "";
|
|
13203
|
+
}).join("\n").trim();
|
|
13204
|
+
};
|
|
13205
|
+
const serialized = serialize(editor2.getJSON());
|
|
13206
|
+
onChange(serialized);
|
|
13207
|
+
}
|
|
13208
|
+
});
|
|
13209
|
+
if (!editor) {
|
|
13210
|
+
return null;
|
|
13211
|
+
}
|
|
13212
|
+
return /* @__PURE__ */ React27.createElement("div", { className: "relative group/editor min-h-[1.5rem] w-full" }, /* @__PURE__ */ React27.createElement(
|
|
13213
|
+
EditorContent,
|
|
13214
|
+
{
|
|
13215
|
+
editor,
|
|
13216
|
+
className: "text-sm text-slate-200 placeholder-slate-600 focus:outline-none"
|
|
13217
|
+
}
|
|
13218
|
+
), /* @__PURE__ */ React27.createElement("style", null, `
|
|
13219
|
+
.tiptap p {
|
|
13220
|
+
margin: 0;
|
|
13221
|
+
min-height: 1.25rem;
|
|
13222
|
+
line-height: 1.5;
|
|
13223
|
+
}
|
|
13224
|
+
.tiptap .mention {
|
|
13225
|
+
display: inline-flex;
|
|
13226
|
+
align-items: center;
|
|
13227
|
+
background: rgba(99, 102, 241, 0.12);
|
|
13228
|
+
border: 1px solid rgba(99, 102, 241, 0.25);
|
|
13229
|
+
border-radius: 6px;
|
|
13230
|
+
padding: 1px 6px;
|
|
13231
|
+
color: #a5b4fc;
|
|
13232
|
+
font-weight: 600;
|
|
13233
|
+
cursor: pointer;
|
|
13234
|
+
margin: 0 1px;
|
|
13235
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
13236
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
13237
|
+
font-size: 0.85rem;
|
|
13238
|
+
text-decoration: none;
|
|
13239
|
+
vertical-align: baseline;
|
|
13240
|
+
}
|
|
13241
|
+
.tiptap .mention:hover {
|
|
13242
|
+
background: rgba(99, 102, 241, 0.22);
|
|
13243
|
+
border-color: rgba(99, 102, 241, 0.5);
|
|
13244
|
+
color: #fff;
|
|
13245
|
+
transform: translateY(-1px);
|
|
13246
|
+
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2);
|
|
13247
|
+
}
|
|
13248
|
+
.tiptap .mention::before {
|
|
13249
|
+
content: "";
|
|
13250
|
+
display: inline-block;
|
|
13251
|
+
width: 12px;
|
|
13252
|
+
height: 12px;
|
|
13253
|
+
margin-right: 4px;
|
|
13254
|
+
background-size: contain;
|
|
13255
|
+
background-repeat: no-repeat;
|
|
13256
|
+
opacity: 0.8;
|
|
13257
|
+
filter: brightness(1.2);
|
|
13258
|
+
}
|
|
13259
|
+
|
|
13260
|
+
/* Type specific styles */
|
|
13261
|
+
.tiptap .mention[data-mention-type="ancestry"] {
|
|
13262
|
+
background: rgba(139, 92, 246, 0.15);
|
|
13263
|
+
border-color: rgba(139, 92, 246, 0.3);
|
|
13264
|
+
color: #c4b5fd;
|
|
13265
|
+
}
|
|
13266
|
+
.tiptap .mention[data-mention-type="quest"] {
|
|
13267
|
+
background: rgba(16, 185, 129, 0.15);
|
|
13268
|
+
border-color: rgba(16, 185, 129, 0.3);
|
|
13269
|
+
color: #6ee7b7;
|
|
13270
|
+
}
|
|
13271
|
+
.tiptap .mention[data-mention-type="node"] {
|
|
13272
|
+
background: rgba(59, 130, 246, 0.15);
|
|
13273
|
+
border-color: rgba(59, 130, 246, 0.3);
|
|
13274
|
+
color: #93c5fd;
|
|
13275
|
+
}
|
|
13276
|
+
.tiptap .mention[data-mention-type="version"] {
|
|
13277
|
+
background: rgba(245, 158, 11, 0.15);
|
|
13278
|
+
border-color: rgba(245, 158, 11, 0.3);
|
|
13279
|
+
color: #fcd34d;
|
|
13280
|
+
}
|
|
13281
|
+
|
|
13282
|
+
.tiptap:focus {
|
|
13283
|
+
outline: none;
|
|
13284
|
+
}
|
|
13285
|
+
|
|
13286
|
+
.ProseMirror-placeholder:first-child::before {
|
|
13287
|
+
content: attr(data-placeholder);
|
|
13288
|
+
float: left;
|
|
13289
|
+
color: #475569;
|
|
13290
|
+
pointer-events: none;
|
|
13291
|
+
height: 0;
|
|
13292
|
+
font-style: italic;
|
|
13293
|
+
}
|
|
13294
|
+
`));
|
|
13295
|
+
};
|
|
13296
|
+
var MentionEditor_default = MentionEditor;
|
|
13297
|
+
|
|
13298
|
+
// src/components/AncestryBoard.jsx
|
|
13003
13299
|
var GroupItem = ({
|
|
13004
13300
|
group,
|
|
13005
13301
|
index,
|
|
13006
|
-
siblings,
|
|
13007
13302
|
onUpdate,
|
|
13008
13303
|
onDelete,
|
|
13009
13304
|
onAddSubgroup,
|
|
13010
13305
|
onIndent,
|
|
13011
13306
|
onOutdent,
|
|
13012
|
-
onRemoveAncestry,
|
|
13013
|
-
onRequestPickAncestry,
|
|
13014
|
-
pickingGroupId,
|
|
13015
13307
|
onPlayAncestry,
|
|
13016
|
-
|
|
13308
|
+
availableMentionItems,
|
|
13017
13309
|
canEdit
|
|
13018
13310
|
}) => {
|
|
13019
13311
|
const canIndent = index > 0;
|
|
13020
|
-
|
|
13021
|
-
const textareaRef = useRef18(null);
|
|
13022
|
-
const adjustHeight = () => {
|
|
13023
|
-
const textarea = textareaRef.current;
|
|
13024
|
-
if (textarea) {
|
|
13025
|
-
textarea.style.height = "auto";
|
|
13026
|
-
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
13027
|
-
}
|
|
13028
|
-
};
|
|
13029
|
-
useEffect21(() => {
|
|
13030
|
-
adjustHeight();
|
|
13031
|
-
}, [group.text]);
|
|
13032
|
-
return /* @__PURE__ */ React26.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__ */ React26.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ React26.createElement(
|
|
13312
|
+
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(
|
|
13033
13313
|
"div",
|
|
13034
13314
|
{
|
|
13035
|
-
className:
|
|
13036
|
-
flex flex-col gap-2 py-2 px-3 transition-all duration-200
|
|
13037
|
-
${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
|
|
13038
|
-
`
|
|
13315
|
+
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"
|
|
13039
13316
|
},
|
|
13040
|
-
/* @__PURE__ */
|
|
13041
|
-
|
|
13317
|
+
/* @__PURE__ */ React28.createElement(
|
|
13318
|
+
MentionEditor_default,
|
|
13042
13319
|
{
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
style: {
|
|
13047
|
-
minHeight: "1.5rem",
|
|
13048
|
-
maxHeight: "250px"
|
|
13320
|
+
initialValue: group.text,
|
|
13321
|
+
onChange: (newText) => {
|
|
13322
|
+
if (canEdit) onUpdate(group.id, { ...group, text: newText });
|
|
13049
13323
|
},
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
13055
|
-
}
|
|
13324
|
+
onPlay: onPlayAncestry,
|
|
13325
|
+
availableItems: availableMentionItems,
|
|
13326
|
+
canEdit,
|
|
13327
|
+
placeholder: "Escreva sobre este grupo... use @ para mencionar"
|
|
13056
13328
|
}
|
|
13057
13329
|
),
|
|
13058
|
-
|
|
13059
|
-
const isValid = anc.type === "ancestry" || !anc.type ? availableIds.has(String(anc.ancestry_id || anc.id)) : true;
|
|
13060
|
-
const isAncestry = anc.type === "ancestry" || !anc.type;
|
|
13061
|
-
const itemId = isAncestry ? anc.ancestry_id : anc.id;
|
|
13062
|
-
let Icon = FiLayers6;
|
|
13063
|
-
let colorClass = "text-indigo-400";
|
|
13064
|
-
if (anc.type === "quest") {
|
|
13065
|
-
Icon = FiCheckSquare3;
|
|
13066
|
-
colorClass = "text-amber-400";
|
|
13067
|
-
} else if (anc.type === "version") {
|
|
13068
|
-
Icon = FiGitBranch3;
|
|
13069
|
-
colorClass = "text-purple-400";
|
|
13070
|
-
} else if (anc.type === "node") {
|
|
13071
|
-
Icon = FiBox;
|
|
13072
|
-
colorClass = "text-emerald-400";
|
|
13073
|
-
}
|
|
13074
|
-
return /* @__PURE__ */ React26.createElement(
|
|
13075
|
-
"div",
|
|
13076
|
-
{
|
|
13077
|
-
key: `${anc.type || "ancestry"}-${itemId}`,
|
|
13078
|
-
className: `
|
|
13079
|
-
flex items-center gap-2 rounded-md px-3 py-1.5 text-xs transition-all group/card border
|
|
13080
|
-
${isValid ? "bg-slate-800/60 border-white/10 hover:border-indigo-500/30 text-slate-200" : "bg-red-900/10 border-red-500/30 text-red-300/70 hover:bg-red-900/20"}
|
|
13081
|
-
`,
|
|
13082
|
-
title: isValid ? "" : "Esta informa\xE7\xE3o n\xE3o est\xE1 mais dispon\xEDvel neste contexto."
|
|
13083
|
-
},
|
|
13084
|
-
isValid ? /* @__PURE__ */ React26.createElement(
|
|
13085
|
-
"button",
|
|
13086
|
-
{
|
|
13087
|
-
onClick: () => onPlayAncestry(anc),
|
|
13088
|
-
className: `${colorClass} hover:text-white hover:bg-current/20 p-1 rounded transition-colors flex items-center justify-center`,
|
|
13089
|
-
title: "Focar no cen\xE1rio"
|
|
13090
|
-
},
|
|
13091
|
-
/* @__PURE__ */ React26.createElement(Icon, { size: 12 }),
|
|
13092
|
-
/* @__PURE__ */ React26.createElement(
|
|
13093
|
-
FiPlay,
|
|
13094
|
-
{
|
|
13095
|
-
size: 8,
|
|
13096
|
-
className: "ml-0.5 fill-current opacity-0 group-hover/card:opacity-100 transition-opacity"
|
|
13097
|
-
}
|
|
13098
|
-
)
|
|
13099
|
-
) : /* @__PURE__ */ React26.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ React26.createElement(FiAlertTriangle, { size: 10 })),
|
|
13100
|
-
/* @__PURE__ */ React26.createElement(
|
|
13101
|
-
"span",
|
|
13102
|
-
{
|
|
13103
|
-
className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}`
|
|
13104
|
-
},
|
|
13105
|
-
anc.name
|
|
13106
|
-
),
|
|
13107
|
-
canEdit && /* @__PURE__ */ React26.createElement(React26.Fragment, null, /* @__PURE__ */ React26.createElement(
|
|
13108
|
-
"div",
|
|
13109
|
-
{
|
|
13110
|
-
className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}`
|
|
13111
|
-
}
|
|
13112
|
-
), /* @__PURE__ */ React26.createElement(
|
|
13113
|
-
"button",
|
|
13114
|
-
{
|
|
13115
|
-
onClick: () => onRemoveAncestry(group.id, itemId),
|
|
13116
|
-
className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
|
|
13117
|
-
title: "Remover men\xE7\xE3o"
|
|
13118
|
-
},
|
|
13119
|
-
/* @__PURE__ */ React26.createElement(FiX8, { size: 12 })
|
|
13120
|
-
))
|
|
13121
|
-
);
|
|
13122
|
-
})),
|
|
13123
|
-
canEdit && /* @__PURE__ */ React26.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__ */ React26.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React26.createElement(
|
|
13124
|
-
"button",
|
|
13125
|
-
{
|
|
13126
|
-
onClick: () => onRequestPickAncestry(group.id),
|
|
13127
|
-
className: `
|
|
13128
|
-
flex items-center gap-1.5 px-2 py-1 rounded text-xs font-medium transition-colors
|
|
13129
|
-
${isPickingForThisGroup ? "text-indigo-300 animate-pulse" : "text-slate-500 hover:text-indigo-300 hover:bg-indigo-500/10"}
|
|
13130
|
-
`,
|
|
13131
|
-
title: "Adicionar Men\xE7\xE3o a este grupo"
|
|
13132
|
-
},
|
|
13133
|
-
isPickingForThisGroup ? /* @__PURE__ */ React26.createElement(FiCheckCircle, { size: 12 }) : /* @__PURE__ */ React26.createElement(FiSearch8, { size: 12 }),
|
|
13134
|
-
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
13135
|
-
), /* @__PURE__ */ React26.createElement(
|
|
13330
|
+
canEdit && /* @__PURE__ */ React28.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-0 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
|
|
13136
13331
|
"button",
|
|
13137
13332
|
{
|
|
13138
13333
|
onClick: () => onAddSubgroup(group.id),
|
|
13139
|
-
className: "
|
|
13334
|
+
className: "flex items-center gap-1.5 px-3 py-1.5 text-xs text-slate-500 hover:text-white hover:bg-white/10 rounded-md transition-colors",
|
|
13140
13335
|
title: "Criar Subgrupo"
|
|
13141
13336
|
},
|
|
13142
|
-
/* @__PURE__ */
|
|
13143
|
-
|
|
13337
|
+
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 14 }),
|
|
13338
|
+
/* @__PURE__ */ React28.createElement("span", null, "Adicionar Subgrupo")
|
|
13339
|
+
)), /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ React28.createElement(
|
|
13144
13340
|
"button",
|
|
13145
13341
|
{
|
|
13146
13342
|
onClick: () => onIndent(group.id),
|
|
@@ -13148,25 +13344,25 @@ var GroupItem = ({
|
|
|
13148
13344
|
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
13149
13345
|
title: "Aninhar no grupo acima"
|
|
13150
13346
|
},
|
|
13151
|
-
/* @__PURE__ */
|
|
13152
|
-
), /* @__PURE__ */
|
|
13347
|
+
/* @__PURE__ */ React28.createElement(FiArrowRight2, { size: 14 })
|
|
13348
|
+
), /* @__PURE__ */ React28.createElement(
|
|
13153
13349
|
"button",
|
|
13154
13350
|
{
|
|
13155
13351
|
onClick: () => onOutdent(group.id),
|
|
13156
13352
|
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
13157
13353
|
title: "Desaninhar"
|
|
13158
13354
|
},
|
|
13159
|
-
/* @__PURE__ */
|
|
13160
|
-
), /* @__PURE__ */
|
|
13355
|
+
/* @__PURE__ */ React28.createElement(FiArrowLeft3, { size: 14 })
|
|
13356
|
+
), /* @__PURE__ */ React28.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ React28.createElement(
|
|
13161
13357
|
"button",
|
|
13162
13358
|
{
|
|
13163
13359
|
onClick: () => onDelete(group.id),
|
|
13164
13360
|
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
|
|
13165
13361
|
title: "Remover Grupo"
|
|
13166
13362
|
},
|
|
13167
|
-
/* @__PURE__ */
|
|
13363
|
+
/* @__PURE__ */ React28.createElement(FiTrash23, { size: 14 })
|
|
13168
13364
|
)))
|
|
13169
|
-
), group.children && group.children.length > 0 && /* @__PURE__ */
|
|
13365
|
+
), group.children && group.children.length > 0 && /* @__PURE__ */ React28.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ React28.createElement(
|
|
13170
13366
|
GroupItem,
|
|
13171
13367
|
{
|
|
13172
13368
|
key: childGroup.id,
|
|
@@ -13178,11 +13374,8 @@ var GroupItem = ({
|
|
|
13178
13374
|
onAddSubgroup,
|
|
13179
13375
|
onIndent,
|
|
13180
13376
|
onOutdent,
|
|
13181
|
-
onRemoveAncestry,
|
|
13182
|
-
onRequestPickAncestry,
|
|
13183
|
-
pickingGroupId,
|
|
13184
13377
|
onPlayAncestry,
|
|
13185
|
-
|
|
13378
|
+
availableMentionItems,
|
|
13186
13379
|
canEdit
|
|
13187
13380
|
}
|
|
13188
13381
|
))));
|
|
@@ -13197,21 +13390,19 @@ function AncestryBoard({
|
|
|
13197
13390
|
onSave,
|
|
13198
13391
|
userRole
|
|
13199
13392
|
}) {
|
|
13200
|
-
const [
|
|
13201
|
-
const [
|
|
13202
|
-
const [
|
|
13203
|
-
const
|
|
13204
|
-
const [saveStatus, setSaveStatus] = useState25("idle");
|
|
13205
|
-
const canEdit = useMemo11(() => {
|
|
13393
|
+
const [groups, setGroups] = useState26([]);
|
|
13394
|
+
const [isLoaded, setIsLoaded] = useState26(false);
|
|
13395
|
+
const [saveStatus, setSaveStatus] = useState26("idle");
|
|
13396
|
+
const canEdit = useMemo12(() => {
|
|
13206
13397
|
return userRole !== "viewer";
|
|
13207
13398
|
}, [userRole]);
|
|
13208
|
-
|
|
13399
|
+
useEffect23(() => {
|
|
13209
13400
|
if (initialGroups && !isLoaded) {
|
|
13210
13401
|
setGroups(initialGroups);
|
|
13211
13402
|
setIsLoaded(true);
|
|
13212
13403
|
}
|
|
13213
13404
|
}, [initialGroups, isLoaded]);
|
|
13214
|
-
const nodeNamesMap =
|
|
13405
|
+
const nodeNamesMap = useMemo12(() => {
|
|
13215
13406
|
const map = /* @__PURE__ */ new Map();
|
|
13216
13407
|
if (availableNodes && Array.isArray(availableNodes)) {
|
|
13217
13408
|
availableNodes.forEach((node) => {
|
|
@@ -13222,10 +13413,10 @@ function AncestryBoard({
|
|
|
13222
13413
|
}
|
|
13223
13414
|
return map;
|
|
13224
13415
|
}, [availableNodes]);
|
|
13225
|
-
const availableIds =
|
|
13416
|
+
const availableIds = useMemo12(() => {
|
|
13226
13417
|
return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
|
|
13227
13418
|
}, [availableAncestries]);
|
|
13228
|
-
const
|
|
13419
|
+
const availableMentionItems = useMemo12(() => {
|
|
13229
13420
|
const ancestries = availableAncestries.map((a) => ({
|
|
13230
13421
|
id: String(a.ancestry_id),
|
|
13231
13422
|
ancestry_id: a.ancestry_id,
|
|
@@ -13253,16 +13444,10 @@ function AncestryBoard({
|
|
|
13253
13444
|
return groupList.map((g) => ({
|
|
13254
13445
|
id: g.id,
|
|
13255
13446
|
text: g.text || "",
|
|
13256
|
-
ancestries: (g.ancestries || []).map((a) => ({
|
|
13257
|
-
id: a.id || a.ancestry_id,
|
|
13258
|
-
ancestry_id: a.ancestry_id,
|
|
13259
|
-
name: a.name,
|
|
13260
|
-
type: a.type || "ancestry"
|
|
13261
|
-
})),
|
|
13262
13447
|
children: sanitizeGroups(g.children || [])
|
|
13263
13448
|
}));
|
|
13264
13449
|
};
|
|
13265
|
-
|
|
13450
|
+
useEffect23(() => {
|
|
13266
13451
|
if (!isLoaded || !onSave) return;
|
|
13267
13452
|
const timeoutId = setTimeout(async () => {
|
|
13268
13453
|
setSaveStatus("saving");
|
|
@@ -13280,50 +13465,30 @@ function AncestryBoard({
|
|
|
13280
13465
|
}, 3e3);
|
|
13281
13466
|
return () => clearTimeout(timeoutId);
|
|
13282
13467
|
}, [groups, isLoaded, onSave]);
|
|
13283
|
-
|
|
13468
|
+
useEffect23(() => {
|
|
13284
13469
|
if (!isOpen) return;
|
|
13285
13470
|
const handleKeyDown = (e) => {
|
|
13286
13471
|
if (e.key === "Escape") {
|
|
13287
|
-
|
|
13288
|
-
setPickingGroupId(null);
|
|
13289
|
-
} else {
|
|
13290
|
-
onClose();
|
|
13291
|
-
}
|
|
13472
|
+
onClose();
|
|
13292
13473
|
e.preventDefault();
|
|
13293
13474
|
e.stopPropagation();
|
|
13294
13475
|
}
|
|
13295
13476
|
};
|
|
13296
13477
|
window.addEventListener("keydown", handleKeyDown);
|
|
13297
13478
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
13298
|
-
}, [isOpen, onClose
|
|
13299
|
-
const filtered = useMemo11(() => {
|
|
13300
|
-
const term = searchTerm.toLowerCase().trim();
|
|
13301
|
-
return allMentionableItems.filter((item) => {
|
|
13302
|
-
if (!term) return true;
|
|
13303
|
-
const nameMatch = item.name && item.name.toLowerCase().includes(term);
|
|
13304
|
-
const descMatch = item.description && item.description.toLowerCase().includes(term);
|
|
13305
|
-
let parentMatch = false;
|
|
13306
|
-
if (item.type === "ancestry") {
|
|
13307
|
-
const parentName = nodeNamesMap.get(String(item.ancestral_node)) || "";
|
|
13308
|
-
parentMatch = parentName.toLowerCase().includes(term);
|
|
13309
|
-
}
|
|
13310
|
-
return nameMatch || descMatch || parentMatch;
|
|
13311
|
-
});
|
|
13312
|
-
}, [allMentionableItems, searchTerm, nodeNamesMap]);
|
|
13479
|
+
}, [isOpen, onClose]);
|
|
13313
13480
|
const handleAddRootGroup = () => {
|
|
13314
13481
|
const newGroup = {
|
|
13315
|
-
id:
|
|
13482
|
+
id: uuidv411(),
|
|
13316
13483
|
text: "",
|
|
13317
|
-
ancestries: [],
|
|
13318
13484
|
children: []
|
|
13319
13485
|
};
|
|
13320
13486
|
setGroups((prev) => [newGroup, ...prev]);
|
|
13321
13487
|
};
|
|
13322
13488
|
const handleAddSubgroup = (parentId) => {
|
|
13323
13489
|
const newGroup = {
|
|
13324
|
-
id:
|
|
13490
|
+
id: uuidv411(),
|
|
13325
13491
|
text: "",
|
|
13326
|
-
ancestries: [],
|
|
13327
13492
|
children: []
|
|
13328
13493
|
};
|
|
13329
13494
|
const addRecursive = (list) => {
|
|
@@ -13394,42 +13559,6 @@ function AncestryBoard({
|
|
|
13394
13559
|
return newList;
|
|
13395
13560
|
});
|
|
13396
13561
|
};
|
|
13397
|
-
const handleRequestPick = (groupId) => {
|
|
13398
|
-
setPickingGroupId((prev) => prev === groupId ? null : groupId);
|
|
13399
|
-
};
|
|
13400
|
-
const handleSelectAncestry = (item) => {
|
|
13401
|
-
if (pickingGroupId) {
|
|
13402
|
-
setGroups((prev) => {
|
|
13403
|
-
const addRecursive = (list) => {
|
|
13404
|
-
return list.map((g) => {
|
|
13405
|
-
if (g.id === pickingGroupId) {
|
|
13406
|
-
const currentId = item.id;
|
|
13407
|
-
const exists = g.ancestries.some(
|
|
13408
|
-
(a) => (a.id || a.ancestry_id) === currentId && a.type === item.type
|
|
13409
|
-
);
|
|
13410
|
-
if (exists) return g;
|
|
13411
|
-
return { ...g, ancestries: [...g.ancestries, item] };
|
|
13412
|
-
}
|
|
13413
|
-
return { ...g, children: addRecursive(g.children) };
|
|
13414
|
-
});
|
|
13415
|
-
};
|
|
13416
|
-
return addRecursive(prev);
|
|
13417
|
-
});
|
|
13418
|
-
setPickingGroupId(null);
|
|
13419
|
-
} else {
|
|
13420
|
-
let fullItem = item;
|
|
13421
|
-
if (item.type === "ancestry" || !item.type) {
|
|
13422
|
-
fullItem = availableAncestries.find(
|
|
13423
|
-
(a) => String(a.ancestry_id) === String(item.id || item.ancestry_id)
|
|
13424
|
-
) || item;
|
|
13425
|
-
} else {
|
|
13426
|
-
fullItem = availableNodes.find(
|
|
13427
|
-
(n) => String(n.id) === String(item.id)
|
|
13428
|
-
) || item;
|
|
13429
|
-
}
|
|
13430
|
-
onSelect(fullItem);
|
|
13431
|
-
}
|
|
13432
|
-
};
|
|
13433
13562
|
const handlePlayFromGroup = (item) => {
|
|
13434
13563
|
let fullItem = item;
|
|
13435
13564
|
if (item.type === "ancestry" || !item.type) {
|
|
@@ -13445,52 +13574,34 @@ function AncestryBoard({
|
|
|
13445
13574
|
onSelect(fullItem);
|
|
13446
13575
|
}
|
|
13447
13576
|
};
|
|
13448
|
-
const handleRemoveAncestryFromGroup = (groupId, itemId) => {
|
|
13449
|
-
setGroups((prev) => {
|
|
13450
|
-
const removeRecursive = (list) => {
|
|
13451
|
-
return list.map((g) => {
|
|
13452
|
-
if (g.id === groupId) {
|
|
13453
|
-
return {
|
|
13454
|
-
...g,
|
|
13455
|
-
ancestries: g.ancestries.filter(
|
|
13456
|
-
(a) => (a.id || a.ancestry_id) !== itemId
|
|
13457
|
-
)
|
|
13458
|
-
};
|
|
13459
|
-
}
|
|
13460
|
-
return { ...g, children: removeRecursive(g.children) };
|
|
13461
|
-
});
|
|
13462
|
-
};
|
|
13463
|
-
return removeRecursive(prev);
|
|
13464
|
-
});
|
|
13465
|
-
};
|
|
13466
13577
|
if (!isOpen) return null;
|
|
13467
|
-
return /* @__PURE__ */
|
|
13578
|
+
return /* @__PURE__ */ React28.createElement(
|
|
13468
13579
|
"div",
|
|
13469
13580
|
{
|
|
13470
13581
|
className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
|
|
13471
13582
|
onClick: onClose
|
|
13472
13583
|
},
|
|
13473
|
-
/* @__PURE__ */
|
|
13584
|
+
/* @__PURE__ */ React28.createElement(
|
|
13474
13585
|
"div",
|
|
13475
13586
|
{
|
|
13476
|
-
className: "bg-slate-950 border border-white/10 rounded-xl w-[
|
|
13587
|
+
className: "bg-slate-950 border border-white/10 rounded-xl w-[90vw] max-w-[1200px] h-[90vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
|
|
13477
13588
|
onClick: (e) => e.stopPropagation()
|
|
13478
13589
|
},
|
|
13479
|
-
/* @__PURE__ */
|
|
13590
|
+
/* @__PURE__ */ React28.createElement("div", { className: "h-14 px-6 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(
|
|
13480
13591
|
FiLoader5,
|
|
13481
13592
|
{
|
|
13482
13593
|
className: "animate-spin text-indigo-400",
|
|
13483
13594
|
size: 12
|
|
13484
13595
|
}
|
|
13485
|
-
), /* @__PURE__ */
|
|
13596
|
+
), /* @__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(
|
|
13486
13597
|
"button",
|
|
13487
13598
|
{
|
|
13488
13599
|
onClick: handleAddRootGroup,
|
|
13489
13600
|
className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
|
|
13490
13601
|
},
|
|
13491
|
-
/* @__PURE__ */
|
|
13492
|
-
/* @__PURE__ */
|
|
13493
|
-
), /* @__PURE__ */
|
|
13602
|
+
/* @__PURE__ */ React28.createElement(FiPlus10, { size: 14, className: "text-indigo-400" }),
|
|
13603
|
+
/* @__PURE__ */ React28.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
|
|
13604
|
+
), /* @__PURE__ */ React28.createElement(
|
|
13494
13605
|
"button",
|
|
13495
13606
|
{
|
|
13496
13607
|
onClick: onClose,
|
|
@@ -13498,127 +13609,36 @@ function AncestryBoard({
|
|
|
13498
13609
|
},
|
|
13499
13610
|
"\xD7"
|
|
13500
13611
|
))),
|
|
13501
|
-
/* @__PURE__ */
|
|
13502
|
-
"
|
|
13612
|
+
/* @__PURE__ */ React28.createElement("div", { className: "flex flex-1 overflow-hidden bg-slate-900/20" }, /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React28.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-8 max-w-[900px] mx-auto w-full space-y-6" }, groups.length === 0 ? /* @__PURE__ */ React28.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-4 border-2 border-dashed border-white/5 rounded-2xl bg-slate-900/40 p-12" }, /* @__PURE__ */ React28.createElement(FiLayers7, { size: 40, className: "opacity-10 text-indigo-400" }), /* @__PURE__ */ React28.createElement("div", { className: "text-center space-y-1" }, /* @__PURE__ */ React28.createElement("p", { className: "text-sm font-medium text-slate-300" }, "Nenhum grupo criado"), /* @__PURE__ */ React28.createElement("p", { className: "text-xs text-slate-500 max-w-[200px]" }, canEdit ? "Comece organizando sua narrativa criando o primeiro grupo." : "Este board ainda n\xE3o possui conte\xFAdo.")), canEdit && /* @__PURE__ */ React28.createElement(
|
|
13613
|
+
"button",
|
|
13503
13614
|
{
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
|
|
13507
|
-
min-w-[280px] max-w-[500px] bg-slate-900
|
|
13508
|
-
`
|
|
13615
|
+
onClick: handleAddRootGroup,
|
|
13616
|
+
className: "mt-2 px-4 py-2 bg-indigo-500/10 hover:bg-indigo-500/20 text-indigo-400 rounded-lg border border-indigo-500/20 transition-all text-xs font-bold uppercase tracking-wider"
|
|
13509
13617
|
},
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
{
|
|
13513
|
-
className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}`
|
|
13514
|
-
}
|
|
13515
|
-
), /* @__PURE__ */ React26.createElement(
|
|
13516
|
-
"input",
|
|
13517
|
-
{
|
|
13518
|
-
type: "text",
|
|
13519
|
-
placeholder: pickingGroupId ? "Pesquise para adicionar..." : "Pesquisar (Ancestralidades e Nodes)",
|
|
13520
|
-
className: `
|
|
13521
|
-
w-full rounded-md pl-9 pr-4 py-2 text-sm transition-all focus:outline-none focus:ring-1 focus:ring-indigo-500 border
|
|
13522
|
-
${pickingGroupId ? "bg-indigo-950/30 border-indigo-500/30 text-white placeholder-indigo-300/50" : "bg-slate-950 border-white/10 text-slate-200 placeholder-slate-600"}
|
|
13523
|
-
`,
|
|
13524
|
-
value: searchTerm,
|
|
13525
|
-
onChange: (e) => setSearchTerm(e.target.value),
|
|
13526
|
-
autoFocus: !pickingGroupId
|
|
13527
|
-
}
|
|
13528
|
-
))),
|
|
13529
|
-
/* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((item) => {
|
|
13530
|
-
const isPicking = !!pickingGroupId;
|
|
13531
|
-
const isQuest = item.type === "quest";
|
|
13532
|
-
const isVersion = item.type === "version";
|
|
13533
|
-
const isNode = item.type === "node";
|
|
13534
|
-
let Icon = FiLayers6;
|
|
13535
|
-
let colorClass = "bg-slate-800 text-indigo-400 border-white/5";
|
|
13536
|
-
let pickingColorClass = "bg-indigo-500 text-white border-indigo-400";
|
|
13537
|
-
let hoverClass = "hover:bg-indigo-600/10 hover:border-indigo-500/30";
|
|
13538
|
-
let badge = null;
|
|
13539
|
-
if (isQuest) {
|
|
13540
|
-
Icon = FiCheckSquare3;
|
|
13541
|
-
colorClass = "bg-slate-800 text-amber-400 border-white/5";
|
|
13542
|
-
pickingColorClass = "bg-amber-500 text-white border-amber-400";
|
|
13543
|
-
hoverClass = "hover:bg-amber-500/10 hover:border-amber-500/30";
|
|
13544
|
-
badge = "Quest";
|
|
13545
|
-
} else if (isVersion) {
|
|
13546
|
-
Icon = FiGitBranch3;
|
|
13547
|
-
colorClass = "bg-slate-800 text-purple-400 border-white/5";
|
|
13548
|
-
pickingColorClass = "bg-purple-500 text-white border-purple-400";
|
|
13549
|
-
hoverClass = "hover:bg-purple-500/10 hover:border-purple-500/30";
|
|
13550
|
-
badge = "Ver";
|
|
13551
|
-
} else if (isNode) {
|
|
13552
|
-
Icon = FiBox;
|
|
13553
|
-
colorClass = "bg-slate-800 text-emerald-400 border-white/5";
|
|
13554
|
-
pickingColorClass = "bg-emerald-500 text-white border-emerald-400";
|
|
13555
|
-
hoverClass = "hover:bg-emerald-500/10 hover:border-emerald-500/30";
|
|
13556
|
-
badge = "Node";
|
|
13557
|
-
}
|
|
13558
|
-
return /* @__PURE__ */ React26.createElement(
|
|
13559
|
-
"div",
|
|
13560
|
-
{
|
|
13561
|
-
key: `${item.type}-${item.id}`,
|
|
13562
|
-
onClick: () => {
|
|
13563
|
-
if (isPicking) handleSelectAncestry(item);
|
|
13564
|
-
},
|
|
13565
|
-
className: `
|
|
13566
|
-
group relative flex items-start gap-3 p-3 text-left rounded-lg border transition-all duration-200
|
|
13567
|
-
${isPicking ? `border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer` : `border-white/5 bg-slate-800/40 ${hoverClass} cursor-default`}
|
|
13568
|
-
`
|
|
13569
|
-
},
|
|
13570
|
-
/* @__PURE__ */ React26.createElement(
|
|
13571
|
-
"div",
|
|
13572
|
-
{
|
|
13573
|
-
className: `
|
|
13574
|
-
mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
|
|
13575
|
-
${isPicking ? pickingColorClass : `${colorClass} group-hover:bg-opacity-80`}
|
|
13576
|
-
`
|
|
13577
|
-
},
|
|
13578
|
-
isPicking ? /* @__PURE__ */ React26.createElement(FiPlus10, { size: 16 }) : /* @__PURE__ */ React26.createElement(Icon, { size: 14 })
|
|
13579
|
-
),
|
|
13580
|
-
/* @__PURE__ */ React26.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ React26.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ React26.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, item.name || "Sem Nome"), badge && /* @__PURE__ */ React26.createElement("span", { className: `text-[9px] px-1 py-0.5 rounded ${isQuest ? "bg-amber-500/10 text-amber-400" : isVersion ? "bg-purple-500/10 text-purple-400" : "bg-emerald-500/10 text-emerald-400"} border border-current opacity-50` }, badge), item.is_private && /* @__PURE__ */ React26.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), item.type === "ancestry" && /* @__PURE__ */ React26.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ React26.createElement(FiCornerUpRight4, { size: 10 }), /* @__PURE__ */ React26.createElement("span", { className: "truncate max-w-[120px]" }, nodeNamesMap.get(String(item.ancestral_node)) || "Node Desconhecido")), item.description && /* @__PURE__ */ React26.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, item.description)),
|
|
13581
|
-
!isPicking && /* @__PURE__ */ React26.createElement(
|
|
13582
|
-
"button",
|
|
13583
|
-
{
|
|
13584
|
-
onClick: (e) => {
|
|
13585
|
-
e.stopPropagation();
|
|
13586
|
-
handleSelectAncestry(item);
|
|
13587
|
-
},
|
|
13588
|
-
className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
|
|
13589
|
-
title: "Renderizar / Focar"
|
|
13590
|
-
},
|
|
13591
|
-
/* @__PURE__ */ React26.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ React26.createElement(FiPlay, { size: 14, className: "ml-0.5" }))
|
|
13592
|
-
)
|
|
13593
|
-
);
|
|
13594
|
-
}))
|
|
13595
|
-
), /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ React26.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ React26.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ React26.createElement(FiLayers6, { size: 24, className: "opacity-20" }), /* @__PURE__ */ React26.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ React26.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ React26.createElement(React26.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ React26.createElement(
|
|
13618
|
+
"Criar Primeiro Grupo"
|
|
13619
|
+
)) : groups.map((group, index) => /* @__PURE__ */ React28.createElement(
|
|
13596
13620
|
GroupItem,
|
|
13597
13621
|
{
|
|
13598
13622
|
key: group.id,
|
|
13599
13623
|
index,
|
|
13600
13624
|
group,
|
|
13601
|
-
siblings: groups,
|
|
13602
13625
|
onUpdate: handleUpdateGroup,
|
|
13603
13626
|
onDelete: handleDeleteGroup,
|
|
13604
13627
|
onAddSubgroup: handleAddSubgroup,
|
|
13605
13628
|
onIndent: handleIndent,
|
|
13606
13629
|
onOutdent: handleOutdent,
|
|
13607
|
-
onRemoveAncestry: handleRemoveAncestryFromGroup,
|
|
13608
|
-
onRequestPickAncestry: handleRequestPick,
|
|
13609
|
-
pickingGroupId,
|
|
13610
13630
|
onPlayAncestry: handlePlayFromGroup,
|
|
13611
|
-
|
|
13631
|
+
availableMentionItems,
|
|
13612
13632
|
canEdit
|
|
13613
13633
|
}
|
|
13614
13634
|
))))),
|
|
13615
|
-
/* @__PURE__ */
|
|
13635
|
+
/* @__PURE__ */ React28.createElement("div", { className: "px-6 py-3 border-t border-white/10 bg-slate-950/50 text-[10px] uppercase tracking-widest font-bold text-slate-600 flex justify-between items-center flex-shrink-0" }, /* @__PURE__ */ React28.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React28.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React28.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-indigo-500" }), " ", availableMentionItems.length, " RECURSOS DISPON\xCDVEIS"), /* @__PURE__ */ React28.createElement("span", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React28.createElement("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }), " ", groups.length, " GRUPOS PRINCIPAIS")), /* @__PURE__ */ React28.createElement("span", { className: "text-slate-700" }, "X.VIEW :: ANCESTRY BOARD ENGINE"))
|
|
13616
13636
|
)
|
|
13617
13637
|
);
|
|
13618
13638
|
}
|
|
13619
13639
|
|
|
13620
13640
|
// src/components/MilestoneManager.jsx
|
|
13621
|
-
import
|
|
13641
|
+
import React29, { useState as useState27 } from "react";
|
|
13622
13642
|
import { FiTarget as FiTarget4, FiPlus as FiPlus11, FiTrash2 as FiTrash24, FiX as FiX9, FiCheck as FiCheck12, FiPauseCircle, FiPlayCircle } from "react-icons/fi";
|
|
13623
13643
|
function MilestoneManager({
|
|
13624
13644
|
isOpen,
|
|
@@ -13627,7 +13647,7 @@ function MilestoneManager({
|
|
|
13627
13647
|
onUpdateMilestones = () => {
|
|
13628
13648
|
}
|
|
13629
13649
|
}) {
|
|
13630
|
-
const [newMilestoneName, setNewMilestoneName] =
|
|
13650
|
+
const [newMilestoneName, setNewMilestoneName] = useState27("");
|
|
13631
13651
|
const handleAddMilestone = () => {
|
|
13632
13652
|
if (!newMilestoneName.trim()) return;
|
|
13633
13653
|
const newMilestone = {
|
|
@@ -13652,27 +13672,27 @@ function MilestoneManager({
|
|
|
13652
13672
|
};
|
|
13653
13673
|
if (!isOpen) return null;
|
|
13654
13674
|
const swallow = (e) => e.stopPropagation();
|
|
13655
|
-
return /* @__PURE__ */
|
|
13675
|
+
return /* @__PURE__ */ React29.createElement(
|
|
13656
13676
|
"div",
|
|
13657
13677
|
{
|
|
13658
13678
|
className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-950/40 backdrop-blur-sm animate-in fade-in duration-300",
|
|
13659
13679
|
onClick: onClose
|
|
13660
13680
|
},
|
|
13661
|
-
/* @__PURE__ */
|
|
13681
|
+
/* @__PURE__ */ React29.createElement(
|
|
13662
13682
|
"div",
|
|
13663
13683
|
{
|
|
13664
13684
|
className: "w-full max-w-lg bg-slate-900/90 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl flex flex-col max-h-[85vh] animate-in zoom-in-95 duration-300",
|
|
13665
13685
|
onClick: swallow
|
|
13666
13686
|
},
|
|
13667
|
-
/* @__PURE__ */
|
|
13687
|
+
/* @__PURE__ */ React29.createElement("div", { className: "px-6 py-4 border-b border-white/10 flex items-center justify-between" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React29.createElement("div", { className: "p-2 rounded-lg bg-indigo-500/20 text-indigo-400" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 20 })), /* @__PURE__ */ React29.createElement("div", null, /* @__PURE__ */ React29.createElement("h2", { className: "text-lg font-semibold text-slate-100" }, "Milestones"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-400" }, "Gerencie os marcos do seu cen\xE1rio"))), /* @__PURE__ */ React29.createElement(
|
|
13668
13688
|
"button",
|
|
13669
13689
|
{
|
|
13670
13690
|
onClick: onClose,
|
|
13671
13691
|
className: "p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
|
|
13672
13692
|
},
|
|
13673
|
-
/* @__PURE__ */
|
|
13693
|
+
/* @__PURE__ */ React29.createElement(FiX9, { size: 20 })
|
|
13674
13694
|
)),
|
|
13675
|
-
/* @__PURE__ */
|
|
13695
|
+
/* @__PURE__ */ React29.createElement("div", { className: "px-6 py-5 bg-white/5 border-b border-white/5" }, /* @__PURE__ */ React29.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React29.createElement(
|
|
13676
13696
|
"input",
|
|
13677
13697
|
{
|
|
13678
13698
|
type: "text",
|
|
@@ -13682,47 +13702,47 @@ function MilestoneManager({
|
|
|
13682
13702
|
placeholder: "Adicionar novo milestone...",
|
|
13683
13703
|
className: "flex-1 bg-slate-800/50 border border-white/10 rounded-xl px-4 py-2.5 text-sm text-slate-100 placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/40 focus:border-indigo-500/50 transition-all shadow-inner"
|
|
13684
13704
|
}
|
|
13685
|
-
), /* @__PURE__ */
|
|
13705
|
+
), /* @__PURE__ */ React29.createElement(
|
|
13686
13706
|
"button",
|
|
13687
13707
|
{
|
|
13688
13708
|
onClick: handleAddMilestone,
|
|
13689
13709
|
disabled: !newMilestoneName.trim(),
|
|
13690
13710
|
className: "px-4 py-2.5 rounded-xl bg-indigo-600 hover:bg-indigo-500 disabled:opacity-30 disabled:cursor-not-allowed text-white text-sm font-medium transition-all flex items-center gap-2 shadow-lg shadow-indigo-500/20 active:scale-95"
|
|
13691
13711
|
},
|
|
13692
|
-
/* @__PURE__ */
|
|
13712
|
+
/* @__PURE__ */ React29.createElement(FiPlus11, { size: 18 }),
|
|
13693
13713
|
"Adicionar"
|
|
13694
13714
|
))),
|
|
13695
|
-
/* @__PURE__ */
|
|
13715
|
+
/* @__PURE__ */ React29.createElement("div", { className: "flex-1 overflow-y-auto px-6 py-4 custom-scrollbar" }, milestones.length > 0 ? /* @__PURE__ */ React29.createElement("div", { className: "space-y-3" }, milestones.map((ms) => /* @__PURE__ */ React29.createElement(
|
|
13696
13716
|
"div",
|
|
13697
13717
|
{
|
|
13698
13718
|
key: ms.id,
|
|
13699
13719
|
className: `group flex items-center justify-between p-4 rounded-xl border transition-all duration-200 ${ms.status === "active" ? "bg-slate-800/40 border-indigo-500/20 hover:border-indigo-500/40" : "bg-slate-900/40 border-white/5 opacity-60 grayscale-[0.3]"}`
|
|
13700
13720
|
},
|
|
13701
|
-
/* @__PURE__ */
|
|
13721
|
+
/* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-3 min-w-0" }, /* @__PURE__ */ React29.createElement(
|
|
13702
13722
|
"div",
|
|
13703
13723
|
{
|
|
13704
13724
|
className: `w-2 h-2 rounded-full shrink-0 ${ms.status === "active" ? "bg-indigo-400 shadow-[0_0_8px_rgba(129,140,248,0.6)]" : "bg-slate-600"}`
|
|
13705
13725
|
}
|
|
13706
|
-
), /* @__PURE__ */
|
|
13707
|
-
/* @__PURE__ */
|
|
13726
|
+
), /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React29.createElement("span", { className: `text-sm font-medium truncate ${ms.status === "active" ? "text-slate-100" : "text-slate-400 line-through"}` }, ms.name), /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-wider" }, ms.status === "active" ? "Ativo" : "Inativo"))),
|
|
13727
|
+
/* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React29.createElement(
|
|
13708
13728
|
"button",
|
|
13709
13729
|
{
|
|
13710
13730
|
onClick: () => handleToggleMilestoneStatus(ms.id),
|
|
13711
13731
|
className: `p-2 rounded-lg transition-all ${ms.status === "active" ? "hover:bg-slate-700 text-slate-400" : "hover:bg-indigo-500/20 text-indigo-400"}`,
|
|
13712
13732
|
title: ms.status === "active" ? "Inativar" : "Ativar"
|
|
13713
13733
|
},
|
|
13714
|
-
ms.status === "active" ? /* @__PURE__ */
|
|
13715
|
-
), /* @__PURE__ */
|
|
13734
|
+
ms.status === "active" ? /* @__PURE__ */ React29.createElement(FiPauseCircle, { size: 18 }) : /* @__PURE__ */ React29.createElement(FiPlayCircle, { size: 18 })
|
|
13735
|
+
), /* @__PURE__ */ React29.createElement(
|
|
13716
13736
|
"button",
|
|
13717
13737
|
{
|
|
13718
13738
|
onClick: () => handleRemoveMilestone(ms.id),
|
|
13719
13739
|
className: "p-2 rounded-lg hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-all",
|
|
13720
13740
|
title: "Remover"
|
|
13721
13741
|
},
|
|
13722
|
-
/* @__PURE__ */
|
|
13742
|
+
/* @__PURE__ */ React29.createElement(FiTrash24, { size: 18 })
|
|
13723
13743
|
))
|
|
13724
|
-
))) : /* @__PURE__ */
|
|
13725
|
-
/* @__PURE__ */
|
|
13744
|
+
))) : /* @__PURE__ */ React29.createElement("div", { className: "flex flex-col items-center justify-center py-12 text-center" }, /* @__PURE__ */ React29.createElement("div", { className: "p-4 rounded-full bg-slate-800/30 text-slate-600 mb-4" }, /* @__PURE__ */ React29.createElement(FiTarget4, { size: 40 })), /* @__PURE__ */ React29.createElement("h3", { className: "text-slate-400 font-medium" }, "Nenhum milestone definido"), /* @__PURE__ */ React29.createElement("p", { className: "text-xs text-slate-600 max-w-[200px] mt-1 italic" }, "Defina marcos importantes para orientar o progresso do projeto."))),
|
|
13745
|
+
/* @__PURE__ */ React29.createElement("div", { className: "px-6 py-4 border-t border-white/5 bg-slate-900/50 flex items-center justify-between rounded-b-2xl" }, /* @__PURE__ */ React29.createElement("div", { className: "flex gap-4" }, /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Total:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-slate-300" }, milestones.length)), /* @__PURE__ */ React29.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React29.createElement("span", { className: "text-[10px] text-slate-500 uppercase tracking-widest" }, "Ativos:"), /* @__PURE__ */ React29.createElement("span", { className: "text-xs font-bold text-indigo-400" }, milestones.filter((m) => m.status === "active").length))))
|
|
13726
13746
|
)
|
|
13727
13747
|
);
|
|
13728
13748
|
}
|
|
@@ -13814,7 +13834,7 @@ function XViewScene({
|
|
|
13814
13834
|
const searchParams = useSearchParams();
|
|
13815
13835
|
const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
|
|
13816
13836
|
const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
|
|
13817
|
-
const viewParams =
|
|
13837
|
+
const viewParams = useMemo13(() => {
|
|
13818
13838
|
if (encryptedConfig) {
|
|
13819
13839
|
const data = decryptData(encryptedConfig);
|
|
13820
13840
|
if (data) {
|
|
@@ -13823,7 +13843,7 @@ function XViewScene({
|
|
|
13823
13843
|
}
|
|
13824
13844
|
return null;
|
|
13825
13845
|
}, [encryptedConfig, session]);
|
|
13826
|
-
|
|
13846
|
+
useEffect24(() => {
|
|
13827
13847
|
async function verifyPermission() {
|
|
13828
13848
|
if (!viewParams || !session || !check_user_permission) return;
|
|
13829
13849
|
const { id, type, owner_id } = viewParams;
|
|
@@ -13860,21 +13880,21 @@ function XViewScene({
|
|
|
13860
13880
|
setIsLoading(false);
|
|
13861
13881
|
}
|
|
13862
13882
|
}, [viewParams, session, status, check_user_permission]);
|
|
13863
|
-
const sceneConfigId =
|
|
13864
|
-
const ownerId =
|
|
13865
|
-
const dbSaveUrl =
|
|
13883
|
+
const sceneConfigId = useMemo13(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
|
|
13884
|
+
const ownerId = useMemo13(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
|
|
13885
|
+
const dbSaveUrl = useMemo13(() => {
|
|
13866
13886
|
if (ownerId && sceneConfigId) {
|
|
13867
13887
|
return `x_view_dbs/${ownerId}/${sceneConfigId}`;
|
|
13868
13888
|
}
|
|
13869
13889
|
return null;
|
|
13870
13890
|
}, [ownerId, sceneConfigId]);
|
|
13871
|
-
const sceneSaveUrl =
|
|
13891
|
+
const sceneSaveUrl = useMemo13(() => {
|
|
13872
13892
|
if (ownerId && sceneConfigId) {
|
|
13873
13893
|
return `x_view_scenes/${ownerId}/${sceneConfigId}`;
|
|
13874
13894
|
}
|
|
13875
13895
|
return null;
|
|
13876
13896
|
}, [ownerId, sceneConfigId]);
|
|
13877
|
-
const ancestry_save_url =
|
|
13897
|
+
const ancestry_save_url = useMemo13(() => {
|
|
13878
13898
|
if (ownerId && sceneConfigId) {
|
|
13879
13899
|
return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
|
|
13880
13900
|
}
|
|
@@ -13883,42 +13903,42 @@ function XViewScene({
|
|
|
13883
13903
|
const sceneDataRef = useRef19(null);
|
|
13884
13904
|
const parentDataRef = useRef19(null);
|
|
13885
13905
|
const ancestryDataRef = useRef19(null);
|
|
13886
|
-
const [isLoading, setIsLoading] =
|
|
13887
|
-
const [permissionStatus, setPermissionStatus] =
|
|
13888
|
-
const [userPermissionRole, setUserPermissionRole] =
|
|
13889
|
-
const [viewMembers, setViewMembers] =
|
|
13890
|
-
const [isInitialized, setIsInitialized] =
|
|
13891
|
-
const [sceneVersion, setSceneVersion] =
|
|
13892
|
-
const [contextMenu, setContextMenu] =
|
|
13906
|
+
const [isLoading, setIsLoading] = useState28(true);
|
|
13907
|
+
const [permissionStatus, setPermissionStatus] = useState28("loading");
|
|
13908
|
+
const [userPermissionRole, setUserPermissionRole] = useState28(null);
|
|
13909
|
+
const [viewMembers, setViewMembers] = useState28([]);
|
|
13910
|
+
const [isInitialized, setIsInitialized] = useState28(false);
|
|
13911
|
+
const [sceneVersion, setSceneVersion] = useState28(0);
|
|
13912
|
+
const [contextMenu, setContextMenu] = useState28({
|
|
13893
13913
|
visible: false,
|
|
13894
13914
|
x: 0,
|
|
13895
13915
|
y: 0,
|
|
13896
13916
|
nodeData: null
|
|
13897
13917
|
});
|
|
13898
|
-
const [multiContextMenu, setMultiContextMenu] =
|
|
13918
|
+
const [multiContextMenu, setMultiContextMenu] = useState28({
|
|
13899
13919
|
visible: false,
|
|
13900
13920
|
x: 0,
|
|
13901
13921
|
y: 0,
|
|
13902
13922
|
nodeIds: null
|
|
13903
13923
|
});
|
|
13904
|
-
const [relationshipMenu, setRelationshipMenu] =
|
|
13924
|
+
const [relationshipMenu, setRelationshipMenu] = useState28({
|
|
13905
13925
|
visible: false,
|
|
13906
13926
|
x: 0,
|
|
13907
13927
|
y: 0,
|
|
13908
13928
|
linkObject: null
|
|
13909
13929
|
});
|
|
13910
|
-
const [creationMode, setCreationMode] =
|
|
13930
|
+
const [creationMode, setCreationMode] = useState28({
|
|
13911
13931
|
isActive: false,
|
|
13912
13932
|
sourceNodeData: null
|
|
13913
13933
|
});
|
|
13914
|
-
const [versionMode, setVersionMode] =
|
|
13934
|
+
const [versionMode, setVersionMode] = useState28({
|
|
13915
13935
|
isActive: false,
|
|
13916
13936
|
sourceNodeData: null
|
|
13917
13937
|
});
|
|
13918
|
-
const [questMode, setQuestMode] =
|
|
13919
|
-
const [hasFocusedInitial, setHasFocusedInitial] =
|
|
13920
|
-
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] =
|
|
13921
|
-
const [ancestryMode, setAncestryMode] =
|
|
13938
|
+
const [questMode, setQuestMode] = useState28({ isActive: false });
|
|
13939
|
+
const [hasFocusedInitial, setHasFocusedInitial] = useState28(false);
|
|
13940
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = useState28(false);
|
|
13941
|
+
const [ancestryMode, setAncestryMode] = useState28({
|
|
13922
13942
|
isActive: false,
|
|
13923
13943
|
tree: null,
|
|
13924
13944
|
selectedParentId: null,
|
|
@@ -13929,38 +13949,38 @@ function XViewScene({
|
|
|
13929
13949
|
ancestryDescriptionSections: [],
|
|
13930
13950
|
isAddingNodes: false
|
|
13931
13951
|
});
|
|
13932
|
-
const [readingMode, setReadingMode] =
|
|
13952
|
+
const [readingMode, setReadingMode] = useState28({
|
|
13933
13953
|
isActive: false,
|
|
13934
13954
|
ancestry: null,
|
|
13935
13955
|
branchStack: [],
|
|
13936
13956
|
autoAbstraction: false
|
|
13937
13957
|
});
|
|
13938
|
-
const [formPosition, setFormPosition] =
|
|
13958
|
+
const [formPosition, setFormPosition] = useState28({
|
|
13939
13959
|
left: 16,
|
|
13940
13960
|
top: 16,
|
|
13941
13961
|
opacity: 0
|
|
13942
13962
|
});
|
|
13943
|
-
const [detailsNode, setDetailsNode] =
|
|
13944
|
-
const [detailsLink, setDetailsLink] =
|
|
13945
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] =
|
|
13946
|
-
const [imageViewer, setImageViewer] =
|
|
13963
|
+
const [detailsNode, setDetailsNode] = useState28(null);
|
|
13964
|
+
const [detailsLink, setDetailsLink] = useState28(null);
|
|
13965
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = useState28(null);
|
|
13966
|
+
const [imageViewer, setImageViewer] = useState28({
|
|
13947
13967
|
visible: false,
|
|
13948
13968
|
images: [],
|
|
13949
13969
|
startIndex: 0
|
|
13950
13970
|
});
|
|
13951
|
-
const [editingAncestryRel, setEditingAncestryRel] =
|
|
13971
|
+
const [editingAncestryRel, setEditingAncestryRel] = useState28({
|
|
13952
13972
|
visible: false,
|
|
13953
13973
|
data: null,
|
|
13954
13974
|
path: null
|
|
13955
13975
|
});
|
|
13956
|
-
const [isImportModalOpen, setIsImportModalOpen] =
|
|
13957
|
-
const [importSuccessMessage, setImportSuccessMessage] =
|
|
13958
|
-
const [invalidTargetError, setInvalidTargetError] =
|
|
13959
|
-
const [highlightedNodeId, setHighlightedNodeId] =
|
|
13960
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] =
|
|
13961
|
-
const [ancestryBoardData, setAncestryBoardData] =
|
|
13962
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
13963
|
-
const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] =
|
|
13976
|
+
const [isImportModalOpen, setIsImportModalOpen] = useState28(false);
|
|
13977
|
+
const [importSuccessMessage, setImportSuccessMessage] = useState28("");
|
|
13978
|
+
const [invalidTargetError, setInvalidTargetError] = useState28(null);
|
|
13979
|
+
const [highlightedNodeId, setHighlightedNodeId] = useState28(null);
|
|
13980
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = useState28(false);
|
|
13981
|
+
const [ancestryBoardData, setAncestryBoardData] = useState28([]);
|
|
13982
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState28(false);
|
|
13983
|
+
const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState28(false);
|
|
13964
13984
|
const mountRef = useRef19(null);
|
|
13965
13985
|
const tooltipRef = useRef19(null);
|
|
13966
13986
|
const formRef = useRef19(null);
|
|
@@ -14028,10 +14048,10 @@ function XViewScene({
|
|
|
14028
14048
|
minWidth: 320,
|
|
14029
14049
|
maxWidth: maxReadPanelW
|
|
14030
14050
|
});
|
|
14031
|
-
|
|
14051
|
+
useEffect24(() => {
|
|
14032
14052
|
stateRef.current.ancestry = ancestryMode;
|
|
14033
14053
|
}, [ancestryMode]);
|
|
14034
|
-
|
|
14054
|
+
useEffect24(() => {
|
|
14035
14055
|
var _a2;
|
|
14036
14056
|
if (!isInitialized) return;
|
|
14037
14057
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -14593,7 +14613,7 @@ function XViewScene({
|
|
|
14593
14613
|
}
|
|
14594
14614
|
});
|
|
14595
14615
|
}, []);
|
|
14596
|
-
|
|
14616
|
+
useEffect24(() => {
|
|
14597
14617
|
async function fetchAllData(configPath, ownerId2) {
|
|
14598
14618
|
var _a2, _b2;
|
|
14599
14619
|
if (!get_scene_view_data) {
|
|
@@ -14958,7 +14978,7 @@ function XViewScene({
|
|
|
14958
14978
|
camTween.start();
|
|
14959
14979
|
}
|
|
14960
14980
|
}, [addOrUpdateNodeMesh]);
|
|
14961
|
-
|
|
14981
|
+
useEffect24(() => {
|
|
14962
14982
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
14963
14983
|
const currentMount = mountRef.current;
|
|
14964
14984
|
if (!currentMount) return;
|
|
@@ -15962,7 +15982,7 @@ function XViewScene({
|
|
|
15962
15982
|
};
|
|
15963
15983
|
});
|
|
15964
15984
|
}, []);
|
|
15965
|
-
const actionHandlerContext =
|
|
15985
|
+
const actionHandlerContext = useMemo13(
|
|
15966
15986
|
() => {
|
|
15967
15987
|
var _a2;
|
|
15968
15988
|
return {
|
|
@@ -17071,7 +17091,7 @@ function XViewScene({
|
|
|
17071
17091
|
}
|
|
17072
17092
|
setHighlightedNodeId(nodeId);
|
|
17073
17093
|
}, []);
|
|
17074
|
-
const activeNodeBranches =
|
|
17094
|
+
const activeNodeBranches = useMemo13(() => {
|
|
17075
17095
|
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree)
|
|
17076
17096
|
return null;
|
|
17077
17097
|
const fullTree = buildFullAncestryTree(
|
|
@@ -17115,7 +17135,7 @@ function XViewScene({
|
|
|
17115
17135
|
readingMode.branchStack,
|
|
17116
17136
|
ancestryDataRef.current
|
|
17117
17137
|
]);
|
|
17118
|
-
const backNavigationInfo =
|
|
17138
|
+
const backNavigationInfo = useMemo13(() => {
|
|
17119
17139
|
const { branchStack } = readingMode;
|
|
17120
17140
|
if (!branchStack || branchStack.length === 0) return null;
|
|
17121
17141
|
const lastStep = branchStack[branchStack.length - 1];
|
|
@@ -17126,7 +17146,7 @@ function XViewScene({
|
|
|
17126
17146
|
name: "Voltar para anterior"
|
|
17127
17147
|
};
|
|
17128
17148
|
}, [readingMode.branchStack]);
|
|
17129
|
-
const getReadModeDisplayContext =
|
|
17149
|
+
const getReadModeDisplayContext = useMemo13(() => {
|
|
17130
17150
|
const { ancestry, branchStack } = readingMode;
|
|
17131
17151
|
if (!ancestry) return null;
|
|
17132
17152
|
if (branchStack.length === 0) {
|
|
@@ -17169,7 +17189,7 @@ function XViewScene({
|
|
|
17169
17189
|
customProperties: branchProps
|
|
17170
17190
|
};
|
|
17171
17191
|
}, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
|
|
17172
|
-
const readModeAbstractionTree =
|
|
17192
|
+
const readModeAbstractionTree = useMemo13(() => {
|
|
17173
17193
|
if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
|
|
17174
17194
|
return null;
|
|
17175
17195
|
}
|
|
@@ -17814,7 +17834,7 @@ function XViewScene({
|
|
|
17814
17834
|
},
|
|
17815
17835
|
[sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]
|
|
17816
17836
|
);
|
|
17817
|
-
const existingNodeTypes =
|
|
17837
|
+
const existingNodeTypes = useMemo13(() => {
|
|
17818
17838
|
if (!parentDataRef.current) {
|
|
17819
17839
|
return [];
|
|
17820
17840
|
}
|
|
@@ -17826,7 +17846,7 @@ function XViewScene({
|
|
|
17826
17846
|
).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
|
|
17827
17847
|
return [...new Set(allTypes)];
|
|
17828
17848
|
}, [parentDataRef.current, sceneVersion]);
|
|
17829
|
-
const searchableDbNodes =
|
|
17849
|
+
const searchableDbNodes = useMemo13(() => {
|
|
17830
17850
|
var _a2;
|
|
17831
17851
|
if (!parentDataRef.current) {
|
|
17832
17852
|
return [];
|
|
@@ -17945,13 +17965,13 @@ function XViewScene({
|
|
|
17945
17965
|
console.error("Erro na chamada de save_view_data:", error);
|
|
17946
17966
|
}
|
|
17947
17967
|
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
17948
|
-
const allAvailableNodes =
|
|
17968
|
+
const allAvailableNodes = useMemo13(() => {
|
|
17949
17969
|
if (!parentDataRef.current) return [];
|
|
17950
17970
|
return Object.values(parentDataRef.current).flatMap(
|
|
17951
17971
|
(fileData) => fileData.nodes || []
|
|
17952
17972
|
);
|
|
17953
17973
|
}, [sceneVersion, isInitialized]);
|
|
17954
|
-
const allAvailableAncestries =
|
|
17974
|
+
const allAvailableAncestries = useMemo13(() => {
|
|
17955
17975
|
return ancestryDataRef.current || [];
|
|
17956
17976
|
}, [sceneVersion, isInitialized]);
|
|
17957
17977
|
const handleOpenReference = useCallback4(
|
|
@@ -18015,7 +18035,7 @@ function XViewScene({
|
|
|
18015
18035
|
},
|
|
18016
18036
|
[tweenToTarget]
|
|
18017
18037
|
);
|
|
18018
|
-
const availableDatasets =
|
|
18038
|
+
const availableDatasets = useMemo13(() => {
|
|
18019
18039
|
if (!sceneDataRef.current || !parentDataRef.current) return [];
|
|
18020
18040
|
return sceneDataRef.current.parent_dbs.map((db) => {
|
|
18021
18041
|
var _a2;
|
|
@@ -18029,7 +18049,7 @@ function XViewScene({
|
|
|
18029
18049
|
String(creationMode.sourceNodeData.id)
|
|
18030
18050
|
)) == null ? void 0 : _c.parentFileId : null;
|
|
18031
18051
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
18032
|
-
|
|
18052
|
+
useEffect24(() => {
|
|
18033
18053
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
18034
18054
|
const nodeObjects = stateRef.current.nodeObjects || {};
|
|
18035
18055
|
const targetMesh = nodeObjects[String(focusNodeId)];
|
|
@@ -18052,7 +18072,7 @@ function XViewScene({
|
|
|
18052
18072
|
hasFocusedInitial,
|
|
18053
18073
|
tweenToTarget
|
|
18054
18074
|
]);
|
|
18055
|
-
|
|
18075
|
+
useEffect24(() => {
|
|
18056
18076
|
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
18057
18077
|
const ancestries = ancestryDataRef.current || [];
|
|
18058
18078
|
const targetAncestry = ancestries.find(
|
|
@@ -18077,7 +18097,7 @@ function XViewScene({
|
|
|
18077
18097
|
hasOpenedInitialAncestry,
|
|
18078
18098
|
handleStartReadingAncestry
|
|
18079
18099
|
]);
|
|
18080
|
-
|
|
18100
|
+
useEffect24(() => {
|
|
18081
18101
|
function handleKeyDown(event) {
|
|
18082
18102
|
var _a2, _b2, _c2;
|
|
18083
18103
|
const context = actionHandlerContext;
|
|
@@ -18200,10 +18220,10 @@ function XViewScene({
|
|
|
18200
18220
|
// <-- handleCancelQuest adicionado aqui
|
|
18201
18221
|
]);
|
|
18202
18222
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
18203
|
-
return /* @__PURE__ */
|
|
18223
|
+
return /* @__PURE__ */ React30.createElement(LoadingScreen, null);
|
|
18204
18224
|
}
|
|
18205
18225
|
if (permissionStatus === "denied") {
|
|
18206
|
-
return /* @__PURE__ */
|
|
18226
|
+
return /* @__PURE__ */ React30.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ React30.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ React30.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ React30.createElement(
|
|
18207
18227
|
"svg",
|
|
18208
18228
|
{
|
|
18209
18229
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -18213,7 +18233,7 @@ function XViewScene({
|
|
|
18213
18233
|
stroke: "currentColor",
|
|
18214
18234
|
className: "w-16 h-16 mx-auto"
|
|
18215
18235
|
},
|
|
18216
|
-
/* @__PURE__ */
|
|
18236
|
+
/* @__PURE__ */ React30.createElement(
|
|
18217
18237
|
"path",
|
|
18218
18238
|
{
|
|
18219
18239
|
strokeLinecap: "round",
|
|
@@ -18221,13 +18241,13 @@ function XViewScene({
|
|
|
18221
18241
|
d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
|
|
18222
18242
|
}
|
|
18223
18243
|
)
|
|
18224
|
-
)), /* @__PURE__ */
|
|
18244
|
+
)), /* @__PURE__ */ React30.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ React30.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ React30.createElement(
|
|
18225
18245
|
"button",
|
|
18226
18246
|
{
|
|
18227
18247
|
onClick: () => router.push("/dashboard/scenes"),
|
|
18228
18248
|
className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
|
|
18229
18249
|
},
|
|
18230
|
-
/* @__PURE__ */
|
|
18250
|
+
/* @__PURE__ */ React30.createElement(
|
|
18231
18251
|
"svg",
|
|
18232
18252
|
{
|
|
18233
18253
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -18237,7 +18257,7 @@ function XViewScene({
|
|
|
18237
18257
|
stroke: "currentColor",
|
|
18238
18258
|
className: "w-5 h-5"
|
|
18239
18259
|
},
|
|
18240
|
-
/* @__PURE__ */
|
|
18260
|
+
/* @__PURE__ */ React30.createElement(
|
|
18241
18261
|
"path",
|
|
18242
18262
|
{
|
|
18243
18263
|
strokeLinecap: "round",
|
|
@@ -18249,7 +18269,7 @@ function XViewScene({
|
|
|
18249
18269
|
"Voltar para Scenes"
|
|
18250
18270
|
)));
|
|
18251
18271
|
}
|
|
18252
|
-
return /* @__PURE__ */
|
|
18272
|
+
return /* @__PURE__ */ React30.createElement(
|
|
18253
18273
|
"div",
|
|
18254
18274
|
{
|
|
18255
18275
|
ref: mountRef,
|
|
@@ -18261,7 +18281,7 @@ function XViewScene({
|
|
|
18261
18281
|
cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
|
|
18262
18282
|
}
|
|
18263
18283
|
},
|
|
18264
|
-
userPermissionRole !== "link_viewer" && /* @__PURE__ */
|
|
18284
|
+
userPermissionRole !== "link_viewer" && /* @__PURE__ */ React30.createElement(
|
|
18265
18285
|
XViewSidebar,
|
|
18266
18286
|
{
|
|
18267
18287
|
dbNodes: searchableDbNodes,
|
|
@@ -18285,7 +18305,7 @@ function XViewScene({
|
|
|
18285
18305
|
onOpenMilestoneManager: () => setIsMilestoneManagerOpen(true)
|
|
18286
18306
|
}
|
|
18287
18307
|
),
|
|
18288
|
-
creationMode.isActive && /* @__PURE__ */
|
|
18308
|
+
creationMode.isActive && /* @__PURE__ */ React30.createElement(
|
|
18289
18309
|
InSceneCreationForm,
|
|
18290
18310
|
{
|
|
18291
18311
|
onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
|
|
@@ -18317,7 +18337,7 @@ function XViewScene({
|
|
|
18317
18337
|
availableAncestries: allAvailableAncestries
|
|
18318
18338
|
}
|
|
18319
18339
|
),
|
|
18320
|
-
versionMode.isActive && /* @__PURE__ */
|
|
18340
|
+
versionMode.isActive && /* @__PURE__ */ React30.createElement(
|
|
18321
18341
|
InSceneVersionForm,
|
|
18322
18342
|
{
|
|
18323
18343
|
onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
|
|
@@ -18343,7 +18363,7 @@ function XViewScene({
|
|
|
18343
18363
|
availableAncestries: allAvailableAncestries
|
|
18344
18364
|
}
|
|
18345
18365
|
),
|
|
18346
|
-
questMode.isActive && /* @__PURE__ */
|
|
18366
|
+
questMode.isActive && /* @__PURE__ */ React30.createElement(
|
|
18347
18367
|
InSceneQuestForm,
|
|
18348
18368
|
{
|
|
18349
18369
|
onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
|
|
@@ -18371,7 +18391,7 @@ function XViewScene({
|
|
|
18371
18391
|
onUpdateMilestones: handleUpdateMilestones
|
|
18372
18392
|
}
|
|
18373
18393
|
),
|
|
18374
|
-
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */
|
|
18394
|
+
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React30.createElement(
|
|
18375
18395
|
"div",
|
|
18376
18396
|
{
|
|
18377
18397
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
@@ -18384,7 +18404,7 @@ function XViewScene({
|
|
|
18384
18404
|
maxWidth: "92vw"
|
|
18385
18405
|
}
|
|
18386
18406
|
},
|
|
18387
|
-
/* @__PURE__ */
|
|
18407
|
+
/* @__PURE__ */ React30.createElement(
|
|
18388
18408
|
"div",
|
|
18389
18409
|
{
|
|
18390
18410
|
onPointerDown: (e) => {
|
|
@@ -18395,7 +18415,7 @@ function XViewScene({
|
|
|
18395
18415
|
title: "Arraste para redimensionar"
|
|
18396
18416
|
}
|
|
18397
18417
|
),
|
|
18398
|
-
/* @__PURE__ */
|
|
18418
|
+
/* @__PURE__ */ React30.createElement(
|
|
18399
18419
|
DescriptionReadModePanel,
|
|
18400
18420
|
{
|
|
18401
18421
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
@@ -18430,7 +18450,7 @@ function XViewScene({
|
|
|
18430
18450
|
}
|
|
18431
18451
|
)
|
|
18432
18452
|
),
|
|
18433
|
-
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */
|
|
18453
|
+
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ React30.createElement(
|
|
18434
18454
|
CreateAncestryPanel,
|
|
18435
18455
|
{
|
|
18436
18456
|
ancestryMode,
|
|
@@ -18466,7 +18486,7 @@ function XViewScene({
|
|
|
18466
18486
|
onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
|
|
18467
18487
|
}
|
|
18468
18488
|
),
|
|
18469
|
-
editingAncestryRel.visible && /* @__PURE__ */
|
|
18489
|
+
editingAncestryRel.visible && /* @__PURE__ */ React30.createElement(
|
|
18470
18490
|
AncestryRelationshipPanel,
|
|
18471
18491
|
{
|
|
18472
18492
|
data: editingAncestryRel.data,
|
|
@@ -18480,7 +18500,7 @@ function XViewScene({
|
|
|
18480
18500
|
onUploadFile: upload_file_action
|
|
18481
18501
|
}
|
|
18482
18502
|
),
|
|
18483
|
-
detailsNode && detailsNode.is_quest && /* @__PURE__ */
|
|
18503
|
+
detailsNode && detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
|
|
18484
18504
|
QuestDetailsPanel,
|
|
18485
18505
|
{
|
|
18486
18506
|
node: detailsNode,
|
|
@@ -18506,7 +18526,7 @@ function XViewScene({
|
|
|
18506
18526
|
onUpdateMilestones: handleUpdateMilestones
|
|
18507
18527
|
}
|
|
18508
18528
|
),
|
|
18509
|
-
detailsNode && !detailsNode.is_quest && /* @__PURE__ */
|
|
18529
|
+
detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React30.createElement(
|
|
18510
18530
|
NodeDetailsPanel,
|
|
18511
18531
|
{
|
|
18512
18532
|
node: detailsNode,
|
|
@@ -18538,7 +18558,7 @@ function XViewScene({
|
|
|
18538
18558
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
|
|
18539
18559
|
}
|
|
18540
18560
|
),
|
|
18541
|
-
detailsLink && /* @__PURE__ */
|
|
18561
|
+
detailsLink && /* @__PURE__ */ React30.createElement(
|
|
18542
18562
|
RelationshipDetailsPanel,
|
|
18543
18563
|
{
|
|
18544
18564
|
link: detailsLink,
|
|
@@ -18552,7 +18572,7 @@ function XViewScene({
|
|
|
18552
18572
|
userRole: userPermissionRole
|
|
18553
18573
|
}
|
|
18554
18574
|
),
|
|
18555
|
-
ancestryLinkDetails && /* @__PURE__ */
|
|
18575
|
+
ancestryLinkDetails && /* @__PURE__ */ React30.createElement(
|
|
18556
18576
|
AncestryLinkDetailsPanel,
|
|
18557
18577
|
{
|
|
18558
18578
|
data: ancestryLinkDetails,
|
|
@@ -18563,7 +18583,7 @@ function XViewScene({
|
|
|
18563
18583
|
onUploadFile: upload_file_action
|
|
18564
18584
|
}
|
|
18565
18585
|
),
|
|
18566
|
-
/* @__PURE__ */
|
|
18586
|
+
/* @__PURE__ */ React30.createElement(
|
|
18567
18587
|
"div",
|
|
18568
18588
|
{
|
|
18569
18589
|
ref: tooltipRef,
|
|
@@ -18590,7 +18610,7 @@ function XViewScene({
|
|
|
18590
18610
|
}
|
|
18591
18611
|
}
|
|
18592
18612
|
),
|
|
18593
|
-
/* @__PURE__ */
|
|
18613
|
+
/* @__PURE__ */ React30.createElement(
|
|
18594
18614
|
ContextMenu,
|
|
18595
18615
|
{
|
|
18596
18616
|
data: contextMenu,
|
|
@@ -18623,7 +18643,7 @@ function XViewScene({
|
|
|
18623
18643
|
onFinishQuest: handleFinishQuestQuick
|
|
18624
18644
|
}
|
|
18625
18645
|
),
|
|
18626
|
-
/* @__PURE__ */
|
|
18646
|
+
/* @__PURE__ */ React30.createElement(
|
|
18627
18647
|
MultiNodeContextMenu,
|
|
18628
18648
|
{
|
|
18629
18649
|
data: multiContextMenu,
|
|
@@ -18643,7 +18663,7 @@ function XViewScene({
|
|
|
18643
18663
|
)
|
|
18644
18664
|
}
|
|
18645
18665
|
),
|
|
18646
|
-
/* @__PURE__ */
|
|
18666
|
+
/* @__PURE__ */ React30.createElement(
|
|
18647
18667
|
RelationshipContextMenu,
|
|
18648
18668
|
{
|
|
18649
18669
|
data: relationshipMenu,
|
|
@@ -18661,14 +18681,14 @@ function XViewScene({
|
|
|
18661
18681
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
18662
18682
|
}
|
|
18663
18683
|
),
|
|
18664
|
-
/* @__PURE__ */
|
|
18684
|
+
/* @__PURE__ */ React30.createElement(
|
|
18665
18685
|
ImageViewer,
|
|
18666
18686
|
{
|
|
18667
18687
|
data: imageViewer,
|
|
18668
18688
|
onClose: () => setImageViewer({ ...imageViewer, visible: false })
|
|
18669
18689
|
}
|
|
18670
18690
|
),
|
|
18671
|
-
/* @__PURE__ */
|
|
18691
|
+
/* @__PURE__ */ React30.createElement(
|
|
18672
18692
|
AncestryBoard,
|
|
18673
18693
|
{
|
|
18674
18694
|
isOpen: isAncestryBoardOpen,
|
|
@@ -18681,7 +18701,7 @@ function XViewScene({
|
|
|
18681
18701
|
userRole: userPermissionRole
|
|
18682
18702
|
}
|
|
18683
18703
|
),
|
|
18684
|
-
/* @__PURE__ */
|
|
18704
|
+
/* @__PURE__ */ React30.createElement(
|
|
18685
18705
|
MilestoneManager,
|
|
18686
18706
|
{
|
|
18687
18707
|
isOpen: isMilestoneManagerOpen,
|
|
@@ -18690,7 +18710,7 @@ function XViewScene({
|
|
|
18690
18710
|
onUpdateMilestones: handleUpdateMilestones
|
|
18691
18711
|
}
|
|
18692
18712
|
),
|
|
18693
|
-
/* @__PURE__ */
|
|
18713
|
+
/* @__PURE__ */ React30.createElement(
|
|
18694
18714
|
ImportParentFileModal,
|
|
18695
18715
|
{
|
|
18696
18716
|
isOpen: isImportModalOpen,
|
|
@@ -18703,7 +18723,7 @@ function XViewScene({
|
|
|
18703
18723
|
currentAncestries: ancestryDataRef.current || []
|
|
18704
18724
|
}
|
|
18705
18725
|
),
|
|
18706
|
-
invalidTargetError && /* @__PURE__ */
|
|
18726
|
+
invalidTargetError && /* @__PURE__ */ React30.createElement(
|
|
18707
18727
|
"div",
|
|
18708
18728
|
{
|
|
18709
18729
|
className: "ui-overlay",
|
|
@@ -18728,13 +18748,13 @@ function XViewScene({
|
|
|
18728
18748
|
animation: "fadeInDown 0.5s cubic-bezier(0.16, 1, 0.3, 1)"
|
|
18729
18749
|
}
|
|
18730
18750
|
},
|
|
18731
|
-
/* @__PURE__ */
|
|
18751
|
+
/* @__PURE__ */ React30.createElement("style", null, `
|
|
18732
18752
|
@keyframes fadeInDown {
|
|
18733
18753
|
from { opacity: 0; transform: translate(-50%, -20px); }
|
|
18734
18754
|
to { opacity: 1; transform: translate(-50%, 0); }
|
|
18735
18755
|
}
|
|
18736
18756
|
`),
|
|
18737
|
-
/* @__PURE__ */
|
|
18757
|
+
/* @__PURE__ */ React30.createElement(
|
|
18738
18758
|
"svg",
|
|
18739
18759
|
{
|
|
18740
18760
|
width: "20",
|
|
@@ -18746,12 +18766,12 @@ function XViewScene({
|
|
|
18746
18766
|
strokeLinecap: "round",
|
|
18747
18767
|
strokeLinejoin: "round"
|
|
18748
18768
|
},
|
|
18749
|
-
/* @__PURE__ */
|
|
18750
|
-
/* @__PURE__ */
|
|
18751
|
-
/* @__PURE__ */
|
|
18769
|
+
/* @__PURE__ */ React30.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
18770
|
+
/* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
18771
|
+
/* @__PURE__ */ React30.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
18752
18772
|
),
|
|
18753
|
-
/* @__PURE__ */
|
|
18754
|
-
/* @__PURE__ */
|
|
18773
|
+
/* @__PURE__ */ React30.createElement("span", { style: { fontSize: "14px", fontWeight: 500 } }, invalidTargetError),
|
|
18774
|
+
/* @__PURE__ */ React30.createElement(
|
|
18755
18775
|
"button",
|
|
18756
18776
|
{
|
|
18757
18777
|
onClick: () => setInvalidTargetError(null),
|
|
@@ -18781,450 +18801,6 @@ function XViewScene({
|
|
|
18781
18801
|
)
|
|
18782
18802
|
);
|
|
18783
18803
|
}
|
|
18784
|
-
|
|
18785
|
-
// src/x_view_server_logic.js
|
|
18786
|
-
async function save_view_data_logic(db_services, filename, data) {
|
|
18787
|
-
try {
|
|
18788
|
-
const saveResult = await db_services.save_file(filename, data);
|
|
18789
|
-
return saveResult;
|
|
18790
|
-
} catch (error) {
|
|
18791
|
-
console.error("catch (error) em save_view_data_logic:", error);
|
|
18792
|
-
return { success: false, error: error.message };
|
|
18793
|
-
}
|
|
18794
|
-
}
|
|
18795
|
-
async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
|
|
18796
|
-
var _a, _b;
|
|
18797
|
-
try {
|
|
18798
|
-
if (!session || !session.user) {
|
|
18799
|
-
return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
|
|
18800
|
-
}
|
|
18801
|
-
const membershipCheck = await db_services.check_membership(owner_id, type, scene_config, session.user.id);
|
|
18802
|
-
const isFullMember = membershipCheck.success && membershipCheck.isValidMember;
|
|
18803
|
-
if (!isFullMember && !focusNodeId && !focusAncestryId) {
|
|
18804
|
-
return { success: false, error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio." };
|
|
18805
|
-
}
|
|
18806
|
-
const sceneResponse = await db_services.get_file(`x_view_scenes/${owner_id}/${scene_config}`);
|
|
18807
|
-
if (!sceneResponse || !sceneResponse.success) {
|
|
18808
|
-
console.error("Falha ao buscar dados da cena:", sceneResponse == null ? void 0 : sceneResponse.error);
|
|
18809
|
-
return { success: false, error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}` };
|
|
18810
|
-
}
|
|
18811
|
-
const sceneData = sceneResponse.data;
|
|
18812
|
-
const parentDbObjects = sceneData.parent_dbs || [];
|
|
18813
|
-
if (type && type.toLowerCase().includes("database")) {
|
|
18814
|
-
const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
|
|
18815
|
-
if (!selfExists) {
|
|
18816
|
-
parentDbObjects.push({ db_id: scene_config, owner_id });
|
|
18817
|
-
}
|
|
18818
|
-
}
|
|
18819
|
-
const parentResponsesPromises = parentDbObjects.map(
|
|
18820
|
-
(db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
|
|
18821
|
-
);
|
|
18822
|
-
const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
|
|
18823
|
-
const parentData = {};
|
|
18824
|
-
for (let i = 0; i < parentResponsesResults.length; i++) {
|
|
18825
|
-
const result = parentResponsesResults[i];
|
|
18826
|
-
const db_info = parentDbObjects[i];
|
|
18827
|
-
if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
|
|
18828
|
-
parentData[db_info.db_id] = result.value.data;
|
|
18829
|
-
} else {
|
|
18830
|
-
console.warn(
|
|
18831
|
-
`Arquivo pai n\xE3o carregado: ${db_info.db_id}. Pode ter sido deletado.`,
|
|
18832
|
-
result.status === "rejected" ? result.reason : (_b = result.value) == null ? void 0 : _b.error
|
|
18833
|
-
);
|
|
18834
|
-
}
|
|
18835
|
-
}
|
|
18836
|
-
if (type && type.toLowerCase() === "view") {
|
|
18837
|
-
parentData[scene_config] = {
|
|
18838
|
-
dataset_name: "Quests Internas (View)",
|
|
18839
|
-
nodes: sceneData.quest_nodes || [],
|
|
18840
|
-
links: sceneData.quest_links || []
|
|
18841
|
-
};
|
|
18842
|
-
}
|
|
18843
|
-
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
18844
|
-
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
18845
|
-
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
18846
|
-
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
18847
|
-
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
18848
|
-
var _a2, _b2;
|
|
18849
|
-
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
18850
|
-
if (nodeTypes.includes("quest")) {
|
|
18851
|
-
const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
|
|
18852
|
-
if (dbQuestNode) {
|
|
18853
|
-
return { ...sceneNode, ...dbQuestNode };
|
|
18854
|
-
}
|
|
18855
|
-
return sceneNode;
|
|
18856
|
-
}
|
|
18857
|
-
const dbNode = parentNodeMap.get(String(sceneNode.id));
|
|
18858
|
-
if (dbNode) {
|
|
18859
|
-
return { ...sceneNode, ...dbNode };
|
|
18860
|
-
}
|
|
18861
|
-
return null;
|
|
18862
|
-
}).filter(Boolean);
|
|
18863
|
-
const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
|
|
18864
|
-
const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
|
|
18865
|
-
const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
|
|
18866
|
-
const nodesAreValidForScene = validNodeIdsInScene.has(String(sceneLink.source)) && validNodeIdsInScene.has(String(sceneLink.target));
|
|
18867
|
-
return linkExistsInParent && nodesAreValidForScene;
|
|
18868
|
-
}).map((sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`));
|
|
18869
|
-
const validatedSceneData = {
|
|
18870
|
-
...sceneData,
|
|
18871
|
-
nodes: validatedNodes,
|
|
18872
|
-
links: validatedLinks
|
|
18873
|
-
};
|
|
18874
|
-
const ancestryFilePaths = [];
|
|
18875
|
-
ancestryFilePaths.push({
|
|
18876
|
-
path: `x_view_ancestry/${owner_id}/${scene_config}`,
|
|
18877
|
-
source_id: scene_config,
|
|
18878
|
-
owner_id,
|
|
18879
|
-
isSceneFile: true
|
|
18880
|
-
});
|
|
18881
|
-
parentDbObjects.forEach((db_info) => {
|
|
18882
|
-
ancestryFilePaths.push({
|
|
18883
|
-
path: `x_view_ancestry/${db_info.owner_id}/${db_info.db_id}`,
|
|
18884
|
-
source_id: db_info.db_id,
|
|
18885
|
-
owner_id: db_info.owner_id,
|
|
18886
|
-
isSceneFile: false
|
|
18887
|
-
});
|
|
18888
|
-
});
|
|
18889
|
-
const ancestryPromises = ancestryFilePaths.map((file) => db_services.get_file(file.path));
|
|
18890
|
-
const ancestryResults = await Promise.allSettled(ancestryPromises);
|
|
18891
|
-
const ancestriesFromSceneFile = [];
|
|
18892
|
-
const ancestriesFromDbFiles = [];
|
|
18893
|
-
ancestryResults.forEach((result, index) => {
|
|
18894
|
-
var _a2;
|
|
18895
|
-
const fileInfo = ancestryFilePaths[index];
|
|
18896
|
-
if (result.status === "fulfilled" && ((_a2 = result.value) == null ? void 0 : _a2.success) && Array.isArray(result.value.data)) {
|
|
18897
|
-
const ancestriesFromFile = result.value.data.map((ancestry) => {
|
|
18898
|
-
const existingSource = ancestry._source_file_id;
|
|
18899
|
-
const existingOwner = ancestry._source_owner_id;
|
|
18900
|
-
const isImportedItem = existingSource && existingSource !== fileInfo.source_id;
|
|
18901
|
-
return {
|
|
18902
|
-
...ancestry,
|
|
18903
|
-
_source_file_id: isImportedItem ? existingSource : fileInfo.source_id,
|
|
18904
|
-
_source_owner_id: isImportedItem ? existingOwner : fileInfo.owner_id
|
|
18905
|
-
};
|
|
18906
|
-
});
|
|
18907
|
-
if (fileInfo.isSceneFile) {
|
|
18908
|
-
ancestriesFromSceneFile.push(...ancestriesFromFile);
|
|
18909
|
-
} else {
|
|
18910
|
-
ancestriesFromDbFiles.push(...ancestriesFromFile);
|
|
18911
|
-
}
|
|
18912
|
-
}
|
|
18913
|
-
});
|
|
18914
|
-
const ancestryMap = /* @__PURE__ */ new Map();
|
|
18915
|
-
ancestriesFromDbFiles.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
|
|
18916
|
-
ancestriesFromSceneFile.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
|
|
18917
|
-
let ancestryData = Array.from(ancestryMap.values());
|
|
18918
|
-
const externalSourcesToRefresh = /* @__PURE__ */ new Map();
|
|
18919
|
-
ancestryData.forEach((anc) => {
|
|
18920
|
-
const targetSourceId = anc._source_file_id || anc._imported_from_view_id;
|
|
18921
|
-
const targetOwnerId = anc._source_owner_id || anc._imported_from_view_owner_id;
|
|
18922
|
-
if (targetSourceId && targetSourceId !== scene_config && targetOwnerId) {
|
|
18923
|
-
const isAlreadyLoadedAsParent = parentDbObjects.some((db) => String(db.db_id) === String(targetSourceId));
|
|
18924
|
-
if (!isAlreadyLoadedAsParent) {
|
|
18925
|
-
const key = `${targetOwnerId}/${targetSourceId}`;
|
|
18926
|
-
externalSourcesToRefresh.set(key, {
|
|
18927
|
-
owner_id: targetOwnerId,
|
|
18928
|
-
source_id: targetSourceId,
|
|
18929
|
-
key
|
|
18930
|
-
});
|
|
18931
|
-
}
|
|
18932
|
-
}
|
|
18933
|
-
});
|
|
18934
|
-
const successfullyFetchedSources = /* @__PURE__ */ new Set();
|
|
18935
|
-
const failedSources = /* @__PURE__ */ new Set();
|
|
18936
|
-
if (externalSourcesToRefresh.size > 0) {
|
|
18937
|
-
const refreshPromises = Array.from(externalSourcesToRefresh.values()).map(
|
|
18938
|
-
(src) => db_services.get_file(`x_view_ancestry/${src.owner_id}/${src.source_id}`).then((res) => ({ ...res, _meta_key: src.key }))
|
|
18939
|
-
);
|
|
18940
|
-
const refreshResults = await Promise.allSettled(refreshPromises);
|
|
18941
|
-
const freshAncestryMap = /* @__PURE__ */ new Map();
|
|
18942
|
-
refreshResults.forEach((result) => {
|
|
18943
|
-
var _a2, _b2;
|
|
18944
|
-
if (result.status === "fulfilled" && ((_a2 = result.value) == null ? void 0 : _a2.success) && Array.isArray(result.value.data)) {
|
|
18945
|
-
successfullyFetchedSources.add(result.value._meta_key);
|
|
18946
|
-
result.value.data.forEach((freshAnc) => {
|
|
18947
|
-
if (!freshAnc.is_private) {
|
|
18948
|
-
freshAncestryMap.set(String(freshAnc.ancestry_id), freshAnc);
|
|
18949
|
-
}
|
|
18950
|
-
});
|
|
18951
|
-
} else if (result.status === "fulfilled" && !((_b2 = result.value) == null ? void 0 : _b2.success)) {
|
|
18952
|
-
failedSources.add(result.value._meta_key);
|
|
18953
|
-
}
|
|
18954
|
-
});
|
|
18955
|
-
ancestryData = ancestryData.filter((localAnc) => {
|
|
18956
|
-
const targetSourceId = localAnc._source_file_id || localAnc._imported_from_view_id;
|
|
18957
|
-
const targetOwnerId = localAnc._source_owner_id || localAnc._imported_from_view_owner_id;
|
|
18958
|
-
if (!targetSourceId || targetSourceId === scene_config) return true;
|
|
18959
|
-
const key = `${targetOwnerId}/${targetSourceId}`;
|
|
18960
|
-
if (failedSources.has(key)) {
|
|
18961
|
-
return false;
|
|
18962
|
-
}
|
|
18963
|
-
if (externalSourcesToRefresh.has(key) && successfullyFetchedSources.has(key)) {
|
|
18964
|
-
const stillExists = freshAncestryMap.has(String(localAnc.ancestry_id));
|
|
18965
|
-
return stillExists;
|
|
18966
|
-
}
|
|
18967
|
-
return true;
|
|
18968
|
-
}).map((localAnc) => {
|
|
18969
|
-
const freshVersion = freshAncestryMap.get(String(localAnc.ancestry_id));
|
|
18970
|
-
if (freshVersion) {
|
|
18971
|
-
return {
|
|
18972
|
-
...freshVersion,
|
|
18973
|
-
_imported_from_view_id: localAnc._imported_from_view_id,
|
|
18974
|
-
_imported_from_view_owner_id: localAnc._imported_from_view_owner_id,
|
|
18975
|
-
_origin_db_ids: localAnc._origin_db_ids,
|
|
18976
|
-
_source_file_id: localAnc._source_file_id,
|
|
18977
|
-
_source_owner_id: localAnc._source_owner_id
|
|
18978
|
-
};
|
|
18979
|
-
}
|
|
18980
|
-
return localAnc;
|
|
18981
|
-
});
|
|
18982
|
-
}
|
|
18983
|
-
const ancestryFilePath = `x_view_ancestry/${owner_id}/${scene_config}`;
|
|
18984
|
-
const parentNodeIds = new Set(allNodes.map((node) => String(node.id)));
|
|
18985
|
-
const pruneTree = (node) => {
|
|
18986
|
-
if (!node) return null;
|
|
18987
|
-
if (node.is_section) {
|
|
18988
|
-
const validChildren2 = (node.children || []).map((child) => pruneTree(child)).filter(Boolean);
|
|
18989
|
-
return { ...node, children: validChildren2 };
|
|
18990
|
-
}
|
|
18991
|
-
if (!parentNodeIds.has(String(node.node_id))) {
|
|
18992
|
-
return null;
|
|
18993
|
-
}
|
|
18994
|
-
const validChildren = (node.children || []).map((child) => pruneTree(child)).filter(Boolean);
|
|
18995
|
-
let validBranches = [];
|
|
18996
|
-
if (node.parallel_branches) {
|
|
18997
|
-
validBranches = node.parallel_branches.map((branch) => ({
|
|
18998
|
-
...branch,
|
|
18999
|
-
tree: pruneTree(branch.tree)
|
|
19000
|
-
})).filter((b) => b.tree !== null);
|
|
19001
|
-
}
|
|
19002
|
-
return {
|
|
19003
|
-
...node,
|
|
19004
|
-
children: validChildren,
|
|
19005
|
-
parallel_branches: validBranches
|
|
19006
|
-
};
|
|
19007
|
-
};
|
|
19008
|
-
const originalAncestryDataString = JSON.stringify(Array.from(ancestryMap.values()));
|
|
19009
|
-
const cleanedAncestryData = ancestryData.map((ancestry) => {
|
|
19010
|
-
if (!parentNodeIds.has(String(ancestry.ancestral_node))) return null;
|
|
19011
|
-
const cleanedTree = pruneTree(ancestry.tree);
|
|
19012
|
-
if (!cleanedTree) return null;
|
|
19013
|
-
let cleanedAbstraction = null;
|
|
19014
|
-
if (ancestry.abstraction_tree) {
|
|
19015
|
-
cleanedAbstraction = pruneTree(ancestry.abstraction_tree);
|
|
19016
|
-
}
|
|
19017
|
-
return {
|
|
19018
|
-
...ancestry,
|
|
19019
|
-
tree: cleanedTree,
|
|
19020
|
-
abstraction_tree: cleanedAbstraction
|
|
19021
|
-
};
|
|
19022
|
-
}).filter(Boolean);
|
|
19023
|
-
if (JSON.stringify(cleanedAncestryData) !== originalAncestryDataString) {
|
|
19024
|
-
ancestryData = cleanedAncestryData;
|
|
19025
|
-
try {
|
|
19026
|
-
await db_services.save_file(ancestryFilePath, ancestryData);
|
|
19027
|
-
} catch (saveError) {
|
|
19028
|
-
console.error("Falha ao salvar o arquivo de ancestralidade da cena atualizado:", saveError);
|
|
19029
|
-
}
|
|
19030
|
-
}
|
|
19031
|
-
if (!isFullMember) {
|
|
19032
|
-
const requiredNodeIds = /* @__PURE__ */ new Set();
|
|
19033
|
-
const requiredAncestryIds = /* @__PURE__ */ new Set();
|
|
19034
|
-
if (focusNodeId) requiredNodeIds.add(String(focusNodeId));
|
|
19035
|
-
if (focusAncestryId) requiredAncestryIds.add(String(focusAncestryId));
|
|
19036
|
-
const allNodesFromDb = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
19037
|
-
const extractDependenciesFromText = (text) => {
|
|
19038
|
-
if (!text) return;
|
|
19039
|
-
const mentionRegex = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
|
|
19040
|
-
const refRegex = /\[\[REF:(node|ancestry):([a-zA-Z0-9\-_]+):([a-zA-Z0-9\-_]+)\]\]/g;
|
|
19041
|
-
let match;
|
|
19042
|
-
while ((match = mentionRegex.exec(text)) !== null) {
|
|
19043
|
-
requiredNodeIds.add(match[1]);
|
|
19044
|
-
}
|
|
19045
|
-
while ((match = refRegex.exec(text)) !== null) {
|
|
19046
|
-
if (match[1] === "node") requiredNodeIds.add(match[2]);
|
|
19047
|
-
if (match[1] === "ancestry") requiredAncestryIds.add(match[2]);
|
|
19048
|
-
}
|
|
19049
|
-
};
|
|
19050
|
-
const extractTreeDependencies = (treeItem) => {
|
|
19051
|
-
var _a2;
|
|
19052
|
-
if (!treeItem) return;
|
|
19053
|
-
if (treeItem.node_id) requiredNodeIds.add(String(treeItem.node_id));
|
|
19054
|
-
if ((_a2 = treeItem.node) == null ? void 0 : _a2.id) requiredNodeIds.add(String(treeItem.node.id));
|
|
19055
|
-
if (treeItem.children) {
|
|
19056
|
-
treeItem.children.forEach(extractTreeDependencies);
|
|
19057
|
-
}
|
|
19058
|
-
if (treeItem.parallel_branches) {
|
|
19059
|
-
treeItem.parallel_branches.forEach((branch) => {
|
|
19060
|
-
if (branch.linked_ancestry_id) {
|
|
19061
|
-
requiredAncestryIds.add(String(branch.linked_ancestry_id));
|
|
19062
|
-
}
|
|
19063
|
-
if (branch.description) extractDependenciesFromText(branch.description);
|
|
19064
|
-
if (branch.description_sections) {
|
|
19065
|
-
branch.description_sections.forEach((s) => extractDependenciesFromText(s.content));
|
|
19066
|
-
}
|
|
19067
|
-
extractTreeDependencies(branch.tree);
|
|
19068
|
-
});
|
|
19069
|
-
}
|
|
19070
|
-
};
|
|
19071
|
-
let previousSize;
|
|
19072
|
-
do {
|
|
19073
|
-
previousSize = requiredNodeIds.size + requiredAncestryIds.size;
|
|
19074
|
-
requiredAncestryIds.forEach((ancId) => {
|
|
19075
|
-
const anc = ancestryData.find((a) => String(a.ancestry_id) === ancId);
|
|
19076
|
-
if (anc && !anc.is_private) {
|
|
19077
|
-
if (anc.description) extractDependenciesFromText(anc.description);
|
|
19078
|
-
if (anc.description_sections) {
|
|
19079
|
-
anc.description_sections.forEach((s) => extractDependenciesFromText(s.content));
|
|
19080
|
-
}
|
|
19081
|
-
extractTreeDependencies(anc.tree);
|
|
19082
|
-
extractTreeDependencies(anc.abstraction_tree);
|
|
19083
|
-
}
|
|
19084
|
-
});
|
|
19085
|
-
requiredNodeIds.forEach((nodeId) => {
|
|
19086
|
-
const node = allNodesFromDb.find((n) => String(n.id) === nodeId);
|
|
19087
|
-
if (node) {
|
|
19088
|
-
if (node.description) extractDependenciesFromText(node.description);
|
|
19089
|
-
if (node.description_sections) {
|
|
19090
|
-
node.description_sections.forEach((s) => extractDependenciesFromText(s.content));
|
|
19091
|
-
}
|
|
19092
|
-
}
|
|
19093
|
-
});
|
|
19094
|
-
} while (requiredNodeIds.size + requiredAncestryIds.size > previousSize);
|
|
19095
|
-
const restrictedSceneData = { ...validatedSceneData, nodes: [], links: [] };
|
|
19096
|
-
const restrictedParentData = {};
|
|
19097
|
-
const restrictedAncestryData = ancestryData.filter((a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private);
|
|
19098
|
-
for (const [dbId, dbContent] of Object.entries(parentData)) {
|
|
19099
|
-
const filteredNodes = (dbContent.nodes || []).filter((n) => requiredNodeIds.has(String(n.id)));
|
|
19100
|
-
if (filteredNodes.length > 0) {
|
|
19101
|
-
restrictedParentData[dbId] = { ...dbContent, nodes: filteredNodes, links: [] };
|
|
19102
|
-
}
|
|
19103
|
-
}
|
|
19104
|
-
if (focusNodeId) {
|
|
19105
|
-
const mainNode = allNodesFromDb.find((n) => String(n.id) === String(focusNodeId));
|
|
19106
|
-
if (mainNode) {
|
|
19107
|
-
restrictedSceneData.nodes = [mainNode];
|
|
19108
|
-
}
|
|
19109
|
-
}
|
|
19110
|
-
return {
|
|
19111
|
-
success: true,
|
|
19112
|
-
data: {
|
|
19113
|
-
scene: restrictedSceneData,
|
|
19114
|
-
parent: restrictedParentData,
|
|
19115
|
-
ancestry: restrictedAncestryData
|
|
19116
|
-
}
|
|
19117
|
-
};
|
|
19118
|
-
}
|
|
19119
|
-
return {
|
|
19120
|
-
success: true,
|
|
19121
|
-
data: { scene: validatedSceneData, parent: parentData, ancestry: ancestryData }
|
|
19122
|
-
};
|
|
19123
|
-
} catch (error) {
|
|
19124
|
-
console.error("Erro em get_scene_view_data_logic:", error);
|
|
19125
|
-
return { success: false, error: error.message };
|
|
19126
|
-
}
|
|
19127
|
-
}
|
|
19128
|
-
async function import_parent_file_modal_get_logic(db_services, session) {
|
|
19129
|
-
try {
|
|
19130
|
-
const call_firestore_get_x_view_data = await db_services.get_firestore_data(session);
|
|
19131
|
-
const x_view_databases = call_firestore_get_x_view_data.data.sub_collections.x_view_databases || [];
|
|
19132
|
-
const x_views = call_firestore_get_x_view_data.data.sub_collections.x_views || [];
|
|
19133
|
-
return {
|
|
19134
|
-
success: true,
|
|
19135
|
-
data: {
|
|
19136
|
-
databases: x_view_databases,
|
|
19137
|
-
views: x_views
|
|
19138
|
-
}
|
|
19139
|
-
};
|
|
19140
|
-
} catch (error) {
|
|
19141
|
-
console.error("catch (error) em import_parent_file_modal_get_logic:", error);
|
|
19142
|
-
return { success: false, error: error.message };
|
|
19143
|
-
}
|
|
19144
|
-
}
|
|
19145
|
-
async function get_single_parent_file_logic(db_services, file_id, session) {
|
|
19146
|
-
try {
|
|
19147
|
-
const call_GCP_cloud_storage_get_file = await db_services.get_file(`x_view_dbs/${session.user.id}/${file_id}`);
|
|
19148
|
-
return call_GCP_cloud_storage_get_file;
|
|
19149
|
-
} catch (error) {
|
|
19150
|
-
console.error("catch (error) em get_single_parent_file_logic:", error);
|
|
19151
|
-
return { success: false, error: error.message };
|
|
19152
|
-
}
|
|
19153
|
-
}
|
|
19154
|
-
async function x_view_add_new_parent_file_to_scene_at_firebase(file_id, session, new_parent, db_services) {
|
|
19155
|
-
try {
|
|
19156
|
-
const update_data = {
|
|
19157
|
-
scene_id: file_id,
|
|
19158
|
-
new_parent,
|
|
19159
|
-
session
|
|
19160
|
-
};
|
|
19161
|
-
const call_firestore_add_new_parent_file_to_scene_at_firebase = await db_services.add_new_parent_file_to_scene_at_firebase(update_data);
|
|
19162
|
-
return call_firestore_add_new_parent_file_to_scene_at_firebase;
|
|
19163
|
-
} catch (error) {
|
|
19164
|
-
console.error("catch (error) em get_single_parent_file_logic:", error);
|
|
19165
|
-
return { success: false, error: error.message };
|
|
19166
|
-
}
|
|
19167
|
-
}
|
|
19168
|
-
async function get_ancestry_file_logic(db_services, file_id, owner_id) {
|
|
19169
|
-
try {
|
|
19170
|
-
const path = `x_view_ancestry/${owner_id}/${file_id}`;
|
|
19171
|
-
const call_GCP_cloud_storage_get_file = await db_services.get_file(path);
|
|
19172
|
-
return call_GCP_cloud_storage_get_file;
|
|
19173
|
-
} catch (error) {
|
|
19174
|
-
console.error("catch (error) em get_ancestry_file_logic:", error);
|
|
19175
|
-
return { success: false, error: error.message };
|
|
19176
|
-
}
|
|
19177
|
-
}
|
|
19178
|
-
async function save_ancestry_board_logic(db_services, scene_id, type, groups, session, owner_id) {
|
|
19179
|
-
try {
|
|
19180
|
-
const targetOwnerId = owner_id || session.user.id;
|
|
19181
|
-
return await db_services.save_ancestry_board(session, scene_id, type, groups, targetOwnerId);
|
|
19182
|
-
} catch (error) {
|
|
19183
|
-
console.error("Erro em save_ancestry_board_logic:", error);
|
|
19184
|
-
return { success: false, error: error.message };
|
|
19185
|
-
}
|
|
19186
|
-
}
|
|
19187
|
-
async function get_ancestry_board_logic(db_services, scene_id, type, session, owner_id) {
|
|
19188
|
-
try {
|
|
19189
|
-
const targetOwnerId = owner_id || session.user.id;
|
|
19190
|
-
return await db_services.get_ancestry_board(session, scene_id, type, targetOwnerId);
|
|
19191
|
-
} catch (error) {
|
|
19192
|
-
console.error("Erro em get_ancestry_board_logic:", error);
|
|
19193
|
-
return { success: false, error: error.message };
|
|
19194
|
-
}
|
|
19195
|
-
}
|
|
19196
|
-
async function delete_uploaded_file_logic(db_services, fileUrl) {
|
|
19197
|
-
try {
|
|
19198
|
-
if (db_services.delete_public_file) {
|
|
19199
|
-
return await db_services.delete_public_file(fileUrl);
|
|
19200
|
-
}
|
|
19201
|
-
return { success: false, error: "Servi\xE7o de dele\xE7\xE3o n\xE3o configurado." };
|
|
19202
|
-
} catch (error) {
|
|
19203
|
-
console.error("Erro em delete_uploaded_file_logic:", error);
|
|
19204
|
-
return { success: false, error: error.message };
|
|
19205
|
-
}
|
|
19206
|
-
}
|
|
19207
|
-
async function get_view_members_logic(db_services, ownerId, type, itemId) {
|
|
19208
|
-
try {
|
|
19209
|
-
if (!db_services.get_view_members) {
|
|
19210
|
-
return { success: false, error: "Servi\xE7o de busca de membros n\xE3o configurado." };
|
|
19211
|
-
}
|
|
19212
|
-
return await db_services.get_view_members(ownerId, type, itemId);
|
|
19213
|
-
} catch (error) {
|
|
19214
|
-
console.error("Erro em get_view_members_logic:", error);
|
|
19215
|
-
return { success: false, error: error.message };
|
|
19216
|
-
}
|
|
19217
|
-
}
|
|
19218
18804
|
export {
|
|
19219
|
-
XViewScene
|
|
19220
|
-
delete_uploaded_file_logic,
|
|
19221
|
-
get_ancestry_board_logic,
|
|
19222
|
-
get_ancestry_file_logic,
|
|
19223
|
-
get_scene_view_data_logic,
|
|
19224
|
-
get_single_parent_file_logic,
|
|
19225
|
-
get_view_members_logic,
|
|
19226
|
-
import_parent_file_modal_get_logic,
|
|
19227
|
-
save_ancestry_board_logic,
|
|
19228
|
-
save_view_data_logic,
|
|
19229
|
-
x_view_add_new_parent_file_to_scene_at_firebase
|
|
18805
|
+
XViewScene
|
|
19230
18806
|
};
|