@nestledjs/data-browser 0.1.2 → 0.1.4

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.
Files changed (83) hide show
  1. package/index.d.ts +15 -0
  2. package/index.js +64 -0
  3. package/lib/admin-data.d.ts +2 -0
  4. package/lib/components/filters/DateRangeFilter.d.ts +7 -0
  5. package/lib/components/filters/DateRangeFilter.js +105 -0
  6. package/lib/components/filters/NumberRangeFilter.d.ts +8 -0
  7. package/lib/components/filters/NumberRangeFilter.js +115 -0
  8. package/lib/components/filters/RelationComponents.d.ts +32 -0
  9. package/lib/components/filters/RelationComponents.js +265 -0
  10. package/lib/components/filters/RelationFilterField.d.ts +8 -0
  11. package/lib/components/filters/RelationFilterField.js +116 -0
  12. package/lib/components/filters/index.d.ts +4 -0
  13. package/lib/components/index.d.ts +2 -0
  14. package/lib/components/shared/AdminBreadcrumbs.d.ts +13 -0
  15. package/lib/components/shared/AdminBreadcrumbs.js +103 -0
  16. package/lib/components/shared/AdminErrorStates.d.ts +30 -0
  17. package/lib/components/shared/AdminErrorStates.js +214 -0
  18. package/lib/components/shared/AdminStatusDisplay.d.ts +21 -0
  19. package/lib/components/shared/AdminStatusDisplay.js +205 -0
  20. package/lib/components/shared/index.d.ts +3 -0
  21. package/lib/context/AdminDataContext.d.ts +47 -0
  22. package/lib/context/AdminDataContext.js +28 -0
  23. package/lib/hooks/useAdminList.d.ts +5 -0
  24. package/lib/hooks/useAdminList.js +41 -0
  25. package/lib/hooks/useClickOutside.d.ts +2 -0
  26. package/lib/hooks/useClickOutside.js +13 -0
  27. package/lib/hooks/useDebounce.d.ts +1 -0
  28. package/lib/hooks/useDebounce.js +13 -0
  29. package/lib/hooks/useRelationData.d.ts +7 -0
  30. package/lib/hooks/useRelationData.js +64 -0
  31. package/lib/layouts/AdminDataLayout.d.ts +5 -0
  32. package/lib/layouts/AdminDataLayout.js +315 -0
  33. package/lib/pages/AdminDataCreatePage.d.ts +4 -0
  34. package/lib/pages/AdminDataCreatePage.js +487 -0
  35. package/lib/pages/AdminDataEditPage.d.ts +4 -0
  36. package/lib/pages/AdminDataEditPage.js +903 -0
  37. package/lib/pages/AdminDataIndexPage.d.ts +4 -0
  38. package/lib/pages/AdminDataIndexPage.js +91 -0
  39. package/lib/pages/AdminDataListPage.d.ts +9 -0
  40. package/lib/pages/AdminDataListPage.js +1218 -0
  41. package/lib/types/index.d.ts +60 -0
  42. package/lib/types/index.js +16 -0
  43. package/lib/utils/graphql-utils.d.ts +25 -0
  44. package/lib/utils/graphql-utils.js +265 -0
  45. package/lib/utils/secure-storage.d.ts +50 -0
  46. package/lib/utils/secure-storage.js +145 -0
  47. package/lib/utils/string-utils.d.ts +6 -0
  48. package/lib/utils/string-utils.js +27 -0
  49. package/package.json +8 -2
  50. package/.babelrc +0 -12
  51. package/LICENSE +0 -21
  52. package/eslint.config.mjs +0 -12
  53. package/project.json +0 -35
  54. package/src/index.ts +0 -28
  55. package/src/lib/admin-data.spec.tsx +0 -10
  56. package/src/lib/admin-data.tsx +0 -9
  57. package/src/lib/components/filters/DateRangeFilter.tsx +0 -88
  58. package/src/lib/components/filters/NumberRangeFilter.tsx +0 -111
  59. package/src/lib/components/filters/RelationComponents.tsx +0 -176
  60. package/src/lib/components/filters/RelationFilterField.tsx +0 -106
  61. package/src/lib/components/filters/index.ts +0 -5
  62. package/src/lib/components/index.ts +0 -2
  63. package/src/lib/components/shared/AdminBreadcrumbs.tsx +0 -88
  64. package/src/lib/components/shared/AdminErrorStates.tsx +0 -180
  65. package/src/lib/components/shared/AdminStatusDisplay.tsx +0 -292
  66. package/src/lib/components/shared/index.ts +0 -3
  67. package/src/lib/context/AdminDataContext.tsx +0 -74
  68. package/src/lib/hooks/useAdminList.ts +0 -42
  69. package/src/lib/hooks/useClickOutside.ts +0 -21
  70. package/src/lib/hooks/useDebounce.ts +0 -16
  71. package/src/lib/hooks/useRelationData.ts +0 -114
  72. package/src/lib/layouts/AdminDataLayout.tsx +0 -251
  73. package/src/lib/pages/AdminDataCreatePage.tsx +0 -415
  74. package/src/lib/pages/AdminDataEditPage.tsx +0 -777
  75. package/src/lib/pages/AdminDataIndexPage.tsx +0 -50
  76. package/src/lib/pages/AdminDataListPage.tsx +0 -921
  77. package/src/lib/types/index.ts +0 -51
  78. package/src/lib/utils/graphql-utils.ts +0 -538
  79. package/src/lib/utils/secure-storage.ts +0 -305
  80. package/src/lib/utils/string-utils.ts +0 -53
  81. package/tsconfig.json +0 -17
  82. package/tsconfig.lib.json +0 -20
  83. package/vite.config.ts +0 -35
