@lv-x-software-house/x_view 1.2.4-dev.2 → 1.2.4-dev.5
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 +107 -28
- package/dist/index.mjs +114 -35
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7969,7 +7969,7 @@ function InSceneQuestForm({
|
|
|
7969
7969
|
/* @__PURE__ */ import_react16.default.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
7970
7970
|
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Review" }, "Review"),
|
|
7971
7971
|
/* @__PURE__ */ import_react16.default.createElement("option", { value: "Done" }, "Done")
|
|
7972
|
-
)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
7972
|
+
)), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Nome da Quest"), /* @__PURE__ */ import_react16.default.createElement("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative w-full bg-slate-800/70 p-1.5 min-h-[42px] flex flex-wrap gap-1.5 rounded-lg border border-white/10 focus-within:ring-2 focus-within:ring-indigo-400/60 transition-all" }, types.map((t, index) => /* @__PURE__ */ import_react16.default.createElement("span", { key: index, className: `flex items-center gap-1 px-1.5 py-0.5 rounded-md text-xs font-medium border ${t === "quest" ? "bg-sky-500/20 text-sky-200 border-sky-500/30" : "bg-indigo-500/30 text-indigo-100 border-indigo-500/20"}` }, t, t !== "quest" && /* @__PURE__ */ import_react16.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react16.default.createElement(import_fi14.FiX, { size: 12 })))), /* @__PURE__ */ import_react16.default.createElement(
|
|
7973
7973
|
"input",
|
|
7974
7974
|
{
|
|
7975
7975
|
type: "text",
|
|
@@ -10872,20 +10872,6 @@ function XViewScene({
|
|
|
10872
10872
|
const context = actionHandlerContext;
|
|
10873
10873
|
if (connection.isActive) {
|
|
10874
10874
|
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
10875
|
await userActionHandlers.handleCompleteConnection(context, hoveredNode.userData);
|
|
10890
10876
|
} else {
|
|
10891
10877
|
userActionHandlers.handleCancelConnection(context);
|
|
@@ -11491,6 +11477,10 @@ function XViewScene({
|
|
|
11491
11477
|
// <-- Adicionado
|
|
11492
11478
|
sceneSaveUrl,
|
|
11493
11479
|
// <-- Adicionado
|
|
11480
|
+
sceneConfigId,
|
|
11481
|
+
// <-- Adicionado
|
|
11482
|
+
ownerId,
|
|
11483
|
+
// <-- Adicionado
|
|
11494
11484
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11495
11485
|
// <-- Adicionado
|
|
11496
11486
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
@@ -11524,9 +11514,11 @@ function XViewScene({
|
|
|
11524
11514
|
versionMode,
|
|
11525
11515
|
questMode,
|
|
11526
11516
|
sceneSaveUrl,
|
|
11517
|
+
sceneConfigId,
|
|
11518
|
+
ownerId,
|
|
11527
11519
|
viewParams == null ? void 0 : viewParams.type,
|
|
11528
|
-
tweenToTarget,
|
|
11529
11520
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11521
|
+
tweenToTarget,
|
|
11530
11522
|
handleVersionTimeline,
|
|
11531
11523
|
save_view_data,
|
|
11532
11524
|
get_single_parent_file,
|
|
@@ -11539,32 +11531,110 @@ function XViewScene({
|
|
|
11539
11531
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11540
11532
|
};
|
|
11541
11533
|
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11542
|
-
const { sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType } = context;
|
|
11543
|
-
if (!
|
|
11534
|
+
const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
|
|
11535
|
+
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11544
11536
|
const newNode = {
|
|
11545
11537
|
id: import_short_uuid2.default.generate(),
|
|
11546
11538
|
...newQuestData,
|
|
11547
11539
|
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11548
11540
|
};
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11541
|
+
if (!graphDataRef.current[sceneConfigId2]) {
|
|
11542
|
+
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11543
|
+
}
|
|
11544
|
+
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
11545
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
11546
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((mesh) => {
|
|
11547
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = mesh.userData;
|
|
11548
|
+
return rest;
|
|
11549
|
+
});
|
|
11550
|
+
currentVisualNodes.push(newNode);
|
|
11551
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((line) => {
|
|
11552
|
+
const { sourceNode, targetNode, ...rest } = line.userData;
|
|
11553
|
+
return rest;
|
|
11554
|
+
});
|
|
11555
|
+
const sceneFileData = {
|
|
11556
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11557
|
+
nodes: currentVisualNodes,
|
|
11558
|
+
links: currentVisualLinks,
|
|
11559
|
+
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
11560
|
+
quest_links: graphDataRef.current[sceneConfigId2].links
|
|
11552
11561
|
};
|
|
11553
11562
|
try {
|
|
11554
|
-
await actions.save_view_data(sceneSaveUrl2,
|
|
11555
|
-
|
|
11563
|
+
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
11564
|
+
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
11565
|
+
parentFileId: sceneConfigId2,
|
|
11566
|
+
ownerId: ownerId2,
|
|
11567
|
+
datasetName: "Quests Internas (View)"
|
|
11568
|
+
});
|
|
11556
11569
|
const basePosition = stateRef2.current.controls.target.clone();
|
|
11557
|
-
const offset = new THREE3.Vector3((Math.random() - 0.5) *
|
|
11570
|
+
const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
|
|
11558
11571
|
const finalPosition = basePosition.add(offset);
|
|
11559
|
-
|
|
11572
|
+
addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
|
|
11560
11573
|
context.tweenToTarget(finalPosition, 1.2);
|
|
11561
11574
|
setters.setQuestMode({ isActive: false });
|
|
11562
11575
|
setters.setSceneVersion((v) => v + 1);
|
|
11563
11576
|
} catch (error) {
|
|
11564
|
-
console.error("Falha ao salvar
|
|
11577
|
+
console.error("Falha ao salvar Quest na View:", error);
|
|
11565
11578
|
alert("Ocorreu um erro ao criar a Quest.");
|
|
11566
11579
|
}
|
|
11567
11580
|
};
|
|
11581
|
+
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
11582
|
+
const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2 } = context;
|
|
11583
|
+
const { sourceNodeData } = stateRef2.current.connection;
|
|
11584
|
+
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
11585
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id);
|
|
11589
|
+
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id);
|
|
11590
|
+
let parentInfoToSave = sourceParentInfo;
|
|
11591
|
+
if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
|
|
11592
|
+
parentInfoToSave = targetParentInfo;
|
|
11593
|
+
} else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
|
|
11594
|
+
parentInfoToSave = sourceParentInfo;
|
|
11595
|
+
}
|
|
11596
|
+
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11597
|
+
const newLink = {
|
|
11598
|
+
id: `link_${import_short_uuid2.default.generate()}`,
|
|
11599
|
+
source: sourceNodeData.id,
|
|
11600
|
+
target: targetNodeData.id
|
|
11601
|
+
};
|
|
11602
|
+
try {
|
|
11603
|
+
if (parentFileIdToSave === sceneConfigId2) {
|
|
11604
|
+
const specificParentData = graphDataRef.current[sceneConfigId2];
|
|
11605
|
+
specificParentData.links.push(newLink);
|
|
11606
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((m) => {
|
|
11607
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = m.userData;
|
|
11608
|
+
return rest;
|
|
11609
|
+
});
|
|
11610
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((l) => {
|
|
11611
|
+
const { sourceNode, targetNode, ...rest } = l.userData;
|
|
11612
|
+
return rest;
|
|
11613
|
+
});
|
|
11614
|
+
currentVisualLinks.push(newLink);
|
|
11615
|
+
const viewFilePayload = {
|
|
11616
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11617
|
+
nodes: currentVisualNodes,
|
|
11618
|
+
links: currentVisualLinks,
|
|
11619
|
+
quest_nodes: specificParentData.nodes,
|
|
11620
|
+
quest_links: specificParentData.links
|
|
11621
|
+
// Salva a conexão aqui!
|
|
11622
|
+
};
|
|
11623
|
+
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
11624
|
+
} else {
|
|
11625
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
11626
|
+
specificParentData.links.push(newLink);
|
|
11627
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
11628
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
11629
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
11630
|
+
}
|
|
11631
|
+
addNewLinkToScene(stateRef2.current, newLink);
|
|
11632
|
+
} catch (error) {
|
|
11633
|
+
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
11634
|
+
alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
|
|
11635
|
+
}
|
|
11636
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11637
|
+
};
|
|
11568
11638
|
const handleClearAncestryVisuals = (0, import_react25.useCallback)((ancestryId) => {
|
|
11569
11639
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11570
11640
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
@@ -12832,6 +12902,7 @@ function XViewScene({
|
|
|
12832
12902
|
[actionHandlerContext]
|
|
12833
12903
|
);
|
|
12834
12904
|
const handleSaveCurrentView = (0, import_react25.useCallback)(async () => {
|
|
12905
|
+
var _a2, _b2;
|
|
12835
12906
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12836
12907
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12837
12908
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12856,14 +12927,17 @@ function XViewScene({
|
|
|
12856
12927
|
const sceneFileData = {
|
|
12857
12928
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
12858
12929
|
nodes: currentNodes,
|
|
12859
|
-
links: currentLinks
|
|
12930
|
+
links: currentLinks,
|
|
12931
|
+
// --- ADICIONE ESTAS DUAS LINHAS PARA PRESERVAR A FONTE DA VERDADE ---
|
|
12932
|
+
quest_nodes: ((_a2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _a2.nodes) || [],
|
|
12933
|
+
quest_links: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.links) || []
|
|
12860
12934
|
};
|
|
12861
12935
|
try {
|
|
12862
12936
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
12863
12937
|
} catch (error) {
|
|
12864
12938
|
console.error("Erro na chamada de save_view_data:", error);
|
|
12865
12939
|
}
|
|
12866
|
-
}, [sceneSaveUrl, save_view_data]);
|
|
12940
|
+
}, [sceneSaveUrl, save_view_data, sceneConfigId]);
|
|
12867
12941
|
const allAvailableNodes = (0, import_react25.useMemo)(() => {
|
|
12868
12942
|
if (!parentDataRef.current) return [];
|
|
12869
12943
|
return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
@@ -13351,6 +13425,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13351
13425
|
);
|
|
13352
13426
|
}
|
|
13353
13427
|
}
|
|
13428
|
+
parentData[scene_config] = {
|
|
13429
|
+
dataset_name: "Quests Internas (View)",
|
|
13430
|
+
nodes: sceneData.quest_nodes || [],
|
|
13431
|
+
links: sceneData.quest_links || []
|
|
13432
|
+
};
|
|
13354
13433
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
13355
13434
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13356
13435
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
package/dist/index.mjs
CHANGED
|
@@ -3097,7 +3097,7 @@ function useResizablePanel({ initialWidth, minWidth, maxWidth }) {
|
|
|
3097
3097
|
|
|
3098
3098
|
// src/components/CustomPropertyDisplay.jsx
|
|
3099
3099
|
import React3, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
3100
|
-
import { FiCheck, FiX
|
|
3100
|
+
import { FiCheck, FiX, FiEdit3, FiTrash2, FiExternalLink, FiFileText, FiChevronDown, FiUpload, FiLoader } from "react-icons/fi";
|
|
3101
3101
|
function CustomPropertyDisplay({
|
|
3102
3102
|
prop,
|
|
3103
3103
|
onUpdate,
|
|
@@ -3388,7 +3388,7 @@ function CustomPropertyDisplay({
|
|
|
3388
3388
|
default:
|
|
3389
3389
|
return /* @__PURE__ */ React3.createElement("input", { type: "text", placeholder: "Valor", value: tempProp.value, onChange: (e) => handlePropChange("value", e.target.value), className: baseInput });
|
|
3390
3390
|
}
|
|
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(
|
|
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(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
3392
|
};
|
|
3393
3393
|
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
3394
|
switch (prop.type) {
|
|
@@ -7024,7 +7024,7 @@ function CreateAncestryPanel({
|
|
|
7024
7024
|
|
|
7025
7025
|
// src/components/ImageViewer.jsx
|
|
7026
7026
|
import React11, { useState as useState12, useEffect as useEffect11, useLayoutEffect as useLayoutEffect2, useCallback as useCallback3 } from "react";
|
|
7027
|
-
import { FiX as
|
|
7027
|
+
import { FiX as FiX2, FiChevronLeft as FiChevronLeft3, FiChevronRight as FiChevronRight5 } from "react-icons/fi";
|
|
7028
7028
|
function ImageViewer({ data, onClose }) {
|
|
7029
7029
|
var _a;
|
|
7030
7030
|
const { images = [], startIndex = 0, visible } = data;
|
|
@@ -7109,7 +7109,7 @@ function ImageViewer({ data, onClose }) {
|
|
|
7109
7109
|
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
7110
|
"aria-label": "Fechar"
|
|
7111
7111
|
},
|
|
7112
|
-
/* @__PURE__ */ React11.createElement(
|
|
7112
|
+
/* @__PURE__ */ React11.createElement(FiX2, null)
|
|
7113
7113
|
),
|
|
7114
7114
|
/* @__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
7115
|
"img",
|
|
@@ -7245,7 +7245,7 @@ function ColorPicker({ color, onChange, disabled }) {
|
|
|
7245
7245
|
}
|
|
7246
7246
|
|
|
7247
7247
|
// src/components/InSceneCreationForm.jsx
|
|
7248
|
-
import { FiPlus as FiPlus3, FiMaximize2, FiX as
|
|
7248
|
+
import { FiPlus as FiPlus3, FiMaximize2, FiX as FiX3, FiCheck as FiCheck7, FiEdit2 as FiEdit24, FiSun, FiChevronDown as FiChevronDown4 } from "react-icons/fi";
|
|
7249
7249
|
function InSceneCreationForm({
|
|
7250
7250
|
onSave,
|
|
7251
7251
|
onCancel,
|
|
@@ -7463,7 +7463,7 @@ function InSceneCreationForm({
|
|
|
7463
7463
|
onClick: () => handleRemoveType(index),
|
|
7464
7464
|
className: "hover:text-white transition-colors"
|
|
7465
7465
|
},
|
|
7466
|
-
/* @__PURE__ */ React13.createElement(
|
|
7466
|
+
/* @__PURE__ */ React13.createElement(FiX3, { size: 12 })
|
|
7467
7467
|
))), /* @__PURE__ */ React13.createElement(
|
|
7468
7468
|
"input",
|
|
7469
7469
|
{
|
|
@@ -7837,7 +7837,7 @@ function InSceneVersionForm({
|
|
|
7837
7837
|
|
|
7838
7838
|
// src/components/InSceneQuestForm.jsx
|
|
7839
7839
|
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";
|
|
7840
|
+
import { FiPlus as FiPlus5, FiCheck as FiCheck9, FiEdit2 as FiEdit26, FiTarget, FiX as FiX4 } from "react-icons/fi";
|
|
7841
7841
|
var QUEST_STATUS_COLORS = {
|
|
7842
7842
|
"Backlog": "#64748b",
|
|
7843
7843
|
// Slate (Cinza azulado)
|
|
@@ -7956,7 +7956,7 @@ function InSceneQuestForm({
|
|
|
7956
7956
|
/* @__PURE__ */ React15.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
7957
7957
|
/* @__PURE__ */ React15.createElement("option", { value: "Review" }, "Review"),
|
|
7958
7958
|
/* @__PURE__ */ React15.createElement("option", { value: "Done" }, "Done")
|
|
7959
|
-
)), /* @__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("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ 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(
|
|
7959
|
+
)), /* @__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("input", { required: true, type: "text", placeholder: "Ex.: Refatorar M\xF3dulo X", value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-2 focus:ring-indigo-400/60" })), /* @__PURE__ */ 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
7960
|
"input",
|
|
7961
7961
|
{
|
|
7962
7962
|
type: "text",
|
|
@@ -10872,20 +10872,6 @@ function XViewScene({
|
|
|
10872
10872
|
const context = actionHandlerContext;
|
|
10873
10873
|
if (connection.isActive) {
|
|
10874
10874
|
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
10875
|
await userActionHandlers.handleCompleteConnection(context, hoveredNode.userData);
|
|
10890
10876
|
} else {
|
|
10891
10877
|
userActionHandlers.handleCancelConnection(context);
|
|
@@ -11491,6 +11477,10 @@ function XViewScene({
|
|
|
11491
11477
|
// <-- Adicionado
|
|
11492
11478
|
sceneSaveUrl,
|
|
11493
11479
|
// <-- Adicionado
|
|
11480
|
+
sceneConfigId,
|
|
11481
|
+
// <-- Adicionado
|
|
11482
|
+
ownerId,
|
|
11483
|
+
// <-- Adicionado
|
|
11494
11484
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
11495
11485
|
// <-- Adicionado
|
|
11496
11486
|
userId: (_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id,
|
|
@@ -11524,9 +11514,11 @@ function XViewScene({
|
|
|
11524
11514
|
versionMode,
|
|
11525
11515
|
questMode,
|
|
11526
11516
|
sceneSaveUrl,
|
|
11517
|
+
sceneConfigId,
|
|
11518
|
+
ownerId,
|
|
11527
11519
|
viewParams == null ? void 0 : viewParams.type,
|
|
11528
|
-
tweenToTarget,
|
|
11529
11520
|
(_a = session == null ? void 0 : session.user) == null ? void 0 : _a.id,
|
|
11521
|
+
tweenToTarget,
|
|
11530
11522
|
handleVersionTimeline,
|
|
11531
11523
|
save_view_data,
|
|
11532
11524
|
get_single_parent_file,
|
|
@@ -11539,32 +11531,110 @@ function XViewScene({
|
|
|
11539
11531
|
userActionHandlers.handleStartVersioning(actionHandlerContext, nodeData);
|
|
11540
11532
|
};
|
|
11541
11533
|
const handleSaveQuestNode = async (context, newQuestData) => {
|
|
11542
|
-
const { sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType } = context;
|
|
11543
|
-
if (!
|
|
11534
|
+
const { graphDataRef, sceneDataRef: sceneDataRef2, stateRef: stateRef2, setters, actions, sceneSaveUrl: sceneSaveUrl2, viewType, sceneConfigId: sceneConfigId2, ownerId: ownerId2 } = context;
|
|
11535
|
+
if (!graphDataRef.current || (viewType == null ? void 0 : viewType.toLowerCase()) !== "view") return;
|
|
11544
11536
|
const newNode = {
|
|
11545
11537
|
id: short2.generate(),
|
|
11546
11538
|
...newQuestData,
|
|
11547
11539
|
type: ["quest", ...newQuestData.type.filter((t) => t !== "quest")]
|
|
11548
11540
|
};
|
|
11549
|
-
|
|
11550
|
-
|
|
11551
|
-
|
|
11541
|
+
if (!graphDataRef.current[sceneConfigId2]) {
|
|
11542
|
+
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11543
|
+
}
|
|
11544
|
+
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
11545
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
11546
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((mesh) => {
|
|
11547
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = mesh.userData;
|
|
11548
|
+
return rest;
|
|
11549
|
+
});
|
|
11550
|
+
currentVisualNodes.push(newNode);
|
|
11551
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((line) => {
|
|
11552
|
+
const { sourceNode, targetNode, ...rest } = line.userData;
|
|
11553
|
+
return rest;
|
|
11554
|
+
});
|
|
11555
|
+
const sceneFileData = {
|
|
11556
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11557
|
+
nodes: currentVisualNodes,
|
|
11558
|
+
links: currentVisualLinks,
|
|
11559
|
+
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
11560
|
+
quest_links: graphDataRef.current[sceneConfigId2].links
|
|
11552
11561
|
};
|
|
11553
11562
|
try {
|
|
11554
|
-
await actions.save_view_data(sceneSaveUrl2,
|
|
11555
|
-
|
|
11563
|
+
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
11564
|
+
stateRef2.current.nodeIdToParentFileMap.set(String(newNode.id), {
|
|
11565
|
+
parentFileId: sceneConfigId2,
|
|
11566
|
+
ownerId: ownerId2,
|
|
11567
|
+
datasetName: "Quests Internas (View)"
|
|
11568
|
+
});
|
|
11556
11569
|
const basePosition = stateRef2.current.controls.target.clone();
|
|
11557
|
-
const offset = new THREE3.Vector3((Math.random() - 0.5) *
|
|
11570
|
+
const offset = new THREE3.Vector3((Math.random() - 0.5) * 15, (Math.random() - 0.5) * 5, 0);
|
|
11558
11571
|
const finalPosition = basePosition.add(offset);
|
|
11559
|
-
|
|
11572
|
+
addStandaloneNodeToScene(stateRef2.current, newNode, finalPosition);
|
|
11560
11573
|
context.tweenToTarget(finalPosition, 1.2);
|
|
11561
11574
|
setters.setQuestMode({ isActive: false });
|
|
11562
11575
|
setters.setSceneVersion((v) => v + 1);
|
|
11563
11576
|
} catch (error) {
|
|
11564
|
-
console.error("Falha ao salvar
|
|
11577
|
+
console.error("Falha ao salvar Quest na View:", error);
|
|
11565
11578
|
alert("Ocorreu um erro ao criar a Quest.");
|
|
11566
11579
|
}
|
|
11567
11580
|
};
|
|
11581
|
+
userActionHandlers.handleCompleteConnection = async (context, targetNodeData) => {
|
|
11582
|
+
const { stateRef: stateRef2, graphDataRef, sceneDataRef: sceneDataRef2, sceneConfigId: sceneConfigId2, sceneSaveUrl: sceneSaveUrl2 } = context;
|
|
11583
|
+
const { sourceNodeData } = stateRef2.current.connection;
|
|
11584
|
+
if (!graphDataRef.current || !sceneDataRef2.current || !sourceNodeData || !targetNodeData) {
|
|
11585
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11586
|
+
return;
|
|
11587
|
+
}
|
|
11588
|
+
const sourceParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, sourceNodeData.id);
|
|
11589
|
+
const targetParentInfo = getParentFileInfoForNode(graphDataRef.current, sceneDataRef2.current, targetNodeData.id);
|
|
11590
|
+
let parentInfoToSave = sourceParentInfo;
|
|
11591
|
+
if (sourceParentInfo.parentFileId === sceneConfigId2 && targetParentInfo.parentFileId !== sceneConfigId2) {
|
|
11592
|
+
parentInfoToSave = targetParentInfo;
|
|
11593
|
+
} else if (targetParentInfo.parentFileId === sceneConfigId2 && sourceParentInfo.parentFileId !== sceneConfigId2) {
|
|
11594
|
+
parentInfoToSave = sourceParentInfo;
|
|
11595
|
+
}
|
|
11596
|
+
const { parentFileId: parentFileIdToSave, ownerId: ownerIdToSave } = parentInfoToSave;
|
|
11597
|
+
const newLink = {
|
|
11598
|
+
id: `link_${short2.generate()}`,
|
|
11599
|
+
source: sourceNodeData.id,
|
|
11600
|
+
target: targetNodeData.id
|
|
11601
|
+
};
|
|
11602
|
+
try {
|
|
11603
|
+
if (parentFileIdToSave === sceneConfigId2) {
|
|
11604
|
+
const specificParentData = graphDataRef.current[sceneConfigId2];
|
|
11605
|
+
specificParentData.links.push(newLink);
|
|
11606
|
+
const currentVisualNodes = Object.values(stateRef2.current.nodeObjects).map((m) => {
|
|
11607
|
+
const { _baseEmissiveIntensity, labelObject, labelOffset, timelineIntervalBar, timelineEndLabel, ...rest } = m.userData;
|
|
11608
|
+
return rest;
|
|
11609
|
+
});
|
|
11610
|
+
const currentVisualLinks = stateRef2.current.allLinks.map((l) => {
|
|
11611
|
+
const { sourceNode, targetNode, ...rest } = l.userData;
|
|
11612
|
+
return rest;
|
|
11613
|
+
});
|
|
11614
|
+
currentVisualLinks.push(newLink);
|
|
11615
|
+
const viewFilePayload = {
|
|
11616
|
+
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
11617
|
+
nodes: currentVisualNodes,
|
|
11618
|
+
links: currentVisualLinks,
|
|
11619
|
+
quest_nodes: specificParentData.nodes,
|
|
11620
|
+
quest_links: specificParentData.links
|
|
11621
|
+
// Salva a conexão aqui!
|
|
11622
|
+
};
|
|
11623
|
+
await context.actions.save_view_data(sceneSaveUrl2, viewFilePayload);
|
|
11624
|
+
} else {
|
|
11625
|
+
const specificParentData = JSON.parse(JSON.stringify(graphDataRef.current[parentFileIdToSave]));
|
|
11626
|
+
specificParentData.links.push(newLink);
|
|
11627
|
+
const filenameForSpecificParent = `x_view_dbs/${ownerIdToSave}/${parentFileIdToSave}`;
|
|
11628
|
+
await context.actions.save_view_data(filenameForSpecificParent, specificParentData);
|
|
11629
|
+
graphDataRef.current[parentFileIdToSave] = specificParentData;
|
|
11630
|
+
}
|
|
11631
|
+
addNewLinkToScene(stateRef2.current, newLink);
|
|
11632
|
+
} catch (error) {
|
|
11633
|
+
console.error("Falha ao salvar a nova conex\xE3o:", error);
|
|
11634
|
+
alert("Ocorreu um erro ao salvar a nova conex\xE3o.");
|
|
11635
|
+
}
|
|
11636
|
+
userActionHandlers.handleCancelConnection(context);
|
|
11637
|
+
};
|
|
11568
11638
|
const handleClearAncestryVisuals = useCallback4((ancestryId) => {
|
|
11569
11639
|
const { renderedAncestries, ancestryGroup } = stateRef.current;
|
|
11570
11640
|
const renderIndex = renderedAncestries.findIndex((a) => String(a.id) === String(ancestryId));
|
|
@@ -12832,6 +12902,7 @@ function XViewScene({
|
|
|
12832
12902
|
[actionHandlerContext]
|
|
12833
12903
|
);
|
|
12834
12904
|
const handleSaveCurrentView = useCallback4(async () => {
|
|
12905
|
+
var _a2, _b2;
|
|
12835
12906
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
12836
12907
|
if (!nodeObjects || !allLinks || !sceneSaveUrl || !parentDataRef.current) {
|
|
12837
12908
|
console.warn("N\xE3o \xE9 poss\xEDvel salvar a cena: estado n\xE3o inicializado ou URL de salvamento ausente.");
|
|
@@ -12856,14 +12927,17 @@ function XViewScene({
|
|
|
12856
12927
|
const sceneFileData = {
|
|
12857
12928
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
12858
12929
|
nodes: currentNodes,
|
|
12859
|
-
links: currentLinks
|
|
12930
|
+
links: currentLinks,
|
|
12931
|
+
// --- ADICIONE ESTAS DUAS LINHAS PARA PRESERVAR A FONTE DA VERDADE ---
|
|
12932
|
+
quest_nodes: ((_a2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _a2.nodes) || [],
|
|
12933
|
+
quest_links: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.links) || []
|
|
12860
12934
|
};
|
|
12861
12935
|
try {
|
|
12862
12936
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
12863
12937
|
} catch (error) {
|
|
12864
12938
|
console.error("Erro na chamada de save_view_data:", error);
|
|
12865
12939
|
}
|
|
12866
|
-
}, [sceneSaveUrl, save_view_data]);
|
|
12940
|
+
}, [sceneSaveUrl, save_view_data, sceneConfigId]);
|
|
12867
12941
|
const allAvailableNodes = useMemo12(() => {
|
|
12868
12942
|
if (!parentDataRef.current) return [];
|
|
12869
12943
|
return Object.values(parentDataRef.current).flatMap((fileData) => fileData.nodes || []);
|
|
@@ -13351,6 +13425,11 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
13351
13425
|
);
|
|
13352
13426
|
}
|
|
13353
13427
|
}
|
|
13428
|
+
parentData[scene_config] = {
|
|
13429
|
+
dataset_name: "Quests Internas (View)",
|
|
13430
|
+
nodes: sceneData.quest_nodes || [],
|
|
13431
|
+
links: sceneData.quest_links || []
|
|
13432
|
+
};
|
|
13354
13433
|
const allNodes = Object.values(parentData).flatMap((db) => db.nodes || []);
|
|
13355
13434
|
const allLinks = Object.values(parentData).flatMap((db) => db.links || []);
|
|
13356
13435
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.4-dev.
|
|
3
|
+
"version": "1.2.4-dev.5",
|
|
4
4
|
"description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
|
|
5
5
|
"author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
|
|
6
6
|
"license": "UNLICENSED",
|