@lv-x-software-house/x_view 1.2.5-dev.35 → 1.2.5-dev.36
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 +153 -4
- package/dist/index.mjs +153 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -622,8 +622,10 @@ function XViewSidebar({
|
|
|
622
622
|
},
|
|
623
623
|
isOpen,
|
|
624
624
|
onToggle,
|
|
625
|
-
userRole
|
|
626
|
-
|
|
625
|
+
userRole,
|
|
626
|
+
viewMembers = [],
|
|
627
|
+
onActivateQuestLens = () => {
|
|
628
|
+
}
|
|
627
629
|
}) {
|
|
628
630
|
const [query, setQuery] = (0, import_react2.useState)("");
|
|
629
631
|
const [showList, setShowList] = (0, import_react2.useState)(false);
|
|
@@ -633,12 +635,16 @@ function XViewSidebar({
|
|
|
633
635
|
const [isFilterMenuOpen, setIsFilterMenuOpen] = (0, import_react2.useState)(false);
|
|
634
636
|
const [filterCategory, setFilterCategory] = (0, import_react2.useState)("Type");
|
|
635
637
|
const [filterValue, setFilterValue] = (0, import_react2.useState)("");
|
|
638
|
+
const [questFilterAssignee, setQuestFilterAssignee] = (0, import_react2.useState)("");
|
|
639
|
+
const [questFilterStatus, setQuestFilterStatus] = (0, import_react2.useState)("");
|
|
640
|
+
const [isQuestLensMenuOpen, setIsQuestLensMenuOpen] = (0, import_react2.useState)(false);
|
|
636
641
|
const [isTypeDropdownOpen, setIsTypeDropdownOpen] = (0, import_react2.useState)(false);
|
|
637
642
|
const [highlightedTypeIndex, setHighlightedTypeIndex] = (0, import_react2.useState)(-1);
|
|
638
643
|
const containerRef = (0, import_react2.useRef)(null);
|
|
639
644
|
const inputRef = (0, import_react2.useRef)(null);
|
|
640
645
|
const filterMenuRef = (0, import_react2.useRef)(null);
|
|
641
646
|
const typeDropdownRef = (0, import_react2.useRef)(null);
|
|
647
|
+
const questLensRef = (0, import_react2.useRef)(null);
|
|
642
648
|
const ability = (0, import_react2.useMemo)(() => {
|
|
643
649
|
return defineAbilityFor(userRole);
|
|
644
650
|
}, [userRole]);
|
|
@@ -743,6 +749,17 @@ function XViewSidebar({
|
|
|
743
749
|
}
|
|
744
750
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
745
751
|
}, [isFilterMenuOpen, isTypeDropdownOpen]);
|
|
752
|
+
(0, import_react2.useEffect)(() => {
|
|
753
|
+
const handleClickOutsideQuest = (event) => {
|
|
754
|
+
if (questLensRef.current && !questLensRef.current.contains(event.target)) {
|
|
755
|
+
setIsQuestLensMenuOpen(false);
|
|
756
|
+
}
|
|
757
|
+
};
|
|
758
|
+
if (isQuestLensMenuOpen) {
|
|
759
|
+
document.addEventListener("mousedown", handleClickOutsideQuest);
|
|
760
|
+
}
|
|
761
|
+
return () => document.removeEventListener("mousedown", handleClickOutsideQuest);
|
|
762
|
+
}, [isQuestLensMenuOpen]);
|
|
746
763
|
(0, import_react2.useEffect)(() => {
|
|
747
764
|
if (!query) setSelectedNodeId(null);
|
|
748
765
|
}, [query]);
|
|
@@ -1034,7 +1051,58 @@ function XViewSidebar({
|
|
|
1034
1051
|
},
|
|
1035
1052
|
/* @__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("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), /* @__PURE__ */ import_react2.default.createElement("polyline", { points: "2 17 12 22 22 17" }), /* @__PURE__ */ import_react2.default.createElement("polyline", { points: "2 12 12 17 22 12" })),
|
|
1036
1053
|
"Ancestry Board"
|
|
1037
|
-
)
|
|
1054
|
+
), /* @__PURE__ */ import_react2.default.createElement("div", { className: "relative", ref: questLensRef }, /* @__PURE__ */ import_react2.default.createElement(
|
|
1055
|
+
"button",
|
|
1056
|
+
{
|
|
1057
|
+
onClick: () => setIsQuestLensMenuOpen(!isQuestLensMenuOpen),
|
|
1058
|
+
className: `${buttonBaseClass} ${isQuestLensMenuOpen || questFilterAssignee || questFilterStatus ? "bg-indigo-500/30 border-indigo-400" : ""}`,
|
|
1059
|
+
title: "Abrir filtros da Lente de Quests"
|
|
1060
|
+
},
|
|
1061
|
+
/* @__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("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), /* @__PURE__ */ import_react2.default.createElement("path", { d: "M9 12l2 2 4-4" })),
|
|
1062
|
+
"Quest Lens",
|
|
1063
|
+
(questFilterAssignee || questFilterStatus) && /* @__PURE__ */ import_react2.default.createElement("span", { className: "ml-1 px-1.5 py-0.5 rounded-full bg-indigo-500 text-[9px] font-bold" }, "!")
|
|
1064
|
+
), isQuestLensMenuOpen && /* @__PURE__ */ import_react2.default.createElement("div", { className: "absolute left-0 bottom-full mb-2 w-full p-4 rounded-xl bg-slate-900 border border-white/10 shadow-2xl z-50 flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-2 duration-200" }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Respons\xE1vel"), /* @__PURE__ */ import_react2.default.createElement(
|
|
1065
|
+
"select",
|
|
1066
|
+
{
|
|
1067
|
+
value: questFilterAssignee,
|
|
1068
|
+
onChange: (e) => setQuestFilterAssignee(e.target.value),
|
|
1069
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
1070
|
+
},
|
|
1071
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "" }, "Todos os Respons\xE1veis"),
|
|
1072
|
+
viewMembers.map((m) => /* @__PURE__ */ import_react2.default.createElement("option", { key: m.id, value: m.id }, m.name || m.email))
|
|
1073
|
+
)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Status"), /* @__PURE__ */ import_react2.default.createElement(
|
|
1074
|
+
"select",
|
|
1075
|
+
{
|
|
1076
|
+
value: questFilterStatus,
|
|
1077
|
+
onChange: (e) => setQuestFilterStatus(e.target.value),
|
|
1078
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
1079
|
+
},
|
|
1080
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "" }, "Todos (Exclui Done)"),
|
|
1081
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "Backlog" }, "Backlog"),
|
|
1082
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
1083
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "Review" }, "Review"),
|
|
1084
|
+
/* @__PURE__ */ import_react2.default.createElement("option", { value: "Done" }, "Done")
|
|
1085
|
+
)), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex gap-2 pt-1" }, /* @__PURE__ */ import_react2.default.createElement(
|
|
1086
|
+
"button",
|
|
1087
|
+
{
|
|
1088
|
+
onClick: () => {
|
|
1089
|
+
setQuestFilterAssignee("");
|
|
1090
|
+
setQuestFilterStatus("");
|
|
1091
|
+
},
|
|
1092
|
+
className: "flex-1 py-2 bg-white/5 hover:bg-white/10 text-slate-300 text-[11px] font-medium rounded-lg transition-colors border border-white/5"
|
|
1093
|
+
},
|
|
1094
|
+
"Limpar"
|
|
1095
|
+
), /* @__PURE__ */ import_react2.default.createElement(
|
|
1096
|
+
"button",
|
|
1097
|
+
{
|
|
1098
|
+
onClick: () => {
|
|
1099
|
+
onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
|
|
1100
|
+
setIsQuestLensMenuOpen(false);
|
|
1101
|
+
},
|
|
1102
|
+
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
|
+
},
|
|
1104
|
+
"Aplicar Lente"
|
|
1105
|
+
)))))), /* @__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(
|
|
1038
1106
|
"button",
|
|
1039
1107
|
{
|
|
1040
1108
|
onClick: handleSaveClick,
|
|
@@ -11947,6 +12015,9 @@ var TIMELINE_NODE_SPACING_X = 20;
|
|
|
11947
12015
|
var TIMELINE_INTERVAL_BAR_RADIUS = 0.2;
|
|
11948
12016
|
var TIMELINE_INTERVAL_BAR_OPACITY = 0.85;
|
|
11949
12017
|
var TIMELINE_GOLD_COLOR = 16766720;
|
|
12018
|
+
var QUEST_LENS_COLUMN_SPACING = 80;
|
|
12019
|
+
var QUEST_LENS_ROW_SPACING = 40;
|
|
12020
|
+
var QUEST_STATUS_ORDER = ["Backlog", "In Progress", "Review", "Done"];
|
|
11950
12021
|
var getAllNodeIdsFromTree = (treeNode) => {
|
|
11951
12022
|
const ids = /* @__PURE__ */ new Set();
|
|
11952
12023
|
function traverse(node) {
|
|
@@ -12646,6 +12717,82 @@ function XViewScene({
|
|
|
12646
12717
|
}
|
|
12647
12718
|
});
|
|
12648
12719
|
}, []);
|
|
12720
|
+
const handleActivateQuestLens = (0, import_react28.useCallback)(({ assigneeId, status: status2 }) => {
|
|
12721
|
+
var _a2;
|
|
12722
|
+
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
12723
|
+
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
12724
|
+
const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
|
|
12725
|
+
const filteredQuests = allQuests.filter((q) => {
|
|
12726
|
+
const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
|
|
12727
|
+
const matchStatus = !status2 ? q.status !== "Done" : String(q.status) === String(status2);
|
|
12728
|
+
return matchAssignee && matchStatus;
|
|
12729
|
+
});
|
|
12730
|
+
if (filteredQuests.length === 0) {
|
|
12731
|
+
console.warn("Nenhuma quest encontrada para os filtros selecionados.");
|
|
12732
|
+
return;
|
|
12733
|
+
}
|
|
12734
|
+
const questsByStatus = {
|
|
12735
|
+
Backlog: [],
|
|
12736
|
+
"In Progress": [],
|
|
12737
|
+
Review: [],
|
|
12738
|
+
Done: []
|
|
12739
|
+
};
|
|
12740
|
+
filteredQuests.forEach((q) => {
|
|
12741
|
+
if (questsByStatus[q.status]) {
|
|
12742
|
+
questsByStatus[q.status].push(q);
|
|
12743
|
+
}
|
|
12744
|
+
});
|
|
12745
|
+
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
12746
|
+
Object.keys(nodeObjects).forEach((id) => {
|
|
12747
|
+
const mesh = nodeObjects[id];
|
|
12748
|
+
const isFilteredQuest = filteredQuests.some(
|
|
12749
|
+
(q) => String(q.id) === String(id)
|
|
12750
|
+
);
|
|
12751
|
+
if (!isFilteredQuest) {
|
|
12752
|
+
if (mesh.material) {
|
|
12753
|
+
const fadeTween = new import_tween2.Tween(mesh.material).to({ opacity: 0.15 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
12754
|
+
tweenGroup.add(fadeTween);
|
|
12755
|
+
fadeTween.start();
|
|
12756
|
+
}
|
|
12757
|
+
if (mesh.userData.labelObject) {
|
|
12758
|
+
mesh.userData.labelObject.visible = false;
|
|
12759
|
+
}
|
|
12760
|
+
} else {
|
|
12761
|
+
if (mesh.material) {
|
|
12762
|
+
const fadeInTween = new import_tween2.Tween(mesh.material).to({ opacity: 1 }, 1200).easing(import_tween2.Easing.Cubic.Out);
|
|
12763
|
+
tweenGroup.add(fadeInTween);
|
|
12764
|
+
fadeInTween.start();
|
|
12765
|
+
}
|
|
12766
|
+
if (mesh.userData.labelObject) {
|
|
12767
|
+
mesh.userData.labelObject.visible = true;
|
|
12768
|
+
}
|
|
12769
|
+
}
|
|
12770
|
+
});
|
|
12771
|
+
QUEST_STATUS_ORDER.forEach((statusName, colIndex) => {
|
|
12772
|
+
if (status2 && status2 !== statusName) return;
|
|
12773
|
+
const questsInCol = questsByStatus[statusName];
|
|
12774
|
+
const colX = startX + colIndex * QUEST_LENS_COLUMN_SPACING;
|
|
12775
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
12776
|
+
const nodeId = String(q.id);
|
|
12777
|
+
let mesh = nodeObjects[nodeId];
|
|
12778
|
+
if (!mesh) {
|
|
12779
|
+
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
|
|
12780
|
+
}
|
|
12781
|
+
const targetY = (questsInCol.length - 1) * 0.5 * QUEST_LENS_ROW_SPACING - rowIndex * QUEST_LENS_ROW_SPACING;
|
|
12782
|
+
const lensTween = new import_tween2.Tween(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
12783
|
+
tweenGroup.add(lensTween);
|
|
12784
|
+
lensTween.start();
|
|
12785
|
+
if (mesh.userData.labelObject) {
|
|
12786
|
+
const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
|
|
12787
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, -2.5, 0)
|
|
12788
|
+
);
|
|
12789
|
+
const labelTween = new import_tween2.Tween(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(import_tween2.Easing.Cubic.InOut);
|
|
12790
|
+
tweenGroup.add(labelTween);
|
|
12791
|
+
labelTween.start();
|
|
12792
|
+
}
|
|
12793
|
+
});
|
|
12794
|
+
});
|
|
12795
|
+
}, [addOrUpdateNodeMesh]);
|
|
12649
12796
|
const handleVersionTimeline = (0, import_react28.useCallback)((sourceMesh, versionMeshes) => {
|
|
12650
12797
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
12651
12798
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
@@ -16166,13 +16313,15 @@ function XViewScene({
|
|
|
16166
16313
|
onOpenImportModal: () => setIsImportModalOpen(true),
|
|
16167
16314
|
importSuccessMessage,
|
|
16168
16315
|
onActivateTimeline: handleActivateTimeline,
|
|
16316
|
+
onActivateQuestLens: handleActivateQuestLens,
|
|
16169
16317
|
onOpenAncestryBoard: handleOpenAncestryBoard,
|
|
16170
16318
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
16171
16319
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
|
16172
16320
|
onNavigateBack: handleNavigateBack,
|
|
16173
16321
|
isOpen: isSidebarOpen,
|
|
16174
16322
|
onToggle: setIsSidebarOpen,
|
|
16175
|
-
userRole: userPermissionRole
|
|
16323
|
+
userRole: userPermissionRole,
|
|
16324
|
+
viewMembers
|
|
16176
16325
|
}
|
|
16177
16326
|
),
|
|
16178
16327
|
creationMode.isActive && /* @__PURE__ */ import_react28.default.createElement(
|
package/dist/index.mjs
CHANGED
|
@@ -583,8 +583,10 @@ function XViewSidebar({
|
|
|
583
583
|
},
|
|
584
584
|
isOpen,
|
|
585
585
|
onToggle,
|
|
586
|
-
userRole
|
|
587
|
-
|
|
586
|
+
userRole,
|
|
587
|
+
viewMembers = [],
|
|
588
|
+
onActivateQuestLens = () => {
|
|
589
|
+
}
|
|
588
590
|
}) {
|
|
589
591
|
const [query, setQuery] = useState2("");
|
|
590
592
|
const [showList, setShowList] = useState2(false);
|
|
@@ -594,12 +596,16 @@ function XViewSidebar({
|
|
|
594
596
|
const [isFilterMenuOpen, setIsFilterMenuOpen] = useState2(false);
|
|
595
597
|
const [filterCategory, setFilterCategory] = useState2("Type");
|
|
596
598
|
const [filterValue, setFilterValue] = useState2("");
|
|
599
|
+
const [questFilterAssignee, setQuestFilterAssignee] = useState2("");
|
|
600
|
+
const [questFilterStatus, setQuestFilterStatus] = useState2("");
|
|
601
|
+
const [isQuestLensMenuOpen, setIsQuestLensMenuOpen] = useState2(false);
|
|
597
602
|
const [isTypeDropdownOpen, setIsTypeDropdownOpen] = useState2(false);
|
|
598
603
|
const [highlightedTypeIndex, setHighlightedTypeIndex] = useState2(-1);
|
|
599
604
|
const containerRef = useRef2(null);
|
|
600
605
|
const inputRef = useRef2(null);
|
|
601
606
|
const filterMenuRef = useRef2(null);
|
|
602
607
|
const typeDropdownRef = useRef2(null);
|
|
608
|
+
const questLensRef = useRef2(null);
|
|
603
609
|
const ability = useMemo2(() => {
|
|
604
610
|
return defineAbilityFor(userRole);
|
|
605
611
|
}, [userRole]);
|
|
@@ -704,6 +710,17 @@ function XViewSidebar({
|
|
|
704
710
|
}
|
|
705
711
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
706
712
|
}, [isFilterMenuOpen, isTypeDropdownOpen]);
|
|
713
|
+
useEffect2(() => {
|
|
714
|
+
const handleClickOutsideQuest = (event) => {
|
|
715
|
+
if (questLensRef.current && !questLensRef.current.contains(event.target)) {
|
|
716
|
+
setIsQuestLensMenuOpen(false);
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
if (isQuestLensMenuOpen) {
|
|
720
|
+
document.addEventListener("mousedown", handleClickOutsideQuest);
|
|
721
|
+
}
|
|
722
|
+
return () => document.removeEventListener("mousedown", handleClickOutsideQuest);
|
|
723
|
+
}, [isQuestLensMenuOpen]);
|
|
707
724
|
useEffect2(() => {
|
|
708
725
|
if (!query) setSelectedNodeId(null);
|
|
709
726
|
}, [query]);
|
|
@@ -995,7 +1012,58 @@ function XViewSidebar({
|
|
|
995
1012
|
},
|
|
996
1013
|
/* @__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("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }), /* @__PURE__ */ React2.createElement("polyline", { points: "2 17 12 22 22 17" }), /* @__PURE__ */ React2.createElement("polyline", { points: "2 12 12 17 22 12" })),
|
|
997
1014
|
"Ancestry Board"
|
|
998
|
-
)
|
|
1015
|
+
), /* @__PURE__ */ React2.createElement("div", { className: "relative", ref: questLensRef }, /* @__PURE__ */ React2.createElement(
|
|
1016
|
+
"button",
|
|
1017
|
+
{
|
|
1018
|
+
onClick: () => setIsQuestLensMenuOpen(!isQuestLensMenuOpen),
|
|
1019
|
+
className: `${buttonBaseClass} ${isQuestLensMenuOpen || questFilterAssignee || questFilterStatus ? "bg-indigo-500/30 border-indigo-400" : ""}`,
|
|
1020
|
+
title: "Abrir filtros da Lente de Quests"
|
|
1021
|
+
},
|
|
1022
|
+
/* @__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("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }), /* @__PURE__ */ React2.createElement("path", { d: "M9 12l2 2 4-4" })),
|
|
1023
|
+
"Quest Lens",
|
|
1024
|
+
(questFilterAssignee || questFilterStatus) && /* @__PURE__ */ React2.createElement("span", { className: "ml-1 px-1.5 py-0.5 rounded-full bg-indigo-500 text-[9px] font-bold" }, "!")
|
|
1025
|
+
), isQuestLensMenuOpen && /* @__PURE__ */ React2.createElement("div", { className: "absolute left-0 bottom-full mb-2 w-full p-4 rounded-xl bg-slate-900 border border-white/10 shadow-2xl z-50 flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-2 duration-200" }, /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Respons\xE1vel"), /* @__PURE__ */ React2.createElement(
|
|
1026
|
+
"select",
|
|
1027
|
+
{
|
|
1028
|
+
value: questFilterAssignee,
|
|
1029
|
+
onChange: (e) => setQuestFilterAssignee(e.target.value),
|
|
1030
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
1031
|
+
},
|
|
1032
|
+
/* @__PURE__ */ React2.createElement("option", { value: "" }, "Todos os Respons\xE1veis"),
|
|
1033
|
+
viewMembers.map((m) => /* @__PURE__ */ React2.createElement("option", { key: m.id, value: m.id }, m.name || m.email))
|
|
1034
|
+
)), /* @__PURE__ */ React2.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React2.createElement("label", { className: "text-[10px] uppercase text-slate-400 font-bold tracking-widest" }, "Status"), /* @__PURE__ */ React2.createElement(
|
|
1035
|
+
"select",
|
|
1036
|
+
{
|
|
1037
|
+
value: questFilterStatus,
|
|
1038
|
+
onChange: (e) => setQuestFilterStatus(e.target.value),
|
|
1039
|
+
className: "w-full bg-slate-800 p-2 text-xs rounded border border-white/10 focus:outline-none focus:border-indigo-500/50 text-white appearance-none cursor-pointer"
|
|
1040
|
+
},
|
|
1041
|
+
/* @__PURE__ */ React2.createElement("option", { value: "" }, "Todos (Exclui Done)"),
|
|
1042
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Backlog" }, "Backlog"),
|
|
1043
|
+
/* @__PURE__ */ React2.createElement("option", { value: "In Progress" }, "In Progress"),
|
|
1044
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Review" }, "Review"),
|
|
1045
|
+
/* @__PURE__ */ React2.createElement("option", { value: "Done" }, "Done")
|
|
1046
|
+
)), /* @__PURE__ */ React2.createElement("div", { className: "flex gap-2 pt-1" }, /* @__PURE__ */ React2.createElement(
|
|
1047
|
+
"button",
|
|
1048
|
+
{
|
|
1049
|
+
onClick: () => {
|
|
1050
|
+
setQuestFilterAssignee("");
|
|
1051
|
+
setQuestFilterStatus("");
|
|
1052
|
+
},
|
|
1053
|
+
className: "flex-1 py-2 bg-white/5 hover:bg-white/10 text-slate-300 text-[11px] font-medium rounded-lg transition-colors border border-white/5"
|
|
1054
|
+
},
|
|
1055
|
+
"Limpar"
|
|
1056
|
+
), /* @__PURE__ */ React2.createElement(
|
|
1057
|
+
"button",
|
|
1058
|
+
{
|
|
1059
|
+
onClick: () => {
|
|
1060
|
+
onActivateQuestLens({ assigneeId: questFilterAssignee, status: questFilterStatus });
|
|
1061
|
+
setIsQuestLensMenuOpen(false);
|
|
1062
|
+
},
|
|
1063
|
+
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
|
+
},
|
|
1065
|
+
"Aplicar Lente"
|
|
1066
|
+
)))))), /* @__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(
|
|
999
1067
|
"button",
|
|
1000
1068
|
{
|
|
1001
1069
|
onClick: handleSaveClick,
|
|
@@ -11989,6 +12057,9 @@ var TIMELINE_NODE_SPACING_X = 20;
|
|
|
11989
12057
|
var TIMELINE_INTERVAL_BAR_RADIUS = 0.2;
|
|
11990
12058
|
var TIMELINE_INTERVAL_BAR_OPACITY = 0.85;
|
|
11991
12059
|
var TIMELINE_GOLD_COLOR = 16766720;
|
|
12060
|
+
var QUEST_LENS_COLUMN_SPACING = 80;
|
|
12061
|
+
var QUEST_LENS_ROW_SPACING = 40;
|
|
12062
|
+
var QUEST_STATUS_ORDER = ["Backlog", "In Progress", "Review", "Done"];
|
|
11992
12063
|
var getAllNodeIdsFromTree = (treeNode) => {
|
|
11993
12064
|
const ids = /* @__PURE__ */ new Set();
|
|
11994
12065
|
function traverse(node) {
|
|
@@ -12688,6 +12759,82 @@ function XViewScene({
|
|
|
12688
12759
|
}
|
|
12689
12760
|
});
|
|
12690
12761
|
}, []);
|
|
12762
|
+
const handleActivateQuestLens = useCallback4(({ assigneeId, status: status2 }) => {
|
|
12763
|
+
var _a2;
|
|
12764
|
+
const { nodeObjects, tweenGroup, graphGroup } = stateRef.current;
|
|
12765
|
+
if (!nodeObjects || !tweenGroup || !graphGroup) return;
|
|
12766
|
+
const allQuests = ((_a2 = sceneDataRef.current) == null ? void 0 : _a2.quest_nodes) || [];
|
|
12767
|
+
const filteredQuests = allQuests.filter((q) => {
|
|
12768
|
+
const matchAssignee = !assigneeId || String(q.assignee_id) === String(assigneeId);
|
|
12769
|
+
const matchStatus = !status2 ? q.status !== "Done" : String(q.status) === String(status2);
|
|
12770
|
+
return matchAssignee && matchStatus;
|
|
12771
|
+
});
|
|
12772
|
+
if (filteredQuests.length === 0) {
|
|
12773
|
+
console.warn("Nenhuma quest encontrada para os filtros selecionados.");
|
|
12774
|
+
return;
|
|
12775
|
+
}
|
|
12776
|
+
const questsByStatus = {
|
|
12777
|
+
Backlog: [],
|
|
12778
|
+
"In Progress": [],
|
|
12779
|
+
Review: [],
|
|
12780
|
+
Done: []
|
|
12781
|
+
};
|
|
12782
|
+
filteredQuests.forEach((q) => {
|
|
12783
|
+
if (questsByStatus[q.status]) {
|
|
12784
|
+
questsByStatus[q.status].push(q);
|
|
12785
|
+
}
|
|
12786
|
+
});
|
|
12787
|
+
const startX = -((QUEST_STATUS_ORDER.length - 1) * QUEST_LENS_COLUMN_SPACING) / 2;
|
|
12788
|
+
Object.keys(nodeObjects).forEach((id) => {
|
|
12789
|
+
const mesh = nodeObjects[id];
|
|
12790
|
+
const isFilteredQuest = filteredQuests.some(
|
|
12791
|
+
(q) => String(q.id) === String(id)
|
|
12792
|
+
);
|
|
12793
|
+
if (!isFilteredQuest) {
|
|
12794
|
+
if (mesh.material) {
|
|
12795
|
+
const fadeTween = new Tween2(mesh.material).to({ opacity: 0.15 }, 1200).easing(Easing2.Cubic.Out);
|
|
12796
|
+
tweenGroup.add(fadeTween);
|
|
12797
|
+
fadeTween.start();
|
|
12798
|
+
}
|
|
12799
|
+
if (mesh.userData.labelObject) {
|
|
12800
|
+
mesh.userData.labelObject.visible = false;
|
|
12801
|
+
}
|
|
12802
|
+
} else {
|
|
12803
|
+
if (mesh.material) {
|
|
12804
|
+
const fadeInTween = new Tween2(mesh.material).to({ opacity: 1 }, 1200).easing(Easing2.Cubic.Out);
|
|
12805
|
+
tweenGroup.add(fadeInTween);
|
|
12806
|
+
fadeInTween.start();
|
|
12807
|
+
}
|
|
12808
|
+
if (mesh.userData.labelObject) {
|
|
12809
|
+
mesh.userData.labelObject.visible = true;
|
|
12810
|
+
}
|
|
12811
|
+
}
|
|
12812
|
+
});
|
|
12813
|
+
QUEST_STATUS_ORDER.forEach((statusName, colIndex) => {
|
|
12814
|
+
if (status2 && status2 !== statusName) return;
|
|
12815
|
+
const questsInCol = questsByStatus[statusName];
|
|
12816
|
+
const colX = startX + colIndex * QUEST_LENS_COLUMN_SPACING;
|
|
12817
|
+
questsInCol.forEach((q, rowIndex) => {
|
|
12818
|
+
const nodeId = String(q.id);
|
|
12819
|
+
let mesh = nodeObjects[nodeId];
|
|
12820
|
+
if (!mesh) {
|
|
12821
|
+
mesh = addOrUpdateNodeMesh(q, new THREE3.Vector3(colX, 150, 0), true);
|
|
12822
|
+
}
|
|
12823
|
+
const targetY = (questsInCol.length - 1) * 0.5 * QUEST_LENS_ROW_SPACING - rowIndex * QUEST_LENS_ROW_SPACING;
|
|
12824
|
+
const lensTween = new Tween2(mesh.position).to({ x: colX, y: targetY, z: 0 }, 1500).easing(Easing2.Cubic.InOut);
|
|
12825
|
+
tweenGroup.add(lensTween);
|
|
12826
|
+
lensTween.start();
|
|
12827
|
+
if (mesh.userData.labelObject) {
|
|
12828
|
+
const labelTargetPos = new THREE3.Vector3(colX, targetY, 0).add(
|
|
12829
|
+
mesh.userData.labelOffset || new THREE3.Vector3(0, -2.5, 0)
|
|
12830
|
+
);
|
|
12831
|
+
const labelTween = new Tween2(mesh.userData.labelObject.position).to(labelTargetPos, 1500).easing(Easing2.Cubic.InOut);
|
|
12832
|
+
tweenGroup.add(labelTween);
|
|
12833
|
+
labelTween.start();
|
|
12834
|
+
}
|
|
12835
|
+
});
|
|
12836
|
+
});
|
|
12837
|
+
}, [addOrUpdateNodeMesh]);
|
|
12691
12838
|
const handleVersionTimeline = useCallback4((sourceMesh, versionMeshes) => {
|
|
12692
12839
|
const { tweenGroup, timelineIntervalsGroup } = stateRef.current;
|
|
12693
12840
|
if (!tweenGroup || !timelineIntervalsGroup || versionMeshes.length === 0)
|
|
@@ -16208,13 +16355,15 @@ function XViewScene({
|
|
|
16208
16355
|
onOpenImportModal: () => setIsImportModalOpen(true),
|
|
16209
16356
|
importSuccessMessage,
|
|
16210
16357
|
onActivateTimeline: handleActivateTimeline,
|
|
16358
|
+
onActivateQuestLens: handleActivateQuestLens,
|
|
16211
16359
|
onOpenAncestryBoard: handleOpenAncestryBoard,
|
|
16212
16360
|
viewType: viewParams == null ? void 0 : viewParams.type,
|
|
16213
16361
|
viewName: viewParams == null ? void 0 : viewParams.name,
|
|
16214
16362
|
onNavigateBack: handleNavigateBack,
|
|
16215
16363
|
isOpen: isSidebarOpen,
|
|
16216
16364
|
onToggle: setIsSidebarOpen,
|
|
16217
|
-
userRole: userPermissionRole
|
|
16365
|
+
userRole: userPermissionRole,
|
|
16366
|
+
viewMembers
|
|
16218
16367
|
}
|
|
16219
16368
|
),
|
|
16220
16369
|
creationMode.isActive && /* @__PURE__ */ React27.createElement(
|
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.36",
|
|
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",
|