@nestledjs/data-browser 0.1.17 → 0.1.20

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.
@@ -1,4 +1,5 @@
1
- import React, { useCallback, useEffect, useMemo } from "react";
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo } from "react";
2
3
  import { useQuery } from "@apollo/client/react";
3
4
  import { DataTable, ErrorBoundary } from "@nestledjs/shared-components";
4
5
  import { getPluralName } from "../utils/get-plural-names.js";
@@ -11,17 +12,10 @@ import { RelationFilterField } from "../components/filters/RelationFilterField.j
11
12
  import { useAdminList } from "../hooks/useAdminList.js";
12
13
  import { getAdminDocuments } from "../utils/graphql-utils.js";
13
14
  import { useAdminDataContext } from "../context/AdminDataContext.js";
14
- var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/data-browser/src/lib/pages/AdminDataListPage.tsx";
15
- function AdminDataListPage({
16
- modelName: propModelName
17
- } = {}) {
15
+ function AdminDataListPage({ modelName: propModelName } = {}) {
18
16
  const params = useParams();
19
17
  const [searchParams] = useSearchParams();
20
- const {
21
- sdk,
22
- databaseModels,
23
- basePath = "/admin/data"
24
- } = useAdminDataContext();
18
+ const { sdk, databaseModels, basePath = "/admin/data" } = useAdminDataContext();
25
19
  const getEnumValues = useCallback((enumType) => {
26
20
  try {
27
21
  const enumObject = sdk[enumType];
@@ -38,10 +32,7 @@ function AdminDataListPage({
38
32
  return null;
39
33
  }
40
34
  }, [sdk]);
41
- const {
42
- state,
43
- dispatch
44
- } = useAdminList();
35
+ const { state, dispatch } = useAdminList();
45
36
  const {
46
37
  search,
47
38
  debouncedSearch,
@@ -55,43 +46,43 @@ function AdminDataListPage({
55
46
  showFilters,
56
47
  showSearchFieldSelector
57
48
  } = state;
58
- useCallback((skip2) => dispatch({
59
- type: "SET_SKIP",
60
- payload: skip2
61
- }), [dispatch]);
62
- const setFilters = useCallback((filters2) => dispatch({
63
- type: "SET_FILTERS",
64
- payload: filters2
65
- }), [dispatch]);
66
- const setShowFilters = useCallback((show) => {
67
- if (show !== showFilters) dispatch({
68
- type: "TOGGLE_FILTERS"
69
- });
70
- }, [showFilters, dispatch]);
71
- const setVisibleColumns = useCallback((columns) => dispatch({
72
- type: "SET_VISIBLE_COLUMNS",
73
- payload: columns
74
- }), [dispatch]);
75
- const setShowColumnSelector = useCallback((show) => {
76
- if (show !== showColumnSelector) dispatch({
77
- type: "TOGGLE_COLUMN_SELECTOR"
78
- });
79
- }, [showColumnSelector, dispatch]);
80
- const setSearchFields = useCallback((fields) => dispatch({
81
- type: "SET_SEARCH_FIELDS",
82
- payload: fields
83
- }), [dispatch]);
84
- const setShowSearchFieldSelector = useCallback((show) => {
85
- if (show !== showSearchFieldSelector) dispatch({
86
- type: "TOGGLE_SEARCH_FIELD_SELECTOR"
87
- });
88
- }, [showSearchFieldSelector, dispatch]);
49
+ useCallback(
50
+ (skip2) => dispatch({ type: "SET_SKIP", payload: skip2 }),
51
+ [dispatch]
52
+ );
53
+ const setFilters = useCallback(
54
+ (filters2) => dispatch({ type: "SET_FILTERS", payload: filters2 }),
55
+ [dispatch]
56
+ );
57
+ const setShowFilters = useCallback(
58
+ (show) => {
59
+ if (show !== showFilters) dispatch({ type: "TOGGLE_FILTERS" });
60
+ },
61
+ [showFilters, dispatch]
62
+ );
63
+ const setVisibleColumns = useCallback(
64
+ (columns) => dispatch({ type: "SET_VISIBLE_COLUMNS", payload: columns }),
65
+ [dispatch]
66
+ );
67
+ const setShowColumnSelector = useCallback(
68
+ (show) => {
69
+ if (show !== showColumnSelector) dispatch({ type: "TOGGLE_COLUMN_SELECTOR" });
70
+ },
71
+ [showColumnSelector, dispatch]
72
+ );
73
+ const setSearchFields = useCallback(
74
+ (fields) => dispatch({ type: "SET_SEARCH_FIELDS", payload: fields }),
75
+ [dispatch]
76
+ );
77
+ const setShowSearchFieldSelector = useCallback(
78
+ (show) => {
79
+ if (show !== showSearchFieldSelector) dispatch({ type: "TOGGLE_SEARCH_FIELD_SELECTOR" });
80
+ },
81
+ [showSearchFieldSelector, dispatch]
82
+ );
89
83
  useEffect(() => {
90
84
  const timer = setTimeout(() => {
91
- dispatch({
92
- type: "SET_DEBOUNCED_SEARCH",
93
- payload: state.search
94
- });
85
+ dispatch({ type: "SET_DEBOUNCED_SEARCH", payload: state.search });
95
86
  }, 500);
96
87
  return () => clearTimeout(timer);
97
88
  }, [state.search]);
@@ -111,14 +102,14 @@ function AdminDataListPage({
111
102
  const filters2 = {};
112
103
  for (const [key, value] of searchParams.entries()) {
113
104
  if (key !== "page" && key !== "search" && key !== "sort") {
114
- const relationField = model.fields.find((f) => {
115
- var _a;
116
- return f.relationName && !f.isList && ((_a = f.relationFromFields) == null ? void 0 : _a[0]) === key;
117
- });
105
+ const relationField = model.fields.find(
106
+ (f) => {
107
+ var _a;
108
+ return f.relationName && !f.isList && ((_a = f.relationFromFields) == null ? void 0 : _a[0]) === key;
109
+ }
110
+ );
118
111
  if (relationField) {
119
- filters2[relationField.name] = {
120
- id: value
121
- };
112
+ filters2[relationField.name] = { id: value };
122
113
  } else {
123
114
  const scalarField = model.fields.find((f) => f.name === key && !f.relationName);
124
115
  if (scalarField) {
@@ -131,18 +122,17 @@ function AdminDataListPage({
131
122
  }, [searchParams, model]);
132
123
  const hasUrlFilters = Object.keys(urlFilters).length > 0;
133
124
  const documents = useMemo(() => {
134
- if (!model) return {
135
- query: void 0,
136
- listQuery: void 0,
137
- update: void 0,
138
- delete: void 0,
139
- create: void 0
140
- };
125
+ if (!model)
126
+ return {
127
+ query: void 0,
128
+ listQuery: void 0,
129
+ update: void 0,
130
+ delete: void 0,
131
+ create: void 0
132
+ };
141
133
  return getAdminDocuments(sdk, model);
142
134
  }, [sdk, model]);
143
- const {
144
- listQuery: query
145
- } = documents;
135
+ const { listQuery: query } = documents;
146
136
  const dataPath = useMemo(() => {
147
137
  return (model == null ? void 0 : model.pluralModelPropertyName) || pluralParam.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
148
138
  }, [model, pluralParam]);
@@ -186,70 +176,58 @@ function AdminDataListPage({
186
176
  setVisibleColumns(filteredCols);
187
177
  const storedSort = AdminLocalStorage.getSortPreference(model.name);
188
178
  const sortFieldValid = storedSort && (storedSort.orderBy === "id" || fieldNames.includes(storedSort.orderBy));
189
- const nextSort = sortFieldValid ? storedSort : {
190
- orderBy: "id",
191
- orderDirection: "desc"
192
- };
193
- dispatch({
194
- type: "SET_SORT",
195
- payload: nextSort
196
- });
179
+ const nextSort = sortFieldValid ? storedSort : { orderBy: "id", orderDirection: "desc" };
180
+ dispatch({ type: "SET_SORT", payload: nextSort });
197
181
  const storedSearch = AdminLocalStorage.getSearchFields(model.name);
198
182
  const defaults = getDefaultSearchFields(searchableFieldNames);
199
183
  const filteredSearch = (storedSearch || defaults).filter((f) => searchableFieldNames.includes(f));
200
184
  setSearchFields(filteredSearch);
201
- dispatch({
202
- type: "SET_SEARCH",
203
- payload: ""
204
- });
205
- dispatch({
206
- type: "SET_DEBOUNCED_SEARCH",
207
- payload: ""
208
- });
209
- dispatch({
210
- type: "RESET_FILTERS"
211
- });
212
- dispatch({
213
- type: "RESET_PAGINATION"
214
- });
185
+ dispatch({ type: "SET_SEARCH", payload: "" });
186
+ dispatch({ type: "SET_DEBOUNCED_SEARCH", payload: "" });
187
+ dispatch({ type: "RESET_FILTERS" });
188
+ dispatch({ type: "RESET_PAGINATION" });
215
189
  if (hasUrlFilters) {
216
- dispatch({
217
- type: "SET_FILTERS",
218
- payload: urlFilters
219
- });
220
- dispatch({
221
- type: "SET_SHOW_FILTERS",
222
- payload: true
223
- });
190
+ dispatch({ type: "SET_FILTERS", payload: urlFilters });
191
+ dispatch({ type: "SET_SHOW_FILTERS", payload: true });
224
192
  }
225
193
  }, [model == null ? void 0 : model.name, fieldNames, searchableFieldNames, getDefaultSearchFields, setVisibleColumns, setSearchFields, dispatch, urlFilters]);
226
- const setSortSafely = useCallback((newSort) => {
227
- const resolvedSort = typeof newSort === "function" ? newSort(sort) : newSort;
228
- if (resolvedSort.orderBy !== sort.orderBy || resolvedSort.orderDirection !== sort.orderDirection) {
229
- dispatch({
230
- type: "SET_SORT",
231
- payload: resolvedSort
232
- });
233
- if (model) {
234
- AdminLocalStorage.setSortPreference(model.name, resolvedSort);
194
+ const setSortSafely = useCallback(
195
+ (newSort) => {
196
+ const resolvedSort = typeof newSort === "function" ? newSort(sort) : newSort;
197
+ if (resolvedSort.orderBy !== sort.orderBy || resolvedSort.orderDirection !== sort.orderDirection) {
198
+ dispatch({ type: "SET_SORT", payload: resolvedSort });
199
+ if (model) {
200
+ AdminLocalStorage.setSortPreference(model.name, resolvedSort);
201
+ }
235
202
  }
236
- }
237
- }, [sort.orderBy, sort.orderDirection, model, dispatch]);
238
- const handleClickOutside = useCallback((event) => {
239
- const target = event.target;
240
- if (showColumnSelector) {
241
- const columnSelector2 = document.querySelector('[data-dropdown="column-selector"]');
242
- if (columnSelector2 && !columnSelector2.contains(target)) {
243
- setShowColumnSelector(false);
203
+ },
204
+ [sort.orderBy, sort.orderDirection, model, dispatch]
205
+ );
206
+ const handleClickOutside = useCallback(
207
+ (event) => {
208
+ const target = event.target;
209
+ if (showColumnSelector) {
210
+ const columnSelector2 = document.querySelector('[data-dropdown="column-selector"]');
211
+ if (columnSelector2 && !columnSelector2.contains(target)) {
212
+ setShowColumnSelector(false);
213
+ }
244
214
  }
245
- }
246
- if (showSearchFieldSelector) {
247
- const searchFieldSelector2 = document.querySelector('[data-dropdown="search-field-selector"]');
248
- if (searchFieldSelector2 && !searchFieldSelector2.contains(target)) {
249
- setShowSearchFieldSelector(false);
215
+ if (showSearchFieldSelector) {
216
+ const searchFieldSelector2 = document.querySelector(
217
+ '[data-dropdown="search-field-selector"]'
218
+ );
219
+ if (searchFieldSelector2 && !searchFieldSelector2.contains(target)) {
220
+ setShowSearchFieldSelector(false);
221
+ }
250
222
  }
251
- }
252
- }, [showColumnSelector, showSearchFieldSelector, setShowColumnSelector, setShowSearchFieldSelector]);
223
+ },
224
+ [
225
+ showColumnSelector,
226
+ showSearchFieldSelector,
227
+ setShowColumnSelector,
228
+ setShowSearchFieldSelector
229
+ ]
230
+ );
253
231
  useEffect(() => {
254
232
  if (showColumnSelector || showSearchFieldSelector) {
255
233
  document.addEventListener("mousedown", handleClickOutside);
@@ -267,13 +245,7 @@ function AdminDataListPage({
267
245
  filters: Object.keys(filters).length > 0 ? filters : void 0
268
246
  }
269
247
  };
270
- const {
271
- data,
272
- loading,
273
- error,
274
- networkStatus,
275
- refetch
276
- } = useQuery(query ?? sdk.__AdminUsersDocument, {
248
+ const { data, loading, error, networkStatus, refetch } = useQuery(query ?? sdk.__AdminUsersDocument, {
277
249
  variables,
278
250
  skip: !model || !query,
279
251
  errorPolicy: "all",
@@ -286,11 +258,7 @@ function AdminDataListPage({
286
258
  // 30 second timeout
287
259
  }
288
260
  });
289
- const {
290
- validatedItems,
291
- validatedPagination,
292
- dataError
293
- } = useMemo(() => {
261
+ const { validatedItems, validatedPagination, dataError } = useMemo(() => {
294
262
  var _a, _b;
295
263
  if (error) {
296
264
  const apolloError = error;
@@ -350,479 +318,497 @@ function AdminDataListPage({
350
318
  const items = validatedItems;
351
319
  const pagination = validatedPagination;
352
320
  if (!model) {
353
- return /* @__PURE__ */ React.createElement("div", { className: "min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8", __self: this, __source: {
354
- fileName: _jsxFileName,
355
- lineNumber: 448,
356
- columnNumber: 7
357
- } }, /* @__PURE__ */ React.createElement("div", { className: "mt-8 sm:mx-auto sm:w-full sm:max-w-md", __self: this, __source: {
358
- fileName: _jsxFileName,
359
- lineNumber: 449,
360
- columnNumber: 9
361
- } }, /* @__PURE__ */ React.createElement("div", { className: "bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10", __self: this, __source: {
362
- fileName: _jsxFileName,
363
- lineNumber: 450,
364
- columnNumber: 11
365
- } }, /* @__PURE__ */ React.createElement("div", { className: "text-center", __self: this, __source: {
366
- fileName: _jsxFileName,
367
- lineNumber: 451,
368
- columnNumber: 13
369
- } }, /* @__PURE__ */ React.createElement("svg", { className: "mx-auto h-12 w-12 text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
370
- fileName: _jsxFileName,
371
- lineNumber: 452,
372
- columnNumber: 15
373
- } }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", __self: this, __source: {
374
- fileName: _jsxFileName,
375
- lineNumber: 458,
376
- columnNumber: 17
377
- } })), /* @__PURE__ */ React.createElement("h2", { className: "mt-4 text-lg font-medium text-gray-900", __self: this, __source: {
378
- fileName: _jsxFileName,
379
- lineNumber: 465,
380
- columnNumber: 15
381
- } }, "Invalid Data Type"), /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-sm text-gray-600", __self: this, __source: {
382
- fileName: _jsxFileName,
383
- lineNumber: 466,
384
- columnNumber: 15
385
- } }, 'The data type "', pluralParam, '" is not recognized.'), /* @__PURE__ */ React.createElement("div", { className: "mt-6", __self: this, __source: {
386
- fileName: _jsxFileName,
387
- lineNumber: 469,
388
- columnNumber: 15
389
- } }, /* @__PURE__ */ React.createElement(Link, { to: basePath, className: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-web hover:bg-green-web-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web", __self: this, __source: {
390
- fileName: _jsxFileName,
391
- lineNumber: 470,
392
- columnNumber: 17
393
- } }, "Return to Data Browser"))))));
321
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsx("div", { className: "mt-8 sm:mx-auto sm:w-full sm:max-w-md", children: /* @__PURE__ */ jsx("div", { className: "bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
322
+ /* @__PURE__ */ jsx(
323
+ "svg",
324
+ {
325
+ className: "mx-auto h-12 w-12 text-red-400",
326
+ fill: "none",
327
+ stroke: "currentColor",
328
+ viewBox: "0 0 24 24",
329
+ children: /* @__PURE__ */ jsx(
330
+ "path",
331
+ {
332
+ strokeLinecap: "round",
333
+ strokeLinejoin: "round",
334
+ strokeWidth: 2,
335
+ d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
336
+ }
337
+ )
338
+ }
339
+ ),
340
+ /* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-medium text-gray-900", children: "Invalid Data Type" }),
341
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm text-gray-600", children: [
342
+ 'The data type "',
343
+ pluralParam,
344
+ '" is not recognized.'
345
+ ] }),
346
+ /* @__PURE__ */ jsx("div", { className: "mt-6", children: /* @__PURE__ */ jsx(
347
+ Link,
348
+ {
349
+ to: basePath,
350
+ className: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-web hover:bg-green-web-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web",
351
+ children: "Return to Data Browser"
352
+ }
353
+ ) })
354
+ ] }) }) }) });
394
355
  }
395
356
  if (!query) {
396
- return /* @__PURE__ */ React.createElement("div", { className: "min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8", __self: this, __source: {
397
- fileName: _jsxFileName,
398
- lineNumber: 486,
399
- columnNumber: 7
400
- } }, /* @__PURE__ */ React.createElement("div", { className: "mt-8 sm:mx-auto sm:w-full sm:max-w-md", __self: this, __source: {
401
- fileName: _jsxFileName,
402
- lineNumber: 487,
403
- columnNumber: 9
404
- } }, /* @__PURE__ */ React.createElement("div", { className: "bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10", __self: this, __source: {
405
- fileName: _jsxFileName,
406
- lineNumber: 488,
407
- columnNumber: 11
408
- } }, /* @__PURE__ */ React.createElement("div", { className: "text-center", __self: this, __source: {
409
- fileName: _jsxFileName,
410
- lineNumber: 489,
411
- columnNumber: 13
412
- } }, /* @__PURE__ */ React.createElement("svg", { className: "mx-auto h-12 w-12 text-yellow-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
413
- fileName: _jsxFileName,
414
- lineNumber: 490,
415
- columnNumber: 15
416
- } }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.728-.833-2.498 0L5.316 15c-.77.833.192 2.5 1.732 2.5z", __self: this, __source: {
417
- fileName: _jsxFileName,
418
- lineNumber: 496,
419
- columnNumber: 17
420
- } })), /* @__PURE__ */ React.createElement("h2", { className: "mt-4 text-lg font-medium text-gray-900", __self: this, __source: {
421
- fileName: _jsxFileName,
422
- lineNumber: 503,
423
- columnNumber: 15
424
- } }, "GraphQL Schema Not Available"), /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-sm text-gray-600", __self: this, __source: {
425
- fileName: _jsxFileName,
426
- lineNumber: 506,
427
- columnNumber: 15
428
- } }, 'No GraphQL query found for "', model.name, '". The admin schema may need to be regenerated.'), /* @__PURE__ */ React.createElement("div", { className: "mt-6 space-y-3", __self: this, __source: {
429
- fileName: _jsxFileName,
430
- lineNumber: 510,
431
- columnNumber: 15
432
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => window.location.reload(), className: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-web hover:bg-green-web-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web", __self: this, __source: {
433
- fileName: _jsxFileName,
434
- lineNumber: 511,
435
- columnNumber: 17
436
- } }, "Reload Page"), /* @__PURE__ */ React.createElement(Link, { to: basePath, className: "w-full flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web", __self: this, __source: {
437
- fileName: _jsxFileName,
438
- lineNumber: 517,
439
- columnNumber: 17
440
- } }, "Return to Data Browser"))))));
357
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsx("div", { className: "mt-8 sm:mx-auto sm:w-full sm:max-w-md", children: /* @__PURE__ */ jsx("div", { className: "bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
358
+ /* @__PURE__ */ jsx(
359
+ "svg",
360
+ {
361
+ className: "mx-auto h-12 w-12 text-yellow-400",
362
+ fill: "none",
363
+ stroke: "currentColor",
364
+ viewBox: "0 0 24 24",
365
+ children: /* @__PURE__ */ jsx(
366
+ "path",
367
+ {
368
+ strokeLinecap: "round",
369
+ strokeLinejoin: "round",
370
+ strokeWidth: 2,
371
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.728-.833-2.498 0L5.316 15c-.77.833.192 2.5 1.732 2.5z"
372
+ }
373
+ )
374
+ }
375
+ ),
376
+ /* @__PURE__ */ jsx("h2", { className: "mt-4 text-lg font-medium text-gray-900", children: "GraphQL Schema Not Available" }),
377
+ /* @__PURE__ */ jsxs("p", { className: "mt-2 text-sm text-gray-600", children: [
378
+ 'No GraphQL query found for "',
379
+ model.name,
380
+ '". The admin schema may need to be regenerated.'
381
+ ] }),
382
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-3", children: [
383
+ /* @__PURE__ */ jsx(
384
+ "button",
385
+ {
386
+ onClick: () => window.location.reload(),
387
+ className: "w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-web hover:bg-green-web-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web",
388
+ children: "Reload Page"
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx(
392
+ Link,
393
+ {
394
+ to: basePath,
395
+ className: "w-full flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web",
396
+ children: "Return to Data Browser"
397
+ }
398
+ )
399
+ ] })
400
+ ] }) }) }) });
441
401
  }
442
402
  const createLink = `${basePath}/${kebabCase(model.name)}/create`;
443
- const columnSelector = /* @__PURE__ */ React.createElement("div", { className: "relative", "data-dropdown": "column-selector", __self: this, __source: {
444
- fileName: _jsxFileName,
445
- lineNumber: 536,
446
- columnNumber: 5
447
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => setShowColumnSelector(!showColumnSelector), className: "inline-flex items-center px-3 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web", __self: this, __source: {
448
- fileName: _jsxFileName,
449
- lineNumber: 537,
450
- columnNumber: 7
451
- } }, "Columns", /* @__PURE__ */ React.createElement("svg", { className: "-mr-0.5 ml-2 h-4 w-4", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", __self: this, __source: {
452
- fileName: _jsxFileName,
453
- lineNumber: 542,
454
- columnNumber: 9
455
- } }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd", __self: this, __source: {
456
- fileName: _jsxFileName,
457
- lineNumber: 548,
458
- columnNumber: 11
459
- } }))), showColumnSelector && /* @__PURE__ */ React.createElement("div", { className: "absolute right-0 mt-2 w-80 bg-white rounded-md shadow-lg z-50 border border-gray-200", __self: this, __source: {
460
- fileName: _jsxFileName,
461
- lineNumber: 557,
462
- columnNumber: 9
463
- } }, /* @__PURE__ */ React.createElement("div", { className: "p-4", __self: this, __source: {
464
- fileName: _jsxFileName,
465
- lineNumber: 558,
466
- columnNumber: 11
467
- } }, /* @__PURE__ */ React.createElement("h3", { className: "text-sm font-medium text-gray-900 mb-3", __self: this, __source: {
468
- fileName: _jsxFileName,
469
- lineNumber: 559,
470
- columnNumber: 13
471
- } }, "Visible Columns"), /* @__PURE__ */ React.createElement("div", { className: "space-y-2 max-h-64 overflow-y-auto", __self: this, __source: {
472
- fileName: _jsxFileName,
473
- lineNumber: 560,
474
- columnNumber: 13
475
- } }, fieldNames.map((field) => /* @__PURE__ */ React.createElement("label", { key: field, className: "flex items-start gap-2 cursor-pointer", __self: this, __source: {
476
- fileName: _jsxFileName,
477
- lineNumber: 562,
478
- columnNumber: 17
479
- } }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", checked: visibleColumns.includes(field), onChange: (e) => {
480
- const newColumns = e.target.checked ? [...visibleColumns, field] : visibleColumns.filter((col) => col !== field);
481
- setVisibleColumns(newColumns);
482
- AdminLocalStorage.setColumnVisibility(model.name, newColumns);
483
- }, className: "h-4 w-4 mt-0.5 flex-shrink-0 text-green-web focus:ring-green-web border-gray-300 rounded", __self: this, __source: {
484
- fileName: _jsxFileName,
485
- lineNumber: 563,
486
- columnNumber: 19
487
- } }), /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-700 leading-5", __self: this, __source: {
488
- fileName: _jsxFileName,
489
- lineNumber: 575,
490
- columnNumber: 19
491
- } }, formatFieldName(field))))), /* @__PURE__ */ React.createElement("div", { className: "mt-3 pt-3 border-t border-gray-200 flex justify-between", __self: this, __source: {
492
- fileName: _jsxFileName,
493
- lineNumber: 579,
494
- columnNumber: 13
495
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => {
496
- setVisibleColumns(fieldNames);
497
- AdminLocalStorage.setColumnVisibility(model.name, fieldNames);
498
- }, className: "text-xs text-green-web hover:text-green-web-800", __self: this, __source: {
499
- fileName: _jsxFileName,
500
- lineNumber: 580,
501
- columnNumber: 15
502
- } }, "Select All"), /* @__PURE__ */ React.createElement("button", { onClick: () => {
503
- const defaults = fieldNames.slice(0, 8);
504
- setVisibleColumns(defaults);
505
- AdminLocalStorage.setColumnVisibility(model.name, defaults);
506
- }, className: "text-xs text-gray-600 hover:text-gray-800", __self: this, __source: {
507
- fileName: _jsxFileName,
508
- lineNumber: 589,
509
- columnNumber: 15
510
- } }, "Reset to Defaults")))));
511
- const searchFieldSelector = /* @__PURE__ */ React.createElement("div", { className: "relative", "data-dropdown": "search-field-selector", __self: this, __source: {
512
- fileName: _jsxFileName,
513
- lineNumber: 608,
514
- columnNumber: 5
515
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => setShowSearchFieldSelector(!showSearchFieldSelector), className: "h-full px-3 border-l border-gray-300 text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600", "aria-label": "Configure search fields", __self: this, __source: {
516
- fileName: _jsxFileName,
517
- lineNumber: 609,
518
- columnNumber: 7
519
- } }, /* @__PURE__ */ React.createElement("svg", { className: "h-4 w-4", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", __self: this, __source: {
520
- fileName: _jsxFileName,
521
- lineNumber: 614,
522
- columnNumber: 9
523
- } }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M3 3a1 1 0 000 2v8a2 2 0 002 2h2.586l-1.293 1.293a1 1 0 101.414 1.414L10 15.414l2.293 2.293a1 1 0 001.414-1.414L12.414 15H15a2 2 0 002-2V5a1 1 0 100-2H3zm11.707 4.707a1 1 0 00-1.414-1.414L10 9.586 8.707 8.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clipRule: "evenodd", __self: this, __source: {
524
- fileName: _jsxFileName,
525
- lineNumber: 620,
526
- columnNumber: 11
527
- } }))), showSearchFieldSelector && /* @__PURE__ */ React.createElement("div", { className: "absolute right-0 mt-2 w-72 bg-white rounded-md shadow-lg z-50 border border-gray-200", __self: this, __source: {
528
- fileName: _jsxFileName,
529
- lineNumber: 629,
530
- columnNumber: 9
531
- } }, /* @__PURE__ */ React.createElement("div", { className: "p-4", __self: this, __source: {
532
- fileName: _jsxFileName,
533
- lineNumber: 630,
534
- columnNumber: 11
535
- } }, /* @__PURE__ */ React.createElement("h3", { className: "text-sm font-medium text-gray-900 mb-3", __self: this, __source: {
536
- fileName: _jsxFileName,
537
- lineNumber: 631,
538
- columnNumber: 13
539
- } }, "Search Fields"), searchableFieldNames.length > 0 ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "space-y-2 max-h-48 overflow-y-auto", __self: this, __source: {
540
- fileName: _jsxFileName,
541
- lineNumber: 634,
542
- columnNumber: 17
543
- } }, searchableFieldNames.map((field) => /* @__PURE__ */ React.createElement("label", { key: field, className: "flex items-start gap-2 cursor-pointer", __self: this, __source: {
544
- fileName: _jsxFileName,
545
- lineNumber: 636,
546
- columnNumber: 21
547
- } }, /* @__PURE__ */ React.createElement("input", { type: "checkbox", checked: searchFields.includes(field), onChange: (e) => {
548
- const newFields = e.target.checked ? [...searchFields, field] : searchFields.filter((f) => f !== field);
549
- setSearchFields(newFields);
550
- AdminLocalStorage.setSearchFields(model.name, newFields);
551
- }, className: "h-4 w-4 mt-0.5 flex-shrink-0 text-green-web focus:ring-green-web border-gray-300 rounded", __self: this, __source: {
552
- fileName: _jsxFileName,
553
- lineNumber: 637,
554
- columnNumber: 23
555
- } }), /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-700 leading-5", __self: this, __source: {
556
- fileName: _jsxFileName,
557
- lineNumber: 649,
558
- columnNumber: 23
559
- } }, formatFieldName(field))))), /* @__PURE__ */ React.createElement("div", { className: "mt-3 pt-3 border-t border-gray-200 flex justify-between", __self: this, __source: {
560
- fileName: _jsxFileName,
561
- lineNumber: 655,
562
- columnNumber: 17
563
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => {
564
- setSearchFields(searchableFieldNames);
565
- AdminLocalStorage.setSearchFields(model.name, searchableFieldNames);
566
- }, className: "text-xs text-green-web hover:text-green-web-800 mr-3", __self: this, __source: {
567
- fileName: _jsxFileName,
568
- lineNumber: 656,
569
- columnNumber: 19
570
- } }, "Select All"), /* @__PURE__ */ React.createElement("button", { onClick: () => {
571
- const defaults = getDefaultSearchFields(searchableFieldNames);
572
- setSearchFields(defaults);
573
- AdminLocalStorage.setSearchFields(model.name, defaults);
574
- }, className: "text-xs text-gray-600 hover:text-gray-800", __self: this, __source: {
575
- fileName: _jsxFileName,
576
- lineNumber: 665,
577
- columnNumber: 19
578
- } }, "Reset to Defaults"))) : /* @__PURE__ */ React.createElement("div", { className: "text-sm text-gray-500", __self: this, __source: {
579
- fileName: _jsxFileName,
580
- lineNumber: 678,
581
- columnNumber: 15
582
- } }, "No searchable text fields available"))));
583
- const filterPanel = showFilters && /* @__PURE__ */ React.createElement("div", { className: "mb-4 bg-gray-50 border border-gray-200 rounded-lg p-4", __self: this, __source: {
584
- fileName: _jsxFileName,
585
- lineNumber: 688,
586
- columnNumber: 5
587
- } }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-between mb-3", __self: this, __source: {
588
- fileName: _jsxFileName,
589
- lineNumber: 689,
590
- columnNumber: 7
591
- } }, /* @__PURE__ */ React.createElement("h3", { className: "text-sm font-medium text-gray-900", __self: this, __source: {
592
- fileName: _jsxFileName,
593
- lineNumber: 690,
594
- columnNumber: 9
595
- } }, "Filters"), /* @__PURE__ */ React.createElement("div", { className: "flex items-center space-x-2", __self: this, __source: {
596
- fileName: _jsxFileName,
597
- lineNumber: 691,
598
- columnNumber: 9
599
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => {
600
- setFilters({});
601
- dispatch({
602
- type: "RESET_PAGINATION"
603
- });
604
- }, className: "text-xs text-gray-600 hover:text-gray-800", __self: this, __source: {
605
- fileName: _jsxFileName,
606
- lineNumber: 692,
607
- columnNumber: 11
608
- } }, "Clear All"), /* @__PURE__ */ React.createElement("button", { onClick: () => setShowFilters(false), className: "text-gray-400 hover:text-gray-600", __self: this, __source: {
609
- fileName: _jsxFileName,
610
- lineNumber: 701,
611
- columnNumber: 11
612
- } }, /* @__PURE__ */ React.createElement("svg", { className: "h-5 w-5", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", __self: this, __source: {
613
- fileName: _jsxFileName,
614
- lineNumber: 705,
615
- columnNumber: 13
616
- } }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z", clipRule: "evenodd", __self: this, __source: {
617
- fileName: _jsxFileName,
618
- lineNumber: 711,
619
- columnNumber: 15
620
- } }))))), /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", __self: this, __source: {
621
- fileName: _jsxFileName,
622
- lineNumber: 721,
623
- columnNumber: 7
624
- } }, filterableFieldNames.map((fieldName) => {
625
- const field = model.fields.find((f) => f.name === fieldName);
626
- if (!field) return null;
627
- const currentValue = filters[fieldName];
628
- const handleChange = (value) => {
629
- const newFilters = {
630
- ...filters
403
+ const columnSelector = /* @__PURE__ */ jsxs("div", { className: "relative", "data-dropdown": "column-selector", children: [
404
+ /* @__PURE__ */ jsxs(
405
+ "button",
406
+ {
407
+ onClick: () => setShowColumnSelector(!showColumnSelector),
408
+ className: "inline-flex items-center px-3 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web",
409
+ children: [
410
+ "Columns",
411
+ /* @__PURE__ */ jsx(
412
+ "svg",
413
+ {
414
+ className: "-mr-0.5 ml-2 h-4 w-4",
415
+ xmlns: "http://www.w3.org/2000/svg",
416
+ viewBox: "0 0 20 20",
417
+ fill: "currentColor",
418
+ children: /* @__PURE__ */ jsx(
419
+ "path",
420
+ {
421
+ fillRule: "evenodd",
422
+ d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z",
423
+ clipRule: "evenodd"
424
+ }
425
+ )
426
+ }
427
+ )
428
+ ]
429
+ }
430
+ ),
431
+ showColumnSelector && /* @__PURE__ */ jsx("div", { className: "absolute right-0 mt-2 w-80 bg-white rounded-md shadow-lg z-50 border border-gray-200", children: /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
432
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900 mb-3", children: "Visible Columns" }),
433
+ /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-64 overflow-y-auto", children: fieldNames.map((field) => /* @__PURE__ */ jsxs("label", { className: "flex items-start gap-2 cursor-pointer", children: [
434
+ /* @__PURE__ */ jsx(
435
+ "input",
436
+ {
437
+ type: "checkbox",
438
+ checked: visibleColumns.includes(field),
439
+ onChange: (e) => {
440
+ const newColumns = e.target.checked ? [...visibleColumns, field] : visibleColumns.filter((col) => col !== field);
441
+ setVisibleColumns(newColumns);
442
+ AdminLocalStorage.setColumnVisibility(model.name, newColumns);
443
+ },
444
+ className: "h-4 w-4 mt-0.5 flex-shrink-0 text-green-web focus:ring-green-web border-gray-300 rounded"
445
+ }
446
+ ),
447
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700 leading-5", children: formatFieldName(field) })
448
+ ] }, field)) }),
449
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 pt-3 border-t border-gray-200 flex justify-between", children: [
450
+ /* @__PURE__ */ jsx(
451
+ "button",
452
+ {
453
+ onClick: () => {
454
+ setVisibleColumns(fieldNames);
455
+ AdminLocalStorage.setColumnVisibility(model.name, fieldNames);
456
+ },
457
+ className: "text-xs text-green-web hover:text-green-web-800",
458
+ children: "Select All"
459
+ }
460
+ ),
461
+ /* @__PURE__ */ jsx(
462
+ "button",
463
+ {
464
+ onClick: () => {
465
+ const defaults = fieldNames.slice(0, 8);
466
+ setVisibleColumns(defaults);
467
+ AdminLocalStorage.setColumnVisibility(model.name, defaults);
468
+ },
469
+ className: "text-xs text-gray-600 hover:text-gray-800",
470
+ children: "Reset to Defaults"
471
+ }
472
+ )
473
+ ] })
474
+ ] }) })
475
+ ] });
476
+ const searchFieldSelector = /* @__PURE__ */ jsxs("div", { className: "relative", "data-dropdown": "search-field-selector", children: [
477
+ /* @__PURE__ */ jsx(
478
+ "button",
479
+ {
480
+ onClick: () => setShowSearchFieldSelector(!showSearchFieldSelector),
481
+ className: "h-full px-3 border-l border-gray-300 text-gray-400 hover:text-gray-600 focus:outline-none focus:text-gray-600",
482
+ "aria-label": "Configure search fields",
483
+ children: /* @__PURE__ */ jsx(
484
+ "svg",
485
+ {
486
+ className: "h-4 w-4",
487
+ xmlns: "http://www.w3.org/2000/svg",
488
+ viewBox: "0 0 20 20",
489
+ fill: "currentColor",
490
+ children: /* @__PURE__ */ jsx(
491
+ "path",
492
+ {
493
+ fillRule: "evenodd",
494
+ d: "M3 3a1 1 0 000 2v8a2 2 0 002 2h2.586l-1.293 1.293a1 1 0 101.414 1.414L10 15.414l2.293 2.293a1 1 0 001.414-1.414L12.414 15H15a2 2 0 002-2V5a1 1 0 100-2H3zm11.707 4.707a1 1 0 00-1.414-1.414L10 9.586 8.707 8.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",
495
+ clipRule: "evenodd"
496
+ }
497
+ )
498
+ }
499
+ )
500
+ }
501
+ ),
502
+ showSearchFieldSelector && /* @__PURE__ */ jsx("div", { className: "absolute right-0 mt-2 w-72 bg-white rounded-md shadow-lg z-50 border border-gray-200", children: /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
503
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900 mb-3", children: "Search Fields" }),
504
+ searchableFieldNames.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
505
+ /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-48 overflow-y-auto", children: searchableFieldNames.map((field) => /* @__PURE__ */ jsxs("label", { className: "flex items-start gap-2 cursor-pointer", children: [
506
+ /* @__PURE__ */ jsx(
507
+ "input",
508
+ {
509
+ type: "checkbox",
510
+ checked: searchFields.includes(field),
511
+ onChange: (e) => {
512
+ const newFields = e.target.checked ? [...searchFields, field] : searchFields.filter((f) => f !== field);
513
+ setSearchFields(newFields);
514
+ AdminLocalStorage.setSearchFields(model.name, newFields);
515
+ },
516
+ className: "h-4 w-4 mt-0.5 flex-shrink-0 text-green-web focus:ring-green-web border-gray-300 rounded"
517
+ }
518
+ ),
519
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700 leading-5", children: formatFieldName(field) })
520
+ ] }, field)) }),
521
+ /* @__PURE__ */ jsxs("div", { className: "mt-3 pt-3 border-t border-gray-200 flex justify-between", children: [
522
+ /* @__PURE__ */ jsx(
523
+ "button",
524
+ {
525
+ onClick: () => {
526
+ setSearchFields(searchableFieldNames);
527
+ AdminLocalStorage.setSearchFields(model.name, searchableFieldNames);
528
+ },
529
+ className: "text-xs text-green-web hover:text-green-web-800 mr-3",
530
+ children: "Select All"
531
+ }
532
+ ),
533
+ /* @__PURE__ */ jsx(
534
+ "button",
535
+ {
536
+ onClick: () => {
537
+ const defaults = getDefaultSearchFields(searchableFieldNames);
538
+ setSearchFields(defaults);
539
+ AdminLocalStorage.setSearchFields(model.name, defaults);
540
+ },
541
+ className: "text-xs text-gray-600 hover:text-gray-800",
542
+ children: "Reset to Defaults"
543
+ }
544
+ )
545
+ ] })
546
+ ] }) : /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500", children: "No searchable text fields available" })
547
+ ] }) })
548
+ ] });
549
+ const filterPanel = showFilters && /* @__PURE__ */ jsxs("div", { className: "mb-4 bg-gray-50 border border-gray-200 rounded-lg p-4", children: [
550
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
551
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900", children: "Filters" }),
552
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
553
+ /* @__PURE__ */ jsx(
554
+ "button",
555
+ {
556
+ onClick: () => {
557
+ setFilters({});
558
+ dispatch({ type: "RESET_PAGINATION" });
559
+ },
560
+ className: "text-xs text-gray-600 hover:text-gray-800",
561
+ children: "Clear All"
562
+ }
563
+ ),
564
+ /* @__PURE__ */ jsx(
565
+ "button",
566
+ {
567
+ onClick: () => setShowFilters(false),
568
+ className: "text-gray-400 hover:text-gray-600",
569
+ children: /* @__PURE__ */ jsx(
570
+ "svg",
571
+ {
572
+ className: "h-5 w-5",
573
+ xmlns: "http://www.w3.org/2000/svg",
574
+ viewBox: "0 0 20 20",
575
+ fill: "currentColor",
576
+ children: /* @__PURE__ */ jsx(
577
+ "path",
578
+ {
579
+ fillRule: "evenodd",
580
+ d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
581
+ clipRule: "evenodd"
582
+ }
583
+ )
584
+ }
585
+ )
586
+ }
587
+ )
588
+ ] })
589
+ ] }),
590
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: filterableFieldNames.map((fieldName) => {
591
+ const field = model.fields.find((f) => f.name === fieldName);
592
+ if (!field) return null;
593
+ const currentValue = filters[fieldName];
594
+ const handleChange = (value) => {
595
+ const newFilters = { ...filters };
596
+ if (value === void 0 || value === null || value === "") {
597
+ delete newFilters[fieldName];
598
+ } else {
599
+ newFilters[fieldName] = value;
600
+ }
601
+ setFilters(newFilters);
602
+ dispatch({ type: "RESET_PAGINATION" });
631
603
  };
632
- if (value === void 0 || value === null || value === "") {
633
- delete newFilters[fieldName];
634
- } else {
635
- newFilters[fieldName] = value;
604
+ if (field.relationName && !field.isList) {
605
+ return /* @__PURE__ */ jsx(
606
+ RelationFilterField,
607
+ {
608
+ fieldName,
609
+ relatedModelName: field.type,
610
+ currentValue,
611
+ onChange: handleChange
612
+ },
613
+ fieldName
614
+ );
636
615
  }
637
- setFilters(newFilters);
638
- dispatch({
639
- type: "RESET_PAGINATION"
640
- });
641
- };
642
- if (field.relationName && !field.isList) {
643
- return /* @__PURE__ */ React.createElement(RelationFilterField, { key: fieldName, fieldName, relatedModelName: field.type, currentValue, onChange: handleChange, __self: this, __source: {
644
- fileName: _jsxFileName,
645
- lineNumber: 741,
646
- columnNumber: 15
647
- } });
648
- }
649
- if (field.type.toLowerCase() === "datetime" || field.type.toLowerCase() === "date") {
650
- return /* @__PURE__ */ React.createElement(DateRangeFilter, { key: fieldName, fieldName, currentValue, onChange: handleChange, __self: this, __source: {
651
- fileName: _jsxFileName,
652
- lineNumber: 754,
653
- columnNumber: 15
654
- } });
655
- }
656
- if (["int", "bigint", "float", "decimal"].includes(field.type.toLowerCase())) {
657
- return /* @__PURE__ */ React.createElement(NumberRangeFilter, { key: fieldName, fieldName, fieldType: field.type.toLowerCase(), currentValue, onChange: handleChange, __self: this, __source: {
658
- fileName: _jsxFileName,
659
- lineNumber: 766,
660
- columnNumber: 15
661
- } });
662
- }
663
- if (field.kind === "enum") {
664
- const enumValues = getEnumValues(field.type);
665
- if (enumValues) {
666
- return /* @__PURE__ */ React.createElement("div", { key: fieldName, className: "space-y-1", __self: this, __source: {
667
- fileName: _jsxFileName,
668
- lineNumber: 781,
669
- columnNumber: 17
670
- } }, /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700", __self: this, __source: {
671
- fileName: _jsxFileName,
672
- lineNumber: 782,
673
- columnNumber: 19
674
- } }, formatFieldName(fieldName)), /* @__PURE__ */ React.createElement("select", { value: typeof currentValue === "string" ? currentValue : "", onChange: (e) => handleChange(e.target.value || void 0), className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm", __self: this, __source: {
675
- fileName: _jsxFileName,
676
- lineNumber: 785,
677
- columnNumber: 19
678
- } }, /* @__PURE__ */ React.createElement("option", { value: "", __self: this, __source: {
679
- fileName: _jsxFileName,
680
- lineNumber: 790,
681
- columnNumber: 21
682
- } }, "All"), enumValues.map((val) => /* @__PURE__ */ React.createElement("option", { key: val, value: val, __self: this, __source: {
683
- fileName: _jsxFileName,
684
- lineNumber: 792,
685
- columnNumber: 23
686
- } }, val))));
616
+ if (field.type.toLowerCase() === "datetime" || field.type.toLowerCase() === "date") {
617
+ return /* @__PURE__ */ jsx(
618
+ DateRangeFilter,
619
+ {
620
+ fieldName,
621
+ currentValue,
622
+ onChange: handleChange
623
+ },
624
+ fieldName
625
+ );
687
626
  }
