@nestledjs/data-browser 1.0.15 → 1.0.16

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.
@@ -15,52 +15,62 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
15
15
  const params = useParams();
16
16
  const [searchParams] = useSearchParams();
17
17
  const { sdk, databaseModels, basePath = "/admin/data" } = useAdminDataContext();
18
- const getEnumValues = useCallback((enumType) => {
19
- try {
20
- const enumObject = sdk[enumType];
21
- if (!enumObject || typeof enumObject !== "object") {
18
+ const getEnumValues = useCallback(
19
+ (enumType) => {
20
+ try {
21
+ const enumObject = sdk[enumType];
22
+ if (!enumObject || typeof enumObject !== "object") {
23
+ return null;
24
+ }
25
+ const values = Object.values(enumObject).filter((value) => typeof value === "string");
26
+ if (values.length === 0) {
27
+ const keys = Object.keys(enumObject).filter((key) => Number.isNaN(Number(key)));
28
+ return keys.length > 0 ? keys : null;
29
+ }
30
+ return values.filter((v) => typeof v === "string");
31
+ } catch (error2) {
32
+ console.error("Unexpected error:", error2);
22
33
  return null;
23
34
  }
24
- const values = Object.values(enumObject).filter((value) => typeof value === "string");
25
- if (values.length === 0) {
26
- const keys = Object.keys(enumObject).filter((key) => isNaN(Number(key)));
27
- return keys.length > 0 ? keys : null;
28
- }
29
- return values;
30
- } catch (error2) {
31
- return null;
32
- }
33
- }, [sdk]);
34
- const updateRelatedEnumFilter = useCallback((filters2, relationName, enumFieldName, value) => {
35
- const newFilters = { ...filters2 };
36
- if (value === void 0 || value === null || value === "") {
37
- const relationFilter = newFilters[relationName];
38
- if (relationFilter && typeof relationFilter === "object") {
39
- delete relationFilter[enumFieldName];
40
- if (Object.keys(relationFilter).length === 0) {
41
- delete newFilters[relationName];
35
+ },
36
+ [sdk]
37
+ );
38
+ const updateRelatedEnumFilter = useCallback(
39
+ (filters2, relationName, enumFieldName, value) => {
40
+ const newFilters = { ...filters2 };
41
+ if (value === void 0 || value === null || value === "") {
42
+ const relationFilter = newFilters[relationName];
43
+ if (relationFilter && typeof relationFilter === "object") {
44
+ delete relationFilter[enumFieldName];
45
+ if (Object.keys(relationFilter).length === 0) {
46
+ delete newFilters[relationName];
47
+ }
48
+ }
49
+ } else {
50
+ if (!newFilters[relationName]) {
51
+ newFilters[relationName] = {};
52
+ }
53
+ const relationFilter = newFilters[relationName];
54
+ if (relationFilter && typeof relationFilter === "object") {
55
+ relationFilter[enumFieldName] = value;
42
56
  }
43
57
  }
44
- } else {
45
- if (!newFilters[relationName]) {
46
- newFilters[relationName] = {};
47
- }
48
- const relationFilter = newFilters[relationName];
49
- if (relationFilter && typeof relationFilter === "object") {
50
- relationFilter[enumFieldName] = value;
58
+ return newFilters;
59
+ },
60
+ []
61
+ );
62
+ const updateSimpleFilter = useCallback(
63
+ (filters2, fieldName, value) => {
64
+ const newFilters = { ...filters2 };
65
+ if (value === void 0 || value === null || value === "") {
66
+ delete newFilters[fieldName];
67
+ } else {
68
+ newFilters[fieldName] = value;
51
69
  }
52
- }
53
- return newFilters;
54
- }, []);
55
- const updateSimpleFilter = useCallback((filters2, fieldName, value) => {
56
- const newFilters = { ...filters2 };
57
- if (value === void 0 || value === null || value === "") {
58
- delete newFilters[fieldName];
59
- } else {
60
- newFilters[fieldName] = value;
61
- }
62
- return newFilters;
63
- }, []);
70
+ return newFilters;
71
+ },
72
+ []
73
+ );
64
74
  const { state, dispatch } = useAdminList();
65
75
  const {
66
76
  search,
@@ -75,10 +85,6 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
75
85
  showFilters,
76
86
  showSearchFieldSelector
77
87
  } = state;
78
- useCallback(
79
- (skip2) => dispatch({ type: "SET_SKIP", payload: skip2 }),
80
- [dispatch]
81
- );
82
88
  const setFilters = useCallback(
83
89
  (filters2) => dispatch({ type: "SET_FILTERS", payload: filters2 }),
84
90
  [dispatch]
@@ -160,7 +166,7 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
160
166
  }, [sdk, model]);
161
167
  const { listQuery: query } = documents;
162
168
  const dataPath = useMemo(() => {
163
- return model?.pluralModelPropertyName || pluralParam.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
169
+ return model?.pluralModelPropertyName || pluralParam.replaceAll(/-([a-z])/g, (_, letter) => letter.toUpperCase());
164
170
  }, [model, pluralParam]);
165
171
  const paginationPath = useMemo(() => {
166
172
  return "counters";
@@ -216,11 +222,13 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
216
222
  setVisibleColumns(filteredCols);
217
223
  const storedSort = AdminLocalStorage.getSortPreference(model.name);
218
224
  const sortFieldValid = storedSort && (storedSort.orderBy === "id" || fieldNames.includes(storedSort.orderBy));
219
- const nextSort = sortFieldValid ? storedSort : { orderBy: "id", orderDirection: "desc" };
225
+ const nextSort = sortFieldValid && storedSort ? storedSort : { orderBy: "id", orderDirection: "desc" };
220
226
  dispatch({ type: "SET_SORT", payload: nextSort });
221
227
  const storedSearch = AdminLocalStorage.getSearchFields(model.name);
222
228
  const defaults = getDefaultSearchFields(searchableFieldNames);
223
- const filteredSearch = (storedSearch || defaults).filter((f) => searchableFieldNames.includes(f));
229
+ const filteredSearch = (storedSearch || defaults).filter(
230
+ (f) => searchableFieldNames.includes(f)
231
+ );
224
232
  setSearchFields(filteredSearch);
225
233
  dispatch({ type: "SET_SEARCH", payload: "" });
226
234
  dispatch({ type: "SET_DEBOUNCED_SEARCH", payload: "" });
@@ -230,7 +238,16 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
230
238
  dispatch({ type: "SET_FILTERS", payload: urlFilters });
231
239
  dispatch({ type: "SET_SHOW_FILTERS", payload: true });
232
240
  }
233
- }, [model?.name, fieldNames, searchableFieldNames, getDefaultSearchFields, setVisibleColumns, setSearchFields, dispatch, urlFilters]);
241
+ }, [
242
+ model?.name,
243
+ fieldNames,
244
+ searchableFieldNames,
245
+ getDefaultSearchFields,
246
+ setVisibleColumns,
247
+ setSearchFields,
248
+ dispatch,
249
+ urlFilters
250
+ ]);
234
251
  const setSortSafely = useCallback(
235
252
  (newSort) => {
236
253
  const resolvedSort = typeof newSort === "function" ? newSort(sort) : newSort;
@@ -285,7 +302,22 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
285
302
  filters: Object.keys(filters).length > 0 ? filters : void 0
286
303
  }
287
304
  };
