@lv-x-software-house/x_view 1.2.8-dev.2 → 1.2.8-dev.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +577 -468
  2. package/dist/index.mjs +615 -506
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import React32, {
3
3
  useCallback as useCallback7,
4
4
  useEffect as useEffect25,
5
- useRef as useRef21,
5
+ useRef as useRef22,
6
6
  useState as useState30,
7
7
  useMemo as useMemo14
8
8
  } from "react";
@@ -283,7 +283,12 @@ var updateExistingNodeVisuals = (state, updatedNode) => {
283
283
  if (oldLabelObject.material) oldLabelObject.material.dispose();
284
284
  }
285
285
  }
286
- const newMesh = createNodeMesh(updatedNode, position, state.glowTexture, hadQuestDateLabel);
286
+ const newMesh = createNodeMesh(
287
+ updatedNode,
288
+ position,
289
+ state.glowTexture,
290
+ hadQuestDateLabel
291
+ );
287
292
  if (oldTimelineBar) {
288
293
  newMesh.userData.timelineIntervalBar = oldTimelineBar;
289
294
  }
@@ -835,7 +840,12 @@ var removeNodeFromScene = (state, nodeId) => {
835
840
  var addStandaloneNodeToScene = (state, nodeData, position, forceShowQuestDate = false) => {
836
841
  const { graphGroup, nodeObjects, clickableNodes, glowTexture } = state;
837
842
  if (!graphGroup) return;
838
- const mesh = createNodeMesh(nodeData, position, glowTexture, forceShowQuestDate);
843
+ const mesh = createNodeMesh(
844
+ nodeData,
845
+ position,
846
+ glowTexture,
847
+ forceShowQuestDate
848
+ );
839
849
  mesh.scale.set(0.01, 0.01, 0.01);
840
850
  graphGroup.add(mesh);
841
851
  if (mesh.userData.labelObject) {
@@ -1053,7 +1063,9 @@ var userActionHandlers = {
1053
1063
  if (isCrossDataset) {
1054
1064
  graphDataRef.current[finalTargetDatasetId] = targetDataToUpdate;
1055
1065
  }
1056
- if (sceneDataRef.current.parent_dbs.some((db) => String(db.db_id) === String(sourceParentInfo.parentFileId))) {
1066
+ if (sceneDataRef.current.parent_dbs.some(
1067
+ (db) => String(db.db_id) === String(sourceParentInfo.parentFileId)
1068
+ )) {
1057
1069
  }
1058
1070
  const finalPosition = stateRef.current.ghostElements.node.position.clone();
1059
1071
  addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
@@ -1248,7 +1260,10 @@ var userActionHandlers = {
1248
1260
  context.sceneSaveUrl,
1249
1261
  viewFilePayload
1250
1262
  );
1251
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
1263
+ const questSaveUrl = context.sceneSaveUrl.replace(
1264
+ "x_view_scenes",
1265
+ "x_view_quests"
1266
+ );
1252
1267
  await context.actions.save_view_data(questSaveUrl, questFilePayload);
1253
1268
  } else {
1254
1269
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -1324,7 +1339,12 @@ var userActionHandlers = {
1324
1339
  )
1325
1340
  );
1326
1341
  targetFinalPositions.push(endPosition);
1327
- const targetMesh = createNodeMesh(nodeData, startPosition, glowTexture);
1342
+ const targetMesh = createNodeMesh(
1343
+ nodeData,
1344
+ startPosition,
1345
+ glowTexture,
1346
+ !!nodeData.is_quest
1347
+ );
1328
1348
  targetMesh.scale.set(0.01, 0.01, 0.01);
1329
1349
  graphGroup.add(targetMesh);
1330
1350
  if (targetMesh.userData.labelObject) {
@@ -1476,10 +1496,16 @@ var userActionHandlers = {
1476
1496
  context.sceneConfigId,
1477
1497
  context.ownerId
1478
1498
  );
1479
- if (!sourceParentInfo || !sourceParentInfo.ownerId) {
1499
+ const targetParentInfo = getParentFileInfoForNode(
1500
+ graphDataRef.current,
1501
+ sceneDataRef.current,
1502
+ targetNodeData.id,
1503
+ context.sceneConfigId,
1504
+ context.ownerId
1505
+ );
1506
+ if (!sourceParentInfo || !sourceParentInfo.ownerId || !targetParentInfo) {
1480
1507
  console.error(
1481
- "N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:",
1482
- sourceNodeData.id
1508
+ "N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para os Nodes da conex\xE3o."
1483
1509
  );
1484
1510
  alert(
1485
1511
  "Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio."
@@ -1487,9 +1513,13 @@ var userActionHandlers = {
1487
1513
  userActionHandlers.handleCancelConnection(context);
1488
1514
  return;
1489
1515
  }
1490
- const { parentFileId: sourceParentFileId, ownerId: sourceOwnerId } = sourceParentInfo;
1491
- const parentFileIdToSave = sourceParentFileId;
1492
- const ownerIdToSave = sourceOwnerId;
1516
+ let parentInfoToSave = sourceParentInfo;
1517
+ const isSourceQuest = sourceParentInfo.parentFileId === context.sceneConfigId;
1518
+ const isTargetQuest = targetParentInfo.parentFileId === context.sceneConfigId;
1519
+ if (isSourceQuest || isTargetQuest) {
1520
+ parentInfoToSave = { parentFileId: context.sceneConfigId, ownerId: context.ownerId };
1521
+ }
1522
+ const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
1493
1523
  const newLink = {
1494
1524
  id: `link_${short.generate()}`,
1495
1525
  source: sourceNodeData.id,
@@ -1503,20 +1533,19 @@ var userActionHandlers = {
1503
1533
  const viewFilePayload = {
1504
1534
  parent_dbs: sceneDataRef.current.parent_dbs,
1505
1535
  nodes: sceneDataRef.current.nodes,
1506
- links: sceneDataRef.current.links,
1507
- quest_counter: sceneDataRef.current.quest_counter || 1
1508
- };
1509
- const questFilePayload = {
1510
- nodes: specificParentData.nodes,
1511
- links: specificParentData.links,
1512
- milestones: sceneDataRef.current.milestones || []
1536
+ links: sceneDataRef.current.links
1513
1537
  };
1514
1538
  await context.actions.save_view_data(
1515
1539
  context.sceneSaveUrl,
1516
1540
  viewFilePayload
1517
1541
  );
1518
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
1519
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
1542
+ if (context.actions.upsert_quest_link_firestore) {
1543
+ await context.actions.upsert_quest_link_firestore(
1544
+ context.ownerId,
1545
+ context.sceneConfigId,
1546
+ newLink
1547
+ );
1548
+ }
1520
1549
  } else {
1521
1550
  const specificParentData = JSON.parse(
1522
1551
  JSON.stringify(graphDataRef.current[parentFileIdToSave])
@@ -1665,18 +1694,12 @@ var userActionHandlers = {
1665
1694
  const viewFilePayload = {
1666
1695
  parent_dbs: sceneDataRef.current.parent_dbs,
1667
1696
  nodes: sceneDataRef.current.nodes,
1668
- links: sceneDataRef.current.links,
1669
- quest_counter: sceneDataRef.current.quest_counter || 1
1670
- };
1671
- const questFilePayload = {
1672
- nodes: data.nodes,
1673
- links: data.links,
1674
- milestones: sceneDataRef.current.milestones || []
1697
+ links: sceneDataRef.current.links
1675
1698
  };
1676
- const p1 = context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
1677
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
1678
- const p2 = context.actions.save_view_data(questSaveUrl, questFilePayload);
1679
- return Promise.all([p1, p2]);
1699
+ return context.actions.save_view_data(
1700
+ context.sceneSaveUrl,
1701
+ viewFilePayload
1702
+ );
1680
1703
  } else {
1681
1704
  return context.actions.save_view_data(
1682
1705
  `x_view_dbs/${fileOwnerId}/${fileId}`,
@@ -1701,6 +1724,15 @@ var userActionHandlers = {
1701
1724
  updatedOriginalParentData
1702
1725
  )
1703
1726
  );
1727
+ if (oldGoverningFileId === context.sceneConfigId && context.actions.delete_quest_link_firestore) {
1728
+ savePromises.push(
1729
+ context.actions.delete_quest_link_firestore(
1730
+ context.ownerId,
1731
+ context.sceneConfigId,
1732
+ linkId
1733
+ )
1734
+ );
1735
+ }
1704
1736
  const updatedNewParentData = JSON.parse(
1705
1737
  JSON.stringify(graphDataRef.current[newGoverningFileId])
1706
1738
  );
@@ -1714,6 +1746,15 @@ var userActionHandlers = {
1714
1746
  updatedNewParentData
1715
1747
  )
1716
1748
  );
1749
+ if (newGoverningFileId === context.sceneConfigId && context.actions.upsert_quest_link_firestore) {
1750
+ savePromises.push(
1751
+ context.actions.upsert_quest_link_firestore(
1752
+ context.ownerId,
1753
+ context.sceneConfigId,
1754
+ newLinkData
1755
+ )
1756
+ );
1757
+ }
1717
1758
  } else {
1718
1759
  const updatedParentData = JSON.parse(
1719
1760
  JSON.stringify(graphDataRef.current[oldGoverningFileId])
@@ -1730,6 +1771,15 @@ var userActionHandlers = {
1730
1771
  updatedParentData
1731
1772
  )
1732
1773
  );
1774
+ if (oldGoverningFileId === context.sceneConfigId && context.actions.upsert_quest_link_firestore) {
1775
+ savePromises.push(
1776
+ context.actions.upsert_quest_link_firestore(
1777
+ context.ownerId,
1778
+ context.sceneConfigId,
1779
+ newLinkData
1780
+ )
1781
+ );
1782
+ }
1733
1783
  }
1734
1784
  try {
1735
1785
  await Promise.all(savePromises);
@@ -1760,14 +1810,21 @@ var userActionHandlers = {
1760
1810
  );
1761
1811
  return;
1762
1812
  }
1763
- const parentInfo = getParentFileInfoForNode(
1813
+ const sourceParentInfo = getParentFileInfoForNode(
1764
1814
  graphDataRef.current,
1765
1815
  sceneDataRef.current,
1766
1816
  linkObject.userData.source,
1767
1817
  context.sceneConfigId,
1768
1818
  context.ownerId
1769
1819
  );
1770
- if (!parentInfo || !parentInfo.ownerId) {
1820
+ const targetParentInfo = getParentFileInfoForNode(
1821
+ graphDataRef.current,
1822
+ sceneDataRef.current,
1823
+ linkObject.userData.target,
1824
+ context.sceneConfigId,
1825
+ context.ownerId
1826
+ );
1827
+ if (!sourceParentInfo || !sourceParentInfo.ownerId) {
1771
1828
  console.error(
1772
1829
  "N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:",
1773
1830
  linkIdToDelete
@@ -1777,6 +1834,12 @@ var userActionHandlers = {
1777
1834
  );
1778
1835
  return;
1779
1836
  }
1837
+ let parentInfo = sourceParentInfo;
1838
+ const isSourceQuest = sourceParentInfo.parentFileId === context.sceneConfigId;
1839
+ const isTargetQuest = (targetParentInfo == null ? void 0 : targetParentInfo.parentFileId) === context.sceneConfigId;
1840
+ if (isSourceQuest || isTargetQuest) {
1841
+ parentInfo = { parentFileId: context.sceneConfigId, ownerId: context.ownerId };
1842
+ }
1780
1843
  const { parentFileId, ownerId } = parentInfo;
1781
1844
  const srcName = ((_c = (_b = (_a = linkObject.userData) == null ? void 0 : _a.sourceNode) == null ? void 0 : _b.userData) == null ? void 0 : _c.name) ?? linkObject.userData.source;
1782
1845
  const tgtName = ((_f = (_e = (_d = linkObject.userData) == null ? void 0 : _d.targetNode) == null ? void 0 : _e.userData) == null ? void 0 : _f.name) ?? linkObject.userData.target;
@@ -1789,8 +1852,6 @@ var userActionHandlers = {
1789
1852
  specificParentData.links = newLinks;
1790
1853
  let filenameToSave;
1791
1854
  let payloadToSave;
1792
- let questSaveUrl;
1793
- let questFilePayload;
1794
1855
  const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
1795
1856
  if (isView && parentFileId === context.sceneConfigId) {
1796
1857
  filenameToSave = context.sceneSaveUrl;
@@ -1800,14 +1861,7 @@ var userActionHandlers = {
1800
1861
  payloadToSave = {
1801
1862
  parent_dbs: sceneDataRef.current.parent_dbs,
1802
1863
  nodes: sceneDataRef.current.nodes,
1803
- links: sceneDataRef.current.links,
1804
- quest_counter: sceneDataRef.current.quest_counter || 1
1805
- };
1806
- questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
1807
- questFilePayload = {
1808
- nodes: specificParentData.nodes,
1809
- links: specificParentData.links,
1810
- milestones: sceneDataRef.current.milestones || []
1864
+ links: sceneDataRef.current.links
1811
1865
  };
1812
1866
  } else {
1813
1867
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -1815,8 +1869,12 @@ var userActionHandlers = {
1815
1869
  }
1816
1870
  try {
1817
1871
  await context.actions.save_view_data(filenameToSave, payloadToSave);
1818
- if (questSaveUrl && questFilePayload) {
1819
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
1872
+ if (isView && parentFileId === context.sceneConfigId && context.actions.delete_quest_link_firestore) {
1873
+ await context.actions.delete_quest_link_firestore(
1874
+ context.ownerId,
1875
+ context.sceneConfigId,
1876
+ linkIdToDelete
1877
+ );
1820
1878
  }
1821
1879
  graphDataRef.current[parentFileId] = specificParentData;
1822
1880
  setters.setDetailsLink(
@@ -2045,16 +2103,30 @@ var userActionHandlers = {
2045
2103
  payloadToSave = {
2046
2104
  parent_dbs: sceneDataRef.current.parent_dbs,
2047
2105
  nodes: sceneDataRef.current.nodes,
2048
- links: sceneDataRef.current.links,
2049
- quest_counter: sceneDataRef.current.quest_counter || 1
2050
- };
2051
- const questFilePayload = {
2052
- nodes: originalData.nodes,
2053
- links: originalData.links,
2054
- milestones: sceneDataRef.current.milestones || []
2106
+ links: sceneDataRef.current.links
2055
2107
  };
2056
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
2057
- savePromises.push(context.actions.save_view_data(questSaveUrl, questFilePayload));
2108
+ if (context.actions.delete_quest_firestore) {
2109
+ nodesToDelete.forEach((nodeIdToDelete) => {
2110
+ savePromises.push(
2111
+ context.actions.delete_quest_firestore(
2112
+ context.ownerId,
2113
+ context.sceneConfigId,
2114
+ nodeIdToDelete
2115
+ )
2116
+ );
2117
+ });
2118
+ if (context.actions.delete_quest_link_firestore) {
2119
+ linksToDelete.forEach((linkIdToDelete) => {
2120
+ savePromises.push(
2121
+ context.actions.delete_quest_link_firestore(
2122
+ context.ownerId,
2123
+ context.sceneConfigId,
2124
+ linkIdToDelete
2125
+ )
2126
+ );
2127
+ });
2128
+ }
2129
+ }
2058
2130
  } else {
2059
2131
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2060
2132
  payloadToSave = originalData;
@@ -2125,6 +2197,9 @@ var userActionHandlers = {
2125
2197
  const newLinks = (specificParentData.links || []).filter(
2126
2198
  (l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId
2127
2199
  );
2200
+ const linksToDelete = (specificParentData.links || []).filter(
2201
+ (l) => String(l.source) === strNodeId || String(l.target) === strNodeId
2202
+ );
2128
2203
  specificParentData.nodes = newNodes;
2129
2204
  specificParentData.links = newLinks;
2130
2205
  let filenameToSave;
@@ -2143,18 +2218,27 @@ var userActionHandlers = {
2143
2218
  payloadToSave = {
2144
2219
  parent_dbs: sceneDataRef.current.parent_dbs,
2145
2220
  nodes: newVisualNodes,
2146
- links: newVisualLinks,
2147
- quest_counter: sceneDataRef.current.quest_counter || 1
2221
+ links: newVisualLinks
2148
2222
  };
2149
- const questFilePayload = {
2150
- nodes: specificParentData.nodes,
2151
- links: specificParentData.links,
2152
- milestones: sceneDataRef.current.milestones || []
2153
- };
2154
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
2155
2223
  try {
2156
2224
  await context.actions.save_view_data(filenameToSave, payloadToSave);
2157
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
2225
+ if (context.actions.delete_quest_firestore) {
2226
+ await context.actions.delete_quest_firestore(
2227
+ context.ownerId,
2228
+ context.sceneConfigId,
2229
+ nodeIdToDelete
2230
+ );
2231
+ if (context.actions.delete_quest_link_firestore && linksToDelete.length > 0) {
2232
+ const linkDeletePromises = linksToDelete.map(
2233
+ (link) => context.actions.delete_quest_link_firestore(
2234
+ context.ownerId,
2235
+ context.sceneConfigId,
2236
+ link.id
2237
+ )
2238
+ );
2239
+ await Promise.all(linkDeletePromises);
2240
+ }
2241
+ }
2158
2242
  graphDataRef.current[parentFileId] = specificParentData;
2159
2243
  setters.setDetailsNode(
2160
2244
  (prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev
@@ -2187,6 +2271,7 @@ var userActionHandlers = {
2187
2271
  var _a, _b, _c, _d;
2188
2272
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2189
2273
  if (!graphDataRef.current || !sceneDataRef.current) return;
2274
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2190
2275
  const {
2191
2276
  _baseEmissiveIntensity,
2192
2277
  _baseScale,
@@ -2231,7 +2316,7 @@ var userActionHandlers = {
2231
2316
  const oldNode = specificParentData.nodes[nodeIndex];
2232
2317
  const isNewDone = oldNode.status !== "Done" && nodeToSave.status === "Done";
2233
2318
  specificParentData.nodes[nodeIndex] = { ...nodeToSave };
2234
- if (isNewDone && nodeToSave.is_quest && ((_a = nodeToSave.recurrence_config) == null ? void 0 : _a.enabled)) {
2319
+ if (isNewDone && nodeToSave.is_quest && ((_b = nodeToSave.recurrence_config) == null ? void 0 : _b.enabled)) {
2235
2320
  const nextDateObj = calculateNextRecurrenceDate(
2236
2321
  nodeToSave.recurrence_config
2237
2322
  );
@@ -2256,12 +2341,10 @@ var userActionHandlers = {
2256
2341
  }
2257
2342
  const nextQuestNode = {
2258
2343
  ...JSON.parse(JSON.stringify(nodeToSave)),
2259
- // Deep copy properties
2260
2344
  id: short.generate(),
2261
2345
  name: nextName,
2262
2346
  status: "Backlog",
2263
2347
  color: "#64748b",
2264
- // QUEST_STATUS_COLORS["Backlog"]
2265
2348
  assignee_id: nodeToSave.recurrence_config.next_assignee_id || "",
2266
2349
  Date: nextDateObj,
2267
2350
  timeline: [
@@ -2278,7 +2361,7 @@ var userActionHandlers = {
2278
2361
  ],
2279
2362
  version_node: {
2280
2363
  is_version: true,
2281
- parent_node: ((_b = nodeToSave.version_node) == null ? void 0 : _b.parent_node) || nodeToSave.id
2364
+ parent_node: ((_c = nodeToSave.version_node) == null ? void 0 : _c.parent_node) || nodeToSave.id
2282
2365
  },
2283
2366
  reviewStack: (nodeToSave.reviewStack || []).map((r) => ({
2284
2367
  ...r,
@@ -2286,21 +2369,56 @@ var userActionHandlers = {
2286
2369
  })),
2287
2370
  recurrence_config: nextRecurrenceConfig
2288
2371
  };
2289
- specificParentData.nodes.push(nextQuestNode);
2372
+ const rootId = ((_d = nodeToSave.version_node) == null ? void 0 : _d.parent_node) || nodeToSave.id;
2373
+ const nextQuestLink = {
2374
+ id: `link_${short.generate()}`,
2375
+ source: rootId,
2376
+ target: nextQuestNode.id
2377
+ };
2378
+ await context.actions.upsert_quest_firestore(
2379
+ context.ownerId,
2380
+ context.sceneConfigId,
2381
+ nextQuestNode
2382
+ );
2383
+ await context.actions.upsert_quest_link_firestore(
2384
+ context.ownerId,
2385
+ context.sceneConfigId,
2386
+ nextQuestLink
2387
+ );
2388
+ await context.actions.update_view_counter(
2389
+ context.ownerId,
2390
+ context.sceneConfigId,
2391
+ nextCounter
2392
+ );
2393
+ if (specificParentData.links) {
2394
+ specificParentData.links.push(nextQuestLink);
2395
+ }
2396
+ if (specificParentData.nodes) {
2397
+ specificParentData.nodes.push(nextQuestNode);
2398
+ }
2399
+ if (isView && parentFileId === context.sceneConfigId) {
2400
+ if (!sceneDataRef.current.links) sceneDataRef.current.links = [];
2401
+ sceneDataRef.current.links.push(nextQuestLink);
2402
+ sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2403
+ }
2290
2404
  if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
2291
2405
  const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
2292
2406
  setTimeout(() => {
2293
2407
  if (stateRef.current && stateRef.current.graphGroup) {
2294
2408
  const pos = oldMeshPosition.clone();
2295
2409
  pos.x += 12;
2296
- addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos, true);
2410
+ addStandaloneNodeToScene(
2411
+ stateRef.current,
2412
+ nextQuestNode,
2413
+ pos,
2414
+ true
2415
+ );
2297
2416
  }
2298
2417
  }, 2e3);
2299
2418
  }
2300
2419
  }
2301
2420
  }
2302
2421
  try {
2303
- const isView = ((_c = context.viewType) == null ? void 0 : _c.toLowerCase()) === "view";
2304
2422
  if (isView && parentFileId === context.sceneConfigId) {
2305
2423
  const visualNodeIndex = sceneDataRef.current.nodes.findIndex(
2306
2424
  (n) => String(n.id) === String(nodeToSave.id)
@@ -2311,39 +2429,26 @@ var userActionHandlers = {
2311
2429
  ...nodeToSave
2312
2430
  };
2313
2431
  }
2314
- if (nodeToSave.is_quest && context.actions.save_quest_action) {
2315
- await context.actions.save_quest_action(context.ownerId, context.sceneConfigId, nodeToSave, sceneDataRef.current.quest_counter);
2316
- if (isNewDone && ((_d = nodeToSave.recurrence_config) == null ? void 0 : _d.enabled)) {
2317
- const createdRecurrenceQuest = specificParentData.nodes[specificParentData.nodes.length - 1];
2318
- if (createdRecurrenceQuest && String(createdRecurrenceQuest.id) !== String(nodeToSave.id)) {
2319
- await context.actions.save_quest_action(context.ownerId, context.sceneConfigId, createdRecurrenceQuest, sceneDataRef.current.quest_counter);
2320
- }
2321
- }
2322
- const viewFilePayload = {
2323
- parent_dbs: sceneDataRef.current.parent_dbs,
2324
- nodes: sceneDataRef.current.nodes,
2325
- links: sceneDataRef.current.links,
2326
- quest_counter: sceneDataRef.current.quest_counter || 1
2327
- };
2328
- await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
2329
- } else {
2330
- const viewFilePayload = {
2331
- parent_dbs: sceneDataRef.current.parent_dbs,
2332
- nodes: sceneDataRef.current.nodes,
2333
- links: sceneDataRef.current.links,
2334
- quest_counter: sceneDataRef.current.quest_counter || 1
2335
- };
2336
- const questFilePayload = {
2337
- nodes: specificParentData.nodes,
2338
- links: specificParentData.links,
2339
- milestones: sceneDataRef.current.milestones || []
2340
- };
2341
- await context.actions.save_view_data(
2342
- context.sceneSaveUrl,
2343
- viewFilePayload
2432
+ const viewFilePayload = {
2433
+ parent_dbs: sceneDataRef.current.parent_dbs,
2434
+ nodes: sceneDataRef.current.nodes,
2435
+ links: sceneDataRef.current.links
2436
+ };
2437
+ const questFilePayload = {
2438
+ nodes: specificParentData.nodes,
2439
+ links: specificParentData.links,
2440
+ milestones: sceneDataRef.current.milestones || []
2441
+ };
2442
+ await context.actions.save_view_data(
2443
+ context.sceneSaveUrl,
2444
+ viewFilePayload
2445
+ );
2446
+ if (context.actions.upsert_quest_firestore) {
2447
+ await context.actions.upsert_quest_firestore(
2448
+ context.ownerId,
2449
+ context.sceneConfigId,
2450
+ nodeToSave
2344
2451
  );
2345
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
2346
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
2347
2452
  }
2348
2453
  } else {
2349
2454
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -2355,7 +2460,6 @@ var userActionHandlers = {
2355
2460
  graphDataRef.current[parentFileId] = specificParentData;
2356
2461
  if (isView && parentFileId === context.sceneConfigId) {
2357
2462
  sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2358
- sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2359
2463
  }
2360
2464
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2361
2465
  setters.setSceneVersion((v) => v + 1);
@@ -2412,8 +2516,7 @@ var userActionHandlers = {
2412
2516
  const viewFilePayload = {
2413
2517
  parent_dbs: sceneDataRef.current.parent_dbs,
2414
2518
  nodes: sceneDataRef.current.nodes,
2415
- links: sceneDataRef.current.links,
2416
- quest_counter: sceneDataRef.current.quest_counter || 1
2519
+ links: sceneDataRef.current.links
2417
2520
  };
2418
2521
  const questFilePayload = {
2419
2522
  nodes: specificParentData.nodes,
@@ -2424,8 +2527,13 @@ var userActionHandlers = {
2424
2527
  context.sceneSaveUrl,
2425
2528
  viewFilePayload
2426
2529
  );
2427
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
2428
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
2530
+ if (context.actions.upsert_quest_link_firestore) {
2531
+ await context.actions.upsert_quest_link_firestore(
2532
+ context.ownerId,
2533
+ context.sceneConfigId,
2534
+ linkToSave
2535
+ );
2536
+ }
2429
2537
  } else {
2430
2538
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2431
2539
  await context.actions.save_view_data(
@@ -2520,7 +2628,7 @@ function createNewCustomProperty(existingProps = []) {
2520
2628
  nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2521
2629
  break;
2522
2630
  case "date":
2523
- nextKey = "Date";
2631
+ nextKey = "Data";
2524
2632
  nextValue = { type: "Data", value: "" };
2525
2633
  break;
2526
2634
  case "number":
@@ -2774,7 +2882,7 @@ var IGNORED_KEYS = [
2774
2882
  ];
2775
2883
  function extractCustomPropsFromNode(node) {
2776
2884
  const customPropTypes = node._customPropTypes || {};
2777
- return Object.keys(node).filter((k) => !IGNORED_KEYS.includes(k)).map((key) => {
2885
+ return Object.keys(node).filter((k) => !IGNORED_KEYS.includes(k) || customPropTypes[k]).map((key) => {
2778
2886
  const val = node[key];
2779
2887
  const t = customPropTypes[key] || inferPropType(val);
2780
2888
  if (t === "date") {
@@ -4963,7 +5071,7 @@ function CustomPropertyDisplay({
4963
5071
  links: "Links",
4964
5072
  images: "Images",
4965
5073
  documents: "Documents",
4966
- date: "Date"
5074
+ date: "Data"
4967
5075
  };
4968
5076
  const oldKeyIsFixed = Object.values(fixedKeyMap).includes(tempProp.key);
4969
5077
  if (fixedKeyMap[value]) {
@@ -8828,7 +8936,7 @@ function CreateAncestryPanel({
8828
8936
  }
8829
8937
 
8830
8938
  // src/components/CreateQuestTreePanel.jsx
8831
- import React11, { useState as useState12, useEffect as useEffect11, useCallback as useCallback3, useMemo as useMemo9 } from "react";
8939
+ import React11, { useState as useState12, useEffect as useEffect11, useCallback as useCallback3, useMemo as useMemo9, useRef as useRef9 } from "react";
8832
8940
  import {
8833
8941
  FiFolder as FiFolder3,
8834
8942
  FiLayers as FiLayers6,
@@ -8945,6 +9053,7 @@ function CreateQuestTreePanel({
8945
9053
  const [isSaving, setIsSaving] = useState12(false);
8946
9054
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState12(false);
8947
9055
  const [activeTab, setActiveTab] = useState12("tree");
9056
+ const isInitialLoad = useRef9(true);
8948
9057
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
8949
9058
  const { width: panelWidth, isResizing, handlePointerDown: handleResize } = useResizablePanel({
8950
9059
  initialWidth: 440,
@@ -8978,10 +9087,11 @@ function CreateQuestTreePanel({
8978
9087
  const indexToRemove = pathToRemove[pathToRemove.length - 1];
8979
9088
  if (currentParent.children && currentParent.children.length > indexToRemove) {
8980
9089
  currentParent.children.splice(indexToRemove, 1);
8981
- setHasUnsavedChanges(true);
9090
+ return { ...prev, [treeKey]: newTree };
8982
9091
  }
8983
- return { ...prev, [treeKey]: newTree };
9092
+ return prev;
8984
9093
  });
9094
+ setHasUnsavedChanges(true);
8985
9095
  }, [setQuestTreeMode, activeTab]);
8986
9096
  const handleMoveNode = (sourceId, targetId) => {
8987
9097
  const isAbstraction = activeTab === "abstraction";
@@ -9058,6 +9168,15 @@ function CreateQuestTreePanel({
9058
9168
  }));
9059
9169
  }
9060
9170
  }, [tree, abstraction_tree, questTreeMode.questNodeId, setQuestTreeMode]);
9171
+ useEffect11(() => {
9172
+ if (tree || abstraction_tree) {
9173
+ if (isInitialLoad.current) {
9174
+ isInitialLoad.current = false;
9175
+ return;
9176
+ }
9177
+ setHasUnsavedChanges(true);
9178
+ }
9179
+ }, [tree, abstraction_tree]);
9061
9180
  return /* @__PURE__ */ React11.createElement(
9062
9181
  "div",
9063
9182
  {
@@ -9248,11 +9367,11 @@ function ImageViewer({ data, onClose }) {
9248
9367
  }
9249
9368
 
9250
9369
  // src/components/InSceneCreationForm.jsx
9251
- import React15, { useState as useState15, useEffect as useEffect14, useRef as useRef10 } from "react";
9370
+ import React15, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9252
9371
  import { v4 as uuidv45 } from "uuid";
9253
9372
 
9254
9373
  // src/components/ColorPicker.jsx
9255
- import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef9 } from "react";
9374
+ import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
9256
9375
  import { HexColorPicker } from "react-colorful";
9257
9376
  import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
9258
9377
  var PRESET_COLORS = [
@@ -9274,7 +9393,7 @@ var PRESET_COLORS = [
9274
9393
  ];
9275
9394
  function ColorPicker({ color, onChange, disabled, isCompact = false }) {
9276
9395
  const [isOpen, setIsOpen] = useState14(false);
9277
- const popoverRef = useRef9(null);
9396
+ const popoverRef = useRef10(null);
9278
9397
  useEffect13(() => {
9279
9398
  const handleClickOutside = (event) => {
9280
9399
  if (popoverRef.current && !popoverRef.current.contains(event.target)) {
@@ -9501,7 +9620,7 @@ function InSceneCreationForm({
9501
9620
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState15(false);
9502
9621
  const [isLoadingDocs, setIsLoadingDocs] = useState15(false);
9503
9622
  const [docError, setDocError] = useState15(null);
9504
- const datasetDropdownRef = useRef10(null);
9623
+ const datasetDropdownRef = useRef11(null);
9505
9624
  useEffect14(() => {
9506
9625
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
9507
9626
  }, [sourceNodeDatasetId]);
@@ -9518,7 +9637,7 @@ function InSceneCreationForm({
9518
9637
  document.removeEventListener("mousedown", handleClickOutside);
9519
9638
  };
9520
9639
  }, [isDatasetDropdownOpen]);
9521
- const propsEndRef = useRef10(null);
9640
+ const propsEndRef = useRef11(null);
9522
9641
  const hasImages = customProps.some(
9523
9642
  (p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value)
9524
9643
  );
@@ -10021,7 +10140,7 @@ function InSceneCreationForm({
10021
10140
  }
10022
10141
 
10023
10142
  // src/components/InSceneVersionForm.jsx
10024
- import React16, { useState as useState16, useEffect as useEffect15, useRef as useRef11 } from "react";
10143
+ import React16, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
10025
10144
  import { v4 as uuidv46 } from "uuid";
10026
10145
  import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
10027
10146
  function InSceneVersionForm({
@@ -10053,7 +10172,7 @@ function InSceneVersionForm({
10053
10172
  }
10054
10173
  ]);
10055
10174
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
10056
- const propsEndRef = useRef11(null);
10175
+ const propsEndRef = useRef12(null);
10057
10176
  const [useImageAsTexture, setUseImageAsTexture] = useState16(false);
10058
10177
  const [selectedImageUrl, setSelectedImageUrl] = useState16(null);
10059
10178
  const hasImages = customProps.some(
@@ -10337,7 +10456,7 @@ function InSceneVersionForm({
10337
10456
  }
10338
10457
 
10339
10458
  // src/components/InSceneQuestForm.jsx
10340
- import React18, { useState as useState18, useRef as useRef12 } from "react";
10459
+ import React18, { useState as useState18, useRef as useRef13 } from "react";
10341
10460
  import { v4 as uuidv47 } from "uuid";
10342
10461
  import {
10343
10462
  FiPlus as FiPlus7,
@@ -10576,7 +10695,7 @@ function InSceneQuestForm({
10576
10695
  const [docError, setDocError] = useState18(null);
10577
10696
  const [customProps, setCustomProps] = useState18([]);
10578
10697
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
10579
- const propsEndRef = useRef12(null);
10698
+ const propsEndRef = useRef13(null);
10580
10699
  const [milestoneInput, setMilestoneInput] = useState18("");
10581
10700
  const [showMilestoneSuggestions, setShowMilestoneSuggestions] = useState18(false);
10582
10701
  const activeMilestones = React18.useMemo(
@@ -11371,7 +11490,7 @@ function InSceneQuestForm({
11371
11490
  }
11372
11491
 
11373
11492
  // src/components/NodeDetailsPanel.jsx
11374
- import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef13 } from "react";
11493
+ import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
11375
11494
  import { v4 as uuidv48 } from "uuid";
11376
11495
  import { FiPlus as FiPlus8, FiMaximize2 as FiMaximize23, FiX as FiX6, FiCheck as FiCheck10, FiImage as FiImage3, FiEdit2 as FiEdit27, FiLoader as FiLoader2, FiBookOpen as FiBookOpen3, FiSun as FiSun2, FiLink as FiLink5, FiDatabase } from "react-icons/fi";
11377
11496
  import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters3 } from "react-icons/ai";
@@ -11431,8 +11550,8 @@ function NodeDetailsPanel({
11431
11550
  useEffect16(() => {
11432
11551
  setWidth(isReadMode ? 700 : 440);
11433
11552
  }, [isReadMode, setWidth]);
11434
- const prevNodeIdRef = useRef13(null);
11435
- const propsEndRef = useRef13(null);
11553
+ const prevNodeIdRef = useRef14(null);
11554
+ const propsEndRef = useRef14(null);
11436
11555
  const canEdit = userRole !== "viewer";
11437
11556
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
11438
11557
  const handleImageClickFromText = (url, name2) => {
@@ -11997,7 +12116,7 @@ function NodeDetailsPanel({
11997
12116
  }
11998
12117
 
11999
12118
  // src/components/QuestDetailsPanel.jsx
12000
- import React21, { useState as useState20, useEffect as useEffect17, useRef as useRef14 } from "react";
12119
+ import React21, { useState as useState20, useEffect as useEffect17, useRef as useRef15 } from "react";
12001
12120
  import { v4 as uuidv49 } from "uuid";
12002
12121
  import { FiPlus as FiPlus9, FiX as FiX7, FiCheck as FiCheck11, FiEdit2 as FiEdit28, FiLoader as FiLoader3, FiBookOpen as FiBookOpen4, FiLink as FiLink7, FiTarget as FiTarget3, FiChevronDown as FiChevronDown7, FiUser as FiUser3, FiSearch as FiSearch7, FiRepeat as FiRepeat2, FiCalendar as FiCalendar2, FiImage as FiImage4, FiCopy as FiCopy4, FiGitBranch as FiGitBranch4 } from "react-icons/fi";
12003
12122
 
@@ -12265,8 +12384,8 @@ function QuestDetailsPanel({
12265
12384
  useEffect17(() => {
12266
12385
  setWidth(isReadMode ? 700 : 440);
12267
12386
  }, [isReadMode, setWidth]);
12268
- const prevNodeIdRef = useRef14(null);
12269
- const propsEndRef = useRef14(null);
12387
+ const prevNodeIdRef = useRef15(null);
12388
+ const propsEndRef = useRef15(null);
12270
12389
  const canEdit = userRole !== "viewer";
12271
12390
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
12272
12391
  const handleImageClickFromText = (url, name) => {
@@ -12408,7 +12527,6 @@ function QuestDetailsPanel({
12408
12527
  setIsSaving(false);
12409
12528
  }
12410
12529
  };
12411
- const filteredCustomProps = customProps.filter((p) => p.key !== "Date" && p.key !== "Data");
12412
12530
  const handleAddTimelineNote = async () => {
12413
12531
  if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
12414
12532
  setIsSaving(true);
@@ -13417,7 +13535,7 @@ ${noteText}` : noteText : entry.notes,
13417
13535
  }
13418
13536
 
13419
13537
  // src/components/MultiNodeContextMenu.jsx
13420
- import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState21, useEffect as useEffect18 } from "react";
13538
+ import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef16, useState as useState21, useEffect as useEffect18 } from "react";
13421
13539
  function MultiNodeContextMenu({
13422
13540
  data,
13423
13541
  userRole,
@@ -13426,7 +13544,7 @@ function MultiNodeContextMenu({
13426
13544
  onDismissOtherNodes,
13427
13545
  onDeleteNodes
13428
13546
  }) {
13429
- const menuRef = useRef15(null);
13547
+ const menuRef = useRef16(null);
13430
13548
  const [menuPos, setMenuPos] = useState21({ left: 0, top: 0 });
13431
13549
  const [isConfirmingDelete, setIsConfirmingDelete] = useState21(false);
13432
13550
  const ability = defineAbilityFor(userRole);
@@ -13493,7 +13611,7 @@ function MultiNodeContextMenu({
13493
13611
  }
13494
13612
 
13495
13613
  // src/components/RelationshipDetailsPanel.jsx
13496
- import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef16, useMemo as useMemo10 } from "react";
13614
+ import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef17, useMemo as useMemo10 } from "react";
13497
13615
  import { v4 as uuidv410 } from "uuid";
13498
13616
  import { FiPlus as FiPlus10, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
13499
13617
  function RelationshipDetailsPanel({
@@ -13524,7 +13642,7 @@ function RelationshipDetailsPanel({
13524
13642
  const [isSaving, setIsSaving] = useState22(false);
13525
13643
  const [isReadMode, setIsReadMode] = useState22(false);
13526
13644
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState22(false);
13527
- const propsEndRef = useRef16(null);
13645
+ const propsEndRef = useRef17(null);
13528
13646
  const canEdit = useMemo10(() => {
13529
13647
  const ability = defineAbilityFor(userRole);
13530
13648
  return ability.can("update", "Connection");
@@ -13845,7 +13963,7 @@ function RelationshipDetailsPanel({
13845
13963
  }
13846
13964
 
13847
13965
  // src/components/RelationshipContextMenu.jsx
13848
- import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef17, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13966
+ import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef18, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13849
13967
  function RelationshipContextMenu({
13850
13968
  data,
13851
13969
  userRole,
@@ -13855,7 +13973,7 @@ function RelationshipContextMenu({
13855
13973
  onDelete,
13856
13974
  onClose
13857
13975
  }) {
13858
- const menuRef = useRef17(null);
13976
+ const menuRef = useRef18(null);
13859
13977
  const [menuPos, setMenuPos] = useState23({ left: 0, top: 0 });
13860
13978
  const [isConfirmingDelete, setIsConfirmingDelete] = useState23(false);
13861
13979
  const ability = useMemo11(() => defineAbilityFor(userRole), [userRole]);
@@ -14337,7 +14455,7 @@ import React30, {
14337
14455
  useState as useState28,
14338
14456
  useMemo as useMemo13,
14339
14457
  useEffect as useEffect24,
14340
- useRef as useRef20,
14458
+ useRef as useRef21,
14341
14459
  useCallback as useCallback6
14342
14460
  } from "react";
14343
14461
  import {
@@ -14363,10 +14481,10 @@ import {
14363
14481
  import { v4 as uuidv411 } from "uuid";
14364
14482
 
14365
14483
  // src/components/RichGroupEditor.jsx
14366
- import React29, { useEffect as useEffect23, useRef as useRef19, useState as useState27, useCallback as useCallback5 } from "react";
14484
+ import React29, { useEffect as useEffect23, useRef as useRef20, useState as useState27, useCallback as useCallback5 } from "react";
14367
14485
 
14368
14486
  // src/components/MentionPopover.jsx
14369
- import React28, { useEffect as useEffect22, useRef as useRef18, useState as useState26, useMemo as useMemo12 } from "react";
14487
+ import React28, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useMemo as useMemo12 } from "react";
14370
14488
  import { FiLayers as FiLayers7, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch5, FiBox } from "react-icons/fi";
14371
14489
  var TYPE_CONFIG = {
14372
14490
  ancestry: { Icon: FiLayers7, color: "text-indigo-400", label: "Ancestralidade" },
@@ -14376,7 +14494,7 @@ var TYPE_CONFIG = {
14376
14494
  };
14377
14495
  function MentionPopover({ query, items, position, onSelect, onClose }) {
14378
14496
  const [activeIndex, setActiveIndex] = useState26(0);
14379
- const listRef = useRef18(null);
14497
+ const listRef = useRef19(null);
14380
14498
  const filtered = useMemo12(() => {
14381
14499
  const term = (query || "").toLowerCase().trim();
14382
14500
  if (!term) return items.slice(0, 8);
@@ -14516,9 +14634,9 @@ var RichGroupEditor = React29.memo(function RichGroupEditor2({
14516
14634
  readOnly,
14517
14635
  placeholder
14518
14636
  }) {
14519
- const editorRef = useRef19(null);
14520
- const isMountedRef = useRef19(false);
14521
- const dismissedTriggerRef = useRef19(null);
14637
+ const editorRef = useRef20(null);
14638
+ const isMountedRef = useRef20(false);
14639
+ const dismissedTriggerRef = useRef20(null);
14522
14640
  const [mentionState, setMentionState] = useState27(null);
14523
14641
  const [isEmpty, setIsEmpty] = useState27(true);
14524
14642
  useEffect23(() => {
@@ -14986,7 +15104,7 @@ function Boards({
14986
15104
  const [isLoaded, setIsLoaded] = useState28(false);
14987
15105
  const [saveStatus, setSaveStatus] = useState28("idle");
14988
15106
  const [navigationStack, setNavigationStack] = useState28([]);
14989
- const lastSavedBoardItemsRef = useRef20(null);
15107
+ const lastSavedBoardItemsRef = useRef21(null);
14990
15108
  const canEdit = useMemo13(() => userRole !== "viewer", [userRole]);
14991
15109
  const findGroupAndParent = (list, targetId, parent = null) => {
14992
15110
  for (let i = 0; i < list.length; i++) {
@@ -15558,13 +15676,12 @@ function XViewScene({
15558
15676
  get_view_members,
15559
15677
  create_google_doc_action,
15560
15678
  open_google_picker_action,
15561
- // Firestore Atomic Actions (Quests & Milestones)
15562
- save_quest_action,
15563
- delete_quest_action,
15564
- save_quest_link_action,
15565
- delete_quest_link_action,
15566
- save_milestone_action,
15567
- delete_milestone_action
15679
+ upsert_quest_firestore,
15680
+ delete_quest_firestore,
15681
+ upsert_quest_link_firestore,
15682
+ delete_quest_link_firestore,
15683
+ upsert_milestone_firestore,
15684
+ update_view_counter
15568
15685
  }) {
15569
15686
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
15570
15687
  const { data: session, status } = useSession();
@@ -15638,10 +15755,10 @@ function XViewScene({
15638
15755
  }
15639
15756
  return null;
15640
15757
  }, [ownerId, sceneConfigId]);
15641
- const sceneDataRef = useRef21(null);
15642
- const parentDataRef = useRef21(null);
15758
+ const sceneDataRef = useRef22(null);
15759
+ const parentDataRef = useRef22(null);
15643
15760
  const graphDataRef = parentDataRef;
15644
- const ancestryDataRef = useRef21(null);
15761
+ const ancestryDataRef = useRef22(null);
15645
15762
  const [isLoading, setIsLoading] = useState30(true);
15646
15763
  const [permissionStatus, setPermissionStatus] = useState30("loading");
15647
15764
  const [userPermissionRole, setUserPermissionRole] = useState30(null);
@@ -15730,10 +15847,10 @@ function XViewScene({
15730
15847
  const [boardItems, setBoardItems] = useState30([]);
15731
15848
  const [isSidebarOpen, setIsSidebarOpen] = useState30(false);
15732
15849
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState30(false);
15733
- const mountRef = useRef21(null);
15734
- const tooltipRef = useRef21(null);
15735
- const formRef = useRef21(null);
15736
- const stateRef = useRef21({
15850
+ const mountRef = useRef22(null);
15851
+ const tooltipRef = useRef22(null);
15852
+ const formRef = useRef22(null);
15853
+ const stateRef = useRef22({
15737
15854
  readMode: {
15738
15855
  currentMaxIndex: 0,
15739
15856
  progressMap: {}
@@ -16124,11 +16241,19 @@ function XViewScene({
16124
16241
  }
16125
16242
  }
16126
16243
  Object.values(nodeObjects).forEach((mesh) => {
16127
- const oldLabel = mesh.getObjectByName("timelineLabel");
16128
- if (oldLabel) {
16129
- mesh.remove(oldLabel);
16130
- if (oldLabel.material.map) oldLabel.material.map.dispose();
16131
- oldLabel.material.dispose();
16244
+ const oldTimelineLabel = mesh.getObjectByName("timelineLabel");
16245
+ if (oldTimelineLabel) {
16246
+ mesh.remove(oldTimelineLabel);
16247
+ if (oldTimelineLabel.material.map)
16248
+ oldTimelineLabel.material.map.dispose();
16249
+ oldTimelineLabel.material.dispose();
16250
+ }
16251
+ const oldQuestDateLabel = mesh.getObjectByName("questDateLabel");
16252
+ if (oldQuestDateLabel) {
16253
+ mesh.remove(oldQuestDateLabel);
16254
+ if (oldQuestDateLabel.material.map)
16255
+ oldQuestDateLabel.material.map.dispose();
16256
+ oldQuestDateLabel.material.dispose();
16132
16257
  }
16133
16258
  delete mesh.userData.timelineIntervalBar;
16134
16259
  delete mesh.userData.timelineEndLabel;
@@ -16148,42 +16273,24 @@ function XViewScene({
16148
16273
  return null;
16149
16274
  };
16150
16275
  Object.values(nodeObjects).forEach((mesh) => {
16151
- const dateProp = mesh.userData.Date;
16276
+ var _a2;
16277
+ const dateProp = mesh.userData.Date || ((_a2 = (mesh.userData.properties || []).find(
16278
+ (p) => {
16279
+ var _a3;
16280
+ return ((_a3 = p.name) == null ? void 0 : _a3.toLowerCase()) === "data";
16281
+ }
16282
+ )) == null ? void 0 : _a2.value);
16152
16283
  let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
16153
16284
  if (dateProp) {
16154
- if (dateProp.date) {
16155
- const date = parseDate2(dateProp.date);
16156
- if (date) {
16157
- nodeInfo.startDate = date;
16158
- nodeInfo.endDate = date;
16159
- nodeInfo.label = dateProp.date;
16160
- nodeInfo.isUndated = false;
16161
- allTimePoints.add(date.getTime());
16162
- }
16163
- } else if (dateProp.year) {
16164
- const year = parseInt(dateProp.year, 10);
16165
- if (!isNaN(year)) {
16166
- const date = new Date(year, 0, 1);
16167
- nodeInfo.startDate = date;
16168
- nodeInfo.endDate = date;
16169
- nodeInfo.label = String(year);
16170
- nodeInfo.isUndated = false;
16171
- allTimePoints.add(date.getTime());
16172
- }
16173
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
16174
- const startYear = parseInt(dateProp.date_interval.start, 10);
16175
- const endYear = parseInt(dateProp.date_interval.end, 10) || startYear;
16176
- if (!isNaN(startYear)) {
16177
- const startDate = new Date(startYear, 0, 1);
16178
- const endDate = new Date(endYear, 11, 31);
16179
- nodeInfo.type = "interval";
16180
- nodeInfo.startDate = startDate;
16181
- nodeInfo.endDate = endDate;
16182
- nodeInfo.label = `${startYear} - ${endYear}`;
16183
- nodeInfo.isUndated = false;
16184
- allTimePoints.add(startDate.getTime());
16185
- allTimePoints.add(endDate.getTime());
16186
- }
16285
+ const info = parseDateProp(dateProp);
16286
+ if (!info.isUndated) {
16287
+ nodeInfo.startDate = info.startDate;
16288
+ nodeInfo.endDate = info.endDate;
16289
+ nodeInfo.label = info.label;
16290
+ nodeInfo.type = info.type;
16291
+ nodeInfo.isUndated = false;
16292
+ allTimePoints.add(info.startDate.getTime());
16293
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16187
16294
  }
16188
16295
  }
16189
16296
  timelineNodes.push(nodeInfo);
@@ -16311,50 +16418,35 @@ function XViewScene({
16311
16418
  return null;
16312
16419
  };
16313
16420
  versionMeshes.forEach((mesh) => {
16314
- const dateProp = mesh.userData.Date;
16315
- if (!dateProp) return;
16316
- let nodeInfo = { mesh, type: "point", label: "" };
16317
- if (dateProp.date) {
16318
- const date = parseDate2(dateProp.date);
16319
- if (date) {
16320
- nodeInfo.startDate = date;
16321
- nodeInfo.endDate = date;
16322
- nodeInfo.label = dateProp.date;
16323
- allTimePoints.add(date.getTime());
16324
- timelineNodes.push(nodeInfo);
16325
- }
16326
- } else if (dateProp.year) {
16327
- const year = parseInt(dateProp.year, 10);
16328
- if (!isNaN(year)) {
16329
- const date = new Date(year, 0, 1);
16330
- nodeInfo.startDate = date;
16331
- nodeInfo.endDate = date;
16332
- nodeInfo.label = String(year);
16333
- allTimePoints.add(date.getTime());
16334
- timelineNodes.push(nodeInfo);
16335
- }
16336
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
16337
- const startYear = parseInt(dateProp.date_interval.start, 10);
16338
- const endYear = parseInt(dateProp.date_interval.end, 10) || startYear;
16339
- if (!isNaN(startYear)) {
16340
- const startDate = new Date(startYear, 0, 1);
16341
- const endDate = new Date(endYear, 11, 31);
16342
- nodeInfo.type = "interval";
16343
- nodeInfo.startDate = startDate;
16344
- nodeInfo.endDate = endDate;
16345
- nodeInfo.label = `${startYear} - ${endYear}`;
16346
- allTimePoints.add(startDate.getTime());
16347
- allTimePoints.add(endDate.getTime());
16348
- timelineNodes.push(nodeInfo);
16421
+ var _a2;
16422
+ const dateProp = mesh.userData.Date || ((_a2 = (mesh.userData.properties || []).find(
16423
+ (p) => {
16424
+ var _a3;
16425
+ return ((_a3 = p.name) == null ? void 0 : _a3.toLowerCase()) === "data";
16349
16426
  }
16427
+ )) == null ? void 0 : _a2.value);
16428
+ if (!dateProp) return;
16429
+ const info = parseDateProp(dateProp);
16430
+ if (!info.isUndated) {
16431
+ const nodeInfo = {
16432
+ mesh,
16433
+ type: info.type,
16434
+ startDate: info.startDate,
16435
+ endDate: info.endDate,
16436
+ label: info.label
16437
+ };
16438
+ allTimePoints.add(info.startDate.getTime());
16439
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16440
+ timelineNodes.push(nodeInfo);
16350
16441
  }
16351
16442
  });
16352
16443
  if (timelineNodes.length === 0) return;
16353
16444
  const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
16445
+ const maxTimeIndex = sortedTimePoints.length - 1;
16354
16446
  const timeToYMap = new Map(
16355
16447
  sortedTimePoints.map((time, index) => [
16356
16448
  time,
16357
- index * TIMELINE_LAYER_SPACING_Y
16449
+ (index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
16358
16450
  ])
16359
16451
  );
16360
16452
  timelineNodes.sort(
@@ -16362,18 +16454,38 @@ function XViewScene({
16362
16454
  );
16363
16455
  const baseX = sourceMesh.position.x + TIMELINE_NODE_SPACING_X;
16364
16456
  const baseY = sourceMesh.position.y;
16365
- const maxNodeIndex = timelineNodes.length - 1;
16366
- timelineNodes.forEach((node, index) => {
16457
+ const columns = [];
16458
+ const allFinalPoints = [sourceMesh.position.clone()];
16459
+ timelineNodes.forEach((node) => {
16367
16460
  const { mesh, type, startDate, endDate, label } = node;
16368
- const y = baseY + (index - maxNodeIndex) * TIMELINE_LAYER_SPACING_Y;
16369
- const versionTween = new Tween2(mesh.position).to({ x: baseX, y, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
16461
+ const startY = timeToYMap.get(startDate.getTime());
16462
+ const endY = timeToYMap.get(endDate.getTime()) || startY;
16463
+ let foundColumn = false;
16464
+ for (let i = 0; i < columns.length; i++) {
16465
+ if (columns[i].endY < startY) {
16466
+ node.columnIndex = i;
16467
+ columns[i].endY = endY;
16468
+ foundColumn = true;
16469
+ break;
16470
+ }
16471
+ }
16472
+ if (!foundColumn) {
16473
+ node.columnIndex = columns.length;
16474
+ columns.push({ endY });
16475
+ }
16476
+ const x = baseX + node.columnIndex * TIMELINE_NODE_SPACING_X;
16477
+ const y = baseY + startY;
16478
+ allFinalPoints.push(new THREE3.Vector3(x, y, 0));
16479
+ const versionTween = new Tween2(mesh.position).to({ x, y, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
16370
16480
  tweenGroup.add(versionTween);
16371
16481
  versionTween.start();
16372
- const startLabelText = type === "interval" ? startDate.getFullYear().toString() : label;
16373
- const startLabel = createTextSprite(startLabelText, 48);
16374
- startLabel.name = "timelineLabel";
16375
- startLabel.position.set(0, -2.5, 0);
16376
- mesh.add(startLabel);
16482
+ if (!mesh.getObjectByName("questDateLabel")) {
16483
+ const startLabelText = type === "interval" ? startDate.getFullYear().toString() : label;
16484
+ const startLabel = createTextSprite(startLabelText, 48);
16485
+ startLabel.name = "timelineLabel";
16486
+ startLabel.position.set(0, -2.5, 0);
16487
+ mesh.add(startLabel);
16488
+ }
16377
16489
  if (type === "interval") {
16378
16490
  const relativeEndY = timeToYMap.get(endDate.getTime()) - timeToYMap.get(startDate.getTime());
16379
16491
  if (relativeEndY > 0) {
@@ -16407,7 +16519,21 @@ function XViewScene({
16407
16519
  }
16408
16520
  }
16409
16521
  });
16410
- }, []);
16522
+ if (allFinalPoints.length > 0) {
16523
+ const boundingBox = new THREE3.Box3().setFromPoints(allFinalPoints);
16524
+ const center = new THREE3.Vector3();
16525
+ boundingBox.getCenter(center);
16526
+ const size = new THREE3.Vector3();
16527
+ boundingBox.getSize(size);
16528
+ const spread = Math.max(size.x, size.y, size.z, 1);
16529
+ const desiredDistance = Math.max(
16530
+ x_view_config.CAMERA_ZOOM_DISTANCE,
16531
+ spread * 1.5
16532
+ );
16533
+ const zoomFactor = x_view_config.CAMERA_ZOOM_DISTANCE / desiredDistance;
16534
+ tweenToTarget(center, zoomFactor);
16535
+ }
16536
+ }, [tweenToTarget]);
16411
16537
  useEffect25(() => {
16412
16538
  async function fetchAllData(configPath, ownerId2) {
16413
16539
  var _a2, _b2;
@@ -18072,12 +18198,13 @@ function XViewScene({
18072
18198
  get_scene_view_data,
18073
18199
  upload_file: upload_file_action,
18074
18200
  delete_file: delete_file_action,
18075
- save_quest_action,
18076
- delete_quest_action,
18077
- save_quest_link_action,
18078
- delete_quest_link_action,
18079
- save_milestone_action,
18080
- delete_milestone_action
18201
+ // Adicionado novas importações aqui
18202
+ upsert_quest_firestore,
18203
+ delete_quest_firestore,
18204
+ upsert_quest_link_firestore,
18205
+ delete_quest_link_firestore,
18206
+ upsert_milestone_firestore,
18207
+ update_view_counter
18081
18208
  }
18082
18209
  };
18083
18210
  },
@@ -18097,12 +18224,12 @@ function XViewScene({
18097
18224
  get_scene_view_data,
18098
18225
  upload_file_action,
18099
18226
  delete_file_action,
18100
- save_quest_action,
18101
- delete_quest_action,
18102
- save_quest_link_action,
18103
- delete_quest_link_action,
18104
- save_milestone_action,
18105
- delete_milestone_action
18227
+ upsert_quest_firestore,
18228
+ delete_quest_firestore,
18229
+ upsert_quest_link_firestore,
18230
+ delete_quest_link_firestore,
18231
+ upsert_milestone_firestore,
18232
+ update_view_counter
18106
18233
  ]
18107
18234
  );
18108
18235
  const handleStartVersioning = (nodeData) => {
@@ -18308,45 +18435,30 @@ function XViewScene({
18308
18435
  parentDataRef.current[sceneConfigId].nodes[parentIndex].quest_abstraction_tree = formattedAbstractionTree;
18309
18436
  }
18310
18437
  }
18311
- if (save_quest_action) {
18312
- const updatedNodeData2 = sceneData.quest_nodes[questIndex];
18313
- await save_quest_action(ownerId, sceneConfigId, updatedNodeData2, sceneData.quest_counter || 1);
18314
- } else {
18315
- const sceneFileData = {
18316
- ...sceneData,
18317
- nodes: sceneData.nodes || [],
18318
- links: sceneData.links || [],
18319
- quest_counter: sceneData.quest_counter || 1
18320
- };
18321
- const questFileData = {
18322
- nodes: sceneData.quest_nodes || [],
18323
- links: sceneData.quest_links || [],
18324
- milestones: sceneData.milestones || []
18325
- };
18326
- await save_view_data(sceneSaveUrl, sceneFileData);
18327
- const questSaveUrl = sceneSaveUrl.replace(
18328
- "x_view_scenes",
18329
- "x_view_quests"
18438
+ const updatedNodeData = sceneData.quest_nodes[questIndex];
18439
+ if (upsert_quest_firestore) {
18440
+ await upsert_quest_firestore(
18441
+ ownerId,
18442
+ sceneConfigId,
18443
+ updatedNodeData
18330
18444
  );
18331
- await save_view_data(questSaveUrl, questFileData);
18332
18445
  }
18446
+ const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
18447
+ if (nodeMesh) {
18448
+ nodeMesh.userData = {
18449
+ ...nodeMesh.userData,
18450
+ ...updatedNodeData
18451
+ };
18452
+ }
18453
+ if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
18454
+ setDetailsNode((prev) => ({
18455
+ ...prev,
18456
+ quest_tree: formattedTree,
18457
+ quest_abstraction_tree: formattedAbstractionTree
18458
+ }));
18459
+ }
18460
+ setSceneVersion((v) => v + 1);
18333
18461
  }
18334
- const updatedNodeData = sceneData.quest_nodes[questIndex];
18335
- const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
18336
- if (nodeMesh) {
18337
- nodeMesh.userData = {
18338
- ...nodeMesh.userData,
18339
- ...updatedNodeData
18340
- };
18341
- }
18342
- if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
18343
- setDetailsNode((prev) => ({
18344
- ...prev,
18345
- quest_tree: formattedTree,
18346
- quest_abstraction_tree: formattedAbstractionTree
18347
- }));
18348
- }
18349
- setSceneVersion((v) => v + 1);
18350
18462
  }
18351
18463
  }
18352
18464
  };
@@ -18395,7 +18507,6 @@ function XViewScene({
18395
18507
  ownerId: ownerId2
18396
18508
  } = context;
18397
18509
  if (!graphDataRef2.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
18398
- const currentCounter = sceneDataRef2.current.quest_counter || 1;
18399
18510
  const newNode = {
18400
18511
  id: short2.generate(),
18401
18512
  ...newQuestData,
@@ -18406,25 +18517,16 @@ function XViewScene({
18406
18517
  graphDataRef2.current[sceneConfigId2] = { nodes: [], links: [] };
18407
18518
  }
18408
18519
  graphDataRef2.current[sceneConfigId2].nodes.push(newNode);
18409
- const sceneFileData = {
18410
- ...sceneDataRef2.current,
18411
- quest_counter: currentCounter + 1
18412
- };
18520
+ const currentCounter = sceneDataRef2.current.quest_counter || 1;
18521
+ const nextCounter = currentCounter + 1;
18413
18522
  try {
18414
- if (actions.save_quest_action) {
18415
- await actions.save_quest_action(ownerId2, sceneConfigId2, newNode, currentCounter + 1);
18416
- await actions.save_view_data(sceneSaveUrl2, sceneFileData);
18417
- } else {
18418
- const questFileData = {
18419
- nodes: graphDataRef2.current[sceneConfigId2].nodes,
18420
- links: graphDataRef2.current[sceneConfigId2].links,
18421
- milestones: sceneDataRef2.current.milestones || []
18422
- };
18423
- await actions.save_view_data(sceneSaveUrl2, sceneFileData);
18424
- const questSaveUrl = sceneSaveUrl2.replace("x_view_scenes", "x_view_quests");
18425
- await actions.save_view_data(questSaveUrl, questFileData);
18523
+ if (actions.upsert_quest_firestore) {
18524
+ await actions.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
18426
18525
  }
18427
- sceneDataRef2.current.quest_counter = currentCounter + 1;
18526
+ if (actions.update_view_counter) {
18527
+ await actions.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
18528
+ }
18529
+ sceneDataRef2.current.quest_counter = nextCounter;
18428
18530
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
18429
18531
  parentFileId: sceneConfigId2,
18430
18532
  ownerId: ownerId2,
@@ -18455,88 +18557,6 @@ function XViewScene({
18455
18557
  alert("Ocorreu um erro ao criar a Quest.");
18456
18558
  }
18457
18559
  };
18458
- userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
18459
- const {
18460
- stateRef: stateRef2,
18461
- graphDataRef: graphDataRef2,
18462
- sceneDataRef: sceneDataRef2,
18463
- sceneConfigId: sceneConfigId2,
18464
- sceneSaveUrl: sceneSaveUrl2,
18465
- ownerId: ownerId2
18466
- } = context;
18467
- const { sourceNodeData } = stateRef2.current.connection;
18468
- if (!graphDataRef2.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
18469
- userActionHandlers.handleCancelConnection(context);
18470
- return;
18471
- }
18472
- const sourceParentInfo = getParentFileInfoForNode(
18473
- graphDataRef2.current,
18474
- sceneDataRef2.current,
18475
- sourceNodeData.id,
18476
- sceneConfigId2,
18477
- ownerId2
18478
- );
18479
- const targetParentInfo = getParentFileInfoForNode(
18480
- graphDataRef2.current,
18481
- sceneDataRef2.current,
18482
- targetNodeData.id,
18483
- sceneConfigId2,
18484
- ownerId2
18485
- );
18486
- let parentInfoToSave = sourceParentInfo;
18487
- const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
18488
- const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
18489
- if (isSourceQuest || isTargetQuest) {
18490
- parentInfoToSave = { parentFileId: sceneConfigId2, ownerId: ownerId2 };
18491
- }
18492
- const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
18493
- const newLink = {
18494
- id: `link_${short2.generate()}`,
18495
- source: sourceNodeData.id,
18496
- target: targetNodeData.id
18497
- };
18498
- try {
18499
- if (parentFileIdToSave === sceneConfigId2) {
18500
- const specificParentData = graphDataRef2.current[sceneConfigId2];
18501
- specificParentData.links.push(newLink);
18502
- if (context.actions.save_quest_link_action && (isSourceQuest || isTargetQuest)) {
18503
- await context.actions.save_quest_link_action(ownerId2, sceneConfigId2, newLink);
18504
- } else {
18505
- const viewFilePayload = {
18506
- ...sceneDataRef2.current,
18507
- quest_counter: sceneDataRef2.current.quest_counter || 1
18508
- };
18509
- const questFilePayload = {
18510
- nodes: specificParentData.nodes,
18511
- links: specificParentData.links,
18512
- milestones: sceneDataRef2.current.milestones || []
18513
- };
18514
- await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
18515
- const questSaveUrl = sceneSaveUrl2.replace(
18516
- "x_view_scenes",
18517
- "x_view_quests"
18518
- );
18519
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
18520
- }
18521
- } else {
18522
- const specificParentData = JSON.parse(
18523
- JSON.stringify(graphDataRef2.current[parentFileIdToSave])
18524
- );
18525
- specificParentData.links.push(newLink);
18526
- const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
18527
- await context.actions.save_view_data(
18528
- filenameForSpecificParent,
18529
- specificParentData
18530
- );
18531
- graphDataRef2.current[parentFileIdToSave] = specificParentData;
18532
- }
18533
- addNewLinkToScene(stateRef2.current, newLink);
18534
- } catch (error) {
18535
- console.error("Falha ao salvar a nova conex\xE3o:", error);
18536
- alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
18537
- }
18538
- userActionHandlers.handleCancelConnection(context);
18539
- };
18540
18560
  const handleClearAncestryVisuals = useCallback7((ancestryId) => {
18541
18561
  const { renderedAncestries, ancestryGroup } = stateRef.current;
18542
18562
  const renderIndex = renderedAncestries.findIndex(
@@ -18550,7 +18570,9 @@ function XViewScene({
18550
18570
  if (line.material) line.material.dispose();
18551
18571
  });
18552
18572
  renderedAncestries.splice(renderIndex, 1);
18553
- stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
18573
+ stateRef.current.ancestryLinks = renderedAncestries.flatMap(
18574
+ (a) => a.lines
18575
+ );
18554
18576
  }
18555
18577
  }, []);
18556
18578
  const handleRenderAncestry = useCallback7(
@@ -19123,7 +19145,9 @@ function XViewScene({
19123
19145
  });
19124
19146
  };
19125
19147
  renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
19126
- stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
19148
+ stateRef.current.ancestryLinks = renderedAncestries.flatMap(
19149
+ (a) => a.lines
19150
+ );
19127
19151
  tweenToTarget(rootTargetPos, 0.7);
19128
19152
  },
19129
19153
  [
@@ -19258,7 +19282,10 @@ function XViewScene({
19258
19282
  };
19259
19283
  const descriptionText = targetAncestryInfo.description || "";
19260
19284
  const savedSections = targetAncestryInfo.description_sections || [];
19261
- const sections = parseDescriptionSections(descriptionText, savedSections);
19285
+ const sections = parseDescriptionSections(
19286
+ descriptionText,
19287
+ savedSections
19288
+ );
19262
19289
  let focusTargetId = null;
19263
19290
  if (popped && popped.nodeId) {
19264
19291
  const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
@@ -20035,7 +20062,10 @@ function XViewScene({
20035
20062
  }
20036
20063
  if (ancestry_save_url && isExternalSave && get_ancestry_file) {
20037
20064
  try {
20038
- const viewDbResponse = await get_ancestry_file(sceneConfigId, ownerId);
20065
+ const viewDbResponse = await get_ancestry_file(
20066
+ sceneConfigId,
20067
+ ownerId
20068
+ );
20039
20069
  if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
20040
20070
  const hasInViewDb = viewDbResponse.data.some(
20041
20071
  (anc) => String(anc.ancestry_id) === String(ancestryIdToDelete)
@@ -20225,61 +20255,31 @@ function XViewScene({
20225
20255
  async (newMilestones) => {
20226
20256
  var _a2, _b2, _c2;
20227
20257
  if (!sceneDataRef.current) return;
20228
- const oldMilestones = sceneDataRef.current.milestones || [];
20229
- const removedMilestones = oldMilestones.filter(
20230
- (oldM) => !newMilestones.some((newM) => String(newM.id) === String(oldM.id))
20231
- );
20232
- const addedOrUpdatedMilestones = newMilestones.filter(
20233
- (newM) => !oldMilestones.some((oldM) => JSON.stringify(oldM) === JSON.stringify(newM))
20234
- );
20235
20258
  sceneDataRef.current.milestones = newMilestones;
20236
20259
  setSceneVersion((v) => v + 1);
20237
20260
  const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
20238
20261
  if (!isView || !save_view_data || !sceneSaveUrl) return;
20262
+ const questFileData = {
20263
+ nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
20264
+ links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
20265
+ milestones: newMilestones
20266
+ };
20239
20267
  try {
20240
- if (save_milestone_action) {
20241
- const promises = [];
20242
- if (delete_milestone_action) {
20243
- removedMilestones.forEach((m) => promises.push(delete_milestone_action(ownerId, sceneConfigId, m.id)));
20244
- }
20245
- if (addedOrUpdatedMilestones.length > 0) {
20246
- addedOrUpdatedMilestones.forEach((m) => promises.push(save_milestone_action(ownerId, sceneConfigId, m)));
20247
- }
20248
- await Promise.all(promises);
20249
- const sceneFileData = {
20250
- ...sceneDataRef.current,
20251
- nodes: sceneDataRef.current.nodes || [],
20252
- links: sceneDataRef.current.links || [],
20253
- quest_counter: sceneDataRef.current.quest_counter || 1
20254
- };
20255
- await save_view_data(sceneSaveUrl, sceneFileData);
20256
- } else {
20257
- const sceneFileData = {
20258
- ...sceneDataRef.current,
20259
- nodes: sceneDataRef.current.nodes || [],
20260
- links: sceneDataRef.current.links || [],
20261
- quest_counter: sceneDataRef.current.quest_counter || 1
20262
- };
20263
- const questFileData = {
20264
- nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
20265
- links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
20266
- milestones: newMilestones
20267
- };
20268
- await save_view_data(sceneSaveUrl, sceneFileData);
20269
- const questSaveUrl = sceneSaveUrl.replace(
20270
- "x_view_scenes",
20271
- "x_view_quests"
20268
+ if (upsert_milestone_firestore) {
20269
+ await upsert_milestone_firestore(
20270
+ ownerId,
20271
+ sceneConfigId,
20272
+ newMilestones
20272
20273
  );
20273
- await save_view_data(questSaveUrl, questFileData);
20274
20274
  }
20275
20275
  } catch (error) {
20276
20276
  console.error("Erro ao salvar milestones:", error);
20277
20277
  }
20278
20278
  },
20279
- [sceneConfigId, sceneSaveUrl, save_view_data, save_milestone_action, delete_milestone_action, viewParams == null ? void 0 : viewParams.type]
20279
+ [sceneConfigId, sceneSaveUrl, save_view_data, viewParams == null ? void 0 : viewParams.type]
20280
20280
  );
20281
20281
  const handleSaveCurrentView = useCallback7(async () => {
20282
- var _a2, _b2, _c2;
20282
+ var _a2;
20283
20283
  const { nodeObjects, allLinks } = stateRef.current;
20284
20284
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
20285
20285
  console.warn(
@@ -20309,23 +20309,10 @@ function XViewScene({
20309
20309
  const sceneFileData = {
20310
20310
  ...sceneDataRef.current,
20311
20311
  nodes: currentNodes,
20312
- links: currentLinks,
20313
- quest_counter: sceneDataRef.current.quest_counter || 1
20314
- };
20315
- const questFileData = {
20316
- nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
20317
- links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || [],
20318
- milestones: sceneDataRef.current.milestones || []
20312
+ links: currentLinks
20319
20313
  };
20320
20314
  try {
20321
20315
  await save_view_data(sceneSaveUrl, sceneFileData);
20322
- if (isView) {
20323
- const questSaveUrl = sceneSaveUrl.replace(
20324
- "x_view_scenes",
20325
- "x_view_quests"
20326
- );
20327
- await save_view_data(questSaveUrl, questFileData);
20328
- }
20329
20316
  } catch (error) {
20330
20317
  console.error("Erro na chamada de save_view_data:", error);
20331
20318
  }
@@ -21024,12 +21011,18 @@ function XViewScene({
21024
21011
  data: multiContextMenu,
21025
21012
  userRole: userPermissionRole,
21026
21013
  onClose: () => setMultiContextMenu((prev) => ({ ...prev, visible: false })),
21027
- onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(actionHandlerContext, ids),
21014
+ onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
21015
+ actionHandlerContext,
21016
+ ids
21017
+ ),
21028
21018
  onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(
21029
21019
  actionHandlerContext,
21030
21020
  ids
21031
21021
  ),
21032
- onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
21022
+ onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(
21023
+ actionHandlerContext,
21024
+ ids
21025
+ )
21033
21026
  }
21034
21027
  ),
21035
21028
  /* @__PURE__ */ React32.createElement(
@@ -21182,25 +21175,40 @@ async function save_view_data_logic(db_services, filename, data) {
21182
21175
  }
21183
21176
  }
21184
21177
  async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
21185
- var _a, _b;
21178
+ var _a, _b, _c;
21186
21179
  try {
21187
21180
  if (!session || !session.user) {
21188
21181
  return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
21189
21182
  }
21190
- const membershipCheck = await db_services.check_membership(owner_id, type, scene_config, session.user.id);
21183
+ const membershipCheck = await db_services.check_membership(
21184
+ owner_id,
21185
+ type,
21186
+ scene_config,
21187
+ session.user.id
21188
+ );
21191
21189
  const isFullMember = membershipCheck.success && membershipCheck.isValidMember;
21192
21190
  if (!isFullMember && !focusNodeId && !focusAncestryId) {
21193
- return { success: false, error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio." };
21191
+ return {
21192
+ success: false,
21193
+ error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio."
21194
+ };
21194
21195
  }
21195
- const sceneResponse = await db_services.get_file(`x_view_scenes/${owner_id}/${scene_config}`);
21196
+ const sceneResponse = await db_services.get_file(
21197
+ `x_view_scenes/${owner_id}/${scene_config}`
21198
+ );
21196
21199
  if (!sceneResponse || !sceneResponse.success) {
21197
21200
  console.error("Falha ao buscar dados da cena:", sceneResponse == null ? void 0 : sceneResponse.error);
21198
- return { success: false, error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}` };
21201
+ return {
21202
+ success: false,
21203
+ error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}`
21204
+ };
21199
21205
  }
21200
21206
  const sceneData = sceneResponse.data;
21201
21207
  const parentDbObjects = sceneData.parent_dbs || [];
21202
21208
  if (type && type.toLowerCase().includes("database")) {
21203
- const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
21209
+ const selfExists = parentDbObjects.some(
21210
+ (db) => String(db.db_id) === String(scene_config)
21211
+ );
21204
21212
  if (!selfExists) {
21205
21213
  parentDbObjects.push({ db_id: scene_config, owner_id });
21206
21214
  }
@@ -21209,34 +21217,67 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21209
21217
  const parentResponsesPromises = parentDbObjects.map(
21210
21218
  (db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
21211
21219
  );
21212
- const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
21220
+ if (isView) {
21221
+ const questFetchWithMigrationPromise = (async () => {
21222
+ try {
21223
+ const questsResponse = await db_services.get_view_quests_firestore(
21224
+ owner_id,
21225
+ scene_config
21226
+ );
21227
+ if (questsResponse.success && questsResponse.hasQuests) {
21228
+ return {
21229
+ success: true,
21230
+ data: questsResponse.data,
21231
+ quest_counter: questsResponse.quest_counter
21232
+ };
21233
+ } else {
21234
+ const legacyResponse = await db_services.get_file(
21235
+ `x_view_quests/${owner_id}/${scene_config}`
21236
+ );
21237
+ if (legacyResponse.success && legacyResponse.data) {
21238
+ await db_services.migrate_json_to_firestore(
21239
+ owner_id,
21240
+ scene_config,
21241
+ legacyResponse.data,
21242
+ sceneData.quest_counter
21243
+ );
21244
+ legacyResponse.quest_counter = sceneData.quest_counter || 1;
21245
+ return legacyResponse;
21246
+ }
21247
+ return legacyResponse;
21248
+ }
21249
+ } catch (err) {
21250
+ return { success: false, error: err.message };
21251
+ }
21252
+ })();
21253
+ parentResponsesPromises.push(questFetchWithMigrationPromise);
21254
+ }
21255
+ const parentResponsesResults = await Promise.allSettled(
21256
+ parentResponsesPromises
21257
+ );
21213
21258
  const parentData = {};
21214
21259
  let questDataObj = null;
21215
21260
  for (let i = 0; i < parentResponsesResults.length; i++) {
21216
21261
  const result = parentResponsesResults[i];
21262
+ if (isView && i === parentResponsesResults.length - 1) {
21263
+ if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21264
+ questDataObj = result.value.data;
21265
+ if (result.value.quest_counter !== void 0) {
21266
+ sceneData.quest_counter = result.value.quest_counter;
21267
+ }
21268
+ }
21269
+ continue;
21270
+ }
21217
21271
  const db_info = parentDbObjects[i];
21218
- if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21272
+ if (result.status === "fulfilled" && ((_b = result.value) == null ? void 0 : _b.success)) {
21219
21273
  parentData[db_info.db_id] = result.value.data;
21220
21274
  } else {
21221
21275
  console.warn(
21222
21276
  `Arquivo pai n\xE3o carregado: ${db_info.db_id}. Pode ter sido deletado.`,
21223
- result.status === "rejected" ? result.reason : (_b = result.value) == null ? void 0 : _b.error
21277
+ result.status === "rejected" ? result.reason : (_c = result.value) == null ? void 0 : _c.error
21224
21278
  );
21225
21279
  }
21226
21280
  }
21227
- if (isView) {
21228
- if (db_services.get_x_view_quests_data) {
21229
- const questDataRes = await db_services.get_x_view_quests_data(session, owner_id, scene_config);
21230
- if (questDataRes && questDataRes.success) {
21231
- questDataObj = questDataRes.data;
21232
- }
21233
- } else {
21234
- const questDataRes = await db_services.get_file(`x_view_quests/${owner_id}/${scene_config}`);
21235
- if (questDataRes && questDataRes.success) {
21236
- questDataObj = questDataRes.data;
21237
- }
21238
- }
21239
- }
21240
21281
  const currentQuestNodes = (questDataObj == null ? void 0 : questDataObj.nodes) || [];
21241
21282
  const currentQuestLinks = (questDataObj == null ? void 0 : questDataObj.links) || [];
21242
21283
  const currentMilestones = (questDataObj == null ? void 0 : questDataObj.milestones) || [];
@@ -21249,13 +21290,19 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21249
21290
  }
21250
21291
  const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
21251
21292
  const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
21252
- const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
21253
- const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
21293
+ const parentNodeMap = new Map(
21294
+ allNodes.map((node) => [String(node.id), node])
21295
+ );
21296
+ const parentLinkMap = new Map(
21297
+ allLinks.map((link) => [`${link.source}-${link.target}`, link])
21298
+ );
21254
21299
  const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
21255
21300
  var _a2, _b2;
21256
21301
  const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
21257
21302
  if (nodeTypes.includes("quest")) {
21258
- const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
21303
+ const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find(
21304
+ (qn) => String(qn.id) === String(sceneNode.id)
21305
+ );
21259
21306
  if (dbQuestNode) {
21260
21307
  return { ...sceneNode, ...dbQuestNode };
21261
21308
  }
@@ -21267,18 +21314,22 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21267
21314
  }
21268
21315
  return null;
21269
21316
  }).filter(Boolean);
21270
- const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
21317
+ const validNodeIdsInScene = new Set(
21318
+ validatedNodes.map((node) => String(node.id))
21319
+ );
21271
21320
  const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
21272
- const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
21321
+ const linkExistsInParent = parentLinkMap.has(
21322
+ `${sceneLink.source}-${sceneLink.target}`
21323
+ );
21273
21324
  const nodesAreValidForScene = validNodeIdsInScene.has(String(sceneLink.source)) && validNodeIdsInScene.has(String(sceneLink.target));
21274
21325
  return linkExistsInParent && nodesAreValidForScene;
21275
- }).map((sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`));
21326
+ }).map(
21327
+ (sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`)
21328
+ );
21276
21329
  const validatedSceneData = {
21277
21330
  ...sceneData,
21278
21331
  nodes: validatedNodes,
21279
21332
  links: validatedLinks,
21280
- // Re-injetando no validated para que o restante do sistema (e.g. XViewScene local state)
21281
- // continue acessando as quests sem perceber a separação física
21282
21333
  quest_nodes: currentQuestNodes,
21283
21334
  quest_links: currentQuestLinks,
21284
21335
  milestones: currentMilestones
@@ -21298,7 +21349,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21298
21349
  isSceneFile: false
21299
21350
  });
21300
21351
  });
21301
- const ancestryPromises = ancestryFilePaths.map((file) => db_services.get_file(file.path));
21352
+ const ancestryPromises = ancestryFilePaths.map(
21353
+ (file) => db_services.get_file(file.path)
21354
+ );
21302
21355
  const ancestryResults = await Promise.allSettled(ancestryPromises);
21303
21356
  const ancestriesFromSceneFile = [];
21304
21357
  const ancestriesFromDbFiles = [];
@@ -21324,15 +21377,21 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21324
21377
  }
21325
21378
  });
21326
21379
  const ancestryMap = /* @__PURE__ */ new Map();
21327
- ancestriesFromDbFiles.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
21328
- ancestriesFromSceneFile.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
21380
+ ancestriesFromDbFiles.forEach(
21381
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21382
+ );
21383
+ ancestriesFromSceneFile.forEach(
21384
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21385
+ );
21329
21386
  let ancestryData = Array.from(ancestryMap.values());
21330
21387
  const externalSourcesToRefresh = /* @__PURE__ */ new Map();
21331
21388
  ancestryData.forEach((anc) => {
21332
21389
  const targetSourceId = anc._source_file_id || anc._imported_from_view_id;
21333
21390
  const targetOwnerId = anc._source_owner_id || anc._imported_from_view_owner_id;
21334
21391
  if (targetSourceId && targetSourceId !== scene_config && targetOwnerId) {
21335
- const isAlreadyLoadedAsParent = parentDbObjects.some((db) => String(db.db_id) === String(targetSourceId));
21392
+ const isAlreadyLoadedAsParent = parentDbObjects.some(
21393
+ (db) => String(db.db_id) === String(targetSourceId)
21394
+ );
21336
21395
  if (!isAlreadyLoadedAsParent) {
21337
21396
  const key = `${targetOwnerId}/${targetSourceId}`;
21338
21397
  externalSourcesToRefresh.set(key, {
@@ -21373,12 +21432,16 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21373
21432
  return false;
21374
21433
  }
21375
21434
  if (externalSourcesToRefresh.has(key) && successfullyFetchedSources.has(key)) {
21376
- const stillExists = freshAncestryMap.has(String(localAnc.ancestry_id));
21435
+ const stillExists = freshAncestryMap.has(
21436
+ String(localAnc.ancestry_id)
21437
+ );
21377
21438
  return stillExists;
21378
21439
  }
21379
21440
  return true;
21380
21441
  }).map((localAnc) => {
21381
- const freshVersion = freshAncestryMap.get(String(localAnc.ancestry_id));
21442
+ const freshVersion = freshAncestryMap.get(
21443
+ String(localAnc.ancestry_id)
21444
+ );
21382
21445
  if (freshVersion) {
21383
21446
  return {
21384
21447
  ...freshVersion,
@@ -21417,7 +21480,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21417
21480
  parallel_branches: validBranches
21418
21481
  };
21419
21482
  };
21420
- const originalAncestryDataString = JSON.stringify(Array.from(ancestryMap.values()));
21483
+ const originalAncestryDataString = JSON.stringify(
21484
+ Array.from(ancestryMap.values())
21485
+ );
21421
21486
  const cleanedAncestryData = ancestryData.map((ancestry) => {
21422
21487
  if (!parentNodeIds.has(String(ancestry.ancestral_node))) return null;
21423
21488
  const cleanedTree = pruneTree(ancestry.tree);
@@ -21437,7 +21502,10 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21437
21502
  try {
21438
21503
  await db_services.save_file(ancestryFilePath, ancestryData);
21439
21504
  } catch (saveError) {
21440
- console.error("Falha ao salvar o arquivo de ancestralidade da cena atualizado:", saveError);
21505
+ console.error(
21506
+ "Falha ao salvar o arquivo de ancestralidade da cena atualizado:",
21507
+ saveError
21508
+ );
21441
21509
  }
21442
21510
  }
21443
21511
  if (!isFullMember) {
@@ -21445,7 +21513,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21445
21513
  const requiredAncestryIds = /* @__PURE__ */ new Set();
21446
21514
  if (focusNodeId) requiredNodeIds.add(String(focusNodeId));
21447
21515
  if (focusAncestryId) requiredAncestryIds.add(String(focusAncestryId));
21448
- const allNodesFromDb = Object.values(parentData).flatMap((db) => db.nodes || []);
21516
+ const allNodesFromDb = Object.values(parentData).flatMap(
21517
+ (db) => db.nodes || []
21518
+ );
21449
21519
  const extractDependenciesFromText = (text) => {
21450
21520
  if (!text) return;
21451
21521
  const mentionRegex = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
@@ -21472,9 +21542,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21472
21542
  if (branch.linked_ancestry_id) {
21473
21543
  requiredAncestryIds.add(String(branch.linked_ancestry_id));
21474
21544
  }
21475
- if (branch.description) extractDependenciesFromText(branch.description);
21545
+ if (branch.description)
21546
+ extractDependenciesFromText(branch.description);
21476
21547
  if (branch.description_sections) {
21477
- branch.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21548
+ branch.description_sections.forEach(
21549
+ (s) => extractDependenciesFromText(s.content)
21550
+ );
21478
21551
  }
21479
21552
  extractTreeDependencies(branch.tree);
21480
21553
  });
@@ -21488,7 +21561,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21488
21561
  if (anc && !anc.is_private) {
21489
21562
  if (anc.description) extractDependenciesFromText(anc.description);
21490
21563
  if (anc.description_sections) {
21491
- anc.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21564
+ anc.description_sections.forEach(
21565
+ (s) => extractDependenciesFromText(s.content)
21566
+ );
21492
21567
  }
21493
21568
  extractTreeDependencies(anc.tree);
21494
21569
  extractTreeDependencies(anc.abstraction_tree);
@@ -21499,22 +21574,38 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21499
21574
  if (node) {
21500
21575
  if (node.description) extractDependenciesFromText(node.description);
21501
21576
  if (node.description_sections) {
21502
- node.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21577
+ node.description_sections.forEach(
21578
+ (s) => extractDependenciesFromText(s.content)
21579
+ );
21503
21580
  }
21504
21581
  }
21505
21582
  });
21506
21583
  } while (requiredNodeIds.size + requiredAncestryIds.size > previousSize);
21507
- const restrictedSceneData = { ...validatedSceneData, nodes: [], links: [] };
21584
+ const restrictedSceneData = {
21585
+ ...validatedSceneData,
21586
+ nodes: [],
21587
+ links: []
21588
+ };
21508
21589
  const restrictedParentData = {};
21509
- const restrictedAncestryData = ancestryData.filter((a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private);
21590
+ const restrictedAncestryData = ancestryData.filter(
21591
+ (a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private
21592
+ );
21510
21593
  for (const [dbId, dbContent] of Object.entries(parentData)) {
21511
- const filteredNodes = (dbContent.nodes || []).filter((n) => requiredNodeIds.has(String(n.id)));
21594
+ const filteredNodes = (dbContent.nodes || []).filter(
21595
+ (n) => requiredNodeIds.has(String(n.id))
21596
+ );
21512
21597
  if (filteredNodes.length > 0) {
21513
- restrictedParentData[dbId] = { ...dbContent, nodes: filteredNodes, links: [] };
21598
+ restrictedParentData[dbId] = {
21599
+ ...dbContent,
21600
+ nodes: filteredNodes,
21601
+ links: []
21602
+ };
21514
21603
  }
21515
21604
  }
21516
21605
  if (focusNodeId) {
21517
- const mainNode = allNodesFromDb.find((n) => String(n.id) === String(focusNodeId));
21606
+ const mainNode = allNodesFromDb.find(
21607
+ (n) => String(n.id) === String(focusNodeId)
21608
+ );
21518
21609
  if (mainNode) {
21519
21610
  restrictedSceneData.nodes = [mainNode];
21520
21611
  }
@@ -21530,7 +21621,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21530
21621
  }
21531
21622
  return {
21532
21623
  success: true,
21533
- data: { scene: validatedSceneData, parent: parentData, ancestry: ancestryData }
21624
+ data: {
21625
+ scene: validatedSceneData,
21626
+ parent: parentData,
21627
+ ancestry: ancestryData
21628
+ }
21534
21629
  };
21535
21630
  } catch (error) {
21536
21631
  console.error("Erro em get_scene_view_data_logic:", error);
@@ -21550,13 +21645,18 @@ async function import_parent_file_modal_get_logic(db_services, session) {
21550
21645
  }
21551
21646
  };
21552
21647
  } catch (error) {
21553
- console.error("catch (error) em import_parent_file_modal_get_logic:", error);
21648
+ console.error(
21649
+ "catch (error) em import_parent_file_modal_get_logic:",
21650
+ error
21651
+ );
21554
21652
  return { success: false, error: error.message };
21555
21653
  }
21556
21654
  }
21557
21655
  async function get_single_parent_file_logic(db_services, file_id, session) {
21558
21656
  try {
21559
- const call_GCP_cloud_storage_get_file = await db_services.get_file(`x_view_dbs/${session.user.id}/${file_id}`);
21657
+ const call_GCP_cloud_storage_get_file = await db_services.get_file(
21658
+ `x_view_dbs/${session.user.id}/${file_id}`
21659
+ );
21560
21660
  return call_GCP_cloud_storage_get_file;
21561
21661
  } catch (error) {
21562
21662
  console.error("catch (error) em get_single_parent_file_logic:", error);
@@ -21590,7 +21690,13 @@ async function get_ancestry_file_logic(db_services, file_id, owner_id) {
21590
21690
  async function save_boards_logic(db_services, scene_id, type, boardItems, session, owner_id) {
21591
21691
  try {
21592
21692
  const targetOwnerId = owner_id || session.user.id;
21593
- return await db_services.save_boards(session, scene_id, type, boardItems, targetOwnerId);
21693
+ return await db_services.save_boards(
21694
+ session,
21695
+ scene_id,
21696
+ type,
21697
+ boardItems,
21698
+ targetOwnerId
21699
+ );
21594
21700
  } catch (error) {
21595
21701
  console.error("Erro em save_boards_logic:", error);
21596
21702
  return { success: false, error: error.message };
@@ -21619,7 +21725,10 @@ async function delete_uploaded_file_logic(db_services, fileUrl) {
21619
21725
  async function get_view_members_logic(db_services, ownerId, type, itemId) {
21620
21726
  try {
21621
21727
  if (!db_services.get_view_members) {
21622
- return { success: false, error: "Servi\xE7o de busca de membros n\xE3o configurado." };
21728
+ return {
21729
+ success: false,
21730
+ error: "Servi\xE7o de busca de membros n\xE3o configurado."
21731
+ };
21623
21732
  }
21624
21733
  return await db_services.get_view_members(ownerId, type, itemId);
21625
21734
  } catch (error) {