@asteby/metacore-runtime-react 36.1.0 → 37.0.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.
- package/CHANGELOG.md +19 -0
- package/README.md +33 -0
- package/dist/dynamic-columns-helpers.d.ts +9 -0
- package/dist/dynamic-columns-helpers.d.ts.map +1 -1
- package/dist/dynamic-columns-helpers.js +15 -0
- package/dist/dynamic-columns.d.ts +15 -3
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +26 -6
- package/dist/dynamic-kanban.d.ts +7 -1
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +12 -2
- package/dist/dynamic-table.d.ts +19 -1
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +29 -7
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/realtime-context.d.ts +82 -0
- package/dist/realtime-context.d.ts.map +1 -0
- package/dist/realtime-context.js +182 -0
- package/package.json +3 -3
- package/src/__tests__/metadata-label-i18n.test.ts +19 -0
- package/src/__tests__/realtime-context.test.tsx +195 -0
- package/src/__tests__/resolve-row-actions.test.ts +14 -0
- package/src/dynamic-columns-helpers.ts +22 -0
- package/src/dynamic-columns.tsx +26 -6
- package/src/dynamic-kanban.tsx +18 -1
- package/src/dynamic-table.tsx +48 -6
- package/src/index.ts +17 -1
- package/src/realtime-context.tsx +248 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 37.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 53c3b8a: Fix `isActionConditionMet` (row/table action `condition` gate): `truthy`/`falsy` (and the `present`/`set`/`blank`/`empty` aliases, matching the host's document print gate) were unrecognized operators falling through to the permissive `default: return true` — a `condition: {field, operator: "truthy"}` silently gated nothing, rendering the action on every row regardless of the field's value. Confirmed live: an addon's `condition: {field: "amount_due", operator: "truthy"}` row action rendered on every row, including ones with a zero balance.
|
|
8
|
+
- 0d06571: Translate manifest-contributed dynamic table column and row-action labels at render time, with a humanized fallback for missing addon locale keys. Export `translateMetadataLabel` so host-owned dynamic surfaces can apply the same contract to titles and forms.
|
|
9
|
+
|
|
10
|
+
## 37.0.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- a0616e1: `DynamicTable` acepta la prop opcional `allowedActionKeys?: string[]`: un allowlist de acciones de fila (por `key` del manifest v3) a renderizar para ESA instancia de la tabla, en vez de todas las acciones que el modelo declara. Permite que dos vistas del mismo modelo (una tabla genérica y una pantalla de propósito específico, ej. una cola de aprobación de crédito) muestren distintas acciones sin tocar el manifest ni duplicar el modelo. `undefined` conserva el comportamiento actual (todas las acciones).
|
|
15
|
+
- d1ffa4f: Realtime en React: `RealtimeProvider`, `useRealtime`, `useRealtimeInvalidate` (invalida las queries del QueryClient del host cuya key menciona el modelo/tabla), `useRealtimeStatus`, `useRealtimeTick` y `queryKeyMatchesEvent`. `DynamicTable` y `DynamicKanban` aceptan la prop opt-in `realtime` (apagada por default; `<RealtimeProvider defaultRealtime>` cambia el default) para refetch en vivo ante `DATA_EVENT` del modelo.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [d1ffa4f]
|
|
20
|
+
- @asteby/metacore-sdk@3.7.0
|
|
21
|
+
|
|
3
22
|
## 36.1.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -33,6 +33,39 @@ Peers: `react`, `react-dom`, `react-i18next`, `i18next`, `@tanstack/react-router
|
|
|
33
33
|
| `<LicenseGate state={…} onActivate={…}>` | El blindaje del negocio: envuelve la app; bloquea con un modal full-screen no descartable cuando la licencia de instancia falta/venció, degrada con banner en `grace`/`stale`. Branding-aware. |
|
|
34
34
|
| `<LicenseExpiryBanner state={…} />` / `<LicenseStatusBadge status={…} />` | Piezas sueltas del gate para Ajustes u otros lugares. |
|
|
35
35
|
| `isLicenseOperable` / `isLicenseBlocking` / `isPresetEntitled` / `isTrialExpired` | Helpers puros sobre `LicenseState`, espejo de `State.Operable()/Blocking()` del backend. |
|
|
36
|
+
| `<RealtimeProvider client={…} />` / `useRealtime()` / `useRealtimeInvalidate()` / `useRealtimeStatus()` / `useRealtimeTick()` | Reacción en vivo a `DATA_EVENT` del host (ver [Realtime](#realtime)). |
|
|
37
|
+
|
|
38
|
+
## Realtime
|
|
39
|
+
|
|
40
|
+
El host expone un `RealtimeAPI` (`@asteby/metacore-sdk`) — en ops viaja como
|
|
41
|
+
`host.realtime` a las rutas inmersivas y como `api.realtime` a `register(api)`.
|
|
42
|
+
Los frames son org-scoped y **sin valores de fila** (identidad + qué llaves
|
|
43
|
+
cambiaron); la reacción típica es "refetch lo que muestro".
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
// Host: montar una vez, dentro del QueryClientProvider y del provider de WS.
|
|
47
|
+
<RealtimeProvider client={realtimeClient}>…</RealtimeProvider>
|
|
48
|
+
|
|
49
|
+
// Addon federado: pasar el cliente explícito — el contexto React NO cruza la
|
|
50
|
+
// frontera de module federation, el objeto plano sí.
|
|
51
|
+
useRealtime({ models: ['SalesOrder'], client: host.realtime }, (e) => {
|
|
52
|
+
if (e.action === 'resync' || e.id === currentId) refetch()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Invalidar react-query (usa SIEMPRE el QueryClient del host — nunca crees otro):
|
|
56
|
+
useRealtimeInvalidate({ models: ['SalesOrder', 'sales_order_items'], client: host.realtime })
|
|
57
|
+
|
|
58
|
+
// Tablas y kanbans: opt-in por prop (apagado por default).
|
|
59
|
+
<DynamicTable model="SalesOrder" realtime />
|
|
60
|
+
<DynamicKanban model="WorkOrder" realtime />
|
|
61
|
+
// …o global para todo lo que cuelgue del provider:
|
|
62
|
+
<RealtimeProvider client={realtimeClient} defaultRealtime>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`useRealtimeInvalidate` invalida toda query cuya key (string, array anidado u
|
|
66
|
+
objeto) mencione el modelo, la tabla o `addon.Model` — también como segmento de
|
|
67
|
+
una ruta (`/data/sales_orders?…`). Se puede reemplazar el matcher con `match`.
|
|
68
|
+
Todos los hooks son no-op cuando no hay cliente (host sin realtime).
|
|
36
69
|
|
|
37
70
|
## Blindaje de licencia (`LicenseGate`)
|
|
38
71
|
|
|
@@ -18,4 +18,13 @@
|
|
|
18
18
|
* non-strings. This keeps it safe to call on arbitrary cell values.
|
|
19
19
|
*/
|
|
20
20
|
export declare function humanizeToken(value: unknown): string;
|
|
21
|
+
export type MetadataTranslator = (key: string, options?: {
|
|
22
|
+
defaultValue?: string;
|
|
23
|
+
}) => string;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve addon-contributed metadata at render time. Known i18n keys use the
|
|
26
|
+
* host locale; missing keys degrade to a readable label instead of leaking a
|
|
27
|
+
* machine path such as `models.orders.table.columns.payment_status`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function translateMetadataLabel(value: string | undefined, translate?: MetadataTranslator): string;
|
|
21
30
|
//# sourceMappingURL=dynamic-columns-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns-helpers.d.ts","sourceRoot":"","sources":["../src/dynamic-columns-helpers.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD"}
|
|
1
|
+
{"version":3,"file":"dynamic-columns-helpers.d.ts","sourceRoot":"","sources":["../src/dynamic-columns-helpers.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAiBpD;AAED,MAAM,MAAM,kBAAkB,GAAG,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,KAClC,MAAM,CAAA;AAEX;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,SAAS,CAAC,EAAE,kBAAkB,GAC/B,MAAM,CAOR"}
|
|
@@ -57,3 +57,18 @@ export function humanizeToken(value) {
|
|
|
57
57
|
})
|
|
58
58
|
.join(' ');
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve addon-contributed metadata at render time. Known i18n keys use the
|
|
62
|
+
* host locale; missing keys degrade to a readable label instead of leaking a
|
|
63
|
+
* machine path such as `models.orders.table.columns.payment_status`.
|
|
64
|
+
*/
|
|
65
|
+
export function translateMetadataLabel(value, translate) {
|
|
66
|
+
if (!value)
|
|
67
|
+
return '';
|
|
68
|
+
const token = value.includes('.') ? value.split('.').at(-1) ?? value : value;
|
|
69
|
+
const fallback = humanizeToken(token);
|
|
70
|
+
if (!translate)
|
|
71
|
+
return fallback;
|
|
72
|
+
const translated = translate(value, { defaultValue: fallback });
|
|
73
|
+
return translated && translated !== value ? translated : fallback;
|
|
74
|
+
}
|
|
@@ -56,9 +56,21 @@ export declare const isActionAllowedForRowState: (action: any, row: any) => bool
|
|
|
56
56
|
* Declarative `condition` gate for a per-row action: shows the action only when
|
|
57
57
|
* the row's `field` satisfies the operator. Supports both the SDK dialect
|
|
58
58
|
* (`eq` | `neq` | `in` | `not_in`) and the common host dialect
|
|
59
|
-
* (`equals` | `notEquals` | `not_in`)
|
|
60
|
-
*
|
|
61
|
-
*
|
|
59
|
+
* (`equals` | `notEquals` | `not_in`), plus the truthy/falsy family (same
|
|
60
|
+
* operator set as the host's document print gate — services/document_gate.go
|
|
61
|
+
* — kept in sync so a manifest author doesn't have to know which gate a given
|
|
62
|
+
* contribution goes through). Nested paths (`user.verified`) are resolved via
|
|
63
|
+
* `getNestedValue`. No condition → always shown.
|
|
64
|
+
*
|
|
65
|
+
* `default: return true` for a genuinely unknown operator is deliberate — an
|
|
66
|
+
* addon shipped against a newer SDK than the host runs should degrade to
|
|
67
|
+
* "always show" (worst case: an extra menu item), never to "always hide"
|
|
68
|
+
* (worst case: a feature silently vanishes). That same permissiveness is why
|
|
69
|
+
* `truthy`/`falsy` going unrecognized here was a real, silent bug rather
|
|
70
|
+
* than a build error: confirmed live — a `condition: {field: "amount_due",
|
|
71
|
+
* operator: "truthy"}` row action rendered on every row regardless of
|
|
72
|
+
* amount_due, because the switch fell through to the default and nothing
|
|
73
|
+
* ever signaled it wasn't actually gating anything.
|
|
62
74
|
*/
|
|
63
75
|
export declare const isActionConditionMet: (action: any, row: any) => boolean;
|
|
64
76
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AA0C9C,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAE9D,OAAO,KAAK,EAER,iBAAiB,EACpB,MAAM,wBAAwB,CAAA;AAE/B,qEAAqE;AACrE,MAAM,WAAW,qBAAqB;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AA0BD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,gBAAgB,EAAE,cAAc,MAAM,KAAG,MACzB,CAAA;AAQrD;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,gBAAgB,KAAG,MAAM,GAAG,SAG5D,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC7B,KAAK,gBAAgB,EACrB,OAAO,OAAO,EACd,WAAW,MAAM,EACjB,SAAS,MAAM,KAChB,MAyBF,CAAA;AAsDD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,0BAA0B,GAAI,QAAQ,GAAG,EAAE,KAAK,GAAG,KAAG,OAMlE,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"dynamic-columns.d.ts","sourceRoot":"","sources":["../src/dynamic-columns.tsx"],"names":[],"mappings":"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"}
|
package/dist/dynamic-columns.js
CHANGED
|
@@ -21,7 +21,7 @@ import { Avatar, AvatarFallback, AvatarImage, Badge, Button, Checkbox, DropdownM
|
|
|
21
21
|
import { DataTableColumnHeader, FilterableColumnHeader, } from '@asteby/metacore-ui/data-table';
|
|
22
22
|
import { generateBadgeStyles, getInitials, relationChipStyles, } from '@asteby/metacore-ui/lib';
|
|
23
23
|
import { Progress } from './dialogs/_primitives';
|
|
24
|
-
import { humanizeToken } from './dynamic-columns-helpers';
|
|
24
|
+
import { humanizeToken, translateMetadataLabel } from './dynamic-columns-helpers';
|
|
25
25
|
import { objectLabel } from './dynamic-relation-helpers';
|
|
26
26
|
import { OptionBadge, RelationThumbnail, ImageStack, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
27
27
|
import { MediaValue } from './rich-url';
|
|
@@ -147,9 +147,21 @@ export const isActionAllowedForRowState = (action, row) => {
|
|
|
147
147
|
* Declarative `condition` gate for a per-row action: shows the action only when
|
|
148
148
|
* the row's `field` satisfies the operator. Supports both the SDK dialect
|
|
149
149
|
* (`eq` | `neq` | `in` | `not_in`) and the common host dialect
|
|
150
|
-
* (`equals` | `notEquals` | `not_in`)
|
|
151
|
-
*
|
|
152
|
-
*
|
|
150
|
+
* (`equals` | `notEquals` | `not_in`), plus the truthy/falsy family (same
|
|
151
|
+
* operator set as the host's document print gate — services/document_gate.go
|
|
152
|
+
* — kept in sync so a manifest author doesn't have to know which gate a given
|
|
153
|
+
* contribution goes through). Nested paths (`user.verified`) are resolved via
|
|
154
|
+
* `getNestedValue`. No condition → always shown.
|
|
155
|
+
*
|
|
156
|
+
* `default: return true` for a genuinely unknown operator is deliberate — an
|
|
157
|
+
* addon shipped against a newer SDK than the host runs should degrade to
|
|
158
|
+
* "always show" (worst case: an extra menu item), never to "always hide"
|
|
159
|
+
* (worst case: a feature silently vanishes). That same permissiveness is why
|
|
160
|
+
* `truthy`/`falsy` going unrecognized here was a real, silent bug rather
|
|
161
|
+
* than a build error: confirmed live — a `condition: {field: "amount_due",
|
|
162
|
+
* operator: "truthy"}` row action rendered on every row regardless of
|
|
163
|
+
* amount_due, because the switch fell through to the default and nothing
|
|
164
|
+
* ever signaled it wasn't actually gating anything.
|
|
153
165
|
*/
|
|
154
166
|
export const isActionConditionMet = (action, row) => {
|
|
155
167
|
if (!action?.condition)
|
|
@@ -183,6 +195,14 @@ export const isActionConditionMet = (action, row) => {
|
|
|
183
195
|
case 'not_in':
|
|
184
196
|
case 'notin':
|
|
185
197
|
return !values.includes(rowValue);
|
|
198
|
+
case 'truthy':
|
|
199
|
+
case 'present':
|
|
200
|
+
case 'set':
|
|
201
|
+
return rowValue !== '' && rowValue !== 'false' && rowValue !== '0';
|
|
202
|
+
case 'falsy':
|
|
203
|
+
case 'blank':
|
|
204
|
+
case 'empty':
|
|
205
|
+
return rowValue === '' || rowValue === 'false' || rowValue === '0';
|
|
186
206
|
default:
|
|
187
207
|
return true;
|
|
188
208
|
}
|
|
@@ -580,7 +600,7 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
580
600
|
// `visibility` scope (skips `'modal'` and `'list'`).
|
|
581
601
|
if (!isColumnVisibleInTable(col))
|
|
582
602
|
return;
|
|
583
|
-
const translatedLabel = col.label;
|
|
603
|
+
const translatedLabel = translateMetadataLabel(col.label, t);
|
|
584
604
|
const filterConfig = filterConfigs?.get(col.key);
|
|
585
605
|
const columnMeta = {
|
|
586
606
|
label: translatedLabel,
|
|
@@ -971,7 +991,7 @@ export function makeDefaultGetDynamicColumns(helpers = {}) {
|
|
|
971
991
|
meta: {},
|
|
972
992
|
cell: ({ row }) => (_jsx("div", { className: "flex items-center justify-end", children: _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", className: "h-8 w-8 p-0", children: [_jsx("span", { className: "sr-only", children: "Abrir men\u00FA" }), _jsx(MoreHorizontal, { className: "h-4 w-4" })] }) }), _jsx(DropdownMenuContent, { align: "end", children: resolvedActions
|
|
973
993
|
.filter((action) => isRowActionVisible(action, row.original))
|
|
974
|
-
.map((action) => (_jsxs(DropdownMenuItem, { onClick: () => onAction && onAction(action.key, row.original), children: [_jsx(DynamicIcon, { name: action.icon, className: "mr-2 h-4 w-4" }), action.label] }, action.key))) })] }) })),
|
|
994
|
+
.map((action) => (_jsxs(DropdownMenuItem, { onClick: () => onAction && onAction(action.key, row.original), children: [_jsx(DynamicIcon, { name: action.icon, className: "mr-2 h-4 w-4" }), translateMetadataLabel(action.label, t)] }, action.key))) })] }) })),
|
|
975
995
|
});
|
|
976
996
|
}
|
|
977
997
|
return columns;
|
package/dist/dynamic-kanban.d.ts
CHANGED
|
@@ -106,6 +106,12 @@ export interface DynamicKanbanProps {
|
|
|
106
106
|
endpoint?: string;
|
|
107
107
|
/** Bump to force a metadata + records refetch (same contract as DynamicTable). */
|
|
108
108
|
refreshTrigger?: any;
|
|
109
|
+
/**
|
|
110
|
+
* Refetch the board when the host's realtime client reports a data event
|
|
111
|
+
* for this model (same contract as DynamicTable's `realtime`). Off by
|
|
112
|
+
* default; `<RealtimeProvider defaultRealtime>` flips the default.
|
|
113
|
+
*/
|
|
114
|
+
realtime?: boolean;
|
|
109
115
|
/** Called when a card is clicked (outside its action menu). */
|
|
110
116
|
onCardClick?: (row: any) => void;
|
|
111
117
|
/**
|
|
@@ -136,5 +142,5 @@ export interface DynamicKanbanProps {
|
|
|
136
142
|
*/
|
|
137
143
|
defaultFilters?: Record<string, any>;
|
|
138
144
|
}
|
|
139
|
-
export declare function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, onAction, pageSize, lanePageSize, timeZone, currency, defaultFilters, }: DynamicKanbanProps): React.JSX.Element;
|
|
145
|
+
export declare function DynamicKanban({ model, endpoint, refreshTrigger, realtime: realtimeProp, onCardClick, onAction, pageSize, lanePageSize, timeZone, currency, defaultFilters, }: DynamicKanbanProps): React.JSX.Element;
|
|
140
146
|
//# sourceMappingURL=dynamic-kanban.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"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"}
|
package/dist/dynamic-kanban.js
CHANGED
|
@@ -12,6 +12,7 @@ import { Badge, Button, Card, CardContent, DropdownMenu, DropdownMenuContent, Dr
|
|
|
12
12
|
import { ColumnFilterControl, FilterValueCombobox } from '@asteby/metacore-ui/data-table';
|
|
13
13
|
import { generateBadgeStyles, optionColor } from '@asteby/metacore-ui/lib';
|
|
14
14
|
import { useApi } from './api-context';
|
|
15
|
+
import { useRealtimeDefault, useRealtimeTick } from './realtime-context';
|
|
15
16
|
import { useStageAutomations, StageAutomationsButton, } from './stage-automations';
|
|
16
17
|
import { useCustomStages, splitCustomStages, mergeLaneStages, resolveSmartLanes, cardMatchesStageFilters, smartLaneParams, AddStageColumn, CustomStageDialog, CustomStageDeleteDialog, StageConfigDialog, SmartLane, } from './custom-stages';
|
|
17
18
|
import { useStageOverrides } from './stage-overrides';
|
|
@@ -261,10 +262,17 @@ function useIsDarkTheme() {
|
|
|
261
262
|
}, []);
|
|
262
263
|
return isDark;
|
|
263
264
|
}
|
|
264
|
-
export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, onAction, pageSize = 50, lanePageSize = 25, timeZone, currency, defaultFilters, }) {
|
|
265
|
+
export function DynamicKanban({ model, endpoint, refreshTrigger, realtime: realtimeProp, onCardClick, onAction, pageSize = 50, lanePageSize = 25, timeZone, currency, defaultFilters, }) {
|
|
265
266
|
const { t, i18n } = useTranslation();
|
|
266
267
|
const api = useApi();
|
|
267
268
|
const isDark = useIsDarkTheme();
|
|
269
|
+
// Realtime refetch (opt-in) — debounced counter bumped by DATA_EVENTs for
|
|
270
|
+
// this model; folded into the board refetch effect next to refreshTrigger.
|
|
271
|
+
const realtimeDefault = useRealtimeDefault();
|
|
272
|
+
const realtimeTick = useRealtimeTick({
|
|
273
|
+
models: [model],
|
|
274
|
+
enabled: realtimeProp ?? realtimeDefault,
|
|
275
|
+
});
|
|
268
276
|
// Stage automations (Bitrix-style per-lane rules). Degrades to no-op when
|
|
269
277
|
// the host has no `/stage-automations` endpoint — the ⚡ affordance hides.
|
|
270
278
|
const automations = useStageAutomations(model);
|
|
@@ -518,7 +526,9 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
518
526
|
void fetchData();
|
|
519
527
|
}, 200);
|
|
520
528
|
return () => clearTimeout(handle);
|
|
521
|
-
|
|
529
|
+
// realtimeTick: data events for this model (see the `realtime` prop).
|
|
530
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
531
|
+
}, [fetchData, metadata, refreshTrigger, realtimeTick]);
|
|
522
532
|
// Filterable fields for the toolbar, in metadata order (explicit filters
|
|
523
533
|
// first, then filterable columns), each labeled from its metadata source.
|
|
524
534
|
const filterFields = useMemo(() => {
|
package/dist/dynamic-table.d.ts
CHANGED
|
@@ -20,6 +20,17 @@ export interface DynamicTableProps {
|
|
|
20
20
|
/** Hide the export action on this view. See `hideImport`. */
|
|
21
21
|
hideExport?: boolean;
|
|
22
22
|
hiddenColumns?: string[];
|
|
23
|
+
/**
|
|
24
|
+
* Row-action ALLOWLIST for this table instance, by action key (manifest
|
|
25
|
+
* v3 NavItem.actions, carried through the host's nav item for this route).
|
|
26
|
+
* When set, only these row actions render — even though the model may
|
|
27
|
+
* declare more. Lets two views of the SAME model differ: a generic list
|
|
28
|
+
* keeps every action, while a purpose-built screen (e.g. a credit-approval
|
|
29
|
+
* queue) shows only authorize_credit/reject_credit instead of every action
|
|
30
|
+
* SalesOrder declares (Generar factura, Cancelar, etc. included).
|
|
31
|
+
* Undefined → every row action the model declares (unchanged default).
|
|
32
|
+
*/
|
|
33
|
+
allowedActionKeys?: string[];
|
|
23
34
|
onAction?: (action: string, row: any) => void;
|
|
24
35
|
/**
|
|
25
36
|
* Called when the user clicks anywhere on a data row (not on a checkbox,
|
|
@@ -29,6 +40,13 @@ export interface DynamicTableProps {
|
|
|
29
40
|
*/
|
|
30
41
|
onRowClick?: (row: any) => void;
|
|
31
42
|
refreshTrigger?: any;
|
|
43
|
+
/**
|
|
44
|
+
* Refetch when the host's realtime client reports a data event for this
|
|
45
|
+
* model (created/updated/deleted by anyone in the org, or a `resync`).
|
|
46
|
+
* Off by default; `<RealtimeProvider defaultRealtime>` turns it on for
|
|
47
|
+
* every table, and an explicit prop always wins. No-op without a client.
|
|
48
|
+
*/
|
|
49
|
+
realtime?: boolean;
|
|
32
50
|
defaultFilters?: Record<string, any>;
|
|
33
51
|
extraColumns?: ColumnDef<any>[];
|
|
34
52
|
/**
|
|
@@ -73,5 +91,5 @@ export interface DynamicTableProps {
|
|
|
73
91
|
*/
|
|
74
92
|
infiniteScroll?: boolean;
|
|
75
93
|
}
|
|
76
|
-
export declare function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync, hideImport, hideExport, hiddenColumns, onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns, getDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp, }: DynamicTableProps): import("react").JSX.Element;
|
|
94
|
+
export declare function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync, hideImport, hideExport, hiddenColumns, allowedActionKeys, onAction, onRowClick, refreshTrigger, realtime: realtimeProp, defaultFilters, extraColumns, getDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp, }: DynamicTableProps): import("react").JSX.Element;
|
|
77
95
|
//# sourceMappingURL=dynamic-table.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAiC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AA4FnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,QAAQ,EAAE,YAAY,EACtB,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BAuwCnB"}
|
package/dist/dynamic-table.js
CHANGED
|
@@ -23,6 +23,7 @@ import { toast } from 'sonner';
|
|
|
23
23
|
import { Progress } from './dialogs/_primitives';
|
|
24
24
|
import { useMetadataCache } from './metadata-cache';
|
|
25
25
|
import { useApi, useCurrentBranch } from './api-context';
|
|
26
|
+
import { useRealtimeDefault, useRealtimeTick } from './realtime-context';
|
|
26
27
|
import { defaultGetDynamicColumns, DATE_CELL_TYPES, aggregateOf, formatAggregateTotal } from './dynamic-columns';
|
|
27
28
|
import { useFacetLoaders, isLongTextColumn } from './use-facet-loaders';
|
|
28
29
|
import { translateOptionLabels } from './filter-chips';
|
|
@@ -104,13 +105,20 @@ function writeStoredPageSize(model, size) {
|
|
|
104
105
|
// quota / private mode — persistence is a nicety, never fatal
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
|
-
export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync = true, hideImport, hideExport, hiddenColumns = [], onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns = [], getDynamicColumns = defaultGetDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp = false, }) {
|
|
108
|
+
export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync = true, hideImport, hideExport, hiddenColumns = [], allowedActionKeys, onAction, onRowClick, refreshTrigger, realtime: realtimeProp, defaultFilters, extraColumns = [], getDynamicColumns = defaultGetDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp = false, }) {
|
|
108
109
|
// The explicit `pagination` prop wins; the legacy `infiniteScroll` boolean
|
|
109
110
|
// still selects the mode when `pagination` is absent (back-compat).
|
|
110
111
|
const infiniteScroll = paginationMode ? paginationMode === 'infinite' : infiniteScrollProp;
|
|
111
112
|
const { t, i18n } = useTranslation();
|
|
112
113
|
const api = useApi();
|
|
113
114
|
const currentBranch = useCurrentBranch();
|
|
115
|
+
// Realtime refetch (opt-in): a debounced counter that bumps on every
|
|
116
|
+
// DATA_EVENT for this model and rides the same deps as `refreshTrigger`.
|
|
117
|
+
const realtimeDefault = useRealtimeDefault();
|
|
118
|
+
const realtimeTick = useRealtimeTick({
|
|
119
|
+
models: [model],
|
|
120
|
+
enabled: realtimeProp ?? realtimeDefault,
|
|
121
|
+
});
|
|
114
122
|
const prevBranchId = useRef(currentBranch?.id);
|
|
115
123
|
const { getMetadata, setMetadata: cacheMetadata } = useMetadataCache();
|
|
116
124
|
const cachedMeta = getMetadata(model);
|
|
@@ -611,7 +619,8 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
611
619
|
finally {
|
|
612
620
|
setLoadingData(false);
|
|
613
621
|
}
|
|
614
|
-
|
|
622
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
623
|
+
}, [model, metadata, pagination, buildFilterParams, refreshTrigger, realtimeTick, endpoint, currentBranch?.id, api, enableUrlSync]);
|
|
615
624
|
// Columns whose metadata opts into a footer total (display_config.aggregate
|
|
616
625
|
// → styleConfig.aggregate). When empty, no footer row is rendered and no
|
|
617
626
|
// aggregate request is made.
|
|
@@ -772,8 +781,9 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
772
781
|
// matching the classic path (fetchData carries refreshTrigger in its
|
|
773
782
|
// deps). Without it the comment above lied: infinite lists silently
|
|
774
783
|
// failed to reload after a create ("a veces no recarga la tabla").
|
|
784
|
+
// realtimeTick plays the same role for data events (see the `realtime` prop).
|
|
775
785
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
776
|
-
}, [infiniteScroll, metadata, filterSignature, refreshTrigger]);
|
|
786
|
+
}, [infiniteScroll, metadata, filterSignature, refreshTrigger, realtimeTick]);
|
|
777
787
|
const handleRefresh = useCallback(() => {
|
|
778
788
|
// Infinite mode owns its own list: refresh reloads page 1 and drops the
|
|
779
789
|
// accumulated pages (a classic fetchData would collapse it to one small
|
|
@@ -999,15 +1009,27 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
|
|
|
999
1009
|
// Row-action column only renders per-row actions. Table-level placements
|
|
1000
1010
|
// ("table"/"create") are surfaced by <ModelActionToolbar> at the page
|
|
1001
1011
|
// level, so strip them here to avoid a meaningless per-row button.
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1012
|
+
// `allowedActionKeys`, when given, further narrows the row set to a
|
|
1013
|
+
// per-VIEW allowlist — two nav entries on the same model (a generic
|
|
1014
|
+
// list vs. a purpose-built approval queue) can then show different
|
|
1015
|
+
// actions instead of every action the model declares.
|
|
1016
|
+
const rowMetadata = (() => {
|
|
1017
|
+
let actions = viewMetadata.actions;
|
|
1018
|
+
if (actions?.some((a) => a.placement === 'table' || a.placement === 'create')) {
|
|
1019
|
+
actions = actions.filter((a) => !a.placement || a.placement === 'row');
|
|
1020
|
+
}
|
|
1021
|
+
if (allowedActionKeys && actions) {
|
|
1022
|
+
const allowed = new Set(allowedActionKeys);
|
|
1023
|
+
actions = actions.filter((a) => allowed.has(a.key));
|
|
1024
|
+
}
|
|
1025
|
+
return actions === viewMetadata.actions ? viewMetadata : { ...viewMetadata, actions };
|
|
1026
|
+
})();
|
|
1005
1027
|
const baseColumns = getDynamicColumns(rowMetadata, handleInternalAction, t, i18n.language, columnFilterConfigs, timeZone, currency);
|
|
1006
1028
|
const filteredBase = baseColumns.filter((col) => !hiddenColumns.includes(col.id));
|
|
1007
1029
|
const actionsCol = filteredBase.find((c) => c.id === 'actions');
|
|
1008
1030
|
const otherCols = filteredBase.filter((c) => c.id !== 'actions');
|
|
1009
1031
|
return [...otherCols, ...extraColumns, ...(actionsCol ? [actionsCol] : [])];
|
|
1010
|
-
}, [viewMetadata, handleInternalAction, hiddenColumns, extraColumns, t, i18n.language, columnFilterConfigs, getDynamicColumns, timeZone, currency]);
|
|
1032
|
+
}, [viewMetadata, handleInternalAction, hiddenColumns, allowedActionKeys, extraColumns, t, i18n.language, columnFilterConfigs, getDynamicColumns, timeZone, currency]);
|
|
1011
1033
|
const filters = useMemo(() => [], []);
|
|
1012
1034
|
const table = useReactTable({
|
|
1013
1035
|
data,
|
package/dist/index.d.ts
CHANGED
|
@@ -41,12 +41,14 @@ export * from './print-document-button';
|
|
|
41
41
|
export * from './use-org-document-templates';
|
|
42
42
|
export * from './document-template-editor';
|
|
43
43
|
export * from './metadata-cache';
|
|
44
|
+
export { RealtimeProvider, useRealtimeClient, useRealtimeDefault, useRealtime, useRealtimeStatus, useRealtimeInvalidate, useRealtimeTick, queryKeyMatchesEvent, type RealtimeContextValue, type RealtimeProviderProps, type UseRealtimeOptions, type UseRealtimeInvalidateOptions, type UseRealtimeTickOptions, } from './realtime-context';
|
|
44
45
|
export { ADDON_MANIFEST_CHANGED_TYPE, wireHotSwapInvalidation, useManifestHotSwapSubscriber, type AddonManifestChangedMessage, type ManifestHotSwapClient, type WireHotSwapInvalidationOptions, } from './manifest-hotswap-subscriber';
|
|
45
46
|
export { useHotSwapReload, applyHotSwapReload, withVersionParam, clearFederationContainer, shortenHash, type HotSwapReloadStrategy, type HotSwapReloadConfig, type HotSwapReloadAction, type HotSwapReloadDeps, type UseHotSwapReloadResult, } from './hotswap-reload-policy';
|
|
46
47
|
export * from './dynamic-icon';
|
|
47
48
|
export type { ColumnFilterConfig, FilterOption as DynamicColumnFilterOption, GetDynamicColumns, DynamicIconComponent, } from './dynamic-columns-shim';
|
|
48
49
|
export { defaultGetDynamicColumns, makeDefaultGetDynamicColumns, relationKeyFor, resolveAvatarSrc, resolveMissingActorLabel, resolveActorDisplayName, resolveRelationLabel, type DynamicColumnsHelpers, } from './dynamic-columns';
|
|
49
|
-
export { humanizeToken } from './dynamic-columns-helpers';
|
|
50
|
+
export { humanizeToken, translateMetadataLabel } from './dynamic-columns-helpers';
|
|
51
|
+
export type { MetadataTranslator } from './dynamic-columns-helpers';
|
|
50
52
|
export { UrlChip, FileChip, ImageThumbnail, MediaValue, RichText, linkifyText, classifyUrl, isImageUrl, isFileUrl, ensureHref, smartUrlLabel, fileNameFromUrl, splitTrailingPunct, type UrlKind, type LinkifyOptions, } from './rich-url';
|
|
51
53
|
export { ImageStack, OptionBadge, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
52
54
|
export { CollectionCell, formatScalar, prettifyKey, countLabel, type CollectionCellProps, type Translate as CollectionCellTranslate, } from './collection-cell';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,KAAK,cAAc,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACnG,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,cAAc,EACd,KAAK,mBAAmB,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACvB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,mBAAmB,EACnB,MAAM,EACN,oBAAoB,EACpB,OAAO,EACP,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,wBAAwB,GAChC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,SAAS,GACjB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,GAC9B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,GACtC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AACnE,OAAO,EACH,OAAO,EACP,QAAQ,EACR,cAAc,EACd,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,SAAS,IAAI,uBAAuB,GAC5C,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,YAAY,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,qBAAqB,EACrB,KAAK,0BAA0B,GAClC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,gBAAgB,EAChB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,KAAK,mBAAmB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -46,11 +46,12 @@ export * from './print-document-button';
|
|
|
46
46
|
export * from './use-org-document-templates';
|
|
47
47
|
export * from './document-template-editor';
|
|
48
48
|
export * from './metadata-cache';
|
|
49
|
+
export { RealtimeProvider, useRealtimeClient, useRealtimeDefault, useRealtime, useRealtimeStatus, useRealtimeInvalidate, useRealtimeTick, queryKeyMatchesEvent, } from './realtime-context';
|
|
49
50
|
export { ADDON_MANIFEST_CHANGED_TYPE, wireHotSwapInvalidation, useManifestHotSwapSubscriber, } from './manifest-hotswap-subscriber';
|
|
50
51
|
export { useHotSwapReload, applyHotSwapReload, withVersionParam, clearFederationContainer, shortenHash, } from './hotswap-reload-policy';
|
|
51
52
|
export * from './dynamic-icon';
|
|
52
53
|
export { defaultGetDynamicColumns, makeDefaultGetDynamicColumns, relationKeyFor, resolveAvatarSrc, resolveMissingActorLabel, resolveActorDisplayName, resolveRelationLabel, } from './dynamic-columns';
|
|
53
|
-
export { humanizeToken } from './dynamic-columns-helpers';
|
|
54
|
+
export { humanizeToken, translateMetadataLabel } from './dynamic-columns-helpers';
|
|
54
55
|
export { UrlChip, FileChip, ImageThumbnail, MediaValue, RichText, linkifyText, classifyUrl, isImageUrl, isFileUrl, ensureHref, smartUrlLabel, fileNameFromUrl, splitTrailingPunct, } from './rich-url';
|
|
55
56
|
export { ImageStack, OptionBadge, statusColorFor, useIsDarkTheme, } from './display-value';
|
|
56
57
|
export { CollectionCell, formatScalar, prettifyKey, countLabel, } from './collection-cell';
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { QueryKey } from '@tanstack/react-query';
|
|
2
|
+
import type { DataEvent, DataEventHandler, RealtimeAPI, RealtimeStatus, RealtimeSubscribeOptions } from '@asteby/metacore-sdk';
|
|
3
|
+
export interface RealtimeContextValue {
|
|
4
|
+
/** Host-provided client, or null when the host has no realtime. */
|
|
5
|
+
client: RealtimeAPI | null;
|
|
6
|
+
/**
|
|
7
|
+
* When true, `DynamicTable` / `DynamicKanban` refetch on data events
|
|
8
|
+
* unless a component passes `realtime={false}`. Default false (opt-in).
|
|
9
|
+
*/
|
|
10
|
+
defaultRealtime: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface RealtimeProviderProps {
|
|
13
|
+
client: RealtimeAPI | null | undefined;
|
|
14
|
+
/** Turn realtime refetch on for every dynamic table/kanban below. Default false. */
|
|
15
|
+
defaultRealtime?: boolean;
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Mount once, inside the host's WebSocket provider and QueryClientProvider.
|
|
20
|
+
* `client` may be null while the host is still connecting — hooks become
|
|
21
|
+
* no-ops and re-subscribe when a client appears.
|
|
22
|
+
*/
|
|
23
|
+
export declare function RealtimeProvider({ client, defaultRealtime, children }: RealtimeProviderProps): import("react").JSX.Element;
|
|
24
|
+
/** The host realtime client from context (null when none is mounted). */
|
|
25
|
+
export declare function useRealtimeClient(explicit?: RealtimeAPI | null): RealtimeAPI | null;
|
|
26
|
+
/** Whether dynamic components should refetch on data events by default. */
|
|
27
|
+
export declare function useRealtimeDefault(): boolean;
|
|
28
|
+
export interface UseRealtimeOptions extends RealtimeSubscribeOptions {
|
|
29
|
+
/** Pass `host.realtime` / `api.realtime` to bypass the context. */
|
|
30
|
+
client?: RealtimeAPI | null;
|
|
31
|
+
/** Set false to pause the subscription without unmounting. Default true. */
|
|
32
|
+
enabled?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Subscribe to data events for the given models. The handler is kept in a
|
|
36
|
+
* ref so callers don't need to memoise it; the subscription is torn down on
|
|
37
|
+
* unmount and re-created when models/events/client change.
|
|
38
|
+
*
|
|
39
|
+
* useRealtime({ models: ['SalesOrder'], client: host.realtime }, (e) => {
|
|
40
|
+
* if (e.action === 'resync' || e.id === currentId) refetch()
|
|
41
|
+
* })
|
|
42
|
+
*/
|
|
43
|
+
export declare function useRealtime(options: UseRealtimeOptions, handler: DataEventHandler): void;
|
|
44
|
+
/** Live status of the realtime client ('closed' when none). */
|
|
45
|
+
export declare function useRealtimeStatus(explicit?: RealtimeAPI | null): RealtimeStatus;
|
|
46
|
+
/** Default matcher: any string segment of the query key (case-insensitive)
|
|
47
|
+
* equals the event's model, table or `addon.model`, or contains the model
|
|
48
|
+
* as a path segment (`/data/sales_orders`). */
|
|
49
|
+
export declare function queryKeyMatchesEvent(queryKey: QueryKey, event: DataEvent): boolean;
|
|
50
|
+
export interface UseRealtimeInvalidateOptions extends UseRealtimeOptions {
|
|
51
|
+
/** Override which queries a given event invalidates. Default: `queryKeyMatchesEvent`. */
|
|
52
|
+
match?: (queryKey: QueryKey, event: DataEvent) => boolean;
|
|
53
|
+
/** Coalesce bursts before invalidating (ms). Default 250. */
|
|
54
|
+
debounceMs?: number;
|
|
55
|
+
/** Observe each event after it was scheduled for invalidation. */
|
|
56
|
+
onEvent?: DataEventHandler;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Invalidate every react-query query whose key mentions the event's model /
|
|
60
|
+
* table (see `queryKeyMatchesEvent`). Uses the host's QueryClient. Bursts
|
|
61
|
+
* are debounced so a coalesced frame storm becomes a single refetch round.
|
|
62
|
+
*
|
|
63
|
+
* useRealtimeInvalidate({ models: ['SalesOrder', 'sales_order_items'], client: host.realtime })
|
|
64
|
+
*/
|
|
65
|
+
export declare function useRealtimeInvalidate(options: UseRealtimeInvalidateOptions): void;
|
|
66
|
+
export interface UseRealtimeTickOptions {
|
|
67
|
+
/** Models/tables to watch. */
|
|
68
|
+
models: string[];
|
|
69
|
+
/** Explicit client (federated addons). */
|
|
70
|
+
client?: RealtimeAPI | null;
|
|
71
|
+
/** Master switch — the caller resolves prop vs provider default. */
|
|
72
|
+
enabled: boolean;
|
|
73
|
+
/** Coalesce bursts before ticking (ms). Default 300. */
|
|
74
|
+
debounceMs?: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A counter that increments (debounced) whenever a data event lands for one
|
|
78
|
+
* of `models`. Fold it into a refetch effect's dependencies — that is exactly
|
|
79
|
+
* what `DynamicTable` / `DynamicKanban` do behind their `realtime` prop.
|
|
80
|
+
*/
|
|
81
|
+
export declare function useRealtimeTick(options: UseRealtimeTickOptions): number;
|
|
82
|
+
//# sourceMappingURL=realtime-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"realtime-context.d.ts","sourceRoot":"","sources":["../src/realtime-context.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAErD,OAAO,KAAK,EACR,SAAS,EAET,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,wBAAwB,EAC3B,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,oBAAoB;IACjC,mEAAmE;IACnE,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;IAC1B;;;OAGG;IACH,eAAe,EAAE,OAAO,CAAA;CAC3B;AAID,MAAM,WAAW,qBAAqB;IAClC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,CAAA;IACtC,oFAAoF;IACpF,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,eAAuB,EAAE,QAAQ,EAAE,EAAE,qBAAqB,+BAMpG;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,WAAW,GAAG,IAAI,CAGnF;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED,MAAM,WAAW,kBAAmB,SAAQ,wBAAwB;IAChE,mEAAmE;IACnE,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAoBxF;AAED,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,GAAG,cAAc,CAa/E;AAED;;gDAEgD;AAChD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,GAAG,OAAO,CAelF;AAgBD,MAAM,WAAW,4BAA6B,SAAQ,kBAAkB;IACpE,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,KAAK,OAAO,CAAA;IACzD,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,CAiCjF;AAED,MAAM,WAAW,sBAAsB;IACnC,8BAA8B;IAC9B,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAA;IAChB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAuBvE"}
|