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

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 +553 -423
  2. package/dist/index.mjs +591 -461
  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,14 +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
1536
+ links: sceneDataRef.current.links
1508
1537
  };
1509
1538
  await context.actions.save_view_data(
1510
1539
  context.sceneSaveUrl,
1511
1540
  viewFilePayload
1512
1541
  );
1513
- await context.actions.save_quest_link(context.ownerId, context.sceneConfigId, newLink);
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
+ }
1514
1549
  } else {
1515
1550
  const specificParentData = JSON.parse(
1516
1551
  JSON.stringify(graphDataRef.current[parentFileIdToSave])
@@ -1659,18 +1694,12 @@ var userActionHandlers = {
1659
1694
  const viewFilePayload = {
1660
1695
  parent_dbs: sceneDataRef.current.parent_dbs,
1661
1696
  nodes: sceneDataRef.current.nodes,
1662
- links: sceneDataRef.current.links,
1663
- quest_counter: sceneDataRef.current.quest_counter || 1
1664
- };
1665
- const questFilePayload = {
1666
- nodes: data.nodes,
1667
- links: data.links,
1668
- milestones: sceneDataRef.current.milestones || []
1697
+ links: sceneDataRef.current.links
1669
1698
  };
1670
- const p1 = context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
1671
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
1672
- const p2 = context.actions.save_view_data(questSaveUrl, questFilePayload);
1673
- return Promise.all([p1, p2]);
1699
+ return context.actions.save_view_data(
1700
+ context.sceneSaveUrl,
1701
+ viewFilePayload
1702
+ );
1674
1703
  } else {
1675
1704
  return context.actions.save_view_data(
1676
1705
  `x_view_dbs/${fileOwnerId}/${fileId}`,
@@ -1695,6 +1724,15 @@ var userActionHandlers = {
1695
1724
  updatedOriginalParentData
1696
1725
  )
1697
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
+ }
1698
1736
  const updatedNewParentData = JSON.parse(
1699
1737
  JSON.stringify(graphDataRef.current[newGoverningFileId])
1700
1738
  );
@@ -1708,6 +1746,15 @@ var userActionHandlers = {
1708
1746
  updatedNewParentData
1709
1747
  )
1710
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
+ }
1711
1758
  } else {
1712
1759
  const updatedParentData = JSON.parse(
1713
1760
  JSON.stringify(graphDataRef.current[oldGoverningFileId])
@@ -1724,6 +1771,15 @@ var userActionHandlers = {
1724
1771
  updatedParentData
1725
1772
  )
1726
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
+ }
1727
1783
  }
1728
1784
  try {
1729
1785
  await Promise.all(savePromises);
@@ -1754,14 +1810,21 @@ var userActionHandlers = {
1754
1810
  );
1755
1811
  return;
1756
1812
  }
1757
- const parentInfo = getParentFileInfoForNode(
1813
+ const sourceParentInfo = getParentFileInfoForNode(
1758
1814
  graphDataRef.current,
1759
1815
  sceneDataRef.current,
1760
1816
  linkObject.userData.source,
1761
1817
  context.sceneConfigId,
1762
1818
  context.ownerId
1763
1819
  );
1764
- 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) {
1765
1828
  console.error(
1766
1829
  "N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:",
1767
1830
  linkIdToDelete
@@ -1771,6 +1834,12 @@ var userActionHandlers = {
1771
1834
  );
1772
1835
  return;
1773
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
+ }
1774
1843
  const { parentFileId, ownerId } = parentInfo;
1775
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;
1776
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;
@@ -1783,8 +1852,6 @@ var userActionHandlers = {
1783
1852
  specificParentData.links = newLinks;
1784
1853
  let filenameToSave;
1785
1854
  let payloadToSave;
1786
- let questSaveUrl;
1787
- let questFilePayload;
1788
1855
  const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
1789
1856
  if (isView && parentFileId === context.sceneConfigId) {
1790
1857
  filenameToSave = context.sceneSaveUrl;
@@ -1794,8 +1861,7 @@ var userActionHandlers = {
1794
1861
  payloadToSave = {
1795
1862
  parent_dbs: sceneDataRef.current.parent_dbs,
1796
1863
  nodes: sceneDataRef.current.nodes,
1797
- links: sceneDataRef.current.links,
1798
- quest_counter: sceneDataRef.current.quest_counter || 1
1864
+ links: sceneDataRef.current.links
1799
1865
  };
1800
1866
  } else {
1801
1867
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
@@ -1803,8 +1869,12 @@ var userActionHandlers = {
1803
1869
  }
1804
1870
  try {
1805
1871
  await context.actions.save_view_data(filenameToSave, payloadToSave);
1806
- if (isView && parentFileId === context.sceneConfigId && context.actions.delete_quest_link) {
1807
- await context.actions.delete_quest_link(ownerId, context.sceneConfigId, linkIdToDelete);
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
+ );
1808
1878
  }
1809
1879
  graphDataRef.current[parentFileId] = specificParentData;
1810
1880
  setters.setDetailsLink(
@@ -2033,18 +2103,30 @@ var userActionHandlers = {
2033
2103
  payloadToSave = {
2034
2104
  parent_dbs: sceneDataRef.current.parent_dbs,
2035
2105
  nodes: sceneDataRef.current.nodes,
2036
- links: sceneDataRef.current.links,
2037
- quest_counter: sceneDataRef.current.quest_counter || 1
2106
+ links: sceneDataRef.current.links
2038
2107
  };
2039
- for (const nodeId of nodesToDelete) {
2040
- const questNode = (originalData.nodes || []).find((n) => String(n.id) === String(nodeId));
2041
- if (questNode && questNode.is_quest) {
2042
- await context.actions.delete_quest(ownerId, context.sceneConfigId, nodeId);
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
+ });
2043
2128
  }
2044
2129
  }
2045
- for (const linkId of linksToDelete) {
2046
- await context.actions.delete_quest_link(ownerId, context.sceneConfigId, linkId);
2047
- }
2048
2130
  } else {
2049
2131
  filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
2050
2132
  payloadToSave = originalData;
@@ -2115,6 +2197,9 @@ var userActionHandlers = {
2115
2197
  const newLinks = (specificParentData.links || []).filter(
2116
2198
  (l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId
2117
2199
  );
2200
+ const linksToDelete = (specificParentData.links || []).filter(
2201
+ (l) => String(l.source) === strNodeId || String(l.target) === strNodeId
2202
+ );
2118
2203
  specificParentData.nodes = newNodes;
2119
2204
  specificParentData.links = newLinks;
2120
2205
  let filenameToSave;
@@ -2133,12 +2218,27 @@ var userActionHandlers = {
2133
2218
  payloadToSave = {
2134
2219
  parent_dbs: sceneDataRef.current.parent_dbs,
2135
2220
  nodes: newVisualNodes,
2136
- links: newVisualLinks,
2137
- quest_counter: sceneDataRef.current.quest_counter || 1
2221
+ links: newVisualLinks
2138
2222
  };
2139
2223
  try {
2140
2224
  await context.actions.save_view_data(filenameToSave, payloadToSave);
2141
- await context.actions.delete_quest(ownerId, context.sceneConfigId, nodeIdToDelete);
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
+ }
2142
2242
  graphDataRef.current[parentFileId] = specificParentData;
2143
2243
  setters.setDetailsNode(
2144
2244
  (prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev
@@ -2168,9 +2268,10 @@ var userActionHandlers = {
2168
2268
  }
2169
2269
  },
2170
2270
  handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
2171
- var _a, _b, _c;
2271
+ var _a, _b, _c, _d;
2172
2272
  const { graphDataRef, sceneDataRef, stateRef, setters } = context;
2173
2273
  if (!graphDataRef.current || !sceneDataRef.current) return;
2274
+ const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
2174
2275
  const {
2175
2276
  _baseEmissiveIntensity,
2176
2277
  _baseScale,
@@ -2215,7 +2316,7 @@ var userActionHandlers = {
2215
2316
  const oldNode = specificParentData.nodes[nodeIndex];
2216
2317
  const isNewDone = oldNode.status !== "Done" && nodeToSave.status === "Done";
2217
2318
  specificParentData.nodes[nodeIndex] = { ...nodeToSave };
2218
- 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)) {
2219
2320
  const nextDateObj = calculateNextRecurrenceDate(
2220
2321
  nodeToSave.recurrence_config
2221
2322
  );
@@ -2240,12 +2341,10 @@ var userActionHandlers = {
2240
2341
  }
2241
2342
  const nextQuestNode = {
2242
2343
  ...JSON.parse(JSON.stringify(nodeToSave)),
2243
- // Deep copy properties
2244
2344
  id: short.generate(),
2245
2345
  name: nextName,
2246
2346
  status: "Backlog",
2247
2347
  color: "#64748b",
2248
- // QUEST_STATUS_COLORS["Backlog"]
2249
2348
  assignee_id: nodeToSave.recurrence_config.next_assignee_id || "",
2250
2349
  Date: nextDateObj,
2251
2350
  timeline: [
@@ -2262,7 +2361,7 @@ var userActionHandlers = {
2262
2361
  ],
2263
2362
  version_node: {
2264
2363
  is_version: true,
2265
- 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
2266
2365
  },
2267
2366
  reviewStack: (nodeToSave.reviewStack || []).map((r) => ({
2268
2367
  ...r,
@@ -2270,21 +2369,56 @@ var userActionHandlers = {
2270
2369
  })),
2271
2370
  recurrence_config: nextRecurrenceConfig
2272
2371
  };
2273
- 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
+ }
2274
2404
  if (stateRef.current.nodeObjects[String(nodeToSave.id)]) {
2275
2405
  const oldMeshPosition = stateRef.current.nodeObjects[String(nodeToSave.id)].position.clone();
2276
2406
  setTimeout(() => {
2277
2407
  if (stateRef.current && stateRef.current.graphGroup) {
2278
2408
  const pos = oldMeshPosition.clone();
2279
2409
  pos.x += 12;
2280
- addStandaloneNodeToScene(stateRef.current, nextQuestNode, pos, true);
2410
+ addStandaloneNodeToScene(
2411
+ stateRef.current,
2412
+ nextQuestNode,
2413
+ pos,
2414
+ true
2415
+ );
2281
2416
  }
2282
2417
  }, 2e3);
2283
2418
  }
2284
2419
  }
2285
2420
  }
2286
2421
  try {
2287
- const isView = ((_c = context.viewType) == null ? void 0 : _c.toLowerCase()) === "view";
2288
2422
  if (isView && parentFileId === context.sceneConfigId) {
2289
2423
  const visualNodeIndex = sceneDataRef.current.nodes.findIndex(
2290
2424
  (n) => String(n.id) === String(nodeToSave.id)
@@ -2298,14 +2432,24 @@ var userActionHandlers = {
2298
2432
  const viewFilePayload = {
2299
2433
  parent_dbs: sceneDataRef.current.parent_dbs,
2300
2434
  nodes: sceneDataRef.current.nodes,
2301
- links: sceneDataRef.current.links,
2302
- quest_counter: sceneDataRef.current.quest_counter || 1
2435
+ links: sceneDataRef.current.links
2436
+ };
2437
+ const questFilePayload = {
2438
+ nodes: specificParentData.nodes,
2439
+ links: specificParentData.links,
2440
+ milestones: sceneDataRef.current.milestones || []
2303
2441
  };
2304
2442
  await context.actions.save_view_data(
2305
2443
  context.sceneSaveUrl,
2306
2444
  viewFilePayload
2307
2445
  );
2308
- await context.actions.save_quest(ownerId, context.sceneConfigId, nodeToSave);
2446
+ if (context.actions.upsert_quest_firestore) {
2447
+ await context.actions.upsert_quest_firestore(
2448
+ context.ownerId,
2449
+ context.sceneConfigId,
2450
+ nodeToSave
2451
+ );
2452
+ }
2309
2453
  } else {
2310
2454
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2311
2455
  await context.actions.save_view_data(
@@ -2316,7 +2460,6 @@ var userActionHandlers = {
2316
2460
  graphDataRef.current[parentFileId] = specificParentData;
2317
2461
  if (isView && parentFileId === context.sceneConfigId) {
2318
2462
  sceneDataRef.current.quest_nodes = [...specificParentData.nodes];
2319
- sceneDataRef.current.quest_counter = specificParentData.quest_counter || sceneDataRef.current.quest_counter;
2320
2463
  }
2321
2464
  updateExistingNodeVisuals(stateRef.current, nodeToSave);
2322
2465
  setters.setSceneVersion((v) => v + 1);
@@ -2373,8 +2516,7 @@ var userActionHandlers = {
2373
2516
  const viewFilePayload = {
2374
2517
  parent_dbs: sceneDataRef.current.parent_dbs,
2375
2518
  nodes: sceneDataRef.current.nodes,
2376
- links: sceneDataRef.current.links,
2377
- quest_counter: sceneDataRef.current.quest_counter || 1
2519
+ links: sceneDataRef.current.links
2378
2520
  };
2379
2521
  const questFilePayload = {
2380
2522
  nodes: specificParentData.nodes,
@@ -2385,8 +2527,13 @@ var userActionHandlers = {
2385
2527
  context.sceneSaveUrl,
2386
2528
  viewFilePayload
2387
2529
  );
2388
- const questSaveUrl = context.sceneSaveUrl.replace("x_view_scenes", "x_view_quests");
2389
- 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
+ }
2390
2537
  } else {
2391
2538
  const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
2392
2539
  await context.actions.save_view_data(
@@ -2481,7 +2628,7 @@ function createNewCustomProperty(existingProps = []) {
2481
2628
  nextValue = [{ id: uuidv4(), name: "1", value: "" }];
2482
2629
  break;
2483
2630
  case "date":
2484
- nextKey = "Date";
2631
+ nextKey = "Data";
2485
2632
  nextValue = { type: "Data", value: "" };
2486
2633
  break;
2487
2634
  case "number":
@@ -2735,7 +2882,7 @@ var IGNORED_KEYS = [
2735
2882
  ];
2736
2883
  function extractCustomPropsFromNode(node) {
2737
2884
  const customPropTypes = node._customPropTypes || {};
2738
- 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) => {
2739
2886
  const val = node[key];
2740
2887
  const t = customPropTypes[key] || inferPropType(val);
2741
2888
  if (t === "date") {
@@ -3251,6 +3398,17 @@ var parseDate = (str) => {
3251
3398
  }
3252
3399
  return null;
3253
3400
  };
3401
+ function extractDatePropFromNode(node) {
3402
+ if (!node) return null;
3403
+ if (node.Date) return node.Date;
3404
+ if (node._customPropTypes) {
3405
+ const dateKey = Object.keys(node._customPropTypes).find(
3406
+ (k) => node._customPropTypes[k] === "date"
3407
+ );
3408
+ if (dateKey && node[dateKey]) return node[dateKey];
3409
+ }
3410
+ return null;
3411
+ }
3254
3412
  var parseDateProp = (dateProp) => {
3255
3413
  let info = { isUndated: true, label: "", type: "point" };
3256
3414
  if (!dateProp) return info;
@@ -4924,7 +5082,7 @@ function CustomPropertyDisplay({
4924
5082
  links: "Links",
4925
5083
  images: "Images",
4926
5084
  documents: "Documents",
4927
- date: "Date"
5085
+ date: "Data"
4928
5086
  };
4929
5087
  const oldKeyIsFixed = Object.values(fixedKeyMap).includes(tempProp.key);
4930
5088
  if (fixedKeyMap[value]) {
@@ -8789,7 +8947,7 @@ function CreateAncestryPanel({
8789
8947
  }
8790
8948
 
8791
8949
  // src/components/CreateQuestTreePanel.jsx
8792
- import React11, { useState as useState12, useEffect as useEffect11, useCallback as useCallback3, useMemo as useMemo9 } from "react";
8950
+ import React11, { useState as useState12, useEffect as useEffect11, useCallback as useCallback3, useMemo as useMemo9, useRef as useRef9 } from "react";
8793
8951
  import {
8794
8952
  FiFolder as FiFolder3,
8795
8953
  FiLayers as FiLayers6,
@@ -8906,6 +9064,7 @@ function CreateQuestTreePanel({
8906
9064
  const [isSaving, setIsSaving] = useState12(false);
8907
9065
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState12(false);
8908
9066
  const [activeTab, setActiveTab] = useState12("tree");
9067
+ const isInitialLoad = useRef9(true);
8909
9068
  const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
8910
9069
  const { width: panelWidth, isResizing, handlePointerDown: handleResize } = useResizablePanel({
8911
9070
  initialWidth: 440,
@@ -8939,10 +9098,11 @@ function CreateQuestTreePanel({
8939
9098
  const indexToRemove = pathToRemove[pathToRemove.length - 1];
8940
9099
  if (currentParent.children && currentParent.children.length > indexToRemove) {
8941
9100
  currentParent.children.splice(indexToRemove, 1);
8942
- setHasUnsavedChanges(true);
9101
+ return { ...prev, [treeKey]: newTree };
8943
9102
  }
8944
- return { ...prev, [treeKey]: newTree };
9103
+ return prev;
8945
9104
  });
9105
+ setHasUnsavedChanges(true);
8946
9106
  }, [setQuestTreeMode, activeTab]);
8947
9107
  const handleMoveNode = (sourceId, targetId) => {
8948
9108
  const isAbstraction = activeTab === "abstraction";
@@ -9019,6 +9179,15 @@ function CreateQuestTreePanel({
9019
9179
  }));
9020
9180
  }
9021
9181
  }, [tree, abstraction_tree, questTreeMode.questNodeId, setQuestTreeMode]);
9182
+ useEffect11(() => {
9183
+ if (tree || abstraction_tree) {
9184
+ if (isInitialLoad.current) {
9185
+ isInitialLoad.current = false;
9186
+ return;
9187
+ }
9188
+ setHasUnsavedChanges(true);
9189
+ }
9190
+ }, [tree, abstraction_tree]);
9022
9191
  return /* @__PURE__ */ React11.createElement(
9023
9192
  "div",
9024
9193
  {
@@ -9209,11 +9378,11 @@ function ImageViewer({ data, onClose }) {
9209
9378
  }
9210
9379
 
9211
9380
  // src/components/InSceneCreationForm.jsx
9212
- import React15, { useState as useState15, useEffect as useEffect14, useRef as useRef10 } from "react";
9381
+ import React15, { useState as useState15, useEffect as useEffect14, useRef as useRef11 } from "react";
9213
9382
  import { v4 as uuidv45 } from "uuid";
9214
9383
 
9215
9384
  // src/components/ColorPicker.jsx
9216
- import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef9 } from "react";
9385
+ import React13, { useState as useState14, useEffect as useEffect13, useRef as useRef10 } from "react";
9217
9386
  import { HexColorPicker } from "react-colorful";
9218
9387
  import { FiHash, FiCheck as FiCheck6 } from "react-icons/fi";
9219
9388
  var PRESET_COLORS = [
@@ -9235,7 +9404,7 @@ var PRESET_COLORS = [
9235
9404
  ];
9236
9405
  function ColorPicker({ color, onChange, disabled, isCompact = false }) {
9237
9406
  const [isOpen, setIsOpen] = useState14(false);
9238
- const popoverRef = useRef9(null);
9407
+ const popoverRef = useRef10(null);
9239
9408
  useEffect13(() => {
9240
9409
  const handleClickOutside = (event) => {
9241
9410
  if (popoverRef.current && !popoverRef.current.contains(event.target)) {
@@ -9462,7 +9631,7 @@ function InSceneCreationForm({
9462
9631
  const [isDatasetDropdownOpen, setIsDatasetDropdownOpen] = useState15(false);
9463
9632
  const [isLoadingDocs, setIsLoadingDocs] = useState15(false);
9464
9633
  const [docError, setDocError] = useState15(null);
9465
- const datasetDropdownRef = useRef10(null);
9634
+ const datasetDropdownRef = useRef11(null);
9466
9635
  useEffect14(() => {
9467
9636
  if (sourceNodeDatasetId) setTargetDatasetId(sourceNodeDatasetId);
9468
9637
  }, [sourceNodeDatasetId]);
@@ -9479,7 +9648,7 @@ function InSceneCreationForm({
9479
9648
  document.removeEventListener("mousedown", handleClickOutside);
9480
9649
  };
9481
9650
  }, [isDatasetDropdownOpen]);
9482
- const propsEndRef = useRef10(null);
9651
+ const propsEndRef = useRef11(null);
9483
9652
  const hasImages = customProps.some(
9484
9653
  (p) => p.type === "images" && Array.isArray(p.value) && p.value.length > 0 && p.value.some((img) => img.value)
9485
9654
  );
@@ -9982,7 +10151,7 @@ function InSceneCreationForm({
9982
10151
  }
9983
10152
 
9984
10153
  // src/components/InSceneVersionForm.jsx
9985
- import React16, { useState as useState16, useEffect as useEffect15, useRef as useRef11 } from "react";
10154
+ import React16, { useState as useState16, useEffect as useEffect15, useRef as useRef12 } from "react";
9986
10155
  import { v4 as uuidv46 } from "uuid";
9987
10156
  import { FiPlus as FiPlus5, FiMaximize2 as FiMaximize22, FiCheck as FiCheck8, FiEdit2 as FiEdit25 } from "react-icons/fi";
9988
10157
  function InSceneVersionForm({
@@ -10014,7 +10183,7 @@ function InSceneVersionForm({
10014
10183
  }
10015
10184
  ]);
10016
10185
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
10017
- const propsEndRef = useRef11(null);
10186
+ const propsEndRef = useRef12(null);
10018
10187
  const [useImageAsTexture, setUseImageAsTexture] = useState16(false);
10019
10188
  const [selectedImageUrl, setSelectedImageUrl] = useState16(null);
10020
10189
  const hasImages = customProps.some(
@@ -10298,7 +10467,7 @@ function InSceneVersionForm({
10298
10467
  }
10299
10468
 
10300
10469
  // src/components/InSceneQuestForm.jsx
10301
- import React18, { useState as useState18, useRef as useRef12 } from "react";
10470
+ import React18, { useState as useState18, useRef as useRef13 } from "react";
10302
10471
  import { v4 as uuidv47 } from "uuid";
10303
10472
  import {
10304
10473
  FiPlus as FiPlus7,
@@ -10537,7 +10706,7 @@ function InSceneQuestForm({
10537
10706
  const [docError, setDocError] = useState18(null);
10538
10707
  const [customProps, setCustomProps] = useState18([]);
10539
10708
  const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState18(false);
10540
- const propsEndRef = useRef12(null);
10709
+ const propsEndRef = useRef13(null);
10541
10710
  const [milestoneInput, setMilestoneInput] = useState18("");
10542
10711
  const [showMilestoneSuggestions, setShowMilestoneSuggestions] = useState18(false);
10543
10712
  const activeMilestones = React18.useMemo(
@@ -11332,7 +11501,7 @@ function InSceneQuestForm({
11332
11501
  }
11333
11502
 
11334
11503
  // src/components/NodeDetailsPanel.jsx
11335
- import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef13 } from "react";
11504
+ import React19, { useState as useState19, useEffect as useEffect16, useRef as useRef14 } from "react";
11336
11505
  import { v4 as uuidv48 } from "uuid";
11337
11506
  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";
11338
11507
  import { AiOutlineLoading3Quarters as AiOutlineLoading3Quarters3 } from "react-icons/ai";
@@ -11392,8 +11561,8 @@ function NodeDetailsPanel({
11392
11561
  useEffect16(() => {
11393
11562
  setWidth(isReadMode ? 700 : 440);
11394
11563
  }, [isReadMode, setWidth]);
11395
- const prevNodeIdRef = useRef13(null);
11396
- const propsEndRef = useRef13(null);
11564
+ const prevNodeIdRef = useRef14(null);
11565
+ const propsEndRef = useRef14(null);
11397
11566
  const canEdit = userRole !== "viewer";
11398
11567
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
11399
11568
  const handleImageClickFromText = (url, name2) => {
@@ -11958,7 +12127,7 @@ function NodeDetailsPanel({
11958
12127
  }
11959
12128
 
11960
12129
  // src/components/QuestDetailsPanel.jsx
11961
- import React21, { useState as useState20, useEffect as useEffect17, useRef as useRef14 } from "react";
12130
+ import React21, { useState as useState20, useEffect as useEffect17, useRef as useRef15 } from "react";
11962
12131
  import { v4 as uuidv49 } from "uuid";
11963
12132
  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";
11964
12133
 
@@ -12226,8 +12395,8 @@ function QuestDetailsPanel({
12226
12395
  useEffect17(() => {
12227
12396
  setWidth(isReadMode ? 700 : 440);
12228
12397
  }, [isReadMode, setWidth]);
12229
- const prevNodeIdRef = useRef14(null);
12230
- const propsEndRef = useRef14(null);
12398
+ const prevNodeIdRef = useRef15(null);
12399
+ const propsEndRef = useRef15(null);
12231
12400
  const canEdit = userRole !== "viewer";
12232
12401
  const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
12233
12402
  const handleImageClickFromText = (url, name) => {
@@ -12369,7 +12538,6 @@ function QuestDetailsPanel({
12369
12538
  setIsSaving(false);
12370
12539
  }
12371
12540
  };
12372
- const filteredCustomProps = customProps.filter((p) => p.key !== "Date" && p.key !== "Data");
12373
12541
  const handleAddTimelineNote = async () => {
12374
12542
  if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
12375
12543
  setIsSaving(true);
@@ -13378,7 +13546,7 @@ ${noteText}` : noteText : entry.notes,
13378
13546
  }
13379
13547
 
13380
13548
  // src/components/MultiNodeContextMenu.jsx
13381
- import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef15, useState as useState21, useEffect as useEffect18 } from "react";
13549
+ import React22, { useLayoutEffect as useLayoutEffect3, useRef as useRef16, useState as useState21, useEffect as useEffect18 } from "react";
13382
13550
  function MultiNodeContextMenu({
13383
13551
  data,
13384
13552
  userRole,
@@ -13387,7 +13555,7 @@ function MultiNodeContextMenu({
13387
13555
  onDismissOtherNodes,
13388
13556
  onDeleteNodes
13389
13557
  }) {
13390
- const menuRef = useRef15(null);
13558
+ const menuRef = useRef16(null);
13391
13559
  const [menuPos, setMenuPos] = useState21({ left: 0, top: 0 });
13392
13560
  const [isConfirmingDelete, setIsConfirmingDelete] = useState21(false);
13393
13561
  const ability = defineAbilityFor(userRole);
@@ -13454,7 +13622,7 @@ function MultiNodeContextMenu({
13454
13622
  }
13455
13623
 
13456
13624
  // src/components/RelationshipDetailsPanel.jsx
13457
- import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef16, useMemo as useMemo10 } from "react";
13625
+ import React23, { useState as useState22, useEffect as useEffect19, useRef as useRef17, useMemo as useMemo10 } from "react";
13458
13626
  import { v4 as uuidv410 } from "uuid";
13459
13627
  import { FiPlus as FiPlus10, FiEdit2 as FiEdit29, FiLoader as FiLoader4, FiBookOpen as FiBookOpen5 } from "react-icons/fi";
13460
13628
  function RelationshipDetailsPanel({
@@ -13485,7 +13653,7 @@ function RelationshipDetailsPanel({
13485
13653
  const [isSaving, setIsSaving] = useState22(false);
13486
13654
  const [isReadMode, setIsReadMode] = useState22(false);
13487
13655
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState22(false);
13488
- const propsEndRef = useRef16(null);
13656
+ const propsEndRef = useRef17(null);
13489
13657
  const canEdit = useMemo10(() => {
13490
13658
  const ability = defineAbilityFor(userRole);
13491
13659
  return ability.can("update", "Connection");
@@ -13806,7 +13974,7 @@ function RelationshipDetailsPanel({
13806
13974
  }
13807
13975
 
13808
13976
  // src/components/RelationshipContextMenu.jsx
13809
- import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef17, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13977
+ import React24, { useLayoutEffect as useLayoutEffect4, useRef as useRef18, useState as useState23, useEffect as useEffect20, useMemo as useMemo11 } from "react";
13810
13978
  function RelationshipContextMenu({
13811
13979
  data,
13812
13980
  userRole,
@@ -13816,7 +13984,7 @@ function RelationshipContextMenu({
13816
13984
  onDelete,
13817
13985
  onClose
13818
13986
  }) {
13819
- const menuRef = useRef17(null);
13987
+ const menuRef = useRef18(null);
13820
13988
  const [menuPos, setMenuPos] = useState23({ left: 0, top: 0 });
13821
13989
  const [isConfirmingDelete, setIsConfirmingDelete] = useState23(false);
13822
13990
  const ability = useMemo11(() => defineAbilityFor(userRole), [userRole]);
@@ -14298,7 +14466,7 @@ import React30, {
14298
14466
  useState as useState28,
14299
14467
  useMemo as useMemo13,
14300
14468
  useEffect as useEffect24,
14301
- useRef as useRef20,
14469
+ useRef as useRef21,
14302
14470
  useCallback as useCallback6
14303
14471
  } from "react";
14304
14472
  import {
@@ -14324,10 +14492,10 @@ import {
14324
14492
  import { v4 as uuidv411 } from "uuid";
14325
14493
 
14326
14494
  // src/components/RichGroupEditor.jsx
14327
- import React29, { useEffect as useEffect23, useRef as useRef19, useState as useState27, useCallback as useCallback5 } from "react";
14495
+ import React29, { useEffect as useEffect23, useRef as useRef20, useState as useState27, useCallback as useCallback5 } from "react";
14328
14496
 
14329
14497
  // src/components/MentionPopover.jsx
14330
- import React28, { useEffect as useEffect22, useRef as useRef18, useState as useState26, useMemo as useMemo12 } from "react";
14498
+ import React28, { useEffect as useEffect22, useRef as useRef19, useState as useState26, useMemo as useMemo12 } from "react";
14331
14499
  import { FiLayers as FiLayers7, FiCheckSquare as FiCheckSquare3, FiGitBranch as FiGitBranch5, FiBox } from "react-icons/fi";
14332
14500
  var TYPE_CONFIG = {
14333
14501
  ancestry: { Icon: FiLayers7, color: "text-indigo-400", label: "Ancestralidade" },
@@ -14337,7 +14505,7 @@ var TYPE_CONFIG = {
14337
14505
  };
14338
14506
  function MentionPopover({ query, items, position, onSelect, onClose }) {
14339
14507
  const [activeIndex, setActiveIndex] = useState26(0);
14340
- const listRef = useRef18(null);
14508
+ const listRef = useRef19(null);
14341
14509
  const filtered = useMemo12(() => {
14342
14510
  const term = (query || "").toLowerCase().trim();
14343
14511
  if (!term) return items.slice(0, 8);
@@ -14477,9 +14645,9 @@ var RichGroupEditor = React29.memo(function RichGroupEditor2({
14477
14645
  readOnly,
14478
14646
  placeholder
14479
14647
  }) {
14480
- const editorRef = useRef19(null);
14481
- const isMountedRef = useRef19(false);
14482
- const dismissedTriggerRef = useRef19(null);
14648
+ const editorRef = useRef20(null);
14649
+ const isMountedRef = useRef20(false);
14650
+ const dismissedTriggerRef = useRef20(null);
14483
14651
  const [mentionState, setMentionState] = useState27(null);
14484
14652
  const [isEmpty, setIsEmpty] = useState27(true);
14485
14653
  useEffect23(() => {
@@ -14947,7 +15115,7 @@ function Boards({
14947
15115
  const [isLoaded, setIsLoaded] = useState28(false);
14948
15116
  const [saveStatus, setSaveStatus] = useState28("idle");
14949
15117
  const [navigationStack, setNavigationStack] = useState28([]);
14950
- const lastSavedBoardItemsRef = useRef20(null);
15118
+ const lastSavedBoardItemsRef = useRef21(null);
14951
15119
  const canEdit = useMemo13(() => userRole !== "viewer", [userRole]);
14952
15120
  const findGroupAndParent = (list, targetId, parent = null) => {
14953
15121
  for (let i = 0; i < list.length; i++) {
@@ -15519,12 +15687,12 @@ function XViewScene({
15519
15687
  get_view_members,
15520
15688
  create_google_doc_action,
15521
15689
  open_google_picker_action,
15522
- save_quest_action,
15523
- delete_quest_action,
15524
- save_quest_link_action,
15525
- delete_quest_link_action,
15526
- get_view_quests_and_links_action,
15527
- migrate_legacy_quests_action
15690
+ upsert_quest_firestore,
15691
+ delete_quest_firestore,
15692
+ upsert_quest_link_firestore,
15693
+ delete_quest_link_firestore,
15694
+ upsert_milestone_firestore,
15695
+ update_view_counter
15528
15696
  }) {
15529
15697
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
15530
15698
  const { data: session, status } = useSession();
@@ -15598,10 +15766,10 @@ function XViewScene({
15598
15766
  }
15599
15767
  return null;
15600
15768
  }, [ownerId, sceneConfigId]);
15601
- const sceneDataRef = useRef21(null);
15602
- const parentDataRef = useRef21(null);
15769
+ const sceneDataRef = useRef22(null);
15770
+ const parentDataRef = useRef22(null);
15603
15771
  const graphDataRef = parentDataRef;
15604
- const ancestryDataRef = useRef21(null);
15772
+ const ancestryDataRef = useRef22(null);
15605
15773
  const [isLoading, setIsLoading] = useState30(true);
15606
15774
  const [permissionStatus, setPermissionStatus] = useState30("loading");
15607
15775
  const [userPermissionRole, setUserPermissionRole] = useState30(null);
@@ -15690,10 +15858,10 @@ function XViewScene({
15690
15858
  const [boardItems, setBoardItems] = useState30([]);
15691
15859
  const [isSidebarOpen, setIsSidebarOpen] = useState30(false);
15692
15860
  const [isMilestoneManagerOpen, setIsMilestoneManagerOpen] = useState30(false);
15693
- const mountRef = useRef21(null);
15694
- const tooltipRef = useRef21(null);
15695
- const formRef = useRef21(null);
15696
- const stateRef = useRef21({
15861
+ const mountRef = useRef22(null);
15862
+ const tooltipRef = useRef22(null);
15863
+ const formRef = useRef22(null);
15864
+ const stateRef = useRef22({
15697
15865
  readMode: {
15698
15866
  currentMaxIndex: 0,
15699
15867
  progressMap: {}
@@ -16084,11 +16252,19 @@ function XViewScene({
16084
16252
  }
16085
16253
  }
16086
16254
  Object.values(nodeObjects).forEach((mesh) => {
16087
- const oldLabel = mesh.getObjectByName("timelineLabel");
16088
- if (oldLabel) {
16089
- mesh.remove(oldLabel);
16090
- if (oldLabel.material.map) oldLabel.material.map.dispose();
16091
- oldLabel.material.dispose();
16255
+ const oldTimelineLabel = mesh.getObjectByName("timelineLabel");
16256
+ if (oldTimelineLabel) {
16257
+ mesh.remove(oldTimelineLabel);
16258
+ if (oldTimelineLabel.material.map)
16259
+ oldTimelineLabel.material.map.dispose();
16260
+ oldTimelineLabel.material.dispose();
16261
+ }
16262
+ const oldQuestDateLabel = mesh.getObjectByName("questDateLabel");
16263
+ if (oldQuestDateLabel) {
16264
+ mesh.remove(oldQuestDateLabel);
16265
+ if (oldQuestDateLabel.material.map)
16266
+ oldQuestDateLabel.material.map.dispose();
16267
+ oldQuestDateLabel.material.dispose();
16092
16268
  }
16093
16269
  delete mesh.userData.timelineIntervalBar;
16094
16270
  delete mesh.userData.timelineEndLabel;
@@ -16108,42 +16284,18 @@ function XViewScene({
16108
16284
  return null;
16109
16285
  };
16110
16286
  Object.values(nodeObjects).forEach((mesh) => {
16111
- const dateProp = mesh.userData.Date;
16287
+ const dateProp = extractDatePropFromNode(mesh.userData);
16112
16288
  let nodeInfo = { mesh, type: "point", label: "", isUndated: true };
16113
16289
  if (dateProp) {
16114
- if (dateProp.date) {
16115
- const date = parseDate2(dateProp.date);
16116
- if (date) {
16117
- nodeInfo.startDate = date;
16118
- nodeInfo.endDate = date;
16119
- nodeInfo.label = dateProp.date;
16120
- nodeInfo.isUndated = false;
16121
- allTimePoints.add(date.getTime());
16122
- }
16123
- } else if (dateProp.year) {
16124
- const year = parseInt(dateProp.year, 10);
16125
- if (!isNaN(year)) {
16126
- const date = new Date(year, 0, 1);
16127
- nodeInfo.startDate = date;
16128
- nodeInfo.endDate = date;
16129
- nodeInfo.label = String(year);
16130
- nodeInfo.isUndated = false;
16131
- allTimePoints.add(date.getTime());
16132
- }
16133
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
16134
- const startYear = parseInt(dateProp.date_interval.start, 10);
16135
- const endYear = parseInt(dateProp.date_interval.end, 10) || startYear;
16136
- if (!isNaN(startYear)) {
16137
- const startDate = new Date(startYear, 0, 1);
16138
- const endDate = new Date(endYear, 11, 31);
16139
- nodeInfo.type = "interval";
16140
- nodeInfo.startDate = startDate;
16141
- nodeInfo.endDate = endDate;
16142
- nodeInfo.label = `${startYear} - ${endYear}`;
16143
- nodeInfo.isUndated = false;
16144
- allTimePoints.add(startDate.getTime());
16145
- allTimePoints.add(endDate.getTime());
16146
- }
16290
+ const info = parseDateProp(dateProp);
16291
+ if (!info.isUndated) {
16292
+ nodeInfo.startDate = info.startDate;
16293
+ nodeInfo.endDate = info.endDate;
16294
+ nodeInfo.label = info.label;
16295
+ nodeInfo.type = info.type;
16296
+ nodeInfo.isUndated = false;
16297
+ allTimePoints.add(info.startDate.getTime());
16298
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16147
16299
  }
16148
16300
  }
16149
16301
  timelineNodes.push(nodeInfo);
@@ -16271,50 +16423,29 @@ function XViewScene({
16271
16423
  return null;
16272
16424
  };
16273
16425
  versionMeshes.forEach((mesh) => {
16274
- const dateProp = mesh.userData.Date;
16426
+ const dateProp = extractDatePropFromNode(mesh.userData);
16275
16427
  if (!dateProp) return;
16276
- let nodeInfo = { mesh, type: "point", label: "" };
16277
- if (dateProp.date) {
16278
- const date = parseDate2(dateProp.date);
16279
- if (date) {
16280
- nodeInfo.startDate = date;
16281
- nodeInfo.endDate = date;
16282
- nodeInfo.label = dateProp.date;
16283
- allTimePoints.add(date.getTime());
16284
- timelineNodes.push(nodeInfo);
16285
- }
16286
- } else if (dateProp.year) {
16287
- const year = parseInt(dateProp.year, 10);
16288
- if (!isNaN(year)) {
16289
- const date = new Date(year, 0, 1);
16290
- nodeInfo.startDate = date;
16291
- nodeInfo.endDate = date;
16292
- nodeInfo.label = String(year);
16293
- allTimePoints.add(date.getTime());
16294
- timelineNodes.push(nodeInfo);
16295
- }
16296
- } else if (dateProp.date_interval && dateProp.date_interval.start) {
16297
- const startYear = parseInt(dateProp.date_interval.start, 10);
16298
- const endYear = parseInt(dateProp.date_interval.end, 10) || startYear;
16299
- if (!isNaN(startYear)) {
16300
- const startDate = new Date(startYear, 0, 1);
16301
- const endDate = new Date(endYear, 11, 31);
16302
- nodeInfo.type = "interval";
16303
- nodeInfo.startDate = startDate;
16304
- nodeInfo.endDate = endDate;
16305
- nodeInfo.label = `${startYear} - ${endYear}`;
16306
- allTimePoints.add(startDate.getTime());
16307
- allTimePoints.add(endDate.getTime());
16308
- timelineNodes.push(nodeInfo);
16309
- }
16428
+ const info = parseDateProp(dateProp);
16429
+ if (!info.isUndated) {
16430
+ const nodeInfo = {
16431
+ mesh,
16432
+ type: info.type,
16433
+ startDate: info.startDate,
16434
+ endDate: info.endDate,
16435
+ label: info.label
16436
+ };
16437
+ allTimePoints.add(info.startDate.getTime());
16438
+ if (info.endDate) allTimePoints.add(info.endDate.getTime());
16439
+ timelineNodes.push(nodeInfo);
16310
16440
  }
16311
16441
  });
16312
16442
  if (timelineNodes.length === 0) return;
16313
16443
  const sortedTimePoints = Array.from(allTimePoints).sort((a, b) => a - b);
16444
+ const maxTimeIndex = sortedTimePoints.length - 1;
16314
16445
  const timeToYMap = new Map(
16315
16446
  sortedTimePoints.map((time, index) => [
16316
16447
  time,
16317
- index * TIMELINE_LAYER_SPACING_Y
16448
+ (index - maxTimeIndex) * TIMELINE_LAYER_SPACING_Y
16318
16449
  ])
16319
16450
  );
16320
16451
  timelineNodes.sort(
@@ -16322,18 +16453,38 @@ function XViewScene({
16322
16453
  );
16323
16454
  const baseX = sourceMesh.position.x + TIMELINE_NODE_SPACING_X;
16324
16455
  const baseY = sourceMesh.position.y;
16325
- const maxNodeIndex = timelineNodes.length - 1;
16326
- timelineNodes.forEach((node, index) => {
16456
+ const columns = [];
16457
+ const allFinalPoints = [sourceMesh.position.clone()];
16458
+ timelineNodes.forEach((node) => {
16327
16459
  const { mesh, type, startDate, endDate, label } = node;
16328
- const y = baseY + (index - maxNodeIndex) * TIMELINE_LAYER_SPACING_Y;
16329
- const versionTween = new Tween2(mesh.position).to({ x: baseX, y, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
16460
+ const startY = timeToYMap.get(startDate.getTime());
16461
+ const endY = timeToYMap.get(endDate.getTime()) || startY;
16462
+ let foundColumn = false;
16463
+ for (let i = 0; i < columns.length; i++) {
16464
+ if (columns[i].endY < startY) {
16465
+ node.columnIndex = i;
16466
+ columns[i].endY = endY;
16467
+ foundColumn = true;
16468
+ break;
16469
+ }
16470
+ }
16471
+ if (!foundColumn) {
16472
+ node.columnIndex = columns.length;
16473
+ columns.push({ endY });
16474
+ }
16475
+ const x = baseX + node.columnIndex * TIMELINE_NODE_SPACING_X;
16476
+ const y = baseY + startY;
16477
+ allFinalPoints.push(new THREE3.Vector3(x, y, 0));
16478
+ const versionTween = new Tween2(mesh.position).to({ x, y, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
16330
16479
  tweenGroup.add(versionTween);
16331
16480
  versionTween.start();
16332
- const startLabelText = type === "interval" ? startDate.getFullYear().toString() : label;
16333
- const startLabel = createTextSprite(startLabelText, 48);
16334
- startLabel.name = "timelineLabel";
16335
- startLabel.position.set(0, -2.5, 0);
16336
- mesh.add(startLabel);
16481
+ if (!mesh.getObjectByName("questDateLabel")) {
16482
+ const startLabelText = type === "interval" ? startDate.getFullYear().toString() : label;
16483
+ const startLabel = createTextSprite(startLabelText, 48);
16484
+ startLabel.name = "timelineLabel";
16485
+ startLabel.position.set(0, -2.5, 0);
16486
+ mesh.add(startLabel);
16487
+ }
16337
16488
  if (type === "interval") {
16338
16489
  const relativeEndY = timeToYMap.get(endDate.getTime()) - timeToYMap.get(startDate.getTime());
16339
16490
  if (relativeEndY > 0) {
@@ -16367,7 +16518,21 @@ function XViewScene({
16367
16518
  }
16368
16519
  }
16369
16520
  });
16370
- }, []);
16521
+ if (allFinalPoints.length > 0) {
16522
+ const boundingBox = new THREE3.Box3().setFromPoints(allFinalPoints);
16523
+ const center = new THREE3.Vector3();
16524
+ boundingBox.getCenter(center);
16525
+ const size = new THREE3.Vector3();
16526
+ boundingBox.getSize(size);
16527
+ const spread = Math.max(size.x, size.y, size.z, 1);
16528
+ const desiredDistance = Math.max(
16529
+ x_view_config.CAMERA_ZOOM_DISTANCE,
16530
+ spread * 1.5
16531
+ );
16532
+ const zoomFactor = x_view_config.CAMERA_ZOOM_DISTANCE / desiredDistance;
16533
+ tweenToTarget(center, zoomFactor);
16534
+ }
16535
+ }, [tweenToTarget]);
16371
16536
  useEffect25(() => {
16372
16537
  async function fetchAllData(configPath, ownerId2) {
16373
16538
  var _a2, _b2;
@@ -16388,32 +16553,11 @@ function XViewScene({
16388
16553
  focusAncestryId
16389
16554
  );
16390
16555
  const boardPromise = get_boards_action && session ? get_boards_action(configPath, sceneType, session, ownerId2) : Promise.resolve({ success: false, data: [] });
16391
- const questPromise = get_view_quests_and_links_action && session ? get_view_quests_and_links_action(ownerId2, sceneConfigId) : Promise.resolve({ success: false, quests: [], links: [] });
16392
- const [sceneResponse, boardResponse, questResponse] = await Promise.all([
16556
+ const [sceneResponse, boardResponse] = await Promise.all([
16393
16557
  scenePromise,
16394
- boardPromise,
16395
- questPromise
16558
+ boardPromise
16396
16559
  ]);
16397
16560
  if ((sceneResponse == null ? void 0 : sceneResponse.success) && ((_a2 = sceneResponse.data) == null ? void 0 : _a2.scene) && ((_b2 = sceneResponse.data) == null ? void 0 : _b2.parent)) {
16398
- const sceneData = sceneResponse.data.scene;
16399
- let firestoreQuests = (questResponse == null ? void 0 : questResponse.success) ? questResponse.quests : [];
16400
- let firestoreLinks = (questResponse == null ? void 0 : questResponse.success) ? questResponse.links : [];
16401
- if (!sceneData.quests_migrated && firestoreQuests.length === 0) {
16402
- const legacyQuests = sceneData.quest_nodes || [];
16403
- const legacyLinks = sceneData.quest_links || [];
16404
- if ((legacyQuests.length > 0 || legacyLinks.length > 0) && migrate_legacy_quests_action) {
16405
- console.log(
16406
- "X-View: Iniciando Lazy Migration de Quests para Firestore..."
16407
- );
16408
- await migrate_legacy_quests_action(ownerId2, sceneConfigId, {
16409
- nodes: legacyQuests,
16410
- links: legacyLinks
16411
- });
16412
- firestoreQuests = legacyQuests;
16413
- firestoreLinks = legacyLinks;
16414
- sceneData.quests_migrated = true;
16415
- }
16416
- }
16417
16561
  if (focusNodeId) {
16418
16562
  let targetNode = sceneResponse.data.scene.nodes.find(
16419
16563
  (n) => String(n.id) === String(focusNodeId)
@@ -16435,29 +16579,10 @@ function XViewScene({
16435
16579
  sceneResponse.data.scene.links = [];
16436
16580
  }
16437
16581
  sceneDataRef.current = {
16438
- ...sceneData,
16439
- quests_migrated: sceneData.quests_migrated || false,
16440
- milestones: sceneData.milestones || []
16582
+ ...sceneResponse.data.scene,
16583
+ milestones: sceneResponse.data.scene.milestones || []
16441
16584
  };
16442
- const currentParentData = sceneResponse.data.parent;
16443
- if (currentParentData && currentParentData[sceneConfigId]) {
16444
- const existingNodes = currentParentData[sceneConfigId].nodes || [];
16445
- const firestoreQuestIds = new Set(firestoreQuests.map((q) => String(q.id)));
16446
- const filteredExisting = existingNodes.filter(
16447
- (n) => !firestoreQuestIds.has(String(n.id))
16448
- );
16449
- currentParentData[sceneConfigId].nodes = [
16450
- ...filteredExisting,
16451
- ...firestoreQuests
16452
- ];
16453
- if (firestoreLinks && firestoreLinks.length > 0) {
16454
- currentParentData[sceneConfigId].links = [
16455
- ...currentParentData[sceneConfigId].links || [],
16456
- ...firestoreLinks
16457
- ];
16458
- }
16459
- }
16460
- parentDataRef.current = currentParentData;
16585
+ parentDataRef.current = sceneResponse.data.parent;
16461
16586
  ancestryDataRef.current = sceneResponse.data.ancestry;
16462
16587
  console.log(
16463
16588
  "Console de sceneResponse.data.scene:",
@@ -18072,12 +18197,13 @@ function XViewScene({
18072
18197
  get_scene_view_data,
18073
18198
  upload_file: upload_file_action,
18074
18199
  delete_file: delete_file_action,
18075
- save_quest: save_quest_action,
18076
- delete_quest: delete_quest_action,
18077
- save_quest_link: save_quest_link_action,
18078
- delete_quest_link: delete_quest_link_action,
18079
- get_view_quests_and_links: get_view_quests_and_links_action,
18080
- migrate_legacy_quests: migrate_legacy_quests_action
18200
+ // Adicionado novas importações aqui
18201
+ upsert_quest_firestore,
18202
+ delete_quest_firestore,
18203
+ upsert_quest_link_firestore,
18204
+ delete_quest_link_firestore,
18205
+ upsert_milestone_firestore,
18206
+ update_view_counter
18081
18207
  }
18082
18208
  };
18083
18209
  },
@@ -18097,12 +18223,12 @@ function XViewScene({
18097
18223
  get_scene_view_data,
18098
18224
  upload_file_action,
18099
18225
  delete_file_action,
18100
- save_quest_action,
18101
- delete_quest_action,
18102
- save_quest_link_action,
18103
- delete_quest_link_action,
18104
- get_view_quests_and_links_action,
18105
- migrate_legacy_quests_action
18226
+ upsert_quest_firestore,
18227
+ delete_quest_firestore,
18228
+ upsert_quest_link_firestore,
18229
+ delete_quest_link_firestore,
18230
+ upsert_milestone_firestore,
18231
+ update_view_counter
18106
18232
  ]
18107
18233
  );
18108
18234
  const handleStartVersioning = (nodeData) => {
@@ -18308,36 +18434,30 @@ function XViewScene({
18308
18434
  parentDataRef.current[sceneConfigId].nodes[parentIndex].quest_abstraction_tree = formattedAbstractionTree;
18309
18435
  }
18310
18436
  }
18311
- const sceneFileData = {
18312
- ...sceneData,
18313
- nodes: sceneData.nodes || [],
18314
- links: sceneData.links || [],
18315
- quest_counter: sceneData.quest_counter || 1
18316
- };
18317
- const questFileData = {
18318
- nodes: sceneData.quest_nodes || [],
18319
- links: sceneData.quest_links || [],
18320
- milestones: sceneData.milestones || []
18321
- };
18322
- await save_view_data(sceneSaveUrl, sceneFileData);
18323
- await save_quest_action(ownerId, sceneConfigId, updatedNodeData);
18324
- }
18325
- const updatedNodeData = sceneData.quest_nodes[questIndex];
18326
- const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
18327
- if (nodeMesh) {
18328
- nodeMesh.userData = {
18329
- ...nodeMesh.userData,
18330
- ...updatedNodeData
18331
- };
18332
- }
18333
- if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
18334
- setDetailsNode((prev) => ({
18335
- ...prev,
18336
- quest_tree: formattedTree,
18337
- quest_abstraction_tree: formattedAbstractionTree
18338
- }));
18437
+ const updatedNodeData = sceneData.quest_nodes[questIndex];
18438
+ if (upsert_quest_firestore) {
18439
+ await upsert_quest_firestore(
18440
+ ownerId,
18441
+ sceneConfigId,
18442
+ updatedNodeData
18443
+ );
18444
+ }
18445
+ const nodeMesh = (_a2 = stateRef.current.nodeObjects) == null ? void 0 : _a2[String(questNodeId)];
18446
+ if (nodeMesh) {
18447
+ nodeMesh.userData = {
18448
+ ...nodeMesh.userData,
18449
+ ...updatedNodeData
18450
+ };
18451
+ }
18452
+ if (detailsNode && String(detailsNode.id) === String(questNodeId)) {
18453
+ setDetailsNode((prev) => ({
18454
+ ...prev,
18455
+ quest_tree: formattedTree,
18456
+ quest_abstraction_tree: formattedAbstractionTree
18457
+ }));
18458
+ }
18459
+ setSceneVersion((v) => v + 1);
18339
18460
  }
18340
- setSceneVersion((v) => v + 1);
18341
18461
  }
18342
18462
  }
18343
18463
  };
@@ -18386,7 +18506,6 @@ function XViewScene({
18386
18506
  ownerId: ownerId2
18387
18507
  } = context;
18388
18508
  if (!graphDataRef2.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
18389
- const currentCounter = sceneDataRef2.current.quest_counter || 1;
18390
18509
  const newNode = {
18391
18510
  id: short2.generate(),
18392
18511
  ...newQuestData,
@@ -18397,19 +18516,16 @@ function XViewScene({
18397
18516
  graphDataRef2.current[sceneConfigId2] = { nodes: [], links: [] };
18398
18517
  }
18399
18518
  graphDataRef2.current[sceneConfigId2].nodes.push(newNode);
18400
- const sceneFileData = {
18401
- ...sceneDataRef2.current,
18402
- quest_counter: currentCounter + 1
18403
- };
18404
- const questFileData = {
18405
- nodes: graphDataRef2.current[sceneConfigId2].nodes,
18406
- links: graphDataRef2.current[sceneConfigId2].links,
18407
- milestones: sceneDataRef2.current.milestones || []
18408
- };
18519
+ const currentCounter = sceneDataRef2.current.quest_counter || 1;
18520
+ const nextCounter = currentCounter + 1;
18409
18521
  try {
18410
- await actions.save_view_data(sceneSaveUrl2, sceneFileData);
18411
- await actions.save_quest(ownerId2, sceneConfigId2, newNode);
18412
- sceneDataRef2.current.quest_counter = currentCounter + 1;
18522
+ if (actions.upsert_quest_firestore) {
18523
+ await actions.upsert_quest_firestore(ownerId2, sceneConfigId2, newNode);
18524
+ }
18525
+ if (actions.update_view_counter) {
18526
+ await actions.update_view_counter(ownerId2, sceneConfigId2, nextCounter);
18527
+ }
18528
+ sceneDataRef2.current.quest_counter = nextCounter;
18413
18529
  stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
18414
18530
  parentFileId: sceneConfigId2,
18415
18531
  ownerId: ownerId2,
@@ -18440,84 +18556,6 @@ function XViewScene({
18440
18556
  alert("Ocorreu um erro ao criar a Quest.");
18441
18557
  }
18442
18558
  };
18443
- userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
18444
- const {
18445
- stateRef: stateRef2,
18446
- graphDataRef: graphDataRef2,
18447
- sceneDataRef: sceneDataRef2,
18448
- sceneConfigId: sceneConfigId2,
18449
- sceneSaveUrl: sceneSaveUrl2,
18450
- ownerId: ownerId2
18451
- } = context;
18452
- const { sourceNodeData } = stateRef2.current.connection;
18453
- if (!graphDataRef2.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
18454
- userActionHandlers.handleCancelConnection(context);
18455
- return;
18456
- }
18457
- const sourceParentInfo = getParentFileInfoForNode(
18458
- graphDataRef2.current,
18459
- sceneDataRef2.current,
18460
- sourceNodeData.id,
18461
- sceneConfigId2,
18462
- ownerId2
18463
- );
18464
- const targetParentInfo = getParentFileInfoForNode(
18465
- graphDataRef2.current,
18466
- sceneDataRef2.current,
18467
- targetNodeData.id,
18468
- sceneConfigId2,
18469
- ownerId2
18470
- );
18471
- let parentInfoToSave = sourceParentInfo;
18472
- const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
18473
- const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
18474
- if (isSourceQuest || isTargetQuest) {
18475
- parentInfoToSave = { parentFileId: sceneConfigId2, ownerId: ownerId2 };
18476
- }
18477
- const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
18478
- const newLink = {
18479
- id: `link_${short2.generate()}`,
18480
- source: sourceNodeData.id,
18481
- target: targetNodeData.id
18482
- };
18483
- try {
18484
- if (parentFileIdToSave === sceneConfigId2) {
18485
- const specificParentData = graphDataRef2.current[sceneConfigId2];
18486
- specificParentData.links.push(newLink);
18487
- const viewFilePayload = {
18488
- ...sceneDataRef2.current,
18489
- quest_counter: sceneDataRef2.current.quest_counter || 1
18490
- };
18491
- const questFilePayload = {
18492
- nodes: specificParentData.nodes,
18493
- links: specificParentData.links,
18494
- milestones: sceneDataRef2.current.milestones || []
18495
- };
18496
- await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
18497
- const questSaveUrl = sceneSaveUrl2.replace(
18498
- "x_view_scenes",
18499
- "x_view_quests"
18500
- );
18501
- await context.actions.save_view_data(questSaveUrl, questFilePayload);
18502
- } else {
18503
- const specificParentData = JSON.parse(
18504
- JSON.stringify(graphDataRef2.current[parentFileIdToSave])
18505
- );
18506
- specificParentData.links.push(newLink);
18507
- const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
18508
- await context.actions.save_view_data(
18509
- filenameForSpecificParent,
18510
- specificParentData
18511
- );
18512
- graphDataRef2.current[parentFileIdToSave] = specificParentData;
18513
- }
18514
- addNewLinkToScene(stateRef2.current, newLink);
18515
- } catch (error) {
18516
- console.error("Falha ao salvar a nova conex\xE3o:", error);
18517
- alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
18518
- }
18519
- userActionHandlers.handleCancelConnection(context);
18520
- };
18521
18559
  const handleClearAncestryVisuals = useCallback7((ancestryId) => {
18522
18560
  const { renderedAncestries, ancestryGroup } = stateRef.current;
18523
18561
  const renderIndex = renderedAncestries.findIndex(
@@ -20220,24 +20258,19 @@ function XViewScene({
20220
20258
  setSceneVersion((v) => v + 1);
20221
20259
  const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
20222
20260
  if (!isView || !save_view_data || !sceneSaveUrl) return;
20223
- const sceneFileData = {
20224
- ...sceneDataRef.current,
20225
- nodes: sceneDataRef.current.nodes || [],
20226
- links: sceneDataRef.current.links || [],
20227
- quest_counter: sceneDataRef.current.quest_counter || 1
20228
- };
20229
20261
  const questFileData = {
20230
20262
  nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
20231
20263
  links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
20232
20264
  milestones: newMilestones
20233
20265
  };
20234
20266
  try {
20235
- await save_view_data(sceneSaveUrl, sceneFileData);
20236
- const questSaveUrl = sceneSaveUrl.replace(
20237
- "x_view_scenes",
20238
- "x_view_quests"
20239
- );
20240
- await save_view_data(questSaveUrl, questFileData);
20267
+ if (upsert_milestone_firestore) {
20268
+ await upsert_milestone_firestore(
20269
+ ownerId,
20270
+ sceneConfigId,
20271
+ newMilestones
20272
+ );
20273
+ }
20241
20274
  } catch (error) {
20242
20275
  console.error("Erro ao salvar milestones:", error);
20243
20276
  }
@@ -20245,7 +20278,7 @@ function XViewScene({
20245
20278
  [sceneConfigId, sceneSaveUrl, save_view_data, viewParams == null ? void 0 : viewParams.type]
20246
20279
  );
20247
20280
  const handleSaveCurrentView = useCallback7(async () => {
20248
- var _a2, _b2, _c2;
20281
+ var _a2;
20249
20282
  const { nodeObjects, allLinks } = stateRef.current;
20250
20283
  if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
20251
20284
  console.warn(
@@ -20275,23 +20308,10 @@ function XViewScene({
20275
20308
  const sceneFileData = {
20276
20309
  ...sceneDataRef.current,
20277
20310
  nodes: currentNodes,
20278
- links: currentLinks,
20279
- quest_counter: sceneDataRef.current.quest_counter || 1
20280
- };
20281
- const questFileData = {
20282
- nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
20283
- links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || [],
20284
- milestones: sceneDataRef.current.milestones || []
20311
+ links: currentLinks
20285
20312
  };
20286
20313
  try {
20287
20314
  await save_view_data(sceneSaveUrl, sceneFileData);
20288
- if (isView) {
20289
- const questSaveUrl = sceneSaveUrl.replace(
20290
- "x_view_scenes",
20291
- "x_view_quests"
20292
- );
20293
- await save_view_data(questSaveUrl, questFileData);
20294
- }
20295
20315
  } catch (error) {
20296
20316
  console.error("Erro na chamada de save_view_data:", error);
20297
20317
  }
@@ -21154,25 +21174,40 @@ async function save_view_data_logic(db_services, filename, data) {
21154
21174
  }
21155
21175
  }
21156
21176
  async function get_scene_view_data_logic(db_services, scene_config, owner_id, type, session, focusNodeId = null, focusAncestryId = null) {
21157
- var _a, _b;
21177
+ var _a, _b, _c;
21158
21178
  try {
21159
21179
  if (!session || !session.user) {
21160
21180
  return { success: false, error: "Usu\xE1rio n\xE3o autenticado." };
21161
21181
  }
21162
- const membershipCheck = await db_services.check_membership(owner_id, type, scene_config, session.user.id);
21182
+ const membershipCheck = await db_services.check_membership(
21183
+ owner_id,
21184
+ type,
21185
+ scene_config,
21186
+ session.user.id
21187
+ );
21163
21188
  const isFullMember = membershipCheck.success && membershipCheck.isValidMember;
21164
21189
  if (!isFullMember && !focusNodeId && !focusAncestryId) {
21165
- return { success: false, error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio." };
21190
+ return {
21191
+ success: false,
21192
+ error: "Acesso Negado: Voc\xEA n\xE3o possui permiss\xE3o para acessar este cen\xE1rio."
21193
+ };
21166
21194
  }
21167
- const sceneResponse = await db_services.get_file(`x_view_scenes/${owner_id}/${scene_config}`);
21195
+ const sceneResponse = await db_services.get_file(
21196
+ `x_view_scenes/${owner_id}/${scene_config}`
21197
+ );
21168
21198
  if (!sceneResponse || !sceneResponse.success) {
21169
21199
  console.error("Falha ao buscar dados da cena:", sceneResponse == null ? void 0 : sceneResponse.error);
21170
- return { success: false, error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}` };
21200
+ return {
21201
+ success: false,
21202
+ error: `N\xE3o foi poss\xEDvel carregar o arquivo da cena: ${scene_config}`
21203
+ };
21171
21204
  }
21172
21205
  const sceneData = sceneResponse.data;
21173
21206
  const parentDbObjects = sceneData.parent_dbs || [];
21174
21207
  if (type && type.toLowerCase().includes("database")) {
21175
- const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
21208
+ const selfExists = parentDbObjects.some(
21209
+ (db) => String(db.db_id) === String(scene_config)
21210
+ );
21176
21211
  if (!selfExists) {
21177
21212
  parentDbObjects.push({ db_id: scene_config, owner_id });
21178
21213
  }
@@ -21181,43 +21216,70 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21181
21216
  const parentResponsesPromises = parentDbObjects.map(
21182
21217
  (db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
21183
21218
  );
21184
- const parentResponsesResults = await Promise.allSettled(parentResponsesPromises);
21185
- const parentData = {};
21186
- let currentQuestNodes = [];
21187
- let currentQuestLinks = [];
21188
- let currentMilestones = [];
21189
21219
  if (isView) {
21190
- const firestoreQuestsRes = await db_services.get_view_quests_and_links(owner_id, scene_config);
21191
- const isMigrated = sceneData.quests_migrated === true;
21192
- if (firestoreQuestsRes.success && (firestoreQuestsRes.data.nodes.length > 0 || isMigrated)) {
21193
- currentQuestNodes = firestoreQuestsRes.data.nodes;
21194
- currentQuestLinks = firestoreQuestsRes.data.links;
21195
- currentMilestones = sceneData.milestones || [];
21196
- } else {
21197
- console.log(`Iniciando Lazy Migration para View ${scene_config}...`);
21198
- const legacyQuestsRes = await db_services.get_file(`x_view_quests/${owner_id}/${scene_config}`);
21199
- if (legacyQuestsRes.success && legacyQuestsRes.data) {
21200
- const legacyData = legacyQuestsRes.data;
21201
- currentQuestNodes = legacyData.nodes || [];
21202
- currentQuestLinks = legacyData.links || [];
21203
- currentMilestones = legacyData.milestones || [];
21204
- sceneData.milestones = currentMilestones;
21205
- await db_services.migrate_legacy_quests(owner_id, scene_config, legacyData);
21220
+ const questFetchWithMigrationPromise = (async () => {
21221
+ try {
21222
+ const questsResponse = await db_services.get_view_quests_firestore(
21223
+ owner_id,
21224
+ scene_config
21225
+ );
21226
+ if (questsResponse.success && questsResponse.hasQuests) {
21227
+ return {
21228
+ success: true,
21229
+ data: questsResponse.data,
21230
+ quest_counter: questsResponse.quest_counter
21231
+ };
21232
+ } else {
21233
+ const legacyResponse = await db_services.get_file(
21234
+ `x_view_quests/${owner_id}/${scene_config}`
21235
+ );
21236
+ if (legacyResponse.success && legacyResponse.data) {
21237
+ await db_services.migrate_json_to_firestore(
21238
+ owner_id,
21239
+ scene_config,
21240
+ legacyResponse.data,
21241
+ sceneData.quest_counter
21242
+ );
21243
+ legacyResponse.quest_counter = sceneData.quest_counter || 1;
21244
+ return legacyResponse;
21245
+ }
21246
+ return legacyResponse;
21247
+ }
21248
+ } catch (err) {
21249
+ return { success: false, error: err.message };
21206
21250
  }
21207
- }
21251
+ })();
21252
+ parentResponsesPromises.push(questFetchWithMigrationPromise);
21208
21253
  }
21254
+ const parentResponsesResults = await Promise.allSettled(
21255
+ parentResponsesPromises
21256
+ );
21257
+ const parentData = {};
21258
+ let questDataObj = null;
21209
21259
  for (let i = 0; i < parentResponsesResults.length; i++) {
21210
21260
  const result = parentResponsesResults[i];
21261
+ if (isView && i === parentResponsesResults.length - 1) {
21262
+ if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21263
+ questDataObj = result.value.data;
21264
+ if (result.value.quest_counter !== void 0) {
21265
+ sceneData.quest_counter = result.value.quest_counter;
21266
+ }
21267
+ }
21268
+ continue;
21269
+ }
21211
21270
  const db_info = parentDbObjects[i];
21212
- if (result.status === "fulfilled" && ((_a = result.value) == null ? void 0 : _a.success)) {
21271
+ if (result.status === "fulfilled" && ((_b = result.value) == null ? void 0 : _b.success)) {
21213
21272
  parentData[db_info.db_id] = result.value.data;
21214
21273
  } else {
21215
21274
  console.warn(
21216
21275
  `Arquivo pai n\xE3o carregado: ${db_info.db_id}. Pode ter sido deletado.`,
21217
- result.status === "rejected" ? result.reason : (_b = result.value) == null ? void 0 : _b.error
21276
+ result.status === "rejected" ? result.reason : (_c = result.value) == null ? void 0 : _c.error
21218
21277
  );
21219
21278
  }
21220
21279
  }
21280
+ const currentQuestNodes = (questDataObj == null ? void 0 : questDataObj.nodes) || [];
21281
+ const currentQuestLinks = (questDataObj == null ? void 0 : questDataObj.links) || [];
21282
+ const currentMilestones = (questDataObj == null ? void 0 : questDataObj.milestones) || [];
21221
21283
  if (isView) {
21222
21284
  parentData[scene_config] = {
21223
21285
  dataset_name: "Quests Internas (View)",
@@ -21227,13 +21289,19 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21227
21289
  }
21228
21290
  const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
21229
21291
  const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
21230
- const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
21231
- const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
21292
+ const parentNodeMap = new Map(
21293
+ allNodes.map((node) => [String(node.id), node])
21294
+ );
21295
+ const parentLinkMap = new Map(
21296
+ allLinks.map((link) => [`${link.source}-${link.target}`, link])
21297
+ );
21232
21298
  const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
21233
21299
  var _a2, _b2;
21234
21300
  const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
21235
21301
  if (nodeTypes.includes("quest")) {
21236
- const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
21302
+ const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find(
21303
+ (qn) => String(qn.id) === String(sceneNode.id)
21304
+ );
21237
21305
  if (dbQuestNode) {
21238
21306
  return { ...sceneNode, ...dbQuestNode };
21239
21307
  }
@@ -21245,18 +21313,22 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21245
21313
  }
21246
21314
  return null;
21247
21315
  }).filter(Boolean);
21248
- const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
21316
+ const validNodeIdsInScene = new Set(
21317
+ validatedNodes.map((node) => String(node.id))
21318
+ );
21249
21319
  const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
21250
- const linkExistsInParent = parentLinkMap.has(`${sceneLink.source}-${sceneLink.target}`);
21320
+ const linkExistsInParent = parentLinkMap.has(
21321
+ `${sceneLink.source}-${sceneLink.target}`
21322
+ );
21251
21323
  const nodesAreValidForScene = validNodeIdsInScene.has(String(sceneLink.source)) && validNodeIdsInScene.has(String(sceneLink.target));
21252
21324
  return linkExistsInParent && nodesAreValidForScene;
21253
- }).map((sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`));
21325
+ }).map(
21326
+ (sceneLink) => parentLinkMap.get(`${sceneLink.source}-${sceneLink.target}`)
21327
+ );
21254
21328
  const validatedSceneData = {
21255
21329
  ...sceneData,
21256
21330
  nodes: validatedNodes,
21257
21331
  links: validatedLinks,
21258
- // Re-injetando no validated para que o restante do sistema (e.g. XViewScene local state)
21259
- // continue acessando as quests sem perceber a separação física
21260
21332
  quest_nodes: currentQuestNodes,
21261
21333
  quest_links: currentQuestLinks,
21262
21334
  milestones: currentMilestones
@@ -21276,7 +21348,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21276
21348
  isSceneFile: false
21277
21349
  });
21278
21350
  });
21279
- const ancestryPromises = ancestryFilePaths.map((file) => db_services.get_file(file.path));
21351
+ const ancestryPromises = ancestryFilePaths.map(
21352
+ (file) => db_services.get_file(file.path)
21353
+ );
21280
21354
  const ancestryResults = await Promise.allSettled(ancestryPromises);
21281
21355
  const ancestriesFromSceneFile = [];
21282
21356
  const ancestriesFromDbFiles = [];
@@ -21302,15 +21376,21 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21302
21376
  }
21303
21377
  });
21304
21378
  const ancestryMap = /* @__PURE__ */ new Map();
21305
- ancestriesFromDbFiles.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
21306
- ancestriesFromSceneFile.forEach((anc) => ancestryMap.set(anc.ancestry_id, anc));
21379
+ ancestriesFromDbFiles.forEach(
21380
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21381
+ );
21382
+ ancestriesFromSceneFile.forEach(
21383
+ (anc) => ancestryMap.set(anc.ancestry_id, anc)
21384
+ );
21307
21385
  let ancestryData = Array.from(ancestryMap.values());
21308
21386
  const externalSourcesToRefresh = /* @__PURE__ */ new Map();
21309
21387
  ancestryData.forEach((anc) => {
21310
21388
  const targetSourceId = anc._source_file_id || anc._imported_from_view_id;
21311
21389
  const targetOwnerId = anc._source_owner_id || anc._imported_from_view_owner_id;
21312
21390
  if (targetSourceId && targetSourceId !== scene_config && targetOwnerId) {
21313
- const isAlreadyLoadedAsParent = parentDbObjects.some((db) => String(db.db_id) === String(targetSourceId));
21391
+ const isAlreadyLoadedAsParent = parentDbObjects.some(
21392
+ (db) => String(db.db_id) === String(targetSourceId)
21393
+ );
21314
21394
  if (!isAlreadyLoadedAsParent) {
21315
21395
  const key = `${targetOwnerId}/${targetSourceId}`;
21316
21396
  externalSourcesToRefresh.set(key, {
@@ -21351,12 +21431,16 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21351
21431
  return false;
21352
21432
  }
21353
21433
  if (externalSourcesToRefresh.has(key) && successfullyFetchedSources.has(key)) {
21354
- const stillExists = freshAncestryMap.has(String(localAnc.ancestry_id));
21434
+ const stillExists = freshAncestryMap.has(
21435
+ String(localAnc.ancestry_id)
21436
+ );
21355
21437
  return stillExists;
21356
21438
  }
21357
21439
  return true;
21358
21440
  }).map((localAnc) => {
21359
- const freshVersion = freshAncestryMap.get(String(localAnc.ancestry_id));
21441
+ const freshVersion = freshAncestryMap.get(
21442
+ String(localAnc.ancestry_id)
21443
+ );
21360
21444
  if (freshVersion) {
21361
21445
  return {
21362
21446
  ...freshVersion,
@@ -21395,7 +21479,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21395
21479
  parallel_branches: validBranches
21396
21480
  };
21397
21481
  };
21398
- const originalAncestryDataString = JSON.stringify(Array.from(ancestryMap.values()));
21482
+ const originalAncestryDataString = JSON.stringify(
21483
+ Array.from(ancestryMap.values())
21484
+ );
21399
21485
  const cleanedAncestryData = ancestryData.map((ancestry) => {
21400
21486
  if (!parentNodeIds.has(String(ancestry.ancestral_node))) return null;
21401
21487
  const cleanedTree = pruneTree(ancestry.tree);
@@ -21415,7 +21501,10 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21415
21501
  try {
21416
21502
  await db_services.save_file(ancestryFilePath, ancestryData);
21417
21503
  } catch (saveError) {
21418
- console.error("Falha ao salvar o arquivo de ancestralidade da cena atualizado:", saveError);
21504
+ console.error(
21505
+ "Falha ao salvar o arquivo de ancestralidade da cena atualizado:",
21506
+ saveError
21507
+ );
21419
21508
  }
21420
21509
  }
21421
21510
  if (!isFullMember) {
@@ -21423,7 +21512,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21423
21512
  const requiredAncestryIds = /* @__PURE__ */ new Set();
21424
21513
  if (focusNodeId) requiredNodeIds.add(String(focusNodeId));
21425
21514
  if (focusAncestryId) requiredAncestryIds.add(String(focusAncestryId));
21426
- const allNodesFromDb = Object.values(parentData).flatMap((db) => db.nodes || []);
21515
+ const allNodesFromDb = Object.values(parentData).flatMap(
21516
+ (db) => db.nodes || []
21517
+ );
21427
21518
  const extractDependenciesFromText = (text) => {
21428
21519
  if (!text) return;
21429
21520
  const mentionRegex = /\[\[MENTION:node:([a-zA-Z0-9\-_]+)\]\]/g;
@@ -21450,9 +21541,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21450
21541
  if (branch.linked_ancestry_id) {
21451
21542
  requiredAncestryIds.add(String(branch.linked_ancestry_id));
21452
21543
  }
21453
- if (branch.description) extractDependenciesFromText(branch.description);
21544
+ if (branch.description)
21545
+ extractDependenciesFromText(branch.description);
21454
21546
  if (branch.description_sections) {
21455
- branch.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21547
+ branch.description_sections.forEach(
21548
+ (s) => extractDependenciesFromText(s.content)
21549
+ );
21456
21550
  }
21457
21551
  extractTreeDependencies(branch.tree);
21458
21552
  });
@@ -21466,7 +21560,9 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21466
21560
  if (anc && !anc.is_private) {
21467
21561
  if (anc.description) extractDependenciesFromText(anc.description);
21468
21562
  if (anc.description_sections) {
21469
- anc.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21563
+ anc.description_sections.forEach(
21564
+ (s) => extractDependenciesFromText(s.content)
21565
+ );
21470
21566
  }
21471
21567
  extractTreeDependencies(anc.tree);
21472
21568
  extractTreeDependencies(anc.abstraction_tree);
@@ -21477,22 +21573,38 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21477
21573
  if (node) {
21478
21574
  if (node.description) extractDependenciesFromText(node.description);
21479
21575
  if (node.description_sections) {
21480
- node.description_sections.forEach((s) => extractDependenciesFromText(s.content));
21576
+ node.description_sections.forEach(
21577
+ (s) => extractDependenciesFromText(s.content)
21578
+ );
21481
21579
  }
21482
21580
  }
21483
21581
  });
21484
21582
  } while (requiredNodeIds.size + requiredAncestryIds.size > previousSize);
21485
- const restrictedSceneData = { ...validatedSceneData, nodes: [], links: [] };
21583
+ const restrictedSceneData = {
21584
+ ...validatedSceneData,
21585
+ nodes: [],
21586
+ links: []
21587
+ };
21486
21588
  const restrictedParentData = {};
21487
- const restrictedAncestryData = ancestryData.filter((a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private);
21589
+ const restrictedAncestryData = ancestryData.filter(
21590
+ (a) => requiredAncestryIds.has(String(a.ancestry_id)) && !a.is_private
21591
+ );
21488
21592
  for (const [dbId, dbContent] of Object.entries(parentData)) {
21489
- const filteredNodes = (dbContent.nodes || []).filter((n) => requiredNodeIds.has(String(n.id)));
21593
+ const filteredNodes = (dbContent.nodes || []).filter(
21594
+ (n) => requiredNodeIds.has(String(n.id))
21595
+ );
21490
21596
  if (filteredNodes.length > 0) {
21491
- restrictedParentData[dbId] = { ...dbContent, nodes: filteredNodes, links: [] };
21597
+ restrictedParentData[dbId] = {
21598
+ ...dbContent,
21599
+ nodes: filteredNodes,
21600
+ links: []
21601
+ };
21492
21602
  }
21493
21603
  }
21494
21604
  if (focusNodeId) {
21495
- const mainNode = allNodesFromDb.find((n) => String(n.id) === String(focusNodeId));
21605
+ const mainNode = allNodesFromDb.find(
21606
+ (n) => String(n.id) === String(focusNodeId)
21607
+ );
21496
21608
  if (mainNode) {
21497
21609
  restrictedSceneData.nodes = [mainNode];
21498
21610
  }
@@ -21508,7 +21620,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
21508
21620
  }
21509
21621
  return {
21510
21622
  success: true,
21511
- data: { scene: validatedSceneData, parent: parentData, ancestry: ancestryData }
21623
+ data: {
21624
+ scene: validatedSceneData,
21625
+ parent: parentData,
21626
+ ancestry: ancestryData
21627
+ }
21512
21628
  };
21513
21629
  } catch (error) {
21514
21630
  console.error("Erro em get_scene_view_data_logic:", error);
@@ -21528,13 +21644,18 @@ async function import_parent_file_modal_get_logic(db_services, session) {
21528
21644
  }
21529
21645
  };
21530
21646
  } catch (error) {
21531
- console.error("catch (error) em import_parent_file_modal_get_logic:", error);
21647
+ console.error(
21648
+ "catch (error) em import_parent_file_modal_get_logic:",
21649
+ error
21650
+ );
21532
21651
  return { success: false, error: error.message };
21533
21652
  }
21534
21653
  }
21535
21654
  async function get_single_parent_file_logic(db_services, file_id, session) {
21536
21655
  try {
21537
- const call_GCP_cloud_storage_get_file = await db_services.get_file(`x_view_dbs/${session.user.id}/${file_id}`);
21656
+ const call_GCP_cloud_storage_get_file = await db_services.get_file(
21657
+ `x_view_dbs/${session.user.id}/${file_id}`
21658
+ );
21538
21659
  return call_GCP_cloud_storage_get_file;
21539
21660
  } catch (error) {
21540
21661
  console.error("catch (error) em get_single_parent_file_logic:", error);
@@ -21568,7 +21689,13 @@ async function get_ancestry_file_logic(db_services, file_id, owner_id) {
21568
21689
  async function save_boards_logic(db_services, scene_id, type, boardItems, session, owner_id) {
21569
21690
  try {
21570
21691
  const targetOwnerId = owner_id || session.user.id;
21571
- return await db_services.save_boards(session, scene_id, type, boardItems, targetOwnerId);
21692
+ return await db_services.save_boards(
21693
+ session,
21694
+ scene_id,
21695
+ type,
21696
+ boardItems,
21697
+ targetOwnerId
21698
+ );
21572
21699
  } catch (error) {
21573
21700
  console.error("Erro em save_boards_logic:", error);
21574
21701
  return { success: false, error: error.message };
@@ -21597,7 +21724,10 @@ async function delete_uploaded_file_logic(db_services, fileUrl) {
21597
21724
  async function get_view_members_logic(db_services, ownerId, type, itemId) {
21598
21725
  try {
21599
21726
  if (!db_services.get_view_members) {
21600
- return { success: false, error: "Servi\xE7o de busca de membros n\xE3o configurado." };
21727
+ return {
21728
+ success: false,
21729
+ error: "Servi\xE7o de busca de membros n\xE3o configurado."
21730
+ };
21601
21731
  }
21602
21732
  return await db_services.get_view_members(ownerId, type, itemId);
21603
21733
  } catch (error) {