@@ -0,0 +1,205 @@
1
+ import { jsxDEV as o, Fragment as I } from "react/jsx-dev-runtime";
2
+ import { QuestionMarkCircleIcon as S, PauseCircleIcon as $, CheckCircleIcon as b, XCircleIcon as u, ExclamationTriangleIcon as A, ClockIcon as D } from "@heroicons/react/24/solid";
3
+ const L = (e) => ({
4
+ active: {
5
+ icon: b,
6
+ bgColor: "bg-green-100",
7
+ textColor: "text-green-800",
8
+ borderColor: "border-green-200",
9
+ defaultLabel: "Active"
10
+ },
11
+ inactive: {
12
+ icon: u,
13
+ bgColor: "bg-gray-100",
14
+ textColor: "text-gray-800",
15
+ borderColor: "border-gray-200",
16
+ defaultLabel: "Inactive"
17
+ },
18
+ pending: {
19
+ icon: D,
20
+ bgColor: "bg-yellow-100",
21
+ textColor: "text-yellow-800",
22
+ borderColor: "border-yellow-200",
23
+ defaultLabel: "Pending"
24
+ },
25
+ approved: {
26
+ icon: b,
27
+ bgColor: "bg-green-100",
28
+ textColor: "text-green-800",
29
+ borderColor: "border-green-200",
30
+ defaultLabel: "Approved"
31
+ },
32
+ rejected: {
33
+ icon: u,
34
+ bgColor: "bg-red-100",
35
+ textColor: "text-red-800",
36
+ borderColor: "border-red-200",
37
+ defaultLabel: "Rejected"
38
+ },
39
+ warning: {
40
+ icon: A,
41
+ bgColor: "bg-yellow-100",
42
+ textColor: "text-yellow-800",
43
+ borderColor: "border-yellow-200",
44
+ defaultLabel: "Warning"
45
+ },
46
+ error: {
47
+ icon: u,
48
+ bgColor: "bg-red-100",
49
+ textColor: "text-red-800",
50
+ borderColor: "border-red-200",
51
+ defaultLabel: "Error"
52
+ },
53
+ success: {
54
+ icon: b,
55
+ bgColor: "bg-green-100",
56
+ textColor: "text-green-800",
57
+ borderColor: "border-green-200",
58
+ defaultLabel: "Success"
59
+ },
60
+ paused: {
61
+ icon: $,
62
+ bgColor: "bg-blue-100",
63
+ textColor: "text-blue-800",
64
+ borderColor: "border-blue-200",
65
+ defaultLabel: "Paused"
66
+ },
67
+ unknown: {
68
+ icon: S,
69
+ bgColor: "bg-gray-100",
70
+ textColor: "text-gray-800",
71
+ borderColor: "border-gray-200",
72
+ defaultLabel: "Unknown"
73
+ }
74
+ })[e], x = (e) => ({
75
+ small: {
76
+ text: "text-xs",
77
+ padding: "px-2 py-1",
78
+ icon: "h-3 w-3",
79
+ dot: "h-2 w-2"
80
+ },
81
+ medium: {
82
+ text: "text-sm",
83
+ padding: "px-2.5 py-1.5",
84
+ icon: "h-4 w-4",
85
+ dot: "h-3 w-3"
86
+ },
87
+ large: {
88
+ text: "text-base",
89
+ padding: "px-3 py-2",
90
+ icon: "h-5 w-5",
91
+ dot: "h-4 w-4"
92
+ }
93
+ })[e], P = (e) => ({
94
+ badge: "inline-flex items-center rounded border font-medium",
95
+ pill: "inline-flex items-center rounded-full border font-medium",
96
+ dot: "inline-flex items-center font-medium",
97
+ full: "flex items-center justify-center rounded border font-medium w-full"
98
+ })[e], U = (e) => ({
99
+ online: {
100
+ color: "bg-green-400",
101
+ label: "Online"
102
+ },
103
+ offline: {
104
+ color: "bg-gray-400",
105
+ label: "Offline"
106
+ },
107
+ away: {
108
+ color: "bg-yellow-400",
109
+ label: "Away"
110
+ },
111
+ busy: {
112
+ color: "bg-red-400",
113
+ label: "Busy"
114
+ }
115
+ })[e];
116
+ function O({
117
+ status: e,
118
+ label: t,
119
+ size: c = "medium",
120
+ variant: n = "badge",
121
+ showIcon: r = !0,
122
+ className: a = "",
123
+ onClick: s,
124
+ tooltip: i
125
+ }) {
126
+ const l = L(e), d = x(c), y = P(n), h = l.icon, m = t || l.defaultLabel, g = n === "dot", N = r && !g, f = !!s, C = `${`${y} ${d.text} ${d.padding} ${l.bgColor} ${l.textColor} ${l.borderColor}`} ${f ? "cursor-pointer hover:opacity-80" : ""} ${a}`.trim(), j = () => g ? /* @__PURE__ */ o("span", { className: `inline-block rounded-full mr-2 ${l.bgColor.replace("bg-", "bg-").replace("-100", "-400")} ${d.dot}` }, void 0, !1, {
127
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
128
+ lineNumber: 221,
129
+ columnNumber: 7
130
+ }, this) : null, v = () => N ? /* @__PURE__ */ o(h, { className: `${d.icon} ${m ? "mr-1.5" : ""}` }, void 0, !1, {
131
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
132
+ lineNumber: 229,
133
+ columnNumber: 7
134
+ }, this) : null, p = /* @__PURE__ */ o(I, { children: [
135
+ j(),
136
+ v(),
137
+ m
138
+ ] }, void 0, !0, {
139
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
140
+ lineNumber: 234,
141
+ columnNumber: 5
142
+ }, this), w = () => {
143
+ s && s();
144
+ };
145
+ return f ? /* @__PURE__ */ o(
146
+ "button",
147
+ {
148
+ type: "button",
149
+ onClick: w,
150
+ className: C,
151
+ title: i,
152
+ children: p
153
+ },
154
+ void 0,
155
+ !1,
156
+ {
157
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
158
+ lineNumber: 249,
159
+ columnNumber: 7
160
+ },
161
+ this
162
+ ) : /* @__PURE__ */ o("span", { className: C, title: i, children: p }, void 0, !1, {
163
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
164
+ lineNumber: 261,
165
+ columnNumber: 5
166
+ }, this);
167
+ }
168
+ function V({
169
+ status: e,
170
+ showLabel: t = !1,
171
+ size: c = "medium",
172
+ className: n = ""
173
+ }) {
174
+ const r = U(e), a = x(c), s = a.dot, i = t ? a.text : "";
175
+ return /* @__PURE__ */ o("div", { className: `inline-flex items-center ${n}`, children: [
176
+ /* @__PURE__ */ o(
177
+ "span",
178
+ {
179
+ className: `inline-block rounded-full ${r.color} ${s}`,
180
+ "aria-label": r.label
181
+ },
182
+ void 0,
183
+ !1,
184
+ {
185
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
186
+ lineNumber: 281,
187
+ columnNumber: 7
188
+ },
189
+ this
190
+ ),
191
+ t && /* @__PURE__ */ o("span", { className: `ml-2 text-gray-700 ${i}`, children: r.label }, void 0, !1, {
192
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
193
+ lineNumber: 286,
194
+ columnNumber: 9
195
+ }, this)
196
+ ] }, void 0, !0, {
197
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/components/shared/AdminStatusDisplay.tsx",
198
+ lineNumber: 280,
199
+ columnNumber: 5
200
+ }, this);
201
+ }
202
+ export {
203
+ O as AdminStatusDisplay,
204
+ V as AdminUserStatus
205
+ };
@@ -0,0 +1,3 @@
1
+ export * from './AdminBreadcrumbs';
2
+ export * from './AdminErrorStates';
3
+ export * from './AdminStatusDisplay';
@@ -0,0 +1,47 @@
1
+ import { ReactNode } from 'react';
2
+ export interface AdminDataContextValue {
3
+ /** The SDK namespace for dynamic GraphQL document lookups */
4
+ sdk: any;
5
+ /** Array of database models from Prisma schema */
6
+ databaseModels: any[];
7
+ /** Base path for admin data routes (e.g., "/admin/data") */
8
+ basePath?: string;
9
+ /** Form theme configuration for @nestledjs/forms */
10
+ formTheme: any;
11
+ }
12
+ export interface AdminDataProviderProps {
13
+ children: ReactNode;
14
+ /** The entire SDK namespace (e.g., import * as Sdk from '@your-project/shared/sdk') */
15
+ sdk: any;
16
+ /** DATABASE_MODELS array from your SDK */
17
+ databaseModels: any[];
18
+ /** Optional base path for routes (defaults to "/admin/data") */
19
+ basePath?: string;
20
+ /** Form theme configuration for @nestledjs/forms */
21
+ formTheme: any;
22
+ }
23
+ /**
24
+ * Provider component that supplies SDK and database models to admin data components
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * import * as Sdk from '@your-project/shared/sdk'
29
+ * import { DATABASE_MODELS } from '@your-project/shared/sdk'
30
+ * import { AdminDataProvider } from '@nestledjs/admin-data'
31
+ *
32
+ * <AdminDataProvider
33
+ * sdk={Sdk}
34
+ * databaseModels={DATABASE_MODELS}
35
+ * formTheme={formTheme}
36
+ * basePath="/admin/data"
37
+ * >
38
+ * <AdminDataLayout />
39
+ * </AdminDataProvider>
40
+ * ```
41
+ */
42
+ export declare function AdminDataProvider({ children, sdk, databaseModels, basePath, formTheme }: AdminDataProviderProps): import("react/jsx-runtime").JSX.Element;
43
+ /**
44
+ * Hook to access the admin data context
45
+ * @throws Error if used outside of AdminDataProvider
46
+ */
47
+ export declare function useAdminDataContext(): AdminDataContextValue;
@@ -0,0 +1,28 @@
1
+ import { jsxDEV as o } from "react/jsx-dev-runtime";
2
+ import { createContext as d, useContext as m } from "react";
3
+ const e = d(null);
4
+ function l({
5
+ children: t,
6
+ sdk: n,
7
+ databaseModels: a,
8
+ basePath: r = "/admin/data",
9
+ formTheme: i
10
+ }) {
11
+ return /* @__PURE__ */ o(e.Provider, { value: { sdk: n, databaseModels: a, basePath: r, formTheme: i }, children: t }, void 0, !1, {
12
+ fileName: "/Users/justinhandley/IdeaProjects/nestled_template/libs/admin-data/src/lib/context/AdminDataContext.tsx",
13
+ lineNumber: 55,
14
+ columnNumber: 5
15
+ }, this);
16
+ }
17
+ function x() {
18
+ const t = m(e);
19
+ if (!t)
20
+ throw new Error(
21
+ "useAdminDataContext must be used within AdminDataProvider. Make sure to wrap your admin data routes with <AdminDataProvider>."
22
+ );
23
+ return t;
24
+ }
25
+ export {
26
+ l as AdminDataProvider,
27
+ x as useAdminDataContext
28
+ };
@@ -0,0 +1,5 @@
1
+ import { AdminListAction, AdminListState } from '../types';
2
+ export declare function useAdminList(): {
3
+ state: AdminListState;
4
+ dispatch: import('react').ActionDispatch<[action: AdminListAction]>;
5
+ };
@@ -0,0 +1,41 @@
1
+ import { useReducer as S } from "react";
2
+ import { initialState as E } from "../types/index.js";
3
+ function u(r, e) {
4
+ switch (e.type) {
5
+ case "SET_SEARCH":
6
+ return { ...r, search: e.payload };
7
+ case "SET_DEBOUNCED_SEARCH":
8
+ return { ...r, debouncedSearch: e.payload };
9
+ case "SET_SKIP":
10
+ return { ...r, skip: e.payload };
11
+ case "SET_PAGE_SIZE":
12
+ return { ...r, pageSize: e.payload };
13
+ case "SET_SORT":
14
+ return { ...r, sort: e.payload };
15
+ case "SET_VISIBLE_COLUMNS":
16
+ return { ...r, visibleColumns: e.payload };
17
+ case "TOGGLE_COLUMN_SELECTOR":
18
+ return { ...r, showColumnSelector: !r.showColumnSelector };
19
+ case "SET_SEARCH_FIELDS":
20
+ return { ...r, searchFields: e.payload };
21
+ case "TOGGLE_SEARCH_FIELD_SELECTOR":
22
+ return { ...r, showSearchFieldSelector: !r.showSearchFieldSelector };
23
+ case "SET_FILTERS":
24
+ return { ...r, filters: e.payload };
25
+ case "TOGGLE_FILTERS":
26
+ return { ...r, showFilters: !r.showFilters };
27
+ case "RESET_PAGINATION":
28
+ return { ...r, skip: 0 };
29
+ case "RESET_FILTERS":
30
+ return { ...r, filters: {} };
31
+ default:
32
+ return r;
33
+ }
34
+ }
35
+ function s() {
36
+ const [r, e] = S(u, E);
37
+ return { state: r, dispatch: e };
38
+ }
39
+ export {
40
+ s as useAdminList
41
+ };
@@ -0,0 +1,2 @@
1
+ import { default as React } from 'react';
2
+ export declare function useClickOutside(ref: React.RefObject<HTMLDivElement | null>, handler: () => void, isActive?: boolean): void;
@@ -0,0 +1,13 @@
1
+ import { useEffect as o } from "react";
2
+ function i(e, t, n = !0) {
3
+ o(() => {
4
+ if (!n) return;
5
+ const r = (u) => {
6
+ e.current && !e.current.contains(u.target) && t();
7
+ };
8
+ return document.addEventListener("mousedown", r), () => document.removeEventListener("mousedown", r);
9
+ }, [t, n]);
10
+ }
11
+ export {
12
+ i as useClickOutside
13
+ };
@@ -0,0 +1 @@
1
+ export declare function useDebounce<T>(value: T, delay: number): T;
@@ -0,0 +1,13 @@
1
+ import { useState as r, useEffect as c } from "react";
2
+ function i(e, t) {
3
+ const [o, u] = r(e);
4
+ return c(() => {
5
+ const n = setTimeout(() => {
6
+ u(e);
7
+ }, t);
8
+ return () => clearTimeout(n);
9
+ }, [e, t]), o;
10
+ }
11
+ export {
12
+ i as useDebounce
13
+ };
@@ -0,0 +1,7 @@
1
+ export declare function useRelationData(relatedModelName: string, searchTerm: string, isOpen: boolean): {
2
+ relatedModel: any;
3
+ relatedItems: any[];
4
+ loading: boolean;
5
+ error: import('@apollo/client').ErrorLike | undefined;
6
+ hasDocument: boolean;
7
+ };
@@ -0,0 +1,64 @@
1
+ import { useQuery as g } from "@apollo/client/react";
2
+ import { useMemo as o } from "react";
3
+ import { useAdminDataContext as Q } from "../context/AdminDataContext.js";
4
+ import { getAdminDocuments as w } from "../utils/graphql-utils.js";
5
+ import { getSmartSearchFields as A } from "../utils/string-utils.js";
6
+ import { useDebounce as k } from "./useDebounce.js";
7
+ function v(a, y, d) {
8
+ const { sdk: l, databaseModels: f } = Q(), s = k(y, 300), e = o(
9
+ () => f.find((r) => r.name === a),
10
+ [f, a]
11
+ ), i = o(
12
+ () => e ? w(l, e) : { listQuery: void 0 },
13
+ [l, e]
14
+ ), m = o(
15
+ () => (e == null ? void 0 : e.pluralModelPropertyName) || a.charAt(0).toLowerCase() + a.slice(1) + "s",
16
+ [e, a]
17
+ ), p = o(() => e ? e.fields.filter((r) => {
18
+ const t = r.type.toLowerCase();
19
+ return !r.relationName && (t === "string" || t.includes("text") || t === "boolean");
20
+ }).map((r) => r.name) : [], [e]), c = o(() => A(p), [p]), h = o(
21
+ () => ({
22
+ input: {
23
+ take: 20,
24
+ ...s.trim() ? {
25
+ search: s,
26
+ searchFields: c.length > 0 ? c : void 0
27
+ } : {}
28
+ }
29
+ }),
30
+ [s, c]
31
+ ), {
32
+ data: u,
33
+ loading: D,
34
+ error: n
35
+ } = g(i.listQuery, {
36
+ variables: h,
37
+ skip: !i.listQuery || !d,
38
+ errorPolicy: "all",
39
+ // Continue processing even if there are GraphQL errors
40
+ notifyOnNetworkStatusChange: !0,
41
+ fetchPolicy: "cache-first"
42
+ // Use cache for better performance
43
+ }), b = o(() => {
44
+ if (n)
45
+ return console.warn("[RelationData] GraphQL error:", n.message), [];
46
+ if (!u) return [];
47
+ try {
48
+ const r = u[m] || [];
49
+ return Array.isArray(r) ? r.filter((t) => !(!t || typeof t != "object" || !t.id)) : (console.warn("[RelationData] Expected array but got:", typeof r), []);
50
+ } catch (r) {
51
+ return console.error("[RelationData] Error processing relation data:", r), [];
52
+ }
53
+ }, [u, m, n]);
54
+ return {
55
+ relatedModel: e,
56
+ relatedItems: b,
57
+ loading: D,
58
+ error: n,
59
+ hasDocument: !!i.listQuery
60
+ };
61
+ }
62
+ export {
63
+ v as useRelationData
64
+ };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Main layout component for admin data browser
3
+ * Provides model selector, fullscreen toggle, and preferences import/export
4
+ */
5
+ export declare function AdminDataLayout(): import("react/jsx-runtime").JSX.Element;