@asteby/metacore-runtime-react 28.2.0 → 28.3.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
+ ## 28.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cb0065f: DynamicTable/useDynamicRowActions: nuevo prop `mutationEndpoint` — base de endpoint para escrituras (delete individual y masivo) cuando difiere del endpoint de listado. Hosts que listan desde una ruta role-scoped (`/dynamic/:model/me`) borraban contra `<lista>/<id>` inexistente (404); ahora pueden listar desde `/me` y mutar contra la base real. Fallback: `endpoint` (sin cambio para hosts existentes).
8
+
3
9
  ## 28.2.0
4
10
 
5
11
  ### Minor Changes
@@ -8,6 +8,13 @@ export interface UseDynamicRowActionsParams {
8
8
  * caller lists from (e.g. `/data/<model>/me`) so writes stay org-scoped.
9
9
  */
10
10
  endpoint?: string;
11
+ /**
12
+ * Endpoint base for WRITES when it differs from the list endpoint. Some
13
+ * hosts list from a role-scoped path (`/dynamic/<model>/me`) that does NOT
14
+ * accept `DELETE <base>/<id>` — pass the mutable base here (e.g.
15
+ * `/dynamic/<model>`). Falls back to `endpoint`.
16
+ */
17
+ mutationEndpoint?: string;
11
18
  /** Raw model metadata — used to resolve link/custom action definitions. */
12
19
  metadata: TableMetadata | null;
13
20
  /**
@@ -32,5 +39,5 @@ export interface DynamicRowActions {
32
39
  * Owns the state + dialogs + dispatch logic for per-row actions, shared by
33
40
  * DynamicTable and DynamicKanban so both behave identically.
34
41
  */
35
- export declare function useDynamicRowActions({ model, endpoint, metadata, onAction, onRefresh, }: UseDynamicRowActionsParams): DynamicRowActions;
42
+ export declare function useDynamicRowActions({ model, endpoint, mutationEndpoint, metadata, onAction, onRefresh, }: UseDynamicRowActionsParams): DynamicRowActions;
36
43
  //# sourceMappingURL=dynamic-row-actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-row-actions.d.ts","sourceRoot":"","sources":["../src/dynamic-row-actions.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,SAAS,CAAA;AAE5D,MAAM,WAAW,0BAA0B;IACvC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,2EAA2E;IAC3E,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAA;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,4EAA4E;IAC5E,SAAS,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAC9B,+CAA+C;IAC/C,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE;;;OAGG;IACH,OAAO,EAAE,KAAK,CAAC,YAAY,CAAA;CAC9B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAS,GACZ,EAAE,0BAA0B,GAAG,iBAAiB,CAqHhD"}
1
+ {"version":3,"file":"dynamic-row-actions.d.ts","sourceRoot":"","sources":["../src/dynamic-row-actions.tsx"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,SAAS,CAAA;AAE5D,MAAM,WAAW,0BAA0B;IACvC,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,2EAA2E;IAC3E,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAA;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C,4EAA4E;IAC5E,SAAS,EAAE,MAAM,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAC9B,+CAA+C;IAC/C,oBAAoB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjE;;;OAGG;IACH,OAAO,EAAE,KAAK,CAAC,YAAY,CAAA;CAC9B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EACjC,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,QAAQ,EACR,QAAQ,EACR,SAAS,GACZ,EAAE,0BAA0B,GAAG,iBAAiB,CAsHhD"}
@@ -30,7 +30,8 @@ import { DynamicRecordDialog } from './dialogs/dynamic-record';
30
30
  * Owns the state + dialogs + dispatch logic for per-row actions, shared by
31
31
  * DynamicTable and DynamicKanban so both behave identically.
32
32
  */
33
- export function useDynamicRowActions({ model, endpoint, metadata, onAction, onRefresh, }) {
33
+ export function useDynamicRowActions({ model, endpoint, mutationEndpoint, metadata, onAction, onRefresh, }) {
34
+ const writeBase = mutationEndpoint ?? endpoint;
34
35
  const { t } = useTranslation();
35
36
  const api = useApi();
36
37
  const navigate = useNavigate();
@@ -87,7 +88,7 @@ export function useDynamicRowActions({ model, endpoint, metadata, onAction, onRe
87
88
  return;
88
89
  setIsDeleting(true);
89
90
  try {
90
- const deleteEndpoint = endpoint ? `${endpoint}/${rowToDelete.id}` : `/data/${model}/${rowToDelete.id}`;
91
+ const deleteEndpoint = writeBase ? `${writeBase}/${rowToDelete.id}` : `/data/${model}/${rowToDelete.id}`;
91
92
  const res = await api.delete(deleteEndpoint);
92
93
  // CRUD estándar: no usar res.data.message (el endpoint dinámico
93
94
  // devuelve texto en inglés que se filtraría al toast). String localizado.
@@ -3,6 +3,12 @@ import type { GetDynamicColumns } from './dynamic-columns-shim';
3
3
  export interface DynamicTableProps {
4
4
  model: string;
5
5
  endpoint?: string;
6
+ /**
7
+ * Endpoint base for WRITES (row delete, bulk delete) when it differs from
8
+ * the list endpoint — e.g. listing from a role-scoped `/dynamic/<model>/me`
9
+ * while deleting against `/dynamic/<model>/<id>`. Falls back to `endpoint`.
10
+ */
11
+ mutationEndpoint?: string;
6
12
  enableUrlSync?: boolean;
7
13
  hiddenColumns?: string[];
8
14
  onAction?: (action: string, row: any) => void;
@@ -58,5 +64,5 @@ export interface DynamicTableProps {
58
64
  */
59
65
  infiniteScroll?: boolean;
60
66
  }
61
- export declare function DynamicTable({ model, endpoint, enableUrlSync, hiddenColumns, onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns, getDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp, }: DynamicTableProps): import("react").JSX.Element;
67
+ export declare function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync, hiddenColumns, onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns, getDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp, }: DynamicTableProps): import("react").JSX.Element;
62
68
  //# 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;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AA2FnF,MAAM,WAAW,iBAAiB;IAC9B,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;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,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;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,aAAoB,EACpB,aAAkB,EAClB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BAquCnB"}
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;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AA2FnF,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,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,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,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,aAAkB,EAClB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BAuuCnB"}
@@ -103,7 +103,7 @@ function writeStoredPageSize(model, size) {
103
103
  // quota / private mode — persistence is a nicety, never fatal
104
104
  }
105
105
  }
106
- export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColumns = [], onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns = [], getDynamicColumns = defaultGetDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp = false, }) {
106
+ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync = true, hiddenColumns = [], onAction, onRowClick, refreshTrigger, defaultFilters, extraColumns = [], getDynamicColumns = defaultGetDynamicColumns, timeZone, currency, pagination: paginationMode, infiniteScroll: infiniteScrollProp = false, }) {
107
107
  // The explicit `pagination` prop wins; the legacy `infiniteScroll` boolean
108
108
  // still selects the mode when `pagination` is absent (back-compat).
109
109
  const infiniteScroll = paginationMode ? paginationMode === 'infinite' : infiniteScrollProp;
@@ -782,6 +782,7 @@ export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColu
782
782
  const { handleInternalAction, dialogs: rowActionDialogs } = useDynamicRowActions({
783
783
  model,
784
784
  endpoint,
785
+ mutationEndpoint,
785
786
  metadata,
786
787
  onAction,
787
788
  onRefresh: handleRefresh,
@@ -797,7 +798,8 @@ export function DynamicTable({ model, endpoint, enableUrlSync = true, hiddenColu
797
798
  for (let i = 0; i < selectedRows.length; i++) {
798
799
  const row = selectedRows[i];
799
800
  try {
800
- const deleteEndpoint = endpoint ? `${endpoint}/${row.original.id}` : `/data/${model}/${row.original.id}`;
801
+ const writeBase = mutationEndpoint ?? endpoint;
802
+ const deleteEndpoint = writeBase ? `${writeBase}/${row.original.id}` : `/data/${model}/${row.original.id}`;
801
803
  const res = await api.delete(deleteEndpoint);
802
804
  if (res.data.success)
803
805
  successCount++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "28.2.0",
3
+ "version": "28.3.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -67,8 +67,8 @@
67
67
  "typescript": "^6.0.0",
68
68
  "vitest": "^4.0.0",
69
69
  "zustand": "^5.0.0",
70
- "@asteby/metacore-sdk": "3.4.0",
71
- "@asteby/metacore-ui": "2.12.1"
70
+ "@asteby/metacore-ui": "2.12.1",
71
+ "@asteby/metacore-sdk": "3.4.0"
72
72
  },
73
73
  "scripts": {
74
74
  "build": "tsc -p tsconfig.json",
@@ -45,6 +45,13 @@ export interface UseDynamicRowActionsParams {
45
45
  * caller lists from (e.g. `/data/<model>/me`) so writes stay org-scoped.
46
46
  */
47
47
  endpoint?: string
48
+ /**
49
+ * Endpoint base for WRITES when it differs from the list endpoint. Some
50
+ * hosts list from a role-scoped path (`/dynamic/<model>/me`) that does NOT
51
+ * accept `DELETE <base>/<id>` — pass the mutable base here (e.g.
52
+ * `/dynamic/<model>`). Falls back to `endpoint`.
53
+ */
54
+ mutationEndpoint?: string
48
55
  /** Raw model metadata — used to resolve link/custom action definitions. */
49
56
  metadata: TableMetadata | null
50
57
  /**
@@ -74,10 +81,12 @@ export interface DynamicRowActions {
74
81
  export function useDynamicRowActions({
75
82
  model,
76
83
  endpoint,
84
+ mutationEndpoint,
77
85
  metadata,
78
86
  onAction,
79
87
  onRefresh,
80
88
  }: UseDynamicRowActionsParams): DynamicRowActions {
89
+ const writeBase = mutationEndpoint ?? endpoint
81
90
  const { t } = useTranslation()
82
91
  const api = useApi()
83
92
  const navigate = useNavigate()
@@ -137,7 +146,7 @@ export function useDynamicRowActions({
137
146
  if (!rowToDelete) return
138
147
  setIsDeleting(true)
139
148
  try {
140
- const deleteEndpoint = endpoint ? `${endpoint}/${rowToDelete.id}` : `/data/${model}/${rowToDelete.id}`
149
+ const deleteEndpoint = writeBase ? `${writeBase}/${rowToDelete.id}` : `/data/${model}/${rowToDelete.id}`
141
150
  const res = await api.delete(deleteEndpoint)
142
151
  // CRUD estándar: no usar res.data.message (el endpoint dinámico
143
152
  // devuelve texto en inglés que se filtraría al toast). String localizado.
@@ -158,6 +158,12 @@ function writeStoredPageSize(model: string, size: number | null): void {
158
158
  export interface DynamicTableProps {
159
159
  model: string
160
160
  endpoint?: string
161
+ /**
162
+ * Endpoint base for WRITES (row delete, bulk delete) when it differs from
163
+ * the list endpoint — e.g. listing from a role-scoped `/dynamic/<model>/me`
164
+ * while deleting against `/dynamic/<model>/<id>`. Falls back to `endpoint`.
165
+ */
166
+ mutationEndpoint?: string
161
167
  enableUrlSync?: boolean
162
168
  hiddenColumns?: string[]
163
169
  onAction?: (action: string, row: any) => void
@@ -217,6 +223,7 @@ export interface DynamicTableProps {
217
223
  export function DynamicTable({
218
224
  model,
219
225
  endpoint,
226
+ mutationEndpoint,
220
227
  enableUrlSync = true,
221
228
  hiddenColumns = [],
222
229
  onAction,
@@ -902,6 +909,7 @@ export function DynamicTable({
902
909
  const { handleInternalAction, dialogs: rowActionDialogs } = useDynamicRowActions({
903
910
  model,
904
911
  endpoint,
912
+ mutationEndpoint,
905
913
  metadata,
906
914
  onAction,
907
915
  onRefresh: handleRefresh,
@@ -917,7 +925,8 @@ export function DynamicTable({
917
925
  for (let i = 0; i < selectedRows.length; i++) {
918
926
  const row = selectedRows[i]
919
927
  try {
920
- const deleteEndpoint = endpoint ? `${endpoint}/${row.original.id}` : `/data/${model}/${row.original.id}`
928
+ const writeBase = mutationEndpoint ?? endpoint
929
+ const deleteEndpoint = writeBase ? `${writeBase}/${row.original.id}` : `/data/${model}/${row.original.id}`
921
930
  const res = await api.delete(deleteEndpoint)
922
931
  if (res.data.success) successCount++; else errorCount++
923
932
  } catch (e) { console.error('Error al eliminar', e); errorCount++ }