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

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 +574 -464
  2. package/dist/index.mjs +612 -502
  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(
@@ -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) => {
@@ -13417,7 +13536,7 @@ ${noteText}` : noteText : entry.notes,
13417
13536
  }
13418
13537
 
13419
13538
  // src/components/MultiNodeContextMenu.jsx
13420
- import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState21, useEffect as useEffect18 } from "react";
13539
+ import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef16, useState as useState21, useEffect as useEffect18 } from "react";
13421
13540
  function MultiNodeContextMenu({
13422
13541
  data,
13423
13542
  userRole,
@@ -13426,7 +13545,7 @@ function MultiNodeContextMenu({
13426
13545
  onDismissOtherNodes,
13427
13546
  onDeleteNodes
13428
13547
  }) {
13429
- const menuRef = useRef15(null);
13548
+ const menuRef = useRef16(null);
13430
13549
  const [menuPos, setMenuPos] = useState21({ left: 0, top: 0 });
13431
13550
  const [isConfirmingDelete, setIsConfirmingDelete] = useState21(false);
13432
13551
  const ability = defineAbilityFor(userRole);
@@ -13493,7 +13612,7 @@ function MultiNodeContextMenu({
13493
13612
  }
13494
13613
 
13495
13614
  // src/components/RelationshipDetailsPanel.jsx
13496
- import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef16, useMemo as useMemo10 } from "react";
13615
+ import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef17, useMemo as useMemo10 } from "react";
13497
13616
  import { v4 as uuidv410 } from "uuid";
13498
13617
  import { FiPlus as FiPlus10, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
13499
13618
  function RelationshipDetailsPanel({
@@ -13524,7 +13643,7 @@ function RelationshipDetailsPanel({
13524
13643
  const [isSaving, setIsSaving] = useState22(false);
13525
13644
  const [isReadMode, setIsReadMode] = useState22(false);
13526
13645
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState22(false);
13527
- const propsEndRef = useRef16(null);
13646
+ const propsEndRef = useRef17(null);
13528
13647
  const canEdit = useMemo10(() => {
13529
13648
  const ability = defineAbilityFor(userRole);
13530
13649
  return ability.can("update", "Connection");
@@ -13845,7 +13964,7 @@ function RelationshipDetailsPanel({
13845
13964
  }
13846
13965
 
13847
13966
  // src/components/RelationshipContextMenu.jsx
13848
- import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef17, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13967
+ import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef18, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13849
13968
  function RelationshipContextMenu({
13850
13969
  data,
13851
13970
  userRole,
@@ -13855,7 +13974,7 @@ function RelationshipContextMenu({
13855
13974
  onDelete,
13856
13975
  onClose
13857
13976
  }) {
13858
- const menuRef = useRef17(null);
13977
+ const menuRef = useRef18(null);
13859
13978
  const [menuPos, setMenuPos] = useState23({ left: 0, top: 0 });
13860
13979
  const [isConfirmingDelete, setIsConfirmingDelete] = useState23(false);
13861
13980
  const ability = useMemo11(() => defineAbilityFor(userRole), [userRole]);
@@ -14337,7 +14456,7 @@ import React30, {
14337
14456
  useState as useState28,
14338
14457
  useMemo as useMemo13,
14339
14458
  useEffect as useEffect24,
14340
- useRef as useRef20,
14459
+ useRef as useRef21,
14341
14460
  useCallback as useCallback6
14342
14461
  } from "react";
14343
14462
  import {
@@ -14363,10 +14482,10 @@ import {
14363
14482
  import { v4 as uuidv411 } from "uuid";
14364
14483
 
14365
14484
  // src/components/RichGroupEditor.jsx
14366
- import React29, { useEffect as useEffect23, useRef as useRef19, useState as useState27, useCallback as useCallback5 } from "react";
14485
+ import React29, { useEffect as useEffect23, useRef as useRef20, useState as useState27, useCallback as useCallback5 } from "react";
14367
14486
 
14368
14487
  // src/components/MentionPopover.jsx
14369
- import React28, { useEffect as useEffect22, useRef as useRef18, useState as useState26, useMemo as useMemo12 } from "react";
14488
+ import React28, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useMemo as useMemo12 } from "react";
14370
14489
  import { FiLayers as FiLayers7, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch5, FiBox } from "react-icons/fi";
14371
14490
  var TYPE_CONFIG = {
14372
14491
  ancestry: { Icon: FiLayers7, color: "text-indigo-400", label: "Ancestralidade" },
@@ -14376,7 +14495,7 @@ var TYPE_CONFIG = {
14376
14495
  };
14377
14496
  function MentionPopover({ query, items, position, onSelect, onClose }) {
14378
14497
  const [activeIndex, setActiveIndex] = useState26(0);
14379
- const listRef = useRef18(null);
14498
+ const listRef = useRef19(null);
14380
14499
  const filtered = useMemo12(() => {
14381
14500
  const term = (query || "").toLowerCase().trim();
14382
14501
  if (!term) return items.slice(0, 8);
@@ -14516,9 +14635,9 @@ var RichGroupEditor = React29.memo(function RichGroupEditor2({
14516
14635
  readOnly,
14517
14636
  placeholder
14518
14637
  }) {
14519
- const editorRef = useRef19(null);
14520
- const isMountedRef = useRef19(false);
14521
- const dismissedTriggerRef = useRef19(null);
14638
+ const editorRef = useRef20(null);
14639
+ const isMountedRef = useRef20(false);
14640
+ const dismissedTriggerRef = useRef20(null);
14522
14641
  const [mentionState, setMentionState] = useState27(null);
14523
14642
  const [isEmpty, setIsEmpty] = useState27(true);
14524
14643
  useEffect23(() => {
@@ -14986,7 +15105,7 @@ function Boards({
14986
15105
  const [isLoaded, setIsLoaded] = useState28(false);
14987
15106
  const [saveStatus, setSaveStatus] = useState28("idle");
14988
15107
  const [navigationStack, setNavigationStack] = useState28([]);
14989
- const lastSavedBoardItemsRef = useRef20(null);
15108
+ const lastSavedBoardItemsRef = useRef21(null);
14990
15109
  const canEdit = useMemo13(() => userRole !== "viewer", [userRole]);
14991
15110
  const findGroupAndParent = (list, targetId, parent = null) => {
14992
15111
  for (let i = 0; i < list.length; i++) {
@@ -15558,13 +15677,12 @@ function XViewScene({
15558
15677
  get_view_members,
15559
15678
  create_google_doc_action,
15560
15679
  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
15680
+ upsert_quest_firestore,
15681
+ delete_quest_firestore,
15682
+ upsert_quest_link_firestore,
15683
+ delete_quest_link_firestore,
15684
+ upsert_milestone_firestore,
15685
+ update_view_counter
15568
15686
  }) {
15569
15687
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
15570
15688
  const { data: session, status } = useSession();
@@ -15638,10 +15756,10 @@ function XViewScene({
15638
15756
  }
15639
15757
  return null;
15640
15758
  }, [ownerId, sceneConfigId]);
15641
- const sceneDataRef = useRef21(null);
15642
- const parentDataRef = useRef21(null);
15759
+ const sceneDataRef = useRef22(null);
15760
+ const parentDataRef = useRef22(null);
15643
15761
  const graphDataRef = parentDataRef;
15644
- const ancestryDataRef = useRef21(null);
15762
+ const ancestryDataRef = useRef22(null);
15645
15763
  const [isLoading, setIsLoading] = useState30(true);
15646
15764
  const [permissionStatus, setPermissionStatus] = useState30("loading");
15647
15765
  const [userPermissionRole, setUserPermissionRole] = useState30(null);
@@ -15730,10 +15848,10 @@ function XViewScene({
15730
15848
  const [boardItems, setBoardItems] = useState30([]);
15731
15849
  const [isSidebarOpen, setIsSidebarOpen] = useState30(false);
15732
15850
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState30(false);
15733
- const mountRef = useRef21(null);
15734
- const tooltipRef = useRef21(null);
15735
- const formRef = useRef21(null);
15736
- const stateRef = useRef21({
15851
+ const mountRef = useRef22(null);
15852
+ const tooltipRef = useRef22(null);
15853
+ const formRef = useRef22(null);
15854
+ const stateRef = useRef22({
15737
15855
  readMode: {
15738
15856
  currentMaxIndex: 0,
15739
15857
  progressMap: {}
@@ -16124,11 +16242,19 @@ function XViewScene({
16124
16242
  }
16125
16243
  }
16126
16244
  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();
16245
+ const oldTimelineLabel = mesh.getObjectByName("timelineLabel");
16246
+ if (oldTimelineLabel) {
16247
+ mesh.remove(oldTimelineLabel);
16248
+ if (oldTimelineLabel.material.map)
16249
+ oldTimelineLabel.material.map.dispose();
16250
+ oldTimelineLabel.material.dispose();
16251
+ }
16252
+ const oldQuestDateLabel = mesh.getObjectByName("questDateLabel");
16253
+ if (oldQuestDateLabel) {
16254
+ mesh.remove(oldQuestDateLabel);
16255
+ if (oldQuestDateLabel.material.map)
16256
+ oldQuestDateLabel.material.map.dispose();
16257
+ oldQuestDateLabel.material.dispose();
16132
16258
  }
16133
16259
  delete mesh.userData.timelineIntervalBar;
16134
16260
  delete mesh.userData.timelineEndLabel;
@@ -16148,42 +16274,24 @@ function XViewScene({
16148
16274
  return null;
16149
16275
  };
16150
16276
  Object.values(nodeObjects).forEach((mesh) => {
16151
- const dateProp = mesh.userData.Date;
16277
+ var _a2;
16278
+ const dateProp = mesh.userData.Date || ((_a2 = (mesh.userData.properties || []).find(
16279
+ (p) => {
16280
+ var _a3;
16281
+ return ((_a3 = p.name) == null ? void 0 : _a3.toLowerCase()) === "data";
16282
+ }
16283
+ )) == null ? void 0 : _a2.value);
16152
16284
  let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
16153
16285
  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
- }
16286
+ const info = parseDateProp(dateProp);
16287
+ if (!info.isUndated) {
16288
+ nodeInfo.startDate = info.startDate;
16289
+ nodeInfo.endDate = info.endDate;
16290
+ nodeInfo.label = info.label;
16291
+ nodeInfo.type = info.type;
16292
+ nodeInfo.isUndated = false;
16293
+ allTimePoints.add(info.startDate.getTime());
16294
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16187
16295
  }
16188
16296
  }
16189
16297
  timelineNodes.push(nodeInfo);
@@ -16311,50 +16419,35 @@ function XViewScene({
16311
16419
  return null;
16312
16420
  };
16313
16421
  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);
16422
+ var _a2;
16423
+ const dateProp = mesh.userData.Date || ((_a2 = (mesh.userData.properties || []).find(
16424
+ (p) => {
16425
+ var _a3;
16426
+ return ((_a3 = p.name) == null ? void 0 : _a3.toLowerCase()) === "data";
16349
16427
  }
16428
+ )) == null ? void 0 : _a2.value);
16429
+ if (!dateProp) return;
16430
+ const info = parseDateProp(dateProp);
16431
+ if (!info.isUndated) {
16432
+ const nodeInfo = {
16433
+ mesh,
16434
+ type: info.type,
16435
+ startDate: info.startDate,
16436
+ endDate: info.endDate,
16437
+ label: info.label
16438
+ };
16439
+ allTimePoints.add(info.startDate.getTime());
16440
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16441
+ timelineNodes.push(nodeInfo);
16350
16442
  }
16351
16443
  });
16352
16444
  if (timelineNodes.length === 0) return;
16353
16445
  const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
16446
+ const maxTimeIndex = sortedTimePoints.length - 1;
16354
16447
  const timeToYMap = new Map(
16355
16448
  sortedTimePoints.map((time, index) => [
16356
16449
  time,
16357
- index * TIMELINE_LAYER_SPACING_Y
16450
+ (index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
16358
16451
  ])
16359
16452
  );
16360
16453
  timelineNodes.sort(
@@ -16362,18 +16455,38 @@ function XViewScene({
16362
16455
  );
16363
16456
  const baseX = sourceMesh.position.x + TIMELINE_NODE_SPACING_X;
16364
16457
  const baseY = sourceMesh.position.y;
16365
- const maxNodeIndex = timelineNodes.length - 1;
16366
- timelineNodes.forEach((node, index) => {
16458
+ const columns = [];
16459
+ const allFinalPoints = [sourceMesh.position.clone()];
16460
+ timelineNodes.forEach((node) => {
16367
16461
  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);
16462
+ const startY = timeToYMap.get(startDate.getTime());
16463
+ const endY = timeToYMap.get(endDate.getTime()) || startY;
16464
+ let foundColumn = false;
16465
+ for (let i = 0; i < columns.length; i++) {
16466
+ if (columns[i].endY < startY) {
16467
+ node.columnIndex = i;
16468
+ columns[i].endY = endY;
16469
+ foundColumn = true;
16470
+ break;
16471
+ }
16472
+ }
16473
+ if (!foundColumn) {
16474
+ node.columnIndex = columns.length;
16475
+ columns.push({ endY });
16476
+ }
16477
+ const x = baseX + node.columnIndex * TIMELINE_NODE_SPACING_X;
16478
+ const y = baseY + startY;
16479
+ allFinalPoints.push(new THREE3.Vector3(x, y, 0));
16480
+ const versionTween = new Tween2(mesh.position).to({ x, y, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
16370
16481
  tweenGroup.add(versionTween);
16371
16482
  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);
16483
+ if (!mesh.getObjectByName("questDateLabel")) {
16484
+ const startLabelText = type === "interval" ? startDate.getFullYear().toString() : label;
16485
+ const startLabel = createTextSprite(startLabelText, 48);
16486
+ startLabel.name = "timelineLabel";
16487
+ startLabel.position.set(0, -2.5, 0);
16488
+ mesh.add(startLabel);
16489
+ }
16377
16490
  if (type === "interval") {
16378
16491
  const relativeEndY = timeToYMap.get(endDate.getTime()) - timeToYMap.get(startDate.getTime());
16379
16492
  if (relativeEndY > 0) {
@@ -16407,7 +16520,21 @@ function XViewScene({
16407
16520
  }
16408
16521
  }
16409
16522
  });
16410
- }, []);
16523
+ if (allFinalPoints.length > 0) {
16524
+ const boundingBox = new THREE3.Box3().setFromPoints(allFinalPoints);
16525
+ const center = new THREE3.Vector3();
16526
+ boundingBox.getCenter(center);
16527
+ const size = new THREE3.Vector3();
16528
+ boundingBox.getSize(size);
16529
+ const spread = Math.max(size.x, size.y, size.z, 1);
16530
+ const desiredDistance = Math.max(
16531
+ x_view_config.CAMERA_ZOOM_DISTANCE,
16532
+ spread * 1.5
16533
+ );
16534
+ const zoomFactor = x_view_config.CAMERA_ZOOM_DISTANCE / desiredDistance;
16535
+ tweenToTarget(center, zoomFactor);
16536
+ }
16537
+ }, [tweenToTarget]);
16411
16538
  useEffect25(() => {
16412
16539
  async function fetchAllData(configPath, ownerId2) {
16413
16540
  var _a2, _b2;
@@ -18072,12 +18199,13 @@ function XViewScene({
18072
18199
  get_scene_view_data,
18073
18200
  upload_file: upload_file_action,
18074
18201
  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
18202
+ // Adicionado novas importações aqui
18203
+ upsert_quest_firestore,
18204
+ delete_quest_firestore,
18205
+ upsert_quest_link_firestore,
18206
+ delete_quest_link_firestore,
18207
+ upsert_milestone_firestore,
18208
+ update_view_counter
18081
18209
  }
18082
18210
  };
18083
18211
  },
@@ -18097,12 +18225,12 @@ function XViewScene({
18097
18225
  get_scene_view_data,
18098
18226
  upload_file_action,
18099
18227
  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
18228
+ upsert_quest_firestore,
18229
+ delete_quest_firestore,
18230
+ upsert_quest_link_firestore,
18231
+ delete_quest_link_firestore,
18232
+ upsert_milestone_firestore,
18233
+ update_view_counter
18106
18234
  ]
18107
18235
  );
18108
18236
  const handleStartVersioning = (nodeData) => {
@@ -18308,45 +18436,30 @@ function XViewScene({
18308
18436
  parentDataRef.current[sceneConfigId].nodes[parentIndex].quest_abstraction_tree = formattedAbstractionTree;
18309
18437
  }
18310
18438
  }
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"
18439
+ const updatedNodeData = sceneData.quest_nodes[questIndex];
18440
+ if (upsert_quest_firestore) {
18441
+ await upsert_quest_firestore(
18442
+ ownerId,
18443
+ sceneConfigId,
18444
+ updatedNodeData
18330
18445
  );
18331
- await save_view_data(questSaveUrl, questFileData);
18332
18446
  }
18447
+ const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
18448
+ if (nodeMesh) {
18449
+ nodeMesh.userData = {
18450
+ ...nodeMesh.userData,
18451
+ ...updatedNodeData
18452
+ };
18453
+ }
18454
+ if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
18455
+ setDetailsNode((prev) => ({
18456
+ ...prev,
18457
+ quest_tree: formattedTree,
18458
+ quest_abstraction_tree: formattedAbstractionTree
18459
+ }));
18460
+ }
18461
+ setSceneVersion((v) => v + 1);
18333
18462
  }
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
18463
  }
18351
18464
  }
18352
18465
  };
@@ -18395,7 +18508,6 @@ function XViewScene({
18395
18508
  ownerId: ownerId2
18396
18509
  } = context;
18397
18510
  if (!graphDataRef2.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
18398
- const currentCounter = sceneDataRef2.current.quest_counter || 1;
18399
18511
  const newNode = {
18400
18512
  id: short2.generate(),
18401
18513
  ...newQuestData,
@@ -18406,25 +18518,16 @@ function XViewScene({
18406
18518
  graphDataRef2.current[sceneConfigId2] = { nodes: [], links: [] };
18407
18519
  }
18408
18520
  graphDataRef2.current[sceneConfigId2].nodes.push(newNode);
18409
- const sceneFileData = {
18410
- ...sceneDataRef2.current,
18411
- quest_counter: currentCounter + 1
18412
- };
18521
+ const currentCounter = sceneDataRef2.current.quest_counter || 1;
18522
+ const nextCounter = currentCounter + 1;
18413
18523
  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);
18524
+ if (actions.upsert_quest_firestore) {
18525
+ await actions.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
18426
18526
  }
18427
- sceneDataRef2.current.quest_counter = currentCounter + 1;
18527
+ if (actions.update_view_counter) {
18528
+ await actions.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
18529
+ }
18530
+ sceneDataRef2.current.quest_counter = nextCounter;
18428
18531
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
18429
18532
  parentFileId: sceneConfigId2,
18430
18533
  ownerId: ownerId2,
@@ -18455,88 +18558,6 @@ function XViewScene({
18455
18558
  alert("Ocorreu um erro ao criar a Quest.");
18456
18559
  }
18457
18560
  };
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
18561
  const handleClearAncestryVisuals = useCallback7((ancestryId) => {
18541
18562
  const { renderedAncestries, ancestryGroup } = stateRef.current;
18542
18563
  const renderIndex = renderedAncestries.findIndex(
@@ -18550,7 +18571,9 @@ function XViewScene({
18550
18571
  if (line.material) line.material.dispose();
18551
18572
  });
18552
18573
  renderedAncestries.splice(renderIndex, 1);
18553
- stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
18574
+ stateRef.current.ancestryLinks = renderedAncestries.flatMap(
18575
+ (a) => a.lines
18576
+ );
18554
18577
  }
18555
18578
  }, []);
18556
18579
  const handleRenderAncestry = useCallback7(
@@ -19123,7 +19146,9 @@ function XViewScene({
19123
19146
  });
19124
19147
  };
19125
19148
  renderVertical(fullTree, rootNodeMesh, rootTargetPos, 1);
19126
- stateRef.current.ancestryLinks = renderedAncestries.flatMap((a) => a.lines);
19149
+ stateRef.current.ancestryLinks = renderedAncestries.flatMap(
19150
+ (a) => a.lines
19151
+ );
19127
19152
  tweenToTarget(rootTargetPos, 0.7);
19128
19153
  },
19129
19154
  [
@@ -19258,7 +19283,10 @@ function XViewScene({
19258
19283
  };
19259
19284
  const descriptionText = targetAncestryInfo.description || "";
19260
19285
  const savedSections = targetAncestryInfo.description_sections || [];
19261
- const sections = parseDescriptionSections(descriptionText, savedSections);
19286
+ const sections = parseDescriptionSections(
19287
+ descriptionText,
19288
+ savedSections
19289
+ );
19262
19290
  let focusTargetId = null;
19263
19291
  if (popped && popped.nodeId) {
19264
19292
  const mentionTag = `[[MENTION:node:${popped.nodeId}]]`;
@@ -20035,7 +20063,10 @@ function XViewScene({
20035
20063
  }
20036
20064
  if (ancestry_save_url && isExternalSave && get_ancestry_file) {
20037
20065
  try {
20038
- const viewDbResponse = await get_ancestry_file(sceneConfigId, ownerId);
20066
+ const viewDbResponse = await get_ancestry_file(
20067
+ sceneConfigId,
20068
+ ownerId
20069
+ );
20039
20070
  if (viewDbResponse.success && Array.isArray(viewDbResponse.data)) {
20040
20071
  const hasInViewDb = viewDbResponse.data.some(
20041
20072
  (anc) => String(anc.ancestry_id) === String(ancestryIdToDelete)
@@ -20225,61 +20256,31 @@ function XViewScene({
20225
20256
  async (newMilestones) => {
20226
20257
  var _a2, _b2, _c2;
20227
20258
  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
20259
  sceneDataRef.current.milestones = newMilestones;
20236
20260
  setSceneVersion((v) => v + 1);
20237
20261
  const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
20238
20262
  if (!isView || !save_view_data || !sceneSaveUrl) return;
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
+ };
20239
20268
  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"
20269
+ if (upsert_milestone_firestore) {
20270
+ await upsert_milestone_firestore(
20271
+ ownerId,
20272
+ sceneConfigId,
20273
+ newMilestones
20272
20274
  );
20273
- await save_view_data(questSaveUrl, questFileData);
20274
20275
  }
20275
20276
  } catch (error) {
20276
20277
  console.error("Erro ao salvar milestones:", error);
20277
20278
  }
20278
20279
  },
20279
- [sceneConfigId, sceneSaveUrl, save_view_data, save_milestone_action, delete_milestone_action, viewParams == null ? void 0 : viewParams.type]
20280
+ [sceneConfigId, sceneSaveUrl, save_view_data, viewParams == null ? void 0 : viewParams.type]
20280
20281
  );
20281
20282
  const handleSaveCurrentView = useCallback7(async () => {
20282
- var _a2, _b2, _c2;
20283
+ var _a2;
20283
20284
  const { nodeObjects, allLinks } = stateRef.current;
20284
20285
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
20285
20286
  console.warn(
@@ -20309,23 +20310,10 @@ function XViewScene({
20309
20310
  const sceneFileData = {
20310
20311
  ...sceneDataRef.current,
20311
20312
  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 || []
20313
+ links: currentLinks
20319
20314
  };
20320
20315
  try {
20321
20316
  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
20317
  } catch (error) {
20330
20318
  console.error("Erro na chamada de save_view_data:", error);
20331
20319
  }
@@ -21024,12 +21012,18 @@ function XViewScene({
21024
21012
  data: multiContextMenu,
21025
21013
  userRole: userPermissionRole,
21026
21014
  onClose: () => setMultiContextMenu((prev) => ({ ...prev, visible: false })),
21027
- onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(actionHandlerContext, ids),
21015
+ onDismissNodes: (ids) => userActionHandlers.handleDismissMultipleNodes(
21016
+ actionHandlerContext,
21017
+ ids
21018
+ ),
21028
21019
  onDismissOtherNodes: (ids) => userActionHandlers.handleDismissOtherMultipleNodes(
21029
21020
  actionHandlerContext,
21030
21021
  ids
21031
21022
  ),
21032
- onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(actionHandlerContext, ids)
21023
+ onDeleteNodes: (ids) => userActionHandlers.handleDeleteMultipleNodes(
21024
+ actionHandlerContext,
21025
+ ids
21026
+ )
21033
21027
  }
21034
21028
  ),
21035
21029
  /* @__PURE__ */ React32.createElement(
@@ -21182,25 +21176,40 @@ async function save_view_data_logic(db_services, filename, data) {
21182
21176
  }
21183
21177
  }
21184
21178
  async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
21185
- var _a, _b;
21179
+ var _a, _b, _c;
21186
21180
  try {
21187
21181
  if (!session || !session.user) {
21188
21182
  return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
21189
21183
  }
21190
- const membershipCheck = await db_services.check_membership(owner_id, type, scene_config, session.user.id);
21184
+ const membershipCheck = await db_services.check_membership(
21185
+ owner_id,
21186
+ type,
21187
+ scene_config,
21188
+ session.user.id
21189
+ );
21191
21190
  const isFullMember = membershipCheck.success && membershipCheck.isValidMember;
21192
21191
  if (!isFullMember && !focusNodeId && !focusAncestryId) {
21193
- return { success: false, error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio." };
21192
+ return {
21193
+ success: false,
21194
+ error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio."
21195
+ };
21194
21196
  }
21195
- const sceneResponse = await db_services.get_file(`x_view_scenes/${owner_id}/${scene_config}`);
21197
+ const sceneResponse = await db_services.get_file(
21198
+ `x_view_scenes/${owner_id}/${scene_config}`
21199
+ );
21196
21200
  if (!sceneResponse || !sceneResponse.success) {
21197
21201
  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}` };
