@asteby/metacore-runtime-react 46.0.0 → 46.1.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 46.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 5fab173: `DocumentPage`: los contadores de los botones inteligentes y de las pestañas «records» usan el total del servidor (`meta.total`) en lugar del número de filas traídas. Una ficha de cliente con 312 ventas mostraba «50» (el tamaño de la página); ahora muestra 312. `useDocumentSources` devuelve `totals` y `DocumentContext` lo expone (opcional; sin `meta.total` el contador sigue siendo el largo de las filas). Sin cambios para los specs existentes.
8
+
3
9
  ## 46.0.0
4
10
 
5
11
  ### Minor Changes
@@ -22,11 +22,11 @@ export function DocumentPage(props) {
22
22
  const { t } = useTranslation();
23
23
  const fmt = { locale: props.locale, currency: props.currency, timeZone: props.timeZone };
24
24
  const recordId = record.id;
25
- const { sources, reload } = useDocumentSources(spec.sources, recordId);
25
+ const { sources, totals, reload } = useDocumentSources(spec.sources, recordId);
26
26
  const ctx = useMemo(() => {
27
- const base = { record, sources };
27
+ const base = { record, sources, totals };
28
28
  return { ...base, derived: registration.derive?.(base) ?? {} };
29
- }, [record, sources, registration]);
29
+ }, [record, sources, totals, registration]);
30
30
  // Recarga las fuentes cuando el host avisa de un cambio (acción ejecutada).
31
31
  const [lastReload, setLastReload] = useState(props.reloadKey ?? 0);
32
32
  if ((props.reloadKey ?? 0) !== lastReload) {
@@ -75,7 +75,7 @@ export function DocumentPage(props) {
75
75
  };
76
76
  const smart = (spec.smartButtons ?? [])
77
77
  .map((b) => {
78
- const count = b.source ? sources[b.source]?.length ?? 0 : undefined;
78
+ const count = b.source ? sourceCount(ctx, b.source) : undefined;
79
79
  const active = b.source ? (count ?? 0) > 0 : b.field ? !!readPath(ctx, b.field) : true;
80
80
  if (b.hideWhenEmpty && !active)
81
81
  return null;
@@ -99,9 +99,13 @@ export function DocumentPage(props) {
99
99
  ? { label: t(spec.copyable.label, { defaultValue: spec.copyable.label }), value: String(copyValue) }
100
100
  : undefined, leading: leading, renderLink: renderLink, actions: _jsx(ActionBar, { layout: layout, onAction: (a) => handleAction(a) }) }), _jsx(SmartButtons, { items: smart }), _jsxs(Tabs, { value: tab, onValueChange: setTab, className: 'flex flex-col gap-4', children: [_jsx(TabsList, { className: 'w-fit', children: spec.tabs.map((tb) => (_jsxs(TabsTrigger, { value: tb.key, children: [t(tb.label, { defaultValue: tb.label }), tabCount(tb, ctx) !== undefined ? (_jsx("span", { className: 'ml-1.5 rounded-full bg-muted px-1.5 text-xs tabular-nums', children: tabCount(tb, ctx) })) : null] }, tb.key))) }), spec.tabs.map((tb) => (_jsx(TabsContent, { value: tb.key, className: 'mt-0', children: renderTab(tb, spec, ctx, fmt, slots) }, tb.key)))] })] }));
101
101
  }
