@juv/codego-react-ui 3.3.6 → 3.4.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/dist/index.cjs +27 -5
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.global.js +27 -5
- package/dist/index.js +27 -5
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6405,7 +6405,17 @@ var import_react_dom2 = require("react-dom");
|
|
|
6405
6405
|
var import_axios3 = __toESM(require("axios"), 1);
|
|
6406
6406
|
var import_lucide_react17 = require("lucide-react");
|
|
6407
6407
|
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
6408
|
-
|
|
6408
|
+
var csrfAxios = import_axios3.default.create();
|
|
6409
|
+
csrfAxios.interceptors.request.use((config) => {
|
|
6410
|
+
const method = (config.method ?? "").toUpperCase();
|
|
6411
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
6412
|
+
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
6413
|
+
if (!token) throw new Error('[Table] CSRF token not found. Add <meta name="csrf-token" content="..."> to your HTML <head>.');
|
|
6414
|
+
config.headers.set("X-CSRF-Token", token);
|
|
6415
|
+
}
|
|
6416
|
+
return config;
|
|
6417
|
+
});
|
|
6418
|
+
function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce = 300, transform, manual = false, refresh: refreshEnabled = false, refreshInterval = 0, hardReload, onSuccess, onError }) {
|
|
6409
6419
|
const [data, setData] = React28.useState([]);
|
|
6410
6420
|
const [columns, setColumns] = React28.useState([]);
|
|
6411
6421
|
const [currentPage, setCurrentPage] = React28.useState(1);
|
|
@@ -6415,6 +6425,14 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6415
6425
|
const [tick, setTick] = React28.useState(0);
|
|
6416
6426
|
const [searchValue, setSearchValue] = React28.useState("");
|
|
6417
6427
|
const debounceTimer = React28.useRef(void 0);
|
|
6428
|
+
React28.useEffect(() => {
|
|
6429
|
+
if (hardReload) hardReload.current = () => setTick((t) => t + 1);
|
|
6430
|
+
}, [hardReload]);
|
|
6431
|
+
React28.useEffect(() => {
|
|
6432
|
+
if (!refreshInterval || refreshInterval <= 0) return;
|
|
6433
|
+
const id = setInterval(() => setTick((t) => t + 1), refreshInterval);
|
|
6434
|
+
return () => clearInterval(id);
|
|
6435
|
+
}, [refreshInterval]);
|
|
6418
6436
|
React28.useEffect(() => {
|
|
6419
6437
|
if (manual && tick === 0) return;
|
|
6420
6438
|
let cancelled = false;
|
|
@@ -6486,6 +6504,7 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6486
6504
|
error,
|
|
6487
6505
|
goToPage: (page) => setCurrentPage(page),
|
|
6488
6506
|
reload: () => setTick((t) => t + 1),
|
|
6507
|
+
refresh: () => setTick((t) => t + 1),
|
|
6489
6508
|
searchValue,
|
|
6490
6509
|
onSearchChange: handleSearchChange
|
|
6491
6510
|
};
|
|
@@ -6734,7 +6753,7 @@ function EditModal({
|
|
|
6734
6753
|
setLoading(true);
|
|
6735
6754
|
setError(null);
|
|
6736
6755
|
try {
|
|
6737
|
-
await
|
|
6756
|
+
await csrfAxios.put(`${baseUrl}/${itemId}/update`, form);
|
|
6738
6757
|
const updated = { ...item, ...form };
|
|
6739
6758
|
if (notif && (notif.type ?? "toast") === "notification") {
|
|
6740
6759
|
setBanner(true);
|
|
@@ -6825,7 +6844,7 @@ function DeleteModal({
|
|
|
6825
6844
|
setLoading(true);
|
|
6826
6845
|
setError(null);
|
|
6827
6846
|
try {
|
|
6828
|
-
await
|
|
6847
|
+
await csrfAxios.delete(`${baseUrl}/${itemId}/delete`);
|
|
6829
6848
|
onSuccess?.(item);
|
|
6830
6849
|
onClose();
|
|
6831
6850
|
} catch (err) {
|
|
@@ -6928,6 +6947,7 @@ function Table({
|
|
|
6928
6947
|
setTableData(data ?? []);
|
|
6929
6948
|
}, [data]);
|
|
6930
6949
|
const actionIdKey = defaultActions?.idKey ?? idKey;
|
|
6950
|
+
const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
|
|
6931
6951
|
const autoFields = React28.useMemo(() => {
|
|
6932
6952
|
if (!tableData.length) return [];
|
|
6933
6953
|
return Object.keys(tableData[0]).map((k) => ({
|
|
@@ -7329,7 +7349,7 @@ function Table({
|
|
|
7329
7349
|
{
|
|
7330
7350
|
item: editItem,
|
|
7331
7351
|
fields: editFields,
|
|
7332
|
-
baseUrl:
|
|
7352
|
+
baseUrl: safeBaseUrl,
|
|
7333
7353
|
itemId: String(editItem[actionIdKey] ?? ""),
|
|
7334
7354
|
notif: defaultActions.onSuccessNotif,
|
|
7335
7355
|
grid: defaultActions.editFormGrid,
|
|
@@ -7340,6 +7360,7 @@ function Table({
|
|
|
7340
7360
|
(prev) => prev.map((r) => String(r[actionIdKey]) === String(updated[actionIdKey]) ? updated : r)
|
|
7341
7361
|
);
|
|
7342
7362
|
defaultActions.onSuccess?.("edit", updated);
|
|
7363
|
+
defaultActions.onReload?.();
|
|
7343
7364
|
const notif = defaultActions.onSuccessNotif;
|
|
7344
7365
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
7345
7366
|
toast({
|
|
@@ -7356,7 +7377,7 @@ function Table({
|
|
|
7356
7377
|
DeleteModal,
|
|
7357
7378
|
{
|
|
7358
7379
|
item: deleteItem,
|
|
7359
|
-
baseUrl:
|
|
7380
|
+
baseUrl: safeBaseUrl,
|
|
7360
7381
|
itemId: String(deleteItem[actionIdKey] ?? ""),
|
|
7361
7382
|
notif: defaultActions.onSuccessNotif,
|
|
7362
7383
|
onClose: () => setDeleteItem(null),
|
|
@@ -7365,6 +7386,7 @@ function Table({
|
|
|
7365
7386
|
(prev) => prev.filter((r) => String(r[actionIdKey]) !== String(deleted[actionIdKey]))
|
|
7366
7387
|
);
|
|
7367
7388
|
defaultActions.onSuccess?.("delete", deleted);
|
|
7389
|
+
defaultActions.onReload?.();
|
|
7368
7390
|
const notif = defaultActions.onSuccessNotif;
|
|
7369
7391
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
7370
7392
|
toast({
|
package/dist/index.d.cts
CHANGED
|
@@ -256,6 +256,19 @@ interface UseServerTableOptions {
|
|
|
256
256
|
transform?: (response: any) => any[];
|
|
257
257
|
/** If true, hook won't fetch automatically. Call reload() manually */
|
|
258
258
|
manual?: boolean;
|
|
259
|
+
/** If true, refetch data whenever reload() is called (e.g. after edit/delete) */
|
|
260
|
+
refresh?: boolean;
|
|
261
|
+
/** Auto-refresh interval in milliseconds. Omit or set 0 to disable */
|
|
262
|
+
refreshInterval?: number;
|
|
263
|
+
/**
|
|
264
|
+
* A ref that will be assigned the reload function.
|
|
265
|
+
* Call `hardReloadRef.current()` from any external button or function to trigger a refetch.
|
|
266
|
+
* @example
|
|
267
|
+
* const hardReloadRef = React.useRef<() => void>(() => {})
|
|
268
|
+
* useServerTable({ url, hardReload: hardReloadRef })
|
|
269
|
+
* // then anywhere: hardReloadRef.current()
|
|
270
|
+
*/
|
|
271
|
+
hardReload?: React.MutableRefObject<() => void>;
|
|
259
272
|
/** Called after successful data fetch */
|
|
260
273
|
onSuccess?: (data: any[]) => void;
|
|
261
274
|
/** Called on fetch error */
|
|
@@ -276,6 +289,8 @@ interface UseServerTableReturn<T> {
|
|
|
276
289
|
error: string | null;
|
|
277
290
|
goToPage: (page: number) => void;
|
|
278
291
|
reload: () => void;
|
|
292
|
+
/** Manually trigger a data refresh (alias for reload, respects refresh option) */
|
|
293
|
+
refresh: () => void;
|
|
279
294
|
searchValue?: string;
|
|
280
295
|
onSearchChange?: (value: string) => void;
|
|
281
296
|
}
|
|
@@ -304,7 +319,7 @@ interface ServerPaginationProp {
|
|
|
304
319
|
* })
|
|
305
320
|
* ```
|
|
306
321
|
*/
|
|
307
|
-
declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce, transform, manual, onSuccess, onError }: UseServerTableOptions): UseServerTableReturn<T>;
|
|
322
|
+
declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce, transform, manual, refresh: refreshEnabled, refreshInterval, hardReload, onSuccess, onError }: UseServerTableOptions): UseServerTableReturn<T>;
|
|
308
323
|
/**
|
|
309
324
|
* Available field types for action forms (edit/view modals)
|
|
310
325
|
* @type {ActionFieldType}
|
|
@@ -454,6 +469,8 @@ interface DefaultActionsConfig<T> {
|
|
|
454
469
|
deleteButton?: ActionButtonConfig;
|
|
455
470
|
/** Extra action buttons rendered alongside view/edit/delete */
|
|
456
471
|
extraActions?: ExtraActionConfig<T>[];
|
|
472
|
+
/** Called after a successful edit or delete to trigger a server-side reload (e.g. pass reload from useServerTable) */
|
|
473
|
+
onReload?: () => void;
|
|
457
474
|
}
|
|
458
475
|
/**
|
|
459
476
|
* Configuration for success notifications after edit/delete operations
|
package/dist/index.d.ts
CHANGED
|
@@ -256,6 +256,19 @@ interface UseServerTableOptions {
|
|
|
256
256
|
transform?: (response: any) => any[];
|
|
257
257
|
/** If true, hook won't fetch automatically. Call reload() manually */
|
|
258
258
|
manual?: boolean;
|
|
259
|
+
/** If true, refetch data whenever reload() is called (e.g. after edit/delete) */
|
|
260
|
+
refresh?: boolean;
|
|
261
|
+
/** Auto-refresh interval in milliseconds. Omit or set 0 to disable */
|
|
262
|
+
refreshInterval?: number;
|
|
263
|
+
/**
|
|
264
|
+
* A ref that will be assigned the reload function.
|
|
265
|
+
* Call `hardReloadRef.current()` from any external button or function to trigger a refetch.
|
|
266
|
+
* @example
|
|
267
|
+
* const hardReloadRef = React.useRef<() => void>(() => {})
|
|
268
|
+
* useServerTable({ url, hardReload: hardReloadRef })
|
|
269
|
+
* // then anywhere: hardReloadRef.current()
|
|
270
|
+
*/
|
|
271
|
+
hardReload?: React.MutableRefObject<() => void>;
|
|
259
272
|
/** Called after successful data fetch */
|
|
260
273
|
onSuccess?: (data: any[]) => void;
|
|
261
274
|
/** Called on fetch error */
|
|
@@ -276,6 +289,8 @@ interface UseServerTableReturn<T> {
|
|
|
276
289
|
error: string | null;
|
|
277
290
|
goToPage: (page: number) => void;
|
|
278
291
|
reload: () => void;
|
|
292
|
+
/** Manually trigger a data refresh (alias for reload, respects refresh option) */
|
|
293
|
+
refresh: () => void;
|
|
279
294
|
searchValue?: string;
|
|
280
295
|
onSearchChange?: (value: string) => void;
|
|
281
296
|
}
|
|
@@ -304,7 +319,7 @@ interface ServerPaginationProp {
|
|
|
304
319
|
* })
|
|
305
320
|
* ```
|
|
306
321
|
*/
|
|
307
|
-
declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce, transform, manual, onSuccess, onError }: UseServerTableOptions): UseServerTableReturn<T>;
|
|
322
|
+
declare function useServerTable<T extends Record<string, any>>({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce, transform, manual, refresh: refreshEnabled, refreshInterval, hardReload, onSuccess, onError }: UseServerTableOptions): UseServerTableReturn<T>;
|
|
308
323
|
/**
|
|
309
324
|
* Available field types for action forms (edit/view modals)
|
|
310
325
|
* @type {ActionFieldType}
|
|
@@ -454,6 +469,8 @@ interface DefaultActionsConfig<T> {
|
|
|
454
469
|
deleteButton?: ActionButtonConfig;
|
|
455
470
|
/** Extra action buttons rendered alongside view/edit/delete */
|
|
456
471
|
extraActions?: ExtraActionConfig<T>[];
|
|
472
|
+
/** Called after a successful edit or delete to trigger a server-side reload (e.g. pass reload from useServerTable) */
|
|
473
|
+
onReload?: () => void;
|
|
457
474
|
}
|
|
458
475
|
/**
|
|
459
476
|
* Configuration for success notifications after edit/delete operations
|
package/dist/index.global.js
CHANGED
|
@@ -69551,7 +69551,17 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69551
69551
|
var React28 = __toESM(require_react(), 1);
|
|
69552
69552
|
var import_react_dom2 = __toESM(require_react_dom(), 1);
|
|
69553
69553
|
var import_jsx_runtime32 = __toESM(require_jsx_runtime(), 1);
|
|
69554
|
-
|
|
69554
|
+
var csrfAxios = axios_default.create();
|
|
69555
|
+
csrfAxios.interceptors.request.use((config) => {
|
|
69556
|
+
const method = (config.method ?? "").toUpperCase();
|
|
69557
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
69558
|
+
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
69559
|
+
if (!token) throw new Error('[Table] CSRF token not found. Add <meta name="csrf-token" content="..."> to your HTML <head>.');
|
|
69560
|
+
config.headers.set("X-CSRF-Token", token);
|
|
69561
|
+
}
|
|
69562
|
+
return config;
|
|
69563
|
+
});
|
|
69564
|
+
function useServerTable({ url: url2, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce = 300, transform, manual = false, refresh: refreshEnabled = false, refreshInterval = 0, hardReload, onSuccess, onError }) {
|
|
69555
69565
|
const [data, setData] = React28.useState([]);
|
|
69556
69566
|
const [columns, setColumns] = React28.useState([]);
|
|
69557
69567
|
const [currentPage, setCurrentPage] = React28.useState(1);
|
|
@@ -69561,6 +69571,14 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69561
69571
|
const [tick, setTick] = React28.useState(0);
|
|
69562
69572
|
const [searchValue, setSearchValue] = React28.useState("");
|
|
69563
69573
|
const debounceTimer = React28.useRef(void 0);
|
|
69574
|
+
React28.useEffect(() => {
|
|
69575
|
+
if (hardReload) hardReload.current = () => setTick((t) => t + 1);
|
|
69576
|
+
}, [hardReload]);
|
|
69577
|
+
React28.useEffect(() => {
|
|
69578
|
+
if (!refreshInterval || refreshInterval <= 0) return;
|
|
69579
|
+
const id = setInterval(() => setTick((t) => t + 1), refreshInterval);
|
|
69580
|
+
return () => clearInterval(id);
|
|
69581
|
+
}, [refreshInterval]);
|
|
69564
69582
|
React28.useEffect(() => {
|
|
69565
69583
|
if (manual && tick === 0) return;
|
|
69566
69584
|
let cancelled = false;
|
|
@@ -69632,6 +69650,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69632
69650
|
error,
|
|
69633
69651
|
goToPage: (page) => setCurrentPage(page),
|
|
69634
69652
|
reload: () => setTick((t) => t + 1),
|
|
69653
|
+
refresh: () => setTick((t) => t + 1),
|
|
69635
69654
|
searchValue,
|
|
69636
69655
|
onSearchChange: handleSearchChange
|
|
69637
69656
|
};
|
|
@@ -69880,7 +69899,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69880
69899
|
setLoading(true);
|
|
69881
69900
|
setError(null);
|
|
69882
69901
|
try {
|
|
69883
|
-
await
|
|
69902
|
+
await csrfAxios.put(`${baseUrl}/${itemId}/update`, form);
|
|
69884
69903
|
const updated = { ...item, ...form };
|
|
69885
69904
|
if (notif && (notif.type ?? "toast") === "notification") {
|
|
69886
69905
|
setBanner(true);
|
|
@@ -69971,7 +69990,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
69971
69990
|
setLoading(true);
|
|
69972
69991
|
setError(null);
|
|
69973
69992
|
try {
|
|
69974
|
-
await
|
|
69993
|
+
await csrfAxios.delete(`${baseUrl}/${itemId}/delete`);
|
|
69975
69994
|
onSuccess?.(item);
|
|
69976
69995
|
onClose();
|
|
69977
69996
|
} catch (err) {
|
|
@@ -70074,6 +70093,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
70074
70093
|
setTableData(data ?? []);
|
|
70075
70094
|
}, [data]);
|
|
70076
70095
|
const actionIdKey = defaultActions?.idKey ?? idKey;
|
|
70096
|
+
const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
|
|
70077
70097
|
const autoFields = React28.useMemo(() => {
|
|
70078
70098
|
if (!tableData.length) return [];
|
|
70079
70099
|
return Object.keys(tableData[0]).map((k) => ({
|
|
@@ -70475,7 +70495,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
70475
70495
|
{
|
|
70476
70496
|
item: editItem,
|
|
70477
70497
|
fields: editFields,
|
|
70478
|
-
baseUrl:
|
|
70498
|
+
baseUrl: safeBaseUrl,
|
|
70479
70499
|
itemId: String(editItem[actionIdKey] ?? ""),
|
|
70480
70500
|
notif: defaultActions.onSuccessNotif,
|
|
70481
70501
|
grid: defaultActions.editFormGrid,
|
|
@@ -70486,6 +70506,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
70486
70506
|
(prev) => prev.map((r2) => String(r2[actionIdKey]) === String(updated[actionIdKey]) ? updated : r2)
|
|
70487
70507
|
);
|
|
70488
70508
|
defaultActions.onSuccess?.("edit", updated);
|
|
70509
|
+
defaultActions.onReload?.();
|
|
70489
70510
|
const notif = defaultActions.onSuccessNotif;
|
|
70490
70511
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
70491
70512
|
toast({
|
|
@@ -70502,7 +70523,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
70502
70523
|
DeleteModal,
|
|
70503
70524
|
{
|
|
70504
70525
|
item: deleteItem,
|
|
70505
|
-
baseUrl:
|
|
70526
|
+
baseUrl: safeBaseUrl,
|
|
70506
70527
|
itemId: String(deleteItem[actionIdKey] ?? ""),
|
|
70507
70528
|
notif: defaultActions.onSuccessNotif,
|
|
70508
70529
|
onClose: () => setDeleteItem(null),
|
|
@@ -70511,6 +70532,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
|
|
|
70511
70532
|
(prev) => prev.filter((r2) => String(r2[actionIdKey]) !== String(deleted[actionIdKey]))
|
|
70512
70533
|
);
|
|
70513
70534
|
defaultActions.onSuccess?.("delete", deleted);
|
|
70535
|
+
defaultActions.onReload?.();
|
|
70514
70536
|
const notif = defaultActions.onSuccessNotif;
|
|
70515
70537
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
70516
70538
|
toast({
|
package/dist/index.js
CHANGED
|
@@ -6285,7 +6285,17 @@ import { createPortal as createPortal3 } from "react-dom";
|
|
|
6285
6285
|
import axios3 from "axios";
|
|
6286
6286
|
import { ChevronLeft as ChevronLeft6, ChevronRight as ChevronRight8, Search as Search5, Trash2 as Trash22, ChevronsUpDown, ChevronUp, ChevronDown as ChevronDown4, X as X9, Eye as Eye2, Pencil as Pencil2, Trash as Trash3, Loader2 as Loader22 } from "lucide-react";
|
|
6287
6287
|
import { Fragment as Fragment11, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6288
|
-
|
|
6288
|
+
var csrfAxios = axios3.create();
|
|
6289
|
+
csrfAxios.interceptors.request.use((config) => {
|
|
6290
|
+
const method = (config.method ?? "").toUpperCase();
|
|
6291
|
+
if (["POST", "PUT", "PATCH", "DELETE"].includes(method)) {
|
|
6292
|
+
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
6293
|
+
if (!token) throw new Error('[Table] CSRF token not found. Add <meta name="csrf-token" content="..."> to your HTML <head>.');
|
|
6294
|
+
config.headers.set("X-CSRF-Token", token);
|
|
6295
|
+
}
|
|
6296
|
+
return config;
|
|
6297
|
+
});
|
|
6298
|
+
function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce = 300, transform, manual = false, refresh: refreshEnabled = false, refreshInterval = 0, hardReload, onSuccess, onError }) {
|
|
6289
6299
|
const [data, setData] = React28.useState([]);
|
|
6290
6300
|
const [columns, setColumns] = React28.useState([]);
|
|
6291
6301
|
const [currentPage, setCurrentPage] = React28.useState(1);
|
|
@@ -6295,6 +6305,14 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6295
6305
|
const [tick, setTick] = React28.useState(0);
|
|
6296
6306
|
const [searchValue, setSearchValue] = React28.useState("");
|
|
6297
6307
|
const debounceTimer = React28.useRef(void 0);
|
|
6308
|
+
React28.useEffect(() => {
|
|
6309
|
+
if (hardReload) hardReload.current = () => setTick((t) => t + 1);
|
|
6310
|
+
}, [hardReload]);
|
|
6311
|
+
React28.useEffect(() => {
|
|
6312
|
+
if (!refreshInterval || refreshInterval <= 0) return;
|
|
6313
|
+
const id = setInterval(() => setTick((t) => t + 1), refreshInterval);
|
|
6314
|
+
return () => clearInterval(id);
|
|
6315
|
+
}, [refreshInterval]);
|
|
6298
6316
|
React28.useEffect(() => {
|
|
6299
6317
|
if (manual && tick === 0) return;
|
|
6300
6318
|
let cancelled = false;
|
|
@@ -6366,6 +6384,7 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6366
6384
|
error,
|
|
6367
6385
|
goToPage: (page) => setCurrentPage(page),
|
|
6368
6386
|
reload: () => setTick((t) => t + 1),
|
|
6387
|
+
refresh: () => setTick((t) => t + 1),
|
|
6369
6388
|
searchValue,
|
|
6370
6389
|
onSearchChange: handleSearchChange
|
|
6371
6390
|
};
|
|
@@ -6614,7 +6633,7 @@ function EditModal({
|
|
|
6614
6633
|
setLoading(true);
|
|
6615
6634
|
setError(null);
|
|
6616
6635
|
try {
|
|
6617
|
-
await
|
|
6636
|
+
await csrfAxios.put(`${baseUrl}/${itemId}/update`, form);
|
|
6618
6637
|
const updated = { ...item, ...form };
|
|
6619
6638
|
if (notif && (notif.type ?? "toast") === "notification") {
|
|
6620
6639
|
setBanner(true);
|
|
@@ -6705,7 +6724,7 @@ function DeleteModal({
|
|
|
6705
6724
|
setLoading(true);
|
|
6706
6725
|
setError(null);
|
|
6707
6726
|
try {
|
|
6708
|
-
await
|
|
6727
|
+
await csrfAxios.delete(`${baseUrl}/${itemId}/delete`);
|
|
6709
6728
|
onSuccess?.(item);
|
|
6710
6729
|
onClose();
|
|
6711
6730
|
} catch (err) {
|
|
@@ -6808,6 +6827,7 @@ function Table({
|
|
|
6808
6827
|
setTableData(data ?? []);
|
|
6809
6828
|
}, [data]);
|
|
6810
6829
|
const actionIdKey = defaultActions?.idKey ?? idKey;
|
|
6830
|
+
const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
|
|
6811
6831
|
const autoFields = React28.useMemo(() => {
|
|
6812
6832
|
if (!tableData.length) return [];
|
|
6813
6833
|
return Object.keys(tableData[0]).map((k) => ({
|
|
@@ -7209,7 +7229,7 @@ function Table({
|
|
|
7209
7229
|
{
|
|
7210
7230
|
item: editItem,
|
|
7211
7231
|
fields: editFields,
|
|
7212
|
-
baseUrl:
|
|
7232
|
+
baseUrl: safeBaseUrl,
|
|
7213
7233
|
itemId: String(editItem[actionIdKey] ?? ""),
|
|
7214
7234
|
notif: defaultActions.onSuccessNotif,
|
|
7215
7235
|
grid: defaultActions.editFormGrid,
|
|
@@ -7220,6 +7240,7 @@ function Table({
|
|
|
7220
7240
|
(prev) => prev.map((r) => String(r[actionIdKey]) === String(updated[actionIdKey]) ? updated : r)
|
|
7221
7241
|
);
|
|
7222
7242
|
defaultActions.onSuccess?.("edit", updated);
|
|
7243
|
+
defaultActions.onReload?.();
|
|
7223
7244
|
const notif = defaultActions.onSuccessNotif;
|
|
7224
7245
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
7225
7246
|
toast({
|
|
@@ -7236,7 +7257,7 @@ function Table({
|
|
|
7236
7257
|
DeleteModal,
|
|
7237
7258
|
{
|
|
7238
7259
|
item: deleteItem,
|
|
7239
|
-
baseUrl:
|
|
7260
|
+
baseUrl: safeBaseUrl,
|
|
7240
7261
|
itemId: String(deleteItem[actionIdKey] ?? ""),
|
|
7241
7262
|
notif: defaultActions.onSuccessNotif,
|
|
7242
7263
|
onClose: () => setDeleteItem(null),
|
|
@@ -7245,6 +7266,7 @@ function Table({
|
|
|
7245
7266
|
(prev) => prev.filter((r) => String(r[actionIdKey]) !== String(deleted[actionIdKey]))
|
|
7246
7267
|
);
|
|
7247
7268
|
defaultActions.onSuccess?.("delete", deleted);
|
|
7269
|
+
defaultActions.onReload?.();
|
|
7248
7270
|
const notif = defaultActions.onSuccessNotif;
|
|
7249
7271
|
if (notif && (notif.type ?? "toast") === "toast") {
|
|
7250
7272
|
toast({
|