21202
+ return {
21203
+ success: false,
21204
+ error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}`
21205
+ };
21199
21206
  }
21200
21207
  const sceneData = sceneResponse.data;
21201
21208
  const parentDbObjects = sceneData.parent_dbs || [];
21202
21209
  if (type && type.toLowerCase().includes("database")) {
21203
- const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
21210
+ const selfExists = parentDbObjects.some(
21211
+ (db) => String(db.db_id) === String(scene_config)
21212
+ );
21204
21213
  if (!selfExists) {
21205
21214
  parentDbObjects.push({ db_id: scene_config, owner_id });
21206
21215
  }
@@ -21209,34 +21218,67 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21209
21218
  const parentResponsesPromises = parentDbObjects.map(
21210
21219
  (db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
21211
21220
  );
21212
- const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
21221
+ if (isView) {
21222
+ const questFetchWithMigrationPromise = (async () => {
21223
+ try {
21224
+ const questsResponse = await db_services.get_view_quests_firestore(
21225
+ owner_id,
21226
+ scene_config
21227
+ );
21228
+ if (questsResponse.success && questsResponse.hasQuests) {
21229
+ return {
21230
+ success: true,
21231
+ data: questsResponse.data,
21232
+ quest_counter: questsResponse.quest_counter
21233
+ };
21234
+ } else {
21235
+ const legacyResponse = await db_services.get_file(
21236
+ `x_view_quests/${owner_id}/${scene_config}`
21237
+ );
21238
+ if (legacyResponse.success && legacyResponse.data) {
21239
+ await db_services.migrate_json_to_firestore(
21240
+ owner_id,
21241
+ scene_config,
21242
+ legacyResponse.data,
21243
+ sceneData.quest_counter
21244
+ );
21245
+ legacyResponse.quest_counter = sceneData.quest_counter || 1;
21246
+ return legacyResponse;
21247
+ }
21248
+ return legacyResponse;
21249
+ }
21250
+ } catch (err) {
21251
+ return { success: false, error: err.message };
21252
+ }
21253
+ })();
21254
+ parentResponsesPromises.push(questFetchWithMigrationPromise);
21255
+ }
21256
+ const parentResponsesResults = await Promise.allSettled(
21257
+ parentResponsesPromises
21258
+ );
21213
21259
  const parentData = {};
21214
21260
  let questDataObj = null;
21215
21261
  for (let i = 0; i < parentResponsesResults.length; i++) {
21216
21262
  const result = parentResponsesResults[i];
21263
+ if (isView && i === parentResponsesResults.length - 1) {
21264
+ if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21265
+ questDataObj = result.value.data;
21266
+ if (result.value.quest_counter !== void 0) {
21267
+ sceneData.quest_counter = result.value.quest_counter;
21268
+ }
21269
+ }
21270
+ continue;
21271
+ }
21217
21272
  const db_info = parentDbObjects[i];
21218
- if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21273
+ if (result.status === "fulfilled" && ((_b = result.value) == null ? void 0 : _b.success)) {
21219
21274
  parentData[db_info.db_id] = result.value.data;
21220
21275
  } else {
21221
21276
  console.warn(
21222
21277
  `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
