@asteby/metacore-runtime-react 46.3.0 → 47.0.0

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.
Files changed (99) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/action-modal-dispatcher.d.ts +10 -1
  3. package/dist/action-modal-dispatcher.d.ts.map +1 -1
  4. package/dist/action-modal-dispatcher.js +107 -19
  5. package/dist/business/catalog.d.ts.map +1 -1
  6. package/dist/business/catalog.js +24 -0
  7. package/dist/business/index.d.ts +3 -0
  8. package/dist/business/index.d.ts.map +1 -1
  9. package/dist/business/index.js +3 -0
  10. package/dist/business/print-send-dialog.d.ts +27 -0
  11. package/dist/business/print-send-dialog.d.ts.map +1 -0
  12. package/dist/business/print-send-dialog.js +55 -0
  13. package/dist/business/relate-documents.d.ts +41 -0
  14. package/dist/business/relate-documents.d.ts.map +1 -0
  15. package/dist/business/relate-documents.js +42 -0
  16. package/dist/business/vehicle-picker.d.ts +36 -0
  17. package/dist/business/vehicle-picker.d.ts.map +1 -0
  18. package/dist/business/vehicle-picker.js +61 -0
  19. package/dist/cfdi-stamp-panel.d.ts +29 -0
  20. package/dist/cfdi-stamp-panel.d.ts.map +1 -0
  21. package/dist/cfdi-stamp-panel.js +53 -0
  22. package/dist/dialogs/dynamic-record.d.ts.map +1 -1
  23. package/dist/dialogs/dynamic-record.js +5 -0
  24. package/dist/document-form-dialog.d.ts +23 -0
  25. package/dist/document-form-dialog.d.ts.map +1 -0
  26. package/dist/document-form-dialog.js +196 -0
  27. package/dist/dynamic-crud-page.d.ts +6 -0
  28. package/dist/dynamic-crud-page.d.ts.map +1 -1
  29. package/dist/dynamic-crud-page.js +17 -7
  30. package/dist/dynamic-kanban.d.ts.map +1 -1
  31. package/dist/dynamic-kanban.js +3 -1
  32. package/dist/dynamic-table.d.ts.map +1 -1
  33. package/dist/dynamic-table.js +6 -2
  34. package/dist/index.d.ts +6 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +6 -0
  37. package/dist/list-primary-action.d.ts +31 -0
  38. package/dist/list-primary-action.d.ts.map +1 -0
  39. package/dist/list-primary-action.js +35 -0
  40. package/dist/model-action-toolbar.d.ts +7 -1
  41. package/dist/model-action-toolbar.d.ts.map +1 -1
  42. package/dist/model-action-toolbar.js +10 -3
  43. package/dist/model-extension-registry.d.ts +7 -0
  44. package/dist/model-extension-registry.d.ts.map +1 -1
  45. package/dist/nav-permissions.d.ts +19 -0
  46. package/dist/nav-permissions.d.ts.map +1 -0
  47. package/dist/nav-permissions.js +51 -0
  48. package/dist/navigation-builder.d.ts +6 -0
  49. package/dist/navigation-builder.d.ts.map +1 -1
  50. package/dist/navigation-builder.js +26 -1
  51. package/dist/permissions-manager.d.ts +9 -0
  52. package/dist/permissions-manager.d.ts.map +1 -1
  53. package/dist/permissions-manager.js +50 -17
  54. package/dist/print-document-button.d.ts.map +1 -1
  55. package/dist/print-document-button.js +9 -1
  56. package/dist/record-mutation-events.d.ts +14 -0
  57. package/dist/record-mutation-events.d.ts.map +1 -0
  58. package/dist/record-mutation-events.js +37 -0
  59. package/dist/types.d.ts +60 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/use-print-document.d.ts +15 -1
  62. package/dist/use-print-document.d.ts.map +1 -1
  63. package/dist/use-print-document.js +52 -1
  64. package/dist/use-record-mutation-tick.d.ts +6 -0
  65. package/dist/use-record-mutation-tick.d.ts.map +1 -0
  66. package/dist/use-record-mutation-tick.js +11 -0
  67. package/package.json +3 -3
  68. package/src/__tests__/action-modal-feedback.test.tsx +116 -0
  69. package/src/__tests__/business-pickers.test.tsx +157 -0
  70. package/src/__tests__/document-form-dialog.test.tsx +190 -0
  71. package/src/__tests__/dynamic-table-mutation-refresh.test.tsx +116 -0
  72. package/src/__tests__/list-primary-action.test.tsx +157 -0
  73. package/src/__tests__/nav-permissions.test.tsx +76 -0
  74. package/src/__tests__/permissions-manager.test.tsx +21 -4
  75. package/src/__tests__/use-print-document-feedback.test.tsx +58 -0
  76. package/src/action-modal-dispatcher.tsx +124 -6
  77. package/src/business/catalog.ts +24 -0
  78. package/src/business/index.ts +3 -0
  79. package/src/business/print-send-dialog.tsx +175 -0
  80. package/src/business/relate-documents.tsx +182 -0
  81. package/src/business/vehicle-picker.tsx +188 -0
  82. package/src/cfdi-stamp-panel.tsx +146 -0
  83. package/src/dialogs/dynamic-record.tsx +5 -0
  84. package/src/document-form-dialog.tsx +357 -0
  85. package/src/dynamic-crud-page.tsx +36 -7
  86. package/src/dynamic-kanban.tsx +3 -1
  87. package/src/dynamic-table.tsx +6 -2
  88. package/src/index.ts +36 -0
  89. package/src/list-primary-action.ts +71 -0
  90. package/src/model-action-toolbar.tsx +18 -3
  91. package/src/model-extension-registry.tsx +7 -0
  92. package/src/nav-permissions.ts +58 -0
  93. package/src/navigation-builder.tsx +27 -1
  94. package/src/permissions-manager.tsx +39 -26
  95. package/src/print-document-button.tsx +9 -1
  96. package/src/record-mutation-events.ts +50 -0
  97. package/src/types.ts +63 -0
  98. package/src/use-print-document.ts +66 -3
  99. package/src/use-record-mutation-tick.ts +12 -0
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // permissions-manager — "Permisos y Roles" pro view (rol × módulo × acción).
3
3
  //
