@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
@@ -17,6 +17,7 @@
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'
21
22
 
22
23
  export interface PrintDocumentArgs {
@@ -40,6 +41,42 @@ export interface PrintDocumentArgs {
40
41
  * that is how downloads end up literally named with mustache braces.
41
42
  */
42
43
  filename?: string
44
+ /**
45
+ * User feedback. Default: a toast while the file is prepared, a success toast
46
+ * when it is ready and an error toast with the server's reason when it fails
47
+ * (a download used to give NO sign of life — PIT «Descargar Factura CFDI»).
48
+ * `false` silences all of it; `{ error: false }` leaves errors to the caller
49
+ * (the promise still rejects either way).
50
+ */
51
+ feedback?: boolean | { progress?: boolean; success?: boolean; error?: boolean }
52
+ }
53
+
54
+ const noun = (mode: 'print' | 'download' | 'open') =>
55
+ mode === 'download' ? 'Descargando documento…' : mode === 'open' ? 'Abriendo documento…' : 'Preparando impresión…'
56
+
57
+ const readyMessage = (mode: 'print' | 'download' | 'open') =>
58
+ mode === 'download' ? 'Documento descargado' : mode === 'open' ? 'Documento abierto' : 'Documento listo para imprimir'
59
+
60
+ /** Best-effort message from an error whose body is a Blob (responseType: 'blob'). */
61
+ export async function documentErrorMessage(err: unknown): Promise<string> {
62
+ const fallback = 'No se pudo generar el documento. Inténtalo de nuevo.'
63
+ const e = err as { response?: { data?: unknown; status?: number }; message?: unknown } | undefined
64
+ let data = e?.response?.data
65
+ try {
66
+ if (typeof Blob !== 'undefined' && data instanceof Blob) {
67
+ data = JSON.parse(await data.text())
68
+ }
69
+ } catch {
70
+ data = undefined
71
+ }
72
+ const d = data as { message?: unknown; details?: unknown; error?: unknown } | string | undefined
73
+ if (typeof d === 'string' && d.trim()) return d.trim().slice(0, 200)
74
+ if (d && typeof d === 'object') {
75
+ const msg = [d.message, d.details, d.error].find((x) => typeof x === 'string' && x.trim()) as string | undefined
76
+ if (msg) return msg.trim()
77
+ }
78
+ if (e?.response?.status === 404) return 'El documento no está disponible todavía.'
79
+ return fallback
43
80
  }
44
81
 
45
82
  /** Parse filename from Content-Disposition (RFC 5987 / quoted). */
@@ -71,14 +108,14 @@ export function looksLikeFilenameTemplate(name: string | undefined): boolean {
71
108
  */
72
109
  export function usePrintDocument() {
73
110
  const api = useApi()
74
- return useCallback(
111
+ const run = useCallback(
75
112
  async ({
76
113
  model,
77
114
  id,
78
115
  key,
79
- mode = 'print',
116
+ mode,
80
117
  filename,
81
- }: PrintDocumentArgs): Promise<string> => {
118
+ }: Required<Pick<PrintDocumentArgs, 'model' | 'id' | 'key' | 'mode'>> & Pick<PrintDocumentArgs, 'filename'>): Promise<string> => {
82
119
  const url = `/data/${encodeURIComponent(model)}/${encodeURIComponent(
83
120
  id,
84
121
  )}/documents/${encodeURIComponent(key)}.pdf`
@@ -145,4 +182,30 @@ export function usePrintDocument() {
145
182
  },
146
183
  [api],
147
184
  )
185
+ return useCallback(
186
+ async ({
187
+ model,
188
+ id,
189
+ key,
190
+ mode = 'print',
191
+ filename,
192
+ feedback = true,
193
+ }: PrintDocumentArgs): Promise<string> => {
194
+ const fb = feedback === false ? {} : feedback === true ? { progress: true, success: true, error: true } : feedback
195
+ const toastId = fb.progress ? toast.loading(noun(mode)) : undefined
196
+ try {
197
+ const blobUrl = await run({ model, id, key, mode, filename })
198
+ if (toastId !== undefined) toast.dismiss(toastId)
199
+ if (fb.success) toast.success(readyMessage(mode))
200
+ return blobUrl
201
+ } catch (err) {
202
+ if (toastId !== undefined) toast.dismiss(toastId)
203
+ if (fb.error) toast.error(await documentErrorMessage(err))
204
+ throw err
205
+ } finally {
206
+ if (toastId !== undefined) toast.dismiss(toastId)
207
+ }
208
+ },
209
+ [run],
210
+ )
148
211
  }
@@ -0,0 +1,12 @@
1
+ import { useEffect, useState } from 'react'
2
+ import { subscribeRecordMutations } from './record-mutation-events'
3
+
4
+ /**
5
+ * A counter that increments whenever a record of `model` is created, updated
6
+ * or deleted anywhere in the app. Fold it into a list's refetch deps.
7
+ */
8
+ export function useRecordMutationTick(model: string | undefined | null): number {
9
+ const [tick, setTick] = useState(0)
10
+ useEffect(() => subscribeRecordMutations(model, () => setTick((n) => n + 1)), [model])
11
+ return tick
12
+ }