21278
+ result.status === "rejected" ? result.reason : (_c = result.value) == null ? void 0 : _c.error
21224
21279
  );
21225
21280
  }
21226
21281
  }
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
21282
  const currentQuestNodes = (questDataObj == null ? void 0 : questDataObj.nodes) || [];
21241
21283
  const currentQuestLinks = (questDataObj == null ? void 0 : questDataObj.links) || [];
21242
21284
  const currentMilestones = (questDataObj == null ? void 0 : questDataObj.milestones) || [];
@@ -21249,13 +21291,19 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21249
21291
  }
21250
21292
  const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
21251
21293
  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]));
21294
+ const parentNodeMap = new Map(
21295
+ allNodes.map((node) => [String(node.id), node])
21296
+ );
21297
+ const parentLinkMap = new Map(
21298
+ allLinks.map((link) => [`${link.source}-${link.target}`, link])
21299
+ );
21254
21300
  const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
21255
21301
  var _a2, _b2;
21256
21302
  const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
21257
21303
  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));
21304
+ const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find(
21305
+ (qn) => String(qn.id) === String(sceneNode.id)
21306
+ );
21259
21307
  if (dbQuestNode) {
21260
21308
  return { ...sceneNode, ...dbQuestNode };
21261
21309
  }
@@ -21267,18 +21315,22 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21267
21315
  }