102
+ /** Total de una fuente: el del servidor si lo dio (`meta.total`), si no las filas traídas. */
103
+ function sourceCount(ctx, key) {
104
+ return ctx.totals?.[key] ?? ctx.sources[key]?.length ?? 0;
105
+ }
102
106
  function tabCount(tb, ctx) {
103
107
  if (tb.kind === 'records')
104
- return ctx.sources[tb.source]?.length;
108
+ return ctx.sources[tb.source] ? sourceCount(ctx, tb.source) : undefined;
105
109
  if (tb.kind === 'slot' && tb.count) {
106
110
  const v = readPath(ctx, tb.count);
107
111
  return typeof v === 'number' ? v : undefined;
@@ -178,6 +178,8 @@ export interface DocumentContext {
178
178
  record: Record<string, unknown>;
179
179
  /** Filas por fuente (`sources[key]`). */
180
180
  sources: Record<string, Record<string, unknown>[]>;
181
+ /** Total del servidor por fuente (`meta.total`); si falta, el contador usa el largo de `sources[key]`. */
182
+ totals?: Record<string, number>;
181
183
  /** Derivados (`$`). */
182
184
  derived: Record<string, unknown>;
183
185
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/document/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/document/types.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,12 @@
1
1
  import type { DocumentSourceDef } from './types';
2
2
  export interface DocumentSourcesState {
3
3
  sources: Record<string, Record<string, unknown>[]>;
4
+ /**
5
+ * Total del servidor por fuente directa (`meta.total`), para que un contador
6
+ * diga 312 y no «50» (el tamaño de la página que se trajo). Una fuente sin
7
+ * `meta.total` —o de dos saltos— no aparece: el contador cae al largo de sus filas.
8
+ */
9
+ totals: Record<string, number>;
4
10
  loading: boolean;
5
11
  /** Vuelve a pedir todas las fuentes (tras ejecutar una acción). */
6
12
  reload: () => void;
@@ -1 +1 @@
1
- {"version":3,"file":"use-document-sources.d.ts","sourceRoot":"","sources":["../../src/document/use-document-sources.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAQhD,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;IAClD,OAAO,EAAE,OAAO,CAAA;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACrC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GACtC,oBAAoB,CAgEtB"}
1
+ {"version":3,"file":"use-document-sources.d.ts","sourceRoot":"","sources":["../../src/document/use-document-sources.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAQhD,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAA;IAClD;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,OAAO,EAAE,OAAO,CAAA;IAChB,mEAAmE;IACnE,MAAM,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,iBAAiB,EAAE,GAAG,SAAS,EACrC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GACtC,oBAAoB,CAuEtB"}
@@ -12,16 +12,19 @@ const VIA_CHUNK = 40;
12
12
  export function useDocumentSources(defs, recordId) {
13
13
  const api = useApi();
14
14
  const [sources, setSources] = useState({});
15
+ const [totals, setTotals] = useState({});
15
16
  const [loading, setLoading] = useState(false);
16
17
  const [nonce, setNonce] = useState(0);
17
18
  const reload = useCallback(() => setNonce((n) => n + 1), []);
18
19
  useEffect(() => {
19
20
  if (!defs || defs.length === 0 || recordId === undefined || recordId === null) {
20
21
  setSources({});
22
+ setTotals({});
21
23
  return;
22
24
  }
23
25
  let cancelled = false;
24
26
  setLoading(true);
27
+ const seenTotals = {};
25
28
  const fetchRows = async (d, params) => {
26
29
  try {
27
30
  const res = await api.get(`/data/${d.model}`, {
@@ -29,6 +32,10 @@ export function useDocumentSources(defs, recordId) {
29
32
  });
30
33
  const body = res.data;
31
34
  const rows = (body?.data ?? body);
35
+ const total = body?.meta?.total;
36
+ // Sólo las consultas directas (sin `via`): las de dos saltos se parten en trozos y no suman.
37
+ if (!d.via && typeof total === 'number' && Number.isFinite(total))
38
+ seenTotals[d.key] = total;
32
39
  return Array.isArray(rows) ? rows : [];
33
40
  }
34
41
  catch {
@@ -62,11 +69,12 @@ export function useDocumentSources(defs, recordId) {
62
69
  if (cancelled)
63
70
  return;
64
71
  setSources(out);
72
+ setTotals(seenTotals);
65
73
  setLoading(false);
66
74
  });
67
75
  return () => {
68
76
  cancelled = true;
69
77
  };
70
78
  }, [api, defs, recordId, nonce]);
71
- return { sources, loading, reload };
79
+ return { sources, totals, loading, reload };
72
80
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "46.0.0",
3
+ "version": "46.1.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -104,4 +104,20 @@ describe('DocumentPage', () => {
104
104
  await waitFor(() => expect(open).toHaveBeenCalledWith('https://x/y.pdf', '_blank', 'noopener,noreferrer'))
105
105
  expect(onAction).not.toHaveBeenCalled()
106
106
  })
107
+
108
+ it('el contador usa meta.total del servidor, no el tamaño de la página traída', async () => {
109
+ const api = {
110
+ get: vi.fn().mockResolvedValue({
111
+ data: { success: true, data: [{ id: 'r1', fiscal_uuid: 'REP-UUID-1' }], meta: { total: 312 } },
112
+ }),
113
+ } as unknown as ApiClient
114
+ render(
115
+ <ApiProvider client={api}>
116
+ <DocumentPage registration={registration} record={{ id: 'i1', number: 'A-42', total: 1500 }} onAction={vi.fn()} currency='MXN' />
117
+ </ApiProvider>,
118
+ )
119
+ // 312 en el botón inteligente y en la pestaña; nunca «1» (una fila traída).
120
+ await waitFor(() => expect(screen.getAllByText('312').length).toBeGreaterThan(0))
121
+ expect(screen.queryAllByText('1')).toHaveLength(0)
122
+ })
107
123
  })
@@ -60,12 +60,12 @@ export function DocumentPage(props: DocumentPageProps) {
60
60
  const fmt: FieldFormatOptions = { locale: props.locale, currency: props.currency, timeZone: props.timeZone }
61
61
 
62
62
  const recordId = record.id as string | number | undefined
63
- const { sources, reload } = useDocumentSources(spec.sources, recordId)
63
+ const { sources, totals, reload } = useDocumentSources(spec.sources, recordId)
64
64
 
65
65
  const ctx: DocumentContext = useMemo(() => {
66
- const base = { record, sources }
66
+ const base = { record, sources, totals }
67
67
  return { ...base, derived: registration.derive?.(base) ?? {} }
68
- }, [record, sources, registration])
68
+ }, [record, sources, totals, registration])
69
69
 
70
70
  // Recarga las fuentes cuando el host avisa de un cambio (acción ejecutada).
71
71
  const [lastReload, setLastReload] = useState(props.reloadKey ?? 0)
@@ -120,7 +120,7 @@ export function DocumentPage(props: DocumentPageProps) {
120
120
 
121
121
  const smart: SmartButtonItem[] = (spec.smartButtons ?? [])
122
122
  .map((b): SmartButtonItem | null => {
123
- const count = b.source ? sources[b.source]?.length ?? 0 : undefined
123
+ const count = b.source ? sourceCount(ctx, b.source) : undefined
124
124
  const active = b.source ? (count ?? 0) > 0 : b.field ? !!readPath(ctx, b.field) : true
125
125
  if (b.hideWhenEmpty && !active) return null
126
126
  const href = b.href ? interpolate(b.href, ctx) : undefined
@@ -179,8 +179,13 @@ export function DocumentPage(props: DocumentPageProps) {
179
179
  )
180
180
  }
181
181
 
182
+ /** Total de una fuente: el del servidor si lo dio (`meta.total`), si no las filas traídas. */
183
+ function sourceCount(ctx: DocumentContext, key: string): number {
184
+ return ctx.totals?.[key] ?? ctx.sources[key]?.length ?? 0
185
+ }
186
+
182
187
  function tabCount(tb: DocumentTabDef, ctx: DocumentContext): number | undefined {
183
- if (tb.kind === 'records') return ctx.sources[tb.source]?.length
188
+ if (tb.kind === 'records') return ctx.sources[tb.source] ? sourceCount(ctx, tb.source) : undefined
184
189
  if (tb.kind === 'slot' && tb.count) {
185
190
  const v = readPath(ctx, tb.count)
186
191
  return typeof v === 'number' ? v : undefined
@@ -183,6 +183,8 @@ export interface DocumentContext {
183
183
  record: Record<string, unknown>
184
184
  /** Filas por fuente (`sources[key]`). */
185
185
  sources: Record<string, Record<string, unknown>[]>
186
+ /** Total del servidor por fuente (`meta.total`); si falta, el contador usa el largo de `sources[key]`. */
187
+ totals?: Record<string, number>
186
188
  /** Derivados (`$`). */
187
189
  derived: Record<string, unknown>
188
190
  }
@@ -11,6 +11,12 @@ type Rows = Record<string, unknown>[]
11
11
 
12
12
  export interface DocumentSourcesState {
13
13
  sources: Record<string, Record<string, unknown>[]>
14
+ /**
15
+ * Total del servidor por fuente directa (`meta.total`), para que un contador
16
+ * diga 312 y no «50» (el tamaño de la página que se trajo). Una fuente sin
17
+ * `meta.total` —o de dos saltos— no aparece: el contador cae al largo de sus filas.
18
+ */
19
+ totals: Record<string, number>
14
20
  loading: boolean
15
21
  /** Vuelve a pedir todas las fuentes (tras ejecutar una acción). */
16
22
  reload: () => void
@@ -27,6 +33,7 @@ export function useDocumentSources(
27
33
  ): DocumentSourcesState {
28
34
  const api = useApi()
29
35
  const [sources, setSources] = useState<Record<string, Record<string, unknown>[]>>({})
36
+ const [totals, setTotals] = useState<Record<string, number>>({})
30
37
  const [loading, setLoading] = useState(false)
31
38
  const [nonce, setNonce] = useState(0)
32
39
  const reload = useCallback(() => setNonce((n) => n + 1), [])
@@ -34,10 +41,12 @@ export function useDocumentSources(
34
41
  useEffect(() => {
35
42
  if (!defs || defs.length === 0 || recordId === undefined || recordId === null) {
36
43
  setSources({})
44
+ setTotals({})
37
45
  return
38
46
  }
39
47
  let cancelled = false
40
48
  setLoading(true)
49
+ const seenTotals: Record<string, number> = {}
41
50
  const fetchRows = async (d: DocumentSourceDef, params: Record<string, string>): Promise<Rows> => {
42
51
  try {
43
52
  const res = await api.get(`/data/${d.model}`, {
@@ -45,6 +54,9 @@ export function useDocumentSources(
45
54
  })
46
55
  const body = res.data
47
56
  const rows = (body?.data ?? body) as unknown
57
+ const total = body?.meta?.total
58
+ // Sólo las consultas directas (sin `via`): las de dos saltos se parten en trozos y no suman.
59
+ if (!d.via && typeof total === 'number' && Number.isFinite(total)) seenTotals[d.key] = total
48
60
  return Array.isArray(rows) ? (rows as Rows) : []
49
61
  } catch {
50
62
  return []
@@ -80,6 +92,7 @@ export function useDocumentSources(
80
92
  .then((out) => {
81
93
  if (cancelled) return
82
94
  setSources(out)
95
+ setTotals(seenTotals)
83
96
  setLoading(false)
84
97
  })
85
98
  return () => {
@@ -87,5 +100,5 @@ export function useDocumentSources(
87
100
  }
88
101
  }, [api, defs, recordId, nonce])
89
102
 
90
- return { sources, loading, reload }
103
+ return { sources, totals, loading, reload }
91
104
  }