@lv-x-software-house/x_view 1.2.5-dev.32 → 1.2.5-dev.34
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 +122 -76
- package/dist/index.mjs +122 -76
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8843,7 +8843,6 @@ function InSceneQuestForm({
|
|
|
8843
8843
|
}
|
|
8844
8844
|
};
|
|
8845
8845
|
const handleSubmit = (e) => {
|
|
8846
|
-
var _a2, _b2, _c, _d;
|
|
8847
8846
|
e.preventDefault();
|
|
8848
8847
|
if (!name.trim()) {
|
|
8849
8848
|
alert("O campo 'T\xEDtulo' \xE9 obrigat\xF3rio.");
|
|
@@ -8853,21 +8852,7 @@ function InSceneQuestForm({
|
|
|
8853
8852
|
customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
|
|
8854
8853
|
);
|
|
8855
8854
|
const processedSections = processDescriptionForSave(description, []);
|
|
8856
|
-
const initialTimeline = [
|
|
8857
|
-
createTimelineEntry(
|
|
8858
|
-
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
|
|
8859
|
-
`Quest criada por ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}.`,
|
|
8860
|
-
"quest_created"
|
|
8861
|
-
)
|
|
8862
|
-
];
|
|
8863
|
-
if (assigneeId) {
|
|
8864
|
-
initialTimeline.push(createTimelineEntry(
|
|
8865
|
-
((_c = session == null ? void 0 : session.user) == null ? void 0 : _c.id) || "unknown",
|
|
8866
|
-
`Quest atribu\xEDda para ${((_d = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _d.name) || "respons\xE1vel"}.`,
|
|
8867
|
-
"assignee_changed",
|
|
8868
|
-
{ metadata: { to_assignee_id: assigneeId } }
|
|
8869
|
-
));
|
|
8870
|
-
}
|
|
8855
|
+
const initialTimeline = [];
|
|
8871
8856
|
onSave({
|
|
8872
8857
|
name: standardizedName,
|
|
8873
8858
|
// SALVA O NOME FORMATADO
|
|
@@ -9711,25 +9696,20 @@ var import_fi18 = require("react-icons/fi");
|
|
|
9711
9696
|
// src/components/QuestTimeline.jsx
|
|
9712
9697
|
var import_react19 = __toESM(require("react"));
|
|
9713
9698
|
var import_fi17 = require("react-icons/fi");
|
|
9714
|
-
var
|
|
9715
|
-
"quest_created": { icon: import_fi17.FiPlusCircle, color: "text-sky-400", bg: "bg-sky-400/10" },
|
|
9716
|
-
"assignee_changed": { icon: import_fi17.FiUserPlus, color: "text-indigo-400", bg: "bg-indigo-400/10" },
|
|
9717
|
-
"status_changed": { icon: import_fi17.FiRotateCcw, color: "text-amber-400", bg: "bg-amber-400/10" },
|
|
9718
|
-
"review_cycle_started": { icon: import_fi17.FiSearch, color: "text-purple-400", bg: "bg-purple-400/10" },
|
|
9719
|
-
"review_completed": { icon: import_fi17.FiCheckSquare, color: "text-emerald-400", bg: "bg-emerald-400/10" },
|
|
9720
|
-
"comment": { icon: import_fi17.FiMessageSquare, color: "text-slate-400", bg: "bg-slate-400/10" },
|
|
9721
|
-
"quest_finished": { icon: import_fi17.FiTarget, color: "text-green-400", bg: "bg-green-400/10" },
|
|
9722
|
-
"default": { icon: import_fi17.FiGitCommit, color: "text-slate-500", bg: "bg-slate-500/10" }
|
|
9723
|
-
};
|
|
9699
|
+
var DEFAULT_ICON_CONFIG = { icon: import_fi17.FiGitCommit, color: "text-indigo-400", bg: "bg-indigo-400/10" };
|
|
9724
9700
|
function QuestTimeline({
|
|
9725
9701
|
timeline = [],
|
|
9726
9702
|
viewMembers = [],
|
|
9727
|
-
onOpenImageViewer
|
|
9703
|
+
onOpenImageViewer,
|
|
9704
|
+
onAddNote,
|
|
9705
|
+
// Nova prop para adicionar nota a uma etapa específica
|
|
9706
|
+
canEdit = true
|
|
9728
9707
|
}) {
|
|
9729
9708
|
const sortedTimeline = [...timeline].sort((a, b) => b.timestamp - a.timestamp);
|
|
9730
9709
|
const getMemberName = (userId) => {
|
|
9731
|
-
|
|
9732
|
-
|
|
9710
|
+
if (!userId) return "Sistema";
|
|
9711
|
+
const member = viewMembers.find((m) => String(m.id) === String(userId));
|
|
9712
|
+
return (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || userId;
|
|
9733
9713
|
};
|
|
9734
9714
|
const formatDate = (timestamp) => {
|
|
9735
9715
|
const date = new Date(timestamp);
|
|
@@ -9744,10 +9724,22 @@ function QuestTimeline({
|
|
|
9744
9724
|
return /* @__PURE__ */ import_react19.default.createElement("div", { className: "py-6 flex flex-col items-center justify-center gap-2 border border-white/5 bg-white/5 rounded-xl" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiAlertCircle, { className: "text-slate-600", size: 16 }), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-[10px] text-slate-500 font-light uppercase tracking-widest" }, "Nenhum hist\xF3rico dispon\xEDvel"));
|
|
9745
9725
|
}
|
|
9746
9726
|
return /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ import_react19.default.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ import_react19.default.createElement("div", { className: "relative pl-10 space-y-6 before:content-[''] before:absolute before:left-[21px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
|
|
9747
|
-
const config =
|
|
9727
|
+
const config = DEFAULT_ICON_CONFIG;
|
|
9748
9728
|
const Icon = config.icon;
|
|
9749
9729
|
const actorName = getMemberName(event.actorId);
|
|
9750
|
-
return /* @__PURE__ */ import_react19.default.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ import_react19.default.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ import_react19.default.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ import_react19.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("
|
|
9730
|
+
return /* @__PURE__ */ import_react19.default.createElement("div", { key: event.id || index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ import_react19.default.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ import_react19.default.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ import_react19.default.createElement("div", { className: "group space-y-1" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), canEdit && onAddNote && /* @__PURE__ */ import_react19.default.createElement(
|
|
9731
|
+
"button",
|
|
9732
|
+
{
|
|
9733
|
+
onClick: () => onAddNote(event),
|
|
9734
|
+
className: "opacity-0 group-hover:opacity-100 p-1 rounded-md hover:bg-white/5 text-slate-500 hover:text-indigo-400 transition-all",
|
|
9735
|
+
title: "Adicionar detalhe/anexo a esta etapa"
|
|
9736
|
+
},
|
|
9737
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi17.FiPlusCircle, { size: 12 })
|
|
9738
|
+
)), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), event.notes && /* @__PURE__ */ import_react19.default.createElement("div", { className: "mt-1 py-1 px-2 rounded bg-indigo-500/5 border-l-2 border-indigo-500/30" }, /* @__PURE__ */ import_react19.default.createElement("p", { className: "text-[11px] text-slate-300 italic whitespace-pre-wrap" }, event.notes)), (event.from_status || event.to_status) && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => {
|
|
9739
|
+
const isAssigneeId = key.toLowerCase().includes("assignee_id") || key.toLowerCase().includes("respons\xE1vel") || key.toLowerCase().includes("assignee id");
|
|
9740
|
+
const displayValue = isAssigneeId && typeof value === "string" ? getMemberName(value) : typeof value === "string" ? value : JSON.stringify(value);
|
|
9741
|
+
return /* @__PURE__ */ import_react19.default.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ import_react19.default.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ import_react19.default.createElement("span", { className: `${isAssigneeId ? "text-indigo-300 font-medium" : "text-slate-300"} truncate font-mono` }, displayValue));
|
|
9742
|
+
})), event.links && event.links.length > 0 && /* @__PURE__ */ import_react19.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ import_react19.default.createElement(
|
|
9751
9743
|
"a",
|
|
9752
9744
|
{
|
|
9753
9745
|
key: lIdx,
|
|
@@ -9764,10 +9756,10 @@ function QuestTimeline({
|
|
|
9764
9756
|
key: iIdx,
|
|
9765
9757
|
type: "button",
|
|
9766
9758
|
onClick: () => onOpenImageViewer == null ? void 0 : onOpenImageViewer(event.images, iIdx),
|
|
9767
|
-
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group"
|
|
9759
|
+
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group/img"
|
|
9768
9760
|
},
|
|
9769
9761
|
/* @__PURE__ */ import_react19.default.createElement("img", { src: img.value, alt: img.name, className: "w-full h-full object-cover" }),
|
|
9770
|
-
/* @__PURE__ */ import_react19.default.createElement("div", { className: "absolute inset-0 bg-slate-900/40 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiSearch, { size: 12, className: "text-white" }))
|
|
9762
|
+
/* @__PURE__ */ import_react19.default.createElement("div", { className: "absolute inset-0 bg-slate-900/40 opacity-0 group-hover/img:opacity-100 flex items-center justify-center transition-opacity" }, /* @__PURE__ */ import_react19.default.createElement(import_fi17.FiSearch, { size: 12, className: "text-white" }))
|
|
9771
9763
|
)))));
|
|
9772
9764
|
})));
|
|
9773
9765
|
}
|
|
@@ -9833,6 +9825,8 @@ function QuestDetailsPanel({
|
|
|
9833
9825
|
const [noteLinks, setNoteLinks] = (0, import_react20.useState)([]);
|
|
9834
9826
|
const [noteImages, setNoteImages] = (0, import_react20.useState)([]);
|
|
9835
9827
|
const [isNoteFormOpen, setIsNoteFormOpen] = (0, import_react20.useState)(false);
|
|
9828
|
+
const [editingEntryId, setEditingEntryId] = (0, import_react20.useState)(null);
|
|
9829
|
+
const [editingEntryLabel, setEditingEntryLabel] = (0, import_react20.useState)("");
|
|
9836
9830
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
9837
9831
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
9838
9832
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -9923,12 +9917,11 @@ function QuestDetailsPanel({
|
|
|
9923
9917
|
const actorName = (currentUser == null ? void 0 : currentUser.name) || "Revisor";
|
|
9924
9918
|
const targetMember = viewMembers.find((m) => String(m.id) === String(returnAssigneeId));
|
|
9925
9919
|
const targetName = (targetMember == null ? void 0 : targetMember.name) || "executor";
|
|
9926
|
-
const newEvent =
|
|
9927
|
-
type: "review_returned",
|
|
9928
|
-
timestamp: Date.now(),
|
|
9920
|
+
const newEvent = createTimelineEntry(
|
|
9929
9921
|
actorId,
|
|
9930
|
-
|
|
9931
|
-
|
|
9922
|
+
`Status "In Progress" - Respons\xE1vel: ${targetName}`,
|
|
9923
|
+
"status_changed"
|
|
9924
|
+
);
|
|
9932
9925
|
const updatedTimeline = [...timeline, newEvent];
|
|
9933
9926
|
const updatedStatus = "In Progress";
|
|
9934
9927
|
const updatedColor = "#eab308";
|
|
@@ -9964,14 +9957,30 @@ function QuestDetailsPanel({
|
|
|
9964
9957
|
}
|
|
9965
9958
|
};
|
|
9966
9959
|
const handleAddTimelineNote = async () => {
|
|
9967
|
-
if (!noteText.trim() || isSaving) return;
|
|
9960
|
+
if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
|
|
9968
9961
|
setIsSaving(true);
|
|
9969
9962
|
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9963
|
+
let updatedTimeline;
|
|
9964
|
+
if (editingEntryId) {
|
|
9965
|
+
updatedTimeline = timeline.map((entry) => {
|
|
9966
|
+
if (entry.id === editingEntryId) {
|
|
9967
|
+
return {
|
|
9968
|
+
...entry,
|
|
9969
|
+
notes: noteText.trim() ? entry.notes ? `${entry.notes}
|
|
9970
|
+
${noteText}` : noteText : entry.notes,
|
|
9971
|
+
links: [...entry.links || [], ...noteLinks],
|
|
9972
|
+
images: [...entry.images || [], ...noteImages]
|
|
9973
|
+
};
|
|
9974
|
+
}
|
|
9975
|
+
return entry;
|
|
9976
|
+
});
|
|
9977
|
+
} else {
|
|
9978
|
+
const newEntry = createTimelineEntry(actorId, noteText, "comment", {
|
|
9979
|
+
links: noteLinks,
|
|
9980
|
+
images: noteImages
|
|
9981
|
+
});
|
|
9982
|
+
updatedTimeline = [...timeline, newEntry];
|
|
9983
|
+
}
|
|
9975
9984
|
try {
|
|
9976
9985
|
const nodeToSave = {
|
|
9977
9986
|
...node,
|
|
@@ -9984,12 +9993,26 @@ function QuestDetailsPanel({
|
|
|
9984
9993
|
setNoteLinks([]);
|
|
9985
9994
|
setNoteImages([]);
|
|
9986
9995
|
setIsNoteFormOpen(false);
|
|
9996
|
+
setEditingEntryId(null);
|
|
9997
|
+
setEditingEntryLabel("");
|
|
9987
9998
|
} catch (error) {
|
|
9988
9999
|
console.error("Erro ao adicionar nota:", error);
|
|
9989
10000
|
} finally {
|
|
9990
10001
|
setIsSaving(false);
|
|
9991
10002
|
}
|
|
9992
10003
|
};
|
|
10004
|
+
const handleOpenNoteForEntry = (entry) => {
|
|
10005
|
+
setEditingEntryId(entry.id);
|
|
10006
|
+
setEditingEntryLabel(entry.description);
|
|
10007
|
+
setNoteText("");
|
|
10008
|
+
setNoteLinks([]);
|
|
10009
|
+
setNoteImages([]);
|
|
10010
|
+
setIsNoteFormOpen(true);
|
|
10011
|
+
setTimeout(() => {
|
|
10012
|
+
const form = document.getElementById("quest-note-form");
|
|
10013
|
+
form == null ? void 0 : form.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
10014
|
+
}, 100);
|
|
10015
|
+
};
|
|
9993
10016
|
const addLinkToNote = () => {
|
|
9994
10017
|
setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
|
|
9995
10018
|
};
|
|
@@ -10011,8 +10034,18 @@ function QuestDetailsPanel({
|
|
|
10011
10034
|
const handleStatusChange = (newStatus) => {
|
|
10012
10035
|
setStatus(newStatus);
|
|
10013
10036
|
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
10037
|
+
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
10038
|
+
const currentAssignee = viewMembers.find((m) => String(m.id) === String(assigneeId));
|
|
10039
|
+
const assigneeName = (currentAssignee == null ? void 0 : currentAssignee.name) || (currentAssignee == null ? void 0 : currentAssignee.email) || "Nenhum";
|
|
10040
|
+
const newEvent = createTimelineEntry(
|
|
10041
|
+
actorId,
|
|
10042
|
+
`Status "${newStatus}" - Respons\xE1vel: ${assigneeName}`,
|
|
10043
|
+
"status_changed"
|
|
10044
|
+
);
|
|
10045
|
+
const newTimeline = [...timeline, newEvent];
|
|
10046
|
+
setTimeline(newTimeline);
|
|
10014
10047
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
10015
|
-
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
10048
|
+
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor, timeline: newTimeline });
|
|
10016
10049
|
setHasUnsavedChanges(true);
|
|
10017
10050
|
};
|
|
10018
10051
|
const handleAddType = (newType) => {
|
|
@@ -10233,13 +10266,11 @@ function QuestDetailsPanel({
|
|
|
10233
10266
|
{
|
|
10234
10267
|
onClick: () => {
|
|
10235
10268
|
setAssigneeId("");
|
|
10236
|
-
const newTimeline = [...timeline,
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
description: `Respons\xE1vel removido.`
|
|
10242
|
-
}];
|
|
10269
|
+
const newTimeline = [...timeline, createTimelineEntry(
|
|
10270
|
+
(currentUser == null ? void 0 : currentUser.id) || "unknown",
|
|
10271
|
+
`Status "${status}" - Respons\xE1vel: Nenhum`,
|
|
10272
|
+
"status_changed"
|
|
10273
|
+
)];
|
|
10243
10274
|
setTimeline(newTimeline);
|
|
10244
10275
|
setHasUnsavedChanges(true);
|
|
10245
10276
|
setIsAssigneeDropdownOpen(false);
|
|
@@ -10267,13 +10298,11 @@ function QuestDetailsPanel({
|
|
|
10267
10298
|
key: member.id,
|
|
10268
10299
|
onClick: () => {
|
|
10269
10300
|
setAssigneeId(member.id);
|
|
10270
|
-
const newTimeline = [...timeline,
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
description: `Quest atribu\xEDda para ${member.name || member.email}.`
|
|
10276
|
-
}];
|
|
10301
|
+
const newTimeline = [...timeline, createTimelineEntry(
|
|
10302
|
+
(currentUser == null ? void 0 : currentUser.id) || "unknown",
|
|
10303
|
+
`Status "${status}" - Respons\xE1vel: ${member.name || member.email}`,
|
|
10304
|
+
"status_changed"
|
|
10305
|
+
)];
|
|
10277
10306
|
setTimeline(newTimeline);
|
|
10278
10307
|
setHasUnsavedChanges(true);
|
|
10279
10308
|
setIsAssigneeDropdownOpen(false);
|
|
@@ -10351,17 +10380,32 @@ function QuestDetailsPanel({
|
|
|
10351
10380
|
"button",
|
|
10352
10381
|
{
|
|
10353
10382
|
type: "button",
|
|
10354
|
-
onClick: () =>
|
|
10383
|
+
onClick: () => {
|
|
10384
|
+
if (isNoteFormOpen && editingEntryId) {
|
|
10385
|
+
setEditingEntryId(null);
|
|
10386
|
+
setEditingEntryLabel("");
|
|
10387
|
+
setNoteText("");
|
|
10388
|
+
setNoteLinks([]);
|
|
10389
|
+
setNoteImages([]);
|
|
10390
|
+
} else {
|
|
10391
|
+
setIsNoteFormOpen(!isNoteFormOpen);
|
|
10392
|
+
setEditingEntryId(null);
|
|
10393
|
+
setEditingEntryLabel("");
|
|
10394
|
+
}
|
|
10395
|
+
},
|
|
10355
10396
|
className: "flex items-center gap-1.5 px-2 py-1 text-[10px] rounded-md bg-white/5 hover:bg-white/10 border border-white/10 transition-colors text-slate-300"
|
|
10356
10397
|
},
|
|
10357
|
-
isNoteFormOpen ? /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 12 }) : /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 12 }),
|
|
10358
|
-
isNoteFormOpen ? "Cancelar" : "Nova Nota"
|
|
10359
|
-
)), isNoteFormOpen && /* @__PURE__ */ import_react20.default.createElement("div", { className: "mb-6 p-4 rounded-xl bg-white/5 border border-white/5 space-y-3 animate-in fade-in slide-in-from-top-2" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
10398
|
+
isNoteFormOpen && !editingEntryId ? /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 12 }) : /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 12 }),
|
|
10399
|
+
isNoteFormOpen && !editingEntryId ? "Cancelar" : "Nova Nota"
|
|
10400
|
+
)), isNoteFormOpen && /* @__PURE__ */ import_react20.default.createElement("div", { id: "quest-note-form", className: "mb-6 p-4 rounded-xl bg-white/5 border border-white/5 space-y-3 animate-in fade-in slide-in-from-top-2 border-l-4 border-l-indigo-500/40" }, editingEntryId && /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between mb-2 pb-2 border-b border-white/5" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-[10px] text-indigo-400 font-bold uppercase tracking-wider" }, "Adicionando \xE0 etapa:"), /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-xs text-slate-300 italic truncate max-w-[250px]" }, editingEntryLabel)), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: () => {
|
|
10401
|
+
setIsNoteFormOpen(false);
|
|
10402
|
+
setEditingEntryId(null);
|
|
10403
|
+
}, className: "text-slate-500 hover:text-white" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 14 }))), /* @__PURE__ */ import_react20.default.createElement(
|
|
10360
10404
|
"textarea",
|
|
10361
10405
|
{
|
|
10362
10406
|
value: noteText,
|
|
10363
10407
|
onChange: (e) => setNoteText(e.target.value),
|
|
10364
|
-
placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10408
|
+
placeholder: editingEntryId ? "Adicione uma observa\xE7\xE3o a esta etapa..." : "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10365
10409
|
className: "w-full bg-slate-900/50 p-3 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-500/50 min-h-[80px] resize-none"
|
|
10366
10410
|
}
|
|
10367
10411
|
), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react20.default.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Links"), /* @__PURE__ */ import_react20.default.createElement("button", { type: "button", onClick: addLinkToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 10 }), " Adicionar Link")), noteLinks.length > 0 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, noteLinks.map((link) => /* @__PURE__ */ import_react20.default.createElement("div", { key: link.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
@@ -10396,16 +10440,18 @@ function QuestDetailsPanel({
|
|
|
10396
10440
|
{
|
|
10397
10441
|
type: "button",
|
|
10398
10442
|
onClick: handleAddTimelineNote,
|
|
10399
|
-
disabled: !noteText.trim() || isSaving,
|
|
10443
|
+
disabled: !noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving,
|
|
10400
10444
|
className: "px-3 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-semibold transition-colors disabled:opacity-50"
|
|
10401
10445
|
},
|
|
10402
|
-
"Adicionar ao Hist\xF3rico"
|
|
10446
|
+
editingEntryId ? "Salvar nesta Etapa" : "Adicionar ao Hist\xF3rico"
|
|
10403
10447
|
))), /* @__PURE__ */ import_react20.default.createElement(
|
|
10404
10448
|
QuestTimeline,
|
|
10405
10449
|
{
|
|
10406
10450
|
timeline,
|
|
10407
10451
|
viewMembers,
|
|
10408
|
-
onOpenImageViewer
|
|
10452
|
+
onOpenImageViewer,
|
|
10453
|
+
canEdit,
|
|
10454
|
+
onAddNote: handleOpenNoteForEntry
|
|
10409
10455
|
}
|
|
10410
10456
|
)), /* @__PURE__ */ import_react20.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react20.default.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Node (Size)"), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
|
|
10411
10457
|
const isSelected = size === s;
|
|
@@ -13961,7 +14007,7 @@ function XViewScene({
|
|
|
13961
14007
|
} = questNode;
|
|
13962
14008
|
const newTimeline = [...cleanQuestNode.timeline || [], createTimelineEntry(
|
|
13963
14009
|
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
|
|
13964
|
-
`
|
|
14010
|
+
`Status "In Progress" - Respons\xE1vel: ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}`,
|
|
13965
14011
|
"status_changed"
|
|
13966
14012
|
)];
|
|
13967
14013
|
const updatedNode = {
|
|
@@ -13999,15 +14045,15 @@ function XViewScene({
|
|
|
13999
14045
|
nextIdxToAssign = currentReviewerIdx + 1;
|
|
14000
14046
|
newTimeline.push(createTimelineEntry(
|
|
14001
14047
|
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || cleanQuestNode.assignee_id,
|
|
14002
|
-
`Review
|
|
14003
|
-
"
|
|
14048
|
+
`Status "Review" - Conclu\xEDda por ${((_b2 = viewMembers.find((m) => m.id === cleanQuestNode.assignee_id)) == null ? void 0 : _b2.name) || "revisor"}`,
|
|
14049
|
+
"status_changed"
|
|
14004
14050
|
));
|
|
14005
14051
|
} else {
|
|
14006
14052
|
nextIdxToAssign = currentReviewerIdx !== -1 ? currentReviewerIdx : reviewStack.length;
|
|
14007
14053
|
newTimeline.push(createTimelineEntry(
|
|
14008
14054
|
((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.id) || cleanQuestNode.assignee_id,
|
|
14009
|
-
`
|
|
14010
|
-
"
|
|
14055
|
+
`Status "Done" - Finalizado por ${((_d2 = viewMembers.find((m) => m.id === cleanQuestNode.assignee_id)) == null ? void 0 : _d2.name) || ((_e2 = session == null ? void 0 : session.user) == null ? void 0 : _e2.name) || "respons\xE1vel"}`,
|
|
14056
|
+
"status_changed"
|
|
14011
14057
|
));
|
|
14012
14058
|
}
|
|
14013
14059
|
if (nextIdxToAssign < reviewStack.length) {
|
|
@@ -14019,8 +14065,8 @@ function XViewScene({
|
|
|
14019
14065
|
nextStatus = "Review";
|
|
14020
14066
|
newTimeline.push(createTimelineEntry(
|
|
14021
14067
|
"system",
|
|
14022
|
-
`
|
|
14023
|
-
"
|
|
14068
|
+
`Status "Review" - Respons\xE1vel: ${((_f2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _f2.name) || "revisor"}`,
|
|
14069
|
+
"status_changed",
|
|
14024
14070
|
{ metadata: { to_assignee_id: nextAssigneeId } }
|
|
14025
14071
|
));
|
|
14026
14072
|
} else {
|
|
@@ -14035,8 +14081,8 @@ function XViewScene({
|
|
|
14035
14081
|
if (nextStatus === "Done") {
|
|
14036
14082
|
newTimeline.push(createTimelineEntry(
|
|
14037
14083
|
"system",
|
|
14038
|
-
`Quest
|
|
14039
|
-
"
|
|
14084
|
+
`Status "Done" - Quest Finalizada`,
|
|
14085
|
+
"status_changed"
|
|
14040
14086
|
));
|
|
14041
14087
|
}
|
|
14042
14088
|
const updatedNode = {
|
package/dist/index.mjs
CHANGED
|
@@ -8860,7 +8860,6 @@ function InSceneQuestForm({
|
|
|
8860
8860
|
}
|
|
8861
8861
|
};
|
|
8862
8862
|
const handleSubmit = (e) => {
|
|
8863
|
-
var _a2, _b2, _c, _d;
|
|
8864
8863
|
e.preventDefault();
|
|
8865
8864
|
if (!name.trim()) {
|
|
8866
8865
|
alert("O campo 'T\xEDtulo' \xE9 obrigat\xF3rio.");
|
|
@@ -8870,21 +8869,7 @@ function InSceneQuestForm({
|
|
|
8870
8869
|
customProps.filter((prop) => prop.key.trim() && !prop.isEditing)
|
|
8871
8870
|
);
|
|
8872
8871
|
const processedSections = processDescriptionForSave(description, []);
|
|
8873
|
-
const initialTimeline = [
|
|
8874
|
-
createTimelineEntry(
|
|
8875
|
-
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
|
|
8876
|
-
`Quest criada por ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}.`,
|
|
8877
|
-
"quest_created"
|
|
8878
|
-
)
|
|
8879
|
-
];
|
|
8880
|
-
if (assigneeId) {
|
|
8881
|
-
initialTimeline.push(createTimelineEntry(
|
|
8882
|
-
((_c = session == null ? void 0 : session.user) == null ? void 0 : _c.id) || "unknown",
|
|
8883
|
-
`Quest atribu\xEDda para ${((_d = viewMembers.find((m) => m.id === assigneeId)) == null ? void 0 : _d.name) || "respons\xE1vel"}.`,
|
|
8884
|
-
"assignee_changed",
|
|
8885
|
-
{ metadata: { to_assignee_id: assigneeId } }
|
|
8886
|
-
));
|
|
8887
|
-
}
|
|
8872
|
+
const initialTimeline = [];
|
|
8888
8873
|
onSave({
|
|
8889
8874
|
name: standardizedName,
|
|
8890
8875
|
// SALVA O NOME FORMATADO
|
|
@@ -9740,25 +9725,20 @@ import {
|
|
|
9740
9725
|
FiSearch as FiSearch6,
|
|
9741
9726
|
FiLink as FiLink6
|
|
9742
9727
|
} from "react-icons/fi";
|
|
9743
|
-
var
|
|
9744
|
-
"quest_created": { icon: FiPlusCircle, color: "text-sky-400", bg: "bg-sky-400/10" },
|
|
9745
|
-
"assignee_changed": { icon: FiUserPlus, color: "text-indigo-400", bg: "bg-indigo-400/10" },
|
|
9746
|
-
"status_changed": { icon: FiRotateCcw, color: "text-amber-400", bg: "bg-amber-400/10" },
|
|
9747
|
-
"review_cycle_started": { icon: FiSearch6, color: "text-purple-400", bg: "bg-purple-400/10" },
|
|
9748
|
-
"review_completed": { icon: FiCheckSquare2, color: "text-emerald-400", bg: "bg-emerald-400/10" },
|
|
9749
|
-
"comment": { icon: FiMessageSquare, color: "text-slate-400", bg: "bg-slate-400/10" },
|
|
9750
|
-
"quest_finished": { icon: FiTarget2, color: "text-green-400", bg: "bg-green-400/10" },
|
|
9751
|
-
"default": { icon: FiGitCommit, color: "text-slate-500", bg: "bg-slate-500/10" }
|
|
9752
|
-
};
|
|
9728
|
+
var DEFAULT_ICON_CONFIG = { icon: FiGitCommit, color: "text-indigo-400", bg: "bg-indigo-400/10" };
|
|
9753
9729
|
function QuestTimeline({
|
|
9754
9730
|
timeline = [],
|
|
9755
9731
|
viewMembers = [],
|
|
9756
|
-
onOpenImageViewer
|
|
9732
|
+
onOpenImageViewer,
|
|
9733
|
+
onAddNote,
|
|
9734
|
+
// Nova prop para adicionar nota a uma etapa específica
|
|
9735
|
+
canEdit = true
|
|
9757
9736
|
}) {
|
|
9758
9737
|
const sortedTimeline = [...timeline].sort((a, b) => b.timestamp - a.timestamp);
|
|
9759
9738
|
const getMemberName = (userId) => {
|
|
9760
|
-
|
|
9761
|
-
|
|
9739
|
+
if (!userId) return "Sistema";
|
|
9740
|
+
const member = viewMembers.find((m) => String(m.id) === String(userId));
|
|
9741
|
+
return (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || userId;
|
|
9762
9742
|
};
|
|
9763
9743
|
const formatDate = (timestamp) => {
|
|
9764
9744
|
const date = new Date(timestamp);
|
|
@@ -9773,10 +9753,22 @@ function QuestTimeline({
|
|
|
9773
9753
|
return /* @__PURE__ */ React18.createElement("div", { className: "py-6 flex flex-col items-center justify-center gap-2 border border-white/5 bg-white/5 rounded-xl" }, /* @__PURE__ */ React18.createElement(FiAlertCircle, { className: "text-slate-600", size: 16 }), /* @__PURE__ */ React18.createElement("p", { className: "text-[10px] text-slate-500 font-light uppercase tracking-widest" }, "Nenhum hist\xF3rico dispon\xEDvel"));
|
|
9774
9754
|
}
|
|
9775
9755
|
return /* @__PURE__ */ React18.createElement("div", { className: "space-y-4" }, /* @__PURE__ */ React18.createElement("h3", { className: "text-xs text-slate-400 font-medium uppercase tracking-wider flex items-center gap-2" }, "Hist\xF3rico (Timeline)"), /* @__PURE__ */ React18.createElement("div", { className: "relative pl-10 space-y-6 before:content-[''] before:absolute before:left-[21px] before:top-2 before:bottom-2 before:w-[2px] before:bg-white/5" }, sortedTimeline.map((event, index) => {
|
|
9776
|
-
const config =
|
|
9756
|
+
const config = DEFAULT_ICON_CONFIG;
|
|
9777
9757
|
const Icon = config.icon;
|
|
9778
9758
|
const actorName = getMemberName(event.actorId);
|
|
9779
|
-
return /* @__PURE__ */ React18.createElement("div", { key: index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ React18.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ React18.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ React18.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ React18.createElement("
|
|
9759
|
+
return /* @__PURE__ */ React18.createElement("div", { key: event.id || index, className: "relative animate-in fade-in slide-in-from-left-2 duration-300", style: { animationDelay: `${index * 50}ms` } }, /* @__PURE__ */ React18.createElement("div", { className: `absolute -left-[35px] top-0 w-8 h-8 rounded-full ${config.bg} flex items-center justify-center ring-4 ring-slate-950 border border-white/5` }, /* @__PURE__ */ React18.createElement(Icon, { className: config.iconColor || config.color, size: 14 })), /* @__PURE__ */ React18.createElement("div", { className: "group space-y-1" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center justify-between gap-4" }, /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React18.createElement("span", { className: "text-xs font-semibold text-slate-200" }, actorName), canEdit && onAddNote && /* @__PURE__ */ React18.createElement(
|
|
9760
|
+
"button",
|
|
9761
|
+
{
|
|
9762
|
+
onClick: () => onAddNote(event),
|
|
9763
|
+
className: "opacity-0 group-hover:opacity-100 p-1 rounded-md hover:bg-white/5 text-slate-500 hover:text-indigo-400 transition-all",
|
|
9764
|
+
title: "Adicionar detalhe/anexo a esta etapa"
|
|
9765
|
+
},
|
|
9766
|
+
/* @__PURE__ */ React18.createElement(FiPlusCircle, { size: 12 })
|
|
9767
|
+
)), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500 tabular-nums" }, formatDate(event.timestamp))), /* @__PURE__ */ React18.createElement("p", { className: "text-sm text-slate-400 leading-relaxed" }, event.description), event.notes && /* @__PURE__ */ React18.createElement("div", { className: "mt-1 py-1 px-2 rounded bg-indigo-500/5 border-l-2 border-indigo-500/30" }, /* @__PURE__ */ React18.createElement("p", { className: "text-[11px] text-slate-300 italic whitespace-pre-wrap" }, event.notes)), (event.from_status || event.to_status) && /* @__PURE__ */ React18.createElement("div", { className: "flex items-center gap-1.5 py-1 px-2 rounded-md bg-white/5 border border-white/5 w-fit mt-2" }, /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-slate-500" }, event.from_status || "?"), /* @__PURE__ */ React18.createElement(FiArrowRight, { size: 10, className: "text-slate-600" }), /* @__PURE__ */ React18.createElement("span", { className: "text-[10px] text-indigo-300 font-bold" }, event.to_status || "?")), event.metadata && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "mt-2 text-[10px] grid grid-cols-2 gap-2 p-2 bg-slate-900/50 rounded border border-white/5" }, Object.entries(event.metadata).map(([key, value]) => {
|
|
9768
|
+
const isAssigneeId = key.toLowerCase().includes("assignee_id") || key.toLowerCase().includes("respons\xE1vel") || key.toLowerCase().includes("assignee id");
|
|
9769
|
+
const displayValue = isAssigneeId && typeof value === "string" ? getMemberName(value) : typeof value === "string" ? value : JSON.stringify(value);
|
|
9770
|
+
return /* @__PURE__ */ React18.createElement("div", { key, className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React18.createElement("span", { className: "text-slate-500 capitalize" }, key.replace(/_/g, " ")), /* @__PURE__ */ React18.createElement("span", { className: `${isAssigneeId ? "text-indigo-300 font-medium" : "text-slate-300"} truncate font-mono` }, displayValue));
|
|
9771
|
+
})), event.links && event.links.length > 0 && /* @__PURE__ */ React18.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, event.links.map((link, lIdx) => /* @__PURE__ */ React18.createElement(
|
|
9780
9772
|
"a",
|
|
9781
9773
|
{
|
|
9782
9774
|
key: lIdx,
|
|
@@ -9793,10 +9785,10 @@ function QuestTimeline({
|
|
|
9793
9785
|
key: iIdx,
|
|
9794
9786
|
type: "button",
|
|
9795
9787
|
onClick: () => onOpenImageViewer == null ? void 0 : onOpenImageViewer(event.images, iIdx),
|
|
9796
|
-
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group"
|
|
9788
|
+
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group/img"
|
|
9797
9789
|
},
|
|
9798
9790
|
/* @__PURE__ */ React18.createElement("img", { src: img.value, alt: img.name, className: "w-full h-full object-cover" }),
|
|
9799
|
-
/* @__PURE__ */ React18.createElement("div", { className: "absolute inset-0 bg-slate-900/40 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity" }, /* @__PURE__ */ React18.createElement(FiSearch6, { size: 12, className: "text-white" }))
|
|
9791
|
+
/* @__PURE__ */ React18.createElement("div", { className: "absolute inset-0 bg-slate-900/40 opacity-0 group-hover/img:opacity-100 flex items-center justify-center transition-opacity" }, /* @__PURE__ */ React18.createElement(FiSearch6, { size: 12, className: "text-white" }))
|
|
9800
9792
|
)))));
|
|
9801
9793
|
})));
|
|
9802
9794
|
}
|
|
@@ -9862,6 +9854,8 @@ function QuestDetailsPanel({
|
|
|
9862
9854
|
const [noteLinks, setNoteLinks] = useState19([]);
|
|
9863
9855
|
const [noteImages, setNoteImages] = useState19([]);
|
|
9864
9856
|
const [isNoteFormOpen, setIsNoteFormOpen] = useState19(false);
|
|
9857
|
+
const [editingEntryId, setEditingEntryId] = useState19(null);
|
|
9858
|
+
const [editingEntryLabel, setEditingEntryLabel] = useState19("");
|
|
9865
9859
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
9866
9860
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
9867
9861
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -9952,12 +9946,11 @@ function QuestDetailsPanel({
|
|
|
9952
9946
|
const actorName = (currentUser == null ? void 0 : currentUser.name) || "Revisor";
|
|
9953
9947
|
const targetMember = viewMembers.find((m) => String(m.id) === String(returnAssigneeId));
|
|
9954
9948
|
const targetName = (targetMember == null ? void 0 : targetMember.name) || "executor";
|
|
9955
|
-
const newEvent =
|
|
9956
|
-
type: "review_returned",
|
|
9957
|
-
timestamp: Date.now(),
|
|
9949
|
+
const newEvent = createTimelineEntry(
|
|
9958
9950
|
actorId,
|
|
9959
|
-
|
|
9960
|
-
|
|
9951
|
+
`Status "In Progress" - Respons\xE1vel: ${targetName}`,
|
|
9952
|
+
"status_changed"
|
|
9953
|
+
);
|
|
9961
9954
|
const updatedTimeline = [...timeline, newEvent];
|
|
9962
9955
|
const updatedStatus = "In Progress";
|
|
9963
9956
|
const updatedColor = "#eab308";
|
|
@@ -9993,14 +9986,30 @@ function QuestDetailsPanel({
|
|
|
9993
9986
|
}
|
|
9994
9987
|
};
|
|
9995
9988
|
const handleAddTimelineNote = async () => {
|
|
9996
|
-
if (!noteText.trim() || isSaving) return;
|
|
9989
|
+
if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
|
|
9997
9990
|
setIsSaving(true);
|
|
9998
9991
|
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
9992
|
+
let updatedTimeline;
|
|
9993
|
+
if (editingEntryId) {
|
|
9994
|
+
updatedTimeline = timeline.map((entry) => {
|
|
9995
|
+
if (entry.id === editingEntryId) {
|
|
9996
|
+
return {
|
|
9997
|
+
...entry,
|
|
9998
|
+
notes: noteText.trim() ? entry.notes ? `${entry.notes}
|
|
9999
|
+
${noteText}` : noteText : entry.notes,
|
|
10000
|
+
links: [...entry.links || [], ...noteLinks],
|
|
10001
|
+
images: [...entry.images || [], ...noteImages]
|
|
10002
|
+
};
|
|
10003
|
+
}
|
|
10004
|
+
return entry;
|
|
10005
|
+
});
|
|
10006
|
+
} else {
|
|
10007
|
+
const newEntry = createTimelineEntry(actorId, noteText, "comment", {
|
|
10008
|
+
links: noteLinks,
|
|
10009
|
+
images: noteImages
|
|
10010
|
+
});
|
|
10011
|
+
updatedTimeline = [...timeline, newEntry];
|
|
10012
|
+
}
|
|
10004
10013
|
try {
|
|
10005
10014
|
const nodeToSave = {
|
|
10006
10015
|
...node,
|
|
@@ -10013,12 +10022,26 @@ function QuestDetailsPanel({
|
|
|
10013
10022
|
setNoteLinks([]);
|
|
10014
10023
|
setNoteImages([]);
|
|
10015
10024
|
setIsNoteFormOpen(false);
|
|
10025
|
+
setEditingEntryId(null);
|
|
10026
|
+
setEditingEntryLabel("");
|
|
10016
10027
|
} catch (error) {
|
|
10017
10028
|
console.error("Erro ao adicionar nota:", error);
|
|
10018
10029
|
} finally {
|
|
10019
10030
|
setIsSaving(false);
|
|
10020
10031
|
}
|
|
10021
10032
|
};
|
|
10033
|
+
const handleOpenNoteForEntry = (entry) => {
|
|
10034
|
+
setEditingEntryId(entry.id);
|
|
10035
|
+
setEditingEntryLabel(entry.description);
|
|
10036
|
+
setNoteText("");
|
|
10037
|
+
setNoteLinks([]);
|
|
10038
|
+
setNoteImages([]);
|
|
10039
|
+
setIsNoteFormOpen(true);
|
|
10040
|
+
setTimeout(() => {
|
|
10041
|
+
const form = document.getElementById("quest-note-form");
|
|
10042
|
+
form == null ? void 0 : form.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
10043
|
+
}, 100);
|
|
10044
|
+
};
|
|
10022
10045
|
const addLinkToNote = () => {
|
|
10023
10046
|
setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
|
|
10024
10047
|
};
|
|
@@ -10040,8 +10063,18 @@ function QuestDetailsPanel({
|
|
|
10040
10063
|
const handleStatusChange = (newStatus) => {
|
|
10041
10064
|
setStatus(newStatus);
|
|
10042
10065
|
const newColor = QUEST_STATUS_COLORS3[newStatus];
|
|
10066
|
+
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
10067
|
+
const currentAssignee = viewMembers.find((m) => String(m.id) === String(assigneeId));
|
|
10068
|
+
const assigneeName = (currentAssignee == null ? void 0 : currentAssignee.name) || (currentAssignee == null ? void 0 : currentAssignee.email) || "Nenhum";
|
|
10069
|
+
const newEvent = createTimelineEntry(
|
|
10070
|
+
actorId,
|
|
10071
|
+
`Status "${newStatus}" - Respons\xE1vel: ${assigneeName}`,
|
|
10072
|
+
"status_changed"
|
|
10073
|
+
);
|
|
10074
|
+
const newTimeline = [...timeline, newEvent];
|
|
10075
|
+
setTimeline(newTimeline);
|
|
10043
10076
|
onColorChange == null ? void 0 : onColorChange(node.id, newColor);
|
|
10044
|
-
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor });
|
|
10077
|
+
onDataUpdate == null ? void 0 : onDataUpdate({ ...node, status: newStatus, color: newColor, timeline: newTimeline });
|
|
10045
10078
|
setHasUnsavedChanges(true);
|
|
10046
10079
|
};
|
|
10047
10080
|
const handleAddType = (newType) => {
|
|
@@ -10262,13 +10295,11 @@ function QuestDetailsPanel({
|
|
|
10262
10295
|
{
|
|
10263
10296
|
onClick: () => {
|
|
10264
10297
|
setAssigneeId("");
|
|
10265
|
-
const newTimeline = [...timeline,
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
description: `Respons\xE1vel removido.`
|
|
10271
|
-
}];
|
|
10298
|
+
const newTimeline = [...timeline, createTimelineEntry(
|
|
10299
|
+
(currentUser == null ? void 0 : currentUser.id) || "unknown",
|
|
10300
|
+
`Status "${status}" - Respons\xE1vel: Nenhum`,
|
|
10301
|
+
"status_changed"
|
|
10302
|
+
)];
|
|
10272
10303
|
setTimeline(newTimeline);
|
|
10273
10304
|
setHasUnsavedChanges(true);
|
|
10274
10305
|
setIsAssigneeDropdownOpen(false);
|
|
@@ -10296,13 +10327,11 @@ function QuestDetailsPanel({
|
|
|
10296
10327
|
key: member.id,
|
|
10297
10328
|
onClick: () => {
|
|
10298
10329
|
setAssigneeId(member.id);
|
|
10299
|
-
const newTimeline = [...timeline,
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
|
|
10304
|
-
description: `Quest atribu\xEDda para ${member.name || member.email}.`
|
|
10305
|
-
}];
|
|
10330
|
+
const newTimeline = [...timeline, createTimelineEntry(
|
|
10331
|
+
(currentUser == null ? void 0 : currentUser.id) || "unknown",
|
|
10332
|
+
`Status "${status}" - Respons\xE1vel: ${member.name || member.email}`,
|
|
10333
|
+
"status_changed"
|
|
10334
|
+
)];
|
|
10306
10335
|
setTimeline(newTimeline);
|
|
10307
10336
|
setHasUnsavedChanges(true);
|
|
10308
10337
|
setIsAssigneeDropdownOpen(false);
|
|
@@ -10380,17 +10409,32 @@ function QuestDetailsPanel({
|
|
|
10380
10409
|
"button",
|
|
10381
10410
|
{
|
|
10382
10411
|
type: "button",
|
|
10383
|
-
onClick: () =>
|
|
10412
|
+
onClick: () => {
|
|
10413
|
+
if (isNoteFormOpen && editingEntryId) {
|
|
10414
|
+
setEditingEntryId(null);
|
|
10415
|
+
setEditingEntryLabel("");
|
|
10416
|
+
setNoteText("");
|
|
10417
|
+
setNoteLinks([]);
|
|
10418
|
+
setNoteImages([]);
|
|
10419
|
+
} else {
|
|
10420
|
+
setIsNoteFormOpen(!isNoteFormOpen);
|
|
10421
|
+
setEditingEntryId(null);
|
|
10422
|
+
setEditingEntryLabel("");
|
|
10423
|
+
}
|
|
10424
|
+
},
|
|
10384
10425
|
className: "flex items-center gap-1.5 px-2 py-1 text-[10px] rounded-md bg-white/5 hover:bg-white/10 border border-white/10 transition-colors text-slate-300"
|
|
10385
10426
|
},
|
|
10386
|
-
isNoteFormOpen ? /* @__PURE__ */ React19.createElement(FiX7, { size: 12 }) : /* @__PURE__ */ React19.createElement(FiPlus8, { size: 12 }),
|
|
10387
|
-
isNoteFormOpen ? "Cancelar" : "Nova Nota"
|
|
10388
|
-
)), isNoteFormOpen && /* @__PURE__ */ React19.createElement("div", { className: "mb-6 p-4 rounded-xl bg-white/5 border border-white/5 space-y-3 animate-in fade-in slide-in-from-top-2" }, /* @__PURE__ */ React19.createElement(
|
|
10427
|
+
isNoteFormOpen && !editingEntryId ? /* @__PURE__ */ React19.createElement(FiX7, { size: 12 }) : /* @__PURE__ */ React19.createElement(FiPlus8, { size: 12 }),
|
|
10428
|
+
isNoteFormOpen && !editingEntryId ? "Cancelar" : "Nova Nota"
|
|
10429
|
+
)), isNoteFormOpen && /* @__PURE__ */ React19.createElement("div", { id: "quest-note-form", className: "mb-6 p-4 rounded-xl bg-white/5 border border-white/5 space-y-3 animate-in fade-in slide-in-from-top-2 border-l-4 border-l-indigo-500/40" }, editingEntryId && /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between mb-2 pb-2 border-b border-white/5" }, /* @__PURE__ */ React19.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React19.createElement("span", { className: "text-[10px] text-indigo-400 font-bold uppercase tracking-wider" }, "Adicionando \xE0 etapa:"), /* @__PURE__ */ React19.createElement("span", { className: "text-xs text-slate-300 italic truncate max-w-[250px]" }, editingEntryLabel)), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: () => {
|
|
10430
|
+
setIsNoteFormOpen(false);
|
|
10431
|
+
setEditingEntryId(null);
|
|
10432
|
+
}, className: "text-slate-500 hover:text-white" }, /* @__PURE__ */ React19.createElement(FiX7, { size: 14 }))), /* @__PURE__ */ React19.createElement(
|
|
10389
10433
|
"textarea",
|
|
10390
10434
|
{
|
|
10391
10435
|
value: noteText,
|
|
10392
10436
|
onChange: (e) => setNoteText(e.target.value),
|
|
10393
|
-
placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10437
|
+
placeholder: editingEntryId ? "Adicione uma observa\xE7\xE3o a esta etapa..." : "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10394
10438
|
className: "w-full bg-slate-900/50 p-3 text-sm rounded-lg border border-white/10 focus:outline-none focus:ring-1 focus:ring-indigo-500/50 min-h-[80px] resize-none"
|
|
10395
10439
|
}
|
|
10396
10440
|
), /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React19.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ React19.createElement("span", { className: "text-[10px] text-slate-500 uppercase font-bold tracking-tight" }, "Links"), /* @__PURE__ */ React19.createElement("button", { type: "button", onClick: addLinkToNote, className: "text-indigo-400 hover:text-indigo-300 text-[10px] flex items-center gap-1 font-medium" }, /* @__PURE__ */ React19.createElement(FiPlus8, { size: 10 }), " Adicionar Link")), noteLinks.length > 0 && /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, noteLinks.map((link) => /* @__PURE__ */ React19.createElement("div", { key: link.id, className: "flex items-center gap-2 animate-in fade-in slide-in-from-left-1" }, /* @__PURE__ */ React19.createElement(
|
|
@@ -10425,16 +10469,18 @@ function QuestDetailsPanel({
|
|
|
10425
10469
|
{
|
|
10426
10470
|
type: "button",
|
|
10427
10471
|
onClick: handleAddTimelineNote,
|
|
10428
|
-
disabled: !noteText.trim() || isSaving,
|
|
10472
|
+
disabled: !noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving,
|
|
10429
10473
|
className: "px-3 py-1.5 rounded-lg bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-semibold transition-colors disabled:opacity-50"
|
|
10430
10474
|
},
|
|
10431
|
-
"Adicionar ao Hist\xF3rico"
|
|
10475
|
+
editingEntryId ? "Salvar nesta Etapa" : "Adicionar ao Hist\xF3rico"
|
|
10432
10476
|
))), /* @__PURE__ */ React19.createElement(
|
|
10433
10477
|
QuestTimeline,
|
|
10434
10478
|
{
|
|
10435
10479
|
timeline,
|
|
10436
10480
|
viewMembers,
|
|
10437
|
-
onOpenImageViewer
|
|
10481
|
+
onOpenImageViewer,
|
|
10482
|
+
canEdit,
|
|
10483
|
+
onAddNote: handleOpenNoteForEntry
|
|
10438
10484
|
}
|
|
10439
10485
|
)), /* @__PURE__ */ React19.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React19.createElement("label", { className: "text-xs text-slate-300" }, "Tamanho no Node (Size)"), /* @__PURE__ */ React19.createElement("div", { className: "flex items-center gap-5" }, ["small", "medium", "large"].map((s) => {
|
|
10440
10486
|
const isSelected = size === s;
|
|
@@ -14003,7 +14049,7 @@ function XViewScene({
|
|
|
14003
14049
|
} = questNode;
|
|
14004
14050
|
const newTimeline = [...cleanQuestNode.timeline || [], createTimelineEntry(
|
|
14005
14051
|
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || "unknown",
|
|
14006
|
-
`
|
|
14052
|
+
`Status "In Progress" - Respons\xE1vel: ${((_b2 = session == null ? void 0 : session.user) == null ? void 0 : _b2.name) || "usu\xE1rio"}`,
|
|
14007
14053
|
"status_changed"
|
|
14008
14054
|
)];
|
|
14009
14055
|
const updatedNode = {
|
|
@@ -14041,15 +14087,15 @@ function XViewScene({
|
|
|
14041
14087
|
nextIdxToAssign = currentReviewerIdx + 1;
|
|
14042
14088
|
newTimeline.push(createTimelineEntry(
|
|
14043
14089
|
((_a2 = session == null ? void 0 : session.user) == null ? void 0 : _a2.id) || cleanQuestNode.assignee_id,
|
|
14044
|
-
`Review
|
|
14045
|
-
"
|
|
14090
|
+
`Status "Review" - Conclu\xEDda por ${((_b2 = viewMembers.find((m) => m.id === cleanQuestNode.assignee_id)) == null ? void 0 : _b2.name) || "revisor"}`,
|
|
14091
|
+
"status_changed"
|
|
14046
14092
|
));
|
|
14047
14093
|
} else {
|
|
14048
14094
|
nextIdxToAssign = currentReviewerIdx !== -1 ? currentReviewerIdx : reviewStack.length;
|
|
14049
14095
|
newTimeline.push(createTimelineEntry(
|
|
14050
14096
|
((_c2 = session == null ? void 0 : session.user) == null ? void 0 : _c2.id) || cleanQuestNode.assignee_id,
|
|
14051
|
-
`
|
|
14052
|
-
"
|
|
14097
|
+
`Status "Done" - Finalizado por ${((_d2 = viewMembers.find((m) => m.id === cleanQuestNode.assignee_id)) == null ? void 0 : _d2.name) || ((_e2 = session == null ? void 0 : session.user) == null ? void 0 : _e2.name) || "respons\xE1vel"}`,
|
|
14098
|
+
"status_changed"
|
|
14053
14099
|
));
|
|
14054
14100
|
}
|
|
14055
14101
|
if (nextIdxToAssign < reviewStack.length) {
|
|
@@ -14061,8 +14107,8 @@ function XViewScene({
|
|
|
14061
14107
|
nextStatus = "Review";
|
|
14062
14108
|
newTimeline.push(createTimelineEntry(
|
|
14063
14109
|
"system",
|
|
14064
|
-
`
|
|
14065
|
-
"
|
|
14110
|
+
`Status "Review" - Respons\xE1vel: ${((_f2 = viewMembers.find((m) => m.id === nextAssigneeId)) == null ? void 0 : _f2.name) || "revisor"}`,
|
|
14111
|
+
"status_changed",
|
|
14066
14112
|
{ metadata: { to_assignee_id: nextAssigneeId } }
|
|
14067
14113
|
));
|
|
14068
14114
|
} else {
|
|
@@ -14077,8 +14123,8 @@ function XViewScene({
|
|
|
14077
14123
|
if (nextStatus === "Done") {
|
|
14078
14124
|
newTimeline.push(createTimelineEntry(
|
|
14079
14125
|
"system",
|
|
14080
|
-
`Quest
|
|
14081
|
-
"
|
|
14126
|
+
`Status "Done" - Quest Finalizada`,
|
|
14127
|
+
"status_changed"
|
|
14082
14128
|
));
|
|
14083
14129
|
}
|
|
14084
14130
|
const updatedNode = {
|
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.34",
|
|
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",
|