@lv-x-software-house/x_view 1.2.4-dev.1 → 1.2.4-dev.11
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 +824 -373
- package/dist/index.mjs +744 -293
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,9 +43,9 @@ __export(index_exports, {
|
|
|
43
43
|
module.exports = __toCommonJS(index_exports);
|
|
44
44
|
|
|
45
45
|
// src/XViewScene.jsx
|
|
46
|
-
var
|
|
46
|
+
var import_react25 = __toESM(require("react"));
|
|
47
47
|
var import_navigation = require("next/navigation");
|
|
48
|
-
var
|
|
48
|
+
var import_react26 = require("next-auth/react");
|
|
49
49
|
var import_crypto_js = __toESM(require("crypto-js"));
|
|
50
50
|
var THREE3 = __toESM(require("three"));
|
|
51
51
|
var import_OrbitControls = require("three/examples/jsm/controls/OrbitControls.js");
|
|
@@ -948,7 +948,7 @@ var createNodeMesh = (nodeData, position, glowTexture) => {
|
|
|
948
948
|
if (useImage && nodeData.textureImageUrl) {
|
|
949
949
|
geometry = new THREE.CircleGeometry(1.5, 48);
|
|
950
950
|
const texture = getTexture(nodeData.textureImageUrl);
|
|
951
|
-
material = new
|
|
951
|
+
material = new MeshBasicMaterial({
|
|
952
952
|
map: texture,
|
|
953
953
|
color: 16777215,
|
|
954
954
|
side: THREE.DoubleSide,
|
|
@@ -1559,7 +1559,7 @@ var addStandaloneNodeToScene = (state, nodeData, position) => {
|
|
|
1559
1559
|
scaleTween.start();
|
|
1560
1560
|
}
|
|
1561
1561
|
};
|
|
1562
|
-
var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
|
|
1562
|
+
var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId = null, sceneOwnerId = null) => {
|
|
1563
1563
|
const parentDbsArray = (sceneData == null ? void 0 : sceneData.parent_dbs) || [];
|
|
1564
1564
|
for (const parentFileId in allParentData) {
|
|
1565
1565
|
if (allParentData.hasOwnProperty(parentFileId)) {
|
|
@@ -1568,6 +1568,8 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
|
|
|
1568
1568
|
const parentDbInfo = parentDbsArray.find((db) => String(db.db_id) === String(parentFileId));
|
|
1569
1569
|
if (parentDbInfo) {
|
|
1570
1570
|
return { parentFileId, ownerId: parentDbInfo.owner_id };
|
|
1571
|
+
} else if (sceneConfigId && String(parentFileId) === String(sceneConfigId)) {
|
|
1572
|
+
return { parentFileId, ownerId: sceneOwnerId };
|
|
1571
1573
|
} else {
|
|
1572
1574
|
console.warn(`Owner ID n\xE3o encontrado em sceneData.parent_dbs para o parentFileId: ${parentFileId}`);
|
|
1573
1575
|
return { parentFileId, ownerId: null };
|
|
@@ -1837,6 +1839,7 @@ var userActionHandlers = {
|
|
|
1837
1839
|
setters.setFormPosition((p) => ({ ...p, opacity: 0 }));
|
|
1838
1840
|
},
|
|
1839
1841
|
handleSaveVersionNode: async (context, newNodeData) => {
|
|
1842
|
+
var _a;
|
|
1840
1843
|
const { graphDataRef, sceneDataRef, stateRef, versionMode, setters } = context;
|
|
1841
1844
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
1842
1845
|
const { sourceNodeData } = versionMode;
|
|
@@ -1846,7 +1849,7 @@ var userActionHandlers = {
|
|
|
1846
1849
|
version_node: { is_version: true, parent_node: sourceNodeData.id }
|
|
1847
1850
|
};
|
|
1848
1851
|
const newLink = { id: `link_${import_short_uuid.default.generate()}`, source: sourceNodeData.id, target: newNode.id };
|
|
1849
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
|
|
1852
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
|
|
1850
1853
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
1851
1854
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
|
|
1852
1855
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
|
|
@@ -1856,9 +1859,21 @@ var userActionHandlers = {
|
|
|
1856
1859
|
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
|
|
1857
1860
|
specificParentData.nodes.push(newNode);
|
|
1858
1861
|
specificParentData.links.push(newLink);
|
|
1859
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
1860
1862
|
try {
|
|
1861
|
-
|
|
1863
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
1864
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
1865
|
+
const viewFilePayload = {
|
|
1866
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
1867
|
+
nodes: sceneDataRef.current.nodes,
|
|
1868
|
+
links: sceneDataRef.current.links,
|
|
1869
|
+
quest_nodes: specificParentData.nodes,
|
|
1870
|
+
quest_links: specificParentData.links
|
|
1871
|
+
};
|
|
1872
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
1873
|
+
} else {
|
|
1874
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
1875
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
1876
|
+
}
|
|
1862
1877
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
1863
1878
|
const finalPosition = stateRef.current.ghostElements.node.position.clone();
|
|
1864
1879
|
addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
|
|
@@ -2015,6 +2030,7 @@ var userActionHandlers = {
|
|
|
2015
2030
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
2016
2031
|
},
|
|
2017
2032
|
handleCompleteConnection: async (context, targetNodeData) => {
|
|
2033
|
+
var _a;
|
|
2018
2034
|
const { stateRef, graphDataRef, sceneDataRef } = context;
|
|
2019
2035
|
const { sourceNodeData } = stateRef.current.connection;
|
|
2020
2036
|
if (!graphDataRef.current || !sceneDataRef.current || !sourceNodeData || !targetNodeData) {
|
|
@@ -2022,7 +2038,7 @@ var userActionHandlers = {
|
|
|
2022
2038
|
userActionHandlers.handleCancelConnection(context);
|
|
2023
2039
|
return;
|
|
2024
2040
|
}
|
|
2025
|
-
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
|
|
2041
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
|
|
2026
2042
|
if (!sourceParentInfo || !sourceParentInfo.ownerId) {
|
|
2027
2043
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
|
|
2028
2044
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
|
|
@@ -2037,12 +2053,26 @@ var userActionHandlers = {
|
|
|
2037
2053
|
source: sourceNodeData.id,
|
|
2038
2054
|
target: targetNodeData.id
|
|
2039
2055
|
};
|
|
2040
|
-
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
2041
|
-
specificParentData.links.push(newLink);
|
|
2042
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
2043
2056
|
try {
|
|
2044
|
-
|
|
2045
|
-
|
|
2057
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2058
|
+
if (isView && parentFileIdToSave === context.sceneConfigId) {
|
|
2059
|
+
const specificParentData = graphDataRef.current[context.sceneConfigId];
|
|
2060
|
+
specificParentData.links.push(newLink);
|
|
2061
|
+
const viewFilePayload = {
|
|
2062
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2063
|
+
nodes: sceneDataRef.current.nodes,
|
|
2064
|
+
links: sceneDataRef.current.links,
|
|
2065
|
+
quest_nodes: specificParentData.nodes,
|
|
2066
|
+
quest_links: specificParentData.links
|
|
2067
|
+
};
|
|
2068
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2069
|
+
} else {
|
|
2070
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
2071
|
+
specificParentData.links.push(newLink);
|
|
2072
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
2073
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2074
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
2075
|
+
}
|
|
2046
2076
|
addNewLinkToScene(stateRef.current, newLink);
|
|
2047
2077
|
} catch (error) {
|
|
2048
2078
|
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
@@ -2111,8 +2141,8 @@ var userActionHandlers = {
|
|
|
2111
2141
|
} else {
|
|
2112
2142
|
newTargetId = newEndNodeData.id;
|
|
2113
2143
|
}
|
|
2114
|
-
const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId);
|
|
2115
|
-
const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId);
|
|
2144
|
+
const originalParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
|
|
2145
|
+
const newParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
|
|
2116
2146
|
if (!originalParentInfo || !newParentInfo || !originalParentInfo.ownerId || !newParentInfo.ownerId) {
|
|
2117
2147
|
console.error("N\xE3o foi poss\xEDvel encontrar informa\xE7\xF5es dos arquivos pai para o relink.");
|
|
2118
2148
|
alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
|
|
@@ -2126,6 +2156,22 @@ var userActionHandlers = {
|
|
|
2126
2156
|
target: newTargetId,
|
|
2127
2157
|
id: linkId
|
|
2128
2158
|
};
|
|
2159
|
+
const saveParentData = async (fileId, fileOwnerId, data) => {
|
|
2160
|
+
var _a;
|
|
2161
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2162
|
+
if (isView && fileId === context.sceneConfigId) {
|
|
2163
|
+
const viewFilePayload = {
|
|
2164
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2165
|
+
nodes: sceneDataRef.current.nodes,
|
|
2166
|
+
links: sceneDataRef.current.links,
|
|
2167
|
+
quest_nodes: data.nodes,
|
|
2168
|
+
quest_links: data.links
|
|
2169
|
+
};
|
|
2170
|
+
return context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2171
|
+
} else {
|
|
2172
|
+
return context.actions.save_view_data(`x_view_dbs/${fileOwnerId}/${fileId}`, data);
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2129
2175
|
const savePromises = [];
|
|
2130
2176
|
const filesToUpdate = {};
|
|
2131
2177
|
if (originalParentInfo.parentFileId !== newParentInfo.parentFileId) {
|
|
@@ -2134,16 +2180,12 @@ var userActionHandlers = {
|
|
|
2134
2180
|
(l) => String(l.id) !== String(linkId)
|
|
2135
2181
|
);
|
|
2136
2182
|
filesToUpdate[originalParentInfo.parentFileId] = updatedOriginalParentData;
|
|
2137
|
-
savePromises.push(
|
|
2138
|
-
context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedOriginalParentData)
|
|
2139
|
-
);
|
|
2183
|
+
savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedOriginalParentData));
|
|
2140
2184
|
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newParentInfo.parentFileId]));
|
|
2141
2185
|
if (!updatedNewParentData.links) updatedNewParentData.links = [];
|
|
2142
2186
|
updatedNewParentData.links.push(newLinkData);
|
|
2143
2187
|
filesToUpdate[newParentInfo.parentFileId] = updatedNewParentData;
|
|
2144
|
-
savePromises.push(
|
|
2145
|
-
context.actions.save_view_data(`x_view_dbs/${newParentInfo.ownerId}/${newParentInfo.parentFileId}`, updatedNewParentData)
|
|
2146
|
-
);
|
|
2188
|
+
savePromises.push(saveParentData(newParentInfo.parentFileId, newParentInfo.ownerId, updatedNewParentData));
|
|
2147
2189
|
} else {
|
|
2148
2190
|
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[originalParentInfo.parentFileId]));
|
|
2149
2191
|
updatedParentData.links = updatedParentData.links.filter(
|
|
@@ -2151,9 +2193,7 @@ var userActionHandlers = {
|
|
|
2151
2193
|
);
|
|
2152
2194
|
updatedParentData.links.push(newLinkData);
|
|
2153
2195
|
filesToUpdate[originalParentInfo.parentFileId] = updatedParentData;
|
|
2154
|
-
savePromises.push(
|
|
2155
|
-
context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedParentData)
|
|
2156
|
-
);
|
|
2196
|
+
savePromises.push(saveParentData(originalParentInfo.parentFileId, originalParentInfo.ownerId, updatedParentData));
|
|
2157
2197
|
}
|
|
2158
2198
|
try {
|
|
2159
2199
|
await Promise.all(savePromises);
|
|
@@ -2171,7 +2211,7 @@ var userActionHandlers = {
|
|
|
2171
2211
|
}
|
|
2172
2212
|
},
|
|
2173
2213
|
handleDeleteLink: async (context, linkObject) => {
|
|
2174
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2214
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2175
2215
|
const { stateRef, graphDataRef, sceneDataRef, setters } = context;
|
|
2176
2216
|
setters.setRelationshipMenu({ visible: false });
|
|
2177
2217
|
if (!(linkObject == null ? void 0 : linkObject.userData) || !graphDataRef.current || !sceneDataRef.current) return;
|
|
@@ -2180,7 +2220,7 @@ var userActionHandlers = {
|
|
|
2180
2220
|
console.error("Tentativa de deletar um link sem ID.", linkObject.userData);
|
|
2181
2221
|
return;
|
|
2182
2222
|
}
|
|
2183
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source);
|
|
2223
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source, context.sceneConfigId, context.ownerId);
|
|
2184
2224
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2185
2225
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:", linkIdToDelete);
|
|
2186
2226
|
alert("Ocorreu um erro ao identificar o arquivo pai da rela\xE7\xE3o para exclus\xE3o.");
|
|
@@ -2192,9 +2232,25 @@ var userActionHandlers = {
|
|
|
2192
2232
|
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
|
|
2193
2233
|
const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
|
|
2194
2234
|
specificParentData.links = newLinks;
|
|
2195
|
-
|
|
2235
|
+
let filenameToSave;
|
|
2236
|
+
let payloadToSave;
|
|
2237
|
+
const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
|
|
2238
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2239
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2240
|
+
sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => String(l.id) !== String(linkIdToDelete));
|
|
2241
|
+
payloadToSave = {
|
|
2242
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2243
|
+
nodes: sceneDataRef.current.nodes,
|
|
2244
|
+
links: sceneDataRef.current.links,
|
|
2245
|
+
quest_nodes: specificParentData.nodes,
|
|
2246
|
+
quest_links: specificParentData.links
|
|
2247
|
+
};
|
|
2248
|
+
} else {
|
|
2249
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2250
|
+
payloadToSave = specificParentData;
|
|
2251
|
+
}
|
|
2196
2252
|
try {
|
|
2197
|
-
await context.actions.save_view_data(
|
|
2253
|
+
await context.actions.save_view_data(filenameToSave, payloadToSave);
|
|
2198
2254
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2199
2255
|
setters.setDetailsLink((prev) => String(prev == null ? void 0 : prev.id) === String(linkIdToDelete) ? null : prev);
|
|
2200
2256
|
if (stateRef.current.hoveredLink === linkObject) {
|
|
@@ -2339,6 +2395,7 @@ var userActionHandlers = {
|
|
|
2339
2395
|
stateRef.current.selectedNodes.clear();
|
|
2340
2396
|
},
|
|
2341
2397
|
handleDeleteMultipleNodes: async (context, nodeIds) => {
|
|
2398
|
+
var _a;
|
|
2342
2399
|
const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
|
|
2343
2400
|
setters.setMultiContextMenu({ visible: false });
|
|
2344
2401
|
if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current) return;
|
|
@@ -2357,7 +2414,7 @@ var userActionHandlers = {
|
|
|
2357
2414
|
}
|
|
2358
2415
|
const changesByParentFile = {};
|
|
2359
2416
|
for (const nodeId of strNodeIdsToDelete) {
|
|
2360
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId);
|
|
2417
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId, context.sceneConfigId, context.ownerId);
|
|
2361
2418
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2362
2419
|
console.warn(`Node com ID ${nodeId} n\xE3o encontrado ou sem ownerId. Ignorando.`);
|
|
2363
2420
|
continue;
|
|
@@ -2391,8 +2448,27 @@ var userActionHandlers = {
|
|
|
2391
2448
|
originalData.links = (originalData.links || []).filter(
|
|
2392
2449
|
(l) => !linksToDelete.has(String(l.id))
|
|
2393
2450
|
);
|
|
2394
|
-
|
|
2395
|
-
|
|
2451
|
+
let filenameToSave;
|
|
2452
|
+
let payloadToSave;
|
|
2453
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2454
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2455
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2456
|
+
const strNodesToDelete = Array.from(nodesToDelete).map(String);
|
|
2457
|
+
const strLinksToDelete = Array.from(linksToDelete).map(String);
|
|
2458
|
+
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter((n) => !strNodesToDelete.includes(String(n.id)));
|
|
2459
|
+
sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => !strLinksToDelete.includes(String(l.id)));
|
|
2460
|
+
payloadToSave = {
|
|
2461
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2462
|
+
nodes: sceneDataRef.current.nodes,
|
|
2463
|
+
links: sceneDataRef.current.links,
|
|
2464
|
+
quest_nodes: originalData.nodes,
|
|
2465
|
+
quest_links: originalData.links
|
|
2466
|
+
};
|
|
2467
|
+
} else {
|
|
2468
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2469
|
+
payloadToSave = originalData;
|
|
2470
|
+
}
|
|
2471
|
+
savePromises.push(context.actions.save_view_data(filenameToSave, payloadToSave));
|
|
2396
2472
|
updatedParentDataCache[parentFileId] = originalData;
|
|
2397
2473
|
}
|
|
2398
2474
|
}
|
|
@@ -2413,6 +2489,7 @@ var userActionHandlers = {
|
|
|
2413
2489
|
}
|
|
2414
2490
|
},
|
|
2415
2491
|
handleDeleteNode: async (context, nodeData) => {
|
|
2492
|
+
var _a;
|
|
2416
2493
|
const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
|
|
2417
2494
|
if (actions.delete_file && nodeData) {
|
|
2418
2495
|
const urls = extractFileUrlsFromProperties(nodeData);
|
|
@@ -2424,7 +2501,7 @@ var userActionHandlers = {
|
|
|
2424
2501
|
if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
|
|
2425
2502
|
const nodeIdToDelete = nodeData.id;
|
|
2426
2503
|
const strNodeId = String(nodeIdToDelete);
|
|
2427
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
|
|
2504
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete, context.sceneConfigId, context.ownerId);
|
|
2428
2505
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2429
2506
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser exclu\xEDdo:", nodeIdToDelete);
|
|
2430
2507
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para exclus\xE3o.");
|
|
@@ -2436,9 +2513,28 @@ var userActionHandlers = {
|
|
|
2436
2513
|
const newLinks = (specificParentData.links || []).filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
|
|
2437
2514
|
specificParentData.nodes = newNodes;
|
|
2438
2515
|
specificParentData.links = newLinks;
|
|
2439
|
-
|
|
2516
|
+
let filenameToSave;
|
|
2517
|
+
let payloadToSave;
|
|
2518
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2519
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2520
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2521
|
+
const newVisualNodes = sceneDataRef.current.nodes.filter((n) => String(n.id) !== strNodeId);
|
|
2522
|
+
const newVisualLinks = sceneDataRef.current.links.filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
|
|
2523
|
+
sceneDataRef.current.nodes = newVisualNodes;
|
|
2524
|
+
sceneDataRef.current.links = newVisualLinks;
|
|
2525
|
+
payloadToSave = {
|
|
2526
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2527
|
+
nodes: newVisualNodes,
|
|
2528
|
+
links: newVisualLinks,
|
|
2529
|
+
quest_nodes: specificParentData.nodes,
|
|
2530
|
+
quest_links: specificParentData.links
|
|
2531
|
+
};
|
|
2532
|
+
} else {
|
|
2533
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2534
|
+
payloadToSave = specificParentData;
|
|
2535
|
+
}
|
|
2440
2536
|
try {
|
|
2441
|
-
await context.actions.save_view_data(
|
|
2537
|
+
await context.actions.save_view_data(filenameToSave, payloadToSave);
|
|
2442
2538
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2443
2539
|
setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev);
|
|
2444
2540
|
removeNodeFromScene(stateRef.current, nodeIdToDelete);
|
|
@@ -2449,10 +2545,11 @@ var userActionHandlers = {
|
|
|
2449
2545
|
}
|
|
2450
2546
|
},
|
|
2451
2547
|
handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
|
|
2548
|
+
var _a;
|
|
2452
2549
|
const { graphDataRef, sceneDataRef, stateRef, setters } = context;
|
|
2453
2550
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
2454
2551
|
const { _baseEmissiveIntensity: ignored, ...nodeToSave } = updatedNode;
|
|
2455
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id);
|
|
2552
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id, context.sceneConfigId, context.ownerId);
|
|
2456
2553
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2457
2554
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser atualizado:", nodeToSave.id);
|
|
2458
2555
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
|
|
@@ -2468,9 +2565,21 @@ var userActionHandlers = {
|
|
|
2468
2565
|
alert("Erro interno: Node n\xE3o encontrado para salvar.");
|
|
2469
2566
|
return;
|
|
2470
2567
|
}
|
|
2471
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2472
2568
|
try {
|
|
2473
|
-
|
|
2569
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2570
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2571
|
+
const viewFilePayload = {
|
|
2572
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2573
|
+
nodes: sceneDataRef.current.nodes,
|
|
2574
|
+
links: sceneDataRef.current.links,
|
|
2575
|
+
quest_nodes: specificParentData.nodes,
|
|
2576
|
+
quest_links: specificParentData.links
|
|
2577
|
+
};
|
|
2578
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2579
|
+
} else {
|
|
2580
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2581
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2582
|
+
}
|
|
2474
2583
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2475
2584
|
updateExistingNodeVisuals(stateRef.current, nodeToSave);
|
|
2476
2585
|
setters.setSceneVersion((v) => v + 1);
|
|
@@ -2483,10 +2592,11 @@ var userActionHandlers = {
|
|
|
2483
2592
|
}
|
|
2484
2593
|
},
|
|
2485
2594
|
handleSaveLinkDetails: async (context, updatedLink, keepOpen = false) => {
|
|
2595
|
+
var _a;
|
|
2486
2596
|
const { graphDataRef, sceneDataRef, stateRef, setters } = context;
|
|
2487
2597
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
2488
2598
|
const { sourceNode, targetNode, ...linkToSave } = updatedLink;
|
|
2489
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source);
|
|
2599
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source, context.sceneConfigId, context.ownerId);
|
|
2490
2600
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2491
2601
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link a ser atualizado:", linkToSave.id);
|
|
2492
2602
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
|
|
@@ -2502,9 +2612,21 @@ var userActionHandlers = {
|
|
|
2502
2612
|
alert("Erro interno: link n\xE3o encontrado para salvar.");
|
|
2503
2613
|
return;
|
|
2504
2614
|
}
|
|
2505
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2506
2615
|
try {
|
|
2507
|
-
|
|
2616
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2617
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2618
|
+
const viewFilePayload = {
|
|
2619
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2620
|
+
nodes: sceneDataRef.current.nodes,
|
|
2621
|
+
links: sceneDataRef.current.links,
|
|
2622
|
+
quest_nodes: specificParentData.nodes,
|
|
2623
|
+
quest_links: specificParentData.links
|
|
2624
|
+
};
|
|
2625
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2626
|
+
} else {
|
|
2627
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2628
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2629
|
+
}
|
|
2508
2630
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2509
2631
|
const lineObject = stateRef.current.allLinks.find(
|
|
2510
2632
|
(l) => String(l.userData.id) === String(linkToSave.id)
|
|
@@ -7848,9 +7970,180 @@ function InSceneVersionForm({
|
|
|
7848
7970
|
));
|
|
7849
7971
|
}
|
|
7850
7972
|
|
|
7851
|
-
// src/components/
|
|
7973
|
+
// src/components/InSceneQuestForm.jsx
|
|
7852
7974
|
var import_react16 = __toESM(require("react"));
|
|
7853
7975
|
var import_fi14 = require("react-icons/fi");
|
|
7976
|
+
var QUEST_STATUS_COLORS = {
|
|
7977
|
+
"Backlog": "#64748b",
|
|
7978
|
+
// Slate (Cinza azulado)
|
|
7979
|
+
"In Progress": "#eab308",
|
|
7980
|
+
// Yellow (Amarelo)
|
|
7981
|
+
"Review": "#a855f7",
|
|
7982
|
+
// Purple (Roxo)
|
|
7983
|
+
"Done": "#22c55e"
|
|
7984
|
+
// Green (Verde)
|
|
7985
|
+
};
|
|
7986
|
+
function InSceneQuestForm({
|
|
7987
|
+
onSave,
|
|
7988
|
+
onCancel,
|
|
7989
|
+
style,
|
|
7990
|
+
refEl,
|
|
7991
|
+
onOpenImageViewer,
|
|
7992
|
+
availableNodes = [],
|
|
7993
|
+
availableAncestries = [],
|
|
7994
|
+
onMentionClick,
|
|
7995
|
+
onUploadFile
|
|
7996
|
+
}) {
|
|
7997
|
+
const [name, setName] = (0, import_react16.useState)("");
|
|
7998
|
+
const [types, setTypes] = (0, import_react16.useState)(["quest"]);
|
|
7999
|
+
const [typeInput, setTypeInput] = (0, import_react16.useState)("");
|
|
8000
|
+
const [status, setStatus] = (0, import_react16.useState)("Backlog");
|
|
8001
|
+
const [size, setSize] = (0, import_react16.useState)("medium");
|
|
8002
|
+
const [intensity, setIntensity] = (0, import_react16.useState)(0);
|
|
8003
|
+
const [description, setDescription] = (0, import_react16.useState)("");
|
|
8004
|
+
const [customProps, setCustomProps] = (0, import_react16.useState)([]);
|
|
8005
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react16.useState)(false);
|
|
8006
|
+
const propsEndRef = (0, import_react16.useRef)(null);
|
|
8007
|
+
const handleAddProp = () => {
|
|
8008
|
+
const newProp = createNewCustomProperty(customProps);
|
|
8009
|
+
setCustomProps([...customProps, newProp]);
|
|
8010
|
+
setTimeout(() => {
|
|
8011
|
+
var _a;
|
|
8012
|
+
(_a = propsEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
8013
|
+
}, 100);
|
|
8014
|
+
};
|
|
8015
|
+
const handleRemoveProp = (index) => setCustomProps(customProps.filter((_, i) => i !== index));
|
|
8016
|
+
const handleUpdateProp = (index, updatedProp) => {
|
|
8017
|
+
const newProps = [...customProps];
|
|
8018
|
+
newProps[index] = updatedProp;
|
|
8019
|
+
setCustomProps(newProps);
|
|
8020
|
+
};
|
|
8021
|
+
const handleAddType = (newType) => {
|
|
8022
|
+
const trimmed = newType.trim();
|
|
8023
|
+
if (trimmed && !types.includes(trimmed)) {
|
|
8024
|
+
setTypes([...types, trimmed]);
|
|
8025
|
+
setTypeInput("");
|
|
8026
|
+
}
|
|
8027
|
+
};
|
|
8028
|
+
const handleRemoveType = (indexToRemove) => {
|
|
8029
|
+
if (types[indexToRemove] === "quest") return;
|
|
8030
|
+
setTypes(types.filter((_, index) => index !== indexToRemove));
|
|
8031
|
+
};
|
|
8032
|
+
const handleTypeInputKeyDown = (e) => {
|
|
8033
|
+
if (e.key === "Enter") {
|
|
8034
|
+
e.preventDefault();
|
|
8035
|
+
handleAddType(typeInput);
|
|
8036
|
+
} else if (e.key === "Backspace" && typeInput === "" && types.length > 1) {
|
|
8037
|
+
handleRemoveType(types.length - 1);
|
|
8038
|
+
}
|
|
8039
|
+
};
|
|
8040
|
+
const handleSubmit = (e) => {
|
|
8041
|
+
e.preventDefault();
|
|
8042
|
+
if (!name.trim()) {
|
|
8043
|
+
alert("O campo 'Nome' \xE9 obrigat\xF3rio.");
|
|
8044
|
+
return;
|
|
8045
|
+
}
|
|
8046
|
+
const additionalData = toObjectFromCustomProps(
|
|
8047
|
+
customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
|
|
8048
|
+
);
|
|
8049
|
+
const processedSections = processDescriptionForSave(description, []);
|
|
8050
|
+
onSave({
|
|
8051
|
+
name: name.trim(),
|
|
8052
|
+
type: types,
|
|
8053
|
+
color: QUEST_STATUS_COLORS[status],
|
|
8054
|
+
// Cor atrelada ao status
|
|
8055
|
+
status,
|
|
8056
|
+
size,
|
|
8057
|
+
intensity,
|
|
8058
|
+
description: description.trim(),
|
|
8059
|
+
description_sections: processedSections,
|
|
8060
|
+
useImageAsTexture: false,
|
|
8061
|
+
textureImageUrl: null,
|
|
8062
|
+
...additionalData
|
|
8063
|
+
});
|
|
8064
|
+
};
|
|
8065
|
+
const swallow = (e) => e.stopPropagation();
|
|
8066
|
+
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
8067
|
+
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
8068
|
+
return /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, null, /* @__PURE__ */ import_react16.default.createElement(
|
|
8069
|
+
"div",
|
|
8070
|
+
{
|
|
8071
|
+
ref: refEl,
|
|
8072
|
+
className: "ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white w-[min(92vw,440px)] overflow-hidden",
|
|
8073
|
+
style,
|
|
8074
|
+
onPointerDown: swallow,
|
|
8075
|
+
onClick: swallow,
|
|
8076
|
+
onWheel: swallow,
|
|
8077
|
+
onContextMenu: swallow,
|
|
8078
|
+
onDoubleClick: swallow
|
|
8079
|
+
},
|
|
8080
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
8081
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova Tarefa / Objetivo")), /* @__PURE__ */ import_react16.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")),
|
|
8082
|
+
/* @__PURE__ */ import_react16.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement(
|
|
8083
|
+
"select",
|
|
8084
|
+
{
|
|
8085
|
+
value: status,
|
|
8086
|
+
onChange: (e) => setStatus(e.target.value),
|
|
8087
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 appearance-none cursor-pointer",
|
|
8088
|
+
style: { borderLeft: `4px solid ${QUEST_STATUS_COLORS[status]}` }
|
|
8089
|
+
},
|
|
8090
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Backlog" }, "Backlog"),
|
|
8091
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
8092
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Review" }, "Review"),
|
|
8093
|
+
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
|
|
8094
|
+
)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
8095
|
+
"input",
|
|
8096
|
+
{
|
|
8097
|
+
type: "text",
|
|
8098
|
+
value: typeInput,
|
|
8099
|
+
onChange: (e) => setTypeInput(e.target.value),
|
|
8100
|
+
onKeyDown: handleTypeInputKeyDown,
|
|
8101
|
+
onBlur: () => {
|
|
8102
|
+
if (typeInput.trim()) handleAddType(typeInput);
|
|
8103
|
+
},
|
|
8104
|
+
className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
|
|
8105
|
+
autoComplete: "off"
|
|
8106
|
+
}
|
|
8107
|
+
))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(
|
|
8108
|
+
DescriptionDisplay,
|
|
8109
|
+
{
|
|
8110
|
+
description,
|
|
8111
|
+
savedSections: [],
|
|
8112
|
+
availableNodes,
|
|
8113
|
+
availableAncestries,
|
|
8114
|
+
onMentionClick,
|
|
8115
|
+
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
8116
|
+
}
|
|
8117
|
+
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiEdit2, { size: 14 }))), !description && /* @__PURE__ */ import_react16.default.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Cen\xE1rio (Size)"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ import_react16.default.createElement("button", { key: s, type: "button", onClick: () => setSize(s), className: "flex items-center gap-2 group cursor-pointer focus:outline-none" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react16.default.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s))))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react16.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ import_react16.default.createElement(
|
|
8118
|
+
CustomPropertyDisplay,
|
|
8119
|
+
{
|
|
8120
|
+
key: prop.id,
|
|
8121
|
+
prop,
|
|
8122
|
+
onUpdate: (updatedProp) => handleUpdateProp(index, updatedProp),
|
|
8123
|
+
onRemove: () => handleRemoveProp(index),
|
|
8124
|
+
onOpenImageViewer,
|
|
8125
|
+
unavailableTypes: currentUsedTypes.filter((t) => t !== prop.type),
|
|
8126
|
+
onUploadFile
|
|
8127
|
+
}
|
|
8128
|
+
)), /* @__PURE__ */ import_react16.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: onCancel, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm" }, "Cancelar"), /* @__PURE__ */ import_react16.default.createElement("button", { type: "submit", className: "px-4 py-2 rounded-lg bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 transition-colors font-semibold text-sm shadow-[0_8px_24px_rgba(99,102,241,0.35)]" }, "Salvar Quest")))
|
|
8129
|
+
), isDescriptionModalOpen && /* @__PURE__ */ import_react16.default.createElement(
|
|
8130
|
+
DescriptionEditModal,
|
|
8131
|
+
{
|
|
8132
|
+
isOpen: isDescriptionModalOpen,
|
|
8133
|
+
title: "Editar Descri\xE7\xE3o da Quest",
|
|
8134
|
+
initialValue: description,
|
|
8135
|
+
onSave: (newDescription) => setDescription(newDescription),
|
|
8136
|
+
onClose: () => setIsDescriptionModalOpen(false),
|
|
8137
|
+
availableNodes,
|
|
8138
|
+
availableAncestries,
|
|
8139
|
+
availableImages
|
|
8140
|
+
}
|
|
8141
|
+
));
|
|
8142
|
+
}
|
|
8143
|
+
|
|
8144
|
+
// src/components/NodeDetailsPanel.jsx
|
|
8145
|
+
var import_react17 = __toESM(require("react"));
|
|
8146
|
+
var import_fi15 = require("react-icons/fi");
|
|
7854
8147
|
function NodeDetailsPanel({
|
|
7855
8148
|
node,
|
|
7856
8149
|
onClose,
|
|
@@ -7871,38 +8164,38 @@ function NodeDetailsPanel({
|
|
|
7871
8164
|
userRole,
|
|
7872
8165
|
currentDatasetName
|
|
7873
8166
|
}) {
|
|
7874
|
-
const [name, setName] = (0,
|
|
7875
|
-
const [types, setTypes] = (0,
|
|
7876
|
-
const [typeInput, setTypeInput] = (0,
|
|
7877
|
-
const [color, setColor] = (0,
|
|
7878
|
-
const [size, setSize] = (0,
|
|
7879
|
-
const [description, setDescription] = (0,
|
|
7880
|
-
const [intensity, setIntensity] = (0,
|
|
7881
|
-
const [customProps, setCustomProps] = (0,
|
|
7882
|
-
const [showTypeSuggestions, setShowTypeSuggestions] = (0,
|
|
7883
|
-
const [filteredTypes, setFilteredTypes] = (0,
|
|
7884
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0,
|
|
7885
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
7886
|
-
const [existingSections, setExistingSections] = (0,
|
|
7887
|
-
const [isSaving, setIsSaving] = (0,
|
|
7888
|
-
const [isLinkCopied, setIsLinkCopied] = (0,
|
|
7889
|
-
const [useImageAsTexture, setUseImageAsTexture] = (0,
|
|
8167
|
+
const [name, setName] = (0, import_react17.useState)((node == null ? void 0 : node.name) ?? "");
|
|
8168
|
+
const [types, setTypes] = (0, import_react17.useState)([]);
|
|
8169
|
+
const [typeInput, setTypeInput] = (0, import_react17.useState)("");
|
|
8170
|
+
const [color, setColor] = (0, import_react17.useState)((node == null ? void 0 : node.color) ?? "#8b5cf6");
|
|
8171
|
+
const [size, setSize] = (0, import_react17.useState)((node == null ? void 0 : node.size) ?? "medium");
|
|
8172
|
+
const [description, setDescription] = (0, import_react17.useState)((node == null ? void 0 : node.description) ?? "");
|
|
8173
|
+
const [intensity, setIntensity] = (0, import_react17.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
8174
|
+
const [customProps, setCustomProps] = (0, import_react17.useState)(() => extractCustomPropsFromNode(node || {}));
|
|
8175
|
+
const [showTypeSuggestions, setShowTypeSuggestions] = (0, import_react17.useState)(false);
|
|
8176
|
+
const [filteredTypes, setFilteredTypes] = (0, import_react17.useState)([]);
|
|
8177
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
|
|
8178
|
+
const [isReadMode, setIsReadMode] = (0, import_react17.useState)(false);
|
|
8179
|
+
const [existingSections, setExistingSections] = (0, import_react17.useState)((node == null ? void 0 : node.description_sections) || []);
|
|
8180
|
+
const [isSaving, setIsSaving] = (0, import_react17.useState)(false);
|
|
8181
|
+
const [isLinkCopied, setIsLinkCopied] = (0, import_react17.useState)(false);
|
|
8182
|
+
const [useImageAsTexture, setUseImageAsTexture] = (0, import_react17.useState)(() => {
|
|
7890
8183
|
if ((node == null ? void 0 : node.useImageAsTexture) === "true") return true;
|
|
7891
8184
|
if ((node == null ? void 0 : node.useImageAsTexture) === "false") return false;
|
|
7892
8185
|
return !!(node == null ? void 0 : node.useImageAsTexture);
|
|
7893
8186
|
});
|
|
7894
|
-
const [selectedImageUrl, setSelectedImageUrl] = (0,
|
|
8187
|
+
const [selectedImageUrl, setSelectedImageUrl] = (0, import_react17.useState)((node == null ? void 0 : node.textureImageUrl) ?? null);
|
|
7895
8188
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
7896
8189
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
7897
8190
|
initialWidth: isReadMode ? 700 : 440,
|
|
7898
8191
|
minWidth: 320,
|
|
7899
8192
|
maxWidth: maxPanelW
|
|
7900
8193
|
});
|
|
7901
|
-
(0,
|
|
8194
|
+
(0, import_react17.useEffect)(() => {
|
|
7902
8195
|
setWidth(isReadMode ? 700 : 440);
|
|
7903
8196
|
}, [isReadMode, setWidth]);
|
|
7904
|
-
const prevNodeIdRef = (0,
|
|
7905
|
-
const propsEndRef = (0,
|
|
8197
|
+
const prevNodeIdRef = (0, import_react17.useRef)(null);
|
|
8198
|
+
const propsEndRef = (0, import_react17.useRef)(null);
|
|
7906
8199
|
const canEdit = userRole !== "viewer";
|
|
7907
8200
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
7908
8201
|
const handleImageClickFromText = (url, name2) => {
|
|
@@ -7910,7 +8203,7 @@ function NodeDetailsPanel({
|
|
|
7910
8203
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
7911
8204
|
}
|
|
7912
8205
|
};
|
|
7913
|
-
(0,
|
|
8206
|
+
(0, import_react17.useEffect)(() => {
|
|
7914
8207
|
if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
|
|
7915
8208
|
prevNodeIdRef.current = node == null ? void 0 : node.id;
|
|
7916
8209
|
setName((node == null ? void 0 : node.name) ?? "");
|
|
@@ -7932,13 +8225,13 @@ function NodeDetailsPanel({
|
|
|
7932
8225
|
}
|
|
7933
8226
|
}, [node]);
|
|
7934
8227
|
const hasImages = customProps.some((p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value));
|
|
7935
|
-
(0,
|
|
8228
|
+
(0, import_react17.useEffect)(() => {
|
|
7936
8229
|
if (!hasImages && useImageAsTexture) {
|
|
7937
8230
|
setUseImageAsTexture(false);
|
|
7938
8231
|
setSelectedImageUrl(null);
|
|
7939
8232
|
}
|
|
7940
8233
|
}, [hasImages, useImageAsTexture]);
|
|
7941
|
-
(0,
|
|
8234
|
+
(0, import_react17.useEffect)(() => {
|
|
7942
8235
|
if (typeInput.trim() === "") {
|
|
7943
8236
|
setFilteredTypes(existingTypes.filter((t) => !types.includes(t)));
|
|
7944
8237
|
} else {
|
|
@@ -8110,7 +8403,7 @@ function NodeDetailsPanel({
|
|
|
8110
8403
|
onClose();
|
|
8111
8404
|
};
|
|
8112
8405
|
const currentUsedTypes = customProps.map((p) => p.type).filter((t) => UNIQUE_PROP_TYPES.includes(t));
|
|
8113
|
-
return /* @__PURE__ */
|
|
8406
|
+
return /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(
|
|
8114
8407
|
"div",
|
|
8115
8408
|
{
|
|
8116
8409
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
@@ -8123,7 +8416,7 @@ function NodeDetailsPanel({
|
|
|
8123
8416
|
onContextMenu: swallow,
|
|
8124
8417
|
onDoubleClick: swallow
|
|
8125
8418
|
},
|
|
8126
|
-
/* @__PURE__ */
|
|
8419
|
+
/* @__PURE__ */ import_react17.default.createElement(
|
|
8127
8420
|
"div",
|
|
8128
8421
|
{
|
|
8129
8422
|
onPointerDown: (e) => {
|
|
@@ -8134,7 +8427,7 @@ function NodeDetailsPanel({
|
|
|
8134
8427
|
title: "Arraste para redimensionar"
|
|
8135
8428
|
}
|
|
8136
8429
|
),
|
|
8137
|
-
isReadMode ? /* @__PURE__ */
|
|
8430
|
+
isReadMode ? /* @__PURE__ */ import_react17.default.createElement(
|
|
8138
8431
|
DescriptionReadModePanel,
|
|
8139
8432
|
{
|
|
8140
8433
|
title: name || (node == null ? void 0 : node.name),
|
|
@@ -8155,23 +8448,23 @@ function NodeDetailsPanel({
|
|
|
8155
8448
|
onImageClick: handleImageClickFromText,
|
|
8156
8449
|
onSaveDescription: handleSaveDescriptionInline
|
|
8157
8450
|
}
|
|
8158
|
-
) : /* @__PURE__ */
|
|
8451
|
+
) : /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }), /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react17.default.createElement("div", null, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-indigo-400/80 shadow-[0_0_18px_2px_rgba(99,102,241,0.55)]" }), /* @__PURE__ */ import_react17.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes do Node"), /* @__PURE__ */ import_react17.default.createElement(
|
|
8159
8452
|
"button",
|
|
8160
8453
|
{
|
|
8161
8454
|
onClick: handleCopyLink,
|
|
8162
8455
|
className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-indigo-400"}`,
|
|
8163
8456
|
title: isLinkCopied ? "Link Copiado!" : "Copiar link para este Node"
|
|
8164
8457
|
},
|
|
8165
|
-
isLinkCopied ? /* @__PURE__ */
|
|
8166
|
-
)), /* @__PURE__ */
|
|
8458
|
+
isLinkCopied ? /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLink, { size: 12 })
|
|
8459
|
+
)), /* @__PURE__ */ import_react17.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react17.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos"), /* @__PURE__ */ import_react17.default.createElement("div", { className: `relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ import_react17.default.createElement("span", { key: index, className: "flex items-center gap-1 bg-indigo-500/30 text-indigo-100 px-1.5 py-0.5 rounded-md text-xs font-medium border border-indigo-500/20" }, t, canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8167
8460
|
"button",
|
|
8168
8461
|
{
|
|
8169
8462
|
type: "button",
|
|
8170
8463
|
onClick: () => handleRemoveType(index),
|
|
8171
8464
|
className: "hover:text-white transition-colors"
|
|
8172
8465
|
},
|
|
8173
|
-
/* @__PURE__ */
|
|
8174
|
-
))), canEdit && /* @__PURE__ */
|
|
8466
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiX, { size: 12 })
|
|
8467
|
+
))), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8175
8468
|
"input",
|
|
8176
8469
|
{
|
|
8177
8470
|
type: "text",
|
|
@@ -8192,7 +8485,7 @@ function NodeDetailsPanel({
|
|
|
8192
8485
|
placeholder: types.length === 0 ? "Ex.: Cliente" : "",
|
|
8193
8486
|
autoComplete: "off"
|
|
8194
8487
|
}
|
|
8195
|
-
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */
|
|
8488
|
+
), canEdit && showTypeSuggestions && filteredTypes.length > 0 && /* @__PURE__ */ import_react17.default.createElement("ul", { className: "custom-scrollbar absolute top-full left-0 z-10 w-full mt-1 max-h-40 overflow-y-auto rounded-lg bg-slate-800 border border-white/10 shadow-lg" }, filteredTypes.map((suggestedType, index) => /* @__PURE__ */ import_react17.default.createElement(
|
|
8196
8489
|
"li",
|
|
8197
8490
|
{
|
|
8198
8491
|
key: index,
|
|
@@ -8203,7 +8496,7 @@ function NodeDetailsPanel({
|
|
|
8203
8496
|
}
|
|
8204
8497
|
},
|
|
8205
8498
|
suggestedType
|
|
8206
|
-
))))), /* @__PURE__ */
|
|
8499
|
+
))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome"), /* @__PURE__ */ import_react17.default.createElement(
|
|
8207
8500
|
"input",
|
|
8208
8501
|
{
|
|
8209
8502
|
type: "text",
|
|
@@ -8212,7 +8505,7 @@ function NodeDetailsPanel({
|
|
|
8212
8505
|
readOnly: !canEdit,
|
|
8213
8506
|
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
|
|
8214
8507
|
}
|
|
8215
|
-
)), /* @__PURE__ */
|
|
8508
|
+
)), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
8216
8509
|
DescriptionDisplay,
|
|
8217
8510
|
{
|
|
8218
8511
|
description,
|
|
@@ -8224,7 +8517,7 @@ function NodeDetailsPanel({
|
|
|
8224
8517
|
onImageClick: handleImageClickFromText,
|
|
8225
8518
|
onSaveDescription: handleSaveDescriptionInline
|
|
8226
8519
|
}
|
|
8227
|
-
), /* @__PURE__ */
|
|
8520
|
+
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
8228
8521
|
"button",
|
|
8229
8522
|
{
|
|
8230
8523
|
type: "button",
|
|
@@ -8232,8 +8525,8 @@ function NodeDetailsPanel({
|
|
|
8232
8525
|
className: `p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors ${canEdit ? "border-r border-white/5" : ""}`,
|
|
8233
8526
|
title: "Modo de Leitura"
|
|
8234
8527
|
},
|
|
8235
|
-
/* @__PURE__ */
|
|
8236
|
-
), canEdit && /* @__PURE__ */
|
|
8528
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiBookOpen, { size: 14 })
|
|
8529
|
+
), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8237
8530
|
"button",
|
|
8238
8531
|
{
|
|
8239
8532
|
type: "button",
|
|
@@ -8241,17 +8534,17 @@ function NodeDetailsPanel({
|
|
|
8241
8534
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8242
8535
|
title: "Editar descri\xE7\xE3o (Modo de Escrita)"
|
|
8243
8536
|
},
|
|
8244
|
-
/* @__PURE__ */
|
|
8245
|
-
)), canEdit && !description && /* @__PURE__ */
|
|
8537
|
+
/* @__PURE__ */ import_react17.default.createElement(import_fi15.FiEdit2, { size: 14 })
|
|
8538
|
+
)), canEdit && !description && /* @__PURE__ */ import_react17.default.createElement(
|
|
8246
8539
|
"div",
|
|
8247
8540
|
{
|
|
8248
8541
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8249
8542
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8250
8543
|
},
|
|
8251
8544
|
"Adicionar descri\xE7\xE3o..."
|
|
8252
|
-
))), /* @__PURE__ */
|
|
8545
|
+
))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Size"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
|
|
8253
8546
|
const isSelected = size === s;
|
|
8254
|
-
return /* @__PURE__ */
|
|
8547
|
+
return /* @__PURE__ */ import_react17.default.createElement(
|
|
8255
8548
|
"button",
|
|
8256
8549
|
{
|
|
8257
8550
|
key: s,
|
|
@@ -8259,10 +8552,10 @@ function NodeDetailsPanel({
|
|
|
8259
8552
|
onClick: () => canEdit && handleSizeChange(s),
|
|
8260
8553
|
className: `flex items-center gap-2 group focus:outline-none ${canEdit ? "cursor-pointer" : "cursor-default opacity-80"}`
|
|
8261
8554
|
},
|
|
8262
|
-
/* @__PURE__ */
|
|
8263
|
-
/* @__PURE__ */
|
|
8555
|
+
/* @__PURE__ */ import_react17.default.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${isSelected ? "bg-indigo-500 border-indigo-500 shadow-[0_0_10px_rgba(99,102,241,0.4)]" : "border-slate-600 bg-transparent " + (canEdit ? "group-hover:border-slate-500" : "")}` }, isSelected && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })),
|
|
8556
|
+
/* @__PURE__ */ import_react17.default.createElement("span", { className: `text-sm capitalize transition-colors ${isSelected ? "text-white font-medium" : "text-slate-400 " + (canEdit ? "group-hover:text-slate-300" : "")}` }, s)
|
|
8264
8557
|
);
|
|
8265
|
-
}))), /* @__PURE__ */
|
|
8558
|
+
}))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300" }, "Cor e Brilho"), canEdit && hasImages && /* @__PURE__ */ import_react17.default.createElement("label", { className: "flex items-center gap-2 cursor-pointer group" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: `w-4 h-4 rounded border flex items-center justify-center transition-colors ${useImageAsTexture ? "bg-indigo-500 border-indigo-500" : "border-slate-500 bg-transparent"}` }, useImageAsTexture && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiCheck, { size: 12, className: "text-white" })), /* @__PURE__ */ import_react17.default.createElement(
|
|
8266
8559
|
"input",
|
|
8267
8560
|
{
|
|
8268
8561
|
type: "checkbox",
|
|
@@ -8270,14 +8563,14 @@ function NodeDetailsPanel({
|
|
|
8270
8563
|
onChange: handleToggleImageMode,
|
|
8271
8564
|
className: "hidden"
|
|
8272
8565
|
}
|
|
8273
|
-
), /* @__PURE__ */
|
|
8566
|
+
), /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-xs ${useImageAsTexture ? "text-indigo-300" : "text-slate-400 group-hover:text-slate-300"}` }, "Usar imagem para representar o node"))), /* @__PURE__ */ import_react17.default.createElement(
|
|
8274
8567
|
ColorPicker,
|
|
8275
8568
|
{
|
|
8276
8569
|
color,
|
|
8277
8570
|
onChange: handleColorChange,
|
|
8278
8571
|
disabled: !canEdit || useImageAsTexture
|
|
8279
8572
|
}
|
|
8280
|
-
), /* @__PURE__ */
|
|
8573
|
+
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "mt-3 flex items-center gap-3" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiSun, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement(
|
|
8281
8574
|
"input",
|
|
8282
8575
|
{
|
|
8283
8576
|
type: "range",
|
|
@@ -8290,7 +8583,7 @@ function NodeDetailsPanel({
|
|
|
8290
8583
|
className: `w-full h-1.5 bg-slate-700 rounded-lg appearance-none ${canEdit ? "cursor-pointer accent-indigo-500 hover:accent-indigo-400" : "cursor-default accent-slate-500"}`,
|
|
8291
8584
|
title: `Intensidade do brilho: ${intensity}`
|
|
8292
8585
|
}
|
|
8293
|
-
), /* @__PURE__ */
|
|
8586
|
+
), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-xs text-slate-400 w-6 text-right" }, intensity)), /* @__PURE__ */ import_react17.default.createElement("span", { className: `text-xs block mt-1 transition-opacity ${useImageAsTexture ? "opacity-40" : "text-slate-400"}` }, useImageAsTexture ? "Cor da borda (definida pela imagem)" : "Ajuste a cor e a intensidade do brilho.")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react17.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react17.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react17.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react17.default.createElement(
|
|
8294
8587
|
CustomPropertyDisplay,
|
|
8295
8588
|
{
|
|
8296
8589
|
key: prop.id,
|
|
@@ -8305,7 +8598,7 @@ function NodeDetailsPanel({
|
|
|
8305
8598
|
onUploadFile: canEdit ? onUploadFile : void 0,
|
|
8306
8599
|
readOnly: !canEdit
|
|
8307
8600
|
}
|
|
8308
|
-
)), /* @__PURE__ */
|
|
8601
|
+
)), /* @__PURE__ */ import_react17.default.createElement("div", { ref: propsEndRef }))), currentDatasetName && /* @__PURE__ */ import_react17.default.createElement("div", { className: "pt-3 mt-4 border-t border-white/10 flex items-center justify-end gap-2 text-xs text-slate-400" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "truncate text-right" }, /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, currentDatasetName)))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react17.default.createElement("button", { onClick: handleCancel, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8309
8602
|
"button",
|
|
8310
8603
|
{
|
|
8311
8604
|
onClick: () => handleSave(false),
|
|
@@ -8314,10 +8607,10 @@ function NodeDetailsPanel({
|
|
|
8314
8607
|
${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-indigo-600 to-indigo-400 hover:from-indigo-500 hover:to-indigo-300 text-white"}
|
|
8315
8608
|
`
|
|
8316
8609
|
},
|
|
8317
|
-
isSaving && /* @__PURE__ */
|
|
8610
|
+
isSaving && /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiLoader, { className: "animate-spin" }),
|
|
8318
8611
|
isSaving ? "Salvando..." : "Salvar"
|
|
8319
8612
|
)))
|
|
8320
|
-
), isDescriptionModalOpen && canEdit && /* @__PURE__ */
|
|
8613
|
+
), isDescriptionModalOpen && canEdit && /* @__PURE__ */ import_react17.default.createElement(
|
|
8321
8614
|
DescriptionEditModal,
|
|
8322
8615
|
{
|
|
8323
8616
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8337,7 +8630,7 @@ function NodeDetailsPanel({
|
|
|
8337
8630
|
}
|
|
8338
8631
|
|
|
8339
8632
|
// src/components/MultiNodeContextMenu.jsx
|
|
8340
|
-
var
|
|
8633
|
+
var import_react18 = __toESM(require("react"));
|
|
8341
8634
|
function MultiNodeContextMenu({
|
|
8342
8635
|
data,
|
|
8343
8636
|
userRole,
|
|
@@ -8346,12 +8639,12 @@ function MultiNodeContextMenu({
|
|
|
8346
8639
|
onDismissOtherNodes,
|
|
8347
8640
|
onDeleteNodes
|
|
8348
8641
|
}) {
|
|
8349
|
-
const menuRef = (0,
|
|
8350
|
-
const [menuPos, setMenuPos] = (0,
|
|
8351
|
-
const [isConfirmingDelete, setIsConfirmingDelete] = (0,
|
|
8642
|
+
const menuRef = (0, import_react18.useRef)(null);
|
|
8643
|
+
const [menuPos, setMenuPos] = (0, import_react18.useState)({ left: 0, top: 0 });
|
|
8644
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react18.useState)(false);
|
|
8352
8645
|
const ability = defineAbilityFor(userRole);
|
|
8353
8646
|
const canDelete = ability.can("delete", "Node");
|
|
8354
|
-
(0,
|
|
8647
|
+
(0, import_react18.useLayoutEffect)(() => {
|
|
8355
8648
|
if (!data.visible || !menuRef.current) return;
|
|
8356
8649
|
const el = menuRef.current;
|
|
8357
8650
|
const w = el.clientWidth;
|
|
@@ -8364,7 +8657,7 @@ function MultiNodeContextMenu({
|
|
|
8364
8657
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
8365
8658
|
setMenuPos({ left, top });
|
|
8366
8659
|
}, [data]);
|
|
8367
|
-
(0,
|
|
8660
|
+
(0, import_react18.useEffect)(() => {
|
|
8368
8661
|
if (data.visible) {
|
|
8369
8662
|
setIsConfirmingDelete(false);
|
|
8370
8663
|
}
|
|
@@ -8379,7 +8672,7 @@ function MultiNodeContextMenu({
|
|
|
8379
8672
|
const baseButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-indigo-500/20 text-slate-200 hover:text-white transition-colors duration-150 truncate";
|
|
8380
8673
|
const deleteButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-red-500/25 text-red-400 hover:text-red-300 transition-colors duration-150 truncate";
|
|
8381
8674
|
const nodeCount = data.nodeIds.size;
|
|
8382
|
-
return /* @__PURE__ */
|
|
8675
|
+
return /* @__PURE__ */ import_react18.default.createElement(
|
|
8383
8676
|
"div",
|
|
8384
8677
|
{
|
|
8385
8678
|
ref: menuRef,
|
|
@@ -8393,28 +8686,28 @@ function MultiNodeContextMenu({
|
|
|
8393
8686
|
onContextMenu: swallow,
|
|
8394
8687
|
onDoubleClick: swallow
|
|
8395
8688
|
},
|
|
8396
|
-
/* @__PURE__ */
|
|
8397
|
-
/* @__PURE__ */
|
|
8689
|
+
/* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-indigo-400/0 via-indigo-400/70 to-indigo-400/0" }),
|
|
8690
|
+
/* @__PURE__ */ import_react18.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "w-10 h-10 rounded-full bg-red-500/20 flex items-center justify-center text-red-400 mb-1" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir ", /* @__PURE__ */ import_react18.default.createElement("strong", null, nodeCount, " Nodes"), "?"), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight" }, "Esta a\xE7\xE3o \xE9 irrevers\xEDvel. Todas as conex\xF5es associadas a eles ser\xE3o apagadas.")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react18.default.createElement(
|
|
8398
8691
|
"button",
|
|
8399
8692
|
{
|
|
8400
8693
|
onClick: () => setIsConfirmingDelete(false),
|
|
8401
8694
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8402
8695
|
},
|
|
8403
8696
|
"Cancelar"
|
|
8404
|
-
), /* @__PURE__ */
|
|
8697
|
+
), /* @__PURE__ */ import_react18.default.createElement(
|
|
8405
8698
|
"button",
|
|
8406
8699
|
{
|
|
8407
8700
|
onClick: () => onDeleteNodes(data.nodeIds),
|
|
8408
8701
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-red-500 hover:bg-red-600 rounded-md text-white transition-colors"
|
|
8409
8702
|
},
|
|
8410
8703
|
"Excluir"
|
|
8411
|
-
))) : /* @__PURE__ */
|
|
8704
|
+
))) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es em Grupo (", nodeCount, " Nodes)")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissNodes(data.nodeIds), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss (", nodeCount, ")")), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => onDismissOtherNodes(data.nodeIds), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Dismiss other nodes")), canDelete && /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: () => setIsConfirmingDelete(true), className: deleteButtonClass, title: "Excluir Nodes" }, /* @__PURE__ */ import_react18.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react18.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react18.default.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react18.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ import_react18.default.createElement("span", null, "Excluir Nodes (", nodeCount, ")"))))))
|
|
8412
8705
|
);
|
|
8413
8706
|
}
|
|
8414
8707
|
|
|
8415
8708
|
// src/components/RelationshipDetailsPanel.jsx
|
|
8416
|
-
var
|
|
8417
|
-
var
|
|
8709
|
+
var import_react19 = __toESM(require("react"));
|
|
8710
|
+
var import_fi16 = require("react-icons/fi");
|
|
8418
8711
|
function RelationshipDetailsPanel({
|
|
8419
8712
|
link,
|
|
8420
8713
|
onClose,
|
|
@@ -8428,19 +8721,19 @@ function RelationshipDetailsPanel({
|
|
|
8428
8721
|
onUploadFile,
|
|
8429
8722
|
userRole
|
|
8430
8723
|
}) {
|
|
8431
|
-
const [name, setName] = (0,
|
|
8432
|
-
const [description, setDescription] = (0,
|
|
8433
|
-
const [customProps, setCustomProps] = (0,
|
|
8434
|
-
const [existingSections, setExistingSections] = (0,
|
|
8435
|
-
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0,
|
|
8436
|
-
const [isSaving, setIsSaving] = (0,
|
|
8437
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
8438
|
-
const propsEndRef = (0,
|
|
8439
|
-
const canEdit = (0,
|
|
8724
|
+
const [name, setName] = (0, import_react19.useState)((link == null ? void 0 : link.name) ?? "");
|
|
8725
|
+
const [description, setDescription] = (0, import_react19.useState)((link == null ? void 0 : link.description) ?? "");
|
|
8726
|
+
const [customProps, setCustomProps] = (0, import_react19.useState)(() => extractCustomPropsFromNode(link || {}));
|
|
8727
|
+
const [existingSections, setExistingSections] = (0, import_react19.useState)((link == null ? void 0 : link.description_sections) || []);
|
|
8728
|
+
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react19.useState)(false);
|
|
8729
|
+
const [isSaving, setIsSaving] = (0, import_react19.useState)(false);
|
|
8730
|
+
const [isReadMode, setIsReadMode] = (0, import_react19.useState)(false);
|
|
8731
|
+
const propsEndRef = (0, import_react19.useRef)(null);
|
|
8732
|
+
const canEdit = (0, import_react19.useMemo)(() => {
|
|
8440
8733
|
const ability = defineAbilityFor(userRole);
|
|
8441
8734
|
return ability.can("update", "Connection");
|
|
8442
8735
|
}, [userRole]);
|
|
8443
|
-
(0,
|
|
8736
|
+
(0, import_react19.useEffect)(() => {
|
|
8444
8737
|
setName((link == null ? void 0 : link.name) ?? "");
|
|
8445
8738
|
setDescription((link == null ? void 0 : link.description) ?? "");
|
|
8446
8739
|
setExistingSections((link == null ? void 0 : link.description_sections) || []);
|
|
@@ -8515,7 +8808,7 @@ function RelationshipDetailsPanel({
|
|
|
8515
8808
|
onOpenImageViewer([{ name: name2 || "Imagem", value: url }], 0);
|
|
8516
8809
|
}
|
|
8517
8810
|
};
|
|
8518
|
-
return /* @__PURE__ */
|
|
8811
|
+
return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
|
|
8519
8812
|
"div",
|
|
8520
8813
|
{
|
|
8521
8814
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden transition-all duration-300 ease-out
|
|
@@ -8530,7 +8823,7 @@ function RelationshipDetailsPanel({
|
|
|
8530
8823
|
onContextMenu: swallow,
|
|
8531
8824
|
onDoubleClick: swallow
|
|
8532
8825
|
},
|
|
8533
|
-
isReadMode ? /* @__PURE__ */
|
|
8826
|
+
isReadMode ? /* @__PURE__ */ import_react19.default.createElement(
|
|
8534
8827
|
DescriptionReadModePanel,
|
|
8535
8828
|
{
|
|
8536
8829
|
title: name || "Rela\xE7\xE3o",
|
|
@@ -8551,7 +8844,7 @@ function RelationshipDetailsPanel({
|
|
|
8551
8844
|
onImageClick: handleImageClickFromText,
|
|
8552
8845
|
onSaveDescription: handleSaveDescriptionInline
|
|
8553
8846
|
}
|
|
8554
|
-
) : /* @__PURE__ */
|
|
8847
|
+
) : /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }), /* @__PURE__ */ import_react19.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("div", null, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-teal-400/80 shadow-[0_0_18px_2px_rgba(45,212,191,0.55)]" }), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, name || "Rela\xE7\xE3o")), /* @__PURE__ */ import_react19.default.createElement("button", { onClick: onClose, disabled: isSaving, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl disabled:opacity-50", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Rela\xE7\xE3o (Opcional)"), /* @__PURE__ */ import_react19.default.createElement(
|
|
8555
8848
|
"input",
|
|
8556
8849
|
{
|
|
8557
8850
|
type: "text",
|
|
@@ -8563,7 +8856,7 @@ function RelationshipDetailsPanel({
|
|
|
8563
8856
|
${!canEdit ? "opacity-50 cursor-not-allowed" : ""}
|
|
8564
8857
|
`
|
|
8565
8858
|
}
|
|
8566
|
-
)), /* @__PURE__ */
|
|
8859
|
+
)), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ import_react19.default.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "relative group min-h-[60px] bg-slate-800/40 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ import_react19.default.createElement(
|
|
8567
8860
|
DescriptionDisplay,
|
|
8568
8861
|
{
|
|
8569
8862
|
description,
|
|
@@ -8575,7 +8868,7 @@ function RelationshipDetailsPanel({
|
|
|
8575
8868
|
onImageClick: handleImageClickFromText,
|
|
8576
8869
|
onSaveDescription: handleSaveDescriptionInline
|
|
8577
8870
|
}
|
|
8578
|
-
), /* @__PURE__ */
|
|
8871
|
+
), /* @__PURE__ */ import_react19.default.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ import_react19.default.createElement(
|
|
8579
8872
|
"button",
|
|
8580
8873
|
{
|
|
8581
8874
|
type: "button",
|
|
@@ -8583,8 +8876,8 @@ function RelationshipDetailsPanel({
|
|
|
8583
8876
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors border-r border-white/5",
|
|
8584
8877
|
title: "Modo de Leitura"
|
|
8585
8878
|
},
|
|
8586
|
-
/* @__PURE__ */
|
|
8587
|
-
), canEdit && /* @__PURE__ */
|
|
8879
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi16.FiBookOpen, { size: 14 })
|
|
8880
|
+
), canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8588
8881
|
"button",
|
|
8589
8882
|
{
|
|
8590
8883
|
type: "button",
|
|
@@ -8592,15 +8885,15 @@ function RelationshipDetailsPanel({
|
|
|
8592
8885
|
className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8593
8886
|
title: "Editar descri\xE7\xE3o"
|
|
8594
8887
|
},
|
|
8595
|
-
/* @__PURE__ */
|
|
8596
|
-
)), !description && canEdit && /* @__PURE__ */
|
|
8888
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi16.FiEdit2, { size: 14 })
|
|
8889
|
+
)), !description && canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8597
8890
|
"div",
|
|
8598
8891
|
{
|
|
8599
8892
|
onClick: () => setIsDescriptionModalOpen(true),
|
|
8600
8893
|
className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text"
|
|
8601
8894
|
},
|
|
8602
8895
|
"Adicionar descri\xE7\xE3o..."
|
|
8603
|
-
))), /* @__PURE__ */
|
|
8896
|
+
))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), canEdit && /* @__PURE__ */ import_react19.default.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiPlus, { size: 14 }), " Adicionar")), /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, idx) => /* @__PURE__ */ import_react19.default.createElement(
|
|
8604
8897
|
CustomPropertyDisplay,
|
|
8605
8898
|
{
|
|
8606
8899
|
key: prop.id,
|
|
@@ -8612,7 +8905,7 @@ function RelationshipDetailsPanel({
|
|
|
8612
8905
|
onUploadFile,
|
|
8613
8906
|
disabled: !canEdit
|
|
8614
8907
|
}
|
|
8615
|
-
)), /* @__PURE__ */
|
|
8908
|
+
)), /* @__PURE__ */ import_react19.default.createElement("div", { ref: propsEndRef })))), /* @__PURE__ */ import_react19.default.createElement("div", { className: "sticky bottom-0 z-10 bg-gradient-to-t from-slate-950/80 via-slate-950/50 to-transparent px-6 py-4 border-t border-white/10 flex justify-end gap-3" }, /* @__PURE__ */ import_react19.default.createElement("button", { onClick: onClose, disabled: isSaving, className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm disabled:opacity-50" }, canEdit ? "Cancelar" : "Fechar"), canEdit && /* @__PURE__ */ import_react19.default.createElement(
|
|
8616
8909
|
"button",
|
|
8617
8910
|
{
|
|
8618
8911
|
onClick: () => handleSave(false),
|
|
@@ -8621,10 +8914,10 @@ function RelationshipDetailsPanel({
|
|
|
8621
8914
|
${isSaving ? "bg-slate-700 text-slate-300 cursor-wait" : "bg-gradient-to-tr from-teal-600 to-teal-400 hover:from-teal-500 hover:to-teal-300 text-white"}
|
|
8622
8915
|
`
|
|
8623
8916
|
},
|
|
8624
|
-
isSaving && /* @__PURE__ */
|
|
8917
|
+
isSaving && /* @__PURE__ */ import_react19.default.createElement(import_fi16.FiLoader, { className: "animate-spin" }),
|
|
8625
8918
|
isSaving ? "Salvando..." : "Salvar"
|
|
8626
8919
|
)))
|
|
8627
|
-
), isDescriptionModalOpen && /* @__PURE__ */
|
|
8920
|
+
), isDescriptionModalOpen && /* @__PURE__ */ import_react19.default.createElement(
|
|
8628
8921
|
DescriptionEditModal,
|
|
8629
8922
|
{
|
|
8630
8923
|
isOpen: isDescriptionModalOpen,
|
|
@@ -8645,7 +8938,7 @@ function RelationshipDetailsPanel({
|
|
|
8645
8938
|
}
|
|
8646
8939
|
|
|
8647
8940
|
// src/components/RelationshipContextMenu.jsx
|
|
8648
|
-
var
|
|
8941
|
+
var import_react20 = __toESM(require("react"));
|
|
8649
8942
|
function RelationshipContextMenu({
|
|
8650
8943
|
data,
|
|
8651
8944
|
userRole,
|
|
@@ -8655,25 +8948,25 @@ function RelationshipContextMenu({
|
|
|
8655
8948
|
onDelete,
|
|
8656
8949
|
onClose
|
|
8657
8950
|
}) {
|
|
8658
|
-
const menuRef = (0,
|
|
8659
|
-
const [menuPos, setMenuPos] = (0,
|
|
8660
|
-
const [isConfirmingDelete, setIsConfirmingDelete] = (0,
|
|
8661
|
-
const ability = (0,
|
|
8662
|
-
const sourceName = (0,
|
|
8951
|
+
const menuRef = (0, import_react20.useRef)(null);
|
|
8952
|
+
const [menuPos, setMenuPos] = (0, import_react20.useState)({ left: 0, top: 0 });
|
|
8953
|
+
const [isConfirmingDelete, setIsConfirmingDelete] = (0, import_react20.useState)(false);
|
|
8954
|
+
const ability = (0, import_react20.useMemo)(() => defineAbilityFor(userRole), [userRole]);
|
|
8955
|
+
const sourceName = (0, import_react20.useMemo)(
|
|
8663
8956
|
() => {
|
|
8664
8957
|
var _a, _b, _c, _d;
|
|
8665
8958
|
return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.sourceNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
|
|
8666
8959
|
},
|
|
8667
8960
|
[data == null ? void 0 : data.linkObject]
|
|
8668
8961
|
);
|
|
8669
|
-
const targetName = (0,
|
|
8962
|
+
const targetName = (0, import_react20.useMemo)(
|
|
8670
8963
|
() => {
|
|
8671
8964
|
var _a, _b, _c, _d;
|
|
8672
8965
|
return ((_d = (_c = (_b = (_a = data == null ? void 0 : data.linkObject) == null ? void 0 : _a.userData) == null ? void 0 : _b.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) ?? "(sem nome)";
|
|
8673
8966
|
},
|
|
8674
8967
|
[data == null ? void 0 : data.linkObject]
|
|
8675
8968
|
);
|
|
8676
|
-
(0,
|
|
8969
|
+
(0, import_react20.useLayoutEffect)(() => {
|
|
8677
8970
|
if (!data.visible || !menuRef.current) return;
|
|
8678
8971
|
const el = menuRef.current;
|
|
8679
8972
|
const w = el.clientWidth;
|
|
@@ -8686,7 +8979,7 @@ function RelationshipContextMenu({
|
|
|
8686
8979
|
if (top + h + 8 > vh) top = Math.max(8, vh - h - 8);
|
|
8687
8980
|
setMenuPos({ left, top });
|
|
8688
8981
|
}, [data]);
|
|
8689
|
-
(0,
|
|
8982
|
+
(0, import_react20.useEffect)(() => {
|
|
8690
8983
|
if (data.visible) {
|
|
8691
8984
|
setIsConfirmingDelete(false);
|
|
8692
8985
|
}
|
|
@@ -8702,7 +8995,7 @@ function RelationshipContextMenu({
|
|
|
8702
8995
|
const dangerButtonClass = "w-full flex items-center gap-2.5 px-2 py-1.5 text-left text-sm rounded-md hover:bg-rose-500/20 text-rose-300 hover:text-rose-100 transition-colors duration-150 truncate";
|
|
8703
8996
|
const canUpdate = ability.can("update", "Connection");
|
|
8704
8997
|
const canDelete = ability.can("delete", "Connection");
|
|
8705
|
-
return /* @__PURE__ */
|
|
8998
|
+
return /* @__PURE__ */ import_react20.default.createElement(
|
|
8706
8999
|
"div",
|
|
8707
9000
|
{
|
|
8708
9001
|
ref: menuRef,
|
|
@@ -8716,29 +9009,29 @@ function RelationshipContextMenu({
|
|
|
8716
9009
|
onContextMenu: swallow,
|
|
8717
9010
|
onDoubleClick: swallow
|
|
8718
9011
|
},
|
|
8719
|
-
/* @__PURE__ */
|
|
8720
|
-
/* @__PURE__ */
|
|
9012
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-teal-400/0 via-teal-400/70 to-teal-400/0" }),
|
|
9013
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "p-1.5" }, isConfirmingDelete ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-3 p-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col items-center text-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "w-10 h-10 rounded-full bg-rose-500/20 flex items-center justify-center text-rose-400 mb-1" }, /* @__PURE__ */ import_react20.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" }))), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-sm text-slate-200" }, "Excluir rela\xE7\xE3o?"), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[11px] text-slate-400 leading-tight break-words" }, "Desconectar ", /* @__PURE__ */ import_react20.default.createElement("strong", null, sourceName), " de ", /* @__PURE__ */ import_react20.default.createElement("strong", null, targetName), ".")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex gap-2 mt-1" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
8721
9014
|
"button",
|
|
8722
9015
|
{
|
|
8723
9016
|
onClick: () => setIsConfirmingDelete(false),
|
|
8724
9017
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-white/10 hover:bg-white/20 rounded-md text-white transition-colors"
|
|
8725
9018
|
},
|
|
8726
9019
|
"Cancelar"
|
|
8727
|
-
), /* @__PURE__ */
|
|
9020
|
+
), /* @__PURE__ */ import_react20.default.createElement(
|
|
8728
9021
|
"button",
|
|
8729
9022
|
{
|
|
8730
9023
|
onClick: () => onDelete == null ? void 0 : onDelete(data.linkObject),
|
|
8731
9024
|
className: "flex-1 px-2 py-2 text-xs font-medium bg-rose-600 hover:bg-rose-500 rounded-md text-white transition-colors"
|
|
8732
9025
|
},
|
|
8733
9026
|
"Excluir"
|
|
8734
|
-
))) : /* @__PURE__ */
|
|
9027
|
+
))) : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-teal-400/80 shadow-[0_0_12px_1px_rgba(45,212,191,0.5)]" }), /* @__PURE__ */ import_react20.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Rela\xE7\xE3o")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col gap-1" }, canUpdate && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement(
|
|
8735
9028
|
"button",
|
|
8736
9029
|
{
|
|
8737
9030
|
onClick: () => onRelinkSource == null ? void 0 : onRelinkSource(data.linkObject),
|
|
8738
9031
|
className: baseButtonClass,
|
|
8739
9032
|
title: "Desconectar ponta ligada ao Source"
|
|
8740
9033
|
},
|
|
8741
|
-
/* @__PURE__ */
|
|
9034
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8742
9035
|
"svg",
|
|
8743
9036
|
{
|
|
8744
9037
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8751,18 +9044,18 @@ function RelationshipContextMenu({
|
|
|
8751
9044
|
strokeLinecap: "round",
|
|
8752
9045
|
strokeLinejoin: "round"
|
|
8753
9046
|
},
|
|
8754
|
-
/* @__PURE__ */
|
|
8755
|
-
/* @__PURE__ */
|
|
9047
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }),
|
|
9048
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })
|
|
8756
9049
|
),
|
|
8757
|
-
/* @__PURE__ */
|
|
8758
|
-
), /* @__PURE__ */
|
|
9050
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Source (", sourceName, ")")
|
|
9051
|
+
), /* @__PURE__ */ import_react20.default.createElement(
|
|
8759
9052
|
"button",
|
|
8760
9053
|
{
|
|
8761
9054
|
onClick: () => onRelinkTarget == null ? void 0 : onRelinkTarget(data.linkObject),
|
|
8762
9055
|
className: baseButtonClass,
|
|
8763
9056
|
title: "Desconectar ponta ligada ao Target"
|
|
8764
9057
|
},
|
|
8765
|
-
/* @__PURE__ */
|
|
9058
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8766
9059
|
"svg",
|
|
8767
9060
|
{
|
|
8768
9061
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8775,21 +9068,21 @@ function RelationshipContextMenu({
|
|
|
8775
9068
|
strokeLinecap: "round",
|
|
8776
9069
|
strokeLinejoin: "round"
|
|
8777
9070
|
},
|
|
8778
|
-
/* @__PURE__ */
|
|
8779
|
-
/* @__PURE__ */
|
|
8780
|
-
/* @__PURE__ */
|
|
8781
|
-
/* @__PURE__ */
|
|
8782
|
-
/* @__PURE__ */
|
|
9071
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "16 3 21 3 21 8" }),
|
|
9072
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "20", x2: "21", y2: "3" }),
|
|
9073
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "21 16 21 21 16 21" }),
|
|
9074
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "15", y1: "15", x2: "21", y2: "21" }),
|
|
9075
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "4", y1: "4", x2: "9", y2: "9" })
|
|
8783
9076
|
),
|
|
8784
|
-
/* @__PURE__ */
|
|
8785
|
-
), /* @__PURE__ */
|
|
9077
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Desconectar Target (", targetName, ")")
|
|
9078
|
+
), /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" })), /* @__PURE__ */ import_react20.default.createElement(
|
|
8786
9079
|
"button",
|
|
8787
9080
|
{
|
|
8788
9081
|
onClick: () => onOpenDetails == null ? void 0 : onOpenDetails(data.linkObject),
|
|
8789
9082
|
className: baseButtonClass,
|
|
8790
9083
|
title: "Abrir detalhes da rela\xE7\xE3o"
|
|
8791
9084
|
},
|
|
8792
|
-
/* @__PURE__ */
|
|
9085
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8793
9086
|
"svg",
|
|
8794
9087
|
{
|
|
8795
9088
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8802,19 +9095,19 @@ function RelationshipContextMenu({
|
|
|
8802
9095
|
strokeLinecap: "round",
|
|
8803
9096
|
strokeLinejoin: "round"
|
|
8804
9097
|
},
|
|
8805
|
-
/* @__PURE__ */
|
|
8806
|
-
/* @__PURE__ */
|
|
8807
|
-
/* @__PURE__ */
|
|
9098
|
+
/* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
9099
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
9100
|
+
/* @__PURE__ */ import_react20.default.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "8" })
|
|
8808
9101
|
),
|
|
8809
|
-
/* @__PURE__ */
|
|
8810
|
-
), canDelete && /* @__PURE__ */
|
|
9102
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Abrir Detalhes")
|
|
9103
|
+
), canDelete && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-[1px] my-1 mx-1 bg-white/10" }), /* @__PURE__ */ import_react20.default.createElement(
|
|
8811
9104
|
"button",
|
|
8812
9105
|
{
|
|
8813
9106
|
onClick: () => setIsConfirmingDelete(true),
|
|
8814
9107
|
className: dangerButtonClass,
|
|
8815
9108
|
title: "Excluir esta conex\xE3o"
|
|
8816
9109
|
},
|
|
8817
|
-
/* @__PURE__ */
|
|
9110
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
8818
9111
|
"svg",
|
|
8819
9112
|
{
|
|
8820
9113
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -8827,19 +9120,19 @@ function RelationshipContextMenu({
|
|
|
8827
9120
|
strokeLinecap: "round",
|
|
8828
9121
|
strokeLinejoin: "round"
|
|
8829
9122
|
},
|
|
8830
|
-
/* @__PURE__ */
|
|
8831
|
-
/* @__PURE__ */
|
|
8832
|
-
/* @__PURE__ */
|
|
8833
|
-
/* @__PURE__ */
|
|
8834
|
-
/* @__PURE__ */
|
|
9123
|
+
/* @__PURE__ */ import_react20.default.createElement("polyline", { points: "3 6 5 6 21 6" }),
|
|
9124
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
|
|
9125
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M10 11v6" }),
|
|
9126
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M14 11v6" }),
|
|
9127
|
+
/* @__PURE__ */ import_react20.default.createElement("path", { d: "M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" })
|
|
8835
9128
|
),
|
|
8836
|
-
/* @__PURE__ */
|
|
9129
|
+
/* @__PURE__ */ import_react20.default.createElement("span", null, "Excluir conex\xE3o (", sourceName, " \u2192 ", targetName, ")")
|
|
8837
9130
|
)))))
|
|
8838
9131
|
);
|
|
8839
9132
|
}
|
|
8840
9133
|
|
|
8841
9134
|
// src/components/LoadingScreen.jsx
|
|
8842
|
-
var
|
|
9135
|
+
var import_react21 = __toESM(require("react"));
|
|
8843
9136
|
var styles = {
|
|
8844
9137
|
loadingOverlay: {
|
|
8845
9138
|
position: "fixed",
|
|
@@ -8871,11 +9164,11 @@ var styles = {
|
|
|
8871
9164
|
`
|
|
8872
9165
|
};
|
|
8873
9166
|
function LoadingScreen() {
|
|
8874
|
-
return /* @__PURE__ */
|
|
9167
|
+
return /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement("style", null, styles.keyframes), /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.loadingOverlay }, /* @__PURE__ */ import_react21.default.createElement("div", { style: styles.spinner })));
|
|
8875
9168
|
}
|
|
8876
9169
|
|
|
8877
9170
|
// src/components/ImportParentFileModal.jsx
|
|
8878
|
-
var
|
|
9171
|
+
var import_react22 = __toESM(require("react"));
|
|
8879
9172
|
function ImportParentFileModal({
|
|
8880
9173
|
isOpen,
|
|
8881
9174
|
onClose,
|
|
@@ -8886,12 +9179,12 @@ function ImportParentFileModal({
|
|
|
8886
9179
|
onFetchAvailableFiles,
|
|
8887
9180
|
currentViewName
|
|
8888
9181
|
}) {
|
|
8889
|
-
const [activeTab, setActiveTab] = (0,
|
|
8890
|
-
const [availableDbs, setAvailableDbs] = (0,
|
|
8891
|
-
const [availableViews, setAvailableViews] = (0,
|
|
8892
|
-
const [selectedItem, setSelectedItem] = (0,
|
|
8893
|
-
const [isLoading, setIsLoading] = (0,
|
|
8894
|
-
(0,
|
|
9182
|
+
const [activeTab, setActiveTab] = (0, import_react22.useState)("databases");
|
|
9183
|
+
const [availableDbs, setAvailableDbs] = (0, import_react22.useState)([]);
|
|
9184
|
+
const [availableViews, setAvailableViews] = (0, import_react22.useState)([]);
|
|
9185
|
+
const [selectedItem, setSelectedItem] = (0, import_react22.useState)(null);
|
|
9186
|
+
const [isLoading, setIsLoading] = (0, import_react22.useState)(false);
|
|
9187
|
+
(0, import_react22.useEffect)(() => {
|
|
8895
9188
|
if (isOpen && session && onFetchAvailableFiles) {
|
|
8896
9189
|
const fetchData = async () => {
|
|
8897
9190
|
setIsLoading(true);
|
|
@@ -8927,7 +9220,7 @@ function ImportParentFileModal({
|
|
|
8927
9220
|
fetchData();
|
|
8928
9221
|
}
|
|
8929
9222
|
}, [isOpen, session, parentDbs, onFetchAvailableFiles, currentViewName]);
|
|
8930
|
-
(0,
|
|
9223
|
+
(0, import_react22.useEffect)(() => {
|
|
8931
9224
|
setSelectedItem(null);
|
|
8932
9225
|
}, [activeTab]);
|
|
8933
9226
|
if (!isOpen) {
|
|
@@ -8956,13 +9249,13 @@ function ImportParentFileModal({
|
|
|
8956
9249
|
const swallow = (e) => e.stopPropagation();
|
|
8957
9250
|
const currentList = activeTab === "databases" ? availableDbs : availableViews;
|
|
8958
9251
|
const emptyMessage = activeTab === "databases" ? "Nenhum novo arquivo parent dispon\xEDvel." : "Nenhuma view dispon\xEDvel para importa\xE7\xE3o.";
|
|
8959
|
-
return /* @__PURE__ */
|
|
9252
|
+
return /* @__PURE__ */ import_react22.default.createElement(
|
|
8960
9253
|
"div",
|
|
8961
9254
|
{
|
|
8962
9255
|
className: "ui-overlay fixed inset-0 z-[1200] flex items-center justify-center bg-black/60 backdrop-blur-sm",
|
|
8963
9256
|
onClick: onClose
|
|
8964
9257
|
},
|
|
8965
|
-
/* @__PURE__ */
|
|
9258
|
+
/* @__PURE__ */ import_react22.default.createElement(
|
|
8966
9259
|
"div",
|
|
8967
9260
|
{
|
|
8968
9261
|
className: "ui-overlay relative rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] text-white w-[min(92vw,500px)] flex flex-col max-h-[85vh]",
|
|
@@ -8974,14 +9267,14 @@ function ImportParentFileModal({
|
|
|
8974
9267
|
onContextMenu: swallow,
|
|
8975
9268
|
onDoubleClick: swallow
|
|
8976
9269
|
},
|
|
8977
|
-
/* @__PURE__ */
|
|
9270
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-white/10 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement("h2", { className: "text-lg font-semibold" }, "Importar"), /* @__PURE__ */ import_react22.default.createElement(
|
|
8978
9271
|
"button",
|
|
8979
9272
|
{
|
|
8980
9273
|
onClick: onClose,
|
|
8981
9274
|
className: "p-2 rounded-md text-slate-400 hover:text-white hover:bg-white/10 transition-colors",
|
|
8982
9275
|
title: "Fechar"
|
|
8983
9276
|
},
|
|
8984
|
-
/* @__PURE__ */
|
|
9277
|
+
/* @__PURE__ */ import_react22.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
8985
9278
|
"path",
|
|
8986
9279
|
{
|
|
8987
9280
|
fillRule: "evenodd",
|
|
@@ -8990,14 +9283,14 @@ function ImportParentFileModal({
|
|
|
8990
9283
|
}
|
|
8991
9284
|
))
|
|
8992
9285
|
)),
|
|
8993
|
-
/* @__PURE__ */
|
|
9286
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex px-6 border-b border-white/10 bg-white/5 flex-shrink-0" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
8994
9287
|
"button",
|
|
8995
9288
|
{
|
|
8996
9289
|
onClick: () => setActiveTab("databases"),
|
|
8997
9290
|
className: `flex-1 py-3 text-sm font-medium border-b-2 transition-colors ${activeTab === "databases" ? "border-indigo-500 text-white" : "border-transparent text-slate-400 hover:text-slate-200"}`
|
|
8998
9291
|
},
|
|
8999
9292
|
"Arquivos Parent"
|
|
9000
|
-
), /* @__PURE__ */
|
|
9293
|
+
), /* @__PURE__ */ import_react22.default.createElement(
|
|
9001
9294
|
"button",
|
|
9002
9295
|
{
|
|
9003
9296
|
onClick: () => setActiveTab("views"),
|
|
@@ -9005,24 +9298,24 @@ function ImportParentFileModal({
|
|
|
9005
9298
|
},
|
|
9006
9299
|
"Views (Ancestralidades)"
|
|
9007
9300
|
)),
|
|
9008
|
-
/* @__PURE__ */
|
|
9301
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "p-6 overflow-y-auto custom-scrollbar flex-grow min-h-[200px]" }, isLoading ? /* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-center h-40" }, /* @__PURE__ */ import_react22.default.createElement("div", { className: "w-8 h-8 border-4 border-t-indigo-500 border-slate-700 rounded-full animate-spin" })) : /* @__PURE__ */ import_react22.default.createElement("div", { className: "space-y-2" }, currentList.length > 0 ? currentList.map((item) => /* @__PURE__ */ import_react22.default.createElement(
|
|
9009
9302
|
"div",
|
|
9010
9303
|
{
|
|
9011
9304
|
key: item.id,
|
|
9012
9305
|
onClick: () => setSelectedItem(item),
|
|
9013
9306
|
className: `px-4 py-3 rounded-lg border cursor-pointer transition-all duration-150 flex flex-col gap-1 ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "bg-indigo-600 border-indigo-500 shadow-lg" : "bg-slate-800/60 border-white/10 hover:border-white/20 hover:bg-slate-800"}`
|
|
9014
9307
|
},
|
|
9015
|
-
/* @__PURE__ */
|
|
9016
|
-
item.description && /* @__PURE__ */
|
|
9017
|
-
)) : /* @__PURE__ */
|
|
9018
|
-
/* @__PURE__ */
|
|
9308
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react22.default.createElement("span", { className: "font-medium text-slate-100" }, item.name), activeTab === "views" && /* @__PURE__ */ import_react22.default.createElement("span", { className: "text-[10px] px-1.5 py-0.5 rounded bg-black/30 text-indigo-300 border border-indigo-500/30" }, "VIEW")),
|
|
9309
|
+
item.description && /* @__PURE__ */ import_react22.default.createElement("p", { className: `text-xs ${(selectedItem == null ? void 0 : selectedItem.id) === item.id ? "text-indigo-200" : "text-slate-400"}` }, item.description)
|
|
9310
|
+
)) : /* @__PURE__ */ import_react22.default.createElement("p", { className: "text-slate-400 text-center py-10" }, emptyMessage))),
|
|
9311
|
+
/* @__PURE__ */ import_react22.default.createElement("div", { className: "px-6 py-4 border-t border-white/10 flex justify-end gap-3 flex-shrink-0 bg-slate-900/50" }, /* @__PURE__ */ import_react22.default.createElement(
|
|
9019
9312
|
"button",
|
|
9020
9313
|
{
|
|
9021
9314
|
onClick: onClose,
|
|
9022
9315
|
className: "px-4 py-2 rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-sm text-slate-300"
|
|
9023
9316
|
},
|
|
9024
9317
|
"Cancelar"
|
|
9025
|
-
), /* @__PURE__ */
|
|
9318
|
+
), /* @__PURE__ */ import_react22.default.createElement(
|
|
9026
9319
|
"button",
|
|
9027
9320
|
{
|
|
9028
9321
|
onClick: handleConfirm,
|
|
@@ -9036,8 +9329,8 @@ function ImportParentFileModal({
|
|
|
9036
9329
|
}
|
|
9037
9330
|
|
|
9038
9331
|
// src/components/AncestryLinkDetailsPanel.jsx
|
|
9039
|
-
var
|
|
9040
|
-
var
|
|
9332
|
+
var import_react23 = __toESM(require("react"));
|
|
9333
|
+
var import_fi17 = require("react-icons/fi");
|
|
9041
9334
|
function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenReference, onMentionClick, onUploadFile }) {
|
|
9042
9335
|
var _a, _b, _c, _d;
|
|
9043
9336
|
const relationshipData = data.relationship || {};
|
|
@@ -9046,21 +9339,21 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9046
9339
|
const customProps = extractCustomPropsFromNode(relationshipData);
|
|
9047
9340
|
const sourceName = ((_b = (_a = data.sourceNode) == null ? void 0 : _a.userData) == null ? void 0 : _b.name) || "Origem";
|
|
9048
9341
|
const targetName = ((_d = (_c = data.targetNode) == null ? void 0 : _c.userData) == null ? void 0 : _d.name) || "Destino";
|
|
9049
|
-
const [isReadMode, setIsReadMode] = (0,
|
|
9342
|
+
const [isReadMode, setIsReadMode] = (0, import_react23.useState)(false);
|
|
9050
9343
|
const swallow = (e) => e.stopPropagation();
|
|
9051
9344
|
const handleImageClickFromText = (url, name) => {
|
|
9052
9345
|
if (onOpenImageViewer) {
|
|
9053
9346
|
onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
|
|
9054
9347
|
}
|
|
9055
9348
|
};
|
|
9056
|
-
return /* @__PURE__ */
|
|
9349
|
+
return /* @__PURE__ */ import_react23.default.createElement(
|
|
9057
9350
|
"div",
|
|
9058
9351
|
{
|
|
9059
9352
|
className: "ui-overlay fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-[1200]",
|
|
9060
9353
|
onClick: onClose,
|
|
9061
9354
|
onPointerDown: swallow
|
|
9062
9355
|
},
|
|
9063
|
-
/* @__PURE__ */
|
|
9356
|
+
/* @__PURE__ */ import_react23.default.createElement(
|
|
9064
9357
|
"div",
|
|
9065
9358
|
{
|
|
9066
9359
|
className: `relative group rounded-2xl border border-white/10 bg-slate-950/80 shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col max-h-[calc(100vh-4rem)] transition-all duration-300 ease-out
|
|
@@ -9068,7 +9361,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9068
9361
|
`,
|
|
9069
9362
|
onClick: swallow
|
|
9070
9363
|
},
|
|
9071
|
-
isReadMode ? /* @__PURE__ */
|
|
9364
|
+
isReadMode ? /* @__PURE__ */ import_react23.default.createElement(
|
|
9072
9365
|
DescriptionReadModePanel,
|
|
9073
9366
|
{
|
|
9074
9367
|
title: `${sourceName} \u2794 ${targetName}`,
|
|
@@ -9080,15 +9373,15 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9080
9373
|
onMentionClick,
|
|
9081
9374
|
onImageClick: handleImageClickFromText
|
|
9082
9375
|
}
|
|
9083
|
-
) : /* @__PURE__ */
|
|
9376
|
+
) : /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "h-[2px] bg-gradient-to-r from-blue-500/0 via-blue-500/70 to-blue-500/0" }), /* @__PURE__ */ import_react23.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react23.default.createElement("div", null, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react23.default.createElement("span", { className: "inline-flex h-2.5 w-2.5 rounded-full bg-blue-500/80 shadow-[0_0_18px_2px_rgba(59,130,246,0.55)]" }), /* @__PURE__ */ import_react23.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Ancestralidade")), /* @__PURE__ */ import_react23.default.createElement("h2", { className: "text-lg font-semibold tracking-tight flex items-center gap-2" }, /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, sourceName), /* @__PURE__ */ import_react23.default.createElement("span", { className: "text-slate-500 text-sm" }, "\u2794"), /* @__PURE__ */ import_react23.default.createElement("span", { className: "truncate max-w-[150px]" }, targetName))), /* @__PURE__ */ import_react23.default.createElement("button", { onClick: onClose, className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl", title: "Fechar" }, "\xD7")), /* @__PURE__ */ import_react23.default.createElement("div", { className: "px-6 pb-6 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, description && /* @__PURE__ */ import_react23.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium" }, "Descri\xE7\xE3o"), /* @__PURE__ */ import_react23.default.createElement(
|
|
9084
9377
|
"button",
|
|
9085
9378
|
{
|
|
9086
9379
|
onClick: () => setIsReadMode(true),
|
|
9087
9380
|
className: "p-1 text-slate-400 hover:text-white transition-colors",
|
|
9088
9381
|
title: "Modo de Leitura"
|
|
9089
9382
|
},
|
|
9090
|
-
/* @__PURE__ */
|
|
9091
|
-
)), /* @__PURE__ */
|
|
9383
|
+
/* @__PURE__ */ import_react23.default.createElement(import_fi17.FiBookOpen, { size: 14 })
|
|
9384
|
+
)), /* @__PURE__ */ import_react23.default.createElement("div", { className: "bg-slate-800/40 rounded-lg border border-white/10 p-1 relative group" }, /* @__PURE__ */ import_react23.default.createElement(
|
|
9092
9385
|
DescriptionDisplay,
|
|
9093
9386
|
{
|
|
9094
9387
|
description,
|
|
@@ -9097,7 +9390,7 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9097
9390
|
onMentionClick,
|
|
9098
9391
|
onImageClick: handleImageClickFromText
|
|
9099
9392
|
}
|
|
9100
|
-
))), customProps.length > 0 && /* @__PURE__ */
|
|
9393
|
+
))), customProps.length > 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "pt-2" }, /* @__PURE__ */ import_react23.default.createElement("label", { className: "text-xs text-slate-300 font-medium mb-2 block" }, "Propriedades"), /* @__PURE__ */ import_react23.default.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop) => /* @__PURE__ */ import_react23.default.createElement(
|
|
9101
9394
|
CustomPropertyDisplay,
|
|
9102
9395
|
{
|
|
9103
9396
|
key: prop.id,
|
|
@@ -9106,14 +9399,14 @@ function AncestryLinkDetailsPanel({ data, onClose, onOpenImageViewer, onOpenRefe
|
|
|
9106
9399
|
onOpenImageViewer,
|
|
9107
9400
|
onUploadFile
|
|
9108
9401
|
}
|
|
9109
|
-
)))), !description && customProps.length === 0 && /* @__PURE__ */
|
|
9402
|
+
)))), !description && customProps.length === 0 && /* @__PURE__ */ import_react23.default.createElement("div", { className: "py-8 text-center text-slate-500 text-sm italic border border-dashed border-white/10 rounded-lg" }, "Nenhum detalhe adicional dispon\xEDvel para esta conex\xE3o."), /* @__PURE__ */ import_react23.default.createElement("div", { className: "mt-4 p-3 bg-blue-500/10 border border-blue-500/20 rounded-lg text-xs text-blue-200/80 text-center" }, 'Para editar esta conex\xE3o, utilize o menu "Editar Ancestralidade".')))
|
|
9110
9403
|
)
|
|
9111
9404
|
);
|
|
9112
9405
|
}
|
|
9113
9406
|
|
|
9114
9407
|
// src/components/AncestryBoard.jsx
|
|
9115
|
-
var
|
|
9116
|
-
var
|
|
9408
|
+
var import_react24 = __toESM(require("react"));
|
|
9409
|
+
var import_fi18 = require("react-icons/fi");
|
|
9117
9410
|
var GroupItem = ({
|
|
9118
9411
|
group,
|
|
9119
9412
|
index,
|
|
@@ -9133,7 +9426,7 @@ var GroupItem = ({
|
|
|
9133
9426
|
}) => {
|
|
9134
9427
|
const canIndent = index > 0;
|
|
9135
9428
|
const isPickingForThisGroup = pickingGroupId === group.id;
|
|
9136
|
-
const textareaRef = (0,
|
|
9429
|
+
const textareaRef = (0, import_react24.useRef)(null);
|
|
9137
9430
|
const adjustHeight = () => {
|
|
9138
9431
|
const textarea = textareaRef.current;
|
|
9139
9432
|
if (textarea) {
|
|
@@ -9141,13 +9434,13 @@ var GroupItem = ({
|
|
|
9141
9434
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
9142
9435
|
}
|
|
9143
9436
|
};
|
|
9144
|
-
(0,
|
|
9437
|
+
(0, import_react24.useEffect)(() => {
|
|
9145
9438
|
adjustHeight();
|
|
9146
9439
|
}, [group.text]);
|
|
9147
|
-
return /* @__PURE__ */
|
|
9440
|
+
return /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col gap-2 mb-3 pl-3 border-l border-white/10 relative group/item animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "absolute -left-[1px] top-4 w-2 h-px bg-white/20" }), /* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9148
9441
|
flex flex-col gap-2 py-2 px-3 transition-all duration-200
|
|
9149
9442
|
${isPickingForThisGroup ? "bg-indigo-500/10 border-l-2 border-indigo-500" : "hover:bg-white/5 border-l-2 border-transparent hover:border-white/20"}
|
|
9150
|
-
` }, /* @__PURE__ */
|
|
9443
|
+
` }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9151
9444
|
"textarea",
|
|
9152
9445
|
{
|
|
9153
9446
|
ref: textareaRef,
|
|
@@ -9164,9 +9457,9 @@ var GroupItem = ({
|
|
|
9164
9457
|
if (canEdit) onUpdate(group.id, { ...group, text: e.target.value });
|
|
9165
9458
|
}
|
|
9166
9459
|
}
|
|
9167
|
-
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */
|
|
9460
|
+
), group.ancestries && group.ancestries.length > 0 && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-wrap gap-2 mt-1" }, group.ancestries.map((anc) => {
|
|
9168
9461
|
const isValid = availableIds.has(String(anc.ancestry_id));
|
|
9169
|
-
return /* @__PURE__ */
|
|
9462
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9170
9463
|
"div",
|
|
9171
9464
|
{
|
|
9172
9465
|
key: anc.ancestry_id,
|
|
@@ -9178,28 +9471,28 @@ var GroupItem = ({
|
|
|
9178
9471
|
},
|
|
9179
9472
|
isValid ? (
|
|
9180
9473
|
// [MANTIDO] Botão Play visível para todos
|
|
9181
|
-
/* @__PURE__ */
|
|
9474
|
+
/* @__PURE__ */ import_react24.default.createElement(
|
|
9182
9475
|
"button",
|
|
9183
9476
|
{
|
|
9184
9477
|
onClick: () => onPlayAncestry(anc.ancestry_id),
|
|
9185
9478
|
className: "text-indigo-400 hover:text-white hover:bg-indigo-500 p-1 rounded-full transition-colors",
|
|
9186
9479
|
title: "Renderizar no cen\xE1rio"
|
|
9187
9480
|
},
|
|
9188
|
-
/* @__PURE__ */
|
|
9481
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 10, className: "ml-0.5 fill-current" })
|
|
9189
9482
|
)
|
|
9190
|
-
) : /* @__PURE__ */
|
|
9191
|
-
/* @__PURE__ */
|
|
9192
|
-
canEdit && /* @__PURE__ */
|
|
9483
|
+
) : /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-1 text-red-500 cursor-not-allowed" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiAlertTriangle, { size: 10 })),
|
|
9484
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: `font-medium truncate max-w-[150px] ${!isValid && "line-through decoration-red-500/50"}` }, anc.name),
|
|
9485
|
+
canEdit && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("div", { className: `w-px h-3 mx-0.5 ${isValid ? "bg-white/10" : "bg-red-500/20"}` }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9193
9486
|
"button",
|
|
9194
9487
|
{
|
|
9195
9488
|
onClick: () => onRemoveAncestry(group.id, anc.ancestry_id),
|
|
9196
9489
|
className: `${isValid ? "text-slate-500 hover:text-red-400" : "text-red-400 hover:text-red-200"} p-0.5 rounded transition-colors`,
|
|
9197
9490
|
title: "Remover men\xE7\xE3o"
|
|
9198
9491
|
},
|
|
9199
|
-
/* @__PURE__ */
|
|
9492
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiX, { size: 12 })
|
|
9200
9493
|
))
|
|
9201
9494
|
);
|
|
9202
|
-
})), canEdit && /* @__PURE__ */
|
|
9495
|
+
})), canEdit && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center justify-between pt-2 mt-1 border-t border-white/5 opacity-40 group-hover/item:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9203
9496
|
"button",
|
|
9204
9497
|
{
|
|
9205
9498
|
onClick: () => onRequestPickAncestry(group.id),
|
|
@@ -9209,17 +9502,17 @@ var GroupItem = ({
|
|
|
9209
9502
|
`,
|
|
9210
9503
|
title: "Adicionar Ancestralidade a este grupo"
|
|
9211
9504
|
},
|
|
9212
|
-
isPickingForThisGroup ? /* @__PURE__ */
|
|
9505
|
+
isPickingForThisGroup ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { size: 12 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { size: 12 }),
|
|
9213
9506
|
isPickingForThisGroup ? "Selecionando..." : "Adicionar"
|
|
9214
|
-
), /* @__PURE__ */
|
|
9507
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9215
9508
|
"button",
|
|
9216
9509
|
{
|
|
9217
9510
|
onClick: () => onAddSubgroup(group.id),
|
|
9218
9511
|
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
9219
9512
|
title: "Criar Subgrupo"
|
|
9220
9513
|
},
|
|
9221
|
-
/* @__PURE__ */
|
|
9222
|
-
)), /* @__PURE__ */
|
|
9514
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14 })
|
|
9515
|
+
)), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react24.default.createElement(
|
|
9223
9516
|
"button",
|
|
9224
9517
|
{
|
|
9225
9518
|
onClick: () => onIndent(group.id),
|
|
@@ -9227,24 +9520,24 @@ var GroupItem = ({
|
|
|
9227
9520
|
className: `p-1.5 rounded transition-colors ${!canIndent ? "text-slate-800 cursor-not-allowed" : "text-slate-500 hover:text-white hover:bg-white/10"}`,
|
|
9228
9521
|
title: "Aninhar no grupo acima"
|
|
9229
9522
|
},
|
|
9230
|
-
/* @__PURE__ */
|
|
9231
|
-
), /* @__PURE__ */
|
|
9523
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowRight, { size: 14 })
|
|
9524
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9232
9525
|
"button",
|
|
9233
9526
|
{
|
|
9234
9527
|
onClick: () => onOutdent(group.id),
|
|
9235
9528
|
className: "p-1.5 text-slate-500 hover:text-white hover:bg-white/10 rounded transition-colors",
|
|
9236
9529
|
title: "Desaninhar"
|
|
9237
9530
|
},
|
|
9238
|
-
/* @__PURE__ */
|
|
9239
|
-
), /* @__PURE__ */
|
|
9531
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiArrowLeft, { size: 14 })
|
|
9532
|
+
), /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-3 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9240
9533
|
"button",
|
|
9241
9534
|
{
|
|
9242
9535
|
onClick: () => onDelete(group.id),
|
|
9243
9536
|
className: "p-1.5 text-slate-600 hover:text-red-400 hover:bg-red-500/10 rounded transition-colors",
|
|
9244
9537
|
title: "Remover Grupo"
|
|
9245
9538
|
},
|
|
9246
|
-
/* @__PURE__ */
|
|
9247
|
-
)))), group.children && group.children.length > 0 && /* @__PURE__ */
|
|
9539
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiTrash2, { size: 14 })
|
|
9540
|
+
)))), group.children && group.children.length > 0 && /* @__PURE__ */ import_react24.default.createElement("div", { className: "ml-2" }, group.children.map((childGroup, idx) => /* @__PURE__ */ import_react24.default.createElement(
|
|
9248
9541
|
GroupItem,
|
|
9249
9542
|
{
|
|
9250
9543
|
key: childGroup.id,
|
|
@@ -9276,21 +9569,21 @@ function AncestryBoard({
|
|
|
9276
9569
|
userRole
|
|
9277
9570
|
// [NOVO] Recebe a role do usuário
|
|
9278
9571
|
}) {
|
|
9279
|
-
const [searchTerm, setSearchTerm] = (0,
|
|
9280
|
-
const [groups, setGroups] = (0,
|
|
9281
|
-
const [isLoaded, setIsLoaded] = (0,
|
|
9282
|
-
const [pickingGroupId, setPickingGroupId] = (0,
|
|
9283
|
-
const [saveStatus, setSaveStatus] = (0,
|
|
9284
|
-
const canEdit = (0,
|
|
9572
|
+
const [searchTerm, setSearchTerm] = (0, import_react24.useState)("");
|
|
9573
|
+
const [groups, setGroups] = (0, import_react24.useState)([]);
|
|
9574
|
+
const [isLoaded, setIsLoaded] = (0, import_react24.useState)(false);
|
|
9575
|
+
const [pickingGroupId, setPickingGroupId] = (0, import_react24.useState)(null);
|
|
9576
|
+
const [saveStatus, setSaveStatus] = (0, import_react24.useState)("idle");
|
|
9577
|
+
const canEdit = (0, import_react24.useMemo)(() => {
|
|
9285
9578
|
return userRole !== "viewer";
|
|
9286
9579
|
}, [userRole]);
|
|
9287
|
-
(0,
|
|
9580
|
+
(0, import_react24.useEffect)(() => {
|
|
9288
9581
|
if (initialGroups && !isLoaded) {
|
|
9289
9582
|
setGroups(initialGroups);
|
|
9290
9583
|
setIsLoaded(true);
|
|
9291
9584
|
}
|
|
9292
9585
|
}, [initialGroups, isLoaded]);
|
|
9293
|
-
const nodeNamesMap = (0,
|
|
9586
|
+
const nodeNamesMap = (0, import_react24.useMemo)(() => {
|
|
9294
9587
|
const map = /* @__PURE__ */ new Map();
|
|
9295
9588
|
if (availableNodes && Array.isArray(availableNodes)) {
|
|
9296
9589
|
availableNodes.forEach((node) => {
|
|
@@ -9301,7 +9594,7 @@ function AncestryBoard({
|
|
|
9301
9594
|
}
|
|
9302
9595
|
return map;
|
|
9303
9596
|
}, [availableNodes]);
|
|
9304
|
-
const availableIds = (0,
|
|
9597
|
+
const availableIds = (0, import_react24.useMemo)(() => {
|
|
9305
9598
|
return new Set(availableAncestries.map((a) => String(a.ancestry_id)));
|
|
9306
9599
|
}, [availableAncestries]);
|
|
9307
9600
|
const sanitizeGroups = (groupList) => {
|
|
@@ -9315,7 +9608,7 @@ function AncestryBoard({
|
|
|
9315
9608
|
children: sanitizeGroups(g.children || [])
|
|
9316
9609
|
}));
|
|
9317
9610
|
};
|
|
9318
|
-
(0,
|
|
9611
|
+
(0, import_react24.useEffect)(() => {
|
|
9319
9612
|
if (!isLoaded || !onSave) return;
|
|
9320
9613
|
const timeoutId = setTimeout(async () => {
|
|
9321
9614
|
setSaveStatus("saving");
|
|
@@ -9333,7 +9626,7 @@ function AncestryBoard({
|
|
|
9333
9626
|
}, 3e3);
|
|
9334
9627
|
return () => clearTimeout(timeoutId);
|
|
9335
9628
|
}, [groups, isLoaded, onSave]);
|
|
9336
|
-
(0,
|
|
9629
|
+
(0, import_react24.useEffect)(() => {
|
|
9337
9630
|
if (!isOpen) return;
|
|
9338
9631
|
const handleKeyDown = (e) => {
|
|
9339
9632
|
if (e.key === "Escape") {
|
|
@@ -9349,7 +9642,7 @@ function AncestryBoard({
|
|
|
9349
9642
|
window.addEventListener("keydown", handleKeyDown);
|
|
9350
9643
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
9351
9644
|
}, [isOpen, onClose, pickingGroupId]);
|
|
9352
|
-
const filtered = (0,
|
|
9645
|
+
const filtered = (0, import_react24.useMemo)(() => {
|
|
9353
9646
|
const term = searchTerm.toLowerCase().trim();
|
|
9354
9647
|
return availableAncestries.filter((a) => {
|
|
9355
9648
|
if (!term) return true;
|
|
@@ -9488,27 +9781,27 @@ function AncestryBoard({
|
|
|
9488
9781
|
});
|
|
9489
9782
|
};
|
|
9490
9783
|
if (!isOpen) return null;
|
|
9491
|
-
return /* @__PURE__ */
|
|
9784
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9492
9785
|
"div",
|
|
9493
9786
|
{
|
|
9494
9787
|
className: "fixed inset-0 z-[2200] bg-black/80 backdrop-blur-sm flex items-center justify-center p-2",
|
|
9495
9788
|
onClick: onClose
|
|
9496
9789
|
},
|
|
9497
|
-
/* @__PURE__ */
|
|
9790
|
+
/* @__PURE__ */ import_react24.default.createElement(
|
|
9498
9791
|
"div",
|
|
9499
9792
|
{
|
|
9500
9793
|
className: "bg-slate-950 border border-white/10 rounded-xl w-[98vw] h-[97vh] flex flex-col shadow-2xl overflow-hidden animate-in fade-in zoom-in-95 duration-200",
|
|
9501
9794
|
onClick: (e) => e.stopPropagation()
|
|
9502
9795
|
},
|
|
9503
|
-
/* @__PURE__ */
|
|
9796
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "h-14 px-4 border-b border-white/10 bg-slate-900/90 flex items-center justify-between shrink-0" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react24.default.createElement("h3", { className: "text-base font-semibold text-white flex items-center gap-2 whitespace-nowrap" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { className: "text-indigo-400" }), "Ancestry Board"), saveStatus !== "idle" && /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-2 duration-300" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "w-px h-4 bg-white/10 mx-1" }), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-slate-900/50 border border-white/5" }, saveStatus === "saving" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLoader, { className: "animate-spin text-indigo-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-indigo-300" }, "Salvando")), saveStatus === "saved" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCheckCircle, { className: "text-emerald-400", size: 12 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-slate-400" }, "Salvo")), saveStatus === "error" && /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement("span", { className: "w-2 h-2 rounded-full bg-red-500" }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[10px] uppercase tracking-wide font-medium text-red-400" }, "Erro"))))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-3" }, pickingGroupId && /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-xs text-indigo-300 font-medium animate-pulse hidden sm:inline-block mr-2" }, "Selecione na lateral..."), canEdit && /* @__PURE__ */ import_react24.default.createElement(
|
|
9504
9797
|
"button",
|
|
9505
9798
|
{
|
|
9506
9799
|
onClick: handleAddRootGroup,
|
|
9507
9800
|
className: "\n flex items-center gap-2 px-3 py-1.5 \n bg-white/5 hover:bg-white/10 \n border border-white/10 hover:border-white/20\n backdrop-blur-sm\n text-slate-200 hover:text-white\n rounded-md transition-all duration-200\n text-xs font-medium shadow-sm\n "
|
|
9508
9801
|
},
|
|
9509
|
-
/* @__PURE__ */
|
|
9510
|
-
/* @__PURE__ */
|
|
9511
|
-
), /* @__PURE__ */
|
|
9802
|
+
/* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 14, className: "text-indigo-400" }),
|
|
9803
|
+
/* @__PURE__ */ import_react24.default.createElement("span", { className: "hidden sm:inline" }, "Novo Grupo")
|
|
9804
|
+
), /* @__PURE__ */ import_react24.default.createElement(
|
|
9512
9805
|
"button",
|
|
9513
9806
|
{
|
|
9514
9807
|
onClick: onClose,
|
|
@@ -9516,11 +9809,11 @@ function AncestryBoard({
|
|
|
9516
9809
|
},
|
|
9517
9810
|
"\xD7"
|
|
9518
9811
|
))),
|
|
9519
|
-
/* @__PURE__ */
|
|
9812
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9520
9813
|
flex flex-col border-r border-white/10 transition-all duration-300 flex-none
|
|
9521
9814
|
${pickingGroupId ? "w-[25%] border-indigo-500/30" : "w-[20%]"}
|
|
9522
9815
|
min-w-[280px] max-w-[500px] bg-slate-900
|
|
9523
|
-
` }, /* @__PURE__ */
|
|
9816
|
+
` }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "p-3 border-b border-white/5 bg-slate-900/50" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "relative group" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiSearch, { className: `absolute left-3 top-1/2 -translate-y-1/2 transition-colors ${pickingGroupId ? "text-indigo-400" : "text-slate-500 group-focus-within:text-indigo-400"}` }), /* @__PURE__ */ import_react24.default.createElement(
|
|
9524
9817
|
"input",
|
|
9525
9818
|
{
|
|
9526
9819
|
type: "text",
|
|
@@ -9533,10 +9826,10 @@ function AncestryBoard({
|
|
|
9533
9826
|
onChange: (e) => setSearchTerm(e.target.value),
|
|
9534
9827
|
autoFocus: !pickingGroupId
|
|
9535
9828
|
}
|
|
9536
|
-
))), /* @__PURE__ */
|
|
9829
|
+
))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-3 space-y-2" }, filtered.map((anc) => {
|
|
9537
9830
|
const parentNodeName = nodeNamesMap.get(String(anc.ancestral_node)) || "Node Desconhecido";
|
|
9538
9831
|
const isPicking = !!pickingGroupId;
|
|
9539
|
-
return /* @__PURE__ */
|
|
9832
|
+
return /* @__PURE__ */ import_react24.default.createElement(
|
|
9540
9833
|
"div",
|
|
9541
9834
|
{
|
|
9542
9835
|
key: anc.ancestry_id,
|
|
@@ -9548,12 +9841,12 @@ function AncestryBoard({
|
|
|
9548
9841
|
${isPicking ? "border-indigo-500/30 bg-indigo-500/5 hover:bg-indigo-500/20 hover:border-indigo-400 cursor-pointer" : "border-white/5 bg-slate-800/40 hover:bg-indigo-600/10 hover:border-indigo-500/30 cursor-default"}
|
|
9549
9842
|
`
|
|
9550
9843
|
},
|
|
9551
|
-
/* @__PURE__ */
|
|
9844
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: `
|
|
9552
9845
|
mt-0.5 w-8 h-8 rounded-md grid place-content-center shrink-0 border transition-all shadow-lg
|
|
9553
9846
|
${isPicking ? "bg-indigo-500 text-white border-indigo-400" : "bg-slate-800 text-indigo-400 border-white/5 group-hover:bg-indigo-500 group-hover:text-white"}
|
|
9554
|
-
` }, isPicking ? /* @__PURE__ */
|
|
9555
|
-
/* @__PURE__ */
|
|
9556
|
-
!isPicking && /* @__PURE__ */
|
|
9847
|
+
` }, isPicking ? /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlus, { size: 16 }) : /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 14 })),
|
|
9848
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 min-w-0 pb-2" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ import_react24.default.createElement("h4", { className: "text-sm font-medium text-slate-200 group-hover:text-white truncate transition-colors" }, anc.name || "Sem Nome"), anc.is_private && /* @__PURE__ */ import_react24.default.createElement("span", { className: "text-[9px] px-1 py-0.5 rounded bg-amber-500/10 text-amber-300 border border-amber-500/20" }, "Priv")), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex items-center gap-1.5 mt-0.5 text-[11px] text-slate-500 group-hover:text-indigo-200/70 transition-colors" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiCornerUpRight, { size: 10 }), /* @__PURE__ */ import_react24.default.createElement("span", { className: "truncate max-w-[120px]" }, parentNodeName)), anc.description && /* @__PURE__ */ import_react24.default.createElement("p", { className: "mt-1.5 text-[11px] text-slate-400 line-clamp-2 leading-relaxed opacity-80" }, anc.description)),
|
|
9849
|
+
!isPicking && /* @__PURE__ */ import_react24.default.createElement(
|
|
9557
9850
|
"button",
|
|
9558
9851
|
{
|
|
9559
9852
|
onClick: (e) => {
|
|
@@ -9563,10 +9856,10 @@ function AncestryBoard({
|
|
|
9563
9856
|
className: "absolute right-2 bottom-2 opacity-0 group-hover:opacity-100 transition-all duration-300 transform translate-y-2 group-hover:translate-y-0 z-10",
|
|
9564
9857
|
title: "Renderizar Ancestralidade"
|
|
9565
9858
|
},
|
|
9566
|
-
/* @__PURE__ */
|
|
9859
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "bg-indigo-500 text-white p-2 rounded-full shadow-lg hover:bg-indigo-400 hover:scale-110 transition-all" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiPlay, { size: 14, className: "ml-0.5" }))
|
|
9567
9860
|
)
|
|
9568
9861
|
);
|
|
9569
|
-
}))), /* @__PURE__ */
|
|
9862
|
+
}))), /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col flex-1 bg-slate-950/30" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" }, groups.length === 0 ? /* @__PURE__ */ import_react24.default.createElement("div", { className: "flex flex-col items-center justify-center h-full text-slate-500 gap-3 border-2 border-dashed border-white/5 rounded-xl m-4 bg-slate-900/20" }, /* @__PURE__ */ import_react24.default.createElement(import_fi18.FiLayers, { size: 24, className: "opacity-20" }), /* @__PURE__ */ import_react24.default.createElement("p", { className: "text-xs text-center px-4" }, canEdit ? /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo criado.", /* @__PURE__ */ import_react24.default.createElement("br", null), 'Use o bot\xE3o "Novo Grupo" acima.') : /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, "Nenhum grupo dispon\xEDvel para visualiza\xE7\xE3o."))) : groups.map((group, index) => /* @__PURE__ */ import_react24.default.createElement(
|
|
9570
9863
|
GroupItem,
|
|
9571
9864
|
{
|
|
9572
9865
|
key: group.id,
|
|
@@ -9586,7 +9879,7 @@ function AncestryBoard({
|
|
|
9586
9879
|
canEdit
|
|
9587
9880
|
}
|
|
9588
9881
|
))))),
|
|
9589
|
-
/* @__PURE__ */
|
|
9882
|
+
/* @__PURE__ */ import_react24.default.createElement("div", { className: "px-5 py-2 border-t border-white/10 bg-slate-950/50 text-xs text-slate-500 flex justify-between flex-shrink-0" }, /* @__PURE__ */ import_react24.default.createElement("span", null, filtered.length, " itens encontrados"), /* @__PURE__ */ import_react24.default.createElement("span", null, groups.length, " grupos raiz"))
|
|
9590
9883
|
)
|
|
9591
9884
|
);
|
|
9592
9885
|
}
|
|
@@ -9666,12 +9959,12 @@ function XViewScene({
|
|
|
9666
9959
|
check_user_permission
|
|
9667
9960
|
}) {
|
|
9668
9961
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
9669
|
-
const { data: session, status } = (0,
|
|
9962
|
+
const { data: session, status } = (0, import_react26.useSession)();
|
|
9670
9963
|
const router = (0, import_navigation.useRouter)();
|
|
9671
9964
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
9672
9965
|
const focusNodeId = searchParams == null ? void 0 : searchParams.get("focus");
|
|
9673
9966
|
const focusAncestryId = searchParams == null ? void 0 : searchParams.get("ancestry");
|
|
9674
|
-
const viewParams = (0,
|
|
9967
|
+
const viewParams = (0, import_react25.useMemo)(() => {
|
|
9675
9968
|
if (encryptedConfig) {
|
|
9676
9969
|
const data = decryptData(encryptedConfig);
|
|
9677
9970
|
if (data) {
|
|
@@ -9680,7 +9973,7 @@ function XViewScene({
|
|
|
9680
9973
|
}
|
|
9681
9974
|
return null;
|
|
9682
9975
|
}, [encryptedConfig, session]);
|
|
9683
|
-
(0,
|
|
9976
|
+
(0, import_react25.useEffect)(() => {
|
|
9684
9977
|
async function verifyPermission() {
|
|
9685
9978
|
if (!viewParams || !session || !check_user_permission) return;
|
|
9686
9979
|
const { id, type, owner_id } = viewParams;
|
|
@@ -9710,64 +10003,65 @@ function XViewScene({
|
|
|
9710
10003
|
setIsLoading(false);
|
|
9711
10004
|
}
|
|
9712
10005
|
}, [viewParams, session, status, check_user_permission]);
|
|
9713
|
-
const sceneConfigId = (0,
|
|
9714
|
-
const ownerId = (0,
|
|
9715
|
-
const dbSaveUrl = (0,
|
|
10006
|
+
const sceneConfigId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.id) || null, [viewParams]);
|
|
10007
|
+
const ownerId = (0, import_react25.useMemo)(() => (viewParams == null ? void 0 : viewParams.owner_id) || null, [viewParams]);
|
|
10008
|
+
const dbSaveUrl = (0, import_react25.useMemo)(() => {
|
|
9716
10009
|
if (ownerId && sceneConfigId) {
|
|
9717
10010
|
return `x_view_dbs/${ownerId}/${sceneConfigId}`;
|
|
9718
10011
|
}
|
|
9719
10012
|
return null;
|
|
9720
10013
|
}, [ownerId, sceneConfigId]);
|
|
9721
|
-
const sceneSaveUrl = (0,
|
|
10014
|
+
const sceneSaveUrl = (0, import_react25.useMemo)(() => {
|
|
9722
10015
|
if (ownerId && sceneConfigId) {
|
|
9723
10016
|
return `x_view_scenes/${ownerId}/${sceneConfigId}`;
|
|
9724
10017
|
}
|
|
9725
10018
|
return null;
|
|
9726
10019
|
}, [ownerId, sceneConfigId]);
|
|
9727
|
-
const ancestry_save_url = (0,
|
|
10020
|
+
const ancestry_save_url = (0, import_react25.useMemo)(() => {
|
|
9728
10021
|
if (ownerId && sceneConfigId) {
|
|
9729
10022
|
return `x_view_ancestry/${ownerId}/${sceneConfigId}`;
|
|
9730
10023
|
}
|
|
9731
10024
|
return null;
|
|
9732
10025
|
}, [ownerId, sceneConfigId]);
|
|
9733
|
-
const sceneDataRef = (0,
|
|
9734
|
-
const parentDataRef = (0,
|
|
9735
|
-
const ancestryDataRef = (0,
|
|
9736
|
-
const [isLoading, setIsLoading] = (0,
|
|
9737
|
-
const [permissionStatus, setPermissionStatus] = (0,
|
|
9738
|
-
const [userPermissionRole, setUserPermissionRole] = (0,
|
|
9739
|
-
const [isInitialized, setIsInitialized] = (0,
|
|
9740
|
-
const [sceneVersion, setSceneVersion] = (0,
|
|
9741
|
-
const [contextMenu, setContextMenu] = (0,
|
|
9742
|
-
const [multiContextMenu, setMultiContextMenu] = (0,
|
|
9743
|
-
const [relationshipMenu, setRelationshipMenu] = (0,
|
|
9744
|
-
const [creationMode, setCreationMode] = (0,
|
|
9745
|
-
const [versionMode, setVersionMode] = (0,
|
|
9746
|
-
const [
|
|
9747
|
-
const [
|
|
9748
|
-
const [
|
|
9749
|
-
const [
|
|
10026
|
+
const sceneDataRef = (0, import_react25.useRef)(null);
|
|
10027
|
+
const parentDataRef = (0, import_react25.useRef)(null);
|
|
10028
|
+
const ancestryDataRef = (0, import_react25.useRef)(null);
|
|
10029
|
+
const [isLoading, setIsLoading] = (0, import_react25.useState)(true);
|
|
10030
|
+
const [permissionStatus, setPermissionStatus] = (0, import_react25.useState)("loading");
|
|
10031
|
+
const [userPermissionRole, setUserPermissionRole] = (0, import_react25.useState)(null);
|
|
10032
|
+
const [isInitialized, setIsInitialized] = (0, import_react25.useState)(false);
|
|
10033
|
+
const [sceneVersion, setSceneVersion] = (0, import_react25.useState)(0);
|
|
10034
|
+
const [contextMenu, setContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeData: null });
|
|
10035
|
+
const [multiContextMenu, setMultiContextMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, nodeIds: null });
|
|
10036
|
+
const [relationshipMenu, setRelationshipMenu] = (0, import_react25.useState)({ visible: false, x: 0, y: 0, linkObject: null });
|
|
10037
|
+
const [creationMode, setCreationMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
|
|
10038
|
+
const [versionMode, setVersionMode] = (0, import_react25.useState)({ isActive: false, sourceNodeData: null });
|
|
10039
|
+
const [questMode, setQuestMode] = (0, import_react25.useState)({ isActive: false });
|
|
10040
|
+
const [hasFocusedInitial, setHasFocusedInitial] = (0, import_react25.useState)(false);
|
|
10041
|
+
const [hasOpenedInitialAncestry, setHasOpenedInitialAncestry] = (0, import_react25.useState)(false);
|
|
10042
|
+
const [ancestryMode, setAncestryMode] = (0, import_react25.useState)({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
10043
|
+
const [readingMode, setReadingMode] = (0, import_react25.useState)({
|
|
9750
10044
|
isActive: false,
|
|
9751
10045
|
ancestry: null,
|
|
9752
10046
|
branchStack: [],
|
|
9753
10047
|
autoAbstraction: false
|
|
9754
10048
|
});
|
|
9755
|
-
const [formPosition, setFormPosition] = (0,
|
|
9756
|
-
const [detailsNode, setDetailsNode] = (0,
|
|
9757
|
-
const [detailsLink, setDetailsLink] = (0,
|
|
9758
|
-
const [ancestryLinkDetails, setAncestryLinkDetails] = (0,
|
|
9759
|
-
const [imageViewer, setImageViewer] = (0,
|
|
9760
|
-
const [editingAncestryRel, setEditingAncestryRel] = (0,
|
|
9761
|
-
const [isImportModalOpen, setIsImportModalOpen] = (0,
|
|
9762
|
-
const [importSuccessMessage, setImportSuccessMessage] = (0,
|
|
9763
|
-
const [highlightedNodeId, setHighlightedNodeId] = (0,
|
|
9764
|
-
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0,
|
|
9765
|
-
const [ancestryBoardData, setAncestryBoardData] = (0,
|
|
9766
|
-
const [isSidebarOpen, setIsSidebarOpen] = (0,
|
|
9767
|
-
const mountRef = (0,
|
|
9768
|
-
const tooltipRef = (0,
|
|
9769
|
-
const formRef = (0,
|
|
9770
|
-
const stateRef = (0,
|
|
10049
|
+
const [formPosition, setFormPosition] = (0, import_react25.useState)({ left: 16, top: 16, opacity: 0 });
|
|
10050
|
+
const [detailsNode, setDetailsNode] = (0, import_react25.useState)(null);
|
|
10051
|
+
const [detailsLink, setDetailsLink] = (0, import_react25.useState)(null);
|
|
10052
|
+
const [ancestryLinkDetails, setAncestryLinkDetails] = (0, import_react25.useState)(null);
|
|
10053
|
+
const [imageViewer, setImageViewer] = (0, import_react25.useState)({ visible: false, images: [], startIndex: 0 });
|
|
10054
|
+
const [editingAncestryRel, setEditingAncestryRel] = (0, import_react25.useState)({ visible: false, data: null, path: null });
|
|
10055
|
+
const [isImportModalOpen, setIsImportModalOpen] = (0, import_react25.useState)(false);
|
|
10056
|
+
const [importSuccessMessage, setImportSuccessMessage] = (0, import_react25.useState)("");
|
|
10057
|
+
const [highlightedNodeId, setHighlightedNodeId] = (0, import_react25.useState)(null);
|
|
10058
|
+
const [isAncestryBoardOpen, setIsAncestryBoardOpen] = (0, import_react25.useState)(false);
|
|
10059
|
+
const [ancestryBoardData, setAncestryBoardData] = (0, import_react25.useState)([]);
|
|
10060
|
+
const [isSidebarOpen, setIsSidebarOpen] = (0, import_react25.useState)(false);
|
|
10061
|
+
const mountRef = (0, import_react25.useRef)(null);
|
|
10062
|
+
const tooltipRef = (0, import_react25.useRef)(null);
|
|
10063
|
+
const formRef = (0, import_react25.useRef)(null);
|
|
10064
|
+
const stateRef = (0, import_react25.useRef)({
|
|
9771
10065
|
readMode: {
|
|
9772
10066
|
currentMaxIndex: 0,
|
|
9773
10067
|
progressMap: {}
|
|
@@ -9812,10 +10106,10 @@ function XViewScene({
|
|
|
9812
10106
|
minWidth: 320,
|
|
9813
10107
|
maxWidth: maxReadPanelW
|
|
9814
10108
|
});
|
|
9815
|
-
(0,
|
|
10109
|
+
(0, import_react25.useEffect)(() => {
|
|
9816
10110
|
stateRef.current.ancestry = ancestryMode;
|
|
9817
10111
|
}, [ancestryMode]);
|
|
9818
|
-
(0,
|
|
10112
|
+
(0, import_react25.useEffect)(() => {
|
|
9819
10113
|
var _a2;
|
|
9820
10114
|
if (!isInitialized) return;
|
|
9821
10115
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -9836,10 +10130,10 @@ function XViewScene({
|
|
|
9836
10130
|
}
|
|
9837
10131
|
stateRef.current.nodeIdToParentFileMap = map;
|
|
9838
10132
|
}, [isInitialized, sceneVersion]);
|
|
9839
|
-
const handleNavigateBack = (0,
|
|
10133
|
+
const handleNavigateBack = (0, import_react25.useCallback)(() => {
|
|
9840
10134
|
router.push("/dashboard/scenes");
|
|
9841
10135
|
}, [router]);
|
|
9842
|
-
const handleConfirmImport = (0,
|
|
10136
|
+
const handleConfirmImport = (0, import_react25.useCallback)(
|
|
9843
10137
|
async (importPayload) => {
|
|
9844
10138
|
var _a2, _b2;
|
|
9845
10139
|
let files = [];
|
|
@@ -9937,7 +10231,7 @@ function XViewScene({
|
|
|
9937
10231
|
const handleOpenImageViewer = (images, startIndex) => {
|
|
9938
10232
|
setImageViewer({ visible: true, images, startIndex });
|
|
9939
10233
|
};
|
|
9940
|
-
const tweenToTarget = (0,
|
|
10234
|
+
const tweenToTarget = (0, import_react25.useCallback)((target, zoomFactor = 1, forcedDirection = null) => {
|
|
9941
10235
|
const { camera, controls, tweenGroup } = stateRef.current;
|
|
9942
10236
|
if (!camera || !controls || !tweenGroup) return;
|
|
9943
10237
|
const targetPos = target instanceof THREE3.Mesh ? target.getWorldPosition(new THREE3.Vector3()) : target;
|
|
@@ -9960,7 +10254,7 @@ function XViewScene({
|
|
|
9960
10254
|
if (!t || typeof t.closest !== "function") return false;
|
|
9961
10255
|
return !!t.closest(".ui-overlay");
|
|
9962
10256
|
};
|
|
9963
|
-
const buildFullAncestryTree = (0,
|
|
10257
|
+
const buildFullAncestryTree = (0, import_react25.useCallback)((idTree, nodes, ancestries = []) => {
|
|
9964
10258
|
if (!idTree) return null;
|
|
9965
10259
|
const nodeMap = new Map(nodes.map((n) => [String(n.id), n]));
|
|
9966
10260
|
const ancestryMap = new Map(ancestries.map((a) => [String(a.ancestry_id), a]));
|
|
@@ -10036,7 +10330,7 @@ function XViewScene({
|
|
|
10036
10330
|
}
|
|
10037
10331
|
return recursiveBuild(idTree);
|
|
10038
10332
|
}, []);
|
|
10039
|
-
const handleActivateTimeline = (0,
|
|
10333
|
+
const handleActivateTimeline = (0, import_react25.useCallback)(() => {
|
|
10040
10334
|
const { nodeObjects, tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10041
10335
|
if (!nodeObjects || !tweenGroup || !timelineIntervalsGroup) return;
|
|
10042
10336
|
while (timelineIntervalsGroup.children.length > 0) {
|
|
@@ -10189,7 +10483,7 @@ function XViewScene({
|
|
|
10189
10483
|
}
|
|
10190
10484
|
});
|
|
10191
10485
|
}, []);
|
|
10192
|
-
const handleVersionTimeline = (0,
|
|
10486
|
+
const handleVersionTimeline = (0, import_react25.useCallback)((sourceMesh, versionMeshes) => {
|
|
10193
10487
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
10194
10488
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0) return;
|
|
10195
10489
|
versionMeshes.forEach((mesh) => {
|
|
@@ -10312,7 +10606,7 @@ function XViewScene({
|
|
|
10312
10606
|
}
|
|
10313
10607
|
});
|
|
10314
10608
|
}, []);
|
|
10315
|
-
(0,
|
|
10609
|
+
(0, import_react25.useEffect)(() => {
|
|
10316
10610
|
async function fetchAllData(configPath, ownerId2) {
|
|
10317
10611
|
var _a2, _b2;
|
|
10318
10612
|
if (!get_scene_view_data) {
|
|
@@ -10384,12 +10678,12 @@ function XViewScene({
|
|
|
10384
10678
|
focusNodeId,
|
|
10385
10679
|
focusAncestryId
|
|
10386
10680
|
]);
|
|
10387
|
-
const isNodeInView = (0,
|
|
10681
|
+
const isNodeInView = (0, import_react25.useCallback)((id) => {
|
|
10388
10682
|
const key = String(id);
|
|
10389
10683
|
const objs = stateRef.current.nodeObjects || {};
|
|
10390
10684
|
return !!objs[key];
|
|
10391
10685
|
}, []);
|
|
10392
|
-
const addOrUpdateNodeMesh = (0,
|
|
10686
|
+
const addOrUpdateNodeMesh = (0, import_react25.useCallback)((nodeData, position, suppressVersionUpdate = false) => {
|
|
10393
10687
|
const { graphGroup, nodeObjects, clickableNodes, glowTexture, tweenGroup } = stateRef.current;
|
|
10394
10688
|
const nodeId = String(nodeData.id);
|
|
10395
10689
|
if (nodeObjects[nodeId]) {
|
|
@@ -10416,7 +10710,7 @@ function XViewScene({
|
|
|
10416
10710
|
}
|
|
10417
10711
|
return mesh;
|
|
10418
10712
|
}, []);
|
|
10419
|
-
(0,
|
|
10713
|
+
(0, import_react25.useEffect)(() => {
|
|
10420
10714
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
10421
10715
|
const currentMount = mountRef.current;
|
|
10422
10716
|
if (!currentMount) return;
|
|
@@ -10809,12 +11103,15 @@ function XViewScene({
|
|
|
10809
11103
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
10810
11104
|
}
|
|
10811
11105
|
function handleKeyDown(event) {
|
|
11106
|
+
var _a2, _b2, _c2, _d2;
|
|
10812
11107
|
const context = actionHandlerContext;
|
|
10813
11108
|
if (event.key === "Escape") {
|
|
10814
11109
|
if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
|
|
10815
11110
|
if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
|
|
10816
11111
|
if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
|
|
11112
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
|
|
10817
11113
|
if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
|
|
11114
|
+
if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
|
|
10818
11115
|
if (stateRef.current.selectedNodes.size > 0) {
|
|
10819
11116
|
stateRef.current.selectedNodes.clear();
|
|
10820
11117
|
}
|
|
@@ -10822,6 +11119,17 @@ function XViewScene({
|
|
|
10822
11119
|
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
10823
11120
|
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
10824
11121
|
}
|
|
11122
|
+
if (event.key.toLowerCase() === "q") {
|
|
11123
|
+
const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_c2 = context.versionMode) == null ? void 0 : _c2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isAncestryBoardOpen;
|
|
11124
|
+
if (isUiClear) {
|
|
11125
|
+
const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
|
|
11126
|
+
if (!isView) {
|
|
11127
|
+
alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
|
|
11128
|
+
return;
|
|
11129
|
+
}
|
|
11130
|
+
setQuestMode({ isActive: true });
|
|
11131
|
+
}
|
|
11132
|
+
}
|
|
10825
11133
|
}
|
|
10826
11134
|
function handleDoubleClick(event) {
|
|
10827
11135
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
@@ -10980,9 +11288,7 @@ function XViewScene({
|
|
|
10980
11288
|
mountEl: currentMount,
|
|
10981
11289
|
isSceneBusy: stateRef.current.isDragging || creation.isActive || connection.isActive || relink.isActive || ancestryMode.isActive,
|
|
10982
11290
|
parentData: parentDataRef.current,
|
|
10983
|
-
// <--- ADICIONADO AQUI
|
|
10984
11291
|
ancestryData: ancestryDataRef.current
|
|
10985
|
-
// <--- ADICIONADO AQUI
|
|
10986
11292
|
});
|
|
10987
11293
|
(_b2 = stateRef.current.tweenGroup) == null ? void 0 : _b2.update(time);
|
|
10988
11294
|
stateRef.current.controls.update();
|
|
@@ -11049,7 +11355,7 @@ function XViewScene({
|
|
|
11049
11355
|
}
|
|
11050
11356
|
};
|
|
11051
11357
|
}, [isInitialized, tweenToTarget, dbSaveUrl, isNodeInView, addOrUpdateNodeMesh, handleActivateTimeline, get_scene_view_data, save_view_data]);
|
|
11052
|
-
const handleGhostNodeImageChange = (0,
|
|
11358
|
+
const handleGhostNodeImageChange = (0, import_react25.useCallback)((useImage, imageUrl) => {
|
|
11053
11359
|
const { node: ghostNode, line: ghostLine, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11054
11360
|
const { graphGroup, glowTexture } = stateRef.current;
|
|
11055
11361
|
if (!ghostNode || !graphGroup) return;
|
|
@@ -11091,7 +11397,7 @@ function XViewScene({
|
|
|
11091
11397
|
aura: newGhostNode.getObjectByName("aura")
|
|
11092
11398
|
};
|
|
11093
11399
|
}, []);
|
|
11094
|
-
const handleGhostNodeIntensityChange = (0,
|
|
11400
|
+
const handleGhostNodeIntensityChange = (0, import_react25.useCallback)((newIntensity) => {
|
|
11095
11401
|
const { node: ghostNode, aura: ghostAura } = stateRef.current.ghostElements;
|
|
11096
11402
|
if (!ghostNode) return;
|
|
11097
11403
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -11112,7 +11418,7 @@ function XViewScene({
|
|
|
11112
11418
|
ghostAura.material.opacity = Math.min(0.8, newIntensity * 0.15);
|
|
11113
11419
|
}
|
|
11114
11420
|
}, []);
|
|
11115
|
-
const handleDetailNodeIntensityChange = (0,
|
|
11421
|
+
const handleDetailNodeIntensityChange = (0, import_react25.useCallback)((nodeId, newIntensity) => {
|
|
11116
11422
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
11117
11423
|
if (!mesh) return;
|
|
11118
11424
|
const adjustedIntensity = newIntensity + MIN_VISIBILITY_INTENSITY;
|
|
@@ -11258,7 +11564,7 @@ function XViewScene({
|
|
|
11258
11564
|
mountRef.current.style.cursor = "default";
|
|
11259
11565
|
}
|
|
11260
11566
|
};
|
|
11261
|
-
const handleAncestryTreeUpdate = (0,
|
|
11567
|
+
const handleAncestryTreeUpdate = (0, import_react25.useCallback)((newTree, extraData = null) => {
|
|
11262
11568
|
setAncestryMode((prev) => {
|
|
11263
11569
|
const prevTreeStr = JSON.stringify(prev.tree);
|
|
11264
11570
|
const newTreeStr = JSON.stringify(newTree);
|
|
@@ -11278,7 +11584,7 @@ function XViewScene({
|
|
|
11278
11584
|
};
|
|
11279
11585
|
});
|
|
11280
11586
|
}, []);
|
|
11281
|
-
const actionHandlerContext = (0,
|
|
11587
|
+
const actionHandlerContext = (0, import_react25.useMemo)(
|
|
11282
11588
|
() => {
|
|
11283
11589
|
var _a2;
|
|
11284
11590
|
return {
|
|
@@ -11288,6 +11594,11 @@ function XViewScene({
|
|
|
11288
11594
|
mountRef,
|
|
11289
11595
|
creationMode,
|
|
11290
11596
|
versionMode,
|
|
11597
|
+
questMode,
|
|
11598
|
+
sceneSaveUrl,
|
|
11599
|
+
sceneConfigId,
|
|
11600
|
+
ownerId,
|
|
11601
|
+
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11291
11602
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
11292
11603
|
setters: {
|
|
11293
11604
|
setContextMenu,
|
|
@@ -11299,7 +11610,8 @@ function XViewScene({
|
|
|
11299
11610
|
setDetailsNode,
|
|
11300
11611
|
setDetailsLink,
|
|
11301
11612
|
setSceneVersion,
|
|
11302
|
-
setAncestryMode
|
|
11613
|
+
setAncestryMode,
|
|
11614
|
+
setQuestMode
|
|
11303
11615
|
},
|
|
11304
11616
|
tweenToTarget,
|
|
11305
11617
|
handleVersionTimeline,
|
|
@@ -11315,8 +11627,13 @@ function XViewScene({
|
|
|
11315
11627
|
[
|
|
11316
11628
|
creationMode,
|
|
11317
11629
|
versionMode,
|
|
11318
|
-
|
|
11630
|
+
questMode,
|
|
11631
|
+
sceneSaveUrl,
|
|
11632
|
+
sceneConfigId,
|
|
11633
|
+
ownerId,
|
|
11634
|
+
viewParams == null ? void 0 : viewParams.type,
|
|
11319
11635
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11636
|
+
tweenToTarget,
|
|
11320
11637
|
handleVersionTimeline,
|
|
11321
11638
|
save_view_data,
|
|
11322
11639
|
get_single_parent_file,
|
|
@@ -11328,7 +11645,98 @@ function XViewScene({
|
|
|
11328
11645
|
const handleStartVersioning = (nodeData) => {
|
|
11329
11646
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11330
11647
|
};
|
|
11331
|
-
const
|
|
11648
|
+
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11649
|
+
const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
|
|
11650
|
+
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11651
|
+
const newNode = {
|
|
11652
|
+
id: import_short_uuid2.default.generate(),
|
|
11653
|
+
...newQuestData,
|
|
11654
|
+
is_quest: true,
|
|
11655
|
+
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11656
|
+
};
|
|
11657
|
+
if (!graphDataRef.current[sceneConfigId2]) {
|
|
11658
|
+
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11659
|
+
}
|
|
11660
|
+
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
11661
|
+
const sceneFileData = {
|
|
11662
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11663
|
+
nodes: sceneDataRef2.current.nodes,
|
|
11664
|
+
// <-- Mantém o cenário inicial inalterado
|
|
11665
|
+
links: sceneDataRef2.current.links,
|
|
11666
|
+
// <-- Mantém o cenário inicial inalterado
|
|
11667
|
+
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
11668
|
+
quest_links: graphDataRef.current[sceneConfigId2].links
|
|
11669
|
+
};
|
|
11670
|
+
try {
|
|
11671
|
+
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
11672
|
+
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
11673
|
+
parentFileId: sceneConfigId2,
|
|
11674
|
+
ownerId: ownerId2,
|
|
11675
|
+
datasetName: "Quests Internas (View)"
|
|
11676
|
+
});
|
|
11677
|
+
const basePosition = stateRef2.current.controls.target.clone();
|
|
11678
|
+
const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
|
|
11679
|
+
const finalPosition = basePosition.add(offset);
|
|
11680
|
+
addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
|
|
11681
|
+
context.tweenToTarget(finalPosition, 1.2);
|
|
11682
|
+
setters.setQuestMode({ isActive: false });
|
|
11683
|
+
setters.setSceneVersion((v) => v + 1);
|
|
11684
|
+
} catch (error) {
|
|
11685
|
+
console.error("Falha ao salvar Quest na View:", error);
|
|
11686
|
+
alert("Ocorreu um erro ao criar a Quest.");
|
|
11687
|
+
}
|
|
11688
|
+
};
|
|
11689
|
+
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
11690
|
+
const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2, ownerId: ownerId2 } = context;
|
|
11691
|
+
const { sourceNodeData } = stateRef2.current.connection;
|
|
11692
|
+
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
11693
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11694
|
+
return;
|
|
11695
|
+
}
|
|
11696
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
|
|
11697
|
+
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
|
|
11698
|
+
let parentInfoToSave = sourceParentInfo;
|
|
11699
|
+
if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
|
|
11700
|
+
parentInfoToSave = targetParentInfo;
|
|
11701
|
+
} else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
|
|
11702
|
+
parentInfoToSave = sourceParentInfo;
|
|
11703
|
+
}
|
|
11704
|
+
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11705
|
+
const newLink = {
|
|
11706
|
+
id: `link_${import_short_uuid2.default.generate()}`,
|
|
11707
|
+
source: sourceNodeData.id,
|
|
11708
|
+
target: targetNodeData.id
|
|
11709
|
+
};
|
|
11710
|
+
try {
|
|
11711
|
+
if (parentFileIdToSave === sceneConfigId2) {
|
|
11712
|
+
const specificParentData = graphDataRef.current[sceneConfigId2];
|
|
11713
|
+
specificParentData.links.push(newLink);
|
|
11714
|
+
const viewFilePayload = {
|
|
11715
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11716
|
+
nodes: sceneDataRef2.current.nodes,
|
|
11717
|
+
// <-- Usa o estado original intocado
|
|
11718
|
+
links: sceneDataRef2.current.links,
|
|
11719
|
+
// <-- Usa o estado original intocado
|
|
11720
|
+
quest_nodes: specificParentData.nodes,
|
|
11721
|
+
quest_links: specificParentData.links
|
|
11722
|
+
// Salva a conexão aqui!
|
|
11723
|
+
};
|
|
11724
|
+
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
11725
|
+
} else {
|
|
11726
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
11727
|
+
specificParentData.links.push(newLink);
|
|
11728
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
11729
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
11730
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
11731
|
+
}
|
|
11732
|
+
addNewLinkToScene(stateRef2.current, newLink);
|
|
11733
|
+
} catch (error) {
|
|
11734
|
+
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
11735
|
+
alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
|
|
11736
|
+
}
|
|
11737
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11738
|
+
};
|
|
11739
|
+
const handleClearAncestryVisuals = (0, import_react25.useCallback)((ancestryId) => {
|
|
11332
11740
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11333
11741
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
11334
11742
|
if (renderIndex !== -1) {
|
|
@@ -11342,7 +11750,7 @@ function XViewScene({
|
|
|
11342
11750
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
11343
11751
|
}
|
|
11344
11752
|
}, []);
|
|
11345
|
-
const handleRenderAncestry = (0,
|
|
11753
|
+
const handleRenderAncestry = (0, import_react25.useCallback)(
|
|
11346
11754
|
async (ancestryObject, allowedSectionIds = null, activeSectionIdForFocus = null, baseRotation = 0, forceReprocess = true) => {
|
|
11347
11755
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11348
11756
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -11758,7 +12166,7 @@ function XViewScene({
|
|
|
11758
12166
|
},
|
|
11759
12167
|
[addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, readingMode.isActive, ancestryMode.isActive]
|
|
11760
12168
|
);
|
|
11761
|
-
const handleRenderAbstractionTree = (0,
|
|
12169
|
+
const handleRenderAbstractionTree = (0, import_react25.useCallback)((ancestryObject, targetNodeId = null) => {
|
|
11762
12170
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11763
12171
|
if (!ancestryObject || !ancestryObject.abstraction_tree) return;
|
|
11764
12172
|
const { ancestryGroup, nodeObjects, renderer, renderedAncestries } = stateRef.current;
|
|
@@ -11819,7 +12227,7 @@ function XViewScene({
|
|
|
11819
12227
|
stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
|
|
11820
12228
|
tweenToTarget(rootTargetPos, 0.7);
|
|
11821
12229
|
}, [addOrUpdateNodeMesh, tweenToTarget, buildFullAncestryTree, handleClearAncestryVisuals]);
|
|
11822
|
-
const handleReadModeBranchNav = (0,
|
|
12230
|
+
const handleReadModeBranchNav = (0, import_react25.useCallback)((nodeId, action, direction = "right") => {
|
|
11823
12231
|
const { ancestry, branchStack } = readingMode;
|
|
11824
12232
|
if (!ancestry || !ancestry.tree) return;
|
|
11825
12233
|
const allAncestries = ancestryDataRef.current || [];
|
|
@@ -11960,13 +12368,13 @@ function XViewScene({
|
|
|
11960
12368
|
}));
|
|
11961
12369
|
}
|
|
11962
12370
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, tweenToTarget]);
|
|
11963
|
-
const handleReadModeHighlight = (0,
|
|
12371
|
+
const handleReadModeHighlight = (0, import_react25.useCallback)((nodeId) => {
|
|
11964
12372
|
if (stateRef.current.highlightedNodeId !== nodeId) {
|
|
11965
12373
|
stateRef.current.highlightedNodeId = nodeId;
|
|
11966
12374
|
}
|
|
11967
12375
|
setHighlightedNodeId(nodeId);
|
|
11968
12376
|
}, []);
|
|
11969
|
-
const activeNodeBranches = (0,
|
|
12377
|
+
const activeNodeBranches = (0, import_react25.useMemo)(() => {
|
|
11970
12378
|
if (!highlightedNodeId || !readingMode.ancestry || !readingMode.ancestry.tree) return null;
|
|
11971
12379
|
const fullTree = buildFullAncestryTree(
|
|
11972
12380
|
readingMode.ancestry.tree,
|
|
@@ -12003,7 +12411,7 @@ function XViewScene({
|
|
|
12003
12411
|
}
|
|
12004
12412
|
return null;
|
|
12005
12413
|
}, [highlightedNodeId, readingMode.ancestry, buildFullAncestryTree, readingMode.branchStack, ancestryDataRef.current]);
|
|
12006
|
-
const backNavigationInfo = (0,
|
|
12414
|
+
const backNavigationInfo = (0, import_react25.useMemo)(() => {
|
|
12007
12415
|
const { branchStack } = readingMode;
|
|
12008
12416
|
if (!branchStack || branchStack.length === 0) return null;
|
|
12009
12417
|
const lastStep = branchStack[branchStack.length - 1];
|
|
@@ -12014,7 +12422,7 @@ function XViewScene({
|
|
|
12014
12422
|
name: "Voltar para anterior"
|
|
12015
12423
|
};
|
|
12016
12424
|
}, [readingMode.branchStack]);
|
|
12017
|
-
const getReadModeDisplayContext = (0,
|
|
12425
|
+
const getReadModeDisplayContext = (0, import_react25.useMemo)(() => {
|
|
12018
12426
|
const { ancestry, branchStack } = readingMode;
|
|
12019
12427
|
if (!ancestry) return null;
|
|
12020
12428
|
if (branchStack.length === 0) {
|
|
@@ -12055,7 +12463,7 @@ function XViewScene({
|
|
|
12055
12463
|
customProperties: branchProps
|
|
12056
12464
|
};
|
|
12057
12465
|
}, [readingMode, buildFullAncestryTree, ancestryDataRef.current]);
|
|
12058
|
-
const readModeAbstractionTree = (0,
|
|
12466
|
+
const readModeAbstractionTree = (0, import_react25.useMemo)(() => {
|
|
12059
12467
|
if (!readingMode.isActive || !readingMode.ancestry || !readingMode.ancestry.abstraction_tree) {
|
|
12060
12468
|
return null;
|
|
12061
12469
|
}
|
|
@@ -12067,7 +12475,7 @@ function XViewScene({
|
|
|
12067
12475
|
allAncestries
|
|
12068
12476
|
);
|
|
12069
12477
|
}, [readingMode.isActive, readingMode.ancestry, buildFullAncestryTree, sceneVersion]);
|
|
12070
|
-
const handleStartReadingAncestry = (0,
|
|
12478
|
+
const handleStartReadingAncestry = (0, import_react25.useCallback)(
|
|
12071
12479
|
async (ancestryObject) => {
|
|
12072
12480
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
12073
12481
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -12102,7 +12510,7 @@ function XViewScene({
|
|
|
12102
12510
|
},
|
|
12103
12511
|
[handleRenderAncestry, handleRenderAbstractionTree]
|
|
12104
12512
|
);
|
|
12105
|
-
const handleReadModeSectionChange = (0,
|
|
12513
|
+
const handleReadModeSectionChange = (0, import_react25.useCallback)((activeSectionId) => {
|
|
12106
12514
|
const { ancestry, branchStack } = readingMode;
|
|
12107
12515
|
if (!ancestry || !readingMode.isActive) return;
|
|
12108
12516
|
let targetObj = ancestry;
|
|
@@ -12171,10 +12579,10 @@ function XViewScene({
|
|
|
12171
12579
|
}, 0);
|
|
12172
12580
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
12173
12581
|
}, [readingMode, handleRenderAncestry, buildFullAncestryTree, ancestryDataRef.current]);
|
|
12174
|
-
const handleCloseReadMode = (0,
|
|
12582
|
+
const handleCloseReadMode = (0, import_react25.useCallback)(() => {
|
|
12175
12583
|
setReadingMode({ isActive: false, ancestry: null, branchStack: [] });
|
|
12176
12584
|
}, []);
|
|
12177
|
-
const handleAncestrySectionChange = (0,
|
|
12585
|
+
const handleAncestrySectionChange = (0, import_react25.useCallback)((activeSectionId, ancestryOverride = null, rotation = 0) => {
|
|
12178
12586
|
var _a2, _b2;
|
|
12179
12587
|
const currentMode = stateRef.current.ancestry;
|
|
12180
12588
|
let targetObj = ancestryOverride;
|
|
@@ -12226,7 +12634,7 @@ function XViewScene({
|
|
|
12226
12634
|
const renderPayload = { ...targetObj, tree: treeToRender };
|
|
12227
12635
|
handleRenderAncestry(renderPayload, allowedIds, focusTargetId, rotation);
|
|
12228
12636
|
}, [handleRenderAncestry]);
|
|
12229
|
-
const handleEditAncestry = (0,
|
|
12637
|
+
const handleEditAncestry = (0, import_react25.useCallback)(
|
|
12230
12638
|
async (ancestryObject) => {
|
|
12231
12639
|
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
12232
12640
|
if (!ancestryObject || !ancestryObject.tree) {
|
|
@@ -12265,7 +12673,7 @@ function XViewScene({
|
|
|
12265
12673
|
const handleSelectAncestryParent = (nodeId) => {
|
|
12266
12674
|
setAncestryMode((prev) => ({ ...prev, selectedParentId: nodeId }));
|
|
12267
12675
|
};
|
|
12268
|
-
const handleRemoveFromAncestry = (0,
|
|
12676
|
+
const handleRemoveFromAncestry = (0, import_react25.useCallback)((pathToRemove) => {
|
|
12269
12677
|
if (!Array.isArray(pathToRemove) || pathToRemove.length === 0) {
|
|
12270
12678
|
console.warn("Tentativa de remover a raiz ou caminho inv\xE1lido.");
|
|
12271
12679
|
return;
|
|
@@ -12290,7 +12698,7 @@ function XViewScene({
|
|
|
12290
12698
|
return { ...prev, tree: newTree };
|
|
12291
12699
|
});
|
|
12292
12700
|
}, []);
|
|
12293
|
-
const handleSaveAncestry = (0,
|
|
12701
|
+
const handleSaveAncestry = (0, import_react25.useCallback)(
|
|
12294
12702
|
async (ancestryName, ancestryDescription, ancestrySections, keepOpen = false, treeOverride = null, ancestryCustomProps = {}) => {
|
|
12295
12703
|
const treeToUse = treeOverride || ancestryMode.tree;
|
|
12296
12704
|
const { isEditMode, currentAncestryId } = ancestryMode;
|
|
@@ -12494,7 +12902,7 @@ function XViewScene({
|
|
|
12494
12902
|
});
|
|
12495
12903
|
setEditingAncestryRel({ visible: false, data: null, path: null });
|
|
12496
12904
|
};
|
|
12497
|
-
const handleDeleteAncestry = (0,
|
|
12905
|
+
const handleDeleteAncestry = (0, import_react25.useCallback)(
|
|
12498
12906
|
async (ancestryIdToDelete) => {
|
|
12499
12907
|
if (!ancestryIdToDelete) {
|
|
12500
12908
|
alert("ID da ancestralidade n\xE3o encontrado.");
|
|
@@ -12556,20 +12964,20 @@ function XViewScene({
|
|
|
12556
12964
|
},
|
|
12557
12965
|
[save_view_data, delete_file_action]
|
|
12558
12966
|
);
|
|
12559
|
-
const handleOpenAncestryBoard = (0,
|
|
12967
|
+
const handleOpenAncestryBoard = (0, import_react25.useCallback)(() => {
|
|
12560
12968
|
setIsAncestryBoardOpen(true);
|
|
12561
12969
|
}, []);
|
|
12562
|
-
const handleSelectAncestryFromBoard = (0,
|
|
12970
|
+
const handleSelectAncestryFromBoard = (0, import_react25.useCallback)((ancestry) => {
|
|
12563
12971
|
setIsAncestryBoardOpen(false);
|
|
12564
12972
|
setIsSidebarOpen(false);
|
|
12565
12973
|
handleStartReadingAncestry(ancestry);
|
|
12566
12974
|
}, [handleStartReadingAncestry]);
|
|
12567
|
-
const handleSaveAncestryBoard = (0,
|
|
12975
|
+
const handleSaveAncestryBoard = (0, import_react25.useCallback)(async (groups) => {
|
|
12568
12976
|
if (!sceneConfigId || !viewParams || !session) return;
|
|
12569
12977
|
const sceneType = (viewParams.type || "").toLowerCase().includes("database") ? "database" : "view";
|
|
12570
12978
|
await save_ancestry_board_action(sceneConfigId, sceneType, groups, session, ownerId);
|
|
12571
12979
|
}, [sceneConfigId, viewParams, session, save_ancestry_board_action, ownerId]);
|
|
12572
|
-
const existingNodeTypes = (0,
|
|
12980
|
+
const existingNodeTypes = (0, import_react25.useMemo)(() => {
|
|
12573
12981
|
if (!parentDataRef.current) {
|
|
12574
12982
|
return [];
|
|
12575
12983
|
}
|
|
@@ -12579,7 +12987,7 @@ function XViewScene({
|
|
|
12579
12987
|
})).filter(Boolean);
|
|
12580
12988
|
return [...new Set(allTypes)];
|
|
12581
12989
|
}, [parentDataRef.current, sceneVersion]);
|
|
12582
|
-
const searchableDbNodes = (0,
|
|
12990
|
+
const searchableDbNodes = (0, import_react25.useMemo)(() => {
|
|
12583
12991
|
if (!parentDataRef.current) {
|
|
12584
12992
|
return [];
|
|
12585
12993
|
}
|
|
@@ -12588,13 +12996,14 @@ function XViewScene({
|
|
|
12588
12996
|
return !((_a2 = node.version_node) == null ? void 0 : _a2.is_version);
|
|
12589
12997
|
});
|
|
12590
12998
|
}, [parentDataRef.current, sceneVersion]);
|
|
12591
|
-
const handleAddExistingNode = (0,
|
|
12999
|
+
const handleAddExistingNode = (0, import_react25.useCallback)(
|
|
12592
13000
|
(nodeId) => {
|
|
12593
13001
|
return userActionHandlers.handleAddExistingNodeById(actionHandlerContext, nodeId);
|
|
12594
13002
|
},
|
|
12595
13003
|
[actionHandlerContext]
|
|
12596
13004
|
);
|
|
12597
|
-
const handleSaveCurrentView = (0,
|
|
13005
|
+
const handleSaveCurrentView = (0, import_react25.useCallback)(async () => {
|
|
13006
|
+
var _a2, _b2, _c2;
|
|
12598
13007
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12599
13008
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12600
13009
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12616,25 +13025,30 @@ function XViewScene({
|
|
|
12616
13025
|
const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
|
|
12617
13026
|
return serializableLinkData;
|
|
12618
13027
|
});
|
|
13028
|
+
sceneDataRef.current.nodes = currentNodes;
|
|
13029
|
+
sceneDataRef.current.links = currentLinks;
|
|
13030
|
+
const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
|
|
12619
13031
|
const sceneFileData = {
|
|
12620
13032
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
12621
13033
|
nodes: currentNodes,
|
|
12622
|
-
links: currentLinks
|
|
13034
|
+
links: currentLinks,
|
|
13035
|
+
quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
|
|
13036
|
+
quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || []
|
|
12623
13037
|
};
|
|
12624
13038
|
try {
|
|
12625
13039
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
12626
13040
|
} catch (error) {
|
|
12627
13041
|
console.error("Erro na chamada de save_view_data:", error);
|
|
12628
13042
|
}
|
|
12629
|
-
}, [sceneSaveUrl, save_view_data]);
|
|
12630
|
-
const allAvailableNodes = (0,
|
|
13043
|
+
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
13044
|
+
const allAvailableNodes = (0, import_react25.useMemo)(() => {
|
|
12631
13045
|
if (!parentDataRef.current) return [];
|
|
12632
13046
|
return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
12633
13047
|
}, [sceneVersion, isInitialized]);
|
|
12634
|
-
const allAvailableAncestries = (0,
|
|
13048
|
+
const allAvailableAncestries = (0, import_react25.useMemo)(() => {
|
|
12635
13049
|
return ancestryDataRef.current || [];
|
|
12636
13050
|
}, [sceneVersion, isInitialized]);
|
|
12637
|
-
const handleOpenReference = (0,
|
|
13051
|
+
const handleOpenReference = (0, import_react25.useCallback)((referenceData) => {
|
|
12638
13052
|
const { type, id } = referenceData;
|
|
12639
13053
|
if (type === "node") {
|
|
12640
13054
|
const targetNode = allAvailableNodes.find((n) => String(n.id) === String(id));
|
|
@@ -12661,17 +13075,17 @@ function XViewScene({
|
|
|
12661
13075
|
}
|
|
12662
13076
|
}
|
|
12663
13077
|
}, [allAvailableNodes, allAvailableAncestries, handleEditAncestry, tweenToTarget]);
|
|
12664
|
-
const handleToggleAncestryAddMode = (0,
|
|
13078
|
+
const handleToggleAncestryAddMode = (0, import_react25.useCallback)(() => {
|
|
12665
13079
|
setAncestryMode((prev) => ({ ...prev, isAddingNodes: !prev.isAddingNodes }));
|
|
12666
13080
|
}, []);
|
|
12667
|
-
const handleFocusNode = (0,
|
|
13081
|
+
const handleFocusNode = (0, import_react25.useCallback)((nodeData) => {
|
|
12668
13082
|
if (!nodeData) return;
|
|
12669
13083
|
const nodeMesh = stateRef.current.nodeObjects[String(nodeData.id)];
|
|
12670
13084
|
if (nodeMesh) {
|
|
12671
13085
|
tweenToTarget(nodeMesh, 1.2);
|
|
12672
13086
|
}
|
|
12673
13087
|
}, [tweenToTarget]);
|
|
12674
|
-
const availableDatasets = (0,
|
|
13088
|
+
const availableDatasets = (0, import_react25.useMemo)(() => {
|
|
12675
13089
|
if (!sceneDataRef.current || !parentDataRef.current) return [];
|
|
12676
13090
|
return sceneDataRef.current.parent_dbs.map((db) => {
|
|
12677
13091
|
var _a2;
|
|
@@ -12683,7 +13097,7 @@ function XViewScene({
|
|
|
12683
13097
|
}, [sceneVersion, isInitialized]);
|
|
12684
13098
|
const sourceNodeDatasetId = creationMode.sourceNodeData ? (_b = stateRef.current.nodeIdToParentFileMap.get(String(creationMode.sourceNodeData.id))) == null ? void 0 : _b.parentFileId : null;
|
|
12685
13099
|
const detailsNodeDatasetInfo = detailsNode ? stateRef.current.nodeIdToParentFileMap.get(String(detailsNode.id)) : null;
|
|
12686
|
-
(0,
|
|
13100
|
+
(0, import_react25.useEffect)(() => {
|
|
12687
13101
|
if (isInitialized && focusNodeId && !hasFocusedInitial) {
|
|
12688
13102
|
const nodeObjects = stateRef.current.nodeObjects || {};
|
|
12689
13103
|
const targetMesh = nodeObjects[String(focusNodeId)];
|
|
@@ -12697,7 +13111,7 @@ function XViewScene({
|
|
|
12697
13111
|
}
|
|
12698
13112
|
}
|
|
12699
13113
|
}, [isInitialized, sceneVersion, focusNodeId, hasFocusedInitial, tweenToTarget]);
|
|
12700
|
-
(0,
|
|
13114
|
+
(0, import_react25.useEffect)(() => {
|
|
12701
13115
|
if (isInitialized && focusAncestryId && !hasOpenedInitialAncestry) {
|
|
12702
13116
|
const ancestries = ancestryDataRef.current || [];
|
|
12703
13117
|
const targetAncestry = ancestries.find((a) => String(a.ancestry_id) === String(focusAncestryId));
|
|
@@ -12712,20 +13126,20 @@ function XViewScene({
|
|
|
12712
13126
|
}
|
|
12713
13127
|
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
12714
13128
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
12715
|
-
return /* @__PURE__ */
|
|
13129
|
+
return /* @__PURE__ */ import_react25.default.createElement(LoadingScreen, null);
|
|
12716
13130
|
}
|
|
12717
13131
|
if (permissionStatus === "denied") {
|
|
12718
|
-
return /* @__PURE__ */
|
|
13132
|
+
return /* @__PURE__ */ import_react25.default.createElement("div", { className: "flex flex-col items-center justify-center min-h-screen w-full bg-slate-950 text-white" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "bg-slate-900/50 p-8 rounded-2xl border border-slate-800 shadow-2xl text-center max-w-md" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "mb-4 text-red-500" }, /* @__PURE__ */ import_react25.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", className: "w-16 h-16 mx-auto" }, /* @__PURE__ */ import_react25.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" }))), /* @__PURE__ */ import_react25.default.createElement("h2", { className: "text-2xl font-bold mb-2" }, "Acesso Negado"), /* @__PURE__ */ import_react25.default.createElement("p", { className: "text-slate-400 mb-6" }, "Voc\xEA n\xE3o tem permiss\xE3o para acessar este conte\xFAdo. Solicite acesso ao propriet\xE1rio ou verifique se est\xE1 na conta correta."), /* @__PURE__ */ import_react25.default.createElement(
|
|
12719
13133
|
"button",
|
|
12720
13134
|
{
|
|
12721
13135
|
onClick: () => router.push("/dashboard/scenes"),
|
|
12722
13136
|
className: "flex items-center justify-center gap-2 w-full py-3 px-4 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors font-medium"
|
|
12723
13137
|
},
|
|
12724
|
-
/* @__PURE__ */
|
|
13138
|
+
/* @__PURE__ */ import_react25.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", className: "w-5 h-5" }, /* @__PURE__ */ import_react25.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18" })),
|
|
12725
13139
|
"Voltar para Scenes"
|
|
12726
13140
|
)));
|
|
12727
13141
|
}
|
|
12728
|
-
return /* @__PURE__ */
|
|
13142
|
+
return /* @__PURE__ */ import_react25.default.createElement(
|
|
12729
13143
|
"div",
|
|
12730
13144
|
{
|
|
12731
13145
|
ref: mountRef,
|
|
@@ -12737,7 +13151,7 @@ function XViewScene({
|
|
|
12737
13151
|
cursor: stateRef.current.connection.isActive || stateRef.current.relink.isActive || ancestryMode.isActive ? "crosshair" : creationMode.isActive ? "default" : "grab"
|
|
12738
13152
|
}
|
|
12739
13153
|
},
|
|
12740
|
-
userPermissionRole !== "link_viewer" && /* @__PURE__ */
|
|
13154
|
+
userPermissionRole !== "link_viewer" && /* @__PURE__ */ import_react25.default.createElement(
|
|
12741
13155
|
XViewSidebar,
|
|
12742
13156
|
{
|
|
12743
13157
|
dbNodes: searchableDbNodes,
|
|
@@ -12757,7 +13171,7 @@ function XViewScene({
|
|
|
12757
13171
|
userRole: userPermissionRole
|
|
12758
13172
|
}
|
|
12759
13173
|
),
|
|
12760
|
-
creationMode.isActive && /* @__PURE__ */
|
|
13174
|
+
creationMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
12761
13175
|
InSceneCreationForm,
|
|
12762
13176
|
{
|
|
12763
13177
|
onSave: (data) => userActionHandlers.handleSaveNode(actionHandlerContext, data),
|
|
@@ -12782,7 +13196,7 @@ function XViewScene({
|
|
|
12782
13196
|
availableAncestries: allAvailableAncestries
|
|
12783
13197
|
}
|
|
12784
13198
|
),
|
|
12785
|
-
versionMode.isActive && /* @__PURE__ */
|
|
13199
|
+
versionMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
12786
13200
|
InSceneVersionForm,
|
|
12787
13201
|
{
|
|
12788
13202
|
onSave: (data) => userActionHandlers.handleSaveVersionNode(actionHandlerContext, data),
|
|
@@ -12801,13 +13215,27 @@ function XViewScene({
|
|
|
12801
13215
|
availableAncestries: allAvailableAncestries
|
|
12802
13216
|
}
|
|
12803
13217
|
),
|
|
12804
|
-
|
|
13218
|
+
questMode.isActive && /* @__PURE__ */ import_react25.default.createElement(
|
|
13219
|
+
InSceneQuestForm,
|
|
13220
|
+
{
|
|
13221
|
+
onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
|
|
13222
|
+
onCancel: () => setQuestMode({ isActive: false }),
|
|
13223
|
+
style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
|
|
13224
|
+
refEl: formRef,
|
|
13225
|
+
onOpenImageViewer: handleOpenImageViewer,
|
|
13226
|
+
onMentionClick: handleAddExistingNode,
|
|
13227
|
+
onUploadFile: upload_file_action,
|
|
13228
|
+
availableNodes: allAvailableNodes,
|
|
13229
|
+
availableAncestries: allAvailableAncestries
|
|
13230
|
+
}
|
|
13231
|
+
),
|
|
13232
|
+
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react25.default.createElement(
|
|
12805
13233
|
"div",
|
|
12806
13234
|
{
|
|
12807
13235
|
className: `ui-overlay absolute group rounded-2xl border border-white/10 bg-slate-950/70 backdrop-blur-xl shadow-[0_20px_80px_rgba(0,0,0,0.6)] ring-1 ring-white/10 text-white overflow-hidden flex flex-col ${isReadModeResizing ? "transition-none" : "transition-all duration-300 ease-out"}`,
|
|
12808
13236
|
style: { top: 16, right: 16, zIndex: 1100, maxHeight: "calc(100vh - 32px)", width: `${readModeWidth}px`, maxWidth: "92vw" }
|
|
12809
13237
|
},
|
|
12810
|
-
/* @__PURE__ */
|
|
13238
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12811
13239
|
"div",
|
|
12812
13240
|
{
|
|
12813
13241
|
onPointerDown: (e) => {
|
|
@@ -12818,7 +13246,7 @@ function XViewScene({
|
|
|
12818
13246
|
title: "Arraste para redimensionar"
|
|
12819
13247
|
}
|
|
12820
13248
|
),
|
|
12821
|
-
/* @__PURE__ */
|
|
13249
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12822
13250
|
DescriptionReadModePanel,
|
|
12823
13251
|
{
|
|
12824
13252
|
key: readingMode.branchStack.length > 0 ? readingMode.branchStack[readingMode.branchStack.length - 1].branchId : readingMode.ancestry.ancestry_id,
|
|
@@ -12853,7 +13281,7 @@ function XViewScene({
|
|
|
12853
13281
|
}
|
|
12854
13282
|
)
|
|
12855
13283
|
),
|
|
12856
|
-
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */
|
|
13284
|
+
ancestryMode.isActive && ancestryMode.tree && /* @__PURE__ */ import_react25.default.createElement(
|
|
12857
13285
|
CreateAncestryPanel,
|
|
12858
13286
|
{
|
|
12859
13287
|
ancestryMode,
|
|
@@ -12880,7 +13308,7 @@ function XViewScene({
|
|
|
12880
13308
|
onRenderAbstractionTree: (data, targetId) => handleRenderAbstractionTree(data, targetId)
|
|
12881
13309
|
}
|
|
12882
13310
|
),
|
|
12883
|
-
editingAncestryRel.visible && /* @__PURE__ */
|
|
13311
|
+
editingAncestryRel.visible && /* @__PURE__ */ import_react25.default.createElement(
|
|
12884
13312
|
AncestryRelationshipPanel,
|
|
12885
13313
|
{
|
|
12886
13314
|
data: editingAncestryRel.data,
|
|
@@ -12894,7 +13322,7 @@ function XViewScene({
|
|
|
12894
13322
|
onUploadFile: upload_file_action
|
|
12895
13323
|
}
|
|
12896
13324
|
),
|
|
12897
|
-
detailsNode && /* @__PURE__ */
|
|
13325
|
+
detailsNode && /* @__PURE__ */ import_react25.default.createElement(
|
|
12898
13326
|
NodeDetailsPanel,
|
|
12899
13327
|
{
|
|
12900
13328
|
node: detailsNode,
|
|
@@ -12921,7 +13349,7 @@ function XViewScene({
|
|
|
12921
13349
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName
|
|
12922
13350
|
}
|
|
12923
13351
|
),
|
|
12924
|
-
detailsLink && /* @__PURE__ */
|
|
13352
|
+
detailsLink && /* @__PURE__ */ import_react25.default.createElement(
|
|
12925
13353
|
RelationshipDetailsPanel,
|
|
12926
13354
|
{
|
|
12927
13355
|
link: detailsLink,
|
|
@@ -12935,7 +13363,7 @@ function XViewScene({
|
|
|
12935
13363
|
userRole: userPermissionRole
|
|
12936
13364
|
}
|
|
12937
13365
|
),
|
|
12938
|
-
ancestryLinkDetails && /* @__PURE__ */
|
|
13366
|
+
ancestryLinkDetails && /* @__PURE__ */ import_react25.default.createElement(
|
|
12939
13367
|
AncestryLinkDetailsPanel,
|
|
12940
13368
|
{
|
|
12941
13369
|
data: ancestryLinkDetails,
|
|
@@ -12946,7 +13374,7 @@ function XViewScene({
|
|
|
12946
13374
|
onUploadFile: upload_file_action
|
|
12947
13375
|
}
|
|
12948
13376
|
),
|
|
12949
|
-
/* @__PURE__ */
|
|
13377
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12950
13378
|
"div",
|
|
12951
13379
|
{
|
|
12952
13380
|
ref: tooltipRef,
|
|
@@ -12973,7 +13401,7 @@ function XViewScene({
|
|
|
12973
13401
|
}
|
|
12974
13402
|
}
|
|
12975
13403
|
),
|
|
12976
|
-
/* @__PURE__ */
|
|
13404
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
12977
13405
|
ContextMenu,
|
|
12978
13406
|
{
|
|
12979
13407
|
data: contextMenu,
|
|
@@ -12996,7 +13424,7 @@ function XViewScene({
|
|
|
12996
13424
|
onFocusNode: handleFocusNode
|
|
12997
13425
|
}
|
|
12998
13426
|
),
|
|
12999
|
-
/* @__PURE__ */
|
|
13427
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13000
13428
|
MultiNodeContextMenu,
|
|
13001
13429
|
{
|
|
13002
13430
|
data: multiContextMenu,
|
|
@@ -13007,7 +13435,7 @@ function XViewScene({
|
|
|
13007
13435
|
onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
|
|
13008
13436
|
}
|
|
13009
13437
|
),
|
|
13010
|
-
/* @__PURE__ */
|
|
13438
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13011
13439
|
RelationshipContextMenu,
|
|
13012
13440
|
{
|
|
13013
13441
|
data: relationshipMenu,
|
|
@@ -13025,8 +13453,8 @@ function XViewScene({
|
|
|
13025
13453
|
onDelete: (data) => userActionHandlers.handleDeleteLink(actionHandlerContext, data)
|
|
13026
13454
|
}
|
|
13027
13455
|
),
|
|
13028
|
-
/* @__PURE__ */
|
|
13029
|
-
/* @__PURE__ */
|
|
13456
|
+
/* @__PURE__ */ import_react25.default.createElement(ImageViewer, { data: imageViewer, onClose: () => setImageViewer({ ...imageViewer, visible: false }) }),
|
|
13457
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13030
13458
|
AncestryBoard,
|
|
13031
13459
|
{
|
|
13032
13460
|
isOpen: isAncestryBoardOpen,
|
|
@@ -13039,7 +13467,7 @@ function XViewScene({
|
|
|
13039
13467
|
userRole: userPermissionRole
|
|
13040
13468
|
}
|
|
13041
13469
|
),
|
|
13042
|
-
/* @__PURE__ */
|
|
13470
|
+
/* @__PURE__ */ import_react25.default.createElement(
|
|
13043
13471
|
ImportParentFileModal,
|
|
13044
13472
|
{
|
|
13045
13473
|
isOpen: isImportModalOpen,
|
|
@@ -13083,6 +13511,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13083
13511
|
}
|
|
13084
13512
|
const sceneData = sceneResponse.data;
|
|
13085
13513
|
const parentDbObjects = sceneData.parent_dbs || [];
|
|
13514
|
+
if (type && type.toLowerCase().includes("database")) {
|
|
13515
|
+
const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
|
|
13516
|
+
if (!selfExists) {
|
|
13517
|
+
parentDbObjects.push({ db_id: scene_config, owner_id });
|
|
13518
|
+
}
|
|
13519
|
+
}
|
|
13086
13520
|
const parentResponsesPromises = parentDbObjects.map(
|
|
13087
13521
|
(db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
|
|
13088
13522
|
);
|
|
@@ -13100,11 +13534,28 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13100
13534
|
);
|
|
13101
13535
|
}
|
|
13102
13536
|
}
|
|
13537
|
+
if (type && type.toLowerCase() === "view") {
|
|
13538
|
+
parentData[scene_config] = {
|
|
13539
|
+
dataset_name: "Quests Internas (View)",
|
|
13540
|
+
nodes: sceneData.quest_nodes || [],
|
|
13541
|
+
links: sceneData.quest_links || []
|
|
13542
|
+
};
|
|
13543
|
+
}
|
|
13103
13544
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
13104
13545
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13105
13546
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
13106
13547
|
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
13107
|
-
const validatedNodes = (sceneData.nodes || []).map((sceneNode) =>
|
|
13548
|
+
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
13549
|
+
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
13550
|
+
if (nodeTypes.includes("quest")) {
|
|
13551
|
+
return sceneNode;
|
|
13552
|
+
}
|
|
13553
|
+
const dbNode = parentNodeMap.get(String(sceneNode.id));
|
|
13554
|
+
if (dbNode) {
|
|
13555
|
+
return { ...dbNode, ...sceneNode };
|
|
13556
|
+
}
|
|
13557
|
+
return null;
|
|
13558
|
+
}).filter(Boolean);
|
|
13108
13559
|
const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
|
|
13109
13560
|
const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
|
|
13110
13561
|
const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
|