288
- const { data, loading, error, networkStatus, refetch } = useQuery(query ?? sdk.__AdminUsersDocument, {
305
+ const extractItems = useCallback((anyData, dataPath2) => {
306
+ let processedItems = dataPath2 && anyData[dataPath2] ? anyData[dataPath2] : [];
307
+ if (!processedItems || processedItems.length === 0) {
308
+ for (const [, value] of Object.entries(anyData)) {
309
+ if (Array.isArray(value) && value.length > 0 && value[0]?.id) {
310
+ processedItems = value;
311
+ break;
312
+ }
313
+ }
314
+ }
315
+ return processedItems;
316
+ }, []);
317
+ const filterValidItems = useCallback((items2) => {
318
+ return items2.filter((item) => item && typeof item === "object" && item.id);
319
+ }, []);
320
+ const { data, loading, error } = useQuery(query ?? sdk.__AdminUsersDocument, {
289
321
  variables,
290
322
  skip: !model || !query,
291
323
  errorPolicy: "all",
@@ -299,11 +331,6 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
299
331
  }
300
332
  });
301
333
  const { validatedItems, validatedPagination, dataError } = useMemo(() => {
302
- if (error) {
303
- const apolloError = error;
304
- if (apolloError.networkError) ;
305
- if (apolloError.graphQLErrors?.length > 0) ;
306
- }
307
334
  if (!data) {
308
335
  return {
309
336
  validatedItems: [],
@@ -313,18 +340,8 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
313
340
  }
314
341
  try {
315
342
  const anyData = data;
316
- let processedItems = dataPath && anyData[dataPath] ? anyData[dataPath] : [];
317
343
  const processedPagination = paginationPath && anyData[paginationPath] ? anyData[paginationPath] : void 0;
318
- if (!processedItems || processedItems.length === 0) {
319
- for (const [key, value] of Object.entries(anyData)) {
320
- if (Array.isArray(value)) {
321
- if (value.length > 0 && value[0]?.id) {
322
- processedItems = value;
323
- break;
324
- }
325
- }
326
- }
327
- }
344
+ const processedItems = extractItems(anyData, dataPath);
328
345
  if (!Array.isArray(processedItems)) {
329
346
  return {
330
347
  validatedItems: [],
@@ -332,17 +349,8 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
332
349
  dataError: new Error("Invalid data format: expected array")
333
350
  };
334
351
  }
335
- const filteredItems = processedItems.filter((item, index) => {
336
- if (!item || typeof item !== "object") {
337
- return false;
338
- }
339
- if (!item.id) {
340
- return false;
341
- }
342
- return true;
343
- });
344
352
  return {
345
- validatedItems: filteredItems,
353
+ validatedItems: filterValidItems(processedItems),
346
354
  validatedPagination: processedPagination,
347
355
  dataError: null
348
356
  };
@@ -353,7 +361,7 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
353
361
  dataError: err instanceof Error ? err : new Error("Unknown data processing error")
354
362
  };
355
363
  }
356
- }, [data, dataPath, paginationPath, error]);
364
+ }, [data, dataPath, paginationPath, error, extractItems, filterValidItems]);
357
365
  const items = validatedItems;