4
4
  // Transport-agnostic: every read/write arrives via props (loaders/mutators),
@@ -29,7 +29,7 @@ import { Check, ChevronsUpDown, CheckCheck, ChevronDown, Eraser, Pencil, Plus, S
29
29
  import { toast } from 'sonner';
30
30
  import { extractServerError } from './server-error';
31
31
  import { cn } from '@asteby/metacore-ui/lib';
32
- import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Popover, PopoverContent, PopoverTrigger, Separator, Skeleton, Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@asteby/metacore-ui/primitives';
32
+ import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Checkbox, Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Input, Label, Popover, PopoverContent, PopoverTrigger, Skeleton, Collapsible, CollapsibleContent, CollapsibleTrigger, } from '@asteby/metacore-ui/primitives';
33
33
  import { DynamicIcon } from './dynamic-icon';
34
34
  import { IconPickerField } from './icon-picker-field';
35
35
  import { ColorPickerField, DEFAULT_ROLE_COLOR } from './color-picker-field';
@@ -159,6 +159,29 @@ export function suggestRoleIcon(label) {
159
159
  }
160
160
  return 'Shield';
161
161
  }
162
+ /** Label of the synthetic module that hosts the general (non-model) flags. */
163
+ export const GENERAL_MODULE_LABEL = 'Permisos generales';
164
+ /**
165
+ * The general flags (`general.work_after_hours`, …) as a synthetic module, so
166
+ * they are picked from the module combobox and edited in the same two-column
167
+ * action grid as any module's actions (#1021). Each flag keeps its full
168
+ * capability key through `PermissionActionDef.capability`.
169
+ */
170
+ export function generalPermissionsModule(general) {
171
+ return {
172
+ key: 'general',
173
+ label: GENERAL_MODULE_LABEL,
174
+ icon: 'SlidersHorizontal',
175
+ kind: 'model',
176
+ actions: general.map((g) => ({
177
+ key: g.key.replace(/^general\./, ''),
178
+ label: g.label,
179
+ description: g.description,
180
+ capability: g.key,
181
+ kind: 'custom',
182
+ })),
183
+ };
184
+ }
162
185
  /**
163
186
  * Normalize whatever `loadModules` returned into the canonical grouped shape.
164
187
  *
@@ -287,6 +310,16 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
287
310
  const [deleting, setDeleting] = React.useState(false);
288
311
  const loading = groups === null || roles === null;
289
312
  const allModules = React.useMemo(() => (groups ? flattenGroups(groups) : []), [groups]);
313
+ // What the module picker lists: the catalog groups plus a trailing synthetic
314
+ // group for the general flags. `allModules` / "Otorgar todo" keep using the
315
+ // plain catalog, so that button's scope does not change.
316
+ const pickerGroups = React.useMemo(() => {
317
+ if (!groups)
318
+ return groups;
319
+ if (!general || general.length === 0)
320
+ return groups;
321
+ return [...groups, { title: '', modules: [generalPermissionsModule(general)] }];
322
+ }, [groups, general]);
290
323
  // ---- initial load: catalog + roles in parallel -------------------------
291
324
  React.useEffect(() => {
292
325
  let cancelled = false;
@@ -343,7 +376,7 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
343
376
  // eslint-disable-next-line react-hooks/exhaustive-deps
344
377
  }, [activeRoleId]);
345
378
  const activeRole = React.useMemo(() => roles?.find((r) => r.id === activeRoleId) ?? null, [roles, activeRoleId]);
346
- const activeModule = React.useMemo(() => moduleAtEntry(groups, activeModuleKey)?.module ?? null, [groups, activeModuleKey]);
379
+ const activeModule = React.useMemo(() => moduleAtEntry(pickerGroups, activeModuleKey)?.module ?? null, [pickerGroups, activeModuleKey]);
347
380
  const dirty = baseline !== null && draft !== null && !capabilitySetsEqual(baseline, draft);
348
381
  // ---- capability edits ---------------------------------------------------
349
382
  const toggleCapability = React.useCallback((cap) => {
@@ -513,7 +546,7 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
513
546
  const moduleGranted = activeModule && draft ? grantedCountForModule(draft, activeModule) : 0;
514
547
  const moduleTotal = activeModule?.actions.length ?? 0;
515
548
  const checksDisabled = !activeRole || !draft || loadingPerms || saving;
516
- const activeModuleGroupTitle = React.useMemo(() => moduleAtEntry(groups, activeModuleKey)?.group.title ?? '', [groups, activeModuleKey]);
549
+ const activeModuleGroupTitle = React.useMemo(() => moduleAtEntry(pickerGroups, activeModuleKey)?.group.title ?? '', [pickerGroups, activeModuleKey]);
517
550
  // ---- render --------------------------------------------------------------
518
551
  if (loadError) {
519
552
  return (_jsxs("div", { className: cn('flex flex-col items-center justify-center gap-2 py-16 text-muted-foreground', className), children: [_jsx(Shield, { className: "h-8 w-8 opacity-40" }), _jsx("p", { className: "text-sm", children: "No se pudo cargar el cat\u00E1logo de permisos." })] }));
@@ -528,23 +561,23 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
528
561
  color: DEFAULT_ROLE_COLOR,
529
562
  icon: 'Shield',
530
563
  grantAll: false,
531
- }), children: [_jsx(Plus, { className: "mr-1.5 h-4 w-4" }), " Nuevo rol"] })), _jsxs(Button, { variant: "outline", onClick: () => setAllPermissions(true), disabled: checksDisabled || !allCatalogCapabilities.length, title: "Marca todos los permisos de todos los m\u00F3dulos", children: [_jsx(CheckCheck, { className: "mr-1.5 h-4 w-4" }), " Otorgar todo"] }), _jsxs(Button, { variant: "outline", onClick: () => setAllPermissions(false), disabled: checksDisabled || !draft?.size, title: "Quita todos los permisos del rol", children: [_jsx(Eraser, { className: "mr-1.5 h-4 w-4" }), " Quitar todo"] }), _jsxs(Button, { onClick: handleSave, disabled: !dirty || saving || !activeRole, className: "bg-emerald-600 text-white hover:bg-emerald-700", children: [_jsx(Save, { className: "mr-1.5 h-4 w-4" }), saving ? 'Guardando…' : 'Guardar permisos'] })] })] }), _jsxs("div", { className: "grid items-start gap-4 lg:grid-cols-[340px_1fr]", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Rol" }), _jsx(CardDescription, { children: "Selecciona el rol a configurar." })] }), _jsxs(CardContent, { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs(Popover, { open: roleOpen, onOpenChange: setRoleOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", "aria-expanded": roleOpen, className: "min-w-0 flex-1 justify-between font-normal", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [activeRole && (_jsx("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md", style: {
532
- background: `${activeRole.color || '#64748b'}22`,
533
- color: activeRole.color || '#64748b',
534
- }, "aria-hidden": "true", children: _jsx(DynamicIcon, { name: activeRole.icon || 'Shield', className: "h-3.5 w-3.5" }) })), _jsx("span", { className: "truncate", children: activeRole
535
- ? activeRole.label || activeRole.name
536
- : 'Seleccionar rol…' })] }), _jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "w-[280px] p-0", align: "start", children: _jsxs(Command, { children: [_jsx(CommandInput, { placeholder: "Buscar rol\u2026" }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "Sin resultados." }), _jsx(CommandGroup, { children: (roles ?? []).map((role) => (_jsxs(CommandItem, { value: `${role.label || ''} ${role.name}`, onSelect: () => {
537
- requestRoleSwitch(role.id);
538
- setRoleOpen(false);
539
- }, children: [_jsx("span", { className: "mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md", style: {
540
- background: `${role.color || '#64748b'}22`,
541
- color: role.color || '#64748b',
542
- }, "aria-hidden": "true", children: _jsx(DynamicIcon, { name: role.icon || 'Shield', className: "h-3.5 w-3.5" }) }), _jsx("span", { className: "truncate", children: role.label || role.name }), role.id === activeRoleId && (_jsx(Check, { className: "ml-auto h-4 w-4" }))] }, role.id))) })] })] }) })] }), updateRole && (_jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0", "aria-label": "Editar rol", disabled: !activeRole, onClick: openEditRole, children: _jsx(Pencil, { className: "h-4 w-4" }) })), deleteRole && (_jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0 text-destructive hover:text-destructive", "aria-label": "Eliminar rol", disabled: !activeRole, onClick: () => setDeleteOpen(true), children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }), (general?.length ?? 0) > 0 && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { children: [_jsx("h3", { className: "mb-2 text-sm font-semibold", children: "Permisos Generales" }), _jsx("div", { className: "flex flex-col gap-2", children: general.map((g) => (_jsx(CapabilityCheck, { checked: draft?.has(g.key) ?? false, disabled: checksDisabled, onToggle: () => toggleCapability(g.key), label: g.label, description: g.description }, g.key))) })] })] }))] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "M\u00F3dulo" }), _jsx(CardDescription, { children: "Elige el m\u00F3dulo cuyas acciones quieres configurar." })] }), _jsx(CardContent, { children: _jsxs(Popover, { open: moduleOpen, onOpenChange: setModuleOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", "aria-expanded": moduleOpen, className: "w-full justify-between font-normal", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [activeModule && (_jsx(DynamicIcon, { name: activeModule.icon ||
564
+ }), children: [_jsx(Plus, { className: "mr-1.5 h-4 w-4" }), " Nuevo rol"] })), _jsxs(Button, { variant: "outline", onClick: () => setAllPermissions(true), disabled: checksDisabled || !allCatalogCapabilities.length, title: "Marca todos los permisos de todos los m\u00F3dulos", children: [_jsx(CheckCheck, { className: "mr-1.5 h-4 w-4" }), " Otorgar todo"] }), _jsxs(Button, { variant: "outline", onClick: () => setAllPermissions(false), disabled: checksDisabled || !draft?.size, title: "Quita todos los permisos del rol", children: [_jsx(Eraser, { className: "mr-1.5 h-4 w-4" }), " Quitar todo"] }), _jsxs(Button, { onClick: handleSave, disabled: !dirty || saving || !activeRole, className: "bg-emerald-600 text-white hover:bg-emerald-700", children: [_jsx(Save, { className: "mr-1.5 h-4 w-4" }), saving ? 'Guardando…' : 'Guardar permisos'] })] })] }), _jsxs("div", { className: "grid items-start gap-4 lg:grid-cols-[340px_1fr]", children: [_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "Rol" }), _jsx(CardDescription, { children: "Selecciona el rol a configurar." })] }), _jsx(CardContent, { className: "flex flex-col gap-3", children: _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs(Popover, { open: roleOpen, onOpenChange: setRoleOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", "aria-expanded": roleOpen, className: "min-w-0 flex-1 justify-between font-normal", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [activeRole && (_jsx("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-md", style: {
565
+ background: `${activeRole.color || '#64748b'}22`,
566
+ color: activeRole.color || '#64748b',
567
+ }, "aria-hidden": "true", children: _jsx(DynamicIcon, { name: activeRole.icon || 'Shield', className: "h-3.5 w-3.5" }) })), _jsx("span", { className: "truncate", children: activeRole
568
+ ? activeRole.label || activeRole.name
569
+ : 'Seleccionar rol…' })] }), _jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "w-[280px] p-0", align: "start", children: _jsxs(Command, { children: [_jsx(CommandInput, { placeholder: "Buscar rol\u2026" }), _jsxs(CommandList, { children: [_jsx(CommandEmpty, { children: "Sin resultados." }), _jsx(CommandGroup, { children: (roles ?? []).map((role) => (_jsxs(CommandItem, { value: `${role.label || ''} ${role.name}`, onSelect: () => {
570
+ requestRoleSwitch(role.id);
571
+ setRoleOpen(false);
572
+ }, children: [_jsx("span", { className: "mr-2 flex h-6 w-6 shrink-0 items-center justify-center rounded-md", style: {
573
+ background: `${role.color || '#64748b'}22`,
574
+ color: role.color || '#64748b',
575
+ }, "aria-hidden": "true", children: _jsx(DynamicIcon, { name: role.icon || 'Shield', className: "h-3.5 w-3.5" }) }), _jsx("span", { className: "truncate", children: role.label || role.name }), role.id === activeRoleId && (_jsx(Check, { className: "ml-auto h-4 w-4" }))] }, role.id))) })] })] }) })] }), updateRole && (_jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0", "aria-label": "Editar rol", disabled: !activeRole, onClick: openEditRole, children: _jsx(Pencil, { className: "h-4 w-4" }) })), deleteRole && (_jsx(Button, { variant: "outline", size: "icon", className: "h-9 w-9 shrink-0 text-destructive hover:text-destructive", "aria-label": "Eliminar rol", disabled: !activeRole, onClick: () => setDeleteOpen(true), children: _jsx(Trash2, { className: "h-4 w-4" }) }))] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { children: [_jsx(CardTitle, { className: "text-base", children: "M\u00F3dulo" }), _jsx(CardDescription, { children: "Elige el m\u00F3dulo cuyas acciones quieres configurar." })] }), _jsx(CardContent, { children: _jsxs(Popover, { open: moduleOpen, onOpenChange: setModuleOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", role: "combobox", "aria-expanded": moduleOpen, className: "w-full justify-between font-normal", children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [activeModule && (_jsx(DynamicIcon, { name: activeModule.icon ||
543
576
  (activeModule.kind === 'screen'
544
577
  ? 'Eye'
545
578
  : 'Square'), className: "h-4 w-4 shrink-0 opacity-70" })), _jsx("span", { className: "truncate", children: activeModule
546
579
  ? activeModule.label
547
- : 'Seleccionar módulo…' })] }), _jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] min-w-[280px] p-0", align: "start", children: _jsxs(Command, { children: [_jsx(CommandInput, { placeholder: "Buscar m\u00F3dulo\u2026" }), _jsxs(CommandList, { className: "max-h-[360px]", children: [_jsx(CommandEmpty, { children: "Sin m\u00F3dulos." }), (groups ?? []).map((group, gi) => (_jsx(CommandGroup, { heading: group.title || undefined, children: group.modules.map((mod, mi) => (_jsxs(CommandItem, { value: `${group.title} ${mod.label} ${mod.key} ${moduleEntryId(gi, mi)}`, onSelect: () => {
580
+ : 'Seleccionar módulo…' })] }), _jsx(ChevronsUpDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] }) }), _jsx(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] min-w-[280px] p-0", align: "start", children: _jsxs(Command, { children: [_jsx(CommandInput, { placeholder: "Buscar m\u00F3dulo\u2026" }), _jsxs(CommandList, { className: "max-h-[360px]", children: [_jsx(CommandEmpty, { children: "Sin m\u00F3dulos." }), (pickerGroups ?? []).map((group, gi) => (_jsx(CommandGroup, { heading: group.title || undefined, children: group.modules.map((mod, mi) => (_jsxs(CommandItem, { value: `${group.title} ${mod.label} ${mod.key} ${moduleEntryId(gi, mi)}`, onSelect: () => {
548
581
  setActiveModuleKey(moduleEntryId(gi, mi));
549
582
  setModuleOpen(false);
550
583
  }, children: [_jsx(DynamicIcon, { name: mod.icon ||
@@ -1 +1 @@
1
- {"version":3,"file":"print-document-button.d.ts","sourceRoot":"","sources":["../src/print-document-button.tsx"],"names":[],"mappings":"AASA,OAAO,KAAgC,MAAM,OAAO,CAAA;AACpD,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE/E,MAAM,WAAW,wBACb,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IACtE,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IAChC,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAChC,KAAK,EACL,EAAE,EACF,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,IAAI,EACV,EAAE,wBAAwB,qBA+B1B"}
1
+ {"version":3,"file":"print-document-button.d.ts","sourceRoot":"","sources":["../src/print-document-button.tsx"],"names":[],"mappings":"AASA,OAAO,KAAgC,MAAM,OAAO,CAAA;AACpD,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAE/E,MAAM,WAAW,wBACb,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IACtE,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,EAAE,EAAE,MAAM,CAAA;IACV,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAA;IACnB,gEAAgE;IAChE,IAAI,CAAC,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAA;IAChC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAA;IAChC,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC9B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AAED,wBAAgB,mBAAmB,CAAC,EAChC,KAAK,EACL,EAAE,EACF,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,GAAG,IAAI,EACV,EAAE,wBAAwB,qBAuC1B"}
@@ -19,7 +19,15 @@ export function PrintDocumentButton({ model, id, documentKey, mode, filename, on
19
19
  return;
20
20
  setBusy(true);
21
21
  try {
22
- await printDocument({ model, id, key: documentKey, mode, filename });
22
+ // A caller that handles errors itself keeps ownership of the error toast.
23
+ await printDocument({
24
+ model,
25
+ id,
26
+ key: documentKey,
27
+ mode,
28
+ filename,
29
+ feedback: onError ? { progress: true, success: true, error: false } : true,
30
+ });
23
31
  }
24
32
  catch (err) {
25
33
  onError?.(err);
@@ -0,0 +1,14 @@
1
+ export type RecordMutationKind = 'create' | 'update' | 'delete';
2
+ export declare const RECORD_MUTATION_EVENT = "metacore:record-mutated";
3
+ export interface RecordMutationDetail {
4
+ /** Model key as the emitter knows it (matched case-insensitively). */
5
+ model: string;
6
+ kind: RecordMutationKind;
7
+ }
8
+ /** Announce a successful mutation. Safe to call outside a browser (no-op). */
9
+ export declare function emitRecordMutation(model: string | undefined | null, kind: RecordMutationKind): void;
10
+ /**
11
+ * Listen for mutations of `model` (case-insensitive). Returns an unsubscribe.
12
+ */
13
+ export declare function subscribeRecordMutations(model: string | undefined | null, cb: (detail: RecordMutationDetail) => void): () => void;
14
+ //# sourceMappingURL=record-mutation-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record-mutation-events.d.ts","sourceRoot":"","sources":["../src/record-mutation-events.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE/D,eAAO,MAAM,qBAAqB,4BAA4B,CAAA;AAE9D,MAAM,WAAW,oBAAoB;IACjC,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,kBAAkB,CAAA;CAC3B;AAID,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,kBAAkB,GAAG,IAAI,CASnG;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACpC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,EAChC,EAAE,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,GAC3C,MAAM,IAAI,CAUZ"}
@@ -0,0 +1,37 @@
1
+ // record-mutation-events — a tiny window-level bus that tells every mounted
2
+ // list (DynamicTable, DynamicKanban) "a record of model X just changed".
3
+ //
4
+ // Why: the lists only reloaded when the *caller* bumped `refreshTrigger`. A
5
+ // create/edit/delete done from a dialog the shell opens (the dynamic record
6
+ // dialog, a federated action modal, a wizard, a confirmation) never reached
7
+ // the table, so the row stayed stale until a manual refresh (#1020). Emitting
8
+ // here decouples the mutation site from the list that displays the model.
9
+ export const RECORD_MUTATION_EVENT = 'metacore:record-mutated';
10
+ const norm = (m) => (m ?? '').trim().toLowerCase();
11
+ /** Announce a successful mutation. Safe to call outside a browser (no-op). */
12
+ export function emitRecordMutation(model, kind) {
13
+ if (!model || typeof window === 'undefined' || typeof CustomEvent === 'undefined')
14
+ return;
15
+ try {
16
+ window.dispatchEvent(new CustomEvent(RECORD_MUTATION_EVENT, { detail: { model, kind } }));
17
+ }
18
+ catch {
19
+ /* a listener must never break the save flow */
20
+ }
21
+ }
22
+ /**
23
+ * Listen for mutations of `model` (case-insensitive). Returns an unsubscribe.
24
+ */
25
+ export function subscribeRecordMutations(model, cb) {
26
+ if (typeof window === 'undefined')
27
+ return () => { };
28
+ const want = norm(model);
29
+ const handler = (e) => {
30
+ const d = e.detail;
31
+ if (!d || !want || norm(d.model) !== want)
32
+ return;
33
+ cb(d);
34
+ };
35
+ window.addEventListener(RECORD_MUTATION_EVENT, handler);
36
+ return () => window.removeEventListener(RECORD_MUTATION_EVENT, handler);
37
+ }
package/dist/types.d.ts CHANGED
@@ -17,6 +17,45 @@ export interface ImportSpecMeta {
17
17
  sheetName?: string;
18
18
  instructions?: string[];
19
19
  }
