@asteby/metacore-runtime-react 44.0.0 → 45.2.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 (158) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/approval-events.d.ts +16 -0
  3. package/dist/approval-events.d.ts.map +1 -0
  4. package/dist/approval-events.js +27 -0
  5. package/dist/approval-gate.d.ts +39 -0
  6. package/dist/approval-gate.d.ts.map +1 -0
  7. package/dist/approval-gate.js +110 -0
  8. package/dist/approval-pin-dialog.d.ts +25 -0
  9. package/dist/approval-pin-dialog.d.ts.map +1 -0
  10. package/dist/approval-pin-dialog.js +66 -0
  11. package/dist/business/catalog.d.ts +16 -0
  12. package/dist/business/catalog.d.ts.map +1 -0
  13. package/dist/business/catalog.js +42 -0
  14. package/dist/business/customer-picker.d.ts +39 -0
  15. package/dist/business/customer-picker.d.ts.map +1 -0
  16. package/dist/business/customer-picker.js +51 -0
  17. package/dist/business/feedback.d.ts +72 -0
  18. package/dist/business/feedback.d.ts.map +1 -0
  19. package/dist/business/feedback.js +52 -0
  20. package/dist/business/field-errors.d.ts +26 -0
  21. package/dist/business/field-errors.d.ts.map +1 -0
  22. package/dist/business/field-errors.js +59 -0
  23. package/dist/business/format.d.ts +49 -0
  24. package/dist/business/format.d.ts.map +1 -0
  25. package/dist/business/format.js +128 -0
  26. package/dist/business/index.d.ts +14 -0
  27. package/dist/business/index.d.ts.map +1 -0
  28. package/dist/business/index.js +13 -0
  29. package/dist/business/line-items-editor.d.ts +25 -0
  30. package/dist/business/line-items-editor.d.ts.map +1 -0
  31. package/dist/business/line-items-editor.js +36 -0
  32. package/dist/business/line-items.d.ts +69 -0
  33. package/dist/business/line-items.d.ts.map +1 -0
  34. package/dist/business/line-items.js +133 -0
  35. package/dist/business/payment-capture.d.ts +21 -0
  36. package/dist/business/payment-capture.d.ts.map +1 -0
  37. package/dist/business/payment-capture.js +24 -0
  38. package/dist/business/payment.d.ts +61 -0
  39. package/dist/business/payment.d.ts.map +1 -0
  40. package/dist/business/payment.js +74 -0
  41. package/dist/business/product-picker.d.ts +24 -0
  42. package/dist/business/product-picker.d.ts.map +1 -0
  43. package/dist/business/product-picker.js +48 -0
  44. package/dist/business/product-search.d.ts +70 -0
  45. package/dist/business/product-search.d.ts.map +1 -0
  46. package/dist/business/product-search.js +51 -0
  47. package/dist/business/refund-destination.d.ts +19 -0
  48. package/dist/business/refund-destination.d.ts.map +1 -0
  49. package/dist/business/refund-destination.js +31 -0
  50. package/dist/business/refund.d.ts +29 -0
  51. package/dist/business/refund.d.ts.map +1 -0
  52. package/dist/business/refund.js +43 -0
  53. package/dist/business/use-async-search.d.ts +10 -0
  54. package/dist/business/use-async-search.d.ts.map +1 -0
  55. package/dist/business/use-async-search.js +38 -0
  56. package/dist/document/action-bar.d.ts +12 -0
  57. package/dist/document/action-bar.d.ts.map +1 -0
  58. package/dist/document/action-bar.js +39 -0
  59. package/dist/document/cancel-with-reason.d.ts +47 -0
  60. package/dist/document/cancel-with-reason.d.ts.map +1 -0
  61. package/dist/document/cancel-with-reason.js +52 -0
  62. package/dist/document/document-header.d.ts +41 -0
  63. package/dist/document/document-header.d.ts.map +1 -0
  64. package/dist/document/document-header.js +30 -0
  65. package/dist/document/document-page.d.ts +37 -0
  66. package/dist/document/document-page.d.ts.map +1 -0
  67. package/dist/document/document-page.js +137 -0
  68. package/dist/document/document-timeline.d.ts +20 -0
  69. package/dist/document/document-timeline.d.ts.map +1 -0
  70. package/dist/document/document-timeline.js +26 -0
  71. package/dist/document/evaluate.d.ts +31 -0
  72. package/dist/document/evaluate.d.ts.map +1 -0
  73. package/dist/document/evaluate.js +170 -0
  74. package/dist/document/format.d.ts +9 -0
  75. package/dist/document/format.d.ts.map +1 -0
  76. package/dist/document/format.js +52 -0
  77. package/dist/document/index.d.ts +13 -0
  78. package/dist/document/index.d.ts.map +1 -0
  79. package/dist/document/index.js +12 -0
  80. package/dist/document/registry.d.ts +20 -0
  81. package/dist/document/registry.d.ts.map +1 -0
  82. package/dist/document/registry.js +20 -0
  83. package/dist/document/smart-buttons.d.ts +16 -0
  84. package/dist/document/smart-buttons.d.ts.map +1 -0
  85. package/dist/document/smart-buttons.js +16 -0
  86. package/dist/document/status-badge.d.ts +16 -0
  87. package/dist/document/status-badge.d.ts.map +1 -0
  88. package/dist/document/status-badge.js +23 -0
  89. package/dist/document/types.d.ts +196 -0
  90. package/dist/document/types.d.ts.map +1 -0
  91. package/dist/document/types.js +1 -0
  92. package/dist/document/use-document-sources.d.ts +14 -0
  93. package/dist/document/use-document-sources.d.ts.map +1 -0
  94. package/dist/document/use-document-sources.js +72 -0
  95. package/dist/dynamic-columns.d.ts +11 -0
  96. package/dist/dynamic-columns.d.ts.map +1 -1
  97. package/dist/dynamic-columns.js +13 -1
  98. package/dist/dynamic-kanban.d.ts.map +1 -1
  99. package/dist/dynamic-kanban.js +4 -5
  100. package/dist/dynamic-row-actions.d.ts.map +1 -1
  101. package/dist/dynamic-row-actions.js +12 -1
  102. package/dist/index.d.ts +5 -0
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +6 -0
  105. package/dist/model-action-toolbar.d.ts.map +1 -1
  106. package/dist/model-action-toolbar.js +16 -3
  107. package/dist/requires-addon.d.ts +37 -0
  108. package/dist/requires-addon.d.ts.map +1 -0
  109. package/dist/requires-addon.js +104 -0
  110. package/dist/server-error.d.ts.map +1 -1
  111. package/dist/server-error.js +19 -0
  112. package/dist/types.d.ts +23 -0
  113. package/dist/types.d.ts.map +1 -1
  114. package/package.json +3 -3
  115. package/src/__tests__/approval-gate.test.tsx +134 -0
  116. package/src/__tests__/requires-addon.test.tsx +201 -0
  117. package/src/approval-events.ts +39 -0
  118. package/src/approval-gate.tsx +180 -0
  119. package/src/approval-pin-dialog.tsx +162 -0
  120. package/src/business/business.test.ts +164 -0
  121. package/src/business/catalog.ts +60 -0
  122. package/src/business/customer-picker.tsx +201 -0
  123. package/src/business/feedback.tsx +141 -0
  124. package/src/business/field-errors.ts +92 -0
  125. package/src/business/format.ts +151 -0
  126. package/src/business/index.ts +13 -0
  127. package/src/business/line-items-editor.tsx +259 -0
  128. package/src/business/line-items.ts +190 -0
  129. package/src/business/payment-capture.tsx +158 -0
  130. package/src/business/payment.ts +125 -0
  131. package/src/business/product-picker.tsx +171 -0
  132. package/src/business/product-search.ts +108 -0
  133. package/src/business/refund-destination.tsx +121 -0
  134. package/src/business/refund.ts +71 -0
  135. package/src/business/use-async-search.ts +43 -0
  136. package/src/document/__tests__/document-page.test.tsx +107 -0
  137. package/src/document/__tests__/evaluate.test.ts +140 -0
  138. package/src/document/action-bar.tsx +140 -0
  139. package/src/document/cancel-with-reason.tsx +214 -0
  140. package/src/document/document-header.tsx +140 -0
  141. package/src/document/document-page.tsx +268 -0
  142. package/src/document/document-timeline.tsx +66 -0
  143. package/src/document/evaluate.ts +180 -0
  144. package/src/document/format.ts +59 -0
  145. package/src/document/index.ts +28 -0
  146. package/src/document/registry.ts +39 -0
  147. package/src/document/smart-buttons.tsx +54 -0
  148. package/src/document/status-badge.tsx +44 -0
  149. package/src/document/types.ts +203 -0
  150. package/src/document/use-document-sources.ts +91 -0
  151. package/src/dynamic-columns.tsx +36 -6
  152. package/src/dynamic-kanban.tsx +6 -7
  153. package/src/dynamic-row-actions.tsx +15 -1
  154. package/src/index.ts +34 -0
  155. package/src/model-action-toolbar.tsx +28 -3
  156. package/src/requires-addon.tsx +160 -0
  157. package/src/server-error.ts +20 -0
  158. package/src/types.ts +24 -0
