@asteby/metacore-runtime-react 7.1.4 → 8.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.
- package/CHANGELOG.md +40 -0
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +25 -18
- package/package.json +9 -9
- package/src/dynamic-table.tsx +22 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 8.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [c91d778]
|
|
8
|
+
- Updated dependencies [64de425]
|
|
9
|
+
- @asteby/metacore-sdk@2.3.0
|
|
10
|
+
- @asteby/metacore-ui@2.0.0
|
|
11
|
+
|
|
12
|
+
## 7.1.5
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 922d63b: Add `<MetacoreAppShell>` — single-line provider wiring for metacore apps.
|
|
17
|
+
|
|
18
|
+
Today every app reproduces the same eight-deep wedding cake of providers (QueryClient + ApiProvider + PWAProvider + Toaster + install/update/offline prompts + metadata cache invalidation). The new shell collapses it into:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
import { MetacoreAppShell } from "@asteby/metacore-app-providers";
|
|
22
|
+
|
|
23
|
+
<MetacoreAppShell api={api} queryClient={queryClient}>
|
|
24
|
+
<RouterProvider router={router} />
|
|
25
|
+
</MetacoreAppShell>;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
What it bundles:
|
|
29
|
+
- `QueryClientProvider` (when `queryClient` is supplied)
|
|
30
|
+
- `ApiProvider` from `runtime-react`
|
|
31
|
+
- `PWAProvider` + `PWAInstallPrompt` + `PWAUpdatePrompt` + `OfflineIndicator`
|
|
32
|
+
- `Toaster` from `metacore-ui`
|
|
33
|
+
- A `MetadataInvalidator` that clears `useMetadataCache` the moment the PWA layer reports a new service worker — so the next mount of `<DynamicTable>` fetches fresh column / filter / actions definitions instead of replaying yesterday's metadata. Resolves the stale-cache bug where adding `filterable: true` to a column on the backend was invisible until users cleared localStorage.
|
|
34
|
+
|
|
35
|
+
Apps that want a subset can pass `hidePWAInstall` / `hidePWAUpdate` / `hideOfflineIndicator` / `hideToaster` / `disableMetadataInvalidate` to opt out per layer.
|
|
36
|
+
|
|
37
|
+
`runtime-react` patch: also switches `<DynamicTable>` to stale-while-revalidate metadata fetch (paint with cache, always re-fetch in background) so the shell isn't the only path that picks up backend changes.
|
|
38
|
+
|
|
39
|
+
- 922d63b: Auto-derive `date_range` filter for `type: 'date'` columns.
|
|
40
|
+
|
|
41
|
+
The zero-config filter chip in 7.1.0 picked the right variant for text/number/boolean/select but mapped `type: 'date'` to a generic text filter. `FilterableColumnHeader` already supports `date_range` — pointing the auto-derive at it makes any column flagged `filterable: true` with `type: 'date'` light up the calendar range picker without app-side glue.
|
|
42
|
+
|
|
3
43
|
## 7.1.4
|
|
4
44
|
|
|
5
45
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AA+B9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AASnF,UAAU,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,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;CACxC;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,aAAoB,EACpB,aAAkB,EAClB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,GAC/C,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AA+B9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AASnF,UAAU,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,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;CACxC;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,aAAoB,EACpB,aAAkB,EAClB,QAAQ,EACR,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,GAC/C,EAAE,iBAAiB,2CA8rBnB"}
|
package/dist/dynamic-table.js
CHANGED
|
@@ -191,35 +191,42 @@ export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColu
|
|
|
191
191
|
return;
|
|
192
192
|
metaInitRef.current = true;
|
|
193
193
|
const initMetadataAndOptions = async () => {
|
|
194
|
-
let meta;
|
|
195
194
|
const cached = getMetadata(model);
|
|
195
|
+
// Stale-while-revalidate: paint with the cached metadata if any so
|
|
196
|
+
// the table renders instantly, then always re-fetch in the
|
|
197
|
+
// background so a backend metadata change (new column, new
|
|
198
|
+
// filterable flag) propagates without users having to clear
|
|
199
|
+
// localStorage.
|
|
196
200
|
if (cached) {
|
|
197
|
-
|
|
198
|
-
setMetadata(meta);
|
|
201
|
+
setMetadata(cached);
|
|
199
202
|
if (!urlHadPerPage.current)
|
|
200
|
-
setPagination((prev) => ({ ...prev, pageSize:
|
|
203
|
+
setPagination((prev) => ({ ...prev, pageSize: cached.defaultPerPage || 10 }));
|
|
201
204
|
setLoading(false);
|
|
202
205
|
}
|
|
203
206
|
else {
|
|
204
207
|
setLoading(true);
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
208
|
+
}
|
|
209
|
+
let meta = cached || null;
|
|
210
|
+
try {
|
|
211
|
+
const res = await api.get(`/metadata/table/${model}`);
|
|
212
|
+
if (res.data.success) {
|
|
213
|
+
const fresh = res.data.data;
|
|
214
|
+
meta = fresh;
|
|
215
|
+
setMetadata(fresh);
|
|
216
|
+
cacheMetadata(model, fresh);
|
|
212
217
|
if (!urlHadPerPage.current)
|
|
213
|
-
setPagination((prev) => ({ ...prev, pageSize:
|
|
218
|
+
setPagination((prev) => ({ ...prev, pageSize: fresh.defaultPerPage || 10 }));
|
|
214
219
|
}
|
|
215
|
-
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
if (!cached)
|
|
216
223
|
console.error('Error al cargar la configuración de la tabla', error);
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
finally {
|
|
220
|
-
setLoading(false);
|
|
221
|
-
}
|
|
222
224
|
}
|
|
225
|
+
finally {
|
|
226
|
+
setLoading(false);
|
|
227
|
+
}
|
|
228
|
+
if (!meta)
|
|
229
|
+
return;
|
|
223
230
|
const columnEndpoints = meta.columns.filter(c => c.useOptions && c.searchEndpoint).map(c => c.searchEndpoint);
|
|
224
231
|
const filterEndpoints = (meta.filters || []).filter(f => f.searchEndpoint && (f.type === 'select' || f.type === 'boolean')).map(f => f.searchEndpoint);
|
|
225
232
|
const allEndpoints = [...columnEndpoints, ...filterEndpoints];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"lucide-react": ">=0.460",
|
|
30
30
|
"date-fns": ">=3",
|
|
31
31
|
"react-day-picker": ">=8",
|
|
32
|
-
"@asteby/metacore-sdk": "^2.
|
|
33
|
-
"@asteby/metacore-ui": "^0.
|
|
32
|
+
"@asteby/metacore-sdk": "^2.3.0",
|
|
33
|
+
"@asteby/metacore-ui": "^2.0.0"
|
|
34
34
|
},
|
|
35
35
|
"peerDependenciesMeta": {
|
|
36
36
|
"@tanstack/react-router": {
|
|
@@ -47,16 +47,16 @@
|
|
|
47
47
|
"@types/react": "^19.0.0",
|
|
48
48
|
"date-fns": "^4.1.0",
|
|
49
49
|
"i18next": "^26.0.0",
|
|
50
|
-
"lucide-react": "^0.
|
|
50
|
+
"lucide-react": "^1.0.0",
|
|
51
51
|
"react": "^19.2.4",
|
|
52
|
-
"react-day-picker": "^
|
|
52
|
+
"react-day-picker": "^9.0.0",
|
|
53
53
|
"react-dom": "^19.2.4",
|
|
54
|
-
"react-i18next": "^
|
|
55
|
-
"sonner": "^
|
|
54
|
+
"react-i18next": "^17.0.0",
|
|
55
|
+
"sonner": "^2.0.0",
|
|
56
56
|
"typescript": "^5.6.0",
|
|
57
57
|
"zustand": "^5.0.0",
|
|
58
|
-
"@asteby/metacore-sdk": "2.
|
|
59
|
-
"@asteby/metacore-ui": "0.
|
|
58
|
+
"@asteby/metacore-sdk": "2.3.0",
|
|
59
|
+
"@asteby/metacore-ui": "2.0.0"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"build": "tsc -p tsconfig.json",
|
package/src/dynamic-table.tsx
CHANGED
|
@@ -269,29 +269,35 @@ export function DynamicTable({
|
|
|
269
269
|
if (metaInitRef.current) return
|
|
270
270
|
metaInitRef.current = true
|
|
271
271
|
const initMetadataAndOptions = async () => {
|
|
272
|
-
let meta: TableMetadata
|
|
273
272
|
const cached = getMetadata(model)
|
|
273
|
+
// Stale-while-revalidate: paint with the cached metadata if any so
|
|
274
|
+
// the table renders instantly, then always re-fetch in the
|
|
275
|
+
// background so a backend metadata change (new column, new
|
|
276
|
+
// filterable flag) propagates without users having to clear
|
|
277
|
+
// localStorage.
|
|
274
278
|
if (cached) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (!urlHadPerPage.current) setPagination((prev: PaginationState) => ({ ...prev, pageSize: meta.defaultPerPage || 10 }))
|
|
279
|
+
setMetadata(cached)
|
|
280
|
+
if (!urlHadPerPage.current) setPagination((prev: PaginationState) => ({ ...prev, pageSize: cached.defaultPerPage || 10 }))
|
|
278
281
|
setLoading(false)
|
|
279
282
|
} else {
|
|
280
283
|
setLoading(true)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
} finally {
|
|
292
|
-
setLoading(false)
|
|
284
|
+
}
|
|
285
|
+
let meta: TableMetadata | null = cached || null
|
|
286
|
+
try {
|
|
287
|
+
const res = await api.get(`/metadata/table/${model}`) as { data: ApiResponse<TableMetadata> }
|
|
288
|
+
if (res.data.success) {
|
|
289
|
+
const fresh = res.data.data
|
|
290
|
+
meta = fresh
|
|
291
|
+
setMetadata(fresh)
|
|
292
|
+
cacheMetadata(model, fresh)
|
|
293
|
+
if (!urlHadPerPage.current) setPagination((prev: PaginationState) => ({ ...prev, pageSize: fresh.defaultPerPage || 10 }))
|
|
293
294
|
}
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (!cached) console.error('Error al cargar la configuración de la tabla', error)
|
|
297
|
+
} finally {
|
|
298
|
+
setLoading(false)
|
|
294
299
|
}
|
|
300
|
+
if (!meta) return
|
|
295
301
|
const columnEndpoints = meta.columns.filter(c => c.useOptions && c.searchEndpoint).map(c => c.searchEndpoint!)
|
|
296
302
|
const filterEndpoints = (meta.filters || []).filter(f => f.searchEndpoint && (f.type === 'select' || f.type === 'boolean')).map(f => f.searchEndpoint!)
|
|
297
303
|
const allEndpoints = [...columnEndpoints, ...filterEndpoints]
|