@lv-x-software-house/x_view 1.2.4-dev.25 → 1.2.4-dev.27
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 +62 -20
- package/dist/index.mjs +62 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -505,7 +505,11 @@ function XViewSidebar({
|
|
|
505
505
|
let pool = base;
|
|
506
506
|
const qNorm = normalize(query);
|
|
507
507
|
if (qNorm) {
|
|
508
|
-
pool = pool.filter((n) =>
|
|
508
|
+
pool = pool.filter((n) => {
|
|
509
|
+
const matchName = normalize((n == null ? void 0 : n.name) || "").includes(qNorm);
|
|
510
|
+
const matchRawTitle = n.is_quest && n.raw_title ? normalize(n.raw_title).includes(qNorm) : false;
|
|
511
|
+
return matchName || matchRawTitle;
|
|
512
|
+
});
|
|
509
513
|
}
|
|
510
514
|
if (activeFilters.length > 0) {
|
|
511
515
|
pool = pool.filter((node) => {
|
|
@@ -2552,6 +2556,13 @@ var userActionHandlers = {
|
|
|
2552
2556
|
try {
|
|
2553
2557
|
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2554
2558
|
if (isView && parentFileId === context.sceneConfigId) {
|
|
2559
|
+
const visualNodeIndex = sceneDataRef.current.nodes.findIndex((n) => String(n.id) === String(nodeToSave.id));
|
|
2560
|
+
if (visualNodeIndex > -1) {
|
|
2561
|
+
sceneDataRef.current.nodes[visualNodeIndex] = {
|
|
2562
|
+
...sceneDataRef.current.nodes[visualNodeIndex],
|
|
2563
|
+
...nodeToSave
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2555
2566
|
const viewFilePayload = {
|
|
2556
2567
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2557
2568
|
nodes: sceneDataRef.current.nodes,
|
|
@@ -2895,7 +2906,8 @@ var IGNORED_KEYS = [
|
|
|
2895
2906
|
"selectedAbstractionParentId",
|
|
2896
2907
|
"isAddingAbstractionNodes",
|
|
2897
2908
|
"status",
|
|
2898
|
-
"is_quest"
|
|
2909
|
+
"is_quest",
|
|
2910
|
+
"raw_title"
|
|
2899
2911
|
];
|
|
2900
2912
|
function extractCustomPropsFromNode(node) {
|
|
2901
2913
|
const customPropTypes = node._customPropTypes || {};
|
|
@@ -8091,7 +8103,7 @@ function InSceneQuestForm({
|
|
|
8091
8103
|
},
|
|
8092
8104
|
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"
|
|
8093
8105
|
}
|
|
8094
|
-
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }
|
|
8106
|
+
), /* @__PURE__ */ import_react16.default.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }), /* @__PURE__ */ import_react16.default.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ import_react16.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react16.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react16.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react16.default.createElement(
|
|
8095
8107
|
"button",
|
|
8096
8108
|
{
|
|
8097
8109
|
type: "button",
|
|
@@ -8691,7 +8703,12 @@ function QuestDetailsPanel({
|
|
|
8691
8703
|
userRole,
|
|
8692
8704
|
currentDatasetName
|
|
8693
8705
|
}) {
|
|
8694
|
-
|
|
8706
|
+
var _a;
|
|
8707
|
+
const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
|
|
8708
|
+
const [rawTitle, setRawTitle] = (0, import_react18.useState)(initialRawTitle);
|
|
8709
|
+
const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
|
|
8710
|
+
const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
|
|
8711
|
+
const standardizedName = questPrefix ? `${questPrefix} - \xBB ${rawTitle || "Sem t\xEDtulo"}` : rawTitle;
|
|
8695
8712
|
const [types, setTypes] = (0, import_react18.useState)((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
|
|
8696
8713
|
const [typeInput, setTypeInput] = (0, import_react18.useState)("");
|
|
8697
8714
|
const [status, setStatus] = (0, import_react18.useState)((node == null ? void 0 : node.status) ?? "Backlog");
|
|
@@ -8720,15 +8737,17 @@ function QuestDetailsPanel({
|
|
|
8720
8737
|
const propsEndRef = (0, import_react18.useRef)(null);
|
|
8721
8738
|
const canEdit = userRole !== "viewer";
|
|
8722
8739
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
8723
|
-
const handleImageClickFromText = (url,
|
|
8740
|
+
const handleImageClickFromText = (url, name) => {
|
|
8724
8741
|
if (onOpenImageViewer) {
|
|
8725
|
-
onOpenImageViewer([{ name:
|
|
8742
|
+
onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
|
|
8726
8743
|
}
|
|
8727
8744
|
};
|
|
8728
8745
|
(0, import_react18.useEffect)(() => {
|
|
8746
|
+
var _a2;
|
|
8729
8747
|
if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
|
|
8730
8748
|
prevNodeIdRef.current = node == null ? void 0 : node.id;
|
|
8731
|
-
|
|
8749
|
+
const newRawTitle = (node == null ? void 0 : node.raw_title) || (((_a2 = node == null ? void 0 : node.name) == null ? void 0 : _a2.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
|
|
8750
|
+
setRawTitle(newRawTitle);
|
|
8732
8751
|
setTypes((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
|
|
8733
8752
|
setStatus((node == null ? void 0 : node.status) ?? "Backlog");
|
|
8734
8753
|
setSize((node == null ? void 0 : node.size) ?? "medium");
|
|
@@ -8763,9 +8782,10 @@ function QuestDetailsPanel({
|
|
|
8763
8782
|
};
|
|
8764
8783
|
const swallow = (e) => e.stopPropagation();
|
|
8765
8784
|
const handleNameChange = (e) => {
|
|
8766
|
-
const
|
|
8767
|
-
|
|
8768
|
-
|
|
8785
|
+
const val = e.target.value;
|
|
8786
|
+
setRawTitle(val);
|
|
8787
|
+
const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
|
|
8788
|
+
onNameChange == null ? void 0 : onNameChange(node.id, newStandardName, val);
|
|
8769
8789
|
};
|
|
8770
8790
|
const handleSizeChange = (newSize) => {
|
|
8771
8791
|
setSize(newSize);
|
|
@@ -8801,8 +8821,8 @@ function QuestDetailsPanel({
|
|
|
8801
8821
|
const newProp = createNewCustomProperty(customProps);
|
|
8802
8822
|
setCustomProps((p) => [...p, newProp]);
|
|
8803
8823
|
setTimeout(() => {
|
|
8804
|
-
var
|
|
8805
|
-
(
|
|
8824
|
+
var _a2;
|
|
8825
|
+
(_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
8806
8826
|
}, 100);
|
|
8807
8827
|
};
|
|
8808
8828
|
const handleRemoveProp = (i) => {
|
|
@@ -8824,14 +8844,15 @@ function QuestDetailsPanel({
|
|
|
8824
8844
|
triggerAutoSave({ description: newDescription });
|
|
8825
8845
|
};
|
|
8826
8846
|
const handleSave = async (keepOpen = false, overrides = {}) => {
|
|
8827
|
-
const
|
|
8847
|
+
const currentRawTitle = overrides.rawTitle !== void 0 ? overrides.rawTitle : rawTitle;
|
|
8848
|
+
const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
|
|
8828
8849
|
const currentTypes = overrides.types !== void 0 ? overrides.types : types;
|
|
8829
8850
|
const currentDescription = overrides.description !== void 0 ? overrides.description : description;
|
|
8830
8851
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8831
8852
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8832
8853
|
const currentStatus = overrides.status !== void 0 ? overrides.status : status;
|
|
8833
|
-
if (!
|
|
8834
|
-
alert("O campo '
|
|
8854
|
+
if (!currentRawTitle.trim() || currentTypes.length === 0) {
|
|
8855
|
+
alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8835
8856
|
return;
|
|
8836
8857
|
}
|
|
8837
8858
|
setIsSaving(true);
|
|
@@ -8840,7 +8861,10 @@ function QuestDetailsPanel({
|
|
|
8840
8861
|
const processedSections = processDescriptionForSave(currentDescription, currentExistingSections);
|
|
8841
8862
|
const dataToSave = {
|
|
8842
8863
|
id: node.id,
|
|
8843
|
-
name:
|
|
8864
|
+
name: currentStandardName.trim(),
|
|
8865
|
+
// Salva o nome completo formatado
|
|
8866
|
+
raw_title: currentRawTitle.trim(),
|
|
8867
|
+
// Salva o título simples
|
|
8844
8868
|
type: currentTypes,
|
|
8845
8869
|
color: QUEST_STATUS_COLORS2[currentStatus],
|
|
8846
8870
|
status: currentStatus,
|
|
@@ -8895,7 +8919,7 @@ function QuestDetailsPanel({
|
|
|
8895
8919
|
isReadMode ? /* @__PURE__ */ import_react18.default.createElement(
|
|
8896
8920
|
DescriptionReadModePanel,
|
|
8897
8921
|
{
|
|
8898
|
-
title:
|
|
8922
|
+
title: standardizedName || (node == null ? void 0 : node.name),
|
|
8899
8923
|
description,
|
|
8900
8924
|
savedSections: existingSections,
|
|
8901
8925
|
onBack: () => setIsReadMode(false),
|
|
@@ -8913,7 +8937,16 @@ function QuestDetailsPanel({
|
|
|
8913
8937
|
onImageClick: handleImageClickFromText,
|
|
8914
8938
|
onSaveDescription: handleSaveDescriptionInline
|
|
8915
8939
|
}
|
|
8916
|
-
) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiLink, { size: 12 }))), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" },
|
|
8940
|
+
) : /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ import_react18.default.createElement("div", null, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiTarget, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiCheck, { size: 12 }) : /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiLink, { size: 12 }))), /* @__PURE__ */ import_react18.default.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ import_react18.default.createElement("button", { onClick: handleCancel, disabled: isSaving, 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 disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ import_react18.default.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ import_react18.default.createElement(
|
|
8941
|
+
"input",
|
|
8942
|
+
{
|
|
8943
|
+
type: "text",
|
|
8944
|
+
value: rawTitle,
|
|
8945
|
+
onChange: handleNameChange,
|
|
8946
|
+
readOnly: !canEdit,
|
|
8947
|
+
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
|
|
8948
|
+
}
|
|
8949
|
+
), /* @__PURE__ */ import_react18.default.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }), /* @__PURE__ */ import_react18.default.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react18.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react18.default.createElement(
|
|
8917
8950
|
"button",
|
|
8918
8951
|
{
|
|
8919
8952
|
type: "button",
|
|
@@ -8935,7 +8968,7 @@ function QuestDetailsPanel({
|
|
|
8935
8968
|
},
|
|
8936
8969
|
/* @__PURE__ */ import_react18.default.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
|
|
8937
8970
|
s
|
|
8938
|
-
)))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "
|
|
8971
|
+
)))))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ import_react18.default.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ import_react18.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 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ import_react18.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, canEdit && t !== "quest" && /* @__PURE__ */ import_react18.default.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ import_react18.default.createElement(import_fi16.FiX, { size: 12 })))), canEdit && /* @__PURE__ */ import_react18.default.createElement(
|
|
8939
8972
|
"input",
|
|
8940
8973
|
{
|
|
8941
8974
|
type: "text",
|
|
@@ -11809,7 +11842,7 @@ function XViewScene({
|
|
|
11809
11842
|
graphGroup.add(newLabel);
|
|
11810
11843
|
ghostNode.userData.labelObject = newLabel;
|
|
11811
11844
|
};
|
|
11812
|
-
const handleDetailNodeNameChange = (nodeId, newName) => {
|
|
11845
|
+
const handleDetailNodeNameChange = (nodeId, newName, newRawTitle) => {
|
|
11813
11846
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
11814
11847
|
const { graphGroup } = stateRef.current;
|
|
11815
11848
|
if (!mesh || !graphGroup) return;
|
|
@@ -11823,6 +11856,9 @@ function XViewScene({
|
|
|
11823
11856
|
graphGroup.add(newLabel);
|
|
11824
11857
|
mesh.userData.labelObject = newLabel;
|
|
11825
11858
|
mesh.userData.name = newName;
|
|
11859
|
+
if (newRawTitle !== void 0) {
|
|
11860
|
+
mesh.userData.raw_title = newRawTitle;
|
|
11861
|
+
}
|
|
11826
11862
|
};
|
|
11827
11863
|
const handleDetailNodeColorChange = (nodeId, newColor) => {
|
|
11828
11864
|
var _a2;
|
|
@@ -11997,6 +12033,7 @@ function XViewScene({
|
|
|
11997
12033
|
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11998
12034
|
}
|
|
11999
12035
|
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
12036
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
12000
12037
|
const sceneFileData = {
|
|
12001
12038
|
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
12002
12039
|
nodes: sceneDataRef2.current.nodes,
|
|
@@ -14013,8 +14050,13 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
14013
14050
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
14014
14051
|
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
14015
14052
|
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
14053
|
+
var _a2, _b2;
|
|
14016
14054
|
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
14017
14055
|
if (nodeTypes.includes("quest")) {
|
|
14056
|
+
const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
|
|
14057
|
+
if (dbQuestNode) {
|
|
14058
|
+
return { ...sceneNode, ...dbQuestNode };
|
|
14059
|
+
}
|
|
14018
14060
|
return sceneNode;
|
|
14019
14061
|
}
|
|
14020
14062
|
const dbNode = parentNodeMap.get(String(sceneNode.id));
|
package/dist/index.mjs
CHANGED
|
@@ -461,7 +461,11 @@ function XViewSidebar({
|
|
|
461
461
|
let pool = base;
|
|
462
462
|
const qNorm = normalize(query);
|
|
463
463
|
if (qNorm) {
|
|
464
|
-
pool = pool.filter((n) =>
|
|
464
|
+
pool = pool.filter((n) => {
|
|
465
|
+
const matchName = normalize((n == null ? void 0 : n.name) || "").includes(qNorm);
|
|
466
|
+
const matchRawTitle = n.is_quest && n.raw_title ? normalize(n.raw_title).includes(qNorm) : false;
|
|
467
|
+
return matchName || matchRawTitle;
|
|
468
|
+
});
|
|
465
469
|
}
|
|
466
470
|
if (activeFilters.length > 0) {
|
|
467
471
|
pool = pool.filter((node) => {
|
|
@@ -2508,6 +2512,13 @@ var userActionHandlers = {
|
|
|
2508
2512
|
try {
|
|
2509
2513
|
const isView = ((_a = context.viewType) == null ? void 0 : _a.toLowerCase()) === "view";
|
|
2510
2514
|
if (isView && parentFileId === context.sceneConfigId) {
|
|
2515
|
+
const visualNodeIndex = sceneDataRef.current.nodes.findIndex((n) => String(n.id) === String(nodeToSave.id));
|
|
2516
|
+
if (visualNodeIndex > -1) {
|
|
2517
|
+
sceneDataRef.current.nodes[visualNodeIndex] = {
|
|
2518
|
+
...sceneDataRef.current.nodes[visualNodeIndex],
|
|
2519
|
+
...nodeToSave
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2511
2522
|
const viewFilePayload = {
|
|
2512
2523
|
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
2513
2524
|
nodes: sceneDataRef.current.nodes,
|
|
@@ -2851,7 +2862,8 @@ var IGNORED_KEYS = [
|
|
|
2851
2862
|
"selectedAbstractionParentId",
|
|
2852
2863
|
"isAddingAbstractionNodes",
|
|
2853
2864
|
"status",
|
|
2854
|
-
"is_quest"
|
|
2865
|
+
"is_quest",
|
|
2866
|
+
"raw_title"
|
|
2855
2867
|
];
|
|
2856
2868
|
function extractCustomPropsFromNode(node) {
|
|
2857
2869
|
const customPropTypes = node._customPropTypes || {};
|
|
@@ -8078,7 +8090,7 @@ function InSceneQuestForm({
|
|
|
8078
8090
|
},
|
|
8079
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"
|
|
8080
8092
|
}
|
|
8081
|
-
), /* @__PURE__ */ React15.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ React15.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }
|
|
8093
|
+
), /* @__PURE__ */ React15.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ React15.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }), /* @__PURE__ */ React15.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ React15.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React15.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React15.createElement("div", { className: "relative" }, /* @__PURE__ */ React15.createElement(
|
|
8082
8094
|
"button",
|
|
8083
8095
|
{
|
|
8084
8096
|
type: "button",
|
|
@@ -8678,7 +8690,12 @@ function QuestDetailsPanel({
|
|
|
8678
8690
|
userRole,
|
|
8679
8691
|
currentDatasetName
|
|
8680
8692
|
}) {
|
|
8681
|
-
|
|
8693
|
+
var _a;
|
|
8694
|
+
const initialRawTitle = (node == null ? void 0 : node.raw_title) || (((_a = node == null ? void 0 : node.name) == null ? void 0 : _a.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
|
|
8695
|
+
const [rawTitle, setRawTitle] = useState18(initialRawTitle);
|
|
8696
|
+
const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
|
|
8697
|
+
const questPrefix = prefixParts.length > 1 ? prefixParts[0] : "";
|
|
8698
|
+
const standardizedName = questPrefix ? `${questPrefix} - \xBB ${rawTitle || "Sem t\xEDtulo"}` : rawTitle;
|
|
8682
8699
|
const [types, setTypes] = useState18((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
|
|
8683
8700
|
const [typeInput, setTypeInput] = useState18("");
|
|
8684
8701
|
const [status, setStatus] = useState18((node == null ? void 0 : node.status) ?? "Backlog");
|
|
@@ -8707,15 +8724,17 @@ function QuestDetailsPanel({
|
|
|
8707
8724
|
const propsEndRef = useRef14(null);
|
|
8708
8725
|
const canEdit = userRole !== "viewer";
|
|
8709
8726
|
const availableImages = customProps.filter((p) => p.type === "images").flatMap((p) => Array.isArray(p.value) ? p.value : []).filter((img) => img.value && img.value.trim() !== "");
|
|
8710
|
-
const handleImageClickFromText = (url,
|
|
8727
|
+
const handleImageClickFromText = (url, name) => {
|
|
8711
8728
|
if (onOpenImageViewer) {
|
|
8712
|
-
onOpenImageViewer([{ name:
|
|
8729
|
+
onOpenImageViewer([{ name: name || "Imagem", value: url }], 0);
|
|
8713
8730
|
}
|
|
8714
8731
|
};
|
|
8715
8732
|
useEffect16(() => {
|
|
8733
|
+
var _a2;
|
|
8716
8734
|
if ((node == null ? void 0 : node.id) !== prevNodeIdRef.current) {
|
|
8717
8735
|
prevNodeIdRef.current = node == null ? void 0 : node.id;
|
|
8718
|
-
|
|
8736
|
+
const newRawTitle = (node == null ? void 0 : node.raw_title) || (((_a2 = node == null ? void 0 : node.name) == null ? void 0 : _a2.includes(" - \xBB ")) ? node.name.split(" - \xBB ")[1] : node == null ? void 0 : node.name) || "";
|
|
8737
|
+
setRawTitle(newRawTitle);
|
|
8719
8738
|
setTypes((node == null ? void 0 : node.type) ? Array.isArray(node.type) ? node.type : [node.type] : ["quest"]);
|
|
8720
8739
|
setStatus((node == null ? void 0 : node.status) ?? "Backlog");
|
|
8721
8740
|
setSize((node == null ? void 0 : node.size) ?? "medium");
|
|
@@ -8750,9 +8769,10 @@ function QuestDetailsPanel({
|
|
|
8750
8769
|
};
|
|
8751
8770
|
const swallow = (e) => e.stopPropagation();
|
|
8752
8771
|
const handleNameChange = (e) => {
|
|
8753
|
-
const
|
|
8754
|
-
|
|
8755
|
-
|
|
8772
|
+
const val = e.target.value;
|
|
8773
|
+
setRawTitle(val);
|
|
8774
|
+
const newStandardName = questPrefix ? `${questPrefix} - \xBB ${val || "Sem t\xEDtulo"}` : val;
|
|
8775
|
+
onNameChange == null ? void 0 : onNameChange(node.id, newStandardName, val);
|
|
8756
8776
|
};
|
|
8757
8777
|
const handleSizeChange = (newSize) => {
|
|
8758
8778
|
setSize(newSize);
|
|
@@ -8788,8 +8808,8 @@ function QuestDetailsPanel({
|
|
|
8788
8808
|
const newProp = createNewCustomProperty(customProps);
|
|
8789
8809
|
setCustomProps((p) => [...p, newProp]);
|
|
8790
8810
|
setTimeout(() => {
|
|
8791
|
-
var
|
|
8792
|
-
(
|
|
8811
|
+
var _a2;
|
|
8812
|
+
(_a2 = propsEndRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
8793
8813
|
}, 100);
|
|
8794
8814
|
};
|
|
8795
8815
|
const handleRemoveProp = (i) => {
|
|
@@ -8811,14 +8831,15 @@ function QuestDetailsPanel({
|
|
|
8811
8831
|
triggerAutoSave({ description: newDescription });
|
|
8812
8832
|
};
|
|
8813
8833
|
const handleSave = async (keepOpen = false, overrides = {}) => {
|
|
8814
|
-
const
|
|
8834
|
+
const currentRawTitle = overrides.rawTitle !== void 0 ? overrides.rawTitle : rawTitle;
|
|
8835
|
+
const currentStandardName = questPrefix ? `${questPrefix} - \xBB ${currentRawTitle || "Sem t\xEDtulo"}` : currentRawTitle;
|
|
8815
8836
|
const currentTypes = overrides.types !== void 0 ? overrides.types : types;
|
|
8816
8837
|
const currentDescription = overrides.description !== void 0 ? overrides.description : description;
|
|
8817
8838
|
const currentCustomProps = overrides.customProps !== void 0 ? overrides.customProps : customProps;
|
|
8818
8839
|
const currentExistingSections = overrides.existingSections !== void 0 ? overrides.existingSections : existingSections;
|
|
8819
8840
|
const currentStatus = overrides.status !== void 0 ? overrides.status : status;
|
|
8820
|
-
if (!
|
|
8821
|
-
alert("O campo '
|
|
8841
|
+
if (!currentRawTitle.trim() || currentTypes.length === 0) {
|
|
8842
|
+
alert("O campo 'T\xEDtulo' e pelo menos um 'Tipo' s\xE3o obrigat\xF3rios.");
|
|
8822
8843
|
return;
|
|
8823
8844
|
}
|
|
8824
8845
|
setIsSaving(true);
|
|
@@ -8827,7 +8848,10 @@ function QuestDetailsPanel({
|
|
|
8827
8848
|
const processedSections = processDescriptionForSave(currentDescription, currentExistingSections);
|
|
8828
8849
|
const dataToSave = {
|
|
8829
8850
|
id: node.id,
|
|
8830
|
-
name:
|
|
8851
|
+
name: currentStandardName.trim(),
|
|
8852
|
+
// Salva o nome completo formatado
|
|
8853
|
+
raw_title: currentRawTitle.trim(),
|
|
8854
|
+
// Salva o título simples
|
|
8831
8855
|
type: currentTypes,
|
|
8832
8856
|
color: QUEST_STATUS_COLORS2[currentStatus],
|
|
8833
8857
|
status: currentStatus,
|
|
@@ -8882,7 +8906,7 @@ function QuestDetailsPanel({
|
|
|
8882
8906
|
isReadMode ? /* @__PURE__ */ React17.createElement(
|
|
8883
8907
|
DescriptionReadModePanel,
|
|
8884
8908
|
{
|
|
8885
|
-
title:
|
|
8909
|
+
title: standardizedName || (node == null ? void 0 : node.name),
|
|
8886
8910
|
description,
|
|
8887
8911
|
savedSections: existingSections,
|
|
8888
8912
|
onBack: () => setIsReadMode(false),
|
|
@@ -8900,7 +8924,16 @@ function QuestDetailsPanel({
|
|
|
8900
8924
|
onImageClick: handleImageClickFromText,
|
|
8901
8925
|
onSaveDescription: handleSaveDescriptionInline
|
|
8902
8926
|
}
|
|
8903
|
-
) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement(FiTarget2, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React17.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React17.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React17.createElement(FiLink6, { size: 12 }))), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" },
|
|
8927
|
+
) : /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement("div", { className: "h-[2px]", style: { background: `linear-gradient(to right, transparent, ${QUEST_STATUS_COLORS2[status]}, transparent)` } }), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pt-5 pb-3 flex items-start justify-between gap-4" }, /* @__PURE__ */ React17.createElement("div", null, /* @__PURE__ */ React17.createElement("div", { className: "flex items-center gap-2 mb-1" }, /* @__PURE__ */ React17.createElement(FiTarget2, { className: "text-sky-400", size: 14 }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs/relaxed text-slate-300" }, "Detalhes da Quest"), /* @__PURE__ */ React17.createElement("button", { onClick: handleCopyLink, className: `ml-1 p-1 transition-colors ${isLinkCopied ? "text-green-400" : "text-slate-400 hover:text-sky-400"}`, title: isLinkCopied ? "Link Copiado!" : "Copiar link para esta Quest" }, isLinkCopied ? /* @__PURE__ */ React17.createElement(FiCheck11, { size: 12 }) : /* @__PURE__ */ React17.createElement(FiLink6, { size: 12 }))), /* @__PURE__ */ React17.createElement("h2", { className: "text-xl sm:text-2xl font-semibold tracking-tight" }, standardizedName || (node == null ? void 0 : node.name))), /* @__PURE__ */ React17.createElement("button", { onClick: handleCancel, disabled: isSaving, 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 disabled:opacity-50", title: "Cancelar" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "px-6 pb-28 overflow-y-auto overscroll-contain space-y-4 max-h-[68vh] custom-scrollbar" }, /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "T\xEDtulo da Quest"), /* @__PURE__ */ React17.createElement(
|
|
8928
|
+
"input",
|
|
8929
|
+
{
|
|
8930
|
+
type: "text",
|
|
8931
|
+
value: rawTitle,
|
|
8932
|
+
onChange: handleNameChange,
|
|
8933
|
+
readOnly: !canEdit,
|
|
8934
|
+
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 focus:outline-none ${canEdit ? "focus:ring-2 focus:ring-indigo-400/60" : "cursor-default text-slate-400"}`
|
|
8935
|
+
}
|
|
8936
|
+
), /* @__PURE__ */ React17.createElement("div", { className: "pt-1 flex items-center gap-1.5" }, /* @__PURE__ */ React17.createElement("span", { className: "text-[10px] uppercase font-bold text-slate-500 tracking-wider" }), /* @__PURE__ */ React17.createElement("p", { className: "text-xs text-indigo-300 font-medium truncate", title: standardizedName }, standardizedName))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React17.createElement("div", { className: "relative" }, /* @__PURE__ */ React17.createElement(
|
|
8904
8937
|
"button",
|
|
8905
8938
|
{
|
|
8906
8939
|
type: "button",
|
|
@@ -8922,7 +8955,7 @@ function QuestDetailsPanel({
|
|
|
8922
8955
|
},
|
|
8923
8956
|
/* @__PURE__ */ React17.createElement("span", { className: "w-3 h-3 rounded-full", style: { backgroundColor: QUEST_STATUS_COLORS2[s] } }),
|
|
8924
8957
|
s
|
|
8925
|
-
)))))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "
|
|
8958
|
+
)))))), /* @__PURE__ */ React17.createElement("div", { className: "space-y-1.5" }, /* @__PURE__ */ React17.createElement("label", { className: "text-xs text-slate-300" }, "Tipos Adicionais"), /* @__PURE__ */ React17.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 ${canEdit ? "focus-within:ring-2 focus-within:ring-indigo-400/60" : ""} transition-all` }, types.map((t, index) => /* @__PURE__ */ React17.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, canEdit && t !== "quest" && /* @__PURE__ */ React17.createElement("button", { type: "button", onClick: () => handleRemoveType(index), className: "hover:text-white transition-colors" }, /* @__PURE__ */ React17.createElement(FiX6, { size: 12 })))), canEdit && /* @__PURE__ */ React17.createElement(
|
|
8926
8959
|
"input",
|
|
8927
8960
|
{
|
|
8928
8961
|
type: "text",
|
|
@@ -11809,7 +11842,7 @@ function XViewScene({
|
|
|
11809
11842
|
graphGroup.add(newLabel);
|
|
11810
11843
|
ghostNode.userData.labelObject = newLabel;
|
|
11811
11844
|
};
|
|
11812
|
-
const handleDetailNodeNameChange = (nodeId, newName) => {
|
|
11845
|
+
const handleDetailNodeNameChange = (nodeId, newName, newRawTitle) => {
|
|
11813
11846
|
const mesh = stateRef.current.nodeObjects[String(nodeId)];
|
|
11814
11847
|
const { graphGroup } = stateRef.current;
|
|
11815
11848
|
if (!mesh || !graphGroup) return;
|
|
@@ -11823,6 +11856,9 @@ function XViewScene({
|
|
|
11823
11856
|
graphGroup.add(newLabel);
|
|
11824
11857
|
mesh.userData.labelObject = newLabel;
|
|
11825
11858
|
mesh.userData.name = newName;
|
|
11859
|
+
if (newRawTitle !== void 0) {
|
|
11860
|
+
mesh.userData.raw_title = newRawTitle;
|
|
11861
|
+
}
|
|
11826
11862
|
};
|
|
11827
11863
|
const handleDetailNodeColorChange = (nodeId, newColor) => {
|
|
11828
11864
|
var _a2;
|
|
@@ -11997,6 +12033,7 @@ function XViewScene({
|
|
|
11997
12033
|
graphDataRef.current[sceneConfigId2] = { nodes: [], links: [] };
|
|
11998
12034
|
}
|
|
11999
12035
|
graphDataRef.current[sceneConfigId2].nodes.push(newNode);
|
|
12036
|
+
sceneDataRef2.current.nodes.push(newNode);
|
|
12000
12037
|
const sceneFileData = {
|
|
12001
12038
|
parent_dbs: sceneDataRef2.current.parent_dbs,
|
|
12002
12039
|
nodes: sceneDataRef2.current.nodes,
|
|
@@ -14013,8 +14050,13 @@ async function get_scene_view_data_logic(db_services, scene_config, owner_id, ty
|
|
|
14013
14050
|
const parentNodeMap = new Map(allNodes.map((node) => [String(node.id), node]));
|
|
14014
14051
|
const parentLinkMap = new Map(allLinks.map((link) => [`${link.source}-${link.target}`, link]));
|
|
14015
14052
|
const validatedNodes = (sceneData.nodes || []).map((sceneNode) => {
|
|
14053
|
+
var _a2, _b2;
|
|
14016
14054
|
const nodeTypes = Array.isArray(sceneNode.type) ? sceneNode.type : [sceneNode.type];
|
|
14017
14055
|
if (nodeTypes.includes("quest")) {
|
|
14056
|
+
const dbQuestNode = (_b2 = (_a2 = parentData[scene_config]) == null ? void 0 : _a2.nodes) == null ? void 0 : _b2.find((qn) => String(qn.id) === String(sceneNode.id));
|
|
14057
|
+
if (dbQuestNode) {
|
|
14058
|
+
return { ...sceneNode, ...dbQuestNode };
|
|
14059
|
+
}
|
|
14018
14060
|
return sceneNode;
|
|
14019
14061
|
}
|
|
14020
14062
|
const dbNode = parentNodeMap.get(String(sceneNode.id));
|
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.27",
|
|
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",
|