@lv-x-software-house/x_view 1.2.5-dev.45 → 1.2.5-dev.47
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 +351 -29
- package/dist/index.mjs +351 -29
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -625,12 +625,16 @@ function XViewSidebar({
|
|
|
625
625
|
userRole,
|
|
626
626
|
viewMembers = [],
|
|
627
627
|
onActivateQuestLens = () => {
|
|
628
|
+
},
|
|
629
|
+
milestones = [],
|
|
630
|
+
onUpdateMilestones = () => {
|
|
628
631
|
}
|
|
629
632
|
}) {
|
|
630
633
|
const [query, setQuery] = (0, import_react2.useState)("");
|
|
631
634
|
const [showList, setShowList] = (0, import_react2.useState)(false);
|
|
632
635
|
const [selectedNodeId, setSelectedNodeId] = (0, import_react2.useState)(null);
|
|
633
636
|
const [isSaving, setIsSaving] = (0, import_react2.useState)(false);
|
|
637
|
+
const [newMilestoneName, setNewMilestoneName] = (0, import_react2.useState)("");
|
|
634
638
|
const [activeFilters, setActiveFilters] = (0, import_react2.useState)([]);
|
|
635
639
|
const [isFilterMenuOpen, setIsFilterMenuOpen] = (0, import_react2.useState)(false);
|
|
636
640
|
const [filterCategory, setFilterCategory] = (0, import_react2.useState)("Type");
|
|
@@ -842,6 +846,28 @@ function XViewSidebar({
|
|
|
842
846
|
setIsTypeDropdownOpen(false);
|
|
843
847
|
}
|
|
844
848
|
};
|
|
849
|
+
const handleAddMilestone = () => {
|
|
850
|
+
if (!newMilestoneName.trim()) return;
|
|
851
|
+
const newMilestone = {
|
|
852
|
+
id: `ms_${Date.now()}`,
|
|
853
|
+
name: newMilestoneName.trim(),
|
|
854
|
+
status: "active"
|
|
855
|
+
};
|
|
856
|
+
onUpdateMilestones([...milestones, newMilestone]);
|
|
857
|
+
setNewMilestoneName("");
|
|
858
|
+
};
|
|
859
|
+
const handleToggleMilestoneStatus = (id) => {
|
|
860
|
+
const updated = milestones.map(
|
|
861
|
+
(ms) => ms.id === id ? { ...ms, status: ms.status === "active" ? "inactive" : "active" } : ms
|
|
862
|
+
);
|
|
863
|
+
onUpdateMilestones(updated);
|
|
864
|
+
};
|
|
865
|
+
const handleRemoveMilestone = (id) => {
|
|
866
|
+
var _a;
|
|
867
|
+
if (!confirm(`Deseja remover o milestone "${(_a = milestones.find((m) => m.id === id)) == null ? void 0 : _a.name}"?`)) return;
|
|
868
|
+
const updated = milestones.filter((ms) => ms.id !== id);
|
|
869
|
+
onUpdateMilestones(updated);
|
|
870
|
+
};
|
|
845
871
|
const ToggleButton = /* @__PURE__ */ import_react2.default.createElement(
|
|
846
872
|
"button",
|
|
847
873
|
{
|
|
@@ -1098,11 +1124,59 @@ function XViewSidebar({
|
|
|
1098
1124
|
onClick: () => {
|
|
1099
1125
|
onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
|
|
1100
1126
|
setIsQuestLensMenuOpen(false);
|
|
1127
|
+
onToggle(false);
|
|
1101
1128
|
},
|
|
1102
1129
|
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95"
|
|
1103
1130
|
},
|
|
1104
1131
|
"Aplicar Lente"
|
|
1105
|
-
)))))
|
|
1132
|
+
))))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ import_react2.default.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones")), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ import_react2.default.createElement(
|
|
1133
|
+
"input",
|
|
1134
|
+
{
|
|
1135
|
+
type: "text",
|
|
1136
|
+
value: newMilestoneName,
|
|
1137
|
+
onChange: (e) => setNewMilestoneName(e.target.value),
|
|
1138
|
+
onKeyDown: (e) => e.key === "Enter" && handleAddMilestone(),
|
|
1139
|
+
placeholder: "Novo Milestone...",
|
|
1140
|
+
className: "flex-1 bg-slate-900/50 border border-white/10 rounded-md px-2 py-1.5 text-xs text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500/50"
|
|
1141
|
+
}
|
|
1142
|
+
), /* @__PURE__ */ import_react2.default.createElement(
|
|
1143
|
+
"button",
|
|
1144
|
+
{
|
|
1145
|
+
onClick: handleAddMilestone,
|
|
1146
|
+
disabled: !newMilestoneName.trim(),
|
|
1147
|
+
className: "p-1.5 rounded-md bg-indigo-500/10 hover:bg-indigo-500/20 border border-indigo-500/30 text-indigo-300 disabled:opacity-30 transition-colors"
|
|
1148
|
+
},
|
|
1149
|
+
/* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))
|
|
1150
|
+
)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "space-y-1.5 max-h-[200px] overflow-y-auto custom-scrollbar pr-1" }, milestones.length > 0 ? milestones.map((ms) => /* @__PURE__ */ import_react2.default.createElement(
|
|
1151
|
+
"div",
|
|
1152
|
+
{
|
|
1153
|
+
key: ms.id,
|
|
1154
|
+
className: `group flex items-center justify-between px-2.5 py-2 rounded-lg border transition-all ${ms.status === "active" ? "bg-indigo-500/5 border-indigo-500/20" : "bg-slate-900/30 border-white/5 opacity-60"}`
|
|
1155
|
+
},
|
|
1156
|
+
/* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react2.default.createElement(
|
|
1157
|
+
"div",
|
|
1158
|
+
{
|
|
1159
|
+
className: `w-1.5 h-1.5 rounded-full shrink-0 ${ms.status === "active" ? "bg-indigo-400 shadow-[0_0_8px_rgba(129,140,248,0.5)]" : "bg-slate-600"}`
|
|
1160
|
+
}
|
|
1161
|
+
), /* @__PURE__ */ import_react2.default.createElement("span", { className: `text-[11px] truncate font-medium ${ms.status === "active" ? "text-slate-100" : "text-slate-500 line-through"}` }, ms.name)),
|
|
1162
|
+
/* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react2.default.createElement(
|
|
1163
|
+
"button",
|
|
1164
|
+
{
|
|
1165
|
+
onClick: () => handleToggleMilestoneStatus(ms.id),
|
|
1166
|
+
className: `p-1 rounded hover:bg-white/10 transition-colors ${ms.status === "active" ? "text-slate-400" : "text-indigo-400"}`,
|
|
1167
|
+
title: ms.status === "active" ? "Inativar" : "Ativar"
|
|
1168
|
+
},
|
|
1169
|
+
ms.status === "active" ? /* @__PURE__ */ import_react2.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react2.default.createElement("rect", { x: "6", y: "4", width: "4", height: "16" }), /* @__PURE__ */ import_react2.default.createElement("rect", { x: "14", y: "4", width: "4", height: "16" })) : /* @__PURE__ */ import_react2.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react2.default.createElement("polygon", { points: "5 3 19 12 5 21 5 3" }))
|
|
1170
|
+
), /* @__PURE__ */ import_react2.default.createElement(
|
|
1171
|
+
"button",
|
|
1172
|
+
{
|
|
1173
|
+
onClick: () => handleRemoveMilestone(ms.id),
|
|
1174
|
+
className: "p-1 rounded hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-colors",
|
|
1175
|
+
title: "Remover"
|
|
1176
|
+
},
|
|
1177
|
+
/* @__PURE__ */ import_react2.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react2.default.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ import_react2.default.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__ */ import_react2.default.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ import_react2.default.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" }))
|
|
1178
|
+
))
|
|
1179
|
+
)) : /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-[10px] text-slate-600 text-center py-2 italic font-light italic" }, "Nenhum milestone definido")))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ import_react2.default.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o")), ability.can("update", "Scene") && /* @__PURE__ */ import_react2.default.createElement(
|
|
1106
1180
|
"button",
|
|
1107
1181
|
{
|
|
1108
1182
|
onClick: handleSaveClick,
|
|
@@ -2331,7 +2405,8 @@ var userActionHandlers = {
|
|
|
2331
2405
|
nodes: sceneDataRef.current.nodes,
|
|
2332
2406
|
links: sceneDataRef.current.links,
|
|
2333
2407
|
quest_nodes: specificParentData.nodes,
|
|
2334
|
-
quest_links: specificParentData.links
|
|
2408
|
+
quest_links: specificParentData.links,
|
|
2409
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2335
2410
|
};
|
|
2336
2411
|
await context.actions.save_view_data(
|
|
2337
2412
|
context.sceneSaveUrl,
|
|
@@ -2589,7 +2664,8 @@ var userActionHandlers = {
|
|
|
2589
2664
|
nodes: sceneDataRef.current.nodes,
|
|
2590
2665
|
links: sceneDataRef.current.links,
|
|
2591
2666
|
quest_nodes: specificParentData.nodes,
|
|
2592
|
-
quest_links: specificParentData.links
|
|
2667
|
+
quest_links: specificParentData.links,
|
|
2668
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2593
2669
|
};
|
|
2594
2670
|
await context.actions.save_view_data(
|
|
2595
2671
|
context.sceneSaveUrl,
|
|
@@ -2745,7 +2821,8 @@ var userActionHandlers = {
|
|
|
2745
2821
|
nodes: sceneDataRef.current.nodes,
|
|
2746
2822
|
links: sceneDataRef.current.links,
|
|
2747
2823
|
quest_nodes: data.nodes,
|
|
2748
|
-
quest_links: data.links
|
|
2824
|
+
quest_links: data.links,
|
|
2825
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2749
2826
|
};
|
|
2750
2827
|
return context.actions.save_view_data(
|
|
2751
2828
|
context.sceneSaveUrl,
|
|
@@ -3359,6 +3436,7 @@ var userActionHandlers = {
|
|
|
3359
3436
|
links: sceneDataRef.current.links,
|
|
3360
3437
|
quest_nodes: specificParentData.nodes,
|
|
3361
3438
|
quest_links: specificParentData.links,
|
|
3439
|
+
milestones: sceneDataRef.current.milestones || [],
|
|
3362
3440
|
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
3363
3441
|
};
|
|
3364
3442
|
await context.actions.save_view_data(
|
|
@@ -3431,7 +3509,8 @@ var userActionHandlers = {
|
|
|
3431
3509
|
links: sceneDataRef.current.links,
|
|
3432
3510
|
quest_nodes: specificParentData.nodes,
|
|
3433
3511
|
quest_links: specificParentData.links,
|
|
3434
|
-
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
3512
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
3513
|
+
milestones: sceneDataRef.current.milestones || []
|
|
3435
3514
|
};
|
|
3436
3515
|
await context.actions.save_view_data(
|
|
3437
3516
|
context.sceneSaveUrl,
|
|
@@ -9467,11 +9546,15 @@ function InSceneQuestForm({
|
|
|
9467
9546
|
questCounter = 1,
|
|
9468
9547
|
// NOVA PROP
|
|
9469
9548
|
viewMembers = [],
|
|
9470
|
-
session = null
|
|
9549
|
+
session = null,
|
|
9550
|
+
milestones = [],
|
|
9551
|
+
onUpdateMilestones = () => {
|
|
9552
|
+
}
|
|
9471
9553
|
}) {
|
|
9472
|
-
var _a, _b;
|
|
9554
|
+
var _a, _b, _c;
|
|
9473
9555
|
const [name, setName] = (0, import_react17.useState)("");
|
|
9474
9556
|
const [assigneeId, setAssigneeId] = (0, import_react17.useState)("");
|
|
9557
|
+
const [milestoneId, setMilestoneId] = (0, import_react17.useState)("");
|
|
9475
9558
|
const [types, setTypes] = (0, import_react17.useState)(["quest"]);
|
|
9476
9559
|
const [typeInput, setTypeInput] = (0, import_react17.useState)("");
|
|
9477
9560
|
const [status, setStatus] = (0, import_react17.useState)("Backlog");
|
|
@@ -9493,6 +9576,32 @@ function InSceneQuestForm({
|
|
|
9493
9576
|
const [customProps, setCustomProps] = (0, import_react17.useState)([]);
|
|
9494
9577
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = (0, import_react17.useState)(false);
|
|
9495
9578
|
const propsEndRef = (0, import_react17.useRef)(null);
|
|
9579
|
+
const [isMilestoneDropdownOpen, setIsMilestoneDropdownOpen] = (0, import_react17.useState)(false);
|
|
9580
|
+
const [milestoneSearchQuery, setMilestoneSearchQuery] = (0, import_react17.useState)("");
|
|
9581
|
+
const activeMilestones = import_react17.default.useMemo(
|
|
9582
|
+
() => (milestones || []).filter((ms) => ms.status === "active"),
|
|
9583
|
+
[milestones]
|
|
9584
|
+
);
|
|
9585
|
+
const filteredMilestones = import_react17.default.useMemo(() => {
|
|
9586
|
+
if (!milestoneSearchQuery.trim()) return activeMilestones;
|
|
9587
|
+
return activeMilestones.filter(
|
|
9588
|
+
(ms) => ms.name.toLowerCase().includes(milestoneSearchQuery.toLowerCase())
|
|
9589
|
+
);
|
|
9590
|
+
}, [activeMilestones, milestoneSearchQuery]);
|
|
9591
|
+
const handleSelectMilestone = (id) => {
|
|
9592
|
+
setMilestoneId(id);
|
|
9593
|
+
setIsMilestoneDropdownOpen(false);
|
|
9594
|
+
setMilestoneSearchQuery("");
|
|
9595
|
+
};
|
|
9596
|
+
const handleCreateMilestone = async (name2) => {
|
|
9597
|
+
if (!name2.trim()) return;
|
|
9598
|
+
const newId = `ms_${Date.now()}`;
|
|
9599
|
+
const newMs = { id: newId, name: name2.trim(), status: "active" };
|
|
9600
|
+
await onUpdateMilestones([...milestones, newMs]);
|
|
9601
|
+
setMilestoneId(newId);
|
|
9602
|
+
setIsMilestoneDropdownOpen(false);
|
|
9603
|
+
setMilestoneSearchQuery("");
|
|
9604
|
+
};
|
|
9496
9605
|
const standardizedName = `${viewName} - ${questCounter} - \xBB ${name || "Nova Quest"}`;
|
|
9497
9606
|
const handleAddProp = () => {
|
|
9498
9607
|
const newProp = createNewCustomProperty(customProps);
|
|
@@ -9560,6 +9669,7 @@ function InSceneQuestForm({
|
|
|
9560
9669
|
timeline: initialTimeline,
|
|
9561
9670
|
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
9562
9671
|
recurrence_config: recurrenceConfig,
|
|
9672
|
+
milestone_id: milestoneId || null,
|
|
9563
9673
|
...additionalData
|
|
9564
9674
|
});
|
|
9565
9675
|
};
|
|
@@ -9663,6 +9773,63 @@ function InSceneQuestForm({
|
|
|
9663
9773
|
}
|
|
9664
9774
|
),
|
|
9665
9775
|
s
|
|
9776
|
+
)))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Milestone"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
9777
|
+
"button",
|
|
9778
|
+
{
|
|
9779
|
+
type: "button",
|
|
9780
|
+
onClick: () => setIsMilestoneDropdownOpen(!isMilestoneDropdownOpen),
|
|
9781
|
+
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"
|
|
9782
|
+
},
|
|
9783
|
+
/* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiTarget, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, ((_a = (milestones || []).find((m) => m.id === milestoneId)) == null ? void 0 : _a.name) || "Nenhum")),
|
|
9784
|
+
/* @__PURE__ */ import_react17.default.createElement(
|
|
9785
|
+
import_fi15.FiChevronDown,
|
|
9786
|
+
{
|
|
9787
|
+
className: `text-slate-400 transition-transform duration-200 ${isMilestoneDropdownOpen ? "rotate-180" : ""}`
|
|
9788
|
+
}
|
|
9789
|
+
)
|
|
9790
|
+
), isMilestoneDropdownOpen && /* @__PURE__ */ import_react17.default.createElement(import_react17.default.Fragment, null, /* @__PURE__ */ import_react17.default.createElement(
|
|
9791
|
+
"div",
|
|
9792
|
+
{
|
|
9793
|
+
className: "fixed inset-0 z-40",
|
|
9794
|
+
onClick: () => {
|
|
9795
|
+
setIsMilestoneDropdownOpen(false);
|
|
9796
|
+
setMilestoneSearchQuery("");
|
|
9797
|
+
}
|
|
9798
|
+
}
|
|
9799
|
+
), /* @__PURE__ */ import_react17.default.createElement("div", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-900 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden flex flex-col" }, /* @__PURE__ */ import_react17.default.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiSearch, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ import_react17.default.createElement(
|
|
9800
|
+
"input",
|
|
9801
|
+
{
|
|
9802
|
+
type: "text",
|
|
9803
|
+
autoFocus: true,
|
|
9804
|
+
placeholder: "Buscar ou criar milestone...",
|
|
9805
|
+
value: milestoneSearchQuery,
|
|
9806
|
+
onChange: (e) => setMilestoneSearchQuery(e.target.value),
|
|
9807
|
+
className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
|
|
9808
|
+
onClick: (e) => e.stopPropagation()
|
|
9809
|
+
}
|
|
9810
|
+
)), /* @__PURE__ */ import_react17.default.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
9811
|
+
"li",
|
|
9812
|
+
{
|
|
9813
|
+
onClick: () => handleSelectMilestone(""),
|
|
9814
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!milestoneId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
9815
|
+
},
|
|
9816
|
+
"Nenhum"
|
|
9817
|
+
), filteredMilestones.map((ms) => /* @__PURE__ */ import_react17.default.createElement(
|
|
9818
|
+
"li",
|
|
9819
|
+
{
|
|
9820
|
+
key: ms.id,
|
|
9821
|
+
onClick: () => handleSelectMilestone(ms.id),
|
|
9822
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${milestoneId === ms.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
9823
|
+
},
|
|
9824
|
+
ms.name
|
|
9825
|
+
)), milestoneSearchQuery.trim() && !filteredMilestones.some((ms) => ms.name.toLowerCase() === milestoneSearchQuery.toLowerCase().trim()) && /* @__PURE__ */ import_react17.default.createElement(
|
|
9826
|
+
"li",
|
|
9827
|
+
{
|
|
9828
|
+
onClick: () => handleCreateMilestone(milestoneSearchQuery),
|
|
9829
|
+
className: "px-3 py-3 text-sm cursor-pointer bg-indigo-600/20 text-indigo-200 hover:bg-indigo-600/40 transition-colors flex flex-col gap-0.5"
|
|
9830
|
+
},
|
|
9831
|
+
/* @__PURE__ */ import_react17.default.createElement("span", { className: "text-[10px] uppercase font-bold opacity-60" }, "Criar Novo Milestone"),
|
|
9832
|
+
/* @__PURE__ */ import_react17.default.createElement("span", { className: "font-medium" }, '"', milestoneSearchQuery, '"')
|
|
9666
9833
|
)))))), /* @__PURE__ */ import_react17.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react17.default.createElement("label", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Assignee (Respons\xE1vel)"), /* @__PURE__ */ import_react17.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react17.default.createElement(
|
|
9667
9834
|
"button",
|
|
9668
9835
|
{
|
|
@@ -9670,7 +9837,7 @@ function InSceneQuestForm({
|
|
|
9670
9837
|
onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
|
|
9671
9838
|
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"
|
|
9672
9839
|
},
|
|
9673
|
-
/* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiUser, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, ((
|
|
9840
|
+
/* @__PURE__ */ import_react17.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react17.default.createElement(import_fi15.FiUser, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react17.default.createElement("span", { className: "text-slate-200 font-medium" }, ((_b = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _b.name) || ((_c = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _c.email) || "Nenhum")),
|
|
9674
9841
|
/* @__PURE__ */ import_react17.default.createElement(
|
|
9675
9842
|
import_fi15.FiChevronDown,
|
|
9676
9843
|
{
|
|
@@ -10642,9 +10809,12 @@ function QuestDetailsPanel({
|
|
|
10642
10809
|
userRole,
|
|
10643
10810
|
currentDatasetName,
|
|
10644
10811
|
viewMembers = [],
|
|
10645
|
-
currentUser
|
|
10812
|
+
currentUser,
|
|
10813
|
+
milestones = [],
|
|
10814
|
+
onUpdateMilestones = () => {
|
|
10815
|
+
}
|
|
10646
10816
|
}) {
|
|
10647
|
-
var _a, _b;
|
|
10817
|
+
var _a, _b, _c;
|
|
10648
10818
|
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) || "";
|
|
10649
10819
|
const [rawTitle, setRawTitle] = (0, import_react20.useState)(initialRawTitle);
|
|
10650
10820
|
const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
|
|
@@ -10657,6 +10827,7 @@ function QuestDetailsPanel({
|
|
|
10657
10827
|
const [assigneeId, setAssigneeId] = (0, import_react20.useState)((node == null ? void 0 : node.assignee_id) || "");
|
|
10658
10828
|
const [description, setDescription] = (0, import_react20.useState)((node == null ? void 0 : node.description) ?? "");
|
|
10659
10829
|
const [intensity, setIntensity] = (0, import_react20.useState)((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
10830
|
+
const [milestoneId, setMilestoneId] = (0, import_react20.useState)((node == null ? void 0 : node.milestone_id) || "");
|
|
10660
10831
|
const [isStatusDropdownOpen, setIsStatusDropdownOpen] = (0, import_react20.useState)(false);
|
|
10661
10832
|
const [isAssigneeDropdownOpen, setIsAssigneeDropdownOpen] = (0, import_react20.useState)(false);
|
|
10662
10833
|
const [assigneeSearchQuery, setAssigneeSearchQuery] = (0, import_react20.useState)("");
|
|
@@ -10694,6 +10865,35 @@ function QuestDetailsPanel({
|
|
|
10694
10865
|
minWidth: 320,
|
|
10695
10866
|
maxWidth: maxPanelW
|
|
10696
10867
|
});
|
|
10868
|
+
const [isMilestoneDropdownOpen, setIsMilestoneDropdownOpen] = (0, import_react20.useState)(false);
|
|
10869
|
+
const [milestoneSearchQuery, setMilestoneSearchQuery] = (0, import_react20.useState)("");
|
|
10870
|
+
const activeMilestones = import_react20.default.useMemo(
|
|
10871
|
+
() => (milestones || []).filter((ms) => ms.status === "active"),
|
|
10872
|
+
[milestones]
|
|
10873
|
+
);
|
|
10874
|
+
const filteredMilestones = import_react20.default.useMemo(() => {
|
|
10875
|
+
const search = milestoneSearchQuery.toLowerCase().trim();
|
|
10876
|
+
if (!search) return activeMilestones;
|
|
10877
|
+
return activeMilestones.filter(
|
|
10878
|
+
(ms) => ms.name.toLowerCase().includes(search)
|
|
10879
|
+
);
|
|
10880
|
+
}, [activeMilestones, milestoneSearchQuery]);
|
|
10881
|
+
const handleSelectMilestone = (id) => {
|
|
10882
|
+
setMilestoneId(id);
|
|
10883
|
+
setIsMilestoneDropdownOpen(false);
|
|
10884
|
+
setMilestoneSearchQuery("");
|
|
10885
|
+
setHasUnsavedChanges(true);
|
|
10886
|
+
};
|
|
10887
|
+
const handleCreateMilestone = async (name) => {
|
|
10888
|
+
if (!name.trim()) return;
|
|
10889
|
+
const newId = `ms_${Date.now()}`;
|
|
10890
|
+
const newMs = { id: newId, name: name.trim(), status: "active" };
|
|
10891
|
+
await onUpdateMilestones([...milestones, newMs]);
|
|
10892
|
+
setMilestoneId(newId);
|
|
10893
|
+
setIsMilestoneDropdownOpen(false);
|
|
10894
|
+
setMilestoneSearchQuery("");
|
|
10895
|
+
setHasUnsavedChanges(true);
|
|
10896
|
+
};
|
|
10697
10897
|
(0, import_react20.useEffect)(() => {
|
|
10698
10898
|
setWidth(isReadMode ? 700 : 440);
|
|
10699
10899
|
}, [isReadMode, setWidth]);
|
|
@@ -10719,6 +10919,7 @@ function QuestDetailsPanel({
|
|
|
10719
10919
|
setReturnAssigneeId("");
|
|
10720
10920
|
setDescription((node == null ? void 0 : node.description) ?? "");
|
|
10721
10921
|
setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
10922
|
+
setMilestoneId((node == null ? void 0 : node.milestone_id) || "");
|
|
10722
10923
|
setExistingSections((node == null ? void 0 : node.description_sections) || []);
|
|
10723
10924
|
setCustomProps(extractCustomPropsFromNode(node || {}));
|
|
10724
10925
|
setReviewStack((node == null ? void 0 : node.reviewStack) || []);
|
|
@@ -10731,6 +10932,7 @@ function QuestDetailsPanel({
|
|
|
10731
10932
|
custom_date: "",
|
|
10732
10933
|
next_assignee_id: ""
|
|
10733
10934
|
});
|
|
10935
|
+
setMilestoneId((node == null ? void 0 : node.milestone_id) || "");
|
|
10734
10936
|
setHasUnsavedChanges(false);
|
|
10735
10937
|
}
|
|
10736
10938
|
}, [node]);
|
|
@@ -11029,7 +11231,8 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11029
11231
|
reviewStack: currentReviewStack,
|
|
11030
11232
|
timeline: currentTimeline,
|
|
11031
11233
|
...extrasObj,
|
|
11032
|
-
version_node: node.version_node
|
|
11234
|
+
version_node: node.version_node,
|
|
11235
|
+
milestone_id: milestoneId || null
|
|
11033
11236
|
};
|
|
11034
11237
|
await onSave(dataToSave, keepOpen);
|
|
11035
11238
|
onDataUpdate(dataToSave);
|
|
@@ -11231,7 +11434,51 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11231
11434
|
maxLength: "10",
|
|
11232
11435
|
className: "flex-1 bg-slate-800/70 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-400/60"
|
|
11233
11436
|
}
|
|
11234
|
-
))))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react20.default.createElement("label", { className: "text-xs text-slate-300" }, "
|
|
11437
|
+
))))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react20.default.createElement("label", { className: "text-xs text-slate-300" }, "Milestone"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
11438
|
+
"button",
|
|
11439
|
+
{
|
|
11440
|
+
type: "button",
|
|
11441
|
+
onClick: () => canEdit && setIsMilestoneDropdownOpen(!isMilestoneDropdownOpen),
|
|
11442
|
+
disabled: !canEdit,
|
|
11443
|
+
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 transition-colors flex items-center justify-between ${canEdit ? "hover:border-white/20 focus:ring-2 focus:ring-indigo-400/60 cursor-pointer" : "cursor-default opacity-80"}`
|
|
11444
|
+
},
|
|
11445
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiTarget, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-slate-200 font-medium" }, ((_b = (milestones || []).find((m) => m.id === milestoneId)) == null ? void 0 : _b.name) || "Nenhum")),
|
|
11446
|
+
canEdit && /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isMilestoneDropdownOpen ? "rotate-180" : ""}` })
|
|
11447
|
+
), isMilestoneDropdownOpen && canEdit && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsMilestoneDropdownOpen(false) }), /* @__PURE__ */ import_react20.default.createElement("div", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-900 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden flex flex-col" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiSearch, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ import_react20.default.createElement(
|
|
11448
|
+
"input",
|
|
11449
|
+
{
|
|
11450
|
+
type: "text",
|
|
11451
|
+
autoFocus: true,
|
|
11452
|
+
placeholder: "Buscar ou criar milestone...",
|
|
11453
|
+
value: milestoneSearchQuery,
|
|
11454
|
+
onChange: (e) => setMilestoneSearchQuery(e.target.value),
|
|
11455
|
+
className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
|
|
11456
|
+
onClick: (e) => e.stopPropagation()
|
|
11457
|
+
}
|
|
11458
|
+
)), /* @__PURE__ */ import_react20.default.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
11459
|
+
"li",
|
|
11460
|
+
{
|
|
11461
|
+
onClick: () => handleSelectMilestone(""),
|
|
11462
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!milestoneId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
11463
|
+
},
|
|
11464
|
+
"Nenhum"
|
|
11465
|
+
), filteredMilestones.map((ms) => /* @__PURE__ */ import_react20.default.createElement(
|
|
11466
|
+
"li",
|
|
11467
|
+
{
|
|
11468
|
+
key: ms.id,
|
|
11469
|
+
onClick: () => handleSelectMilestone(ms.id),
|
|
11470
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${milestoneId === ms.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
11471
|
+
},
|
|
11472
|
+
ms.name
|
|
11473
|
+
)), milestoneSearchQuery.trim() && !filteredMilestones.some((ms) => ms.name.toLowerCase() === milestoneSearchQuery.toLowerCase().trim()) && /* @__PURE__ */ import_react20.default.createElement(
|
|
11474
|
+
"li",
|
|
11475
|
+
{
|
|
11476
|
+
onClick: () => handleCreateMilestone(milestoneSearchQuery),
|
|
11477
|
+
className: "px-3 py-3 text-sm cursor-pointer bg-indigo-600/20 text-indigo-200 hover:bg-indigo-600/40 transition-colors flex flex-col gap-0.5"
|
|
11478
|
+
},
|
|
11479
|
+
/* @__PURE__ */ import_react20.default.createElement("span", { className: "text-[10px] uppercase font-bold opacity-60" }, "Criar Novo Milestone"),
|
|
11480
|
+
/* @__PURE__ */ import_react20.default.createElement("span", { className: "font-medium" }, '"', milestoneSearchQuery, '"')
|
|
11481
|
+
)))))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ import_react20.default.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
11235
11482
|
"button",
|
|
11236
11483
|
{
|
|
11237
11484
|
type: "button",
|
|
@@ -11417,7 +11664,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11417
11664
|
onClick: () => setIsReturnDropdownOpen(!isReturnDropdownOpen),
|
|
11418
11665
|
className: "w-full bg-slate-800/80 p-2 text-xs rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-1 focus:ring-purple-400/50 transition-colors flex items-center justify-between"
|
|
11419
11666
|
},
|
|
11420
|
-
/* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiUser, { className: "text-slate-400", size: 12 }), /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-slate-200 font-medium" }, ((
|
|
11667
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiUser, { className: "text-slate-400", size: 12 }), /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-slate-200 font-medium" }, ((_c = viewMembers.find((m) => String(m.id) === String(returnAssigneeId))) == null ? void 0 : _c.name) || "Selecionar respons\xE1vel...")),
|
|
11421
11668
|
/* @__PURE__ */ import_react20.default.createElement(import_fi18.FiChevronDown, { className: `text-slate-400 transition-transform duration-200 ${isReturnDropdownOpen ? "rotate-180" : ""}`, size: 14 })
|
|
11422
11669
|
), isReturnDropdownOpen && /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
|
|
11423
11670
|
setIsReturnDropdownOpen(false);
|
|
@@ -13085,7 +13332,7 @@ function XViewScene({
|
|
|
13085
13332
|
check_user_permission,
|
|
13086
13333
|
get_view_members
|
|
13087
13334
|
}) {
|
|
13088
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
13335
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
13089
13336
|
const { data: session, status } = (0, import_react29.useSession)();
|
|
13090
13337
|
const router = (0, import_navigation.useRouter)();
|
|
13091
13338
|
const searchParams = (0, import_navigation.useSearchParams)();
|
|
@@ -13914,20 +14161,23 @@ function XViewScene({
|
|
|
13914
14161
|
sceneResponse.data.scene.nodes = [];
|
|
13915
14162
|
sceneResponse.data.scene.links = [];
|
|
13916
14163
|
}
|
|
13917
|
-
sceneDataRef.current =
|
|
14164
|
+
sceneDataRef.current = {
|
|
14165
|
+
...sceneResponse.data.scene,
|
|
14166
|
+
milestones: sceneResponse.data.scene.milestones || []
|
|
14167
|
+
};
|
|
13918
14168
|
parentDataRef.current = sceneResponse.data.parent;
|
|
13919
14169
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
13920
14170
|
console.log(
|
|
13921
14171
|
"Console de sceneResponse.data.scene:",
|
|
13922
|
-
|
|
14172
|
+
sceneDataRef.current
|
|
13923
14173
|
);
|
|
13924
14174
|
console.log(
|
|
13925
14175
|
"Console de sceneResponse.data.parent:",
|
|
13926
|
-
|
|
14176
|
+
parentDataRef.current
|
|
13927
14177
|
);
|
|
13928
14178
|
console.log(
|
|
13929
14179
|
"Console de sceneResponse.data.ancestry:",
|
|
13930
|
-
|
|
14180
|
+
ancestryDataRef.current
|
|
13931
14181
|
);
|
|
13932
14182
|
setIsInitialized(true);
|
|
13933
14183
|
} else {
|
|
@@ -14059,6 +14309,9 @@ function XViewScene({
|
|
|
14059
14309
|
timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
|
|
14060
14310
|
});
|
|
14061
14311
|
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
14312
|
+
let sumX = 0;
|
|
14313
|
+
let sumY = 0;
|
|
14314
|
+
let questCount = 0;
|
|
14062
14315
|
const positionGroups = /* @__PURE__ */ new Map();
|
|
14063
14316
|
const NODE_X_GAP = 22;
|
|
14064
14317
|
QUEST_STATUS_ORDER.forEach((statusName) => {
|
|
@@ -14162,6 +14415,9 @@ function XViewScene({
|
|
|
14162
14415
|
const lensTween = new import_tween2.Tween(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14163
14416
|
tweenGroup.add(lensTween);
|
|
14164
14417
|
lensTween.start();
|
|
14418
|
+
sumX += finalX;
|
|
14419
|
+
sumY += targetY;
|
|
14420
|
+
questCount++;
|
|
14165
14421
|
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
14166
14422
|
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
14167
14423
|
dateSprite.name = "questDateLabel";
|
|
@@ -14210,6 +14466,18 @@ function XViewScene({
|
|
|
14210
14466
|
}
|
|
14211
14467
|
});
|
|
14212
14468
|
});
|
|
14469
|
+
if (questCount > 0) {
|
|
14470
|
+
const { camera, controls } = stateRef.current;
|
|
14471
|
+
const centerX = sumX / questCount;
|
|
14472
|
+
const centerY = sumY / questCount;
|
|
14473
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
14474
|
+
const targetTween = new import_tween2.Tween(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14475
|
+
tweenGroup.add(targetTween);
|
|
14476
|
+
targetTween.start();
|
|
14477
|
+
const camTween = new import_tween2.Tween(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: 140 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
14478
|
+
tweenGroup.add(camTween);
|
|
14479
|
+
camTween.start();
|
|
14480
|
+
}
|
|
14213
14481
|
}, [addOrUpdateNodeMesh]);
|
|
14214
14482
|
(0, import_react28.useEffect)(() => {
|
|
14215
14483
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
@@ -15432,7 +15700,8 @@ function XViewScene({
|
|
|
15432
15700
|
links: sceneDataRef2.current.links,
|
|
15433
15701
|
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
15434
15702
|
quest_links: graphDataRef.current[sceneConfigId2].links,
|
|
15435
|
-
quest_counter: currentCounter + 1
|
|
15703
|
+
quest_counter: currentCounter + 1,
|
|
15704
|
+
milestones: sceneDataRef2.current.milestones || []
|
|
15436
15705
|
};
|
|
15437
15706
|
try {
|
|
15438
15707
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
@@ -17084,6 +17353,52 @@ function XViewScene({
|
|
|
17084
17353
|
},
|
|
17085
17354
|
[actionHandlerContext]
|
|
17086
17355
|
);
|
|
17356
|
+
const handleUpdateMilestones = (0, import_react28.useCallback)(
|
|
17357
|
+
async (newMilestones) => {
|
|
17358
|
+
var _a2, _b2, _c2;
|
|
17359
|
+
if (!sceneDataRef.current) return;
|
|
17360
|
+
sceneDataRef.current.milestones = newMilestones;
|
|
17361
|
+
setSceneVersion((v) => v + 1);
|
|
17362
|
+
const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
|
|
17363
|
+
if (!isView || !save_view_data || !sceneSaveUrl) return;
|
|
17364
|
+
const { nodeObjects, allLinks } = stateRef.current;
|
|
17365
|
+
const currentNodes = Object.values(nodeObjects || {}).map((mesh) => {
|
|
17366
|
+
const {
|
|
17367
|
+
_baseEmissiveIntensity,
|
|
17368
|
+
labelObject,
|
|
17369
|
+
labelOffset,
|
|
17370
|
+
timelineIntervalBar,
|
|
17371
|
+
timelineEndLabel,
|
|
17372
|
+
...serializableNodeData
|
|
17373
|
+
} = mesh.userData;
|
|
17374
|
+
return serializableNodeData;
|
|
17375
|
+
});
|
|
17376
|
+
const currentLinks = (allLinks || []).map((line) => {
|
|
17377
|
+
const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
|
|
17378
|
+
return serializableLinkData;
|
|
17379
|
+
});
|
|
17380
|
+
const sceneFileData = {
|
|
17381
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
17382
|
+
nodes: currentNodes,
|
|
17383
|
+
links: currentLinks,
|
|
17384
|
+
quest_nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
|
|
17385
|
+
quest_links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
|
|
17386
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
17387
|
+
milestones: newMilestones
|
|
17388
|
+
};
|
|
17389
|
+
try {
|
|
17390
|
+
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
17391
|
+
} catch (error) {
|
|
17392
|
+
console.error("Erro ao salvar milestones:", error);
|
|
17393
|
+
}
|
|
17394
|
+
},
|
|
17395
|
+
[
|
|
17396
|
+
sceneConfigId,
|
|
17397
|
+
sceneSaveUrl,
|
|
17398
|
+
save_view_data,
|
|
17399
|
+
viewParams == null ? void 0 : viewParams.type
|
|
17400
|
+
]
|
|
17401
|
+
);
|
|
17087
17402
|
const handleSaveCurrentView = (0, import_react28.useCallback)(async () => {
|
|
17088
17403
|
var _a2, _b2, _c2;
|
|
17089
17404
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
@@ -17118,7 +17433,8 @@ function XViewScene({
|
|
|
17118
17433
|
links: currentLinks,
|
|
17119
17434
|
quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
|
|
17120
17435
|
quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || [],
|
|
17121
|
-
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
17436
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
17437
|
+
milestones: sceneDataRef.current.milestones || []
|
|
17122
17438
|
};
|
|
17123
17439
|
try {
|
|
17124
17440
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
@@ -17455,7 +17771,9 @@ function XViewScene({
|
|
|
17455
17771
|
isOpen: isSidebarOpen,
|
|
17456
17772
|
onToggle: setIsSidebarOpen,
|
|
17457
17773
|
userRole: userPermissionRole,
|
|
17458
|
-
viewMembers
|
|
17774
|
+
viewMembers,
|
|
17775
|
+
milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
|
|
17776
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17459
17777
|
}
|
|
17460
17778
|
),
|
|
17461
17779
|
creationMode.isActive && /* @__PURE__ */ import_react28.default.createElement(
|
|
@@ -17479,8 +17797,8 @@ function XViewScene({
|
|
|
17479
17797
|
},
|
|
17480
17798
|
refEl: formRef,
|
|
17481
17799
|
existingTypes: existingNodeTypes,
|
|
17482
|
-
initialColor: (
|
|
17483
|
-
sourceTypes: (
|
|
17800
|
+
initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
|
|
17801
|
+
sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
|
|
17484
17802
|
onIntensityChange: handleGhostNodeIntensityChange,
|
|
17485
17803
|
onUploadFile: upload_file_action,
|
|
17486
17804
|
availableDatasets,
|
|
@@ -17509,8 +17827,8 @@ function XViewScene({
|
|
|
17509
17827
|
transition: "opacity 200ms ease-out"
|
|
17510
17828
|
},
|
|
17511
17829
|
refEl: formRef,
|
|
17512
|
-
fixedType: (
|
|
17513
|
-
fixedColor: (
|
|
17830
|
+
fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
|
|
17831
|
+
fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
|
|
17514
17832
|
onUploadFile: upload_file_action,
|
|
17515
17833
|
availableNodes: allAvailableNodes,
|
|
17516
17834
|
availableAncestries: allAvailableAncestries
|
|
@@ -17538,8 +17856,10 @@ function XViewScene({
|
|
|
17538
17856
|
availableNodes: allAvailableNodes,
|
|
17539
17857
|
availableAncestries: allAvailableAncestries,
|
|
17540
17858
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
|
17541
|
-
questCounter: ((
|
|
17542
|
-
viewMembers
|
|
17859
|
+
questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
|
|
17860
|
+
viewMembers,
|
|
17861
|
+
milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
|
|
17862
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17543
17863
|
}
|
|
17544
17864
|
),
|
|
17545
17865
|
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ import_react28.default.createElement(
|
|
@@ -17671,7 +17991,9 @@ function XViewScene({
|
|
|
17671
17991
|
userRole: userPermissionRole,
|
|
17672
17992
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
|
|
17673
17993
|
viewMembers,
|
|
17674
|
-
currentUser: session == null ? void 0 : session.user
|
|
17994
|
+
currentUser: session == null ? void 0 : session.user,
|
|
17995
|
+
milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
|
|
17996
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17675
17997
|
}
|
|
17676
17998
|
),
|
|
17677
17999
|
detailsNode && !detailsNode.is_quest && /* @__PURE__ */ import_react28.default.createElement(
|
|
@@ -17856,7 +18178,7 @@ function XViewScene({
|
|
|
17856
18178
|
onClose: () => setIsImportModalOpen(false),
|
|
17857
18179
|
onConfirm: handleConfirmImport,
|
|
17858
18180
|
session,
|
|
17859
|
-
parentDbs: ((
|
|
18181
|
+
parentDbs: ((_k = sceneDataRef.current) == null ? void 0 : _k.parent_dbs) || [],
|
|
17860
18182
|
onFetchAvailableFiles: import_parent_file_modal_get,
|
|
17861
18183
|
currentViewName: viewParams == null ? void 0 : viewParams.name,
|
|
17862
18184
|
currentAncestries: ancestryDataRef.current || []
|
package/dist/index.mjs
CHANGED
|
@@ -586,12 +586,16 @@ function XViewSidebar({
|
|
|
586
586
|
userRole,
|
|
587
587
|
viewMembers = [],
|
|
588
588
|
onActivateQuestLens = () => {
|
|
589
|
+
},
|
|
590
|
+
milestones = [],
|
|
591
|
+
onUpdateMilestones = () => {
|
|
589
592
|
}
|
|
590
593
|
}) {
|
|
591
594
|
const [query, setQuery] = useState2("");
|
|
592
595
|
const [showList, setShowList] = useState2(false);
|
|
593
596
|
const [selectedNodeId, setSelectedNodeId] = useState2(null);
|
|
594
597
|
const [isSaving, setIsSaving] = useState2(false);
|
|
598
|
+
const [newMilestoneName, setNewMilestoneName] = useState2("");
|
|
595
599
|
const [activeFilters, setActiveFilters] = useState2([]);
|
|
596
600
|
const [isFilterMenuOpen, setIsFilterMenuOpen] = useState2(false);
|
|
597
601
|
const [filterCategory, setFilterCategory] = useState2("Type");
|
|
@@ -803,6 +807,28 @@ function XViewSidebar({
|
|
|
803
807
|
setIsTypeDropdownOpen(false);
|
|
804
808
|
}
|
|
805
809
|
};
|
|
810
|
+
const handleAddMilestone = () => {
|
|
811
|
+
if (!newMilestoneName.trim()) return;
|
|
812
|
+
const newMilestone = {
|
|
813
|
+
id: `ms_${Date.now()}`,
|
|
814
|
+
name: newMilestoneName.trim(),
|
|
815
|
+
status: "active"
|
|
816
|
+
};
|
|
817
|
+
onUpdateMilestones([...milestones, newMilestone]);
|
|
818
|
+
setNewMilestoneName("");
|
|
819
|
+
};
|
|
820
|
+
const handleToggleMilestoneStatus = (id) => {
|
|
821
|
+
const updated = milestones.map(
|
|
822
|
+
(ms) => ms.id === id ? { ...ms, status: ms.status === "active" ? "inactive" : "active" } : ms
|
|
823
|
+
);
|
|
824
|
+
onUpdateMilestones(updated);
|
|
825
|
+
};
|
|
826
|
+
const handleRemoveMilestone = (id) => {
|
|
827
|
+
var _a;
|
|
828
|
+
if (!confirm(`Deseja remover o milestone "${(_a = milestones.find((m) => m.id === id)) == null ? void 0 : _a.name}"?`)) return;
|
|
829
|
+
const updated = milestones.filter((ms) => ms.id !== id);
|
|
830
|
+
onUpdateMilestones(updated);
|
|
831
|
+
};
|
|
806
832
|
const ToggleButton = /* @__PURE__ */ React2.createElement(
|
|
807
833
|
"button",
|
|
808
834
|
{
|
|
@@ -1059,11 +1085,59 @@ function XViewSidebar({
|
|
|
1059
1085
|
onClick: () => {
|
|
1060
1086
|
onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
|
|
1061
1087
|
setIsQuestLensMenuOpen(false);
|
|
1088
|
+
onToggle(false);
|
|
1062
1089
|
},
|
|
1063
1090
|
className: "flex-[2] py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-[11px] font-bold rounded-lg shadow-lg shadow-indigo-500/20 transition-all hover:scale-[1.02] active:scale-95"
|
|
1064
1091
|
},
|
|
1065
1092
|
"Aplicar Lente"
|
|
1066
|
-
)))))
|
|
1093
|
+
))))), /* @__PURE__ */ React2.createElement("div", { className: "h-px bg-white/10" }), /* @__PURE__ */ React2.createElement("section", { className: "space-y-3" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Milestones")), /* @__PURE__ */ React2.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React2.createElement(
|
|
1094
|
+
"input",
|
|
1095
|
+
{
|
|
1096
|
+
type: "text",
|
|
1097
|
+
value: newMilestoneName,
|
|
1098
|
+
onChange: (e) => setNewMilestoneName(e.target.value),
|
|
1099
|
+
onKeyDown: (e) => e.key === "Enter" && handleAddMilestone(),
|
|
1100
|
+
placeholder: "Novo Milestone...",
|
|
1101
|
+
className: "flex-1 bg-slate-900/50 border border-white/10 rounded-md px-2 py-1.5 text-xs text-slate-100 placeholder:text-slate-600 focus:outline-none focus:border-indigo-500/50"
|
|
1102
|
+
}
|
|
1103
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1104
|
+
"button",
|
|
1105
|
+
{
|
|
1106
|
+
onClick: handleAddMilestone,
|
|
1107
|
+
disabled: !newMilestoneName.trim(),
|
|
1108
|
+
className: "p-1.5 rounded-md bg-indigo-500/10 hover:bg-indigo-500/20 border border-indigo-500/30 text-indigo-300 disabled:opacity-30 transition-colors"
|
|
1109
|
+
},
|
|
1110
|
+
/* @__PURE__ */ React2.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__ */ React2.createElement("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), /* @__PURE__ */ React2.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))
|
|
1111
|
+
)), /* @__PURE__ */ React2.createElement("div", { className: "space-y-1.5 max-h-[200px] overflow-y-auto custom-scrollbar pr-1" }, milestones.length > 0 ? milestones.map((ms) => /* @__PURE__ */ React2.createElement(
|
|
1112
|
+
"div",
|
|
1113
|
+
{
|
|
1114
|
+
key: ms.id,
|
|
1115
|
+
className: `group flex items-center justify-between px-2.5 py-2 rounded-lg border transition-all ${ms.status === "active" ? "bg-indigo-500/5 border-indigo-500/20" : "bg-slate-900/30 border-white/5 opacity-60"}`
|
|
1116
|
+
},
|
|
1117
|
+
/* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React2.createElement(
|
|
1118
|
+
"div",
|
|
1119
|
+
{
|
|
1120
|
+
className: `w-1.5 h-1.5 rounded-full shrink-0 ${ms.status === "active" ? "bg-indigo-400 shadow-[0_0_8px_rgba(129,140,248,0.5)]" : "bg-slate-600"}`
|
|
1121
|
+
}
|
|
1122
|
+
), /* @__PURE__ */ React2.createElement("span", { className: `text-[11px] truncate font-medium ${ms.status === "active" ? "text-slate-100" : "text-slate-500 line-through"}` }, ms.name)),
|
|
1123
|
+
/* @__PURE__ */ React2.createElement("div", { className: "flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ React2.createElement(
|
|
1124
|
+
"button",
|
|
1125
|
+
{
|
|
1126
|
+
onClick: () => handleToggleMilestoneStatus(ms.id),
|
|
1127
|
+
className: `p-1 rounded hover:bg-white/10 transition-colors ${ms.status === "active" ? "text-slate-400" : "text-indigo-400"}`,
|
|
1128
|
+
title: ms.status === "active" ? "Inativar" : "Ativar"
|
|
1129
|
+
},
|
|
1130
|
+
ms.status === "active" ? /* @__PURE__ */ React2.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React2.createElement("rect", { x: "6", y: "4", width: "4", height: "16" }), /* @__PURE__ */ React2.createElement("rect", { x: "14", y: "4", width: "4", height: "16" })) : /* @__PURE__ */ React2.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React2.createElement("polygon", { points: "5 3 19 12 5 21 5 3" }))
|
|
1131
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1132
|
+
"button",
|
|
1133
|
+
{
|
|
1134
|
+
onClick: () => handleRemoveMilestone(ms.id),
|
|
1135
|
+
className: "p-1 rounded hover:bg-red-500/20 text-slate-500 hover:text-red-400 transition-colors",
|
|
1136
|
+
title: "Remover"
|
|
1137
|
+
},
|
|
1138
|
+
/* @__PURE__ */ React2.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ React2.createElement("polyline", { points: "3 6 5 6 21 6" }), /* @__PURE__ */ React2.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__ */ React2.createElement("line", { x1: "10", y1: "11", x2: "10", y2: "17" }), /* @__PURE__ */ React2.createElement("line", { x1: "14", y1: "11", x2: "14", y2: "17" }))
|
|
1139
|
+
))
|
|
1140
|
+
)) : /* @__PURE__ */ React2.createElement("p", { className: "text-[10px] text-slate-600 text-center py-2 italic font-light italic" }, "Nenhum milestone definido")))), /* @__PURE__ */ React2.createElement("div", { className: "px-4 py-3 border-t border-white/10 bg-slate-900/30" }, /* @__PURE__ */ React2.createElement("section", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React2.createElement("p", { className: "text-[11px] uppercase tracking-wider text-slate-400" }, "Navega\xE7\xE3o")), ability.can("update", "Scene") && /* @__PURE__ */ React2.createElement(
|
|
1067
1141
|
"button",
|
|
1068
1142
|
{
|
|
1069
1143
|
onClick: handleSaveClick,
|
|
@@ -2292,7 +2366,8 @@ var userActionHandlers = {
|
|
|
2292
2366
|
nodes: sceneDataRef.current.nodes,
|
|
2293
2367
|
links: sceneDataRef.current.links,
|
|
2294
2368
|
quest_nodes: specificParentData.nodes,
|
|
2295
|
-
quest_links: specificParentData.links
|
|
2369
|
+
quest_links: specificParentData.links,
|
|
2370
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2296
2371
|
};
|
|
2297
2372
|
await context.actions.save_view_data(
|
|
2298
2373
|
context.sceneSaveUrl,
|
|
@@ -2550,7 +2625,8 @@ var userActionHandlers = {
|
|
|
2550
2625
|
nodes: sceneDataRef.current.nodes,
|
|
2551
2626
|
links: sceneDataRef.current.links,
|
|
2552
2627
|
quest_nodes: specificParentData.nodes,
|
|
2553
|
-
quest_links: specificParentData.links
|
|
2628
|
+
quest_links: specificParentData.links,
|
|
2629
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2554
2630
|
};
|
|
2555
2631
|
await context.actions.save_view_data(
|
|
2556
2632
|
context.sceneSaveUrl,
|
|
@@ -2706,7 +2782,8 @@ var userActionHandlers = {
|
|
|
2706
2782
|
nodes: sceneDataRef.current.nodes,
|
|
2707
2783
|
links: sceneDataRef.current.links,
|
|
2708
2784
|
quest_nodes: data.nodes,
|
|
2709
|
-
quest_links: data.links
|
|
2785
|
+
quest_links: data.links,
|
|
2786
|
+
milestones: sceneDataRef.current.milestones || []
|
|
2710
2787
|
};
|
|
2711
2788
|
return context.actions.save_view_data(
|
|
2712
2789
|
context.sceneSaveUrl,
|
|
@@ -3320,6 +3397,7 @@ var userActionHandlers = {
|
|
|
3320
3397
|
links: sceneDataRef.current.links,
|
|
3321
3398
|
quest_nodes: specificParentData.nodes,
|
|
3322
3399
|
quest_links: specificParentData.links,
|
|
3400
|
+
milestones: sceneDataRef.current.milestones || [],
|
|
3323
3401
|
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
3324
3402
|
};
|
|
3325
3403
|
await context.actions.save_view_data(
|
|
@@ -3392,7 +3470,8 @@ var userActionHandlers = {
|
|
|
3392
3470
|
links: sceneDataRef.current.links,
|
|
3393
3471
|
quest_nodes: specificParentData.nodes,
|
|
3394
3472
|
quest_links: specificParentData.links,
|
|
3395
|
-
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
3473
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
3474
|
+
milestones: sceneDataRef.current.milestones || []
|
|
3396
3475
|
};
|
|
3397
3476
|
await context.actions.save_view_data(
|
|
3398
3477
|
context.sceneSaveUrl,
|
|
@@ -9486,11 +9565,15 @@ function InSceneQuestForm({
|
|
|
9486
9565
|
questCounter = 1,
|
|
9487
9566
|
// NOVA PROP
|
|
9488
9567
|
viewMembers = [],
|
|
9489
|
-
session = null
|
|
9568
|
+
session = null,
|
|
9569
|
+
milestones = [],
|
|
9570
|
+
onUpdateMilestones = () => {
|
|
9571
|
+
}
|
|
9490
9572
|
}) {
|
|
9491
|
-
var _a, _b;
|
|
9573
|
+
var _a, _b, _c;
|
|
9492
9574
|
const [name, setName] = useState17("");
|
|
9493
9575
|
const [assigneeId, setAssigneeId] = useState17("");
|
|
9576
|
+
const [milestoneId, setMilestoneId] = useState17("");
|
|
9494
9577
|
const [types, setTypes] = useState17(["quest"]);
|
|
9495
9578
|
const [typeInput, setTypeInput] = useState17("");
|
|
9496
9579
|
const [status, setStatus] = useState17("Backlog");
|
|
@@ -9512,6 +9595,32 @@ function InSceneQuestForm({
|
|
|
9512
9595
|
const [customProps, setCustomProps] = useState17([]);
|
|
9513
9596
|
const [isDescriptionModalOpen, setIsDescriptionModalOpen] = useState17(false);
|
|
9514
9597
|
const propsEndRef = useRef12(null);
|
|
9598
|
+
const [isMilestoneDropdownOpen, setIsMilestoneDropdownOpen] = useState17(false);
|
|
9599
|
+
const [milestoneSearchQuery, setMilestoneSearchQuery] = useState17("");
|
|
9600
|
+
const activeMilestones = React16.useMemo(
|
|
9601
|
+
() => (milestones || []).filter((ms) => ms.status === "active"),
|
|
9602
|
+
[milestones]
|
|
9603
|
+
);
|
|
9604
|
+
const filteredMilestones = React16.useMemo(() => {
|
|
9605
|
+
if (!milestoneSearchQuery.trim()) return activeMilestones;
|
|
9606
|
+
return activeMilestones.filter(
|
|
9607
|
+
(ms) => ms.name.toLowerCase().includes(milestoneSearchQuery.toLowerCase())
|
|
9608
|
+
);
|
|
9609
|
+
}, [activeMilestones, milestoneSearchQuery]);
|
|
9610
|
+
const handleSelectMilestone = (id) => {
|
|
9611
|
+
setMilestoneId(id);
|
|
9612
|
+
setIsMilestoneDropdownOpen(false);
|
|
9613
|
+
setMilestoneSearchQuery("");
|
|
9614
|
+
};
|
|
9615
|
+
const handleCreateMilestone = async (name2) => {
|
|
9616
|
+
if (!name2.trim()) return;
|
|
9617
|
+
const newId = `ms_${Date.now()}`;
|
|
9618
|
+
const newMs = { id: newId, name: name2.trim(), status: "active" };
|
|
9619
|
+
await onUpdateMilestones([...milestones, newMs]);
|
|
9620
|
+
setMilestoneId(newId);
|
|
9621
|
+
setIsMilestoneDropdownOpen(false);
|
|
9622
|
+
setMilestoneSearchQuery("");
|
|
9623
|
+
};
|
|
9515
9624
|
const standardizedName = `${viewName} - ${questCounter} - \xBB ${name || "Nova Quest"}`;
|
|
9516
9625
|
const handleAddProp = () => {
|
|
9517
9626
|
const newProp = createNewCustomProperty(customProps);
|
|
@@ -9579,6 +9688,7 @@ function InSceneQuestForm({
|
|
|
9579
9688
|
timeline: initialTimeline,
|
|
9580
9689
|
Date: questDate ? { ...questDate, confirmed: true } : null,
|
|
9581
9690
|
recurrence_config: recurrenceConfig,
|
|
9691
|
+
milestone_id: milestoneId || null,
|
|
9582
9692
|
...additionalData
|
|
9583
9693
|
});
|
|
9584
9694
|
};
|
|
@@ -9682,6 +9792,63 @@ function InSceneQuestForm({
|
|
|
9682
9792
|
}
|
|
9683
9793
|
),
|
|
9684
9794
|
s
|
|
9795
|
+
)))))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Milestone"), /* @__PURE__ */ React16.createElement("div", { className: "relative" }, /* @__PURE__ */ React16.createElement(
|
|
9796
|
+
"button",
|
|
9797
|
+
{
|
|
9798
|
+
type: "button",
|
|
9799
|
+
onClick: () => setIsMilestoneDropdownOpen(!isMilestoneDropdownOpen),
|
|
9800
|
+
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"
|
|
9801
|
+
},
|
|
9802
|
+
/* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React16.createElement(FiTarget, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React16.createElement("span", { className: "text-slate-200 font-medium" }, ((_a = (milestones || []).find((m) => m.id === milestoneId)) == null ? void 0 : _a.name) || "Nenhum")),
|
|
9803
|
+
/* @__PURE__ */ React16.createElement(
|
|
9804
|
+
FiChevronDown6,
|
|
9805
|
+
{
|
|
9806
|
+
className: `text-slate-400 transition-transform duration-200 ${isMilestoneDropdownOpen ? "rotate-180" : ""}`
|
|
9807
|
+
}
|
|
9808
|
+
)
|
|
9809
|
+
), isMilestoneDropdownOpen && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
|
|
9810
|
+
"div",
|
|
9811
|
+
{
|
|
9812
|
+
className: "fixed inset-0 z-40",
|
|
9813
|
+
onClick: () => {
|
|
9814
|
+
setIsMilestoneDropdownOpen(false);
|
|
9815
|
+
setMilestoneSearchQuery("");
|
|
9816
|
+
}
|
|
9817
|
+
}
|
|
9818
|
+
), /* @__PURE__ */ React16.createElement("div", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-900 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden flex flex-col" }, /* @__PURE__ */ React16.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ React16.createElement(FiSearch5, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ React16.createElement(
|
|
9819
|
+
"input",
|
|
9820
|
+
{
|
|
9821
|
+
type: "text",
|
|
9822
|
+
autoFocus: true,
|
|
9823
|
+
placeholder: "Buscar ou criar milestone...",
|
|
9824
|
+
value: milestoneSearchQuery,
|
|
9825
|
+
onChange: (e) => setMilestoneSearchQuery(e.target.value),
|
|
9826
|
+
className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
|
|
9827
|
+
onClick: (e) => e.stopPropagation()
|
|
9828
|
+
}
|
|
9829
|
+
)), /* @__PURE__ */ React16.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ React16.createElement(
|
|
9830
|
+
"li",
|
|
9831
|
+
{
|
|
9832
|
+
onClick: () => handleSelectMilestone(""),
|
|
9833
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!milestoneId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
9834
|
+
},
|
|
9835
|
+
"Nenhum"
|
|
9836
|
+
), filteredMilestones.map((ms) => /* @__PURE__ */ React16.createElement(
|
|
9837
|
+
"li",
|
|
9838
|
+
{
|
|
9839
|
+
key: ms.id,
|
|
9840
|
+
onClick: () => handleSelectMilestone(ms.id),
|
|
9841
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${milestoneId === ms.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
9842
|
+
},
|
|
9843
|
+
ms.name
|
|
9844
|
+
)), milestoneSearchQuery.trim() && !filteredMilestones.some((ms) => ms.name.toLowerCase() === milestoneSearchQuery.toLowerCase().trim()) && /* @__PURE__ */ React16.createElement(
|
|
9845
|
+
"li",
|
|
9846
|
+
{
|
|
9847
|
+
onClick: () => handleCreateMilestone(milestoneSearchQuery),
|
|
9848
|
+
className: "px-3 py-3 text-sm cursor-pointer bg-indigo-600/20 text-indigo-200 hover:bg-indigo-600/40 transition-colors flex flex-col gap-0.5"
|
|
9849
|
+
},
|
|
9850
|
+
/* @__PURE__ */ React16.createElement("span", { className: "text-[10px] uppercase font-bold opacity-60" }, "Criar Novo Milestone"),
|
|
9851
|
+
/* @__PURE__ */ React16.createElement("span", { className: "font-medium" }, '"', milestoneSearchQuery, '"')
|
|
9685
9852
|
)))))), /* @__PURE__ */ React16.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React16.createElement("label", { className: "text-xs text-slate-300 font-medium uppercase tracking-wider" }, "Assignee (Respons\xE1vel)"), /* @__PURE__ */ React16.createElement("div", { className: "relative" }, /* @__PURE__ */ React16.createElement(
|
|
9686
9853
|
"button",
|
|
9687
9854
|
{
|
|
@@ -9689,7 +9856,7 @@ function InSceneQuestForm({
|
|
|
9689
9856
|
onClick: () => setIsAssigneeDropdownOpen(!isAssigneeDropdownOpen),
|
|
9690
9857
|
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"
|
|
9691
9858
|
},
|
|
9692
|
-
/* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React16.createElement(FiUser2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React16.createElement("span", { className: "text-slate-200 font-medium" }, ((
|
|
9859
|
+
/* @__PURE__ */ React16.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React16.createElement(FiUser2, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React16.createElement("span", { className: "text-slate-200 font-medium" }, ((_b = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _b.name) || ((_c = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _c.email) || "Nenhum")),
|
|
9693
9860
|
/* @__PURE__ */ React16.createElement(
|
|
9694
9861
|
FiChevronDown6,
|
|
9695
9862
|
{
|
|
@@ -10673,9 +10840,12 @@ function QuestDetailsPanel({
|
|
|
10673
10840
|
userRole,
|
|
10674
10841
|
currentDatasetName,
|
|
10675
10842
|
viewMembers = [],
|
|
10676
|
-
currentUser
|
|
10843
|
+
currentUser,
|
|
10844
|
+
milestones = [],
|
|
10845
|
+
onUpdateMilestones = () => {
|
|
10846
|
+
}
|
|
10677
10847
|
}) {
|
|
10678
|
-
var _a, _b;
|
|
10848
|
+
var _a, _b, _c;
|
|
10679
10849
|
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) || "";
|
|
10680
10850
|
const [rawTitle, setRawTitle] = useState19(initialRawTitle);
|
|
10681
10851
|
const prefixParts = ((node == null ? void 0 : node.name) || "").split(" - \xBB ");
|
|
@@ -10688,6 +10858,7 @@ function QuestDetailsPanel({
|
|
|
10688
10858
|
const [assigneeId, setAssigneeId] = useState19((node == null ? void 0 : node.assignee_id) || "");
|
|
10689
10859
|
const [description, setDescription] = useState19((node == null ? void 0 : node.description) ?? "");
|
|
10690
10860
|
const [intensity, setIntensity] = useState19((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
10861
|
+
const [milestoneId, setMilestoneId] = useState19((node == null ? void 0 : node.milestone_id) || "");
|
|
10691
10862
|
const [isStatusDropdownOpen, setIsStatusDropdownOpen] = useState19(false);
|
|
10692
10863
|
const [isAssigneeDropdownOpen, setIsAssigneeDropdownOpen] = useState19(false);
|
|
10693
10864
|
const [assigneeSearchQuery, setAssigneeSearchQuery] = useState19("");
|
|
@@ -10725,6 +10896,35 @@ function QuestDetailsPanel({
|
|
|
10725
10896
|
minWidth: 320,
|
|
10726
10897
|
maxWidth: maxPanelW
|
|
10727
10898
|
});
|
|
10899
|
+
const [isMilestoneDropdownOpen, setIsMilestoneDropdownOpen] = useState19(false);
|
|
10900
|
+
const [milestoneSearchQuery, setMilestoneSearchQuery] = useState19("");
|
|
10901
|
+
const activeMilestones = React19.useMemo(
|
|
10902
|
+
() => (milestones || []).filter((ms) => ms.status === "active"),
|
|
10903
|
+
[milestones]
|
|
10904
|
+
);
|
|
10905
|
+
const filteredMilestones = React19.useMemo(() => {
|
|
10906
|
+
const search = milestoneSearchQuery.toLowerCase().trim();
|
|
10907
|
+
if (!search) return activeMilestones;
|
|
10908
|
+
return activeMilestones.filter(
|
|
10909
|
+
(ms) => ms.name.toLowerCase().includes(search)
|
|
10910
|
+
);
|
|
10911
|
+
}, [activeMilestones, milestoneSearchQuery]);
|
|
10912
|
+
const handleSelectMilestone = (id) => {
|
|
10913
|
+
setMilestoneId(id);
|
|
10914
|
+
setIsMilestoneDropdownOpen(false);
|
|
10915
|
+
setMilestoneSearchQuery("");
|
|
10916
|
+
setHasUnsavedChanges(true);
|
|
10917
|
+
};
|
|
10918
|
+
const handleCreateMilestone = async (name) => {
|
|
10919
|
+
if (!name.trim()) return;
|
|
10920
|
+
const newId = `ms_${Date.now()}`;
|
|
10921
|
+
const newMs = { id: newId, name: name.trim(), status: "active" };
|
|
10922
|
+
await onUpdateMilestones([...milestones, newMs]);
|
|
10923
|
+
setMilestoneId(newId);
|
|
10924
|
+
setIsMilestoneDropdownOpen(false);
|
|
10925
|
+
setMilestoneSearchQuery("");
|
|
10926
|
+
setHasUnsavedChanges(true);
|
|
10927
|
+
};
|
|
10728
10928
|
useEffect16(() => {
|
|
10729
10929
|
setWidth(isReadMode ? 700 : 440);
|
|
10730
10930
|
}, [isReadMode, setWidth]);
|
|
@@ -10750,6 +10950,7 @@ function QuestDetailsPanel({
|
|
|
10750
10950
|
setReturnAssigneeId("");
|
|
10751
10951
|
setDescription((node == null ? void 0 : node.description) ?? "");
|
|
10752
10952
|
setIntensity((node == null ? void 0 : node.intensity) !== void 0 ? node.intensity : 0);
|
|
10953
|
+
setMilestoneId((node == null ? void 0 : node.milestone_id) || "");
|
|
10753
10954
|
setExistingSections((node == null ? void 0 : node.description_sections) || []);
|
|
10754
10955
|
setCustomProps(extractCustomPropsFromNode(node || {}));
|
|
10755
10956
|
setReviewStack((node == null ? void 0 : node.reviewStack) || []);
|
|
@@ -10762,6 +10963,7 @@ function QuestDetailsPanel({
|
|
|
10762
10963
|
custom_date: "",
|
|
10763
10964
|
next_assignee_id: ""
|
|
10764
10965
|
});
|
|
10966
|
+
setMilestoneId((node == null ? void 0 : node.milestone_id) || "");
|
|
10765
10967
|
setHasUnsavedChanges(false);
|
|
10766
10968
|
}
|
|
10767
10969
|
}, [node]);
|
|
@@ -11060,7 +11262,8 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11060
11262
|
reviewStack: currentReviewStack,
|
|
11061
11263
|
timeline: currentTimeline,
|
|
11062
11264
|
...extrasObj,
|
|
11063
|
-
version_node: node.version_node
|
|
11265
|
+
version_node: node.version_node,
|
|
11266
|
+
milestone_id: milestoneId || null
|
|
11064
11267
|
};
|
|
11065
11268
|
await onSave(dataToSave, keepOpen);
|
|
11066
11269
|
onDataUpdate(dataToSave);
|
|
@@ -11262,7 +11465,51 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11262
11465
|
maxLength: "10",
|
|
11263
11466
|
className: "flex-1 bg-slate-800/70 p-2 text-xs rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-400/60"
|
|
11264
11467
|
}
|
|
11265
|
-
))))), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "
|
|
11468
|
+
))))), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "Milestone"), /* @__PURE__ */ React19.createElement("div", { className: "relative" }, /* @__PURE__ */ React19.createElement(
|
|
11469
|
+
"button",
|
|
11470
|
+
{
|
|
11471
|
+
type: "button",
|
|
11472
|
+
onClick: () => canEdit && setIsMilestoneDropdownOpen(!isMilestoneDropdownOpen),
|
|
11473
|
+
disabled: !canEdit,
|
|
11474
|
+
className: `w-full bg-slate-800/70 p-2.5 text-sm rounded-lg border border-white/10 transition-colors flex items-center justify-between ${canEdit ? "hover:border-white/20 focus:ring-2 focus:ring-indigo-400/60 cursor-pointer" : "cursor-default opacity-80"}`
|
|
11475
|
+
},
|
|
11476
|
+
/* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React19.createElement(FiTarget3, { className: "text-slate-400", size: 14 }), /* @__PURE__ */ React19.createElement("span", { className: "text-slate-200 font-medium" }, ((_b = (milestones || []).find((m) => m.id === milestoneId)) == null ? void 0 : _b.name) || "Nenhum")),
|
|
11477
|
+
canEdit && /* @__PURE__ */ React19.createElement(FiChevronDown7, { className: `text-slate-400 transition-transform duration-200 ${isMilestoneDropdownOpen ? "rotate-180" : ""}` })
|
|
11478
|
+
), isMilestoneDropdownOpen && canEdit && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsMilestoneDropdownOpen(false) }), /* @__PURE__ */ React19.createElement("div", { className: "absolute top-full left-0 mt-1.5 w-full bg-slate-900 border border-white/10 rounded-lg shadow-[0_8px_30px_rgba(0,0,0,0.5)] z-50 overflow-hidden flex flex-col" }, /* @__PURE__ */ React19.createElement("div", { className: "p-2 border-b border-white/5 bg-white/5 flex items-center gap-2" }, /* @__PURE__ */ React19.createElement(FiSearch7, { className: "text-slate-500", size: 14 }), /* @__PURE__ */ React19.createElement(
|
|
11479
|
+
"input",
|
|
11480
|
+
{
|
|
11481
|
+
type: "text",
|
|
11482
|
+
autoFocus: true,
|
|
11483
|
+
placeholder: "Buscar ou criar milestone...",
|
|
11484
|
+
value: milestoneSearchQuery,
|
|
11485
|
+
onChange: (e) => setMilestoneSearchQuery(e.target.value),
|
|
11486
|
+
className: "bg-transparent border-none outline-none text-xs text-white placeholder-slate-500 w-full",
|
|
11487
|
+
onClick: (e) => e.stopPropagation()
|
|
11488
|
+
}
|
|
11489
|
+
)), /* @__PURE__ */ React19.createElement("ul", { className: "max-h-48 overflow-y-auto custom-scrollbar" }, /* @__PURE__ */ React19.createElement(
|
|
11490
|
+
"li",
|
|
11491
|
+
{
|
|
11492
|
+
onClick: () => handleSelectMilestone(""),
|
|
11493
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${!milestoneId ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
11494
|
+
},
|
|
11495
|
+
"Nenhum"
|
|
11496
|
+
), filteredMilestones.map((ms) => /* @__PURE__ */ React19.createElement(
|
|
11497
|
+
"li",
|
|
11498
|
+
{
|
|
11499
|
+
key: ms.id,
|
|
11500
|
+
onClick: () => handleSelectMilestone(ms.id),
|
|
11501
|
+
className: `px-3 py-2.5 text-sm cursor-pointer transition-colors flex items-center gap-2 ${milestoneId === ms.id ? "bg-indigo-500/20 text-white" : "text-slate-300 hover:bg-white/5 hover:text-white"}`
|
|
11502
|
+
},
|
|
11503
|
+
ms.name
|
|
11504
|
+
)), milestoneSearchQuery.trim() && !filteredMilestones.some((ms) => ms.name.toLowerCase() === milestoneSearchQuery.toLowerCase().trim()) && /* @__PURE__ */ React19.createElement(
|
|
11505
|
+
"li",
|
|
11506
|
+
{
|
|
11507
|
+
onClick: () => handleCreateMilestone(milestoneSearchQuery),
|
|
11508
|
+
className: "px-3 py-3 text-sm cursor-pointer bg-indigo-600/20 text-indigo-200 hover:bg-indigo-600/40 transition-colors flex flex-col gap-0.5"
|
|
11509
|
+
},
|
|
11510
|
+
/* @__PURE__ */ React19.createElement("span", { className: "text-[10px] uppercase font-bold opacity-60" }, "Criar Novo Milestone"),
|
|
11511
|
+
/* @__PURE__ */ React19.createElement("span", { className: "font-medium" }, '"', milestoneSearchQuery, '"')
|
|
11512
|
+
)))))), /* @__PURE__ */ React19.createElement("div", { className: "space-y-1.5 relative mt-2" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "Status da Quest"), /* @__PURE__ */ React19.createElement("div", { className: "relative" }, /* @__PURE__ */ React19.createElement(
|
|
11266
11513
|
"button",
|
|
11267
11514
|
{
|
|
11268
11515
|
type: "button",
|
|
@@ -11448,7 +11695,7 @@ ${noteText}` : noteText : entry.notes,
|
|
|
11448
11695
|
onClick: () => setIsReturnDropdownOpen(!isReturnDropdownOpen),
|
|
11449
11696
|
className: "w-full bg-slate-800/80 p-2 text-xs rounded-lg border border-white/10 hover:border-white/20 focus:outline-none focus:ring-1 focus:ring-purple-400/50 transition-colors flex items-center justify-between"
|
|
11450
11697
|
},
|
|
11451
|
-
/* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React19.createElement(FiUser3, { className: "text-slate-400", size: 12 }), /* @__PURE__ */ React19.createElement("span", { className: "text-slate-200 font-medium" }, ((
|
|
11698
|
+
/* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React19.createElement(FiUser3, { className: "text-slate-400", size: 12 }), /* @__PURE__ */ React19.createElement("span", { className: "text-slate-200 font-medium" }, ((_c = viewMembers.find((m) => String(m.id) === String(returnAssigneeId))) == null ? void 0 : _c.name) || "Selecionar respons\xE1vel...")),
|
|
11452
11699
|
/* @__PURE__ */ React19.createElement(FiChevronDown7, { className: `text-slate-400 transition-transform duration-200 ${isReturnDropdownOpen ? "rotate-180" : ""}`, size: 14 })
|
|
11453
11700
|
), isReturnDropdownOpen && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement("div", { className: "fixed inset-0 z-40", onClick: () => {
|
|
11454
11701
|
setIsReturnDropdownOpen(false);
|
|
@@ -13129,7 +13376,7 @@ function XViewScene({
|
|
|
13129
13376
|
check_user_permission,
|
|
13130
13377
|
get_view_members
|
|
13131
13378
|
}) {
|
|
13132
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
13379
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
13133
13380
|
const { data: session, status } = useSession();
|
|
13134
13381
|
const router = useRouter();
|
|
13135
13382
|
const searchParams = useSearchParams();
|
|
@@ -13958,20 +14205,23 @@ function XViewScene({
|
|
|
13958
14205
|
sceneResponse.data.scene.nodes = [];
|
|
13959
14206
|
sceneResponse.data.scene.links = [];
|
|
13960
14207
|
}
|
|
13961
|
-
sceneDataRef.current =
|
|
14208
|
+
sceneDataRef.current = {
|
|
14209
|
+
...sceneResponse.data.scene,
|
|
14210
|
+
milestones: sceneResponse.data.scene.milestones || []
|
|
14211
|
+
};
|
|
13962
14212
|
parentDataRef.current = sceneResponse.data.parent;
|
|
13963
14213
|
ancestryDataRef.current = sceneResponse.data.ancestry;
|
|
13964
14214
|
console.log(
|
|
13965
14215
|
"Console de sceneResponse.data.scene:",
|
|
13966
|
-
|
|
14216
|
+
sceneDataRef.current
|
|
13967
14217
|
);
|
|
13968
14218
|
console.log(
|
|
13969
14219
|
"Console de sceneResponse.data.parent:",
|
|
13970
|
-
|
|
14220
|
+
parentDataRef.current
|
|
13971
14221
|
);
|
|
13972
14222
|
console.log(
|
|
13973
14223
|
"Console de sceneResponse.data.ancestry:",
|
|
13974
|
-
|
|
14224
|
+
ancestryDataRef.current
|
|
13975
14225
|
);
|
|
13976
14226
|
setIsInitialized(true);
|
|
13977
14227
|
} else {
|
|
@@ -14103,6 +14353,9 @@ function XViewScene({
|
|
|
14103
14353
|
timeToYMap.set(ms, idx * TIMELINE_LAYER_SPACING_Y);
|
|
14104
14354
|
});
|
|
14105
14355
|
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
14356
|
+
let sumX = 0;
|
|
14357
|
+
let sumY = 0;
|
|
14358
|
+
let questCount = 0;
|
|
14106
14359
|
const positionGroups = /* @__PURE__ */ new Map();
|
|
14107
14360
|
const NODE_X_GAP = 22;
|
|
14108
14361
|
QUEST_STATUS_ORDER.forEach((statusName) => {
|
|
@@ -14206,6 +14459,9 @@ function XViewScene({
|
|
|
14206
14459
|
const lensTween = new Tween2(mesh.position).to({ x: finalX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
14207
14460
|
tweenGroup.add(lensTween);
|
|
14208
14461
|
lensTween.start();
|
|
14462
|
+
sumX += finalX;
|
|
14463
|
+
sumY += targetY;
|
|
14464
|
+
questCount++;
|
|
14209
14465
|
if (!timeInfo.isUndated && timeInfo.label && !mesh.getObjectByName("questDateLabel")) {
|
|
14210
14466
|
const dateSprite = createTextSprite(timeInfo.label, 36);
|
|
14211
14467
|
dateSprite.name = "questDateLabel";
|
|
@@ -14254,6 +14510,18 @@ function XViewScene({
|
|
|
14254
14510
|
}
|
|
14255
14511
|
});
|
|
14256
14512
|
});
|
|
14513
|
+
if (questCount > 0) {
|
|
14514
|
+
const { camera, controls } = stateRef.current;
|
|
14515
|
+
const centerX = sumX / questCount;
|
|
14516
|
+
const centerY = sumY / questCount;
|
|
14517
|
+
const targetFocus = new THREE3.Vector3(centerX, centerY, 0);
|
|
14518
|
+
const targetTween = new Tween2(controls.target).to({ x: targetFocus.x, y: targetFocus.y, z: targetFocus.z }, 1500).easing(Easing2.Cubic.InOut);
|
|
14519
|
+
tweenGroup.add(targetTween);
|
|
14520
|
+
targetTween.start();
|
|
14521
|
+
const camTween = new Tween2(camera.position).to({ x: targetFocus.x, y: targetFocus.y, z: 140 }, 1500).easing(Easing2.Cubic.InOut);
|
|
14522
|
+
tweenGroup.add(camTween);
|
|
14523
|
+
camTween.start();
|
|
14524
|
+
}
|
|
14257
14525
|
}, [addOrUpdateNodeMesh]);
|
|
14258
14526
|
useEffect22(() => {
|
|
14259
14527
|
if (!isInitialized || !sceneDataRef.current) return;
|
|
@@ -15476,7 +15744,8 @@ function XViewScene({
|
|
|
15476
15744
|
links: sceneDataRef2.current.links,
|
|
15477
15745
|
quest_nodes: graphDataRef.current[sceneConfigId2].nodes,
|
|
15478
15746
|
quest_links: graphDataRef.current[sceneConfigId2].links,
|
|
15479
|
-
quest_counter: currentCounter + 1
|
|
15747
|
+
quest_counter: currentCounter + 1,
|
|
15748
|
+
milestones: sceneDataRef2.current.milestones || []
|
|
15480
15749
|
};
|
|
15481
15750
|
try {
|
|
15482
15751
|
await actions.save_view_data(sceneSaveUrl2, sceneFileData);
|
|
@@ -17128,6 +17397,52 @@ function XViewScene({
|
|
|
17128
17397
|
},
|
|
17129
17398
|
[actionHandlerContext]
|
|
17130
17399
|
);
|
|
17400
|
+
const handleUpdateMilestones = useCallback4(
|
|
17401
|
+
async (newMilestones) => {
|
|
17402
|
+
var _a2, _b2, _c2;
|
|
17403
|
+
if (!sceneDataRef.current) return;
|
|
17404
|
+
sceneDataRef.current.milestones = newMilestones;
|
|
17405
|
+
setSceneVersion((v) => v + 1);
|
|
17406
|
+
const isView = ((_a2 = viewParams == null ? void 0 : viewParams.type) == null ? void 0 : _a2.toLowerCase()) === "view";
|
|
17407
|
+
if (!isView || !save_view_data || !sceneSaveUrl) return;
|
|
17408
|
+
const { nodeObjects, allLinks } = stateRef.current;
|
|
17409
|
+
const currentNodes = Object.values(nodeObjects || {}).map((mesh) => {
|
|
17410
|
+
const {
|
|
17411
|
+
_baseEmissiveIntensity,
|
|
17412
|
+
labelObject,
|
|
17413
|
+
labelOffset,
|
|
17414
|
+
timelineIntervalBar,
|
|
17415
|
+
timelineEndLabel,
|
|
17416
|
+
...serializableNodeData
|
|
17417
|
+
} = mesh.userData;
|
|
17418
|
+
return serializableNodeData;
|
|
17419
|
+
});
|
|
17420
|
+
const currentLinks = (allLinks || []).map((line) => {
|
|
17421
|
+
const { sourceNode, targetNode, ...serializableLinkData } = line.userData;
|
|
17422
|
+
return serializableLinkData;
|
|
17423
|
+
});
|
|
17424
|
+
const sceneFileData = {
|
|
17425
|
+
parent_dbs: sceneDataRef.current.parent_dbs,
|
|
17426
|
+
nodes: currentNodes,
|
|
17427
|
+
links: currentLinks,
|
|
17428
|
+
quest_nodes: ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || sceneDataRef.current.quest_nodes || [],
|
|
17429
|
+
quest_links: ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || sceneDataRef.current.quest_links || [],
|
|
17430
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
17431
|
+
milestones: newMilestones
|
|
17432
|
+
};
|
|
17433
|
+
try {
|
|
17434
|
+
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
17435
|
+
} catch (error) {
|
|
17436
|
+
console.error("Erro ao salvar milestones:", error);
|
|
17437
|
+
}
|
|
17438
|
+
},
|
|
17439
|
+
[
|
|
17440
|
+
sceneConfigId,
|
|
17441
|
+
sceneSaveUrl,
|
|
17442
|
+
save_view_data,
|
|
17443
|
+
viewParams == null ? void 0 : viewParams.type
|
|
17444
|
+
]
|
|
17445
|
+
);
|
|
17131
17446
|
const handleSaveCurrentView = useCallback4(async () => {
|
|
17132
17447
|
var _a2, _b2, _c2;
|
|
17133
17448
|
const { nodeObjects, allLinks } = stateRef.current;
|
|
@@ -17162,7 +17477,8 @@ function XViewScene({
|
|
|
17162
17477
|
links: currentLinks,
|
|
17163
17478
|
quest_nodes: isView ? ((_b2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _b2.nodes) || [] : sceneDataRef.current.quest_nodes || [],
|
|
17164
17479
|
quest_links: isView ? ((_c2 = parentDataRef.current[sceneConfigId]) == null ? void 0 : _c2.links) || [] : sceneDataRef.current.quest_links || [],
|
|
17165
|
-
quest_counter: sceneDataRef.current.quest_counter || 1
|
|
17480
|
+
quest_counter: sceneDataRef.current.quest_counter || 1,
|
|
17481
|
+
milestones: sceneDataRef.current.milestones || []
|
|
17166
17482
|
};
|
|
17167
17483
|
try {
|
|
17168
17484
|
await save_view_data(sceneSaveUrl, sceneFileData);
|
|
@@ -17499,7 +17815,9 @@ function XViewScene({
|
|
|
17499
17815
|
isOpen: isSidebarOpen,
|
|
17500
17816
|
onToggle: setIsSidebarOpen,
|
|
17501
17817
|
userRole: userPermissionRole,
|
|
17502
|
-
viewMembers
|
|
17818
|
+
viewMembers,
|
|
17819
|
+
milestones: ((_c = sceneDataRef.current) == null ? void 0 : _c.milestones) || [],
|
|
17820
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17503
17821
|
}
|
|
17504
17822
|
),
|
|
17505
17823
|
creationMode.isActive && /* @__PURE__ */ React27.createElement(
|
|
@@ -17523,8 +17841,8 @@ function XViewScene({
|
|
|
17523
17841
|
},
|
|
17524
17842
|
refEl: formRef,
|
|
17525
17843
|
existingTypes: existingNodeTypes,
|
|
17526
|
-
initialColor: (
|
|
17527
|
-
sourceTypes: (
|
|
17844
|
+
initialColor: (_d = creationMode.sourceNodeData) == null ? void 0 : _d.color,
|
|
17845
|
+
sourceTypes: (_e = creationMode.sourceNodeData) == null ? void 0 : _e.type,
|
|
17528
17846
|
onIntensityChange: handleGhostNodeIntensityChange,
|
|
17529
17847
|
onUploadFile: upload_file_action,
|
|
17530
17848
|
availableDatasets,
|
|
@@ -17553,8 +17871,8 @@ function XViewScene({
|
|
|
17553
17871
|
transition: "opacity 200ms ease-out"
|
|
17554
17872
|
},
|
|
17555
17873
|
refEl: formRef,
|
|
17556
|
-
fixedType: (
|
|
17557
|
-
fixedColor: (
|
|
17874
|
+
fixedType: (_f = versionMode.sourceNodeData) == null ? void 0 : _f.type,
|
|
17875
|
+
fixedColor: (_g = versionMode.sourceNodeData) == null ? void 0 : _g.color,
|
|
17558
17876
|
onUploadFile: upload_file_action,
|
|
17559
17877
|
availableNodes: allAvailableNodes,
|
|
17560
17878
|
availableAncestries: allAvailableAncestries
|
|
@@ -17582,8 +17900,10 @@ function XViewScene({
|
|
|
17582
17900
|
availableNodes: allAvailableNodes,
|
|
17583
17901
|
availableAncestries: allAvailableAncestries,
|
|
17584
17902
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
|
17585
|
-
questCounter: ((
|
|
17586
|
-
viewMembers
|
|
17903
|
+
questCounter: ((_h = sceneDataRef.current) == null ? void 0 : _h.quest_counter) || 1,
|
|
17904
|
+
viewMembers,
|
|
17905
|
+
milestones: ((_i = sceneDataRef.current) == null ? void 0 : _i.milestones) || [],
|
|
17906
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17587
17907
|
}
|
|
17588
17908
|
),
|
|
17589
17909
|
readingMode.isActive && readingMode.ancestry && /* @__PURE__ */ React27.createElement(
|
|
@@ -17715,7 +18035,9 @@ function XViewScene({
|
|
|
17715
18035
|
userRole: userPermissionRole,
|
|
17716
18036
|
currentDatasetName: detailsNodeDatasetInfo == null ? void 0 : detailsNodeDatasetInfo.datasetName,
|
|
17717
18037
|
viewMembers,
|
|
17718
|
-
currentUser: session == null ? void 0 : session.user
|
|
18038
|
+
currentUser: session == null ? void 0 : session.user,
|
|
18039
|
+
milestones: ((_j = sceneDataRef.current) == null ? void 0 : _j.milestones) || [],
|
|
18040
|
+
onUpdateMilestones: handleUpdateMilestones
|
|
17719
18041
|
}
|
|
17720
18042
|
),
|
|
17721
18043
|
detailsNode && !detailsNode.is_quest && /* @__PURE__ */ React27.createElement(
|
|
@@ -17900,7 +18222,7 @@ function XViewScene({
|
|
|
17900
18222
|
onClose: () => setIsImportModalOpen(false),
|
|
17901
18223
|
onConfirm: handleConfirmImport,
|
|
17902
18224
|
session,
|
|
17903
|
-
parentDbs: ((
|
|
18225
|
+
parentDbs: ((_k = sceneDataRef.current) == null ? void 0 : _k.parent_dbs) || [],
|
|
17904
18226
|
onFetchAvailableFiles: import_parent_file_modal_get,
|
|
17905
18227
|
currentViewName: viewParams == null ? void 0 : viewParams.name,
|
|
17906
18228
|
currentAncestries: ancestryDataRef.current || []
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.2.5-dev.
|
|
3
|
+
"version": "1.2.5-dev.47",
|
|
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",
|