21268
21316
  return null;
21269
21317
  }).filter(Boolean);
21270
- const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
21318
+ const validNodeIdsInScene = new Set(
21319
+ validatedNodes.map((node) => String(node.id))
21320
+ );
21271
21321
  const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
21272
- const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
21322
+ const linkExistsInParent = parentLinkMap.has(
21323
+ `${sceneLink.source}-${sceneLink.target}`
21324
+ );
21273
21325
  const nodesAreValidForScene = validNodeIdsInScene.has(String(sceneLink.source)) && validNodeIdsInScene.has(String(sceneLink.target));
21274
21326
  return linkExistsInParent && nodesAreValidForScene;
21275
- }).map((sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`));
21327
+ }).map(
21328
+ (sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`)
21329
+ );
21276
21330
  const validatedSceneData = {
21277
21331
  ...sceneData,
21278
21332
  nodes: validatedNodes,
21279
21333
  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
21334
  quest_nodes: currentQuestNodes,
21283
21335
  quest_links: currentQuestLinks,
21284
21336
  milestones: currentMilestones
@@ -21298,7 +21350,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21298
21350
  isSceneFile: false
21299
21351
  });
21300
21352
  });
21301
- const ancestryPromises = ancestryFilePaths.map((file) => db_services.get_file(file.path));
21353
+ const ancestryPromises = ancestryFilePaths.map(
21354
+ (file) => db_services.get_file(file.path)
21355
+ );
21302
21356
  const ancestryResults = await Promise.allSettled(ancestryPromises);
