@lv-x-software-house/x_view 1.2.4-dev.2 → 1.2.4-dev.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +484 -178
- package/dist/index.mjs +491 -185
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -250,11 +250,12 @@ function ContextMenu({
|
|
|
250
250
|
});
|
|
251
251
|
};
|
|
252
252
|
const renderMainView = () => {
|
|
253
|
+
var _a2;
|
|
253
254
|
const hasVersions = computedVersions.length > 0;
|
|
254
255
|
const canCreateVersion = ability.can("create", "Versioning");
|
|
255
256
|
const canReadVersion = ability.can("read", "Versioning");
|
|
256
257
|
const shouldShowVersioningBtn = canCreateVersion || canReadVersion && hasVersions;
|
|
257
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
258
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 px-2 pt-1 pb-2" }, /* @__PURE__ */ React.createElement("span", { className: "inline-flex h-2 w-2 rounded-full bg-indigo-400/80 shadow-[0_0_12px_1px_rgba(99,102,241,0.5)]" }), /* @__PURE__ */ React.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "A\xE7\xF5es R\xE1pidas")), /* @__PURE__ */ React.createElement("div", { className: "flex flex-col gap-1" }, ability.can("create", "Connection") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartConnection == null ? void 0 : onStartConnection(data.nodeData), className: baseButtonClass, title: "Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", null, "Conectar")), ability.can("create", "Node") && !((_a2 = data.nodeData) == null ? void 0 : _a2.is_quest) && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartCreation == null ? void 0 : onStartCreation(data.nodeData), className: baseButtonClass, title: "Criar e Conectar" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "16" }), /* @__PURE__ */ React.createElement("line", { x1: "8", y1: "12", x2: "16", y2: "12" })), /* @__PURE__ */ React.createElement("span", null, "Criar e Conectar")), ability.can("create", "Ancestry") && /* @__PURE__ */ React.createElement("button", { onClick: () => onStartAncestryCreation == null ? void 0 : onStartAncestryCreation(data.nodeData), className: baseButtonClass, title: "Criar Ancestralidade" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 20.5c.5-.5.8-1.2.8-2s-.3-1.5-.8-2c-.5-.5-1.2-.8-2-.8s-1.5.3-2 .8c-.5.5-.8 1.2-.8 2s.3 1.5.8 2c.5.5 1.2-.8 2 .8s1.5-.3 2-.8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M10 16v-3a2 2 0 0 1 2-2h4" }), /* @__PURE__ */ React.createElement("path", { d: "M14 3.5c.5.5.8 1.2.8 2s-.3 1.5-.8 2c-.5-.5-1.2-.8-2 .8s1.5.3-2-.8c-.5-.5-.8-1.2-.8-2s.3-1.5.8-2c.5.5 1.2-.8 2 .8s1.5.3 2 .8Z" }), /* @__PURE__ */ React.createElement("path", { d: "M14 8v3a2 2 0 0 0 2 2h4" })), /* @__PURE__ */ React.createElement("span", null, "Criar Ancestralidade")), shouldShowVersioningBtn && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("versioning"), className: baseButtonClass, title: hasVersions ? "Versionamento" : "Criar Versionamento" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("line", { x1: "6", y1: "3", x2: "6", y2: "15" }), /* @__PURE__ */ React.createElement("circle", { cx: "18", cy: "6", r: "3" }), /* @__PURE__ */ React.createElement("circle", { cx: "6", cy: "18", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M18 9a9 9 0 0 1-9 9" })), /* @__PURE__ */ React.createElement("span", null, hasVersions || !canCreateVersion ? "Versionamento" : "Criar Versionamento")), (connections.length > 0 || availableAncestries.length > 0) && ability.can("read", "Connection") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("connections"), className: baseButtonClass, title: "Conex\xF5es" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2z" }), /* @__PURE__ */ React.createElement("path", { d: "M8 12h8" }), /* @__PURE__ */ React.createElement("path", { d: "M12 8v8" })), /* @__PURE__ */ React.createElement("span", null, "Conex\xF5es (", totalConnectionsCount, ")"))), /* @__PURE__ */ React.createElement("div", { className: "my-1 h-px w-full bg-white/10" }), /* @__PURE__ */ React.createElement("button", { onClick: () => {
|
|
258
259
|
onFocusNode == null ? void 0 : onFocusNode(data.nodeData);
|
|
259
260
|
onClose();
|
|
260
261
|
}, className: baseButtonClass, title: "Focar na c\xE2mera" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" })), /* @__PURE__ */ React.createElement("span", null, "Focar neste Node")), /* @__PURE__ */ React.createElement("button", { onClick: (e) => handleCopyLink(e, data.nodeData), className: baseButtonClass, title: "Copiar Link para Compartilhar" }, isLinkCopied ? /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#4ade80", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "20 6 9 17 4 12" })) : /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.72" }), /* @__PURE__ */ React.createElement("path", { d: "M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.72-1.72" })), /* @__PURE__ */ React.createElement("span", { className: isLinkCopied ? "text-green-400" : "" }, isLinkCopied ? "Copiado!" : "Copiar Link")), ability.can("dismiss", "Node") && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissNode == null ? void 0 : onDismissNode(data.nodeData), className: baseButtonClass, title: "Remover da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("path", { d: "M9.88 9.88a3 3 0 1 0 4.24 4.24" }), /* @__PURE__ */ React.createElement("path", { d: "M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68" }), /* @__PURE__ */ React.createElement("path", { d: "M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61" }), /* @__PURE__ */ React.createElement("line", { x1: "2", y1: "2", x2: "22", y2: "22" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss")), /* @__PURE__ */ React.createElement("button", { onClick: () => onDismissOtherNodes == null ? void 0 : onDismissOtherNodes(data.nodeData), className: baseButtonClass, title: "Remover outros da visualiza\xE7\xE3o" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("circle", { cx: "12", cy: "12", r: "3" }), /* @__PURE__ */ React.createElement("path", { d: "M3 7V5a2 2 0 0 1 2-2h2" }), /* @__PURE__ */ React.createElement("path", { d: "M17 3h2a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("path", { d: "M21 17v2a2 2 0 0 1-2 2h-2" }), /* @__PURE__ */ React.createElement("path", { d: "M7 21H5a2 2 0 0 1-2-2v-2" })), /* @__PURE__ */ React.createElement("span", null, "Dismiss other nodes"))), ability.can("delete", "Node") && /* @__PURE__ */ React.createElement("button", { onClick: () => setMenuView("deleteConfirmation"), className: deleteButtonClass, title: "Excluir Node" }, /* @__PURE__ */ React.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React.createElement("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }), /* @__PURE__ */ React.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" })), /* @__PURE__ */ React.createElement("span", null, "Excluir Node"))));
|
|
@@ -1181,8 +1182,6 @@ var createMultipleLinkLines = (linksArray, sourceNodeMesh, targetNodeMesh, resol
|
|
|
1181
1182
|
targetNodeMesh,
|
|
1182
1183
|
resolution,
|
|
1183
1184
|
isCurved,
|
|
1184
|
-
isCurved,
|
|
1185
|
-
isCurved,
|
|
1186
1185
|
curveOffset
|
|
1187
1186
|
);
|
|
1188
1187
|
line.userData = {
|
|
@@ -1515,7 +1514,7 @@ var addStandaloneNodeToScene = (state, nodeData, position) => {
|
|
|
1515
1514
|
scaleTween.start();
|
|
1516
1515
|
}
|
|
1517
1516
|
};
|
|
1518
|
-
var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
|
|
1517
|
+
var getParentFileInfoForNode = (allParentData, sceneData, nodeId, sceneConfigId = null, sceneOwnerId = null) => {
|
|
1519
1518
|
const parentDbsArray = (sceneData == null ? void 0 : sceneData.parent_dbs) || [];
|
|
1520
1519
|
for (const parentFileId in allParentData) {
|
|
1521
1520
|
if (allParentData.hasOwnProperty(parentFileId)) {
|
|
@@ -1524,6 +1523,8 @@ var getParentFileInfoForNode = (allParentData, sceneData, nodeId) => {
|
|
|
1524
1523
|
const parentDbInfo = parentDbsArray.find((db) => String(db.db_id) === String(parentFileId));
|
|
1525
1524
|
if (parentDbInfo) {
|
|
1526
1525
|
return { parentFileId, ownerId: parentDbInfo.owner_id };
|
|
1526
|
+
} else if (sceneConfigId && String(parentFileId) === String(sceneConfigId)) {
|
|
1527
|
+
return { parentFileId, ownerId: sceneOwnerId };
|
|
1527
1528
|
} else {
|
|
1528
1529
|
console.warn(`Owner ID n\xE3o encontrado em sceneData.parent_dbs para o parentFileId: ${parentFileId}`);
|
|
1529
1530
|
return { parentFileId, ownerId: null };
|
|
@@ -1793,6 +1794,7 @@ var userActionHandlers = {
|
|
|
1793
1794
|
setters.setFormPosition((p) => ({ ...p, opacity: 0 }));
|
|
1794
1795
|
},
|
|
1795
1796
|
handleSaveVersionNode: async (context, newNodeData) => {
|
|
1797
|
+
var _a;
|
|
1796
1798
|
const { graphDataRef, sceneDataRef, stateRef, versionMode, setters } = context;
|
|
1797
1799
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
1798
1800
|
const { sourceNodeData } = versionMode;
|
|
@@ -1802,7 +1804,7 @@ var userActionHandlers = {
|
|
|
1802
1804
|
version_node: { is_version: true, parent_node: sourceNodeData.id }
|
|
1803
1805
|
};
|
|
1804
1806
|
const newLink = { id: `link_${short.generate()}`, source: sourceNodeData.id, target: newNode.id };
|
|
1805
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
|
|
1807
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
|
|
1806
1808
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
1807
1809
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
|
|
1808
1810
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
|
|
@@ -1812,9 +1814,21 @@ var userActionHandlers = {
|
|
|
1812
1814
|
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
|
|
1813
1815
|
specificParentData.nodes.push(newNode);
|
|
1814
1816
|
specificParentData.links.push(newLink);
|
|
1815
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
1816
1817
|
try {
|
|
1817
|
-
|
|
1818
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
1819
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
1820
|
+
const viewFilePayload = {
|
|
1821
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
1822
|
+
nodes: sceneDataRef.current.nodes,
|
|
1823
|
+
links: sceneDataRef.current.links,
|
|
1824
|
+
quest_nodes: specificParentData.nodes,
|
|
1825
|
+
quest_links: specificParentData.links
|
|
1826
|
+
};
|
|
1827
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
1828
|
+
} else {
|
|
1829
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
1830
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
1831
|
+
}
|
|
1818
1832
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
1819
1833
|
const finalPosition = stateRef.current.ghostElements.node.position.clone();
|
|
1820
1834
|
addNewNodeToScene(stateRef.current, newNode, newLink, finalPosition);
|
|
@@ -1838,10 +1852,6 @@ var userActionHandlers = {
|
|
|
1838
1852
|
var _a;
|
|
1839
1853
|
const isSource = String(link.source) === String(sourceNode.id);
|
|
1840
1854
|
const targetNodeId = isSource ? link.target : link.source;
|
|
1841
|
-
const linkAlreadyInSceneData = sceneDataRef.current.links.some((l) => String(l.id) === String(link.id));
|
|
1842
|
-
if (!linkAlreadyInSceneData) {
|
|
1843
|
-
sceneDataRef.current.links.push(link);
|
|
1844
|
-
}
|
|
1845
1855
|
if (!nodeObjects[String(targetNodeId)]) {
|
|
1846
1856
|
const allParentNodes = Object.values(graphDataRef.current).flatMap((fileData) => fileData.nodes);
|
|
1847
1857
|
const nodeData = allParentNodes.find((n) => String(n.id) === String(targetNodeId));
|
|
@@ -1849,9 +1859,6 @@ var userActionHandlers = {
|
|
|
1849
1859
|
console.warn(`Dados do Node com ID ${targetNodeId} n\xE3o encontrados no cache.`);
|
|
1850
1860
|
return;
|
|
1851
1861
|
}
|
|
1852
|
-
if (!sceneDataRef.current.nodes.some((n) => String(n.id) === String(nodeData.id))) {
|
|
1853
|
-
sceneDataRef.current.nodes.push(nodeData);
|
|
1854
|
-
}
|
|
1855
1862
|
const startPosition = sourceNodeMesh.position.clone();
|
|
1856
1863
|
const endPosition = startPosition.clone().add(
|
|
1857
1864
|
new THREE.Vector3((Math.random() - 0.5) * 60, (Math.random() - 0.5) * 15, (Math.random() - 0.5) * 60)
|
|
@@ -1971,6 +1978,7 @@ var userActionHandlers = {
|
|
|
1971
1978
|
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
1972
1979
|
},
|
|
1973
1980
|
handleCompleteConnection: async (context, targetNodeData) => {
|
|
1981
|
+
var _a;
|
|
1974
1982
|
const { stateRef, graphDataRef, sceneDataRef } = context;
|
|
1975
1983
|
const { sourceNodeData } = stateRef.current.connection;
|
|
1976
1984
|
if (!graphDataRef.current || !sceneDataRef.current || !sourceNodeData || !targetNodeData) {
|
|
@@ -1978,7 +1986,7 @@ var userActionHandlers = {
|
|
|
1978
1986
|
userActionHandlers.handleCancelConnection(context);
|
|
1979
1987
|
return;
|
|
1980
1988
|
}
|
|
1981
|
-
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id);
|
|
1989
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, sourceNodeData.id, context.sceneConfigId, context.ownerId);
|
|
1982
1990
|
if (!sourceParentInfo || !sourceParentInfo.ownerId) {
|
|
1983
1991
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node de origem:", sourceNodeData.id);
|
|
1984
1992
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio.");
|
|
@@ -1993,12 +2001,26 @@ var userActionHandlers = {
|
|
|
1993
2001
|
source: sourceNodeData.id,
|
|
1994
2002
|
target: targetNodeData.id
|
|
1995
2003
|
};
|
|
1996
|
-
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
1997
|
-
specificParentData.links.push(newLink);
|
|
1998
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
1999
2004
|
try {
|
|
2000
|
-
|
|
2001
|
-
|
|
2005
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2006
|
+
if (isView && parentFileIdToSave === context.sceneConfigId) {
|
|
2007
|
+
const specificParentData = graphDataRef.current[context.sceneConfigId];
|
|
2008
|
+
specificParentData.links.push(newLink);
|
|
2009
|
+
const viewFilePayload = {
|
|
2010
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2011
|
+
nodes: sceneDataRef.current.nodes,
|
|
2012
|
+
links: sceneDataRef.current.links,
|
|
2013
|
+
quest_nodes: specificParentData.nodes,
|
|
2014
|
+
quest_links: specificParentData.links
|
|
2015
|
+
};
|
|
2016
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2017
|
+
} else {
|
|
2018
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
2019
|
+
specificParentData.links.push(newLink);
|
|
2020
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
2021
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2022
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
2023
|
+
}
|
|
2002
2024
|
addNewLinkToScene(stateRef.current, newLink);
|
|
2003
2025
|
} catch (error) {
|
|
2004
2026
|
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
@@ -2067,14 +2089,28 @@ var userActionHandlers = {
|
|
|
2067
2089
|
} else {
|
|
2068
2090
|
newTargetId = newEndNodeData.id;
|
|
2069
2091
|
}
|
|
2070
|
-
const
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2092
|
+
const oldSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldSourceId, context.sceneConfigId, context.ownerId);
|
|
2093
|
+
const oldTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, oldTargetId, context.sceneConfigId, context.ownerId);
|
|
2094
|
+
const newSourceInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newSourceId, context.sceneConfigId, context.ownerId);
|
|
2095
|
+
const newTargetInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, newTargetId, context.sceneConfigId, context.ownerId);
|
|
2096
|
+
if (!oldSourceInfo || !oldTargetInfo || !newSourceInfo || !newTargetInfo) {
|
|
2097
|
+
console.error("Informa\xE7\xF5es dos arquivos pai incompletas para o relink.");
|
|
2074
2098
|
alert("Ocorreu um erro ao identificar os arquivos pai para salvar a altera\xE7\xE3o.");
|
|
2075
2099
|
userActionHandlers.handleCancelRelink(context);
|
|
2076
2100
|
return;
|
|
2077
2101
|
}
|
|
2102
|
+
let oldGoverningFileId = oldSourceInfo.parentFileId;
|
|
2103
|
+
let oldGoverningOwnerId = oldSourceInfo.ownerId;
|
|
2104
|
+
if (oldSourceInfo.parentFileId === context.sceneConfigId || oldTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2105
|
+
oldGoverningFileId = context.sceneConfigId;
|
|
2106
|
+
oldGoverningOwnerId = context.ownerId;
|
|
2107
|
+
}
|
|
2108
|
+
let newGoverningFileId = newSourceInfo.parentFileId;
|
|
2109
|
+
let newGoverningOwnerId = newSourceInfo.ownerId;
|
|
2110
|
+
if (newSourceInfo.parentFileId === context.sceneConfigId || newTargetInfo.parentFileId === context.sceneConfigId) {
|
|
2111
|
+
newGoverningFileId = context.sceneConfigId;
|
|
2112
|
+
newGoverningOwnerId = context.ownerId;
|
|
2113
|
+
}
|
|
2078
2114
|
const { sourceNode, targetNode, ...dataToKeep } = originalLinkData;
|
|
2079
2115
|
const newLinkData = {
|
|
2080
2116
|
...dataToKeep,
|
|
@@ -2082,34 +2118,44 @@ var userActionHandlers = {
|
|
|
2082
2118
|
target: newTargetId,
|
|
2083
2119
|
id: linkId
|
|
2084
2120
|
};
|
|
2121
|
+
const saveParentData = async (fileId, fileOwnerId, data) => {
|
|
2122
|
+
var _a;
|
|
2123
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2124
|
+
if (isView && fileId === context.sceneConfigId) {
|
|
2125
|
+
const viewFilePayload = {
|
|
2126
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2127
|
+
nodes: sceneDataRef.current.nodes,
|
|
2128
|
+
links: sceneDataRef.current.links,
|
|
2129
|
+
quest_nodes: data.nodes,
|
|
2130
|
+
quest_links: data.links
|
|
2131
|
+
};
|
|
2132
|
+
return context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2133
|
+
} else {
|
|
2134
|
+
return context.actions.save_view_data(`x_view_dbs/${fileOwnerId}/${fileId}`, data);
|
|
2135
|
+
}
|
|
2136
|
+
};
|
|
2085
2137
|
const savePromises = [];
|
|
2086
2138
|
const filesToUpdate = {};
|
|
2087
|
-
if (
|
|
2088
|
-
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2139
|
+
if (oldGoverningFileId !== newGoverningFileId) {
|
|
2140
|
+
const updatedOriginalParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2089
2141
|
updatedOriginalParentData.links = updatedOriginalParentData.links.filter(
|
|
2090
2142
|
(l) => String(l.id) !== String(linkId)
|
|
2091
2143
|
);
|
|
2092
|
-
filesToUpdate[
|
|
2093
|
-
savePromises.push(
|
|
2094
|
-
|
|
2095
|
-
);
|
|
2096
|
-
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newParentInfo.parentFileId]));
|
|
2144
|
+
filesToUpdate[oldGoverningFileId] = updatedOriginalParentData;
|
|
2145
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedOriginalParentData));
|
|
2146
|
+
const updatedNewParentData = JSON.parse(JSON.stringify(graphDataRef.current[newGoverningFileId]));
|
|
2097
2147
|
if (!updatedNewParentData.links) updatedNewParentData.links = [];
|
|
2098
2148
|
updatedNewParentData.links.push(newLinkData);
|
|
2099
|
-
filesToUpdate[
|
|
2100
|
-
savePromises.push(
|
|
2101
|
-
context.actions.save_view_data(`x_view_dbs/${newParentInfo.ownerId}/${newParentInfo.parentFileId}`, updatedNewParentData)
|
|
2102
|
-
);
|
|
2149
|
+
filesToUpdate[newGoverningFileId] = updatedNewParentData;
|
|
2150
|
+
savePromises.push(saveParentData(newGoverningFileId, newGoverningOwnerId, updatedNewParentData));
|
|
2103
2151
|
} else {
|
|
2104
|
-
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[
|
|
2152
|
+
const updatedParentData = JSON.parse(JSON.stringify(graphDataRef.current[oldGoverningFileId]));
|
|
2105
2153
|
updatedParentData.links = updatedParentData.links.filter(
|
|
2106
2154
|
(l) => String(l.id) !== String(linkId)
|
|
2107
2155
|
);
|
|
2108
2156
|
updatedParentData.links.push(newLinkData);
|
|
2109
|
-
filesToUpdate[
|
|
2110
|
-
savePromises.push(
|
|
2111
|
-
context.actions.save_view_data(`x_view_dbs/${originalParentInfo.ownerId}/${originalParentInfo.parentFileId}`, updatedParentData)
|
|
2112
|
-
);
|
|
2157
|
+
filesToUpdate[oldGoverningFileId] = updatedParentData;
|
|
2158
|
+
savePromises.push(saveParentData(oldGoverningFileId, oldGoverningOwnerId, updatedParentData));
|
|
2113
2159
|
}
|
|
2114
2160
|
try {
|
|
2115
2161
|
await Promise.all(savePromises);
|
|
@@ -2127,7 +2173,7 @@ var userActionHandlers = {
|
|
|
2127
2173
|
}
|
|
2128
2174
|
},
|
|
2129
2175
|
handleDeleteLink: async (context, linkObject) => {
|
|
2130
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2176
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2131
2177
|
const { stateRef, graphDataRef, sceneDataRef, setters } = context;
|
|
2132
2178
|
setters.setRelationshipMenu({ visible: false });
|
|
2133
2179
|
if (!(linkObject == null ? void 0 : linkObject.userData) || !graphDataRef.current || !sceneDataRef.current) return;
|
|
@@ -2136,7 +2182,7 @@ var userActionHandlers = {
|
|
|
2136
2182
|
console.error("Tentativa de deletar um link sem ID.", linkObject.userData);
|
|
2137
2183
|
return;
|
|
2138
2184
|
}
|
|
2139
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source);
|
|
2185
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkObject.userData.source, context.sceneConfigId, context.ownerId);
|
|
2140
2186
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2141
2187
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link:", linkIdToDelete);
|
|
2142
2188
|
alert("Ocorreu um erro ao identificar o arquivo pai da rela\xE7\xE3o para exclus\xE3o.");
|
|
@@ -2148,9 +2194,25 @@ var userActionHandlers = {
|
|
|
2148
2194
|
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileId]));
|
|
2149
2195
|
const newLinks = (specificParentData.links || []).filter((l) => String(l.id) !== String(linkIdToDelete));
|
|
2150
2196
|
specificParentData.links = newLinks;
|
|
2151
|
-
|
|
2197
|
+
let filenameToSave;
|
|
2198
|
+
let payloadToSave;
|
|
2199
|
+
const isView = ((_g = context.viewType) == null ? void 0 : _g.toLowerCase()) === "view";
|
|
2200
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2201
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2202
|
+
sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => String(l.id) !== String(linkIdToDelete));
|
|
2203
|
+
payloadToSave = {
|
|
2204
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2205
|
+
nodes: sceneDataRef.current.nodes,
|
|
2206
|
+
links: sceneDataRef.current.links,
|
|
2207
|
+
quest_nodes: specificParentData.nodes,
|
|
2208
|
+
quest_links: specificParentData.links
|
|
2209
|
+
};
|
|
2210
|
+
} else {
|
|
2211
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2212
|
+
payloadToSave = specificParentData;
|
|
2213
|
+
}
|
|
2152
2214
|
try {
|
|
2153
|
-
await context.actions.save_view_data(
|
|
2215
|
+
await context.actions.save_view_data(filenameToSave, payloadToSave);
|
|
2154
2216
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2155
2217
|
setters.setDetailsLink((prev) => String(prev == null ? void 0 : prev.id) === String(linkIdToDelete) ? null : prev);
|
|
2156
2218
|
if (stateRef.current.hoveredLink === linkObject) {
|
|
@@ -2168,12 +2230,6 @@ var userActionHandlers = {
|
|
|
2168
2230
|
if (!nodeData || !sceneDataRef.current) return;
|
|
2169
2231
|
const nodeIdToDismiss = nodeData.id;
|
|
2170
2232
|
const strNodeId = String(nodeIdToDismiss);
|
|
2171
|
-
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter(
|
|
2172
|
-
(n) => String(n.id) !== strNodeId
|
|
2173
|
-
);
|
|
2174
|
-
sceneDataRef.current.links = sceneDataRef.current.links.filter(
|
|
2175
|
-
(l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId
|
|
2176
|
-
);
|
|
2177
2233
|
const { ancestryGroup, ancestryLinks } = stateRef.current;
|
|
2178
2234
|
if (ancestryGroup && ancestryLinks) {
|
|
2179
2235
|
const remainingAncestryLinks = [];
|
|
@@ -2215,22 +2271,12 @@ var userActionHandlers = {
|
|
|
2215
2271
|
removeNodeFromScene(stateRef.current, nodeId);
|
|
2216
2272
|
setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeId) ? null : prev);
|
|
2217
2273
|
});
|
|
2218
|
-
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter(
|
|
2219
|
-
(n) => String(n.id) === strNodeIdToKeep
|
|
2220
|
-
);
|
|
2221
|
-
sceneDataRef.current.links = [];
|
|
2222
2274
|
},
|
|
2223
2275
|
handleDismissMultipleNodes: (context, nodeIds) => {
|
|
2224
2276
|
const { stateRef, sceneDataRef, setters } = context;
|
|
2225
2277
|
setters.setMultiContextMenu({ visible: false });
|
|
2226
2278
|
if (!nodeIds || nodeIds.size === 0 || !sceneDataRef.current) return;
|
|
2227
2279
|
const strNodeIds = Array.from(nodeIds).map(String);
|
|
2228
|
-
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter(
|
|
2229
|
-
(n) => !strNodeIds.includes(String(n.id))
|
|
2230
|
-
);
|
|
2231
|
-
sceneDataRef.current.links = sceneDataRef.current.links.filter(
|
|
2232
|
-
(l) => !strNodeIds.includes(String(l.source)) && !strNodeIds.includes(String(l.target))
|
|
2233
|
-
);
|
|
2234
2280
|
const { ancestryGroup, ancestryLinks } = stateRef.current;
|
|
2235
2281
|
if (ancestryGroup && ancestryLinks) {
|
|
2236
2282
|
const remainingAncestryLinks = [];
|
|
@@ -2286,15 +2332,10 @@ var userActionHandlers = {
|
|
|
2286
2332
|
removeNodeFromScene(stateRef.current, nodeId);
|
|
2287
2333
|
setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeId) ? null : prev);
|
|
2288
2334
|
});
|
|
2289
|
-
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter(
|
|
2290
|
-
(n) => strNodeIdsToKeep.includes(String(n.id))
|
|
2291
|
-
);
|
|
2292
|
-
sceneDataRef.current.links = sceneDataRef.current.links.filter(
|
|
2293
|
-
(l) => strNodeIdsToKeep.includes(String(l.source)) && strNodeIdsToKeep.includes(String(l.target))
|
|
2294
|
-
);
|
|
2295
2335
|
stateRef.current.selectedNodes.clear();
|
|
2296
2336
|
},
|
|
2297
2337
|
handleDeleteMultipleNodes: async (context, nodeIds) => {
|
|
2338
|
+
var _a;
|
|
2298
2339
|
const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
|
|
2299
2340
|
setters.setMultiContextMenu({ visible: false });
|
|
2300
2341
|
if (!nodeIds || nodeIds.size === 0 || !graphDataRef.current || !sceneDataRef.current) return;
|
|
@@ -2313,7 +2354,7 @@ var userActionHandlers = {
|
|
|
2313
2354
|
}
|
|
2314
2355
|
const changesByParentFile = {};
|
|
2315
2356
|
for (const nodeId of strNodeIdsToDelete) {
|
|
2316
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId);
|
|
2357
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeId, context.sceneConfigId, context.ownerId);
|
|
2317
2358
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2318
2359
|
console.warn(`Node com ID ${nodeId} n\xE3o encontrado ou sem ownerId. Ignorando.`);
|
|
2319
2360
|
continue;
|
|
@@ -2347,8 +2388,27 @@ var userActionHandlers = {
|
|
|
2347
2388
|
originalData.links = (originalData.links || []).filter(
|
|
2348
2389
|
(l) => !linksToDelete.has(String(l.id))
|
|
2349
2390
|
);
|
|
2350
|
-
|
|
2351
|
-
|
|
2391
|
+
let filenameToSave;
|
|
2392
|
+
let payloadToSave;
|
|
2393
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2394
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2395
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2396
|
+
const strNodesToDelete = Array.from(nodesToDelete).map(String);
|
|
2397
|
+
const strLinksToDelete = Array.from(linksToDelete).map(String);
|
|
2398
|
+
sceneDataRef.current.nodes = sceneDataRef.current.nodes.filter((n) => !strNodesToDelete.includes(String(n.id)));
|
|
2399
|
+
sceneDataRef.current.links = sceneDataRef.current.links.filter((l) => !strLinksToDelete.includes(String(l.id)));
|
|
2400
|
+
payloadToSave = {
|
|
2401
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2402
|
+
nodes: sceneDataRef.current.nodes,
|
|
2403
|
+
links: sceneDataRef.current.links,
|
|
2404
|
+
quest_nodes: originalData.nodes,
|
|
2405
|
+
quest_links: originalData.links
|
|
2406
|
+
};
|
|
2407
|
+
} else {
|
|
2408
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2409
|
+
payloadToSave = originalData;
|
|
2410
|
+
}
|
|
2411
|
+
savePromises.push(context.actions.save_view_data(filenameToSave, payloadToSave));
|
|
2352
2412
|
updatedParentDataCache[parentFileId] = originalData;
|
|
2353
2413
|
}
|
|
2354
2414
|
}
|
|
@@ -2369,6 +2429,7 @@ var userActionHandlers = {
|
|
|
2369
2429
|
}
|
|
2370
2430
|
},
|
|
2371
2431
|
handleDeleteNode: async (context, nodeData) => {
|
|
2432
|
+
var _a;
|
|
2372
2433
|
const { stateRef, graphDataRef, sceneDataRef, setters, actions } = context;
|
|
2373
2434
|
if (actions.delete_file && nodeData) {
|
|
2374
2435
|
const urls = extractFileUrlsFromProperties(nodeData);
|
|
@@ -2380,7 +2441,7 @@ var userActionHandlers = {
|
|
|
2380
2441
|
if (!nodeData || !graphDataRef.current || !sceneDataRef.current) return;
|
|
2381
2442
|
const nodeIdToDelete = nodeData.id;
|
|
2382
2443
|
const strNodeId = String(nodeIdToDelete);
|
|
2383
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete);
|
|
2444
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeIdToDelete, context.sceneConfigId, context.ownerId);
|
|
2384
2445
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2385
2446
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser exclu\xEDdo:", nodeIdToDelete);
|
|
2386
2447
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para exclus\xE3o.");
|
|
@@ -2392,9 +2453,28 @@ var userActionHandlers = {
|
|
|
2392
2453
|
const newLinks = (specificParentData.links || []).filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
|
|
2393
2454
|
specificParentData.nodes = newNodes;
|
|
2394
2455
|
specificParentData.links = newLinks;
|
|
2395
|
-
|
|
2456
|
+
let filenameToSave;
|
|
2457
|
+
let payloadToSave;
|
|
2458
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2459
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2460
|
+
filenameToSave = context.sceneSaveUrl;
|
|
2461
|
+
const newVisualNodes = sceneDataRef.current.nodes.filter((n) => String(n.id) !== strNodeId);
|
|
2462
|
+
const newVisualLinks = sceneDataRef.current.links.filter((l) => String(l.source) !== strNodeId && String(l.target) !== strNodeId);
|
|
2463
|
+
sceneDataRef.current.nodes = newVisualNodes;
|
|
2464
|
+
sceneDataRef.current.links = newVisualLinks;
|
|
2465
|
+
payloadToSave = {
|
|
2466
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2467
|
+
nodes: newVisualNodes,
|
|
2468
|
+
links: newVisualLinks,
|
|
2469
|
+
quest_nodes: specificParentData.nodes,
|
|
2470
|
+
quest_links: specificParentData.links
|
|
2471
|
+
};
|
|
2472
|
+
} else {
|
|
2473
|
+
filenameToSave = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2474
|
+
payloadToSave = specificParentData;
|
|
2475
|
+
}
|
|
2396
2476
|
try {
|
|
2397
|
-
await context.actions.save_view_data(
|
|
2477
|
+
await context.actions.save_view_data(filenameToSave, payloadToSave);
|
|
2398
2478
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2399
2479
|
setters.setDetailsNode((prev) => String(prev == null ? void 0 : prev.id) === String(nodeIdToDelete) ? null : prev);
|
|
2400
2480
|
removeNodeFromScene(stateRef.current, nodeIdToDelete);
|
|
@@ -2405,10 +2485,11 @@ var userActionHandlers = {
|
|
|
2405
2485
|
}
|
|
2406
2486
|
},
|
|
2407
2487
|
handleSaveNodeDetails: async (context, updatedNode, keepOpen = false) => {
|
|
2488
|
+
var _a;
|
|
2408
2489
|
const { graphDataRef, sceneDataRef, stateRef, setters } = context;
|
|
2409
2490
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
2410
2491
|
const { _baseEmissiveIntensity: ignored, ...nodeToSave } = updatedNode;
|
|
2411
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id);
|
|
2492
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, nodeToSave.id, context.sceneConfigId, context.ownerId);
|
|
2412
2493
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2413
2494
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o Node a ser atualizado:", nodeToSave.id);
|
|
2414
2495
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
|
|
@@ -2424,9 +2505,21 @@ var userActionHandlers = {
|
|
|
2424
2505
|
alert("Erro interno: Node n\xE3o encontrado para salvar.");
|
|
2425
2506
|
return;
|
|
2426
2507
|
}
|
|
2427
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2428
2508
|
try {
|
|
2429
|
-
|
|
2509
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2510
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2511
|
+
const viewFilePayload = {
|
|
2512
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2513
|
+
nodes: sceneDataRef.current.nodes,
|
|
2514
|
+
links: sceneDataRef.current.links,
|
|
2515
|
+
quest_nodes: specificParentData.nodes,
|
|
2516
|
+
quest_links: specificParentData.links
|
|
2517
|
+
};
|
|
2518
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2519
|
+
} else {
|
|
2520
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2521
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2522
|
+
}
|
|
2430
2523
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2431
2524
|
updateExistingNodeVisuals(stateRef.current, nodeToSave);
|
|
2432
2525
|
setters.setSceneVersion((v) => v + 1);
|
|
@@ -2439,10 +2532,11 @@ var userActionHandlers = {
|
|
|
2439
2532
|
}
|
|
2440
2533
|
},
|
|
2441
2534
|
handleSaveLinkDetails: async (context, updatedLink, keepOpen = false) => {
|
|
2535
|
+
var _a;
|
|
2442
2536
|
const { graphDataRef, sceneDataRef, stateRef, setters } = context;
|
|
2443
2537
|
if (!graphDataRef.current || !sceneDataRef.current) return;
|
|
2444
2538
|
const { sourceNode, targetNode, ...linkToSave } = updatedLink;
|
|
2445
|
-
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source);
|
|
2539
|
+
const parentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef.current, linkToSave.source, context.sceneConfigId, context.ownerId);
|
|
2446
2540
|
if (!parentInfo || !parentInfo.ownerId) {
|
|
2447
2541
|
console.error("N\xE3o foi poss\xEDvel encontrar as informa\xE7\xF5es do arquivo pai (ou ownerId) para o link a ser atualizado:", linkToSave.id);
|
|
2448
2542
|
alert("Ocorreu um erro ao identificar o arquivo pai ou seu propriet\xE1rio para atualiza\xE7\xE3o.");
|
|
@@ -2458,9 +2552,21 @@ var userActionHandlers = {
|
|
|
2458
2552
|
alert("Erro interno: link n\xE3o encontrado para salvar.");
|
|
2459
2553
|
return;
|
|
2460
2554
|
}
|
|
2461
|
-
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2462
2555
|
try {
|
|
2463
|
-
|
|
2556
|
+
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2557
|
+
if (isView && parentFileId === context.sceneConfigId) {
|
|
2558
|
+
const viewFilePayload = {
|
|
2559
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2560
|
+
nodes: sceneDataRef.current.nodes,
|
|
2561
|
+
links: sceneDataRef.current.links,
|
|
2562
|
+
quest_nodes: specificParentData.nodes,
|
|
2563
|
+
quest_links: specificParentData.links
|
|
2564
|
+
};
|
|
2565
|
+
await context.actions.save_view_data(context.sceneSaveUrl, viewFilePayload);
|
|
2566
|
+
} else {
|
|
2567
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerId}/${parentFileId}`;
|
|
2568
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
2569
|
+
}
|
|
2464
2570
|
graphDataRef.current[parentFileId] = specificParentData;
|
|
2465
2571
|
const lineObject = stateRef.current.allLinks.find(
|
|
2466
2572
|
(l) => String(l.userData.id) === String(linkToSave.id)
|
|
@@ -2483,7 +2589,7 @@ var userActionHandlers = {
|
|
|
2483
2589
|
}
|
|
2484
2590
|
},
|
|
2485
2591
|
handleAddExistingNodeById: (context, nodeId) => {
|
|
2486
|
-
var _a
|
|
2592
|
+
var _a;
|
|
2487
2593
|
const { stateRef, sceneDataRef, graphDataRef, tweenToTarget, setters } = context;
|
|
2488
2594
|
const state = stateRef.current;
|
|
2489
2595
|
const graphFull = graphDataRef.current;
|
|
@@ -2499,16 +2605,12 @@ var userActionHandlers = {
|
|
|
2499
2605
|
tweenToTarget(state.nodeObjects[strNodeId]);
|
|
2500
2606
|
return;
|
|
2501
2607
|
}
|
|
2502
|
-
const alreadyInSceneData = (((_a = sceneDataRef.current) == null ? void 0 : _a.nodes) || []).some((n) => String(n.id) === String(strNodeId));
|
|
2503
|
-
if (!alreadyInSceneData) {
|
|
2504
|
-
sceneDataRef.current.nodes.push(nodeData);
|
|
2505
|
-
}
|
|
2506
2608
|
const base = state.controls ? state.controls.target.clone() : new THREE.Vector3(0, 0, 0);
|
|
2507
2609
|
const offset = new THREE.Vector3((Math.random() - 0.5) * 20, (Math.random() - 0.5) * 6, (Math.random() - 0.5) * 20);
|
|
2508
2610
|
const position = base.add(offset);
|
|
2509
2611
|
addStandaloneNodeToScene(state, nodeData, position);
|
|
2510
2612
|
tweenToTarget(position, 1.3);
|
|
2511
|
-
(
|
|
2613
|
+
(_a = setters == null ? void 0 : setters.setSceneVersion) == null ? void 0 : _a.call(setters, (v) => v + 1);
|
|
2512
2614
|
}
|
|
2513
2615
|
};
|
|
2514
2616
|
|
|
@@ -3097,7 +3199,7 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
|
|
|
3097
3199
|
|
|
3098
3200
|
// src/components/CustomPropertyDisplay.jsx
|
|
3099
3201
|
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
3100
|
-
import { FiCheck, FiX
|
|
3202
|
+
import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
|
|
3101
3203
|
function CustomPropertyDisplay({
|
|
3102
3204
|
prop,
|
|
3103
3205
|
onUpdate,
|
|
@@ -3388,7 +3490,7 @@ function CustomPropertyDisplay({
|
|
|
3388
3490
|
default:
|
|
3389
3491
|
return /* @__PURE__ */ React3.createElement("input", { type: "text", placeholder: "Valor", value: tempProp.value, onChange: (e) => handlePropChange("value", e.target.value), className: baseInput });
|
|
3390
3492
|
}
|
|
3391
|
-
})()), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-end items-center gap-2 pt-1" }, /* @__PURE__ */ React3.createElement("button", { onClick: handleCancel, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(
|
|
3493
|
+
})()), /* @__PURE__ */ React3.createElement("div", { className: "flex justify-end items-center gap-2 pt-1" }, /* @__PURE__ */ React3.createElement("button", { onClick: handleCancel, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(FiX, { className: "text-red-400" })), /* @__PURE__ */ React3.createElement("button", { onClick: handleSave, type: "button", className: "w-8 h-8 grid place-items-center rounded-lg hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React3.createElement(FiCheck, { className: "text-green-400" }))));
|
|
3392
3494
|
};
|
|
3393
3495
|
const renderDisplayView = () => /* @__PURE__ */ React3.createElement("div", { className: "w-full space-y-2 text-sm" }, /* @__PURE__ */ React3.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React3.createElement("p", { className: "font-semibold text-slate-200" }, prop.key), /* @__PURE__ */ React3.createElement("span", { className: "text-xs capitalize bg-slate-700/50 px-2 py-0.5 rounded text-slate-400" }, prop.type)), /* @__PURE__ */ React3.createElement("div", { className: "text-slate-300 pl-1" }, (() => {
|
|
3394
3496
|
switch (prop.type) {
|
|
@@ -7024,7 +7126,7 @@ function CreateAncestryPanel({
|
|
|
7024
7126
|
|
|
7025
7127
|
// src/components/ImageViewer.jsx
|
|
7026
7128
|
import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
|
|
7027
|
-
import { FiX as
|
|
7129
|
+
import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
|
|
7028
7130
|
function ImageViewer({ data, onClose }) {
|
|
7029
7131
|
var _a;
|
|
7030
7132
|
const { images = [], startIndex = 0, visible } = data;
|
|
@@ -7109,7 +7211,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
7109
7211
|
className: "absolute top-4 right-4 z-10 w-10 h-10 flex items-center justify-center bg-white/10 hover:bg-white/20 rounded-full text-white text-2xl transition-colors",
|
|
7110
7212
|
"aria-label": "Fechar"
|
|
7111
7213
|
},
|
|
7112
|
-
/* @__PURE__ */ React11.createElement(
|
|
7214
|
+
/* @__PURE__ */ React11.createElement(FiX2, null)
|
|
7113
7215
|
),
|
|
7114
7216
|
/* @__PURE__ */ React11.createElement("div", { className: "relative max-w-full max-h-full flex items-center justify-center" }, isLoading && /* @__PURE__ */ React11.createElement("div", { className: "absolute inset-0 flex items-center justify-center" }, /* @__PURE__ */ React11.createElement("div", { className: "h-10 w-10 border-2 border-white/40 border-t-white rounded-full animate-spin" })), loadedSrc && /* @__PURE__ */ React11.createElement(
|
|
7115
7217
|
"img",
|
|
@@ -7245,7 +7347,7 @@ function ColorPicker({ color, onChange, disabled }) {
|
|
|
7245
7347
|
}
|
|
7246
7348
|
|
|
7247
7349
|
// src/components/InSceneCreationForm.jsx
|
|
7248
|
-
import { FiPlus as FiPlus3, FiMaximize2, FiX as
|
|
7350
|
+
import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun, FiChevronDown as FiChevronDown4 } from "react-icons/fi";
|
|
7249
7351
|
function InSceneCreationForm({
|
|
7250
7352
|
onSave,
|
|
7251
7353
|
onCancel,
|
|
@@ -7463,7 +7565,7 @@ function InSceneCreationForm({
|
|
|
7463
7565
|
onClick: () => handleRemoveType(index),
|
|
7464
7566
|
className: "hover:text-white transition-colors"
|
|
7465
7567
|
},
|
|
7466
|
-
/* @__PURE__ */ React13.createElement(
|
|
7568
|
+
/* @__PURE__ */ React13.createElement(FiX3, { size: 12 })
|
|
7467
7569
|
))), /* @__PURE__ */ React13.createElement(
|
|
7468
7570
|
"input",
|
|
7469
7571
|
{
|
|
@@ -7837,16 +7939,12 @@ function InSceneVersionForm({
|
|
|
7837
7939
|
|
|
7838
7940
|
// src/components/InSceneQuestForm.jsx
|
|
7839
7941
|
import React15, { useState as useState16, useRef as useRef12 } from "react";
|
|
7840
|
-
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget } from "react-icons/fi";
|
|
7942
|
+
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4, FiChevronDown as FiChevronDown5 } from "react-icons/fi";
|
|
7841
7943
|
var QUEST_STATUS_COLORS = {
|
|
7842
7944
|
"Backlog": "#64748b",
|
|
7843
|
-
// Slate (Cinza azulado)
|
|
7844
7945
|
"In Progress": "#eab308",
|
|
7845
|
-
// Yellow (Amarelo)
|
|
7846
7946
|
"Review": "#a855f7",
|
|
7847
|
-
// Purple (Roxo)
|
|
7848
7947
|
"Done": "#22c55e"
|
|
7849
|
-
// Green (Verde)
|
|
7850
7948
|
};
|
|
7851
7949
|
function InSceneQuestForm({
|
|
7852
7950
|
onSave,
|
|
@@ -7857,7 +7955,11 @@ function InSceneQuestForm({
|
|
|
7857
7955
|
availableNodes = [],
|
|
7858
7956
|
availableAncestries = [],
|
|
7859
7957
|
onMentionClick,
|
|
7860
|
-
onUploadFile
|
|
7958
|
+
onUploadFile,
|
|
7959
|
+
// NOVAS PROPS PARA O GHOST NODE
|
|
7960
|
+
onNameChange,
|
|
7961
|
+
onColorChange,
|
|
7962
|
+
onSizeChange
|
|
7861
7963
|
}) {
|
|
7862
7964
|
const [name, setName] = useState16("");
|
|
7863
7965
|
const [types, setTypes] = useState16(["quest"]);
|
|
@@ -7866,6 +7968,7 @@ function InSceneQuestForm({
|
|
|
7866
7968
|
const [size, setSize] = useState16("medium");
|
|
7867
7969
|
const [intensity, setIntensity] = useState16(0);
|
|
7868
7970
|
const [description, setDescription] = useState16("");
|
|
7971
|
+
const [isStatusDropdownOpen, setIsStatusDropdownOpen] = useState16(false);
|
|
7869
7972
|
const [customProps, setCustomProps] = useState16([]);
|
|
7870
7973
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState16(false);
|
|
7871
7974
|
const propsEndRef = useRef12(null);
|
|
@@ -7884,7 +7987,7 @@ function InSceneQuestForm({
|
|
|
7884
7987
|
setCustomProps(newProps);
|
|
7885
7988
|
};
|
|
7886
7989
|
const handleAddType = (newType) => {
|
|
7887
|
-
const trimmed = newType.trim()
|
|
7990
|
+
const trimmed = newType.trim();
|
|
7888
7991
|
if (trimmed && !types.includes(trimmed)) {
|
|
7889
7992
|
setTypes([...types, trimmed]);
|
|
7890
7993
|
setTypeInput("");
|
|
@@ -7916,7 +8019,6 @@ function InSceneQuestForm({
|
|
|
7916
8019
|
name: name.trim(),
|
|
7917
8020
|
type: types,
|
|
7918
8021
|
color: QUEST_STATUS_COLORS[status],
|
|
7919
|
-
// Cor atrelada ao status
|
|
7920
8022
|
status,
|
|
7921
8023
|
size,
|
|
7922
8024
|
intensity,
|
|
@@ -7943,20 +8045,52 @@ function InSceneQuestForm({
|
|
|
7943
8045
|
onDoubleClick: swallow
|
|
7944
8046
|
},
|
|
7945
8047
|
/* @__PURE__ */ React15.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS[status]}, transparent)` } }),
|
|
7946
|
-
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
8048
|
+
/* @__PURE__ */ React15.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React15.createElement("div", null, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React15.createElement(FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Nova quest")), /* @__PURE__ */ React15.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, "Criar Quest")), /* @__PURE__ */ React15.createElement(
|
|
8049
|
+
"button",
|
|
8050
|
+
{
|
|
8051
|
+
type: "button",
|
|
8052
|
+
onClick: onCancel,
|
|
8053
|
+
className: "w-9 h-9 grid place-content-center rounded-lg border border-white/15 bg-transparent hover:bg-white/5 transition-colors text-xl",
|
|
8054
|
+
title: "Fechar"
|
|
8055
|
+
},
|
|
8056
|
+
"\xD7"
|
|
8057
|
+
)),
|
|
8058
|
+
/* @__PURE__ */ React15.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col max-h-[68vh]" }, /* @__PURE__ */ React15.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 custom-scrollbar" }, /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
|
|
8059
|
+
"button",
|
|
8060
|
+
{
|
|
8061
|
+
type: "button",
|
|
8062
|
+
onClick: () => setIsStatusDropdownOpen(!isStatusDropdownOpen),
|
|
8063
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-2 focus:ring-indigo-400/60 transition-colors flex items-center justify-between"
|
|
8064
|
+
},
|
|
8065
|
+
/* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full shadow-[0_0_8px_rgba(0,0,0,0.5)]", style: { backgroundColor: QUEST_STATUS_COLORS[status] } }), /* @__PURE__ */ React15.createElement("span", { className: "text-slate-200 font-medium" }, status)),
|
|
8066
|
+
/* @__PURE__ */ React15.createElement(FiChevronDown5, { className: `text-slate-400 transition-transform duration-200 ${isStatusDropdownOpen ? "rotate-180" : ""}` })
|
|
8067
|
+
), isStatusDropdownOpen && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsStatusDropdownOpen(false) }), /* @__PURE__ */ React15.createElement("ul", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-800 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden" }, Object.keys(QUEST_STATUS_COLORS).map((s) => /* @__PURE__ */ React15.createElement(
|
|
8068
|
+
"li",
|
|
8069
|
+
{
|
|
8070
|
+
key: s,
|
|
8071
|
+
onClick: () => {
|
|
8072
|
+
setStatus(s);
|
|
8073
|
+
setIsStatusDropdownOpen(false);
|
|
8074
|
+
onColorChange == null ? void 0 : onColorChange(QUEST_STATUS_COLORS[s]);
|
|
8075
|
+
},
|
|
8076
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${status === s ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
7954
8077
|
},
|
|
7955
|
-
/* @__PURE__ */ React15.createElement("
|
|
7956
|
-
|
|
7957
|
-
|
|
7958
|
-
|
|
7959
|
-
|
|
8078
|
+
/* @__PURE__ */ React15.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS[s] } }),
|
|
8079
|
+
s
|
|
8080
|
+
)))))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ React15.createElement(
|
|
8081
|
+
"input",
|
|
8082
|
+
{
|
|
8083
|
+
required: true,
|
|
8084
|
+
type: "text",
|
|
8085
|
+
placeholder: "Ex.: Refatorar M\xF3dulo X",
|
|
8086
|
+
value: name,
|
|
8087
|
+
onChange: (e) => {
|
|
8088
|
+
setName(e.target.value);
|
|
8089
|
+
onNameChange == null ? void 0 : onNameChange(e.target.value);
|
|
8090
|
+
},
|
|
8091
|
+
className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60"
|
|
8092
|
+
}
|
|
8093
|
+
)), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React15.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ React15.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React15.createElement(FiX4, { size: 12 })))), /* @__PURE__ */ React15.createElement(
|
|
7960
8094
|
"input",
|
|
7961
8095
|
{
|
|
7962
8096
|
type: "text",
|
|
@@ -7967,7 +8101,6 @@ function InSceneQuestForm({
|
|
|
7967
8101
|
if (typeInput.trim()) handleAddType(typeInput);
|
|
7968
8102
|
},
|
|
7969
8103
|
className: "flex-1 bg-transparent text-sm min-w-[80px] focus:outline-none text-slate-200",
|
|
7970
|
-
placeholder: "Ex.: Bugfix",
|
|
7971
8104
|
autoComplete: "off"
|
|
7972
8105
|
}
|
|
7973
8106
|
))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Descri\xE7\xE3o (Opcional)"), /* @__PURE__ */ React15.createElement("div", { className: "relative group min-h-[80px] bg-slate-800/70 p-2.5 rounded-lg border border-white/10 hover:border-white/20 transition-colors" }, /* @__PURE__ */ React15.createElement(
|
|
@@ -7980,7 +8113,20 @@ function InSceneQuestForm({
|
|
|
7980
8113
|
onMentionClick,
|
|
7981
8114
|
onSaveDescription: (newDesc) => setDescription(newDesc)
|
|
7982
8115
|
}
|
|
7983
|
-
), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no
|
|
8116
|
+
), /* @__PURE__ */ React15.createElement("div", { className: "absolute top-0 right-0 flex bg-slate-900/50 rounded-bl-lg backdrop-blur-sm opacity-0 group-hover:opacity-100 transition-opacity overflow-hidden border-b border-l border-white/5" }, /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: () => setIsDescriptionModalOpen(true), className: "p-2 text-slate-400 hover:text-white hover:bg-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiEdit26, { size: 14 }))), !description && /* @__PURE__ */ React15.createElement("div", { onClick: () => setIsDescriptionModalOpen(true), className: "absolute inset-0 flex items-center justify-center text-xs text-slate-500 cursor-text" }, "Adicionar descri\xE7\xE3o..."))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Node (Size)"), /* @__PURE__ */ React15.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => /* @__PURE__ */ React15.createElement(
|
|
8117
|
+
"button",
|
|
8118
|
+
{
|
|
8119
|
+
key: s,
|
|
8120
|
+
type: "button",
|
|
8121
|
+
onClick: () => {
|
|
8122
|
+
setSize(s);
|
|
8123
|
+
onSizeChange == null ? void 0 : onSizeChange(s);
|
|
8124
|
+
},
|
|
8125
|
+
className: "flex items-center gap-2 group cursor-pointer focus:outline-none"
|
|
8126
|
+
},
|
|
8127
|
+
/* @__PURE__ */ React15.createElement("div", { className: `w-4 h-4 rounded-[4px] border flex items-center justify-center transition-all duration-200 ${size === s ? "bg-indigo-500 border-indigo-500" : "border-slate-600 bg-transparent group-hover:border-slate-500"}` }, size === s && /* @__PURE__ */ React15.createElement(FiCheck9, { size: 12, className: "text-white" })),
|
|
8128
|
+
/* @__PURE__ */ React15.createElement("span", { className: `text-sm capitalize transition-colors ${size === s ? "text-white font-medium" : "text-slate-400 group-hover:text-slate-300"}` }, s)
|
|
8129
|
+
)))), /* @__PURE__ */ React15.createElement("div", { className: "pt-2" }, /* @__PURE__ */ React15.createElement("div", { className: "flex items-center justify-between mb-2" }, /* @__PURE__ */ React15.createElement("h3", { className: "text-sm font-medium" }, "Propriedades Adicionais"), /* @__PURE__ */ React15.createElement("button", { type: "button", onClick: handleAddProp, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-xs rounded-md bg-slate-800/70 hover:bg-slate-700/70 border border-white/10 transition-colors" }, /* @__PURE__ */ React15.createElement(FiPlus5, { size: 14 }), " Adicionar")), /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col gap-3" }, customProps.map((prop, index) => /* @__PURE__ */ React15.createElement(
|
|
7984
8130
|
CustomPropertyDisplay,
|
|
7985
8131
|
{
|
|
7986
8132
|
key: prop.id,
|
|
@@ -10173,7 +10319,7 @@ function XViewScene({
|
|
|
10173
10319
|
});
|
|
10174
10320
|
}
|
|
10175
10321
|
return {
|
|
10176
|
-
node: effectiveNode
|
|
10322
|
+
...effectiveNode ? { node: effectiveNode } : { node: { id: nodeId, name: "Unknown" } },
|
|
10177
10323
|
relationship: treeItem.relationship || {},
|
|
10178
10324
|
children: (treeItem.children || []).map(recursiveBuild).filter(Boolean),
|
|
10179
10325
|
parallel_branches: processedBranches
|
|
@@ -10872,20 +11018,6 @@ function XViewScene({
|
|
|
10872
11018
|
const context = actionHandlerContext;
|
|
10873
11019
|
if (connection.isActive) {
|
|
10874
11020
|
if (hoveredNode && String(hoveredNode.userData.id) !== String(connection.sourceNodeData.id)) {
|
|
10875
|
-
const sourceId = String(connection.sourceNodeData.id);
|
|
10876
|
-
const targetId = String(hoveredNode.userData.id);
|
|
10877
|
-
let parentInfo = stateRef.current.nodeIdToParentFileMap.get(sourceId);
|
|
10878
|
-
if (!parentInfo || !parentInfo.ownerId) {
|
|
10879
|
-
parentInfo = stateRef.current.nodeIdToParentFileMap.get(targetId);
|
|
10880
|
-
if (parentInfo && parentInfo.ownerId) {
|
|
10881
|
-
stateRef.current.nodeIdToParentFileMap.set(sourceId, parentInfo);
|
|
10882
|
-
} else {
|
|
10883
|
-
console.error("Nenhum dos Nodes possui um Dataset pai v\xE1lido para salvar a conex\xE3o.");
|
|
10884
|
-
alert("N\xE3o \xE9 poss\xEDvel conectar dois Nodes de Quest diretamente sem um Dataset pai, ou ocorreu um erro.");
|
|
10885
|
-
userActionHandlers.handleCancelConnection(context);
|
|
10886
|
-
return;
|
|
10887
|
-
}
|
|
10888
|
-
}
|
|
10889
11021
|
await userActionHandlers.handleCompleteConnection(context, hoveredNode.userData);
|
|
10890
11022
|
} else {
|
|
10891
11023
|
userActionHandlers.handleCancelConnection(context);
|
|
@@ -10991,39 +11123,6 @@ function XViewScene({
|
|
|
10991
11123
|
}
|
|
10992
11124
|
}
|
|
10993
11125
|
}
|
|
10994
|
-
function handleCancelAncestryCreation() {
|
|
10995
|
-
setAncestryMode({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
10996
|
-
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
10997
|
-
}
|
|
10998
|
-
function handleKeyDown(event) {
|
|
10999
|
-
var _a2, _b2, _c2, _d2;
|
|
11000
|
-
const context = actionHandlerContext;
|
|
11001
|
-
if (event.key === "Escape") {
|
|
11002
|
-
if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
|
|
11003
|
-
if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
|
|
11004
|
-
if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
|
|
11005
|
-
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
|
|
11006
|
-
if (stateRef.current.ancestry.isActive) handleCancelAncestryCreation();
|
|
11007
|
-
if ((_b2 = context.questMode) == null ? void 0 : _b2.isActive) context.setters.setQuestMode({ isActive: false });
|
|
11008
|
-
if (stateRef.current.selectedNodes.size > 0) {
|
|
11009
|
-
stateRef.current.selectedNodes.clear();
|
|
11010
|
-
}
|
|
11011
|
-
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
11012
|
-
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
11013
|
-
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
11014
|
-
}
|
|
11015
|
-
if (event.key.toLowerCase() === "q") {
|
|
11016
|
-
const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_c2 = context.versionMode) == null ? void 0 : _c2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isAncestryBoardOpen;
|
|
11017
|
-
if (isUiClear) {
|
|
11018
|
-
const isView = ((_d2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _d2.toLowerCase()) === "view";
|
|
11019
|
-
if (!isView) {
|
|
11020
|
-
alert("Nodes de Quest s\xF3 podem ser criados dentro de uma View.");
|
|
11021
|
-
return;
|
|
11022
|
-
}
|
|
11023
|
-
setQuestMode({ isActive: true });
|
|
11024
|
-
}
|
|
11025
|
-
}
|
|
11026
|
-
}
|
|
11027
11126
|
function handleDoubleClick(event) {
|
|
11028
11127
|
if (stateRef.current.camera) stateRef.current.camera.layers.enableAll();
|
|
11029
11128
|
if (isFromUiOverlay(event) || stateRef.current.isDragging || stateRef.current.creation.isActive || stateRef.current.connection.isActive || stateRef.current.relink.isActive) return;
|
|
@@ -11076,7 +11175,6 @@ function XViewScene({
|
|
|
11076
11175
|
currentMount.addEventListener("dblclick", handleDoubleClick);
|
|
11077
11176
|
currentMount.addEventListener("pointermove", onPointerMove);
|
|
11078
11177
|
currentMount.addEventListener("contextmenu", handleContextMenu);
|
|
11079
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
11080
11178
|
const originalBackground = scene.background;
|
|
11081
11179
|
const clock = new THREE3.Clock();
|
|
11082
11180
|
let animationFrameId = 0;
|
|
@@ -11214,7 +11312,6 @@ function XViewScene({
|
|
|
11214
11312
|
return () => {
|
|
11215
11313
|
cancelAnimationFrame(animationFrameId);
|
|
11216
11314
|
window.removeEventListener("resize", handleResize);
|
|
11217
|
-
window.removeEventListener("keydown", handleKeyDown);
|
|
11218
11315
|
currentMount.removeEventListener("pointerdown", onPointerDown);
|
|
11219
11316
|
currentMount.removeEventListener("pointerup", onPointerUp);
|
|
11220
11317
|
currentMount.removeEventListener("dblclick", handleDoubleClick);
|
|
@@ -11488,11 +11585,10 @@ function XViewScene({
|
|
|
11488
11585
|
creationMode,
|
|
11489
11586
|
versionMode,
|
|
11490
11587
|
questMode,
|
|
11491
|
-
// <-- Adicionado
|
|
11492
11588
|
sceneSaveUrl,
|
|
11493
|
-
|
|
11589
|
+
sceneConfigId,
|
|
11590
|
+
ownerId,
|
|
11494
11591
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11495
|
-
// <-- Adicionado
|
|
11496
11592
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
11497
11593
|
setters: {
|
|
11498
11594
|
setContextMenu,
|
|
@@ -11506,7 +11602,6 @@ function XViewScene({
|
|
|
11506
11602
|
setSceneVersion,
|
|
11507
11603
|
setAncestryMode,
|
|
11508
11604
|
setQuestMode
|
|
11509
|
-
// <-- Adicionado
|
|
11510
11605
|
},
|
|
11511
11606
|
tweenToTarget,
|
|
11512
11607
|
handleVersionTimeline,
|
|
@@ -11524,9 +11619,11 @@ function XViewScene({
|
|
|
11524
11619
|
versionMode,
|
|
11525
11620
|
questMode,
|
|
11526
11621
|
sceneSaveUrl,
|
|
11622
|
+
sceneConfigId,
|
|
11623
|
+
ownerId,
|
|
11527
11624
|
viewParams == null ? void 0 : viewParams.type,
|
|
11528
|
-
tweenToTarget,
|
|
11529
11625
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11626
|
+
tweenToTarget,
|
|
11530
11627
|
handleVersionTimeline,
|
|
11531
11628
|
save_view_data,
|
|
11532
11629
|
get_single_parent_file,
|
|
@@ -11538,33 +11635,116 @@ function XViewScene({
|
|
|
11538
11635
|
const handleStartVersioning = (nodeData) => {
|
|
11539
11636
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11540
11637
|
};
|
|
11638
|
+
const handleCancelQuest = useCallback4(() => {
|
|
11639
|
+
const { graphGroup, ghostElements } = stateRef.current;
|
|
11640
|
+
if (ghostElements.node && graphGroup) {
|
|
11641
|
+
if (ghostElements.node.userData.labelObject) {
|
|
11642
|
+
graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
11643
|
+
if (ghostElements.node.userData.labelObject.material.map) ghostElements.node.userData.labelObject.material.map.dispose();
|
|
11644
|
+
ghostElements.node.userData.labelObject.material.dispose();
|
|
11645
|
+
}
|
|
11646
|
+
graphGroup.remove(ghostElements.node);
|
|
11647
|
+
ghostElements.node.traverse((child) => {
|
|
11648
|
+
if (child.material) {
|
|
11649
|
+
if (Array.isArray(child.material)) child.material.forEach((m) => m.dispose());
|
|
11650
|
+
else child.material.dispose();
|
|
11651
|
+
}
|
|
11652
|
+
if (child.geometry) child.geometry.dispose();
|
|
11653
|
+
});
|
|
11654
|
+
}
|
|
11655
|
+
stateRef.current.ghostElements = { node: null, line: null, aura: null };
|
|
11656
|
+
setQuestMode({ isActive: false });
|
|
11657
|
+
}, []);
|
|
11541
11658
|
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11542
|
-
const { sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType } = context;
|
|
11543
|
-
if (!
|
|
11659
|
+
const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
|
|
11660
|
+
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11544
11661
|
const newNode = {
|
|
11545
11662
|
id: short2.generate(),
|
|
11546
11663
|
...newQuestData,
|
|
11664
|
+
is_quest: true,
|
|
11547
11665
|
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11548
11666
|
};
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11667
|
+
if (!graphDataRef.current[sceneConfigId2]) {
|
|
11668
|
+
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11669
|
+
}
|
|
11670
|
+
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
11671
|
+
const sceneFileData = {
|
|
11672
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11673
|
+
nodes: sceneDataRef2.current.nodes,
|
|
11674
|
+
links: sceneDataRef2.current.links,
|
|
11675
|
+
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
11676
|
+
quest_links: graphDataRef.current[sceneConfigId2].links
|
|
11552
11677
|
};
|
|
11553
11678
|
try {
|
|
11554
|
-
await actions.save_view_data(sceneSaveUrl2,
|
|
11555
|
-
|
|
11556
|
-
|
|
11557
|
-
|
|
11558
|
-
|
|
11559
|
-
|
|
11679
|
+
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
11680
|
+
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
11681
|
+
parentFileId: sceneConfigId2,
|
|
11682
|
+
ownerId: ownerId2,
|
|
11683
|
+
datasetName: "Quests Internas (View)"
|
|
11684
|
+
});
|
|
11685
|
+
const finalPosition = stateRef2.current.ghostElements.node ? stateRef2.current.ghostElements.node.position.clone() : stateRef2.current.controls.target.clone();
|
|
11686
|
+
const { graphGroup, ghostElements } = stateRef2.current;
|
|
11687
|
+
if (ghostElements.node && graphGroup) {
|
|
11688
|
+
if (ghostElements.node.userData.labelObject) graphGroup.remove(ghostElements.node.userData.labelObject);
|
|
11689
|
+
graphGroup.remove(ghostElements.node);
|
|
11690
|
+
}
|
|
11691
|
+
stateRef2.current.ghostElements = { node: null, line: null, aura: null };
|
|
11692
|
+
addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
|
|
11560
11693
|
context.tweenToTarget(finalPosition, 1.2);
|
|
11561
11694
|
setters.setQuestMode({ isActive: false });
|
|
11562
11695
|
setters.setSceneVersion((v) => v + 1);
|
|
11563
11696
|
} catch (error) {
|
|
11564
|
-
console.error("Falha ao salvar
|
|
11697
|
+
console.error("Falha ao salvar Quest na View:", error);
|
|
11565
11698
|
alert("Ocorreu um erro ao criar a Quest.");
|
|
11566
11699
|
}
|
|
11567
11700
|
};
|
|
11701
|
+
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
11702
|
+
const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2, ownerId: ownerId2 } = context;
|
|
11703
|
+
const { sourceNodeData } = stateRef2.current.connection;
|
|
11704
|
+
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
11705
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11706
|
+
return;
|
|
11707
|
+
}
|
|
11708
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id, sceneConfigId2, ownerId2);
|
|
11709
|
+
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id, sceneConfigId2, ownerId2);
|
|
11710
|
+
let parentInfoToSave = sourceParentInfo;
|
|
11711
|
+
const isSourceQuest = sourceParentInfo.parentFileId === sceneConfigId2;
|
|
11712
|
+
const isTargetQuest = targetParentInfo.parentFileId === sceneConfigId2;
|
|
11713
|
+
if (isSourceQuest || isTargetQuest) {
|
|
11714
|
+
parentInfoToSave = { parentFileId: sceneConfigId2, ownerId: ownerId2 };
|
|
11715
|
+
}
|
|
11716
|
+
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11717
|
+
const newLink = {
|
|
11718
|
+
id: `link_${short2.generate()}`,
|
|
11719
|
+
source: sourceNodeData.id,
|
|
11720
|
+
target: targetNodeData.id
|
|
11721
|
+
};
|
|
11722
|
+
try {
|
|
11723
|
+
if (parentFileIdToSave === sceneConfigId2) {
|
|
11724
|
+
const specificParentData = graphDataRef.current[sceneConfigId2];
|
|
11725
|
+
specificParentData.links.push(newLink);
|
|
11726
|
+
const viewFilePayload = {
|
|
11727
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11728
|
+
nodes: sceneDataRef2.current.nodes,
|
|
11729
|
+
links: sceneDataRef2.current.links,
|
|
11730
|
+
quest_nodes: specificParentData.nodes,
|
|
11731
|
+
quest_links: specificParentData.links
|
|
11732
|
+
};
|
|
11733
|
+
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
11734
|
+
} else {
|
|
11735
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
11736
|
+
specificParentData.links.push(newLink);
|
|
11737
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
11738
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
11739
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
11740
|
+
}
|
|
11741
|
+
addNewLinkToScene(stateRef2.current, newLink);
|
|
11742
|
+
} catch (error) {
|
|
11743
|
+
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
11744
|
+
alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
|
|
11745
|
+
}
|
|
11746
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11747
|
+
};
|
|
11568
11748
|
const handleClearAncestryVisuals = useCallback4((ancestryId) => {
|
|
11569
11749
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11570
11750
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
@@ -12813,7 +12993,7 @@ function XViewScene({
|
|
|
12813
12993
|
const allTypes = Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes.flatMap((node) => {
|
|
12814
12994
|
if (Array.isArray(node.type)) return node.type;
|
|
12815
12995
|
return [node.type];
|
|
12816
|
-
})).filter(Boolean);
|
|
12996
|
+
})).filter((t) => Boolean(t) && String(t).toLowerCase() !== "quest");
|
|
12817
12997
|
return [...new Set(allTypes)];
|
|
12818
12998
|
}, [parentDataRef.current, sceneVersion]);
|
|
12819
12999
|
const searchableDbNodes = useMemo12(() => {
|
|
@@ -12832,6 +13012,7 @@ function XViewScene({
|
|
|
12832
13012
|
[actionHandlerContext]
|
|
12833
13013
|
);
|
|
12834
13014
|
const handleSaveCurrentView = useCallback4(async () => {
|
|
13015
|
+
var _a2, _b2, _c2;
|
|
12835
13016
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12836
13017
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12837
13018
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12853,17 +13034,22 @@ function XViewScene({
|
|
|
12853
13034
|
const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
|
|
12854
13035
|
return serializableLinkData;
|
|
12855
13036
|
});
|
|
13037
|
+
sceneDataRef.current.nodes = currentNodes;
|
|
13038
|
+
sceneDataRef.current.links = currentLinks;
|
|
13039
|
+
const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
|
|
12856
13040
|
const sceneFileData = {
|
|
12857
13041
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
12858
13042
|
nodes: currentNodes,
|
|
12859
|
-
links: currentLinks
|
|
13043
|
+
links: currentLinks,
|
|
13044
|
+
quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
|
|
13045
|
+
quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || []
|
|
12860
13046
|
};
|
|
12861
13047
|
try {
|
|
12862
13048
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
12863
13049
|
} catch (error) {
|
|
12864
13050
|
console.error("Erro na chamada de save_view_data:", error);
|
|
12865
13051
|
}
|
|
12866
|
-
}, [sceneSaveUrl, save_view_data]);
|
|
13052
|
+
}, [sceneSaveUrl, save_view_data, sceneConfigId, viewParams == null ? void 0 : viewParams.type]);
|
|
12867
13053
|
const allAvailableNodes = useMemo12(() => {
|
|
12868
13054
|
if (!parentDataRef.current) return [];
|
|
12869
13055
|
return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
@@ -12948,6 +13134,106 @@ function XViewScene({
|
|
|
12948
13134
|
}
|
|
12949
13135
|
}
|
|
12950
13136
|
}, [isInitialized, sceneVersion, focusAncestryId, hasOpenedInitialAncestry, handleStartReadingAncestry]);
|
|
13137
|
+
useEffect21(() => {
|
|
13138
|
+
function handleKeyDown(event) {
|
|
13139
|
+
var _a2, _b2, _c2;
|
|
13140
|
+
const context = actionHandlerContext;
|
|
13141
|
+
if (event.key === "Escape") {
|
|
13142
|
+
if (stateRef.current.connection.isActive) userActionHandlers.handleCancelConnection(context);
|
|
13143
|
+
if (stateRef.current.relink.isActive) userActionHandlers.handleCancelRelink(context);
|
|
13144
|
+
if (stateRef.current.creation.isActive) userActionHandlers.handleCancelCreation(context);
|
|
13145
|
+
if ((_a2 = stateRef.current.versionMode) == null ? void 0 : _a2.isActive) userActionHandlers.handleCancelVersioning(context);
|
|
13146
|
+
if (stateRef.current.ancestry.isActive) {
|
|
13147
|
+
setAncestryMode({ isActive: false, tree: null, selectedParentId: null, isEditMode: false, currentAncestryId: null, ancestryName: "", ancestryDescription: "", ancestryDescriptionSections: [], isAddingNodes: false });
|
|
13148
|
+
if (mountRef.current) mountRef.current.style.cursor = "grab";
|
|
13149
|
+
}
|
|
13150
|
+
if (questMode.isActive) {
|
|
13151
|
+
handleCancelQuest();
|
|
13152
|
+
}
|
|
13153
|
+
if (stateRef.current.selectedNodes.size > 0) {
|
|
13154
|
+
stateRef.current.selectedNodes.clear();
|
|
13155
|
+
}
|
|
13156
|
+
setContextMenu((prev) => prev.visible ? { ...prev, visible: false } : prev);
|
|
13157
|
+
setMultiContextMenu((prev) => ({ ...prev, visible: false }));
|
|
13158
|
+
setRelationshipMenu((prev) => ({ ...prev, visible: false }));
|
|
13159
|
+
}
|
|
13160
|
+
if (event.key.toLowerCase() === "q") {
|
|
13161
|
+
const isUiClear = !stateRef.current.creation.isActive && !stateRef.current.connection.isActive && !stateRef.current.relink.isActive && !stateRef.current.ancestry.isActive && !((_b2 = context.versionMode) == null ? void 0 : _b2.isActive) && !contextMenu.visible && !multiContextMenu.visible && !relationshipMenu.visible && !readingMode.isActive && !isImportModalOpen && !isAncestryBoardOpen && !isSidebarOpen && !detailsNode && !detailsLink && !ancestryLinkDetails && !imageViewer.visible && !editingAncestryRel.visible && !questMode.isActive;
|
|
13162
|
+
if (isUiClear) {
|
|
13163
|
+
const isView = ((_c2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _c2.toLowerCase()) === "view";
|
|
13164
|
+
if (!isView) return;
|
|
13165
|
+
const { graphGroup, glowTexture, controls, nodeObjects } = stateRef.current;
|
|
13166
|
+
if (graphGroup) {
|
|
13167
|
+
let ghostPosition = controls.target.clone();
|
|
13168
|
+
const existingNodes = Object.values(nodeObjects);
|
|
13169
|
+
let isOccupied = true;
|
|
13170
|
+
let radius = 18;
|
|
13171
|
+
let angle = 0;
|
|
13172
|
+
let attempts = 0;
|
|
13173
|
+
const MIN_CLEARANCE = 15;
|
|
13174
|
+
while (isOccupied && attempts < 30) {
|
|
13175
|
+
isOccupied = existingNodes.some((mesh) => mesh.position.distanceTo(ghostPosition) < MIN_CLEARANCE);
|
|
13176
|
+
if (isOccupied) {
|
|
13177
|
+
ghostPosition.x = controls.target.x + Math.cos(angle) * radius;
|
|
13178
|
+
ghostPosition.y = controls.target.y + (Math.random() - 0.5) * 8;
|
|
13179
|
+
ghostPosition.z = controls.target.z + Math.sin(angle) * radius;
|
|
13180
|
+
angle += Math.PI / 3;
|
|
13181
|
+
radius += 2.5;
|
|
13182
|
+
attempts++;
|
|
13183
|
+
}
|
|
13184
|
+
}
|
|
13185
|
+
const ghostData = {
|
|
13186
|
+
id: "ghost_quest",
|
|
13187
|
+
name: "Nova Quest",
|
|
13188
|
+
color: "#64748b",
|
|
13189
|
+
// Cor padrão de "Backlog"
|
|
13190
|
+
size: "medium",
|
|
13191
|
+
intensity: 0,
|
|
13192
|
+
type: ["quest"]
|
|
13193
|
+
};
|
|
13194
|
+
const ghostNode = createNodeMesh(ghostData, ghostPosition, glowTexture);
|
|
13195
|
+
ghostNode.traverse((child) => {
|
|
13196
|
+
if (child.isMesh) {
|
|
13197
|
+
child.material.transparent = true;
|
|
13198
|
+
child.material.opacity = 0.75;
|
|
13199
|
+
}
|
|
13200
|
+
});
|
|
13201
|
+
graphGroup.add(ghostNode);
|
|
13202
|
+
if (ghostNode.userData.labelObject) {
|
|
13203
|
+
graphGroup.add(ghostNode.userData.labelObject);
|
|
13204
|
+
}
|
|
13205
|
+
stateRef.current.ghostElements = {
|
|
13206
|
+
node: ghostNode,
|
|
13207
|
+
line: null,
|
|
13208
|
+
aura: ghostNode.getObjectByName("aura")
|
|
13209
|
+
};
|
|
13210
|
+
context.tweenToTarget(ghostPosition, 1.6);
|
|
13211
|
+
}
|
|
13212
|
+
setQuestMode({ isActive: true });
|
|
13213
|
+
}
|
|
13214
|
+
}
|
|
13215
|
+
}
|
|
13216
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
13217
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
13218
|
+
}, [
|
|
13219
|
+
contextMenu.visible,
|
|
13220
|
+
multiContextMenu.visible,
|
|
13221
|
+
relationshipMenu.visible,
|
|
13222
|
+
readingMode.isActive,
|
|
13223
|
+
isImportModalOpen,
|
|
13224
|
+
isAncestryBoardOpen,
|
|
13225
|
+
isSidebarOpen,
|
|
13226
|
+
detailsNode,
|
|
13227
|
+
detailsLink,
|
|
13228
|
+
ancestryLinkDetails,
|
|
13229
|
+
imageViewer.visible,
|
|
13230
|
+
editingAncestryRel.visible,
|
|
13231
|
+
questMode.isActive,
|
|
13232
|
+
viewParams,
|
|
13233
|
+
actionHandlerContext,
|
|
13234
|
+
handleCancelQuest
|
|
13235
|
+
// <-- handleCancelQuest adicionado aqui
|
|
13236
|
+
]);
|
|
12951
13237
|
if (isLoading || status === "loading" || permissionStatus === "loading") {
|
|
12952
13238
|
return /* @__PURE__ */ React24.createElement(LoadingScreen, null);
|
|
12953
13239
|
}
|
|
@@ -13042,7 +13328,10 @@ function XViewScene({
|
|
|
13042
13328
|
InSceneQuestForm,
|
|
13043
13329
|
{
|
|
13044
13330
|
onSave: (data) => handleSaveQuestNode(actionHandlerContext, data),
|
|
13045
|
-
onCancel:
|
|
13331
|
+
onCancel: handleCancelQuest,
|
|
13332
|
+
onNameChange: handleGhostNodeNameChange,
|
|
13333
|
+
onColorChange: handleGhostNodeColorChange,
|
|
13334
|
+
onSizeChange: handleGhostNodeSizeChange,
|
|
13046
13335
|
style: { position: "absolute", left: `16px`, top: `16px`, zIndex: 20, transition: "opacity 200ms ease-out" },
|
|
13047
13336
|
refEl: formRef,
|
|
13048
13337
|
onOpenImageViewer: handleOpenImageViewer,
|
|
@@ -13334,6 +13623,12 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13334
13623
|
}
|
|
13335
13624
|
const sceneData = sceneResponse.data;
|
|
13336
13625
|
const parentDbObjects = sceneData.parent_dbs || [];
|
|
13626
|
+
if (type && type.toLowerCase().includes("database")) {
|
|
13627
|
+
const selfExists = parentDbObjects.some((db) => String(db.db_id) === String(scene_config));
|
|
13628
|
+
if (!selfExists) {
|
|
13629
|
+
parentDbObjects.push({ db_id: scene_config, owner_id });
|
|
13630
|
+
}
|
|
13631
|
+
}
|
|
13337
13632
|
const parentResponsesPromises = parentDbObjects.map(
|
|
13338
13633
|
(db_info) => db_services.get_file(`x_view_dbs/${db_info.owner_id}/${db_info.db_id}`)
|
|
13339
13634
|
);
|
|
@@ -13351,6 +13646,13 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13351
13646
|
);
|
|
13352
13647
|
}
|
|
13353
13648
|
}
|
|
13649
|
+
if (type && type.toLowerCase() === "view") {
|
|
13650
|
+
parentData[scene_config] = {
|
|
13651
|
+
dataset_name: "Quests Internas (View)",
|
|
13652
|
+
nodes: sceneData.quest_nodes || [],
|
|
13653
|
+
links: sceneData.quest_links || []
|
|
13654
|
+
};
|
|
13655
|
+
}
|
|
13354
13656
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
13355
13657
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13356
13658
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
@@ -13360,7 +13662,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13360
13662
|
if (nodeTypes.includes("quest")) {
|
|
13361
13663
|
return sceneNode;
|
|
13362
13664
|
}
|
|
13363
|
-
|
|
13665
|
+
const dbNode = parentNodeMap.get(String(sceneNode.id));
|
|
13666
|
+
if (dbNode) {
|
|
13667
|
+
return { ...sceneNode, ...dbNode };
|
|
13668
|
+
}
|
|
13669
|
+
return null;
|
|
13364
13670
|
}).filter(Boolean);
|
|
13365
13671
|
const validNodeIdsInScene = new Set(validatedNodes.map((node) => String(node.id)));
|
|
13366
13672
|
const validatedLinks = (sceneData.links || []).filter((sceneLink) => {
|