package/dist/types.d.ts CHANGED
@@ -597,6 +597,15 @@ export interface FieldOptionsConfig {
597
597
  /** Optional column projected into `option.image`. */
598
598
  image?: string;
599
599
  }
600
+ /** An optional addon an action needs before it can run. */
601
+ export interface RequiresAddon {
602
+ /** Addon key, e.g. "connector_whatsapp". */
603
+ key: string;
604
+ /** Localized display name, e.g. "Conector WhatsApp". Falls back to `key`. */
605
+ name?: string;
606
+ /** Why the action needs it (literal or i18n key). */
607
+ reason?: string;
608
+ }
600
609
  export interface ActionDefinition {
601
610
  key: string;
602
611
  name: string;
@@ -623,6 +632,13 @@ export interface ActionDefinition {
623
632
  * "create" — toolbar button that replaces the generic create button.
624
633
  */
625
634
  placement?: 'row' | 'table' | 'create';
635
+ /**
636
+ * Optional addon this action depends on, stamped by the host only while it
637
+ * is NOT installed (served as `requires_addon`; read through
638
+ * resolveRequiresAddon). The action stays visible but locked: a click opens
639
+ * the "requires addon" dialog instead of executing.
640
+ */
641
+ requiresAddon?: RequiresAddon;
626
642
  }
627
643
  export interface ApiResponse<T> {
628
644
  success: boolean;
@@ -660,5 +676,12 @@ export interface ActionMetadata {
660
676
  /** Federated modal slug "<addon_key>.<action_key>"; see ActionModalDispatcher. */
661
677
  modal?: string;
662
678
  placement?: 'row' | 'table' | 'create';
679
+ /**
680
+ * Optional addon this action depends on, stamped by the host only while it
681
+ * is NOT installed (served as `requires_addon`; read through
682
+ * resolveRequiresAddon). The action stays visible but locked: a click opens
683
+ * the "requires addon" dialog instead of executing.
684
+ */
685
+ requiresAddon?: RequiresAddon;
663
686
  }
664
687
  //# sourceMappingURL=types.d.ts.map
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "44.0.0",
3
+ "version": "45.2.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,7 +26,7 @@
26
26
  "zod": "^4.3.0"
27
27
  },
28
28
  "peerDependencies": {
29
- "@asteby/metacore-sdk": "^3.10.0",
29
+ "@asteby/metacore-sdk": "^3.11.0",
30
30
  "@asteby/metacore-ui": "^2.23.0",
31
31
  "@tanstack/react-query": ">=5",
32
32
  "@tanstack/react-router": ">=1.100",
@@ -50,7 +50,7 @@
50
50
  }
51
51
  },