21303
21357
  const ancestriesFromSceneFile = [];
21304
21358
  const ancestriesFromDbFiles = [];
@@ -21324,15 +21378,21 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21324
21378
  }
21325
21379
  });
21326
21380
  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));
21381
+ ancestriesFromDbFiles.forEach(
21382
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21383
+ );
21384
+ ancestriesFromSceneFile.forEach(
21385
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21386
+ );
21329
21387
  let ancestryData = Array.from(ancestryMap.values());
21330
21388
  const externalSourcesToRefresh = /* @__PURE__ */ new Map();
21331
21389
  ancestryData.forEach((anc) => {
21332
21390
  const targetSourceId = anc._source_file_id || anc._imported_from_view_id;
21333
21391
  const targetOwnerId = anc._source_owner_id || anc._imported_from_view_owner_id;
21334
21392
  if (targetSourceId && targetSourceId !== scene_config && targetOwnerId) {
21335
- const isAlreadyLoadedAsParent = parentDbObjects.some((db) => String(db.db_id) === String(targetSourceId));
21393
+ const isAlreadyLoadedAsParent = parentDbObjects.some(
21394
+ (db) => String(db.db_id) === String(targetSourceId)
21395
+ );
21336
21396
  if (!isAlreadyLoadedAsParent) {
21337
21397
  const key = `${targetOwnerId}/${targetSourceId}`;
21338
21398
  externalSourcesToRefresh.set(key, {
@@ -21373,12 +21433,16 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21373
21433
  return false;
21374
21434
  }
21375
21435
  if (externalSourcesToRefresh.has(key) && successfullyFetchedSources.has(key)) {
21376
- const stillExists = freshAncestryMap.has(String(localAnc.ancestry_id));
21436
+ const stillExists = freshAncestryMap.has(
21437
+ String(localAnc.ancestry_id)
21438
+ );
21377
21439
  return stillExists;
21378
21440
  }
21379
21441
  return true;
21380
21442
  }).map((localAnc) => {
21381
- const freshVersion = freshAncestryMap.get(String(localAnc.ancestry_id));
21443
+ const freshVersion = freshAncestryMap.get(
21444
+ String(localAnc.ancestry_id)
21445
+ );
21382
21446
  if (freshVersion) {
21383
21447
  return {
21384
21448
  ...freshVersion,
@@ -21417,7 +21481,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21417
21481
  parallel_branches: validBranches
21418
21482
  };
21419
21483
  };
21420
- const originalAncestryDataString = JSON.stringify(Array.from(ancestryMap.values()));
21484
+ const originalAncestryDataString = JSON.stringify(
21485
+ Array.from(ancestryMap.values())
21486
+ );
21421
21487
  const cleanedAncestryData = ancestryData.map((ancestry) => {
21422
21488
  if (!parentNodeIds.has(String(ancestry.ancestral_node))) return null;
21423
21489
  const cleanedTree = pruneTree(ancestry.tree);
@@ -21437,7 +21503,10 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21437
21503
  try {
21438
21504
  await db_services.save_file(ancestryFilePath, ancestryData);
21439
21505
  } catch (saveError) {
21440
- console.error("Falha ao salvar o arquivo de ancestralidade da cena atualizado:", saveError);
21506
+ console.error(
21507
+ "Falha ao salvar o arquivo de ancestralidade da cena atualizado:",
21508
+ saveError
21509
+ );
21441
21510
  }
21442
21511
  }
21443
21512
  if (!isFullMember) {
@@ -21445,7 +21514,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21445
21514
  const requiredAncestryIds = /* @__PURE__ */ new Set();
21446
21515
  if (focusNodeId) requiredNodeIds.add(String(focusNodeId));
21447
21516
  if (focusAncestryId) requiredAncestryIds.add(String(focusAncestryId));
21448
- const allNodesFromDb = Object.values(parentData).flatMap((db) => db.nodes || []);
21517
+ const allNodesFromDb = Object.values(parentData).flatMap(
21518
+ (db) => db.nodes || []
21519
+ );
21449
21520
  const extractDependenciesFromText = (text) => {
21450
21521
  if (!text) return;
21451
21522
  const mentionRegex = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
@@ -21472,9 +21543,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21472
21543
  if (branch.linked_ancestry_id) {
21473
21544
  requiredAncestryIds.add(String(branch.linked_ancestry_id));
21474
21545
  }
21475
- if (branch.description) extractDependenciesFromText(branch.description);
21546
+ if (branch.description)
21547
+ extractDependenciesFromText(branch.description);
21476
21548
  if (branch.description_sections) {
21477
- branch.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21549
+ branch.description_sections.forEach(
21550
+ (s) => extractDependenciesFromText(s.content)
21551
+ );
21478
21552
  }
21479
21553
  extractTreeDependencies(branch.tree);
21480
21554
  });
@@ -21488,7 +21562,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21488
21562
  if (anc && !anc.is_private) {
21489
21563
  if (anc.description) extractDependenciesFromText(anc.description);
21490
21564
  if (anc.description_sections) {
21491
- anc.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21565
+ anc.description_sections.forEach(
21566
+ (s) => extractDependenciesFromText(s.content)
21567
+ );
21492
21568
  }
21493
21569
  extractTreeDependencies(anc.tree);
21494
21570
  extractTreeDependencies(anc.abstraction_tree);
@@ -21499,22 +21575,38 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21499
21575
  if (node) {
21500
21576
  if (node.description) extractDependenciesFromText(node.description);
21501
21577
  if (node.description_sections) {
21502
- node.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21578
+ node.description_sections.forEach(
21579
+ (s) => extractDependenciesFromText(s.content)
21580
+ );
21503
21581
  }
21504
21582
  }
21505
21583
  });
21506
21584
  } while (requiredNodeIds.size + requiredAncestryIds.size > previousSize);
21507
- const restrictedSceneData = { ...validatedSceneData, nodes: [], links: [] };
21585
+ const restrictedSceneData = {
21586
+ ...validatedSceneData,
21587
+ nodes: [],
21588
+ links: []
21589
+ };
21508
21590
  const restrictedParentData = {};
21509
- const restrictedAncestryData = ancestryData.filter((a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private);
21591
+ const restrictedAncestryData = ancestryData.filter(
21592
+ (a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private
21593
+ );
21510
21594
  for (const [dbId, dbContent] of Object.entries(parentData)) {
21511
- const filteredNodes = (dbContent.nodes || []).filter((n) => requiredNodeIds.has(String(n.id)));
21595
+ const filteredNodes = (dbContent.nodes || []).filter(
21596
+ (n) => requiredNodeIds.has(String(n.id))
21597
+ );
21512
21598
  if (filteredNodes.length > 0) {
21513
- restrictedParentData[dbId] = { ...dbContent, nodes: filteredNodes, links: [] };
21599
+ restrictedParentData[dbId] = {
21600
+ ...dbContent,
21601
+ nodes: filteredNodes,
21602
+ links: []
21603
+ };
21514
21604
  }
21515
21605
  }
21516
21606
  if (focusNodeId) {
21517
- const mainNode = allNodesFromDb.find((n) => String(n.id) === String(focusNodeId));
21607
+ const mainNode = allNodesFromDb.find(
21608
+ (n) => String(n.id) === String(focusNodeId)
21609
+ );
21518
21610
  if (mainNode) {
21519
21611
  restrictedSceneData.nodes = [mainNode];
21520
21612
  }
@@ -21530,7 +21622,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21530
21622
  }
21531
21623
  return {
21532
21624
  success: true,
21533
- data: { scene: validatedSceneData, parent: parentData, ancestry: ancestryData }
21625
+ data: {
21626
+ scene: validatedSceneData,
21627
+ parent: parentData,
21628
+ ancestry: ancestryData
21629
+ }
21534
21630
  };
21535
21631
  } catch (error) {
21536
21632
  console.error("Erro em get_scene_view_data_logic:", error);
@@ -21550,13 +21646,18 @@ async function import_parent_file_modal_get_logic(db_services, session) {
21550
21646
  }
21551
21647
  };
21552
21648
  } catch (error) {
21553
- console.error("catch (error) em import_parent_file_modal_get_logic:", error);
21649
+ console.error(
21650
+ "catch (error) em import_parent_file_modal_get_logic:",
21651
+ error
21652
+ );
21554
21653
  return { success: false, error: error.message };
21555
21654
  }
21556
21655
  }
21557
21656
  async function get_single_parent_file_logic(db_services, file_id, session) {
21558
21657
  try {
21559
- const call_GCP_cloud_storage_get_file = await db_services.get_file(`x_view_dbs/${session.user.id}/${file_id}`);
21658
+ const call_GCP_cloud_storage_get_file = await db_services.get_file(
21659
+ `x_view_dbs/${session.user.id}/${file_id}`
21660
+ );
21560
21661
  return call_GCP_cloud_storage_get_file;
21561
21662
  } catch (error) {
21562
21663
  console.error("catch (error) em get_single_parent_file_logic:", error);
@@ -21590,7 +21691,13 @@ async function get_ancestry_file_logic(db_services, file_id, owner_id) {
21590
21691
  async function save_boards_logic(db_services, scene_id, type, boardItems, session, owner_id) {
21591
21692
  try {
21592
21693
  const targetOwnerId = owner_id || session.user.id;
21593
- return await db_services.save_boards(session, scene_id, type, boardItems, targetOwnerId);
21694
+ return await db_services.save_boards(
21695
+ session,
21696
+ scene_id,
21697
+ type,
21698
+ boardItems,
21699
+ targetOwnerId
21700
+ );
21594
21701
  } catch (error) {
21595
21702
  console.error("Erro em save_boards_logic:", error);
21596
21703
  return { success: false, error: error.message };
@@ -21619,7 +21726,10 @@ async function delete_uploaded_file_logic(db_services, fileUrl) {
21619
21726
  async function get_view_members_logic(db_services, ownerId, type, itemId) {
21620
21727
  try {
21621
21728
  if (!db_services.get_view_members) {
21622
- return { success: false, error: "Servi\xE7o de busca de membros n\xE3o configurado." };
21729
+ return {
21730
+ success: false,
21731
+ error: "Servi\xE7o de busca de membros n\xE3o configurado."
21732
+ };
21623
21733
  }
21624
21734
  return await db_services.get_view_members(ownerId, type, itemId);
21625
21735
  } catch (error) {