688
- }
689
- if (field.type.toLowerCase() === "boolean") {
690
- return /* @__PURE__ */ React.createElement("div", { key: fieldName, className: "space-y-1", __self: this, __source: {
691
- fileName: _jsxFileName,
692
- lineNumber: 805,
693
- columnNumber: 15
694
- } }, /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700", __self: this, __source: {
695
- fileName: _jsxFileName,
696
- lineNumber: 806,
697
- columnNumber: 17
698
- } }, formatFieldName(fieldName)), /* @__PURE__ */ React.createElement("select", { value: currentValue === void 0 || currentValue === null ? "" : currentValue.toString(), onChange: (e) => {
699
- const value = e.target.value;
700
- handleChange(value === "" ? void 0 : value === "true");
701
- }, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm", __self: this, __source: {
702
- fileName: _jsxFileName,
703
- lineNumber: 809,
704
- columnNumber: 17
705
- } }, /* @__PURE__ */ React.createElement("option", { value: "", __self: this, __source: {
706
- fileName: _jsxFileName,
707
- lineNumber: 817,
708
- columnNumber: 19
709
- } }, "All"), /* @__PURE__ */ React.createElement("option", { value: "true", __self: this, __source: {
710
- fileName: _jsxFileName,
711
- lineNumber: 818,
712
- columnNumber: 19
713
- } }, "Yes"), /* @__PURE__ */ React.createElement("option", { value: "false", __self: this, __source: {
714
- fileName: _jsxFileName,
715
- lineNumber: 819,
716
- columnNumber: 19
717
- } }, "No")));
718
- }
719
- return /* @__PURE__ */ React.createElement("div", { key: fieldName, className: "space-y-1", __self: this, __source: {
720
- fileName: _jsxFileName,
721
- lineNumber: 827,
722
- columnNumber: 13
723
- } }, /* @__PURE__ */ React.createElement("label", { className: "block text-sm font-medium text-gray-700", __self: this, __source: {
724
- fileName: _jsxFileName,
725
- lineNumber: 828,
726
- columnNumber: 15
727
- } }, formatFieldName(fieldName)), /* @__PURE__ */ React.createElement("input", { type: "text", value: typeof currentValue === "string" ? currentValue : "", onChange: (e) => handleChange(e.target.value || void 0), placeholder: `Filter by ${formatFieldName(fieldName).toLowerCase()}...`, className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm", __self: this, __source: {
728
- fileName: _jsxFileName,
729
- lineNumber: 831,
730
- columnNumber: 15
731
- } }));
732
- })));
733
- const searchFilter = /* @__PURE__ */ React.createElement("div", { className: "mb-4 flex items-center justify-between", __self: this, __source: {
734
- fileName: _jsxFileName,
735
- lineNumber: 846,
736
- columnNumber: 5
737
- } }, /* @__PURE__ */ React.createElement("div", { className: "flex-1 max-w-lg", __self: this, __source: {
738
- fileName: _jsxFileName,
739
- lineNumber: 847,
740
- columnNumber: 7
741
- } }, /* @__PURE__ */ React.createElement("label", { htmlFor: "search", className: "sr-only", __self: this, __source: {
742
- fileName: _jsxFileName,
743
- lineNumber: 848,
744
- columnNumber: 9
745
- } }, "Search"), /* @__PURE__ */ React.createElement("div", { className: "relative", __self: this, __source: {
746
- fileName: _jsxFileName,
747
- lineNumber: 851,
748
- columnNumber: 9
749
- } }, /* @__PURE__ */ React.createElement("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", __self: this, __source: {
750
- fileName: _jsxFileName,
751
- lineNumber: 852,
752
- columnNumber: 11
753
- } }, loading && search !== debouncedSearch ? /* @__PURE__ */ React.createElement("svg", { className: "animate-spin h-5 w-5 text-gray-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", __self: this, __source: {
754
- fileName: _jsxFileName,
755
- lineNumber: 854,
756
- columnNumber: 15
757
- } }, /* @__PURE__ */ React.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4", __self: this, __source: {
758
- fileName: _jsxFileName,
759
- lineNumber: 860,
760
- columnNumber: 17
761
- } }), /* @__PURE__ */ React.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z", __self: this, __source: {
762
- fileName: _jsxFileName,
763
- lineNumber: 868,
764
- columnNumber: 17
765
- } })) : /* @__PURE__ */ React.createElement("svg", { className: "h-5 w-5 text-gray-400", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", __self: this, __source: {
766
- fileName: _jsxFileName,
767
- lineNumber: 875,
768
- columnNumber: 15
769
- } }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z", clipRule: "evenodd", __self: this, __source: {
770
- fileName: _jsxFileName,
771
- lineNumber: 882,
772
- columnNumber: 17
773
- } }))), /* @__PURE__ */ React.createElement("input", { id: "search", name: "search", className: "block w-full pl-10 pr-12 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-green-web focus:border-green-web sm:text-sm", placeholder: `Search ${searchFields.length > 0 ? searchFields.map((field) => field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (str) => str.toUpperCase())).join(", ") : getPluralName(model.name).toLowerCase()}...`, type: "search", value: state.search || "", onChange: (e) => dispatch({
774
- type: "SET_SEARCH",
775
- payload: e.target.value
776
- }), __self: this, __source: {
777
- fileName: _jsxFileName,
778
- lineNumber: 890,
779
- columnNumber: 11
780
- } }), searchableFieldNames.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "absolute inset-y-0 right-0 flex items-center", __self: this, __source: {
781
- fileName: _jsxFileName,
782
- lineNumber: 900,
783
- columnNumber: 13
784
- } }, searchFieldSelector))), /* @__PURE__ */ React.createElement("div", { className: "ml-4 flex space-x-2", __self: this, __source: {
785
- fileName: _jsxFileName,
786
- lineNumber: 906,
787
- columnNumber: 7
788
- } }, /* @__PURE__ */ React.createElement("button", { onClick: () => setShowFilters(!showFilters), className: `inline-flex items-center px-3 py-2 border text-sm font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web ${showFilters || Object.keys(filters).length > 0 ? "border-green-web text-green-web bg-green-50 hover:bg-green-100" : "border-gray-300 text-gray-700 bg-white hover:bg-gray-50"}`, __self: this, __source: {
789
- fileName: _jsxFileName,
790
- lineNumber: 907,
791
- columnNumber: 9
792
- } }, /* @__PURE__ */ React.createElement("svg", { className: "w-4 h-4 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
793
- fileName: _jsxFileName,
794
- lineNumber: 915,
795
- columnNumber: 11
796
- } }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z", __self: this, __source: {
797
- fileName: _jsxFileName,
798
- lineNumber: 916,
799
- columnNumber: 13
800
- } })), "Filters", Object.keys(filters).length > 0 && /* @__PURE__ */ React.createElement("span", { className: "ml-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white bg-green-web rounded-full", __self: this, __source: {
801
- fileName: _jsxFileName,
802
- lineNumber: 925,
803
- columnNumber: 13
804
- } }, Object.keys(filters).length)), columnSelector, /* @__PURE__ */ React.createElement(Link, { to: createLink, className: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-600", __self: this, __source: {
805
- fileName: _jsxFileName,
806
- lineNumber: 931,
807
- columnNumber: 9
808
- } }, "Create New")));
809
- return /* @__PURE__ */ React.createElement(React.Fragment, null, filterPanel, searchFilter, /* @__PURE__ */ React.createElement(DataTable, { data: items, path: createLink.replace("/create", ""), fields: visibleColumns.length > 0 ? visibleColumns : fieldNames, pagination, setSkip: (skip2) => dispatch({
810
- type: "SET_SKIP",
811
- payload: skip2
812
- }), sort: state.sort, setSort: setSortSafely, __self: this, __source: {
813
- fileName: _jsxFileName,
814
- lineNumber: 945,
815
- columnNumber: 7
816
- } }));
627
+ if (["int", "bigint", "float", "decimal"].includes(field.type.toLowerCase())) {
628
+ return /* @__PURE__ */ jsx(
629
+ NumberRangeFilter,
630
+ {
631
+ fieldName,
632
+ fieldType: field.type.toLowerCase(),
633
+ currentValue,
634
+ onChange: handleChange
635
+ },
636
+ fieldName
637
+ );
638
+ }
639
+ if (field.kind === "enum") {
640
+ const enumValues = getEnumValues(field.type);
641
+ if (enumValues) {
642
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
643
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700", children: formatFieldName(fieldName) }),
644
+ /* @__PURE__ */ jsxs(
645
+ "select",
646
+ {
647
+ value: typeof currentValue === "string" ? currentValue : "",
648
+ onChange: (e) => handleChange(e.target.value || void 0),
649
+ className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm",
650
+ children: [
651
+ /* @__PURE__ */ jsx("option", { value: "", children: "All" }),
652
+ enumValues.map((val) => /* @__PURE__ */ jsx("option", { value: val, children: val }, val))
653
+ ]
654
+ }
655
+ )
656
+ ] }, fieldName);
657
+ }
658
+ }
659
+ if (field.type.toLowerCase() === "boolean") {
660
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
661
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700", children: formatFieldName(fieldName) }),
662
+ /* @__PURE__ */ jsxs(
663
+ "select",
664
+ {
665
+ value: currentValue === void 0 || currentValue === null ? "" : currentValue.toString(),
666
+ onChange: (e) => {
667
+ const value = e.target.value;
668
+ handleChange(value === "" ? void 0 : value === "true");
669
+ },
670
+ className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm",
671
+ children: [
672
+ /* @__PURE__ */ jsx("option", { value: "", children: "All" }),
673
+ /* @__PURE__ */ jsx("option", { value: "true", children: "Yes" }),
674
+ /* @__PURE__ */ jsx("option", { value: "false", children: "No" })
675
+ ]
676
+ }
677
+ )
678
+ ] }, fieldName);
679
+ }
680
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
681
+ /* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700", children: formatFieldName(fieldName) }),
682
+ /* @__PURE__ */ jsx(
683
+ "input",
684
+ {
685
+ type: "text",
686
+ value: typeof currentValue === "string" ? currentValue : "",
687
+ onChange: (e) => handleChange(e.target.value || void 0),
688
+ placeholder: `Filter by ${formatFieldName(fieldName).toLowerCase()}...`,
689
+ className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-sm"
690
+ }
691
+ )
692
+ ] }, fieldName);
693
+ }) })
694
+ ] });
695
+ const searchFilter = /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center justify-between", children: [
696
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 max-w-lg", children: [
697
+ /* @__PURE__ */ jsx("label", { htmlFor: "search", className: "sr-only", children: "Search" }),
698
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
699
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: loading && search !== debouncedSearch ? /* @__PURE__ */ jsxs(
700
+ "svg",
701
+ {
702
+ className: "animate-spin h-5 w-5 text-gray-400",
703
+ xmlns: "http://www.w3.org/2000/svg",
704
+ fill: "none",
705
+ viewBox: "0 0 24 24",
706
+ children: [
707
+ /* @__PURE__ */ jsx(
708
+ "circle",
709
+ {
710
+ className: "opacity-25",
711
+ cx: "12",
712
+ cy: "12",
713
+ r: "10",
714
+ stroke: "currentColor",
715
+ strokeWidth: "4"
716
+ }
717
+ ),
718
+ /* @__PURE__ */ jsx(
719
+ "path",
720
+ {
721
+ className: "opacity-75",
722
+ fill: "currentColor",
723
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
724
+ }
725
+ )
726
+ ]
727
+ }
728
+ ) : /* @__PURE__ */ jsx(
729
+ "svg",
730
+ {
731
+ className: "h-5 w-5 text-gray-400",
732
+ xmlns: "http://www.w3.org/2000/svg",
733
+ viewBox: "0 0 20 20",
734
+ fill: "currentColor",
735
+ "aria-hidden": "true",
736
+ children: /* @__PURE__ */ jsx(
737
+ "path",
738
+ {
739
+ fillRule: "evenodd",
740
+ d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
741
+ clipRule: "evenodd"
742
+ }
743
+ )
744
+ }
745
+ ) }),
746
+ /* @__PURE__ */ jsx(
747
+ "input",
748
+ {
749
+ id: "search",
750
+ name: "search",
751
+ className: "block w-full pl-10 pr-12 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-green-web focus:border-green-web sm:text-sm",
752
+ placeholder: `Search ${searchFields.length > 0 ? searchFields.map((field) => field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (str) => str.toUpperCase())).join(", ") : getPluralName(model.name).toLowerCase()}...`,
753
+ type: "search",
754
+ value: state.search || "",
755
+ onChange: (e) => dispatch({ type: "SET_SEARCH", payload: e.target.value })
756
+ }
757
+ ),
758
+ searchableFieldNames.length > 0 && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 flex items-center", children: searchFieldSelector })
759
+ ] })
760
+ ] }),
761
+ /* @__PURE__ */ jsxs("div", { className: "ml-4 flex space-x-2", children: [
762
+ /* @__PURE__ */ jsxs(
763
+ "button",
764
+ {
765
+ onClick: () => setShowFilters(!showFilters),
766
+ className: `inline-flex items-center px-3 py-2 border text-sm font-medium rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-web ${showFilters || Object.keys(filters).length > 0 ? "border-green-web text-green-web bg-green-50 hover:bg-green-100" : "border-gray-300 text-gray-700 bg-white hover:bg-gray-50"}`,
767
+ children: [
768
+ /* @__PURE__ */ jsx("svg", { className: "w-4 h-4 mr-2", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
769
+ "path",
770
+ {
771
+ strokeLinecap: "round",
772
+ strokeLinejoin: "round",
773
+ strokeWidth: 2,
774
+ d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
775
+ }
776
+ ) }),
777
+ "Filters",
778
+ Object.keys(filters).length > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-white bg-green-web rounded-full", children: Object.keys(filters).length })
779
+ ]
780
+ }
781
+ ),
782
+ columnSelector,
783
+ /* @__PURE__ */ jsx(
784
+ Link,
785
+ {
786
+ to: createLink,
787
+ className: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-600",
788
+ children: "Create New"
789
+ }
790
+ )
791
+ ] })
792
+ ] });
793
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
794
+ filterPanel,
795
+ searchFilter,
796
+ /* @__PURE__ */ jsx(
797
+ DataTable,
798
+ {
799
+ data: items,
800
+ path: createLink.replace("/create", ""),
801
+ fields: visibleColumns.length > 0 ? visibleColumns : fieldNames,
802
+ pagination,
803
+ setSkip: (skip2) => dispatch({ type: "SET_SKIP", payload: skip2 }),
804
+ sort: state.sort,
805
+ setSort: setSortSafely
806
+ }
807
+ )
808
+ ] });
817
809
  }
818
- function AdminDataErrorBoundary({
819
- error
820
- }) {
821
- return /* @__PURE__ */ React.createElement(ErrorBoundary, { error, __self: this, __source: {
822
- fileName: _jsxFileName,
823
- lineNumber: 959,
824
- columnNumber: 10
825
- } });
810
+ function AdminDataErrorBoundary({ error }) {
811
+ return /* @__PURE__ */ jsx(ErrorBoundary, { error });
826
812
  }
827
813
  export {
828
814
  AdminDataErrorBoundary,