52
52
  "devDependencies": {
53
- "@asteby/metacore-sdk": "3.10.0",
53
+ "@asteby/metacore-sdk": "3.11.0",
54
54
  "@asteby/metacore-ui": "2.23.0",
55
55
  "@tanstack/react-query": "^5.95.0",
56
56
  "@tanstack/react-router": "^1.168.0",
@@ -0,0 +1,134 @@
1
+ // @vitest-environment happy-dom
2
+ //
3
+ // ApprovalGate: inline PIN grants + parked-request approval, and the capability
4
+ // bypass that lets a supervisor skip their own prompt.
5
+ import { afterEach, describe, expect, it, vi } from 'vitest'
6
+ import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
7
+
8
+ vi.mock('react-i18next', () => ({
9
+ useTranslation: () => ({
10
+ t: (_k: string, opts?: { defaultValue?: string }) => opts?.defaultValue ?? _k,
11
+ }),
12
+ }))
13
+ vi.mock('sonner', () => ({ toast: Object.assign(vi.fn(), { info: vi.fn(), success: vi.fn(), error: vi.fn() }) }))
14
+
15
+ import { ApiProvider, type ApiClient } from '../api-context'
16
+ import { PermissionsProvider } from '../permissions-context'
17
+ import {
18
+ ApprovalGateProvider,
19
+ useApprovalGate,
20
+ approvalRequiredInfo,
21
+ APPROVAL_PARKED_EVENT,
22
+ type ApprovalGrant,
23
+ } from '../approval-gate'
24
+ import { toastServerError } from '../server-error'
25
+ import { toast } from 'sonner'
26
+
27
+ afterEach(() => {
28
+ cleanup()
29
+ vi.clearAllMocks()
30
+ })
31
+
32
+ function makeApi(post: ApiClient['post']): ApiClient {
33
+ return { get: vi.fn(), post, put: vi.fn(), delete: vi.fn() } as unknown as ApiClient
34
+ }
35
+
36
+ let lastGrant: ApprovalGrant | null | undefined
37
+ function Probe({ policy }: { policy: string }) {
38
+ const gate = useApprovalGate()
39
+ return (
40
+ <button
41
+ onClick={async () => {
42
+ lastGrant = await gate.requestApproval({ policy, label: 'Venta sin existencias', context: { qty: 3 } })
43
+ }}
44
+ >
45
+ ask
46
+ </button>
47
+ )
48
+ }
49
+
50
+ function mount(post: ApiClient['post'], caps: string[] = [], isAdmin = false) {
51
+ lastGrant = undefined
52
+ return render(
53
+ <ApiProvider client={makeApi(post)}>
54
+ <PermissionsProvider permissions={caps} isAdmin={isAdmin}>
55
+ <ApprovalGateProvider>
56
+ <Probe policy="oversell" />
57
+ </ApprovalGateProvider>
58
+ </PermissionsProvider>
59
+ </ApiProvider>,
60
+ )
61
+ }
62
+
63
+ function fill(reason: string, pin: string) {
64
+ fireEvent.change(screen.getByLabelText('Motivo'), { target: { value: reason } })
65
+ fireEvent.change(screen.getByLabelText('PIN del supervisor'), { target: { value: pin } })
66
+ }
67
+
68
+ describe('ApprovalGate', () => {
69
+ it('a holder of general.approve_<policy> passes without a prompt', async () => {
70
+ const post = vi.fn()
71
+ mount(post, ['general.approve_oversell'])
72
+ await act(async () => fireEvent.click(screen.getByText('ask')))
73
+ expect(lastGrant).toEqual({ id: null, policy: 'oversell', bypassed: true })
74
+ expect(post).not.toHaveBeenCalled()
75
+ expect(screen.queryByLabelText('PIN del supervisor')).toBeNull()
76
+ })
77
+
78
+ it('posts pin-grant with reason + context and resolves the audit id', async () => {
79
+ const post = vi.fn().mockResolvedValue({ data: { success: true, data: { id: 'audit-1' } } })
80
+ mount(post)
81
+ await act(async () => fireEvent.click(screen.getByText('ask')))
82
+ const submit = screen.getByText('Autorizar').closest('button')!
83
+ expect(submit.hasAttribute('disabled')).toBe(true) // reason + PIN required
84
+ fill('cliente esperando', '4321')
85
+ await act(async () => fireEvent.click(submit))
86
+ await waitFor(() => expect(lastGrant).toBeDefined())
87
+ expect(post).toHaveBeenCalledWith(
88
+ '/approvals/pin-grant',
89
+ expect.objectContaining({ policy: 'oversell', pin: '4321', reason: 'cliente esperando', context: { qty: 3 } }),
90
+ )
91
+ expect(lastGrant).toMatchObject({ id: 'audit-1', bypassed: false })
92
+ })
93
+
94
+ it('a wrong PIN keeps the dialog open with an inline message and nothing resolves', async () => {
95
+ const post = vi.fn().mockRejectedValue({ response: { data: { error: { code: 'approval_pin_invalid' } } } })
96
+ mount(post)
97
+ await act(async () => fireEvent.click(screen.getByText('ask')))
98
+ fill('r', '0000')
99
+ await act(async () => fireEvent.click(screen.getByText('Autorizar').closest('button')!))
100
+ expect(await screen.findByRole('alert')).toBeTruthy()
101
+ expect(lastGrant).toBeUndefined()
102
+ })
103
+
104
+ it('cancelling resolves null (fail closed)', async () => {
105
+ mount(vi.fn())
106
+ await act(async () => fireEvent.click(screen.getByText('ask')))
107
+ await act(async () => fireEvent.click(screen.getByText('Cancelar')))
108
+ await waitFor(() => expect(lastGrant).toBeNull())
109
+ })
110
+
111
+ it('a parked approval_required toast offers the PIN and approves through approve-pin', async () => {
112
+ const post = vi.fn().mockResolvedValue({ data: { success: true } })
113
+ mount(post)
114
+ const err = {
115
+ response: {
116
+ data: { success: false, error: { code: 'approval_required' }, meta: { approval_request_id: 'req-9', approval_label: 'Precio bajo el piso', approval_roles: ['gerente'] } },
117
+ },
118
+ }
119
+ expect(approvalRequiredInfo(err)).toMatchObject({ requestId: 'req-9', roles: ['gerente'] })
120
+ toastServerError(err)
121
+ const opts = (toast.info as unknown as ReturnType<typeof vi.fn>).mock.calls[0][1]
122
+ expect(toast.error).not.toHaveBeenCalled()
123
+ await act(async () => opts.action.onClick())
124
+ fill('autorizado', '1234')
125
+ await act(async () => fireEvent.click(screen.getByText('Autorizar').closest('button')!))
126
+ await waitFor(() => expect(post).toHaveBeenCalledWith('/approvals/req-9/approve-pin', { pin: '1234', reason: 'autorizado' }))
127
+ })
128
+
129
+ it('without a gate mounted the parked toast has no PIN action and the event is inert', () => {
130
+ toastServerError({ response: { data: { error: { code: 'approval_required' }, meta: { approval_request_id: 'x' } } } })
131
+ expect((toast.info as unknown as ReturnType<typeof vi.fn>).mock.calls[0][1].action).toBeUndefined()
132
+ window.dispatchEvent(new CustomEvent(APPROVAL_PARKED_EVENT, { detail: { requestId: 'x', roles: [] } }))
133
+ })
134
+ })
@@ -0,0 +1,201 @@
1
+ // @vitest-environment happy-dom
2
+ //
3
+ // requiresAddon: an action gated by a missing optional addon stays visible but
4
+ // locked. A click must NOT reach the dispatcher / federated modal / backend; it
5
+ // opens the "requires addon" dialog whose "Instalar" hands the key to the host
6
+ // handler, or routes to /marketplace/<key> through the SDK router.
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
8
+ import { act, cleanup, fireEvent, render, renderHook, screen } from '@testing-library/react'
9
+
10
+ const I18N_T = (_k: string, opts?: { defaultValue?: string; [k: string]: unknown }) =>
11
+ (opts?.defaultValue ?? _k).replace(/\{\{(\w+)\}\}/g, (_: string, v: string) => String(opts?.[v] ?? ''))
12
+ const USE_TRANSLATION = { t: I18N_T, i18n: { language: 'es' } }
13
+ vi.mock('react-i18next', () => ({
14
+ useTranslation: () => USE_TRANSLATION,
15
+ }))
16
+
17
+ const navigate = vi.fn()
18
+ vi.mock('@tanstack/react-router', () => ({
19
+ useNavigate: () => navigate,
20
+ }))
21
+
22
+ // The dispatcher must never mount for a gated action.
23
+ const dispatcherSpy = vi.fn()
24
+ vi.mock('../action-modal-dispatcher', () => ({
25
+ ActionModalDispatcher: (props: unknown) => {
26
+ dispatcherSpy(props)
27
+ return <div data-testid="dispatcher" />
28
+ },
29
+ }))
30
+
31
+ import { useDynamicRowActions } from '../dynamic-row-actions'
32
+ import { ModelActionToolbar } from '../model-action-toolbar'
33
+ import { RowActionMenuItem } from '../dynamic-columns'
34
+ import { ApiProvider } from '../api-context'
35
+ import { resolveRequiresAddon, setAddonInstallHandler } from '../requires-addon'
36
+ import type { ActionDefinition, TableMetadata } from '../types'
37
+ import { DropdownMenu, DropdownMenuContent } from '@asteby/metacore-ui/primitives'
38
+
39
+ const post = vi.fn(async () => ({ data: { success: true } }))
40
+ const api = {
41
+ get: async () => ({ data: { data: {} } }),
42
+ post,
43
+ put: async () => ({ data: { success: true } }),
44
+ delete: async () => ({ data: { success: true } }),
45
+ } as never
46
+
47
+ const WIRE_REQUIREMENT = {
48
+ key: 'connector_whatsapp',
49
+ name: 'Conector WhatsApp',
50
+ reason: 'Necesitas el conector para vincular un número.',
51
+ }
52
+
53
+ // Exactly as ops serves it: snake_case, plus a federated modal + executable so
54
+ // that, without the gate, the click would open the dispatcher.
55
+ const gatedRowAction = {
56
+ key: 'connect_device',
57
+ name: 'connect_device',
58
+ label: 'Conectar WhatsApp',
59
+ icon: 'QrCode',
60
+ class: '',
61
+ type: 'custom',
62
+ modal: 'link_inbox.connect_device',
63
+ executable: true,
64
+ requires_addon: WIRE_REQUIREMENT,
65
+ } as unknown as ActionDefinition
66
+
67
+ const metadata = { title: 'Devices', actions: [gatedRowAction] } as unknown as TableMetadata
68
+
69
+ function Wrapper({ children }: { children: React.ReactNode }) {
70
+ return <ApiProvider client={api}>{children}</ApiProvider>
71
+ }
72
+
73
+ beforeEach(() => {
74
+ post.mockClear()
75
+ navigate.mockClear()
76
+ dispatcherSpy.mockClear()
77
+ setAddonInstallHandler(null)
78
+ })
79
+ afterEach(cleanup)
80
+
81
+ describe('resolveRequiresAddon', () => {
82
+ it('normalizes the snake_case requires_addon served by the host', () => {
83
+ expect(resolveRequiresAddon({ requires_addon: WIRE_REQUIREMENT })).toEqual(WIRE_REQUIREMENT)
84
+ })
85
+ it('reads camelCase requiresAddon', () => {
86
+ expect(resolveRequiresAddon({ requiresAddon: { key: 'x' } })).toEqual({ key: 'x' })
87
+ })
88
+ it('treats absent / keyless requirements as runnable', () => {
89
+ expect(resolveRequiresAddon({ key: 'a' })).toBeNull()
90
+ expect(resolveRequiresAddon({ requires_addon: { name: 'Sin key' } })).toBeNull()
91
+ expect(resolveRequiresAddon(undefined)).toBeNull()
92
+ })
93
+ })
94
+
95
+ function RowHarness() {
96
+ const { handleInternalAction, dialogs } = useDynamicRowActions({
97
+ model: 'Device',
98
+ metadata,
99
+ onRefresh: () => {},
100
+ })
101
+ return (
102
+ <>
103
+ <button onClick={() => handleInternalAction('connect_device', { id: 'r1' })}>run</button>
104
+ {dialogs}
105
+ </>
106
+ )
107
+ }
108
+
109
+ describe('row actions (table / kanban shared handler)', () => {
110
+ it('does not dispatch nor post; opens the requires-addon dialog', async () => {
111
+ const onAction = vi.fn()
112
+ const { result } = renderHook(
113
+ () => useDynamicRowActions({ model: 'Device', metadata, onAction, onRefresh: () => {} }),
114
+ { wrapper: Wrapper },
115
+ )
116
+ await act(() => result.current.handleInternalAction('connect_device', { id: 'r1' }))
117
+ expect(onAction).not.toHaveBeenCalled()
118
+
119
+ render(<RowHarness />, { wrapper: Wrapper })
120
+ await act(async () => fireEvent.click(screen.getByText('run')))
121
+
122
+ expect(screen.getByText('Esta acción requiere «Conector WhatsApp»')).toBeTruthy()
123
+ expect(screen.getByText(WIRE_REQUIREMENT.reason)).toBeTruthy()
124
+ expect(screen.queryByTestId('dispatcher')).toBeNull()
125
+ expect(dispatcherSpy).not.toHaveBeenCalled()
126
+ expect(post).not.toHaveBeenCalled()
127
+ })
128
+
129
+ it('Instalar invokes the host handler with the addon key', async () => {
130
+ const handler = vi.fn()
131
+ setAddonInstallHandler(handler)
132
+ render(<RowHarness />, { wrapper: Wrapper })
133
+ await act(async () => fireEvent.click(screen.getByText('run')))
134
+ await act(async () => fireEvent.click(screen.getByText('Instalar «Conector WhatsApp»')))
135
+ expect(handler).toHaveBeenCalledWith('connector_whatsapp')
136
+ expect(navigate).not.toHaveBeenCalled()
137
+ })
138
+
139
+ it('without a handler navigates through the router to /marketplace/<key>', async () => {
140
+ render(<RowHarness />, { wrapper: Wrapper })
141
+ await act(async () => fireEvent.click(screen.getByText('run')))
142
+ await act(async () => fireEvent.click(screen.getByText('Instalar «Conector WhatsApp»')))
143
+ expect(navigate).toHaveBeenCalledWith({ to: '/marketplace/connector_whatsapp' })
144
+ })
145
+
146
+ it('menu entry stays visible with a lock and the addon name as tooltip', () => {
147
+ render(
148
+ <DropdownMenu open>
149
+ <DropdownMenuContent>
150
+ <RowActionMenuItem action={gatedRowAction} label="Conectar WhatsApp" onSelect={() => {}} />
151
+ </DropdownMenuContent>
152
+ </DropdownMenu>,
153
+ )
154
+ const item = screen.getByText('Conectar WhatsApp').closest('[data-requires-addon]')
155
+ expect(item?.getAttribute('data-requires-addon')).toBe('connector_whatsapp')
156
+ expect(item?.getAttribute('title')).toBe('Requiere «Conector WhatsApp»')
157
+ })
158
+ })
159
+
160
+ describe('ModelActionToolbar', () => {
161
+ const toolbarAction = {
162
+ ...gatedRowAction,
163
+ placement: 'table',
164
+ requires_addon: undefined,
165
+ requiresAddon: { key: 'connector_whatsapp', name: 'Conector WhatsApp' },
166
+ } as unknown as ActionDefinition
167
+
168
+ it('renders the action locked and opens the dialog instead of the dispatcher', async () => {
169
+ const intent = vi.fn()
170
+ render(
171
+ <Wrapper>
172
+ <ModelActionToolbar model="Device" actions={[toolbarAction]} onActionIntent={intent} />
173
+ </Wrapper>,
174
+ )
175
+ const button = screen.getByText('Conectar WhatsApp').closest('button')!
176
+ expect(button.getAttribute('title')).toBe('Requiere «Conector WhatsApp»')
177
+ expect(button.querySelector('[data-requires-addon="connector_whatsapp"]')).toBeTruthy()
178
+
179
+ await act(async () => fireEvent.click(button))
180
+ expect(screen.getByText('Esta acción requiere «Conector WhatsApp»')).toBeTruthy()
181
+ // No reason from the host → generic copy.
182
+ expect(screen.getByText('Instala «Conector WhatsApp» para habilitar esta acción.')).toBeTruthy()
183
+ expect(dispatcherSpy).not.toHaveBeenCalled()
184
+ expect(intent).not.toHaveBeenCalled()
185
+ expect(post).not.toHaveBeenCalled()
186
+
187
+ await act(async () => fireEvent.click(screen.getByText('Instalar «Conector WhatsApp»')))
188
+ expect(navigate).toHaveBeenCalledWith({ to: '/marketplace/connector_whatsapp' })
189
+ })
190
+
191
+ it('an ungated action still opens the dispatcher', async () => {
192
+ const plain = { ...toolbarAction, key: 'other', label: 'Otra', requiresAddon: undefined } as ActionDefinition
193
+ render(
194
+ <Wrapper>
195
+ <ModelActionToolbar model="Device" actions={[plain]} />
196
+ </Wrapper>,
197
+ )
198
+ await act(async () => fireEvent.click(screen.getByText('Otra')))
199
+ expect(dispatcherSpy).toHaveBeenCalled()
200
+ })
201
+ })
@@ -0,0 +1,39 @@
1
+ // approval-events — dependency-free glue between server-error.ts (which sees a
2
+ // parked `approval_required` write) and <ApprovalGateProvider> (which owns the
3
+ // PIN dialog). Kept apart so the error toaster never imports React/UI code.
4
+
5
+ /** Window event toastServerError fires for a parked `approval_required` write. */
6
+ export const APPROVAL_PARKED_EVENT = 'metacore:approval-parked'
7
+ /** Fired after a parked request was approved (and replayed) with a PIN. */
8
+ export const APPROVAL_DECIDED_EVENT = 'metacore:approval-decided'
9
+
10
+ let gateMounted = 0
11
+ /** @internal provider bookkeeping. */
12
+ export function gateMountedDelta(d: number): void {
13
+ gateMounted += d
14
+ }
15
+
16
+ /** True while an <ApprovalGateProvider> is mounted (toastServerError offers the PIN action only then). */
17
+ export function approvalGateAvailable(): boolean {
18
+ return gateMounted > 0
19
+ }
20
+
21
+ export interface ApprovalRequiredInfo {
22
+ requestId: string
23
+ label?: string
24
+ roles: string[]
25
+ }
26
+
27
+ /** Extracts the parked-request info from an axios error / response body, or null. */
28
+ export function approvalRequiredInfo(err: unknown): ApprovalRequiredInfo | null {
29
+ const data = ((err as { response?: { data?: unknown } })?.response?.data ?? err) as
30
+ | { error?: { code?: string }; meta?: { approval_request_id?: string; approval_label?: string; approval_roles?: string[] } }
31
+ | undefined
32
+ if (data?.error?.code !== 'approval_required') return null
33
+ return {
34
+ requestId: data.meta?.approval_request_id ?? '',
35
+ label: data.meta?.approval_label,
36
+ roles: data.meta?.approval_roles ?? [],
37
+ }
38
+ }
39
+
@@ -0,0 +1,180 @@
1
+ // ApprovalGate — one place for "this needs a supervisor" in hosts that mount an
2
+ // ApiProvider. It answers two situations with the same PIN dialog:
3
+ //
4
+ // 1. INLINE policy (POS oversell, discount over the cap, refund…): the client
5
+ // calls `requestApproval({policy, …})`. A user who already holds the policy's
6
+ // `general.approve_<policy>` capability passes straight through (`bypassed`);
7
+ // everyone else gets the dialog, which posts `/approvals/pin-grant`.
8
+ // 2. PARKED request: a write answered 422 `approval_required`. toastServerError
9
+ // shows "Enviado a aprobación" with an "Aprobar con PIN" action that opens the
10
+ // dialog against `/approvals/:id/approve-pin` (kernel approvals_pin.go).
11
+ //
12
+ // Federated addons with their own HTTP client use <ApprovalPinDialog> directly
13
+ // (approval-pin-dialog.tsx) and post to the same endpoints.
14
+ import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'
15
+ import { useTranslation } from 'react-i18next'
16
+ import { toast } from 'sonner'
17
+ import { useApi } from './api-context'
18
+ import { useCan } from './permissions-context'
19
+ import { ApprovalPinDialog, type ApprovalPinSubmit } from './approval-pin-dialog'
20
+ import {
21
+ APPROVAL_DECIDED_EVENT,
22
+ APPROVAL_PARKED_EVENT,
23
+ gateMountedDelta,
24
+ type ApprovalRequiredInfo,
25
+ } from './approval-events'
26
+
27
+ export {
28
+ APPROVAL_DECIDED_EVENT,
29
+ APPROVAL_PARKED_EVENT,
30
+ approvalGateAvailable,
31
+ approvalRequiredInfo,
32
+ type ApprovalRequiredInfo,
33
+ } from './approval-events'
34
+
35
+ /** Capability that authorizes `policy` (and lets its holder skip the prompt). */
36
+ export function approvalCapability(policy: string): string {
37
+ return `general.approve_${policy}`
38
+ }
39
+
40
+ export interface ApprovalGrant {
41
+ /** Audit row id (ApprovalRequest.kind=pin); null when the caller bypassed. */
42
+ id: string | null
43
+ policy: string
44
+ bypassed: boolean
45
+ reason?: string
46
+ }
47
+
48
+ export interface RequestApprovalOptions {
49
+ /** Policy key: oversell | discount | price_below_min | refund | cancel_cfdi | inventory_adjust | <addon-declared>. */
50
+ policy: string
51
+ label: string
52
+ description?: React.ReactNode
53
+ /** Free-form audit data stored with the grant (product, qty, before → after…). */
54
+ context?: Record<string, unknown>
55
+ model?: string
56
+ recordId?: string
57
+ addonKey?: string
58
+ }
59
+
60
+ export interface ApprovalGateValue {
61
+ /** Resolves the grant, or null when the operator cancelled. */
62
+ requestApproval: (opts: RequestApprovalOptions) => Promise<ApprovalGrant | null>
63
+ /** True when the current user may do `policy` without asking anyone. */
64
+ canSelfApprove: (policy: string) => boolean
65
+ }
66
+
67
+ const ApprovalGateContext = createContext<ApprovalGateValue | null>(null)
68
+
69
+ type Pending =
70
+ | { kind: 'inline'; opts: RequestApprovalOptions; resolve: (g: ApprovalGrant | null) => void }
71
+ | { kind: 'parked'; info: ApprovalRequiredInfo }
72
+
73
+ export function ApprovalGateProvider({ children }: { children: React.ReactNode }) {
74
+ const { t } = useTranslation()
75
+ const api = useApi()
76
+ const can = useCan()
77
+ const [pending, setPending] = useState<Pending | null>(null)
78
+ const pendingRef = useRef<Pending | null>(null)
79
+ pendingRef.current = pending
80
+
81
+ useEffect(() => {
82
+ gateMountedDelta(1)
83
+ const onParked = (e: Event) => {
84
+ const info = (e as CustomEvent<ApprovalRequiredInfo>).detail
85
+ if (info?.requestId) setPending({ kind: 'parked', info })
86
+ }
87
+ window.addEventListener(APPROVAL_PARKED_EVENT, onParked)
88
+ return () => {
89
+ gateMountedDelta(-1)
90
+ window.removeEventListener(APPROVAL_PARKED_EVENT, onParked)
91
+ }
92
+ }, [])
93
+
94
+ const canSelfApprove = useCallback((policy: string) => can(approvalCapability(policy)), [can])
95
+
96
+ const requestApproval = useCallback(
97
+ (opts: RequestApprovalOptions) => {
98
+ if (can(approvalCapability(opts.policy))) {
99
+ return Promise.resolve<ApprovalGrant>({ id: null, policy: opts.policy, bypassed: true })
100
+ }
101
+ return new Promise<ApprovalGrant | null>((resolve) => {
102
+ pendingRef.current?.kind === 'inline' && pendingRef.current.resolve(null)
103
+ setPending({ kind: 'inline', opts, resolve })
104
+ })
105
+ },
106
+ [can],
107
+ )
108
+
109
+ const close = () => {
110
+ const p = pendingRef.current
111
+ if (p?.kind === 'inline') p.resolve(null)
112
+ setPending(null)
113
+ }
114
+
115
+ const submit = async ({ pin, reason }: ApprovalPinSubmit) => {
116
+ const p = pendingRef.current
117
+ if (!p) return
118
+ if (p.kind === 'inline') {
119
+ const res = await api.post('/approvals/pin-grant', {
120
+ policy: p.opts.policy,
121
+ label: p.opts.label,
122
+ pin,
123
+ reason,
124
+ context: p.opts.context,
125
+ model: p.opts.model,
126
+ record_id: p.opts.recordId,
127
+ addon_key: p.opts.addonKey,
128
+ })
129
+ const row = res.data?.data
130
+ p.resolve({ id: row?.id ?? null, policy: p.opts.policy, bypassed: false, reason })
131
+ } else {
132
+ await api.post(`/approvals/${p.info.requestId}/approve-pin`, { pin, reason })
133
+ toast.success(t('approvals.approved_applied', { defaultValue: 'Aprobado y aplicado' }))
134
+ window.dispatchEvent(new CustomEvent(APPROVAL_DECIDED_EVENT, { detail: p.info }))
135
+ }
136
+ setPending(null)
137
+ }
138
+
139
+ const value = useMemo<ApprovalGateValue>(() => ({ requestApproval, canSelfApprove }), [requestApproval, canSelfApprove])
140
+
141
+ const title =
142
+ pending?.kind === 'inline'
143
+ ? pending.opts.label
144
+ : pending?.kind === 'parked'
145
+ ? pending.info.label || t('approvals.parked_title', { defaultValue: 'Requiere aprobación' })
146
+ : ''
147
+
148
+ return (
149
+ <ApprovalGateContext.Provider value={value}>
150
+ {children}
151
+ <ApprovalPinDialog
152
+ open={pending !== null}
153
+ title={title}
154
+ description={pending?.kind === 'inline' ? pending.opts.description : undefined}
155
+ onSubmit={submit}
156
+ onCancel={close}
157
+ />
158
+ </ApprovalGateContext.Provider>
159
+ )
160
+ }
161
+
162
+ /**
163
+ * Access the gate. Without a provider the gate fails CLOSED for inline requests
164
+ * (resolves null) — never silently authorizes — but honours the capability
165
+ * bypass, and `canSelfApprove` follows `useCan()` (always-true with no
166
+ * <PermissionsProvider>, i.e. legacy hosts keep today's behaviour).
167
+ */
168
+ export function useApprovalGate(): ApprovalGateValue {
169
+ const ctx = useContext(ApprovalGateContext)
170
+ const can = useCan()
171
+ return useMemo<ApprovalGateValue>(
172
+ () =>
173
+ ctx ?? {
174
+ canSelfApprove: (policy) => can(approvalCapability(policy)),
175
+ requestApproval: async (opts) =>
176
+ can(approvalCapability(opts.policy)) ? { id: null, policy: opts.policy, bypassed: true } : null,
177
+ },
178
+ [ctx, can],
179
+ )
180
+ }