innoboxrr-vue-datatable 3.0.0 → 3.1.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/README.md +4 -2
- package/package.json +1 -1
- package/src/table.js +34 -7
- package/src/useDataTable.js +6 -6
package/README.md
CHANGED
|
@@ -63,7 +63,7 @@ import 'innoboxrr-form-core/styles'
|
|
|
63
63
|
| Prop | Por defecto | |
|
|
64
64
|
|---|---|---|
|
|
65
65
|
| `dataUrl`, `policyUrl` | — | Obligatorias. |
|
|
66
|
-
| `dataMethod`, `policyMethod` | `'post'` | `get` manda `params
|
|
66
|
+
| `dataMethod`, `policyMethod` | `'post'` | `get` manda `params`, sin el token CSRF; `post`, `data`, con `_token`. |
|
|
67
67
|
| `model` | — | El contrato del modelo (abajo). |
|
|
68
68
|
| `formFilters` | `{}` | Un cambio vuelve a la primera página. |
|
|
69
69
|
| `externalFilters` | `{}` | Un cambio recarga sin cambiar de página. |
|
|
@@ -101,9 +101,11 @@ export const setFilters = (filters) => filters
|
|
|
101
101
|
// Opcionales
|
|
102
102
|
export const dataTableComponents = () => ({ CopyLink })
|
|
103
103
|
export const bulkActions = () => [
|
|
104
|
-
{ id: 'delete', name: 'Borrar', icon: 'delete', callback: 'bulkDelete', danger: true },
|
|
104
|
+
{ id: 'delete', name: 'Borrar', icon: 'delete', callback: 'bulkDelete', danger: true, success: 'Borrados' },
|
|
105
|
+
{ id: 'publish', name: 'Publicar', callback: 'bulkUpdate', params: { status: 'published' } },
|
|
105
106
|
]
|
|
106
107
|
export const bulkDelete = (ids, rows) => { /* … */ }
|
|
108
|
+
export const bulkUpdate = (ids, rows, data) => { /* … */ }
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
- **Acciones.** `route: true` navega a `params.to` con vue-router;
|
package/package.json
CHANGED
package/src/table.js
CHANGED
|
@@ -130,9 +130,13 @@ export const sortIcon = (column, orderBy, sort = {}) => {
|
|
|
130
130
|
/**
|
|
131
131
|
* Lo que espera el backend. Con orden interno, el del usuario gana a lo que
|
|
132
132
|
* traigan los filtros externos; sin él, es al revés.
|
|
133
|
+
*
|
|
134
|
+
* El token CSRF no va aquí: no es un filtro, y lo que sale de aquí también lo
|
|
135
|
+
* recibe el modelo con `setFilters()`. Lo pone `requestConfig()`, que sabe por
|
|
136
|
+
* dónde viaja la petición.
|
|
133
137
|
*/
|
|
134
138
|
export const requestFilters = ({ formFilters = {}, externalFilters = {}, orderBy, sort = {}, page, internalSort }) => {
|
|
135
|
-
const params = {
|
|
139
|
+
const params = { managed: true, except_view_any: true }
|
|
136
140
|
const order = { orderBy, orderMode: sort[orderBy] }
|
|
137
141
|
|
|
138
142
|
return internalSort
|
|
@@ -140,12 +144,35 @@ export const requestFilters = ({ formFilters = {}, externalFilters = {}, orderBy
|
|
|
140
144
|
: { ...params, ...formFilters, ...order, ...externalFilters, page }
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Los métodos cuyo payload viaja en la query. En el piloto de la aplicación
|
|
149
|
+
* base la tabla pedía GET /api/app/product/index?_token=...: el token CSRF
|
|
150
|
+
* acababa en los registros de acceso, en los proxies y en el historial del
|
|
151
|
+
* navegador. Laravel no comprueba CSRF en ellos y axios ya manda X-XSRF-TOKEN
|
|
152
|
+
* desde la cookie, así que no hace falta.
|
|
153
|
+
*/
|
|
154
|
+
const QUERY_METHODS = ['get', 'head']
|
|
155
|
+
|
|
156
|
+
const withCsrfToken = (method, payload) => {
|
|
157
|
+
if (QUERY_METHODS.includes(String(method ?? '').toLowerCase())) {
|
|
158
|
+
const { _token: omitted, ...rest } = payload ?? {}
|
|
159
|
+
|
|
160
|
+
return rest
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return { _token: csrfToken(), ...payload }
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const requestConfig = (method, url, payload) => {
|
|
167
|
+
const body = withCsrfToken(method, payload)
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
method,
|
|
171
|
+
url,
|
|
172
|
+
data: method === 'post' ? body : null,
|
|
173
|
+
params: method === 'get' ? body : null,
|
|
174
|
+
}
|
|
175
|
+
}
|
|
149
176
|
|
|
150
177
|
/** El usuario canceló una confirmación: no es un error que haya que contar. */
|
|
151
178
|
export const isCancelled = (error) => ['RequestCancelledError', 'CanceledError'].includes(error?.name)
|
package/src/useDataTable.js
CHANGED
|
@@ -205,10 +205,8 @@ export default function useDataTable(props, { navigate = null, labels = core.DEF
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
try {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
id,
|
|
211
|
-
}))
|
|
208
|
+
// El token CSRF lo pone requestConfig, solo si no viaja en la query.
|
|
209
|
+
const response = await axios(core.requestConfig(props.policyMethod, props.policyUrl, { id }))
|
|
212
210
|
|
|
213
211
|
allowed.value = { ...allowed.value, [key]: response.data ?? {} }
|
|
214
212
|
} catch {
|
|
@@ -271,7 +269,9 @@ export default function useDataTable(props, { navigate = null, labels = core.DEF
|
|
|
271
269
|
|
|
272
270
|
/**
|
|
273
271
|
* Una acción masiva recibe los ids seleccionados —también los de otras
|
|
274
|
-
* páginas
|
|
272
|
+
* páginas—, las filas cargadas que están entre ellos y sus `params`. Con
|
|
273
|
+
* los params, una misma función sirve para varias acciones: marcar como
|
|
274
|
+
* publicado y marcar como borrador son la misma llamada con otro valor.
|
|
275
275
|
*/
|
|
276
276
|
const runBulk = async (action) => {
|
|
277
277
|
if (typeof props.model[action.callback] !== 'function') {
|
|
@@ -284,7 +284,7 @@ export default function useDataTable(props, { navigate = null, labels = core.DEF
|
|
|
284
284
|
const loaded = table.getSelectedRowModel().rows.map((row) => row.original)
|
|
285
285
|
|
|
286
286
|
try {
|
|
287
|
-
await props.model[action.callback](ids, loaded)
|
|
287
|
+
await props.model[action.callback](ids, loaded, action.params ?? {})
|
|
288
288
|
} catch (failure) {
|
|
289
289
|
if (! core.isCancelled(failure)) {
|
|
290
290
|
notifyError(core.describeError(failure, text(), text().actionFailed).message)
|