@fayz-ai/admin 0.36.0 → 0.36.1
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CrudPage.d.ts","sourceRoot":"","sources":["../../src/crud/CrudPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAA;AAUhF,OAAO,EAAgB,KAAK,YAAY,EAAkB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"CrudPage.d.ts","sourceRoot":"","sources":["../../src/crud/CrudPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAA;AAUhF,OAAO,EAAgB,KAAK,YAAY,EAAkB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAEjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAmB/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAG1D,KAAK,WAAW,GAAG,OAAO,GAAG,OAAO,CAAA;AAYpC,UAAU,aAAa,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE;IAC9C,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IACvB,QAAQ,EAAE,MAAM,SAAS,CAAC,CAAC,CAAC,CAAA;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,UAAU,EAAE,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,YAAY,EAAE,CAAA;IAC5D;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB;qDACiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA0ID,wBAAgB,QAAQ,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC,qBA4mB5M"}
|
|
@@ -20,5 +20,7 @@ export declare function RelatedSection({ parentId, related, compact }: {
|
|
|
20
20
|
related: RelatedList;
|
|
21
21
|
compact?: boolean;
|
|
22
22
|
}): React.JSX.Element;
|
|
23
|
+
/** Copies a parent's related rows onto another parent (used by list "Duplicate"). */
|
|
24
|
+
export declare function copyRelatedRows(related: RelatedList, fromParentId: string, toParentId: string): Promise<void>;
|
|
23
25
|
export {};
|
|
24
26
|
//# sourceMappingURL=RelatedSection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RelatedSection.d.ts","sourceRoot":"","sources":["../../src/crud/RelatedSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EAAuB,WAAW,EAAE,MAAM,eAAe,CAAA;AAoCrE,KAAK,oBAAoB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAM/D,gFAAgF;AAChF,wBAAgB,kBAAkB,IAAI;IACpC,QAAQ,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAA;KAAE,CAAA;IACnE,KAAK,EAAE,oBAAoB,CAAA;CAC5B,CAcA;AAED,wBAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAC3D,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAA;KAAE,CAAA;IAChE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,qBAEA;AAiED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC7D,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,
|
|
1
|
+
{"version":3,"file":"RelatedSection.d.ts","sourceRoot":"","sources":["../../src/crud/RelatedSection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,OAAO,KAAK,EAAuB,WAAW,EAAE,MAAM,eAAe,CAAA;AAoCrE,KAAK,oBAAoB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAM/D,gFAAgF;AAChF,wBAAgB,kBAAkB,IAAI;IACpC,QAAQ,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAA;KAAE,CAAA;IACnE,KAAK,EAAE,oBAAoB,CAAA;CAC5B,CAcA;AAED,wBAAgB,uBAAuB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAC3D,KAAK,EAAE;QAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,IAAI,CAAA;KAAE,CAAA;IAChE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,qBAEA;AAiED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC7D,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,WAAW,CAAA;IACpB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,qBAqfA;AAED,qFAAqF;AACrF,wBAAsB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBnH"}
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import { useAuthStore, useAuth, buildAppHandoffUrl } from '@fayz-ai/auth';
|
|
|
32
32
|
export { useAuth } from '@fayz-ai/auth';
|
|
33
33
|
import { create, useStore as useStore$1 } from 'zustand';
|
|
34
34
|
import * as LucideIcons from 'lucide-react';
|
|
35
|
-
import { Pencil, Trash2, Upload, Search, ArrowDown, ArrowUp, ArrowUpDown, Check, Download, ChevronLeft, ChevronRight, AlertTriangle, Building2, Inbox, Package, Sparkles, Plug, DollarSign, Clock, X, WandSparkles, Loader2, ArrowDownToLine, ArrowUpFromLine, CheckCircle2, Crown, ArrowRight, History, SquarePen, Settings2, Mic, User, Plus, Minus, ListChecks, ChevronDown, ArrowLeft, Calendar, ClipboardList, CheckSquare, BookOpen, Lock, PinOff, Pin, Eye, Users, StickyNote, CheckSquare2, Square, RotateCcw,
|
|
35
|
+
import { Pencil, Copy, Trash2, Upload, Search, ArrowDown, ArrowUp, ArrowUpDown, Check, Download, ChevronLeft, ChevronRight, AlertTriangle, Building2, Inbox, Package, Sparkles, Plug, DollarSign, Clock, X, WandSparkles, Loader2, ArrowDownToLine, ArrowUpFromLine, CheckCircle2, Crown, ArrowRight, History, SquarePen, Settings2, Mic, User, Plus, Minus, ListChecks, ChevronDown, ArrowLeft, Calendar, ClipboardList, CheckSquare, BookOpen, Lock, PinOff, Pin, Eye, Users, StickyNote, CheckSquare2, Square, RotateCcw, Globe, LayoutTemplate, Store, ChevronsUpDown, ExternalLink, PenSquare, RefreshCw, XCircle, Camera, Edit, Star, Link2Off, Layers, ShoppingBag, MoreHorizontal, ChevronUp, List, LayoutGrid, CircleDollarSign, Receipt, Settings, Mail, MessageCircle, Cake, HelpCircle, Wrench, ShieldCheck, MessageSquare, Paperclip, Infinity, CheckCheck, PartyPopper, Compass, Play, MapPin, Landmark, LocateFixed, ArrowUpCircle, ArrowUpRight, Pause, CalendarDays, CircleCheckBig, UserX, Ban, CircleAlert, CircleEllipsis, FileText, CircleDashed, Power, ArrowRightLeft, File as File$1, FileImage, FileSpreadsheet, AlertCircle, CreditCard, SlidersHorizontal, Puzzle, Shield, Palette, Blocks, ShieldAlert, UserCog, LogOut, Bell, Database, Radio, Zap, Save, ImagePlus, UserPlus, Contact, UserMinus, Send, Sun, Moon, Monitor, Languages, Info, Link2, KeyRound, Bug, Home, Heart, Briefcase, BarChart3, Tag, Truck, Globe2 } from 'lucide-react';
|
|
36
36
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
37
37
|
import { createPortal } from 'react-dom';
|
|
38
38
|
import { profileHasSystemPermission, mergeLimitDeclarations } from '@fayz-ai/core/access';
|
|
@@ -23472,21 +23472,77 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
23472
23472
|
}
|
|
23473
23473
|
}
|
|
23474
23474
|
const shown = child.fields.filter((f) => f.showInTable !== false);
|
|
23475
|
+
const groupKey = related.duplicable ? child.fields.find((f) => f.type === "relation")?.key : void 0;
|
|
23476
|
+
const [lastEdit, setLastEdit] = React127.useState(null);
|
|
23477
|
+
function siblingsToSync(row, key) {
|
|
23478
|
+
if (!groupKey || key === groupKey || row[groupKey] == null) return [];
|
|
23479
|
+
return rows.filter((r) => r.id !== row.id && r[groupKey] === row[groupKey] && r[key] !== row[key]);
|
|
23480
|
+
}
|
|
23481
|
+
async function applyToSiblings(row, key) {
|
|
23482
|
+
const alvos = siblingsToSync(row, key);
|
|
23483
|
+
if (!alvos.length) return;
|
|
23484
|
+
const value = row[key];
|
|
23485
|
+
const ids = new Set(alvos.map((r) => r.id));
|
|
23486
|
+
const antes = rows;
|
|
23487
|
+
setRows((prev) => prev.map((r) => ids.has(r.id) ? { ...r, [key]: value } : r));
|
|
23488
|
+
setLastEdit(null);
|
|
23489
|
+
if (orfa) return;
|
|
23490
|
+
try {
|
|
23491
|
+
await Promise.all(alvos.map((r) => provider2.update(r.id, { [key]: value })));
|
|
23492
|
+
} catch (e) {
|
|
23493
|
+
setRows(antes);
|
|
23494
|
+
toast.error(errorMessage(e));
|
|
23495
|
+
}
|
|
23496
|
+
}
|
|
23475
23497
|
async function patch(id, key, value, price) {
|
|
23476
23498
|
const antes = rows.find((r) => r.id === id);
|
|
23477
23499
|
if (!antes) return;
|
|
23500
|
+
if (key !== groupKey) setLastEdit({ id, key });
|
|
23478
23501
|
const mudanca = { [key]: value, ...heranca(key, price, { ...antes, [key]: value }) };
|
|
23479
23502
|
if (Object.entries(mudanca).every(([k, v]) => antes[k] === v)) return;
|
|
23480
23503
|
setRows((prev) => prev.map((r) => r.id === id ? { ...r, ...mudanca } : r));
|
|
23481
23504
|
if (orfa) return;
|
|
23482
|
-
|
|
23483
|
-
|
|
23484
|
-
|
|
23485
|
-
|
|
23486
|
-
|
|
23487
|
-
}
|
|
23505
|
+
queueWrite(id, mudanca, antes);
|
|
23506
|
+
}
|
|
23507
|
+
const escritas = React127.useRef(/* @__PURE__ */ new Map());
|
|
23508
|
+
function queueWrite(id, mudanca, antes) {
|
|
23509
|
+
const atual = escritas.current.get(id);
|
|
23510
|
+
const entry = atual ?? { mudanca: {}, antes, fila: Promise.resolve() };
|
|
23511
|
+
entry.mudanca = { ...entry.mudanca, ...mudanca };
|
|
23512
|
+
if (entry.timer) clearTimeout(entry.timer);
|
|
23513
|
+
entry.timer = setTimeout(() => flushWrite(id), 400);
|
|
23514
|
+
escritas.current.set(id, entry);
|
|
23515
|
+
}
|
|
23516
|
+
function flushWrite(id) {
|
|
23517
|
+
const entry = escritas.current.get(id);
|
|
23518
|
+
if (!entry || !Object.keys(entry.mudanca).length) return;
|
|
23519
|
+
const { mudanca, antes } = entry;
|
|
23520
|
+
entry.mudanca = {};
|
|
23521
|
+
entry.timer = void 0;
|
|
23522
|
+
entry.fila = entry.fila.then(async () => {
|
|
23523
|
+
try {
|
|
23524
|
+
await provider2.update(id, mudanca);
|
|
23525
|
+
} catch (e) {
|
|
23526
|
+
setRows((prev) => prev.map((r) => r.id === id ? antes : r));
|
|
23527
|
+
toast.error(errorMessage(e));
|
|
23528
|
+
}
|
|
23529
|
+
});
|
|
23530
|
+
const fila = entry.fila;
|
|
23531
|
+
void fila.then(() => {
|
|
23532
|
+
const e = escritas.current.get(id);
|
|
23533
|
+
if (e && e.fila === fila && !e.timer) escritas.current.delete(id);
|
|
23534
|
+
});
|
|
23488
23535
|
}
|
|
23536
|
+
React127.useEffect(() => () => {
|
|
23537
|
+
for (const [id, e] of escritas.current) {
|
|
23538
|
+
if (e.timer) {
|
|
23539
|
+
clearTimeout(e.timer);
|
|
23540
|
+
flushWrite(id);
|
|
23541
|
+
}
|
|
23542
|
+
}
|
|
23543
|
+
}, []);
|
|
23489
23544
|
const required = child.fields.filter((f) => f.required);
|
|
23545
|
+
const criando = React127.useRef(false);
|
|
23490
23546
|
async function commitDraft(key, next, price) {
|
|
23491
23547
|
const completo = { ...next, ...heranca(key, price, next) };
|
|
23492
23548
|
setDraft(completo);
|
|
@@ -23495,17 +23551,36 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
23495
23551
|
);
|
|
23496
23552
|
const pronto = { ...defaults, ...completo };
|
|
23497
23553
|
if (required.some((f) => pronto[f.key] == null || pronto[f.key] === "")) return;
|
|
23554
|
+
if (criando.current) return;
|
|
23498
23555
|
if (orfa) {
|
|
23499
23556
|
setRows((prev) => [...prev, { id: `draft-${prev.length}-${completo[key]}`, ...pronto }]);
|
|
23500
23557
|
setDraft(null);
|
|
23501
23558
|
return;
|
|
23502
23559
|
}
|
|
23560
|
+
criando.current = true;
|
|
23503
23561
|
try {
|
|
23504
23562
|
await provider2.create(pronto);
|
|
23505
23563
|
setDraft(null);
|
|
23506
23564
|
await load();
|
|
23507
23565
|
} catch (e) {
|
|
23508
23566
|
toast.error(errorMessage(e));
|
|
23567
|
+
} finally {
|
|
23568
|
+
criando.current = false;
|
|
23569
|
+
}
|
|
23570
|
+
}
|
|
23571
|
+
async function duplicate(row) {
|
|
23572
|
+
const copia = Object.fromEntries(
|
|
23573
|
+
child.fields.filter((f) => row[f.key] !== void 0).map((f) => [f.key, row[f.key]])
|
|
23574
|
+
);
|
|
23575
|
+
if (orfa) {
|
|
23576
|
+
setRows((prev) => [...prev, { ...copia, id: `draft-${prev.length}-copy` }]);
|
|
23577
|
+
return;
|
|
23578
|
+
}
|
|
23579
|
+
try {
|
|
23580
|
+
await provider2.create(copia);
|
|
23581
|
+
await load();
|
|
23582
|
+
} catch (e) {
|
|
23583
|
+
toast.error(errorMessage(e));
|
|
23509
23584
|
}
|
|
23510
23585
|
}
|
|
23511
23586
|
function heranca(fieldKey, price, linha) {
|
|
@@ -23608,25 +23683,57 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
23608
23683
|
error ? /* @__PURE__ */ jsx("p", { className: "rounded-lg border border-destructive/30 bg-destructive-soft px-3 py-2 text-xs text-destructive-soft-foreground", children: error }) : loading ? /* @__PURE__ */ jsx("div", { className: "h-8 w-40 animate-pulse rounded bg-muted/40" }) : rows.length === 0 && draft === null ? /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: compact ? "py-3" : "py-4", children: /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: related.emptyHint ?? "\u2014" }) }) }) : /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsx(CardContent, { className: "overflow-x-auto p-0", children: /* @__PURE__ */ jsxs("table", { className: "w-full min-w-[26rem] text-xs", children: [
|
|
23609
23684
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b text-left text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: [
|
|
23610
23685
|
shown.map((f) => /* @__PURE__ */ jsx("th", { className: "px-3 py-2 font-medium", children: f.label }, f.key)),
|
|
23611
|
-
/* @__PURE__ */ jsx("th", { className: "w-10 px-3 py-2" })
|
|
23686
|
+
/* @__PURE__ */ jsx("th", { className: related.duplicable ? "w-16 px-3 py-2" : "w-10 px-3 py-2" })
|
|
23612
23687
|
] }) }),
|
|
23613
23688
|
/* @__PURE__ */ jsxs("tbody", { children: [
|
|
23614
23689
|
rows.map((row) => /* @__PURE__ */ jsxs("tr", { className: "border-b last:border-0", children: [
|
|
23615
|
-
shown.map((f) => /* @__PURE__ */
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
|
|
23619
|
-
|
|
23620
|
-
|
|
23621
|
-
|
|
23622
|
-
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
23626
|
-
|
|
23627
|
-
|
|
23628
|
-
|
|
23629
|
-
|
|
23690
|
+
shown.map((f) => /* @__PURE__ */ jsxs("td", { className: "px-3 py-1.5 align-middle", children: [
|
|
23691
|
+
cell(f, row[f.key], (next, price) => {
|
|
23692
|
+
void patch(row.id, f.key, next, price);
|
|
23693
|
+
}, row),
|
|
23694
|
+
lastEdit?.id === row.id && lastEdit?.key === f.key && siblingsToSync(row, f.key).length > 0 && /* @__PURE__ */ jsxs(
|
|
23695
|
+
"button",
|
|
23696
|
+
{
|
|
23697
|
+
type: "button",
|
|
23698
|
+
onClick: () => {
|
|
23699
|
+
void applyToSiblings(row, f.key);
|
|
23700
|
+
},
|
|
23701
|
+
className: "mt-1 text-[11px] font-medium text-primary hover:underline",
|
|
23702
|
+
children: [
|
|
23703
|
+
"Aplicar para todos (",
|
|
23704
|
+
siblingsToSync(row, f.key).length,
|
|
23705
|
+
")"
|
|
23706
|
+
]
|
|
23707
|
+
}
|
|
23708
|
+
)
|
|
23709
|
+
] }, f.key)),
|
|
23710
|
+
/* @__PURE__ */ jsxs("td", { className: "whitespace-nowrap px-3 py-1.5 text-right", children: [
|
|
23711
|
+
related.duplicable && /* @__PURE__ */ jsx(
|
|
23712
|
+
"button",
|
|
23713
|
+
{
|
|
23714
|
+
type: "button",
|
|
23715
|
+
"aria-label": `${label3}: duplicar`,
|
|
23716
|
+
title: "Duplicar",
|
|
23717
|
+
onClick: () => {
|
|
23718
|
+
void duplicate(row);
|
|
23719
|
+
},
|
|
23720
|
+
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
23721
|
+
children: /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
|
|
23722
|
+
}
|
|
23723
|
+
),
|
|
23724
|
+
/* @__PURE__ */ jsx(
|
|
23725
|
+
"button",
|
|
23726
|
+
{
|
|
23727
|
+
type: "button",
|
|
23728
|
+
"aria-label": `${label3}: remover`,
|
|
23729
|
+
onClick: () => {
|
|
23730
|
+
void remove(row.id);
|
|
23731
|
+
},
|
|
23732
|
+
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-destructive",
|
|
23733
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
23734
|
+
}
|
|
23735
|
+
)
|
|
23736
|
+
] })
|
|
23630
23737
|
] }, row.id)),
|
|
23631
23738
|
draft !== null && /* @__PURE__ */ jsxs("tr", { className: "border-b last:border-0 bg-muted/20", children: [
|
|
23632
23739
|
shown.map((f) => /* @__PURE__ */ jsx("td", { className: "px-3 py-1.5 align-middle", children: cell(
|
|
@@ -23698,6 +23805,27 @@ function RelatedSection({ parentId, related, compact }) {
|
|
|
23698
23805
|
)
|
|
23699
23806
|
] });
|
|
23700
23807
|
}
|
|
23808
|
+
async function copyRelatedRows(related, fromParentId, toParentId) {
|
|
23809
|
+
const data = related.entity.data;
|
|
23810
|
+
if (!data) return;
|
|
23811
|
+
const fk = columnOf(related.entity, related.foreignKey);
|
|
23812
|
+
const reader = resolveDataProvider(
|
|
23813
|
+
{ ...related.entity, data: { ...data, filters: { ...data.filters ?? {}, [fk]: fromParentId } } },
|
|
23814
|
+
[],
|
|
23815
|
+
{ cache: false }
|
|
23816
|
+
);
|
|
23817
|
+
const writer = resolveDataProvider(
|
|
23818
|
+
{ ...related.entity, data: { ...data, defaults: { ...data.defaults ?? {}, [fk]: toParentId } } },
|
|
23819
|
+
[],
|
|
23820
|
+
{ cache: false }
|
|
23821
|
+
);
|
|
23822
|
+
const result = await reader.list({ page: 1, pageSize: 500 });
|
|
23823
|
+
const keys = related.entity.fields.map((f) => f.key).filter((k) => k !== related.foreignKey);
|
|
23824
|
+
for (const row of result?.data ?? []) {
|
|
23825
|
+
const copia = Object.fromEntries(keys.filter((k) => row[k] !== void 0).map((k) => [k, row[k]]));
|
|
23826
|
+
await writer.create({ ...copia, [related.foreignKey]: toParentId });
|
|
23827
|
+
}
|
|
23828
|
+
}
|
|
23701
23829
|
var PRICING_FIELDS = /* @__PURE__ */ new Set(["price", "cost", "currency", "unit"]);
|
|
23702
23830
|
var STOCK_FIELDS = /* @__PURE__ */ new Set(["stock", "minStock"]);
|
|
23703
23831
|
var SKIP_FIELDS2 = /* @__PURE__ */ new Set(["status", "isActive", "tags", "imageUrl", "name", "description", "sku", "category"]);
|
|
@@ -26467,6 +26595,13 @@ function useCrudColumns(entityDef, options) {
|
|
|
26467
26595
|
onSelect: () => setCrudHash(options.basePath, id, "edit"),
|
|
26468
26596
|
hidden: options.feature ? !can(options.feature, "edit") : false
|
|
26469
26597
|
},
|
|
26598
|
+
...options.onDuplicate ? [{
|
|
26599
|
+
id: "duplicate",
|
|
26600
|
+
label: t("crud.list.duplicate"),
|
|
26601
|
+
icon: Copy,
|
|
26602
|
+
onSelect: () => options.onDuplicate(row.original),
|
|
26603
|
+
hidden: options.feature ? !can(options.feature, "create") : false
|
|
26604
|
+
}] : [],
|
|
26470
26605
|
...options.onDelete ? [{
|
|
26471
26606
|
id: "delete",
|
|
26472
26607
|
label: t("common.delete"),
|
|
@@ -26481,7 +26616,7 @@ function useCrudColumns(entityDef, options) {
|
|
|
26481
26616
|
});
|
|
26482
26617
|
}
|
|
26483
26618
|
return tanCols;
|
|
26484
|
-
}, [cols, displayField, options?.basePath, options?.onDelete, options?.feature, options?.readOnly, t, can]);
|
|
26619
|
+
}, [cols, displayField, options?.basePath, options?.onDelete, options?.onDuplicate, options?.feature, options?.readOnly, t, can]);
|
|
26485
26620
|
}
|
|
26486
26621
|
function CrudPage({ entityDef: rawEntityDef, useStore: useStore2, basePath, display, feature, readOnly, navTabs, activeNavTab, stats, embedded, emptyHint, aiCreate }) {
|
|
26487
26622
|
const store = useStore2();
|
|
@@ -26572,7 +26707,33 @@ function CrudPage({ entityDef: rawEntityDef, useStore: useStore2, basePath, disp
|
|
|
26572
26707
|
const handleInlineUpdate = useCallback(async (id, field, value) => {
|
|
26573
26708
|
await store.update(id, { [field]: value });
|
|
26574
26709
|
}, [store]);
|
|
26575
|
-
const
|
|
26710
|
+
const handleDuplicate = useCallback(async (row) => {
|
|
26711
|
+
try {
|
|
26712
|
+
const display2 = entityDef.displayField ?? entityDef.fields[0]?.key;
|
|
26713
|
+
const copia = Object.fromEntries(
|
|
26714
|
+
entityDef.fields.filter((f) => f.showInForm !== false && row[f.key] !== void 0).map((f) => [f.key, row[f.key]])
|
|
26715
|
+
);
|
|
26716
|
+
if (display2 && typeof copia[display2] === "string") copia[display2] = `${copia[display2]} ${t("crud.list.copySuffix")}`;
|
|
26717
|
+
const created = await store.create(copia);
|
|
26718
|
+
for (const related of entityDef.relatedSections ?? []) {
|
|
26719
|
+
await copyRelatedRows(related, row.id, created.id);
|
|
26720
|
+
}
|
|
26721
|
+
toast.success(t("crud.list.duplicated", { entity: entityDef.name }));
|
|
26722
|
+
setCrudHash(normalizedBasePath, created.id, "edit");
|
|
26723
|
+
} catch (err) {
|
|
26724
|
+
toast.error(err instanceof Error ? err.message : String(err));
|
|
26725
|
+
}
|
|
26726
|
+
}, [entityDef, store, t, normalizedBasePath]);
|
|
26727
|
+
const tanColumns = useCrudColumns(entityDef, {
|
|
26728
|
+
basePath: normalizedBasePath,
|
|
26729
|
+
onDelete: readOnly ? void 0 : (item) => setDeleteItem(item),
|
|
26730
|
+
onDuplicate: readOnly || !entityDef.duplicable ? void 0 : (item) => {
|
|
26731
|
+
void handleDuplicate(item);
|
|
26732
|
+
},
|
|
26733
|
+
onInlineUpdate: handleInlineUpdate,
|
|
26734
|
+
feature,
|
|
26735
|
+
readOnly
|
|
26736
|
+
});
|
|
26576
26737
|
const currentOrgId = useOrganizationStore((s) => s.currentOrg?.id);
|
|
26577
26738
|
const guardImport = useLimitGuard(entityDef.limitKey ?? "");
|
|
26578
26739
|
useEffect(() => {
|
|
@@ -35854,7 +36015,7 @@ function OrderDetailView(props) {
|
|
|
35854
36015
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: tile.label }),
|
|
35855
36016
|
tile.icon && /* @__PURE__ */ jsx(tile.icon, { className: "h-4 w-4 shrink-0 text-muted-foreground/70" })
|
|
35856
36017
|
] }),
|
|
35857
|
-
/* @__PURE__ */ jsx("
|
|
36018
|
+
/* @__PURE__ */ jsx("div", { className: "mt-1 truncate text-lg font-semibold", children: tile.value })
|
|
35858
36019
|
] }, tile.id ?? i)) }),
|
|
35859
36020
|
banner && /* @__PURE__ */ jsxs("div", { className: banner.tone === "warning" ? "flex items-center gap-3 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-900" : "flex items-center gap-3 rounded-lg border border-border bg-muted/40 px-4 py-3 text-sm", children: [
|
|
35860
36021
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4 shrink-0" }),
|