358
366
  const pagination = validatedPagination;
359
367
  if (!model) {
@@ -422,7 +430,7 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
422
430
  /* @__PURE__ */ jsx(
423
431
  "button",
424
432
  {
425
- onClick: () => window.location.reload(),
433
+ onClick: () => globalThis.location.reload(),
426
434
  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",
427
435
  children: "Reload Page"
428
436
  }
@@ -710,7 +718,7 @@ function AdminDataListPage({ modelName: propModelName } = {}) {
710
718
  id: "search",
711
719
  name: "search",
712
720
  className: "block w-full pl-10 pr-12 py-2 border border-gray-300 dark:border-gray-600 rounded-md leading-5 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:placeholder-gray-400 dark:focus:placeholder-gray-500 focus:ring-1 focus:ring-green-web focus:border-green-web sm:text-sm",
713
- 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()}...`,
721
+ placeholder: `Search ${searchFields.length > 0 ? searchFields.map((field) => field.replaceAll(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (str) => str.toUpperCase())).join(", ") : getPluralName(model.name).toLowerCase()}...`,
714
722
  type: "search",
715
723
  value: state.search || "",
716
724
  onChange: (e) => dispatch({ type: "SET_SEARCH", payload: e.target.value })
@@ -1,4 +1,4 @@
1
- import { FormField } from '@nestledjs/forms';
1
+ import { FormField } from '@nestledjs/forms-core';
2
2
  import { DatabaseModel } from '../types';
3
3
  import { DisplayFieldConfig } from '../context/AdminDataContext';
4
4
  /**
@@ -15,6 +15,10 @@ export declare function getAdminDocuments(sdk: any, model: DatabaseModel): {
15
15
  * Get the GraphQL mutation name for a given operation
16
16
  */
17
17
  export declare function getMutationName(model: DatabaseModel, operation: 'create' | 'update' | 'delete'): string;
18
+ /**
19
+ * Convert model name to kebab-case for URLs
20
+ */
21
+ export declare function toKebabCase(str: string): string;
18
22
  /**
19
23
  * Options for building form fields
20
24
  */
@@ -34,3 +38,5 @@ export declare function buildFormFields(sdk: any, model: DatabaseModel, operatio
34
38
  * Removes Apollo metadata and system fields
35
39
  */
36
40
  export declare function cleanFormInput(input: Record<string, unknown>, model?: DatabaseModel): Record<string, unknown>;
41
+ export declare function toReadableText(text: string): string;
42
+ export declare function sanitizeInput(input: string | undefined): string;