@lv-x-software-house/x_view 1.2.5-dev.32 → 1.2.5-dev.33
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 +85 -20
- package/dist/index.mjs +85 -20
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9724,12 +9724,16 @@ var EVENT_ICONS = {
|
|
|
9724
9724
|
function QuestTimeline({
|
|
9725
9725
|
timeline = [],
|
|
9726
9726
|
viewMembers = [],
|
|
9727
|
-
onOpenImageViewer
|
|
9727
|
+
onOpenImageViewer,
|
|
9728
|
+
onAddNote,
|
|
9729
|
+
// Nova prop para adicionar nota a uma etapa específica
|
|
9730
|
+
canEdit = true
|
|
9728
9731
|
}) {
|
|
9729
9732
|
const sortedTimeline = [...timeline].sort((a, b) => b.timestamp - a.timestamp);
|
|
9730
9733
|
const getMemberName = (userId) => {
|
|
9731
|
-
|
|
9732
|
-
|
|
9734
|
+
if (!userId) return "Sistema";
|
|
9735
|
+
const member = viewMembers.find((m) => String(m.id) === String(userId));
|
|
9736
|
+
return (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || userId;
|
|
9733
9737
|
};
|
|
9734
9738
|
const formatDate = (timestamp) => {
|
|
9735
9739
|
const date = new Date(timestamp);
|
|
@@ -9747,7 +9751,19 @@ function QuestTimeline({
|
|
|
9747
9751
|
const config = EVENT_ICONS[event.type] || EVENT_ICONS.default;
|
|
9748
9752
|
const Icon = config.icon;
|
|
9749
9753
|
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("
|
|
9754
|
+
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(
|
|
9755
|
+
"button",
|
|
9756
|
+
{
|
|
9757
|
+
onClick: () => onAddNote(event),
|
|
9758
|
+
className: "opacity-0 group-hover:opacity-100 p-1 rounded-md hover:bg-white/5 text-slate-500 hover:text-indigo-400 transition-all",
|
|
9759
|
+
title: "Adicionar detalhe/anexo a esta etapa"
|
|
9760
|
+
},
|
|
9761
|
+
/* @__PURE__ */ import_react19.default.createElement(import_fi17.FiPlusCircle, { size: 12 })
|
|
9762
|
+
)), /* @__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]) => {
|
|
9763
|
+
const isAssigneeId = key.toLowerCase().includes("assignee_id") || key.toLowerCase().includes("respons\xE1vel") || key.toLowerCase().includes("assignee id");
|
|
9764
|
+
const displayValue = isAssigneeId && typeof value === "string" ? getMemberName(value) : typeof value === "string" ? value : JSON.stringify(value);
|
|
9765
|
+
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));
|
|
9766
|
+
})), 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
9767
|
"a",
|
|
9752
9768
|
{
|
|
9753
9769
|
key: lIdx,
|
|
@@ -9764,10 +9780,10 @@ function QuestTimeline({
|
|
|
9764
9780
|
key: iIdx,
|
|
9765
9781
|
type: "button",
|
|
9766
9782
|
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"
|
|
9783
|
+
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group/img"
|
|
9768
9784
|
},
|
|
9769
9785
|
/* @__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" }))
|
|
9786
|
+
/* @__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
9787
|
)))));
|
|
9772
9788
|
})));
|
|
9773
9789
|
}
|
|
@@ -9833,6 +9849,8 @@ function QuestDetailsPanel({
|
|
|
9833
9849
|
const [noteLinks, setNoteLinks] = (0, import_react20.useState)([]);
|
|
9834
9850
|
const [noteImages, setNoteImages] = (0, import_react20.useState)([]);
|
|
9835
9851
|
const [isNoteFormOpen, setIsNoteFormOpen] = (0, import_react20.useState)(false);
|
|
9852
|
+
const [editingEntryId, setEditingEntryId] = (0, import_react20.useState)(null);
|
|
9853
|
+
const [editingEntryLabel, setEditingEntryLabel] = (0, import_react20.useState)("");
|
|
9836
9854
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
9837
9855
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
9838
9856
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -9964,14 +9982,30 @@ function QuestDetailsPanel({
|
|
|
9964
9982
|
}
|
|
9965
9983
|
};
|
|
9966
9984
|
const handleAddTimelineNote = async () => {
|
|
9967
|
-
if (!noteText.trim() || isSaving) return;
|
|
9985
|
+
if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
|
|
9968
9986
|
setIsSaving(true);
|
|
9969
9987
|
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
|
|
9973
|
-
|
|
9974
|
-
|
|
9988
|
+
let updatedTimeline;
|
|
9989
|
+
if (editingEntryId) {
|
|
9990
|
+
updatedTimeline = timeline.map((entry) => {
|
|
9991
|
+
if (entry.id === editingEntryId) {
|
|
9992
|
+
return {
|
|
9993
|
+
...entry,
|
|
9994
|
+
notes: noteText.trim() ? entry.notes ? `${entry.notes}
|
|
9995
|
+
${noteText}` : noteText : entry.notes,
|
|
9996
|
+
links: [...entry.links || [], ...noteLinks],
|
|
9997
|
+
images: [...entry.images || [], ...noteImages]
|
|
9998
|
+
};
|
|
9999
|
+
}
|
|
10000
|
+
return entry;
|
|
10001
|
+
});
|
|
10002
|
+
} else {
|
|
10003
|
+
const newEntry = createTimelineEntry(actorId, noteText, "comment", {
|
|
10004
|
+
links: noteLinks,
|
|
10005
|
+
images: noteImages
|
|
10006
|
+
});
|
|
10007
|
+
updatedTimeline = [...timeline, newEntry];
|
|
10008
|
+
}
|
|
9975
10009
|
try {
|
|
9976
10010
|
const nodeToSave = {
|
|
9977
10011
|
...node,
|
|
@@ -9984,12 +10018,26 @@ function QuestDetailsPanel({
|
|
|
9984
10018
|
setNoteLinks([]);
|
|
9985
10019
|
setNoteImages([]);
|
|
9986
10020
|
setIsNoteFormOpen(false);
|
|
10021
|
+
setEditingEntryId(null);
|
|
10022
|
+
setEditingEntryLabel("");
|
|
9987
10023
|
} catch (error) {
|
|
9988
10024
|
console.error("Erro ao adicionar nota:", error);
|
|
9989
10025
|
} finally {
|
|
9990
10026
|
setIsSaving(false);
|
|
9991
10027
|
}
|
|
9992
10028
|
};
|
|
10029
|
+
const handleOpenNoteForEntry = (entry) => {
|
|
10030
|
+
setEditingEntryId(entry.id);
|
|
10031
|
+
setEditingEntryLabel(entry.description);
|
|
10032
|
+
setNoteText("");
|
|
10033
|
+
setNoteLinks([]);
|
|
10034
|
+
setNoteImages([]);
|
|
10035
|
+
setIsNoteFormOpen(true);
|
|
10036
|
+
setTimeout(() => {
|
|
10037
|
+
const form = document.getElementById("quest-note-form");
|
|
10038
|
+
form == null ? void 0 : form.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
10039
|
+
}, 100);
|
|
10040
|
+
};
|
|
9993
10041
|
const addLinkToNote = () => {
|
|
9994
10042
|
setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
|
|
9995
10043
|
};
|
|
@@ -10351,17 +10399,32 @@ function QuestDetailsPanel({
|
|
|
10351
10399
|
"button",
|
|
10352
10400
|
{
|
|
10353
10401
|
type: "button",
|
|
10354
|
-
onClick: () =>
|
|
10402
|
+
onClick: () => {
|
|
10403
|
+
if (isNoteFormOpen && editingEntryId) {
|
|
10404
|
+
setEditingEntryId(null);
|
|
10405
|
+
setEditingEntryLabel("");
|
|
10406
|
+
setNoteText("");
|
|
10407
|
+
setNoteLinks([]);
|
|
10408
|
+
setNoteImages([]);
|
|
10409
|
+
} else {
|
|
10410
|
+
setIsNoteFormOpen(!isNoteFormOpen);
|
|
10411
|
+
setEditingEntryId(null);
|
|
10412
|
+
setEditingEntryLabel("");
|
|
10413
|
+
}
|
|
10414
|
+
},
|
|
10355
10415
|
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
10416
|
},
|
|
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(
|
|
10417
|
+
isNoteFormOpen && !editingEntryId ? /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 12 }) : /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiPlus, { size: 12 }),
|
|
10418
|
+
isNoteFormOpen && !editingEntryId ? "Cancelar" : "Nova Nota"
|
|
10419
|
+
)), 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: () => {
|
|
10420
|
+
setIsNoteFormOpen(false);
|
|
10421
|
+
setEditingEntryId(null);
|
|
10422
|
+
}, className: "text-slate-500 hover:text-white" }, /* @__PURE__ */ import_react20.default.createElement(import_fi18.FiX, { size: 14 }))), /* @__PURE__ */ import_react20.default.createElement(
|
|
10360
10423
|
"textarea",
|
|
10361
10424
|
{
|
|
10362
10425
|
value: noteText,
|
|
10363
10426
|
onChange: (e) => setNoteText(e.target.value),
|
|
10364
|
-
placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10427
|
+
placeholder: editingEntryId ? "Adicione uma observa\xE7\xE3o a esta etapa..." : "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10365
10428
|
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
10429
|
}
|
|
10367
10430
|
), /* @__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 +10459,18 @@ function QuestDetailsPanel({
|
|
|
10396
10459
|
{
|
|
10397
10460
|
type: "button",
|
|
10398
10461
|
onClick: handleAddTimelineNote,
|
|
10399
|
-
disabled: !noteText.trim() || isSaving,
|
|
10462
|
+
disabled: !noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving,
|
|
10400
10463
|
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
10464
|
},
|
|
10402
|
-
"Adicionar ao Hist\xF3rico"
|
|
10465
|
+
editingEntryId ? "Salvar nesta Etapa" : "Adicionar ao Hist\xF3rico"
|
|
10403
10466
|
))), /* @__PURE__ */ import_react20.default.createElement(
|
|
10404
10467
|
QuestTimeline,
|
|
10405
10468
|
{
|
|
10406
10469
|
timeline,
|
|
10407
10470
|
viewMembers,
|
|
10408
|
-
onOpenImageViewer
|
|
10471
|
+
onOpenImageViewer,
|
|
10472
|
+
canEdit,
|
|
10473
|
+
onAddNote: handleOpenNoteForEntry
|
|
10409
10474
|
}
|
|
10410
10475
|
)), /* @__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
10476
|
const isSelected = size === s;
|
package/dist/index.mjs
CHANGED
|
@@ -9753,12 +9753,16 @@ var EVENT_ICONS = {
|
|
|
9753
9753
|
function QuestTimeline({
|
|
9754
9754
|
timeline = [],
|
|
9755
9755
|
viewMembers = [],
|
|
9756
|
-
onOpenImageViewer
|
|
9756
|
+
onOpenImageViewer,
|
|
9757
|
+
onAddNote,
|
|
9758
|
+
// Nova prop para adicionar nota a uma etapa específica
|
|
9759
|
+
canEdit = true
|
|
9757
9760
|
}) {
|
|
9758
9761
|
const sortedTimeline = [...timeline].sort((a, b) => b.timestamp - a.timestamp);
|
|
9759
9762
|
const getMemberName = (userId) => {
|
|
9760
|
-
|
|
9761
|
-
|
|
9763
|
+
if (!userId) return "Sistema";
|
|
9764
|
+
const member = viewMembers.find((m) => String(m.id) === String(userId));
|
|
9765
|
+
return (member == null ? void 0 : member.name) || (member == null ? void 0 : member.email) || userId;
|
|
9762
9766
|
};
|
|
9763
9767
|
const formatDate = (timestamp) => {
|
|
9764
9768
|
const date = new Date(timestamp);
|
|
@@ -9776,7 +9780,19 @@ function QuestTimeline({
|
|
|
9776
9780
|
const config = EVENT_ICONS[event.type] || EVENT_ICONS.default;
|
|
9777
9781
|
const Icon = config.icon;
|
|
9778
9782
|
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("
|
|
9783
|
+
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(
|
|
9784
|
+
"button",
|
|
9785
|
+
{
|
|
9786
|
+
onClick: () => onAddNote(event),
|
|
9787
|
+
className: "opacity-0 group-hover:opacity-100 p-1 rounded-md hover:bg-white/5 text-slate-500 hover:text-indigo-400 transition-all",
|
|
9788
|
+
title: "Adicionar detalhe/anexo a esta etapa"
|
|
9789
|
+
},
|
|
9790
|
+
/* @__PURE__ */ React18.createElement(FiPlusCircle, { size: 12 })
|
|
9791
|
+
)), /* @__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]) => {
|
|
9792
|
+
const isAssigneeId = key.toLowerCase().includes("assignee_id") || key.toLowerCase().includes("respons\xE1vel") || key.toLowerCase().includes("assignee id");
|
|
9793
|
+
const displayValue = isAssigneeId && typeof value === "string" ? getMemberName(value) : typeof value === "string" ? value : JSON.stringify(value);
|
|
9794
|
+
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));
|
|
9795
|
+
})), 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
9796
|
"a",
|
|
9781
9797
|
{
|
|
9782
9798
|
key: lIdx,
|
|
@@ -9793,10 +9809,10 @@ function QuestTimeline({
|
|
|
9793
9809
|
key: iIdx,
|
|
9794
9810
|
type: "button",
|
|
9795
9811
|
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"
|
|
9812
|
+
className: "relative w-12 h-12 rounded border border-white/10 overflow-hidden hover:border-sky-500/50 transition-colors group/img"
|
|
9797
9813
|
},
|
|
9798
9814
|
/* @__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" }))
|
|
9815
|
+
/* @__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
9816
|
)))));
|
|
9801
9817
|
})));
|
|
9802
9818
|
}
|
|
@@ -9862,6 +9878,8 @@ function QuestDetailsPanel({
|
|
|
9862
9878
|
const [noteLinks, setNoteLinks] = useState19([]);
|
|
9863
9879
|
const [noteImages, setNoteImages] = useState19([]);
|
|
9864
9880
|
const [isNoteFormOpen, setIsNoteFormOpen] = useState19(false);
|
|
9881
|
+
const [editingEntryId, setEditingEntryId] = useState19(null);
|
|
9882
|
+
const [editingEntryLabel, setEditingEntryLabel] = useState19("");
|
|
9865
9883
|
const maxPanelW = typeof window !== "undefined" ? window.innerWidth * 0.92 : 1200;
|
|
9866
9884
|
const { width: panelWidth, isResizing, handlePointerDown: handleResize, setWidth } = useResizablePanel({
|
|
9867
9885
|
initialWidth: isReadMode ? 700 : 440,
|
|
@@ -9993,14 +10011,30 @@ function QuestDetailsPanel({
|
|
|
9993
10011
|
}
|
|
9994
10012
|
};
|
|
9995
10013
|
const handleAddTimelineNote = async () => {
|
|
9996
|
-
if (!noteText.trim() || isSaving) return;
|
|
10014
|
+
if (!noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving) return;
|
|
9997
10015
|
setIsSaving(true);
|
|
9998
10016
|
const actorId = (currentUser == null ? void 0 : currentUser.id) || "unknown";
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10017
|
+
let updatedTimeline;
|
|
10018
|
+
if (editingEntryId) {
|
|
10019
|
+
updatedTimeline = timeline.map((entry) => {
|
|
10020
|
+
if (entry.id === editingEntryId) {
|
|
10021
|
+
return {
|
|
10022
|
+
...entry,
|
|
10023
|
+
notes: noteText.trim() ? entry.notes ? `${entry.notes}
|
|
10024
|
+
${noteText}` : noteText : entry.notes,
|
|
10025
|
+
links: [...entry.links || [], ...noteLinks],
|
|
10026
|
+
images: [...entry.images || [], ...noteImages]
|
|
10027
|
+
};
|
|
10028
|
+
}
|
|
10029
|
+
return entry;
|
|
10030
|
+
});
|
|
10031
|
+
} else {
|
|
10032
|
+
const newEntry = createTimelineEntry(actorId, noteText, "comment", {
|
|
10033
|
+
links: noteLinks,
|
|
10034
|
+
images: noteImages
|
|
10035
|
+
});
|
|
10036
|
+
updatedTimeline = [...timeline, newEntry];
|
|
10037
|
+
}
|
|
10004
10038
|
try {
|
|
10005
10039
|
const nodeToSave = {
|
|
10006
10040
|
...node,
|
|
@@ -10013,12 +10047,26 @@ function QuestDetailsPanel({
|
|
|
10013
10047
|
setNoteLinks([]);
|
|
10014
10048
|
setNoteImages([]);
|
|
10015
10049
|
setIsNoteFormOpen(false);
|
|
10050
|
+
setEditingEntryId(null);
|
|
10051
|
+
setEditingEntryLabel("");
|
|
10016
10052
|
} catch (error) {
|
|
10017
10053
|
console.error("Erro ao adicionar nota:", error);
|
|
10018
10054
|
} finally {
|
|
10019
10055
|
setIsSaving(false);
|
|
10020
10056
|
}
|
|
10021
10057
|
};
|
|
10058
|
+
const handleOpenNoteForEntry = (entry) => {
|
|
10059
|
+
setEditingEntryId(entry.id);
|
|
10060
|
+
setEditingEntryLabel(entry.description);
|
|
10061
|
+
setNoteText("");
|
|
10062
|
+
setNoteLinks([]);
|
|
10063
|
+
setNoteImages([]);
|
|
10064
|
+
setIsNoteFormOpen(true);
|
|
10065
|
+
setTimeout(() => {
|
|
10066
|
+
const form = document.getElementById("quest-note-form");
|
|
10067
|
+
form == null ? void 0 : form.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
10068
|
+
}, 100);
|
|
10069
|
+
};
|
|
10022
10070
|
const addLinkToNote = () => {
|
|
10023
10071
|
setNoteLinks([...noteLinks, { id: v4_default(), name: "", value: "" }]);
|
|
10024
10072
|
};
|
|
@@ -10380,17 +10428,32 @@ function QuestDetailsPanel({
|
|
|
10380
10428
|
"button",
|
|
10381
10429
|
{
|
|
10382
10430
|
type: "button",
|
|
10383
|
-
onClick: () =>
|
|
10431
|
+
onClick: () => {
|
|
10432
|
+
if (isNoteFormOpen && editingEntryId) {
|
|
10433
|
+
setEditingEntryId(null);
|
|
10434
|
+
setEditingEntryLabel("");
|
|
10435
|
+
setNoteText("");
|
|
10436
|
+
setNoteLinks([]);
|
|
10437
|
+
setNoteImages([]);
|
|
10438
|
+
} else {
|
|
10439
|
+
setIsNoteFormOpen(!isNoteFormOpen);
|
|
10440
|
+
setEditingEntryId(null);
|
|
10441
|
+
setEditingEntryLabel("");
|
|
10442
|
+
}
|
|
10443
|
+
},
|
|
10384
10444
|
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
10445
|
},
|
|
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(
|
|
10446
|
+
isNoteFormOpen && !editingEntryId ? /* @__PURE__ */ React19.createElement(FiX7, { size: 12 }) : /* @__PURE__ */ React19.createElement(FiPlus8, { size: 12 }),
|
|
10447
|
+
isNoteFormOpen && !editingEntryId ? "Cancelar" : "Nova Nota"
|
|
10448
|
+
)), 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: () => {
|
|
10449
|
+
setIsNoteFormOpen(false);
|
|
10450
|
+
setEditingEntryId(null);
|
|
10451
|
+
}, className: "text-slate-500 hover:text-white" }, /* @__PURE__ */ React19.createElement(FiX7, { size: 14 }))), /* @__PURE__ */ React19.createElement(
|
|
10389
10452
|
"textarea",
|
|
10390
10453
|
{
|
|
10391
10454
|
value: noteText,
|
|
10392
10455
|
onChange: (e) => setNoteText(e.target.value),
|
|
10393
|
-
placeholder: "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10456
|
+
placeholder: editingEntryId ? "Adicione uma observa\xE7\xE3o a esta etapa..." : "Escreva uma observa\xE7\xE3o no hist\xF3rico...",
|
|
10394
10457
|
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
10458
|
}
|
|
10396
10459
|
), /* @__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 +10488,18 @@ function QuestDetailsPanel({
|
|
|
10425
10488
|
{
|
|
10426
10489
|
type: "button",
|
|
10427
10490
|
onClick: handleAddTimelineNote,
|
|
10428
|
-
disabled: !noteText.trim() || isSaving,
|
|
10491
|
+
disabled: !noteText.trim() && noteLinks.length === 0 && noteImages.length === 0 || isSaving,
|
|
10429
10492
|
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
10493
|
},
|
|
10431
|
-
"Adicionar ao Hist\xF3rico"
|
|
10494
|
+
editingEntryId ? "Salvar nesta Etapa" : "Adicionar ao Hist\xF3rico"
|
|
10432
10495
|
))), /* @__PURE__ */ React19.createElement(
|
|
10433
10496
|
QuestTimeline,
|
|
10434
10497
|
{
|
|
10435
10498
|
timeline,
|
|
10436
10499
|
viewMembers,
|
|
10437
|
-
onOpenImageViewer
|
|
10500
|
+
onOpenImageViewer,
|
|
10501
|
+
canEdit,
|
|
10502
|
+
onAddNote: handleOpenNoteForEntry
|
|
10438
10503
|
}
|
|
10439
10504
|
)), /* @__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
10505
|
const isSelected = size === s;
|
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.33",
|
|
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",
|