20
+ /** Paso de renglones de un tipo de documento (usa el editor de renglones del SDK). */
21
+ export interface DocumentFormLines {
22
+ /** Campo del payload que recibe los renglones. Default: `lines` (o `lines_field` del manifest). */
23
+ field?: string;
24
+ /** Columnas opcionales del editor (`discount`, `tax`, `unit`…). */
25
+ columns?: string[];
26
+ /** `sale` (precio de lista) o `cost` (compras). Default `sale`. */
27
+ price_source?: 'sale' | 'cost';
28
+ /** Al menos un renglón para guardar. Default true. */
29
+ required?: boolean;
30
+ /** Título del paso. Default «Renglones». */
31
+ title?: string;
32
+ }
33
+ /** Un tipo de documento (Factura, Nota de crédito, REP, Global, Traslado…). */
34
+ export interface DocumentFormType {
35
+ key: string;
36
+ label: string;
37
+ description?: string;
38
+ icon?: string;
39
+ /** Valor que se escribe en `type_field` (p. ej. `"E"`). Default: `key`. */
40
+ value?: string;
41
+ /** Campos del tipo, en el mismo vocabulario que los campos de una acción. */
42
+ fields: ActionFieldDef[];
43
+ /** Valores fijos que viajan en el alta de este tipo. */
44
+ defaults?: Record<string, unknown>;
45
+ /** Con esto el tipo tiene paso de renglones. */
46
+ lines?: DocumentFormLines | boolean;
47
+ /** Endpoint de alta propio de este tipo. Default: el del modelo. */
48
+ endpoint?: string;
49
+ /** Texto del botón final. Default «Crear». */
50
+ submit_label?: string;
51
+ }
52
+ export interface DocumentFormsManifest {
53
+ /** Columna discriminadora del modelo (p. ej. `"type"`). Sin ella no se escribe el tipo. */
54
+ type_field?: string;
55
+ /** Campo por defecto de los renglones. Default `lines`. */
56
+ lines_field?: string;
57
+ types: DocumentFormType[];
58
+ }
20
59
  export interface TableMetadata {
21
60
  title: string;
22
61
  endpoint: string;
@@ -31,6 +70,20 @@ export interface TableMetadata {
31
70
  canExport?: boolean;
32
71
  canImport?: boolean;
33
72
  canCreate?: boolean;
73
+ /**
74
+ * Formularios de alta guiados por tipo de documento (FAC-12). Cuando trae
75
+ * al menos un tipo, `DynamicCRUDPage` abre `DocumentFormDialog` en lugar del
76
+ * formulario genérico del modelo. Lo sirve el kernel o el addon; el SDK no
77
+ * conoce campos fiscales.
78
+ */
79
+ document_forms?: DocumentFormsManifest;
80
+ /**
81
+ * Cómo se pinta el alta genérica. `generic` (o ausente) es el botón Crear.
82
+ * `hidden` lo quita. `action` lo quita porque el módulo trae la suya
83
+ * (`placement: create` o `replaces_create`). Lo sirve el kernel; un host
84
+ * también puede fijarlo con `ModelExtension.createMode` sin cambio de kernel.
85
+ */
86
+ create_mode?: 'generic' | 'hidden' | 'action';
34
87
  /**
35
88
  * The model's spreadsheet-import declaration, served by the kernel: the
36
89
  * columns of the generated template and the headers accepted when parsing
@@ -644,6 +697,13 @@ export interface ActionDefinition {
644
697
  * "create" — toolbar button that replaces the generic create button.
645
698
  */
646
699
  placement?: 'row' | 'table' | 'create';
700
+ /**
701
+ * Esta acción de toolbar sustituye al Crear genérico aunque su `placement`
702
+ * sea `table`. El kernel tiene que reenviar el campo; si lo recorta, el
703
+ * host usa `ModelExtension.primaryActionKey` o `createMode`.
704
+ */
705
+ replaces_create?: boolean;
706
+ replacesCreate?: boolean;
647
707
  /**
648
708
  * Optional addon this action depends on, stamped by the host only while it
649
709
  * is NOT installed (served as `requires_addon`; read through
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,21 @@ export interface PrintDocumentArgs {
19
19
  * that is how downloads end up literally named with mustache braces.
20
20
  */
21
21
  filename?: string;
22
+ /**
23
+ * User feedback. Default: a toast while the file is prepared, a success toast
24
+ * when it is ready and an error toast with the server's reason when it fails
25
+ * (a download used to give NO sign of life — PIT «Descargar Factura CFDI»).
26
+ * `false` silences all of it; `{ error: false }` leaves errors to the caller
27
+ * (the promise still rejects either way).
28
+ */
29
+ feedback?: boolean | {
30
+ progress?: boolean;
31
+ success?: boolean;
32
+ error?: boolean;
33
+ };
22
34
  }
35
+ /** Best-effort message from an error whose body is a Blob (responseType: 'blob'). */
36
+ export declare function documentErrorMessage(err: unknown): Promise<string>;
23
37
  /** Parse filename from Content-Disposition (RFC 5987 / quoted). */
24
38
  export declare function filenameFromContentDisposition(header: string | undefined | null): string | undefined;
25
39
  /** True when a caller passed an unexpanded mustache template as filename. */
@@ -30,5 +44,5 @@ export declare function looksLikeFilenameTemplate(name: string | undefined): boo
30
44
  * rejects if the fetch fails (surface the error to a toast). Returns the blob
31
45
  * URL created, revoked automatically after a minute.
32
46
  */
33
- export declare function usePrintDocument(): ({ model, id, key, mode, filename, }: PrintDocumentArgs) => Promise<string>;
47
+ export declare function usePrintDocument(): ({ model, id, key, mode, filename, feedback, }: PrintDocumentArgs) => Promise<string>;
34
48
  //# sourceMappingURL=use-print-document.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-print-document.d.ts","sourceRoot":"","sources":["../src/use-print-document.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,iBAAiB;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAA;IACX;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAA;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,mEAAmE;AACnE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAapG;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,0CASrB,iBAAiB,KAAG,OAAO,CAAC,MAAM,CAAC,CAmE7C"}
1
+ {"version":3,"file":"use-print-document.d.ts","sourceRoot":"","sources":["../src/use-print-document.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,iBAAiB;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAA;IACX;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAA;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAClF;AAQD,qFAAqF;AACrF,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBxE;AAED,mEAAmE;AACnE,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAapG;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,oDAoFrB,iBAAiB,KAAG,OAAO,CAAC,MAAM,CAAC,CAkB7C"}
@@ -17,7 +17,35 @@
17
17
  // The ApiClient is a PEER via <ApiProvider> (same one useAddonSettings uses), so
18
18
  // this hook constructs no client of its own.
19
19
  import { useCallback } from 'react';
20
+ import { toast } from 'sonner';
20
21
  import { useApi } from './api-context';
22
+ const noun = (mode) => mode === 'download' ? 'Descargando documento…' : mode === 'open' ? 'Abriendo documento…' : 'Preparando impresión…';
23
+ const readyMessage = (mode) => mode === 'download' ? 'Documento descargado' : mode === 'open' ? 'Documento abierto' : 'Documento listo para imprimir';
24
+ /** Best-effort message from an error whose body is a Blob (responseType: 'blob'). */
25
+ export async function documentErrorMessage(err) {
26
+ const fallback = 'No se pudo generar el documento. Inténtalo de nuevo.';
27
+ const e = err;
28
+ let data = e?.response?.data;
29
+ try {
30
+ if (typeof Blob !== 'undefined' && data instanceof Blob) {
31
+ data = JSON.parse(await data.text());
32
+ }
33
+ }
34
+ catch {
35
+ data = undefined;
36
+ }
37
+ const d = data;
38
+ if (typeof d === 'string' && d.trim())
39
+ return d.trim().slice(0, 200);
40
+ if (d && typeof d === 'object') {
41
+ const msg = [d.message, d.details, d.error].find((x) => typeof x === 'string' && x.trim());
42
+ if (msg)
43
+ return msg.trim();
44
+ }
45
+ if (e?.response?.status === 404)
46
+ return 'El documento no está disponible todavía.';
47
+ return fallback;
48
+ }
21
49
  /** Parse filename from Content-Disposition (RFC 5987 / quoted). */
22
50
  export function filenameFromContentDisposition(header) {
23
51
  if (!header)
@@ -47,7 +75,7 @@ export function looksLikeFilenameTemplate(name) {
47
75
  */
48
76
  export function usePrintDocument() {
49
77
  const api = useApi();
50
- return useCallback(async ({ model, id, key, mode = 'print', filename, }) => {
78
+ const run = useCallback(async ({ model, id, key, mode, filename, }) => {
51
79
  const url = `/data/${encodeURIComponent(model)}/${encodeURIComponent(id)}/documents/${encodeURIComponent(key)}.pdf`;
52
80
  const res = await api.get(url, { responseType: 'blob' });
53
81
  const blob = res.data instanceof Blob
@@ -103,4 +131,27 @@ export function usePrintDocument() {
103
131
  document.body.appendChild(iframe);
104
132
  return blobUrl;
105
133
  }, [api]);
134
+ return useCallback(async ({ model, id, key, mode = 'print', filename, feedback = true, }) => {
135
+ const fb = feedback === false ? {} : feedback === true ? { progress: true, success: true, error: true } : feedback;
136
+ const toastId = fb.progress ? toast.loading(noun(mode)) : undefined;
137
+ try {
138
+ const blobUrl = await run({ model, id, key, mode, filename });
139
+ if (toastId !== undefined)
140
+ toast.dismiss(toastId);
141
+ if (fb.success)
142
+ toast.success(readyMessage(mode));
143
+ return blobUrl;
144
+ }
145
+ catch (err) {
146
+ if (toastId !== undefined)
147
+ toast.dismiss(toastId);
148
+ if (fb.error)
149
+ toast.error(await documentErrorMessage(err));
150
+ throw err;
151
+ }
152
+ finally {
153
+ if (toastId !== undefined)
154
+ toast.dismiss(toastId);
155
+ }
156
+ }, [run]);
106
157
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A counter that increments whenever a record of `model` is created, updated
3
+ * or deleted anywhere in the app. Fold it into a list's refetch deps.
4
+ */
5
+ export declare function useRecordMutationTick(model: string | undefined | null): number;
6
+ //# sourceMappingURL=use-record-mutation-tick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-record-mutation-tick.d.ts","sourceRoot":"","sources":["../src/use-record-mutation-tick.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAI9E"}
@@ -0,0 +1,11 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { subscribeRecordMutations } from './record-mutation-events';
3
+ /**
4
+ * A counter that increments whenever a record of `model` is created, updated
5
+ * or deleted anywhere in the app. Fold it into a list's refetch deps.
6
+ */
7
+ export function useRecordMutationTick(model) {
8
+ const [tick, setTick] = useState(0);
9
+ useEffect(() => subscribeRecordMutations(model, () => setTick((n) => n + 1)), [model]);
10
+ return tick;
11
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "46.3.0",
3
+ "version": "47.0.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@asteby/metacore-sdk": "^3.12.0",
30
- "@asteby/metacore-ui": "^2.23.0",
30
+ "@asteby/metacore-ui": "^2.24.0",
31
31
  "@tanstack/react-query": ">=5",
32
32
  "@tanstack/react-router": ">=1.100",
33
33
  "@tanstack/react-table": ">=8",
@@ -51,7 +51,7 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@asteby/metacore-sdk": "3.12.0",
54
- "@asteby/metacore-ui": "2.23.0",
54
+ "@asteby/metacore-ui": "2.24.0",
55
55
  "@tanstack/react-query": "^5.95.0",
56
56
  "@tanstack/react-router": "^1.168.0",
57
57
  "@tanstack/react-table": "^8.20.0",
@@ -0,0 +1,116 @@
1
+ // @vitest-environment happy-dom
2
+ //
3
+ // Action dialogs (PIT-046 #1023, FAC-3/PIT-051 #1024):
4
+ // - a failed submit (422 with `errors`, or 500) paints a banner INSIDE the
5
+ // dialog and keeps it open;
6
+ // - a stamp result ({fiscal_uuid, pdf_url, xml_url}) renders as a panel with
7
+ // PDF/XML links, never as raw JSON; other payloads invent nothing.
8
+ import { afterEach, describe, expect, it, vi } from 'vitest'
9
+ import { cleanup, render, screen, fireEvent, waitFor } from '@testing-library/react'
10
+
11
+ vi.mock('react-i18next', () => ({
12
+ useTranslation: () => ({
13
+ t: (k: string, o?: any) => o?.defaultValue ?? k,
14
+ i18n: { language: 'es' },
15
+ }),
16
+ }))
17
+
18
+ import { ActionModalDispatcher } from '../action-modal-dispatcher'
19
+ import { extractStampResult } from '../cfdi-stamp-panel'
20
+ import { ApiProvider, type ApiClient } from '../api-context'
21
+ import type { ActionMetadata } from '@asteby/metacore-sdk'
22
+
23
+ afterEach(cleanup)
24
+
25
+ const action = {
26
+ key: 'rebill',
27
+ label: 'Refacturar',
28
+ icon: 'file',
29
+ fields: [{ key: 'reason', label: 'Motivo', type: 'text' }],
30
+ } as unknown as ActionMetadata
31
+
32
+ function setup(postImpl: () => Promise<any>) {
33
+ const post = vi.fn(postImpl)
34
+ const api = { get: vi.fn().mockResolvedValue({ data: {} }), post } as unknown as ApiClient
35
+ const onOpenChange = vi.fn()
36
+ const onSuccess = vi.fn()
37
+ render(
38
+ <ApiProvider client={api}>
39
+ <ActionModalDispatcher
40
+ open
41
+ onOpenChange={onOpenChange}
42
+ action={action}
43
+ model="invoice"
44
+ record={{ id: '7' } as any}
45
+ endpoint="/data/invoice"
46
+ onSuccess={onSuccess}
47
+ />
48
+ </ApiProvider>,
49
+ )
50
+ return { post, onOpenChange, onSuccess }
51
+ }
52
+
53
+ const submit = () => fireEvent.click(screen.getByRole('button', { name: 'Refacturar' }))
54
+
55
+ describe('action dialog error banner', () => {
56
+ it('shows the 422 field errors in the dialog and stays open', async () => {
57
+ const { onOpenChange, onSuccess } = setup(() =>
58
+ Promise.reject({
59
+ response: {
60
+ status: 422,
61
+ data: { success: false, message: 'validation failed', errors: { reason: ['Motivo inválido para SAT'] } },
62
+ },
63
+ }),
64
+ )
65
+ submit()
66
+ const banner = await screen.findByRole('alert')
67
+ expect(banner.textContent).toContain('Motivo inválido para SAT')
68
+ expect(onOpenChange).not.toHaveBeenCalledWith(false)
69
+ expect(onSuccess).not.toHaveBeenCalled()
70
+ })
71
+
72
+ it('shows the server message of a 500 in the dialog', async () => {
73
+ const { onOpenChange } = setup(() =>
74
+ Promise.reject({ response: { status: 500, data: { success: false, message: 'PAC no disponible', details: 'timeout 30s' } } }),
75
+ )
76
+ submit()
77
+ const banner = await screen.findByRole('alert')
78
+ expect(banner.textContent).toContain('PAC no disponible')
79
+ expect(banner.textContent).toContain('timeout 30s')
80
+ expect(onOpenChange).not.toHaveBeenCalledWith(false)
81
+ })
82
+ })
83
+
84
+ describe('stamp result panel', () => {
85
+ it('renders UUID + PDF/XML links instead of JSON', async () => {
86
+ const { onSuccess } = setup(() =>
87
+ Promise.resolve({
88
+ data: {
89
+ success: true,
90
+ data: {
91
+ document_id: 'd1',
92
+ fiscal_uuid: '6B1C0E7E-0000-4000-8000-ABCDEF123456',
93
+ pdf_url: 'https://files.example/f.pdf',
94
+ xml_url: 'https://files.example/f.xml',
95
+ },
96
+ },
97
+ }),
98
+ )
99
+ submit()
100
+ const uuid = await screen.findByText('6B1C0E7E-0000-4000-8000-ABCDEF123456')
101
+ expect(uuid).toBeTruthy()
102
+ expect((screen.getByText('Descargar PDF').closest('a') as HTMLAnchorElement).href).toBe('https://files.example/f.pdf')
103
+ expect((screen.getByText('Descargar XML').closest('a') as HTMLAnchorElement).href).toBe('https://files.example/f.xml')
104
+ expect(document.body.textContent).not.toContain('document_id')
105
+ expect(onSuccess).not.toHaveBeenCalled()
106
+ fireEvent.click(screen.getByRole('button', { name: 'Cerrar' }))
107
+ await waitFor(() => expect(onSuccess).toHaveBeenCalledTimes(1))
108
+ })
109
+
110
+ it('does not invent a fiscal result without the keys', () => {
111
+ expect(extractStampResult({ success: true, data: { id: 1, name: 'x' } })).toBeUndefined()
112
+ expect(extractStampResult({ success: true })).toBeUndefined()
113
+ expect(extractStampResult({ data: { uuid: 'abc' } })).toBeUndefined()
114
+ expect(extractStampResult({ data: { fiscal_uuid: 'U' } })).toMatchObject({ fiscalUuid: 'U' })
115
+ })
116
+ })