@nestledjs/data-browser 0.1.12 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +2 -0
- package/lib/components/RelationFieldWrapper.d.ts +9 -0
- package/lib/components/RelationFieldWrapper.js +63 -0
- package/lib/components/filters/DateRangeFilter.d.ts +1 -1
- package/lib/components/filters/DateRangeFilter.js +9 -9
- package/lib/components/filters/NumberRangeFilter.js +21 -21
- package/lib/components/filters/RelationComponents.d.ts +4 -4
- package/lib/components/filters/RelationComponents.js +16 -16
- package/lib/components/filters/RelationFilterField.js +16 -10
- package/lib/components/index.d.ts +1 -0
- package/lib/components/shared/AdminBreadcrumbs.js +3 -3
- package/lib/components/shared/AdminErrorStates.js +1 -1
- package/lib/components/shared/AdminStatusDisplay.js +1 -1
- package/lib/context/AdminDataContext.d.ts +1 -1
- package/lib/context/AdminDataContext.js +6 -5
- package/lib/hooks/useRelationData.d.ts +1 -1
- package/lib/hooks/useRelationData.js +3 -2
- package/lib/layouts/AdminDataLayout.js +53 -56
- package/lib/pages/AdminDataCreatePage.js +6 -5
- package/lib/pages/AdminDataEditPage.js +6 -5
- package/lib/pages/AdminDataIndexPage.js +14 -13
- package/lib/pages/AdminDataListPage.js +138 -99
- package/lib/utils/graphql-utils.d.ts +1 -1
- package/lib/utils/graphql-utils.js +132 -24
- package/lib/utils/string-utils.js +3 -3
- package/package.json +3 -3
|
@@ -4,7 +4,7 @@ import { useNavigate, useParams, Outlet } from "react-router";
|
|
|
4
4
|
import { AdminLocalStorage } from "../utils/secure-storage.js";
|
|
5
5
|
import { spacedWords, kebabCase } from "../utils/string-utils.js";
|
|
6
6
|
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
7
|
-
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/
|
|
7
|
+
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/data-browser/src/lib/layouts/AdminDataLayout.tsx";
|
|
8
8
|
function AdminDataLayout() {
|
|
9
9
|
const navigate = useNavigate();
|
|
10
10
|
const params = useParams();
|
|
@@ -58,18 +58,16 @@ function AdminDataLayout() {
|
|
|
58
58
|
link.download = `admin-data-preferences-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`;
|
|
59
59
|
document.body.appendChild(link);
|
|
60
60
|
link.click();
|
|
61
|
-
|
|
61
|
+
link.remove();
|
|
62
62
|
URL.revokeObjectURL(url);
|
|
63
63
|
showNotification("success", "Preferences exported successfully");
|
|
64
64
|
};
|
|
65
|
-
const handleImport = (event) => {
|
|
65
|
+
const handleImport = async (event) => {
|
|
66
66
|
var _a;
|
|
67
67
|
const file = (_a = event.target.files) == null ? void 0 : _a[0];
|
|
68
68
|
if (!file) return;
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
var _a2;
|
|
72
|
-
const content2 = (_a2 = e.target) == null ? void 0 : _a2.result;
|
|
69
|
+
try {
|
|
70
|
+
const content2 = await file.text();
|
|
73
71
|
if (!content2) {
|
|
74
72
|
showNotification("error", "Failed to read file");
|
|
75
73
|
return;
|
|
@@ -77,186 +75,185 @@ function AdminDataLayout() {
|
|
|
77
75
|
const success = AdminLocalStorage.importConfig(content2);
|
|
78
76
|
if (success) {
|
|
79
77
|
showNotification("success", "Preferences imported successfully. Refreshing...");
|
|
80
|
-
setTimeout(() =>
|
|
78
|
+
setTimeout(() => globalThis.location.reload(), 1500);
|
|
81
79
|
} else {
|
|
82
80
|
showNotification("error", "Invalid preferences file");
|
|
83
81
|
}
|
|
84
|
-
}
|
|
85
|
-
reader.onerror = () => {
|
|
82
|
+
} catch {
|
|
86
83
|
showNotification("error", "Failed to read file");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
} finally {
|
|
85
|
+
if (fileInputRef.current) {
|
|
86
|
+
fileInputRef.current.value = "";
|
|
87
|
+
}
|
|
91
88
|
}
|
|
92
89
|
};
|
|
93
90
|
const triggerImport = () => {
|
|
94
91
|
var _a;
|
|
95
92
|
(_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
96
93
|
};
|
|
97
|
-
const content = /* @__PURE__ */ React.createElement("div", { className: "max-w-full mx-auto flex flex-col", __self: this, __source: {
|
|
94
|
+
const content = /* @__PURE__ */ React.createElement("div", { className: "max-w-full mx-auto flex flex-col p-0.5", __self: this, __source: {
|
|
98
95
|
fileName: _jsxFileName,
|
|
99
|
-
lineNumber:
|
|
96
|
+
lineNumber: 119,
|
|
100
97
|
columnNumber: 5
|
|
101
98
|
} }, notification && /* @__PURE__ */ React.createElement("div", { className: `mb-4 px-4 py-3 rounded-md border ${notification.type === "success" ? "bg-green-50 border-green-200 text-green-800 dark:bg-green-900/20 dark:border-green-800 dark:text-green-200" : "bg-red-50 border-red-200 text-red-800 dark:bg-red-900/20 dark:border-red-800 dark:text-red-200"}`, __self: this, __source: {
|
|
102
99
|
fileName: _jsxFileName,
|
|
103
|
-
lineNumber:
|
|
100
|
+
lineNumber: 122,
|
|
104
101
|
columnNumber: 9
|
|
105
102
|
} }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center", __self: this, __source: {
|
|
106
103
|
fileName: _jsxFileName,
|
|
107
|
-
lineNumber:
|
|
104
|
+
lineNumber: 127,
|
|
108
105
|
columnNumber: 11
|
|
109
106
|
} }, notification.type === "success" ? /* @__PURE__ */ React.createElement("svg", { className: "w-5 h-5 mr-2", fill: "currentColor", viewBox: "0 0 20 20", __self: this, __source: {
|
|
110
107
|
fileName: _jsxFileName,
|
|
111
|
-
lineNumber:
|
|
108
|
+
lineNumber: 129,
|
|
112
109
|
columnNumber: 15
|
|
113
110
|
} }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clipRule: "evenodd", __self: this, __source: {
|
|
114
111
|
fileName: _jsxFileName,
|
|
115
|
-
lineNumber:
|
|
112
|
+
lineNumber: 130,
|
|
116
113
|
columnNumber: 17
|
|
117
114
|
} })) : /* @__PURE__ */ React.createElement("svg", { className: "w-5 h-5 mr-2", fill: "currentColor", viewBox: "0 0 20 20", __self: this, __source: {
|
|
118
115
|
fileName: _jsxFileName,
|
|
119
|
-
lineNumber:
|
|
116
|
+
lineNumber: 133,
|
|
120
117
|
columnNumber: 15
|
|
121
118
|
} }, /* @__PURE__ */ React.createElement("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", clipRule: "evenodd", __self: this, __source: {
|
|
122
119
|
fileName: _jsxFileName,
|
|
123
|
-
lineNumber:
|
|
120
|
+
lineNumber: 134,
|
|
124
121
|
columnNumber: 17
|
|
125
122
|
} })), /* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium", __self: this, __source: {
|
|
126
123
|
fileName: _jsxFileName,
|
|
127
|
-
lineNumber:
|
|
124
|
+
lineNumber: 137,
|
|
128
125
|
columnNumber: 13
|
|
129
126
|
} }, notification.message))), /* @__PURE__ */ React.createElement("div", { className: "mb-6 space-y-3", __self: this, __source: {
|
|
130
127
|
fileName: _jsxFileName,
|
|
131
|
-
lineNumber:
|
|
128
|
+
lineNumber: 143,
|
|
132
129
|
columnNumber: 7
|
|
133
130
|
} }, /* @__PURE__ */ React.createElement("div", { className: "flex items-end gap-3", __self: this, __source: {
|
|
134
131
|
fileName: _jsxFileName,
|
|
135
|
-
lineNumber:
|
|
132
|
+
lineNumber: 144,
|
|
136
133
|
columnNumber: 9
|
|
137
134
|
} }, /* @__PURE__ */ React.createElement("div", { className: "flex-1", __self: this, __source: {
|
|
138
135
|
fileName: _jsxFileName,
|
|
139
|
-
lineNumber:
|
|
136
|
+
lineNumber: 145,
|
|
140
137
|
columnNumber: 11
|
|
141
138
|
} }, /* @__PURE__ */ React.createElement("label", { htmlFor: "model-selector", className: "block text-sm font-medium text-gray-900 dark:text-gray-100 mb-2", __self: this, __source: {
|
|
142
139
|
fileName: _jsxFileName,
|
|
143
|
-
lineNumber:
|
|
140
|
+
lineNumber: 146,
|
|
144
141
|
columnNumber: 13
|
|
145
142
|
} }, "Select Model"), /* @__PURE__ */ React.createElement("div", { className: "relative", __self: this, __source: {
|
|
146
143
|
fileName: _jsxFileName,
|
|
147
|
-
lineNumber:
|
|
144
|
+
lineNumber: 149,
|
|
148
145
|
columnNumber: 13
|
|
149
146
|
} }, /* @__PURE__ */ React.createElement("select", { id: "model-selector", value: (currentModel == null ? void 0 : currentModel.name) || "", onChange: handleModelChange, className: "w-full h-[50px] pl-4 pr-10 py-3 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web text-base appearance-none cursor-pointer", __self: this, __source: {
|
|
150
147
|
fileName: _jsxFileName,
|
|
151
|
-
lineNumber:
|
|
148
|
+
lineNumber: 150,
|
|
152
149
|
columnNumber: 15
|
|
153
150
|
} }, /* @__PURE__ */ React.createElement("option", { value: "", __self: this, __source: {
|
|
154
151
|
fileName: _jsxFileName,
|
|
155
|
-
lineNumber:
|
|
152
|
+
lineNumber: 156,
|
|
156
153
|
columnNumber: 17
|
|
157
154
|
} }, "Choose a model..."), sortedModels.map((model) => /* @__PURE__ */ React.createElement("option", { key: model.name, value: model.name, __self: this, __source: {
|
|
158
155
|
fileName: _jsxFileName,
|
|
159
|
-
lineNumber:
|
|
156
|
+
lineNumber: 158,
|
|
160
157
|
columnNumber: 19
|
|
161
158
|
} }, getPluralName(spacedWords(model.name))))), /* @__PURE__ */ React.createElement("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3", __self: this, __source: {
|
|
162
159
|
fileName: _jsxFileName,
|
|
163
|
-
lineNumber:
|
|
160
|
+
lineNumber: 164,
|
|
164
161
|
columnNumber: 15
|
|
165
162
|
} }, /* @__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", __self: this, __source: {
|
|
166
163
|
fileName: _jsxFileName,
|
|
167
|
-
lineNumber:
|
|
164
|
+
lineNumber: 165,
|
|
168
165
|
columnNumber: 17
|
|
169
166
|
} }, /* @__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: {
|
|
170
167
|
fileName: _jsxFileName,
|
|
171
|
-
lineNumber:
|
|
168
|
+
lineNumber: 166,
|
|
172
169
|
columnNumber: 19
|
|
173
170
|
} }))))), /* @__PURE__ */ React.createElement("button", { onClick: toggleFullscreen, className: "h-[50px] px-4 py-3 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-green-web focus:border-green-web transition-colors", title: isFullscreen ? "Exit fullscreen" : "Enter fullscreen", __self: this, __source: {
|
|
174
171
|
fileName: _jsxFileName,
|
|
175
|
-
lineNumber:
|
|
172
|
+
lineNumber: 173,
|
|
176
173
|
columnNumber: 11
|
|
177
174
|
} }, isFullscreen ? /* @__PURE__ */ React.createElement("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
|
|
178
175
|
fileName: _jsxFileName,
|
|
179
|
-
lineNumber:
|
|
176
|
+
lineNumber: 179,
|
|
180
177
|
columnNumber: 15
|
|
181
178
|
} }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25", __self: this, __source: {
|
|
182
179
|
fileName: _jsxFileName,
|
|
183
|
-
lineNumber:
|
|
180
|
+
lineNumber: 180,
|
|
184
181
|
columnNumber: 17
|
|
185
182
|
} })) : /* @__PURE__ */ React.createElement("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
|
|
186
183
|
fileName: _jsxFileName,
|
|
187
|
-
lineNumber:
|
|
184
|
+
lineNumber: 183,
|
|
188
185
|
columnNumber: 15
|
|
189
186
|
} }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 5l-5-5m5 5v-4m0 4h-4", __self: this, __source: {
|
|
190
187
|
fileName: _jsxFileName,
|
|
191
|
-
lineNumber:
|
|
188
|
+
lineNumber: 184,
|
|
192
189
|
columnNumber: 17
|
|
193
190
|
} })))), /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 text-sm", __self: this, __source: {
|
|
194
191
|
fileName: _jsxFileName,
|
|
195
|
-
lineNumber:
|
|
192
|
+
lineNumber: 191,
|
|
196
193
|
columnNumber: 9
|
|
197
194
|
} }, /* @__PURE__ */ React.createElement("span", { className: "text-gray-600 dark:text-gray-400", __self: this, __source: {
|
|
198
195
|
fileName: _jsxFileName,
|
|
199
|
-
lineNumber:
|
|
196
|
+
lineNumber: 192,
|
|
200
197
|
columnNumber: 11
|
|
201
198
|
} }, "Preferences:"), /* @__PURE__ */ React.createElement("button", { onClick: handleExport, className: "inline-flex items-center px-3 py-1.5 text-gray-700 dark:text-gray-300 hover:text-green-web dark:hover:text-green-web transition-colors", title: "Export your preferences to a file", __self: this, __source: {
|
|
202
199
|
fileName: _jsxFileName,
|
|
203
|
-
lineNumber:
|
|
200
|
+
lineNumber: 193,
|
|
204
201
|
columnNumber: 11
|
|
205
202
|
} }, /* @__PURE__ */ React.createElement("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
|
|
206
203
|
fileName: _jsxFileName,
|
|
207
|
-
lineNumber:
|
|
204
|
+
lineNumber: 198,
|
|
208
205
|
columnNumber: 13
|
|
209
206
|
} }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4", __self: this, __source: {
|
|
210
207
|
fileName: _jsxFileName,
|
|
211
|
-
lineNumber:
|
|
208
|
+
lineNumber: 199,
|
|
212
209
|
columnNumber: 15
|
|
213
210
|
} })), "Export"), /* @__PURE__ */ React.createElement("span", { className: "text-gray-300 dark:text-gray-600", __self: this, __source: {
|
|
214
211
|
fileName: _jsxFileName,
|
|
215
|
-
lineNumber:
|
|
212
|
+
lineNumber: 203,
|
|
216
213
|
columnNumber: 11
|
|
217
214
|
} }, "|"), /* @__PURE__ */ React.createElement("button", { onClick: triggerImport, className: "inline-flex items-center px-3 py-1.5 text-gray-700 dark:text-gray-300 hover:text-green-web dark:hover:text-green-web transition-colors", title: "Import preferences from a file", __self: this, __source: {
|
|
218
215
|
fileName: _jsxFileName,
|
|
219
|
-
lineNumber:
|
|
216
|
+
lineNumber: 204,
|
|
220
217
|
columnNumber: 11
|
|
221
218
|
} }, /* @__PURE__ */ React.createElement("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", __self: this, __source: {
|
|
222
219
|
fileName: _jsxFileName,
|
|
223
|
-
lineNumber:
|
|
220
|
+
lineNumber: 209,
|
|
224
221
|
columnNumber: 13
|
|
225
222
|
} }, /* @__PURE__ */ React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12", __self: this, __source: {
|
|
226
223
|
fileName: _jsxFileName,
|
|
227
|
-
lineNumber:
|
|
224
|
+
lineNumber: 210,
|
|
228
225
|
columnNumber: 15
|
|
229
226
|
} })), "Import"), /* @__PURE__ */ React.createElement("input", { ref: fileInputRef, type: "file", accept: "application/json,.json", onChange: handleImport, className: "hidden", __self: this, __source: {
|
|
230
227
|
fileName: _jsxFileName,
|
|
231
|
-
lineNumber:
|
|
228
|
+
lineNumber: 214,
|
|
232
229
|
columnNumber: 11
|
|
233
230
|
} }))), /* @__PURE__ */ React.createElement("div", { __self: this, __source: {
|
|
234
231
|
fileName: _jsxFileName,
|
|
235
|
-
lineNumber:
|
|
232
|
+
lineNumber: 225,
|
|
236
233
|
columnNumber: 7
|
|
237
234
|
} }, /* @__PURE__ */ React.createElement(Outlet, { __self: this, __source: {
|
|
238
235
|
fileName: _jsxFileName,
|
|
239
|
-
lineNumber:
|
|
236
|
+
lineNumber: 226,
|
|
240
237
|
columnNumber: 9
|
|
241
238
|
} })));
|
|
242
239
|
if (isFullscreen) {
|
|
243
|
-
return /* @__PURE__ */ React.createElement("div", { className: "fixed inset-0 z-50 bg-white dark:bg-gray-900 flex flex-col", __self: this, __source: {
|
|
240
|
+
return /* @__PURE__ */ React.createElement("div", { className: "fixed inset-0 z-50 bg-white dark:bg-gray-900 flex flex-col overflow-auto", __self: this, __source: {
|
|
244
241
|
fileName: _jsxFileName,
|
|
245
|
-
lineNumber:
|
|
242
|
+
lineNumber: 233,
|
|
246
243
|
columnNumber: 7
|
|
247
244
|
} }, /* @__PURE__ */ React.createElement("div", { className: "w-full p-6 md:p-8 lg:p-12", __self: this, __source: {
|
|
248
245
|
fileName: _jsxFileName,
|
|
249
|
-
lineNumber:
|
|
246
|
+
lineNumber: 234,
|
|
250
247
|
columnNumber: 9
|
|
251
248
|
} }, content));
|
|
252
249
|
}
|
|
253
250
|
return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col", __self: this, __source: {
|
|
254
251
|
fileName: _jsxFileName,
|
|
255
|
-
lineNumber:
|
|
252
|
+
lineNumber: 242,
|
|
256
253
|
columnNumber: 5
|
|
257
254
|
} }, /* @__PURE__ */ React.createElement("main", { className: "w-full p-6 md:p-8 lg:p-12", __self: this, __source: {
|
|
258
255
|
fileName: _jsxFileName,
|
|
259
|
-
lineNumber:
|
|
256
|
+
lineNumber: 243,
|
|
260
257
|
columnNumber: 7
|
|
261
258
|
} }, content));
|
|
262
259
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import React, { useState, useMemo, useEffect } from "react";
|
|
1
2
|
import { gql } from "@apollo/client";
|
|
2
3
|
import { useMutation } from "@apollo/client/react";
|
|
3
4
|
import { ExclamationCircleIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
|
4
|
-
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
5
5
|
import { ErrorBoundary } from "@nestledjs/shared-components";
|
|
6
6
|
import { Form } from "@nestledjs/forms";
|
|
7
|
-
import {
|
|
7
|
+
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
8
8
|
import { useParams, Link, useNavigate } from "react-router";
|
|
9
9
|
import { getAdminDocuments, buildFormFields, cleanFormInput } from "../utils/graphql-utils.js";
|
|
10
|
-
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/
|
|
10
|
+
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/data-browser/src/lib/pages/AdminDataCreatePage.tsx";
|
|
11
11
|
function toReadableText(text) {
|
|
12
12
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (str) => str.toUpperCase());
|
|
13
13
|
}
|
|
@@ -132,7 +132,8 @@ function AdminDataCreatePageContent({
|
|
|
132
132
|
}) {
|
|
133
133
|
const navigate = useNavigate();
|
|
134
134
|
const {
|
|
135
|
-
sdk
|
|
135
|
+
sdk,
|
|
136
|
+
databaseModels
|
|
136
137
|
} = useAdminDataContext();
|
|
137
138
|
const [submissionState, setSubmissionState] = useState({
|
|
138
139
|
status: "idle"
|
|
@@ -202,7 +203,7 @@ function AdminDataCreatePageContent({
|
|
|
202
203
|
columnNumber: 17
|
|
203
204
|
} }, "Return to Data Browser"))))));
|
|
204
205
|
}
|
|
205
|
-
const formFields = buildFormFields(sdk, model, "create");
|
|
206
|
+
const formFields = buildFormFields(sdk, model, "create", void 0, submissionState.status === "loading", basePath, databaseModels);
|
|
206
207
|
const handleSubmit = async (formData) => {
|
|
207
208
|
try {
|
|
208
209
|
setSubmissionState({
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
+
import React, { useState, useMemo, useEffect } from "react";
|
|
1
2
|
import { gql } from "@apollo/client";
|
|
2
3
|
import { useQuery, useMutation } from "@apollo/client/react";
|
|
3
4
|
import { loadDevMessages, loadErrorMessages } from "@apollo/client/dev";
|
|
4
5
|
import { ExclamationCircleIcon, CheckCircleIcon } from "@heroicons/react/24/outline";
|
|
5
6
|
import { TrashIcon } from "@heroicons/react/24/solid";
|
|
6
|
-
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
7
7
|
import { ErrorBoundary } from "@nestledjs/shared-components";
|
|
8
8
|
import { Form } from "@nestledjs/forms";
|
|
9
|
-
import {
|
|
9
|
+
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
10
10
|
import { useParams, Link, useNavigate } from "react-router";
|
|
11
11
|
import { getAdminDocuments, buildFormFields, cleanFormInput } from "../utils/graphql-utils.js";
|
|
12
|
-
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/
|
|
12
|
+
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/data-browser/src/lib/pages/AdminDataEditPage.tsx";
|
|
13
13
|
function toLowerCamelCase(name) {
|
|
14
14
|
if (!name) return "";
|
|
15
15
|
return name.charAt(0).toLowerCase() + name.slice(1);
|
|
@@ -166,7 +166,8 @@ function AdminDataEditPageContent({
|
|
|
166
166
|
}) {
|
|
167
167
|
const navigate = useNavigate();
|
|
168
168
|
const {
|
|
169
|
-
sdk
|
|
169
|
+
sdk,
|
|
170
|
+
databaseModels
|
|
170
171
|
} = useAdminDataContext();
|
|
171
172
|
const [submissionState, setSubmissionState] = useState({
|
|
172
173
|
status: "idle"
|
|
@@ -423,7 +424,7 @@ function AdminDataEditPageContent({
|
|
|
423
424
|
columnNumber: 17
|
|
424
425
|
} }, "Back to List"))))));
|
|
425
426
|
}
|
|
426
|
-
const formFields = buildFormFields(sdk, model, "update");
|
|
427
|
+
const formFields = buildFormFields(sdk, model, "update", item, submissionState.status === "loading", basePath, databaseModels);
|
|
427
428
|
const initialValues = {};
|
|
428
429
|
if (item) {
|
|
429
430
|
const editableFields = model.fields.filter((field) => {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import { Link } from "react-router";
|
|
2
3
|
import { getPluralName } from "@nestledjs/helpers";
|
|
3
4
|
import { useAdminDataContext } from "../context/AdminDataContext.js";
|
|
4
5
|
import { kebabCase, spacedWords } from "../utils/string-utils.js";
|
|
5
|
-
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/
|
|
6
|
+
var _jsxFileName = "/Users/justinhandley/IdeaProjects/nestled_template/libs/data-browser/src/lib/pages/AdminDataIndexPage.tsx";
|
|
6
7
|
function AdminDataIndexPage() {
|
|
7
8
|
const {
|
|
8
9
|
databaseModels,
|
|
@@ -10,51 +11,51 @@ function AdminDataIndexPage() {
|
|
|
10
11
|
} = useAdminDataContext();
|
|
11
12
|
return /* @__PURE__ */ React.createElement("div", { className: "text-center py-12", __self: this, __source: {
|
|
12
13
|
fileName: _jsxFileName,
|
|
13
|
-
lineNumber:
|
|
14
|
+
lineNumber: 14,
|
|
14
15
|
columnNumber: 5
|
|
15
16
|
} }, /* @__PURE__ */ React.createElement("div", { className: "max-w-2xl mx-auto", __self: this, __source: {
|
|
16
17
|
fileName: _jsxFileName,
|
|
17
|
-
lineNumber:
|
|
18
|
+
lineNumber: 15,
|
|
18
19
|
columnNumber: 7
|
|
19
20
|
} }, /* @__PURE__ */ React.createElement("h1", { className: "text-3xl font-bold text-gray-900 dark:text-gray-100 mb-4", __self: this, __source: {
|
|
20
21
|
fileName: _jsxFileName,
|
|
21
|
-
lineNumber:
|
|
22
|
+
lineNumber: 16,
|
|
22
23
|
columnNumber: 9
|
|
23
24
|
} }, "Database Administration"), /* @__PURE__ */ React.createElement("p", { className: "text-lg text-gray-600 dark:text-gray-300 mb-8", __self: this, __source: {
|
|
24
25
|
fileName: _jsxFileName,
|
|
25
|
-
lineNumber:
|
|
26
|
+
lineNumber: 17,
|
|
26
27
|
columnNumber: 9
|
|
27
28
|
} }, "Choose a data model from the sidebar to get started with managing your database records."), /* @__PURE__ */ React.createElement("div", { className: "bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-6 mb-8", __self: this, __source: {
|
|
28
29
|
fileName: _jsxFileName,
|
|
29
|
-
lineNumber:
|
|
30
|
+
lineNumber: 21,
|
|
30
31
|
columnNumber: 9
|
|
31
32
|
} }, /* @__PURE__ */ React.createElement("h2", { className: "text-lg font-semibold text-blue-900 dark:text-blue-200 mb-2", __self: this, __source: {
|
|
32
33
|
fileName: _jsxFileName,
|
|
33
|
-
lineNumber:
|
|
34
|
+
lineNumber: 22,
|
|
34
35
|
columnNumber: 11
|
|
35
36
|
} }, "Available Models"), /* @__PURE__ */ React.createElement("p", { className: "text-blue-700 dark:text-blue-300 mb-4", __self: this, __source: {
|
|
36
37
|
fileName: _jsxFileName,
|
|
37
|
-
lineNumber:
|
|
38
|
+
lineNumber: 23,
|
|
38
39
|
columnNumber: 11
|
|
39
40
|
} }, "You can manage ", databaseModels.length, " different data models in your database:"), /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-2 text-sm", __self: this, __source: {
|
|
40
41
|
fileName: _jsxFileName,
|
|
41
|
-
lineNumber:
|
|
42
|
+
lineNumber: 26,
|
|
42
43
|
columnNumber: 11
|
|
43
44
|
} }, databaseModels.slice(0, 12).map((model) => /* @__PURE__ */ React.createElement(Link, { key: model.name, to: `${basePath}/${kebabCase(getPluralName(model.name))}`, className: "text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 hover:underline", __self: this, __source: {
|
|
44
45
|
fileName: _jsxFileName,
|
|
45
|
-
lineNumber:
|
|
46
|
+
lineNumber: 28,
|
|
46
47
|
columnNumber: 15
|
|
47
48
|
} }, getPluralName(spacedWords(model.name)))), databaseModels.length > 12 && /* @__PURE__ */ React.createElement("span", { className: "text-blue-600 dark:text-blue-400 italic", __self: this, __source: {
|
|
48
49
|
fileName: _jsxFileName,
|
|
49
|
-
lineNumber:
|
|
50
|
+
lineNumber: 37,
|
|
50
51
|
columnNumber: 15
|
|
51
52
|
} }, "+", databaseModels.length - 12, " more..."))), /* @__PURE__ */ React.createElement("div", { className: "text-sm text-gray-500 dark:text-gray-400", __self: this, __source: {
|
|
52
53
|
fileName: _jsxFileName,
|
|
53
|
-
lineNumber:
|
|
54
|
+
lineNumber: 42,
|
|
54
55
|
columnNumber: 9
|
|
55
56
|
} }, /* @__PURE__ */ React.createElement("p", { __self: this, __source: {
|
|
56
57
|
fileName: _jsxFileName,
|
|
57
|
-
lineNumber:
|
|
58
|
+
lineNumber: 43,
|
|
58
59
|
columnNumber: 11
|
|
59
60
|
} }, "This interface provides full CRUD (Create, Read, Update, Delete) operations for all your database models. Select a model from the sidebar to view and manage records."))));
|
|
60
61
|
}
|