@dyrected/admin 2.5.46 → 2.5.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.css +32 -119
- package/dist/index.mjs +390 -290
- package/package.json +4 -3
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { HashRouter, Link, MemoryRouter, Route, Routes, useLocation, useNavigate
|
|
|
5
5
|
import { QueryClient, QueryClientProvider, useInfiniteQuery, useMutation, useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
6
6
|
import { createClient } from "@dyrected/sdk";
|
|
7
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, Archive, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ArrowUpRight, Bold,
|
|
8
|
+
import { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, Archive, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, ArrowUpRight, Bold, Braces, Calendar, Check, CheckCircle, CheckCircle2, ChevronDown, ChevronDownIcon, ChevronLeft, ChevronLeftIcon, ChevronRight, ChevronRightIcon, ChevronUp, ChevronsUpDown, Circle, Clock, Clock3, Code, Copy, Database, Download, ExternalLink, Eye, EyeOff, FileDown, FileIcon, FileText, FileUp, Filter, Globe, GripVertical, Heading1, Heading2, Image as Image$1, Info, Italic, KeyRound, Layers, LayoutDashboard, Library, Link as Link$1, List, ListOrdered, Loader2, Lock, LogOut, Mail, Menu, Monitor, Moon, MoreHorizontal, PanelLeftClose, PanelLeftOpen, Pencil, Play, Plus, Quote, RotateCcw, Save, Scissors, Search, Settings, Settings2, Share2, Shield, Smartphone, Sparkles, Strikethrough, Sun, Table, Trash2, Underline, Undo2, Upload, UploadCloud, Users, Video, Volume2, X, XCircle, icons } from "lucide-react";
|
|
9
9
|
import { clsx } from "clsx";
|
|
10
10
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
11
11
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
@@ -19,13 +19,13 @@ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
|
19
19
|
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
|
|
20
20
|
import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
21
21
|
import { CSS } from "@dnd-kit/utilities";
|
|
22
|
-
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
23
22
|
import Papa from "papaparse";
|
|
24
23
|
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
25
24
|
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
|
|
26
25
|
import jexl from "jexl";
|
|
27
26
|
import { DataSheetGrid, checkboxColumn, keyColumn, textColumn } from "react-datasheet-grid";
|
|
28
27
|
import "react-datasheet-grid/dist/style.css";
|
|
28
|
+
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
29
29
|
import { EditorContent, useEditor } from "@tiptap/react";
|
|
30
30
|
import StarterKit from "@tiptap/starter-kit";
|
|
31
31
|
import TextAlign from "@tiptap/extension-text-align";
|
|
@@ -50,12 +50,11 @@ import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
|
50
50
|
import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio";
|
|
51
51
|
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
52
52
|
import { Blurhash } from "react-blurhash";
|
|
53
|
+
import { GENERATE_CMS_PROMPT } from "@dyrected/knowledge";
|
|
53
54
|
//#region src/providers/admin-auth.ts
|
|
54
55
|
function getAdminCollectionSlug(schemas) {
|
|
55
56
|
if (!schemas) return null;
|
|
56
|
-
|
|
57
|
-
if (requested) return requested;
|
|
58
|
-
return findCollection(schemas.collections, (collection) => collection.slug === "__admins")?.slug ?? findCollection(schemas.collections, (collection) => !!collection.auth)?.slug ?? null;
|
|
57
|
+
return findCollection(schemas.collections, (collection) => collection.slug === "__admins")?.slug ?? findCollection(schemas.collections, (collection) => collection.slug === schemas.adminAuth?.collectionSlug)?.slug ?? findCollection(schemas.collections, (collection) => !!collection.auth)?.slug ?? null;
|
|
59
58
|
}
|
|
60
59
|
function findCollection(collections, predicate) {
|
|
61
60
|
return collections.find(predicate);
|
|
@@ -75,7 +74,8 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
|
|
|
75
74
|
const [apiKey, setApiKey] = useState(() => initialApiKey || (typeof window !== "undefined" ? localStorage.getItem("dyrected_key") : null) || void 0);
|
|
76
75
|
const [siteId, setSiteId] = useState(() => initialSiteId || (typeof window !== "undefined" ? localStorage.getItem("dyrected_site_id") : null) || void 0);
|
|
77
76
|
const [schemas, setSchemas] = useState(null);
|
|
78
|
-
const
|
|
77
|
+
const initialTokenUser = useMemo(() => initialToken ? decodeTokenPayload(initialToken) : null, [initialToken]);
|
|
78
|
+
const [user, setUser] = useState(() => initialTokenUser);
|
|
79
79
|
const [authCollectionSlug, setAuthCollectionSlug] = useState(() => (typeof window !== "undefined" ? localStorage.getItem("dyrected_admin_auth_collection") : null) || null);
|
|
80
80
|
const client = useMemo(() => {
|
|
81
81
|
if (!baseUrl) return null;
|
|
@@ -106,6 +106,7 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
|
|
|
106
106
|
cancelled = true;
|
|
107
107
|
};
|
|
108
108
|
}, [client]);
|
|
109
|
+
const activeUser = initialTokenUser ?? user;
|
|
109
110
|
useEffect(() => {
|
|
110
111
|
if (initialToken && client) client.setToken(initialToken);
|
|
111
112
|
}, [initialToken, client]);
|
|
@@ -143,32 +144,26 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
|
|
|
143
144
|
schemas
|
|
144
145
|
]);
|
|
145
146
|
useEffect(() => {
|
|
146
|
-
if (initialToken || !client || !schemas ||
|
|
147
|
+
if (initialToken || !client || !schemas || activeUser) return;
|
|
147
148
|
const token = localStorage.getItem("dyrected_token");
|
|
148
149
|
const resolvedCollectionSlug = authCollectionSlug || getAdminCollectionSlug(schemas);
|
|
149
150
|
if (!token || !resolvedCollectionSlug) return;
|
|
150
151
|
client.setToken(token);
|
|
151
152
|
client.collection(resolvedCollectionSlug).me().then((nextUser) => setUser(nextUser), () => setUser(null));
|
|
152
153
|
}, [
|
|
154
|
+
activeUser,
|
|
153
155
|
authCollectionSlug,
|
|
154
156
|
client,
|
|
155
157
|
initialToken,
|
|
156
|
-
schemas
|
|
157
|
-
user
|
|
158
|
+
schemas
|
|
158
159
|
]);
|
|
159
160
|
const logout = useCallback(() => {
|
|
160
|
-
localStorage.removeItem("dyrected_url");
|
|
161
|
-
localStorage.removeItem("dyrected_key");
|
|
162
|
-
localStorage.removeItem("dyrected_site_id");
|
|
163
161
|
localStorage.removeItem("dyrected_token");
|
|
164
162
|
localStorage.removeItem("dyrected_admin_auth_collection");
|
|
165
|
-
|
|
166
|
-
setApiKey(void 0);
|
|
167
|
-
setSiteId(void 0);
|
|
163
|
+
if (client) client.clearToken();
|
|
168
164
|
setAuthCollectionSlug(null);
|
|
169
165
|
setUser(null);
|
|
170
|
-
|
|
171
|
-
}, []);
|
|
166
|
+
}, [client]);
|
|
172
167
|
return /* @__PURE__ */ jsx(DyrectedContext.Provider, {
|
|
173
168
|
value: {
|
|
174
169
|
client,
|
|
@@ -183,13 +178,37 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
|
|
|
183
178
|
logout,
|
|
184
179
|
isAuthenticated: !!baseUrl && !!apiKey,
|
|
185
180
|
schemas,
|
|
186
|
-
user,
|
|
181
|
+
user: activeUser,
|
|
187
182
|
initialToken,
|
|
188
183
|
components
|
|
189
184
|
},
|
|
190
185
|
children
|
|
191
186
|
});
|
|
192
187
|
}
|
|
188
|
+
function decodeTokenPayload(token) {
|
|
189
|
+
const payload = token.split(".")[1];
|
|
190
|
+
if (!payload) return null;
|
|
191
|
+
try {
|
|
192
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
193
|
+
const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, "=");
|
|
194
|
+
const json = decodeURIComponent(atob(padded).split("").map((char) => `%${char.charCodeAt(0).toString(16).padStart(2, "0")}`).join(""));
|
|
195
|
+
const parsed = JSON.parse(json);
|
|
196
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
197
|
+
const user = parsed;
|
|
198
|
+
const roles = Array.isArray(user.roles) ? user.roles.filter((role) => typeof role === "string").map(normalizeCloudRole) : [];
|
|
199
|
+
const role = typeof user.role === "string" ? normalizeCloudRole(user.role) : void 0;
|
|
200
|
+
return {
|
|
201
|
+
...user,
|
|
202
|
+
...role ? { role } : {},
|
|
203
|
+
roles: roles.length > 0 ? roles : role ? [role] : roles
|
|
204
|
+
};
|
|
205
|
+
} catch {
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function normalizeCloudRole(role) {
|
|
210
|
+
return role === "owner" ? "admin" : role;
|
|
211
|
+
}
|
|
193
212
|
//#endregion
|
|
194
213
|
//#region src/providers/query-provider.tsx
|
|
195
214
|
function QueryProvider({ children }) {
|
|
@@ -616,7 +635,7 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
616
635
|
const OptionIcon = option.icon;
|
|
617
636
|
return /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
|
|
618
637
|
value: option.value,
|
|
619
|
-
className: "dy-cursor-pointer",
|
|
638
|
+
className: "dy-cursor-pointer dy-space-x-2",
|
|
620
639
|
children: [/* @__PURE__ */ jsx(OptionIcon, { className: "dy-h-4 dy-w-4" }), option.label]
|
|
621
640
|
}, option.value);
|
|
622
641
|
})
|
|
@@ -915,7 +934,7 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
915
934
|
className: "dy-ml-auto dy-flex dy-items-center dy-gap-1.5",
|
|
916
935
|
children: [/* @__PURE__ */ jsx(ThemeSelector, { mobile: true }), user && /* @__PURE__ */ jsx("div", {
|
|
917
936
|
className: "dy-flex dy-h-8 dy-w-8 dy-items-center dy-justify-center dy-rounded-full dy-bg-primary/10 dy-text-primary dy-font-semibold dy-text-xs dy-shrink-0",
|
|
918
|
-
children: (user.name || user.email || "?")
|
|
937
|
+
children: (user.name || user.email || "?").charAt(0).toUpperCase()
|
|
919
938
|
})]
|
|
920
939
|
})
|
|
921
940
|
]
|
|
@@ -2047,59 +2066,6 @@ var Checkbox = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
2047
2066
|
}));
|
|
2048
2067
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
2049
2068
|
//#endregion
|
|
2050
|
-
//#region src/components/ui/dialog.tsx
|
|
2051
|
-
var Dialog = DialogPrimitive.Root;
|
|
2052
|
-
var DialogTrigger = DialogPrimitive.Trigger;
|
|
2053
|
-
var DialogPortal = DialogPrimitive.Portal;
|
|
2054
|
-
var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
|
|
2055
|
-
ref,
|
|
2056
|
-
className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
|
|
2057
|
-
...props
|
|
2058
|
-
}));
|
|
2059
|
-
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
2060
|
-
var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
|
|
2061
|
-
const { resolvedTheme, themeClassName } = useAdminTheme();
|
|
2062
|
-
return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
2063
|
-
className: themeClassName,
|
|
2064
|
-
"data-theme": resolvedTheme,
|
|
2065
|
-
children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
|
|
2066
|
-
ref,
|
|
2067
|
-
className: cn("dy-fixed dy-left-[50%] dy-top-[50%] dy-z-50 dy-grid dy-w-full dy-max-w-lg dy-translate-x-[-50%] dy-translate-y-[-50%] dy-gap-4 dy-border dy-bg-background dy-p-6 dy-shadow-2xl dy-duration-200 data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0 data-[state=closed]:dy-zoom-out-95 data-[state=open]:dy-zoom-in-95 data-[state=closed]:dy-slide-out-to-left-1/2 data-[state=closed]:dy-slide-out-to-top-[48%] data-[state=open]:dy-slide-in-from-left-1/2 data-[state=open]:dy-slide-in-from-top-[48%] sm:dy-rounded-xl", className),
|
|
2068
|
-
...props,
|
|
2069
|
-
children: [children, /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
|
|
2070
|
-
className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-accent data-[state=open]:dy-text-muted-foreground",
|
|
2071
|
-
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
2072
|
-
className: "dy-sr-only",
|
|
2073
|
-
children: "Close"
|
|
2074
|
-
})]
|
|
2075
|
-
})]
|
|
2076
|
-
})]
|
|
2077
|
-
}) });
|
|
2078
|
-
});
|
|
2079
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
2080
|
-
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2081
|
-
className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
|
|
2082
|
-
...props
|
|
2083
|
-
});
|
|
2084
|
-
DialogHeader.displayName = "DialogHeader";
|
|
2085
|
-
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2086
|
-
className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
|
|
2087
|
-
...props
|
|
2088
|
-
});
|
|
2089
|
-
DialogFooter.displayName = "DialogFooter";
|
|
2090
|
-
var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
2091
|
-
ref,
|
|
2092
|
-
className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
|
|
2093
|
-
...props
|
|
2094
|
-
}));
|
|
2095
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
2096
|
-
var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, {
|
|
2097
|
-
ref,
|
|
2098
|
-
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
2099
|
-
...props
|
|
2100
|
-
}));
|
|
2101
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
2102
|
-
//#endregion
|
|
2103
2069
|
//#region src/components/ui/progress.tsx
|
|
2104
2070
|
var Progress = React$1.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(ProgressPrimitive.Root, {
|
|
2105
2071
|
ref,
|
|
@@ -2145,39 +2111,72 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2145
2111
|
const [parsedRows, setParsedRows] = React$1.useState([]);
|
|
2146
2112
|
const [mapping, setMapping] = React$1.useState({});
|
|
2147
2113
|
const [validatedData, setValidatedData] = React$1.useState([]);
|
|
2114
|
+
const [isDragging, setIsDragging] = React$1.useState(false);
|
|
2115
|
+
const [fileError, setFileError] = React$1.useState(null);
|
|
2116
|
+
const [confirmedSkip, setConfirmedSkip] = React$1.useState(false);
|
|
2148
2117
|
const [totalRows, setTotalRows] = React$1.useState(0);
|
|
2149
2118
|
const [processedCount, setProcessedCount] = React$1.useState(0);
|
|
2150
2119
|
const [successCount, setSuccessCount] = React$1.useState(0);
|
|
2151
2120
|
const [failedRows, setFailedRows] = React$1.useState([]);
|
|
2121
|
+
const [retryableRows, setRetryableRows] = React$1.useState([]);
|
|
2152
2122
|
const importableFields = React$1.useMemo(() => {
|
|
2153
2123
|
return schema.fields.filter((f) => f.name !== "id" && f.name !== "createdAt" && f.name !== "updatedAt" && f.type !== "row" && f.type !== "join" && !f.admin?.hidden);
|
|
2154
2124
|
}, [schema]);
|
|
2155
2125
|
const requiredFields = React$1.useMemo(() => {
|
|
2156
2126
|
return importableFields.filter((f) => f.required);
|
|
2157
2127
|
}, [importableFields]);
|
|
2158
|
-
const
|
|
2159
|
-
|
|
2160
|
-
if (!
|
|
2161
|
-
|
|
2128
|
+
const processFile = (file) => {
|
|
2129
|
+
setFileError(null);
|
|
2130
|
+
if (!(file.type === "text/csv" || file.name.toLowerCase().endsWith(".csv"))) {
|
|
2131
|
+
setFileError(`Unsupported file type: "${file.name}". Please upload a CSV file.`);
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
Papa.parse(file, {
|
|
2162
2135
|
header: true,
|
|
2163
2136
|
skipEmptyLines: "greedy",
|
|
2164
2137
|
complete: (results) => {
|
|
2165
2138
|
const headers = results.meta.fields || [];
|
|
2139
|
+
const rows = results.data;
|
|
2140
|
+
if (rows.length === 0) {
|
|
2141
|
+
setFileError("This CSV file has no importable rows. Please upload a file with at least one data row.");
|
|
2142
|
+
return;
|
|
2143
|
+
}
|
|
2166
2144
|
setCsvHeaders(headers);
|
|
2167
|
-
setParsedRows(
|
|
2145
|
+
setParsedRows(rows);
|
|
2168
2146
|
const initialMapping = {};
|
|
2169
2147
|
headers.forEach((header) => {
|
|
2170
|
-
|
|
2171
|
-
initialMapping[header] = match ? match.name : "__ignore__";
|
|
2148
|
+
initialMapping[header] = importableFields.find((f) => f.name?.toLowerCase() === header.toLowerCase() || f.label?.toLowerCase() === header.toLowerCase())?.name ?? "__ignore__";
|
|
2172
2149
|
});
|
|
2173
2150
|
setMapping(initialMapping);
|
|
2174
2151
|
setStep("map");
|
|
2175
2152
|
},
|
|
2176
2153
|
error: (error) => {
|
|
2177
|
-
|
|
2154
|
+
setFileError(`Failed to parse CSV: ${error.message}`);
|
|
2178
2155
|
}
|
|
2179
2156
|
});
|
|
2180
2157
|
};
|
|
2158
|
+
const handleFileChange = (e) => {
|
|
2159
|
+
const selectedFile = e.target.files?.[0];
|
|
2160
|
+
if (selectedFile) processFile(selectedFile);
|
|
2161
|
+
e.target.value = "";
|
|
2162
|
+
};
|
|
2163
|
+
const handleDragOver = (e) => {
|
|
2164
|
+
e.preventDefault();
|
|
2165
|
+
e.stopPropagation();
|
|
2166
|
+
setIsDragging(true);
|
|
2167
|
+
};
|
|
2168
|
+
const handleDragLeave = (e) => {
|
|
2169
|
+
e.preventDefault();
|
|
2170
|
+
e.stopPropagation();
|
|
2171
|
+
setIsDragging(false);
|
|
2172
|
+
};
|
|
2173
|
+
const handleDrop = (e) => {
|
|
2174
|
+
e.preventDefault();
|
|
2175
|
+
e.stopPropagation();
|
|
2176
|
+
setIsDragging(false);
|
|
2177
|
+
const file = e.dataTransfer.files?.[0];
|
|
2178
|
+
if (file) processFile(file);
|
|
2179
|
+
};
|
|
2181
2180
|
const handleMapChange = (header, fieldName) => {
|
|
2182
2181
|
setMapping((prev) => ({
|
|
2183
2182
|
...prev,
|
|
@@ -2292,18 +2291,21 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2292
2291
|
isValid
|
|
2293
2292
|
};
|
|
2294
2293
|
}));
|
|
2294
|
+
setConfirmedSkip(false);
|
|
2295
2295
|
setStep("preview");
|
|
2296
2296
|
};
|
|
2297
|
-
const startImport = async () => {
|
|
2297
|
+
const startImport = async (rows = validatedData) => {
|
|
2298
2298
|
setStep("importing");
|
|
2299
|
-
setTotalRows(
|
|
2299
|
+
setTotalRows(rows.length);
|
|
2300
2300
|
setProcessedCount(0);
|
|
2301
2301
|
setSuccessCount(0);
|
|
2302
2302
|
setFailedRows([]);
|
|
2303
|
+
setRetryableRows([]);
|
|
2303
2304
|
let success = 0;
|
|
2304
2305
|
const failures = [];
|
|
2305
|
-
|
|
2306
|
-
|
|
2306
|
+
const apiFailures = [];
|
|
2307
|
+
for (let i = 0; i < rows.length; i++) {
|
|
2308
|
+
const rowResult = rows[i];
|
|
2307
2309
|
setProcessedCount(i + 1);
|
|
2308
2310
|
if (!rowResult.isValid) {
|
|
2309
2311
|
failures.push({
|
|
@@ -2333,17 +2335,24 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2333
2335
|
success++;
|
|
2334
2336
|
setSuccessCount(success);
|
|
2335
2337
|
} catch (error) {
|
|
2338
|
+
const message = error.message || "Failed to create entry";
|
|
2336
2339
|
failures.push({
|
|
2337
2340
|
row: rowResult.rowNumber,
|
|
2338
2341
|
data: rowResult.data,
|
|
2339
|
-
error:
|
|
2342
|
+
error: message
|
|
2340
2343
|
});
|
|
2341
2344
|
setFailedRows([...failures]);
|
|
2345
|
+
apiFailures.push(rowResult);
|
|
2342
2346
|
}
|
|
2343
2347
|
}
|
|
2348
|
+
setRetryableRows(apiFailures);
|
|
2344
2349
|
queryClient.invalidateQueries({ queryKey: ["collection", slug] });
|
|
2345
2350
|
setStep("complete");
|
|
2346
2351
|
};
|
|
2352
|
+
const handleRetryFailed = () => {
|
|
2353
|
+
setValidatedData(retryableRows);
|
|
2354
|
+
startImport(retryableRows);
|
|
2355
|
+
};
|
|
2347
2356
|
const downloadFailedCsv = () => {
|
|
2348
2357
|
if (failedRows.length === 0) return;
|
|
2349
2358
|
const headers = [...csvHeaders, "Import Error"];
|
|
@@ -2375,14 +2384,17 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2375
2384
|
return /* @__PURE__ */ jsxs("div", {
|
|
2376
2385
|
className: "dy-space-y-6",
|
|
2377
2386
|
children: [
|
|
2378
|
-
step === "upload" && /* @__PURE__ */
|
|
2387
|
+
step === "upload" && /* @__PURE__ */ jsxs("div", {
|
|
2379
2388
|
className: "dy-space-y-4",
|
|
2380
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
2381
|
-
className: "dy-text-center dy-py-10 dy-border-2 dy-border-dashed dy-border-
|
|
2389
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2390
|
+
className: cn("dy-text-center dy-py-10 dy-border-2 dy-border-dashed dy-rounded-xl dy-transition-colors", isDragging ? "dy-border-primary dy-bg-primary/5" : "dy-border-border hover:dy-bg-muted/30"),
|
|
2391
|
+
onDragOver: handleDragOver,
|
|
2392
|
+
onDragLeave: handleDragLeave,
|
|
2393
|
+
onDrop: handleDrop,
|
|
2382
2394
|
children: /* @__PURE__ */ jsxs("label", {
|
|
2383
2395
|
className: "dy-cursor-pointer dy-block dy-space-y-4 dy-px-6",
|
|
2384
2396
|
children: [
|
|
2385
|
-
/* @__PURE__ */ jsx(Upload, { className: "dy-h-10 dy-w-10 dy-mx-auto dy-text-muted-foreground" }),
|
|
2397
|
+
/* @__PURE__ */ jsx(Upload, { className: cn("dy-h-10 dy-w-10 dy-mx-auto", isDragging ? "dy-text-primary" : "dy-text-muted-foreground") }),
|
|
2386
2398
|
/* @__PURE__ */ jsxs("div", {
|
|
2387
2399
|
className: "dy-space-y-1",
|
|
2388
2400
|
children: [/* @__PURE__ */ jsx("p", {
|
|
@@ -2401,7 +2413,10 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2401
2413
|
})
|
|
2402
2414
|
]
|
|
2403
2415
|
})
|
|
2404
|
-
})
|
|
2416
|
+
}), fileError && /* @__PURE__ */ jsxs("div", {
|
|
2417
|
+
className: "dy-flex dy-items-center dy-gap-2 dy-p-3 dy-rounded-lg dy-bg-destructive/10 dy-border dy-border-destructive/20 dy-text-destructive dy-text-sm",
|
|
2418
|
+
children: [/* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }), fileError]
|
|
2419
|
+
})]
|
|
2405
2420
|
}),
|
|
2406
2421
|
step === "map" && /* @__PURE__ */ jsxs("div", {
|
|
2407
2422
|
className: "dy-space-y-4",
|
|
@@ -2505,19 +2520,22 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2505
2520
|
})]
|
|
2506
2521
|
}),
|
|
2507
2522
|
/* @__PURE__ */ jsx("div", {
|
|
2508
|
-
className: "dy-
|
|
2523
|
+
className: "dy-overflow-x-auto dy-overflow-y-auto dy-max-h-[60vh] dy-border dy-border-border dy-rounded-xl",
|
|
2509
2524
|
children: /* @__PURE__ */ jsxs("table", {
|
|
2510
|
-
className: "dy-w-
|
|
2511
|
-
children: [/* @__PURE__ */ jsx("thead", {
|
|
2512
|
-
className: "dy-
|
|
2513
|
-
children:
|
|
2514
|
-
className: "dy-
|
|
2515
|
-
children: "
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2525
|
+
className: "dy-min-w-max dy-w-full dy-text-left dy-border-collapse",
|
|
2526
|
+
children: [/* @__PURE__ */ jsx("thead", {
|
|
2527
|
+
className: "dy-sticky dy-top-0 dy-z-10",
|
|
2528
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
2529
|
+
className: "dy-border-b dy-border-border dy-bg-muted/40 dy-text-xs dy-font-semibold dy-text-muted-foreground",
|
|
2530
|
+
children: [/* @__PURE__ */ jsx("th", {
|
|
2531
|
+
className: "dy-p-3 dy-w-16",
|
|
2532
|
+
children: "Row"
|
|
2533
|
+
}), importableFields.filter((f) => Object.values(mapping).includes(f.name)).map((f) => /* @__PURE__ */ jsx("th", {
|
|
2534
|
+
className: "dy-p-3",
|
|
2535
|
+
children: f.label || f.name
|
|
2536
|
+
}, f.name))]
|
|
2537
|
+
})
|
|
2538
|
+
}), /* @__PURE__ */ jsx("tbody", {
|
|
2521
2539
|
className: "dy-text-sm",
|
|
2522
2540
|
children: previewRows.map((rowResult) => /* @__PURE__ */ jsxs("tr", {
|
|
2523
2541
|
className: "dy-border-b dy-border-border hover:dy-bg-muted/20",
|
|
@@ -2539,6 +2557,39 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2539
2557
|
})]
|
|
2540
2558
|
})
|
|
2541
2559
|
}),
|
|
2560
|
+
totalErrors > 0 && totalErrors < validatedData.length && /* @__PURE__ */ jsxs("label", {
|
|
2561
|
+
className: "dy-flex dy-items-start dy-gap-3 dy-p-3 dy-rounded-lg dy-border dy-border-amber-300/60 dy-bg-amber-500/10 dy-cursor-pointer",
|
|
2562
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
2563
|
+
type: "checkbox",
|
|
2564
|
+
className: "dy-mt-0.5 dy-accent-amber-500",
|
|
2565
|
+
checked: confirmedSkip,
|
|
2566
|
+
onChange: (e) => setConfirmedSkip(e.target.checked)
|
|
2567
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
2568
|
+
className: "dy-text-xs dy-text-amber-700 dark:dy-text-amber-400",
|
|
2569
|
+
children: [
|
|
2570
|
+
"I understand that ",
|
|
2571
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
2572
|
+
totalErrors,
|
|
2573
|
+
" row",
|
|
2574
|
+
totalErrors !== 1 ? "s" : ""
|
|
2575
|
+
] }),
|
|
2576
|
+
" with validation errors will be skipped. Only the ",
|
|
2577
|
+
validatedData.length - totalErrors,
|
|
2578
|
+
" valid row",
|
|
2579
|
+
validatedData.length - totalErrors !== 1 ? "s" : "",
|
|
2580
|
+
" will be imported."
|
|
2581
|
+
]
|
|
2582
|
+
})]
|
|
2583
|
+
}),
|
|
2584
|
+
totalErrors === validatedData.length && /* @__PURE__ */ jsxs("div", {
|
|
2585
|
+
className: "dy-flex dy-items-center dy-gap-2 dy-p-3 dy-rounded-lg dy-bg-destructive/10 dy-border dy-border-destructive/20 dy-text-destructive dy-text-sm",
|
|
2586
|
+
children: [
|
|
2587
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }),
|
|
2588
|
+
"All ",
|
|
2589
|
+
totalErrors,
|
|
2590
|
+
" rows have validation errors. Fix your CSV and re-upload before importing."
|
|
2591
|
+
]
|
|
2592
|
+
}),
|
|
2542
2593
|
/* @__PURE__ */ jsxs("div", {
|
|
2543
2594
|
className: "dy-flex dy-justify-between dy-pt-4",
|
|
2544
2595
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
@@ -2546,14 +2597,17 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2546
2597
|
onClick: () => setStep("map"),
|
|
2547
2598
|
children: "Back"
|
|
2548
2599
|
}), /* @__PURE__ */ jsxs(Button, {
|
|
2549
|
-
onClick: startImport,
|
|
2600
|
+
onClick: () => startImport(),
|
|
2550
2601
|
variant: "default",
|
|
2551
2602
|
className: "dy-gap-2",
|
|
2603
|
+
disabled: totalErrors === validatedData.length || totalErrors > 0 && !confirmedSkip,
|
|
2552
2604
|
children: [
|
|
2553
2605
|
/* @__PURE__ */ jsx(Play, { className: "dy-h-4 dy-w-4" }),
|
|
2554
2606
|
" Start Import (",
|
|
2555
2607
|
validatedData.length - totalErrors,
|
|
2556
|
-
"
|
|
2608
|
+
" Row",
|
|
2609
|
+
validatedData.length - totalErrors !== 1 ? "s" : "",
|
|
2610
|
+
")"
|
|
2557
2611
|
]
|
|
2558
2612
|
})]
|
|
2559
2613
|
})
|
|
@@ -2631,12 +2685,27 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2631
2685
|
failedRows.length,
|
|
2632
2686
|
" rows)"
|
|
2633
2687
|
]
|
|
2634
|
-
}), /* @__PURE__ */ jsxs(
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2688
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2689
|
+
className: "dy-flex dy-items-center dy-gap-2",
|
|
2690
|
+
children: [retryableRows.length > 0 && /* @__PURE__ */ jsxs(Button, {
|
|
2691
|
+
size: "sm",
|
|
2692
|
+
variant: "outline",
|
|
2693
|
+
className: "dy-h-8 dy-text-xs dy-gap-1.5",
|
|
2694
|
+
onClick: handleRetryFailed,
|
|
2695
|
+
children: [
|
|
2696
|
+
/* @__PURE__ */ jsx(RotateCcw, { className: "dy-h-3.5 dy-w-3.5" }),
|
|
2697
|
+
" Retry ",
|
|
2698
|
+
retryableRows.length,
|
|
2699
|
+
" Failed Row",
|
|
2700
|
+
retryableRows.length !== 1 ? "s" : ""
|
|
2701
|
+
]
|
|
2702
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
2703
|
+
size: "sm",
|
|
2704
|
+
variant: "outline",
|
|
2705
|
+
className: "dy-h-8 dy-text-xs dy-gap-1.5",
|
|
2706
|
+
onClick: downloadFailedCsv,
|
|
2707
|
+
children: [/* @__PURE__ */ jsx(Download, { className: "dy-h-3.5 dy-w-3.5" }), " Download Errors CSV"]
|
|
2708
|
+
})]
|
|
2640
2709
|
})]
|
|
2641
2710
|
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
2642
2711
|
className: "dy-h-[180px] dy-border dy-border-border dy-rounded-xl",
|
|
@@ -2681,27 +2750,6 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2681
2750
|
});
|
|
2682
2751
|
}
|
|
2683
2752
|
//#endregion
|
|
2684
|
-
//#region src/components/ui/csv-importer-dialog.tsx
|
|
2685
|
-
function CsvImporterDialog({ open, onOpenChange, slug, schema }) {
|
|
2686
|
-
const title = schema.labels?.singular || schema.slug || slug;
|
|
2687
|
-
return /* @__PURE__ */ jsx(Dialog, {
|
|
2688
|
-
open,
|
|
2689
|
-
onOpenChange,
|
|
2690
|
-
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
2691
|
-
className: "sm:dy-max-w-2xl",
|
|
2692
|
-
children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Import CSV Data" }), /* @__PURE__ */ jsxs(DialogDescription, { children: [
|
|
2693
|
-
"Import records into the ",
|
|
2694
|
-
title,
|
|
2695
|
-
" collection."
|
|
2696
|
-
] })] }), /* @__PURE__ */ jsx(CsvImporter, {
|
|
2697
|
-
slug,
|
|
2698
|
-
schema,
|
|
2699
|
-
onClose: () => onOpenChange(false)
|
|
2700
|
-
})]
|
|
2701
|
-
})
|
|
2702
|
-
});
|
|
2703
|
-
}
|
|
2704
|
-
//#endregion
|
|
2705
2753
|
//#region src/components/ui/render-cell.tsx
|
|
2706
2754
|
function RenderCell({ value, field, client, schemas }) {
|
|
2707
2755
|
if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", {
|
|
@@ -2917,14 +2965,14 @@ function MediaGrid({ items, baseUrl, onDelete, slug }) {
|
|
|
2917
2965
|
}
|
|
2918
2966
|
//#endregion
|
|
2919
2967
|
//#region src/components/ui/sheet.tsx
|
|
2920
|
-
var Sheet =
|
|
2921
|
-
var SheetPortal =
|
|
2922
|
-
var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2968
|
+
var Sheet = SheetPrimitive.Root;
|
|
2969
|
+
var SheetPortal = SheetPrimitive.Portal;
|
|
2970
|
+
var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
|
|
2923
2971
|
className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
|
|
2924
2972
|
...props,
|
|
2925
2973
|
ref
|
|
2926
2974
|
}));
|
|
2927
|
-
SheetOverlay.displayName =
|
|
2975
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
2928
2976
|
var sheetVariants = cva("dy-fixed dy-z-50 dy-gap-4 dy-bg-background dy-p-6 dy-shadow-2xl dy-transition dy-ease-in-out data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-duration-300 data-[state=open]:dy-duration-500", {
|
|
2929
2977
|
variants: { side: {
|
|
2930
2978
|
top: "dy-inset-x-0 dy-top-0 dy-border-b data-[state=closed]:dy-slide-out-to-top data-[state=open]:dy-slide-in-from-top",
|
|
@@ -2939,11 +2987,11 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
|
|
|
2939
2987
|
return /* @__PURE__ */ jsx(SheetPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
2940
2988
|
className: themeClassName,
|
|
2941
2989
|
"data-theme": resolvedTheme,
|
|
2942
|
-
children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(
|
|
2990
|
+
children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
|
|
2943
2991
|
ref,
|
|
2944
2992
|
className: cn(sheetVariants({ side }), className),
|
|
2945
2993
|
...props,
|
|
2946
|
-
children: [children, /* @__PURE__ */ jsxs(
|
|
2994
|
+
children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
|
|
2947
2995
|
className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-secondary",
|
|
2948
2996
|
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
2949
2997
|
className: "dy-sr-only",
|
|
@@ -2953,7 +3001,7 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
|
|
|
2953
3001
|
})]
|
|
2954
3002
|
}) });
|
|
2955
3003
|
});
|
|
2956
|
-
SheetContent.displayName =
|
|
3004
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
|
2957
3005
|
var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2958
3006
|
className: cn("dy-flex dy-flex-col dy-space-y-2 dy-text-center sm:dy-text-left", className),
|
|
2959
3007
|
...props
|
|
@@ -2964,18 +3012,18 @@ var SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
|
2964
3012
|
...props
|
|
2965
3013
|
});
|
|
2966
3014
|
SheetFooter.displayName = "SheetFooter";
|
|
2967
|
-
var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3015
|
+
var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
|
|
2968
3016
|
ref,
|
|
2969
3017
|
className: cn("dy-text-lg dy-font-semibold dy-text-foreground", className),
|
|
2970
3018
|
...props
|
|
2971
3019
|
}));
|
|
2972
|
-
SheetTitle.displayName =
|
|
2973
|
-
var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3020
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
|
3021
|
+
var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
|
|
2974
3022
|
ref,
|
|
2975
3023
|
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
2976
3024
|
...props
|
|
2977
3025
|
}));
|
|
2978
|
-
SheetDescription.displayName =
|
|
3026
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
2979
3027
|
//#endregion
|
|
2980
3028
|
//#region src/components/ui/toggle.tsx
|
|
2981
3029
|
var toggleVariants = cva("dy-inline-flex dy-items-center dy-justify-center dy-rounded-md dy-text-sm dy-font-medium dy-ring-offset-background dy-transition-colors hover:dy-bg-muted hover:dy-text-muted-foreground focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring focus-visible:dy-ring-offset-2 disabled:dy-pointer-events-none disabled:dy-opacity-50 data-[state=on]:dy-bg-accent data-[state=on]:dy-text-accent-foreground [&_svg]:dy-pointer-events-none [&_svg]:dy-size-4 [&_svg]:dy-shrink-0 dy-gap-2", {
|
|
@@ -3006,6 +3054,59 @@ var Toggle = React$1.forwardRef(({ className, variant, size, ...props }, ref) =>
|
|
|
3006
3054
|
}));
|
|
3007
3055
|
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
3008
3056
|
//#endregion
|
|
3057
|
+
//#region src/components/ui/dialog.tsx
|
|
3058
|
+
var Dialog = SheetPrimitive.Root;
|
|
3059
|
+
var DialogTrigger = SheetPrimitive.Trigger;
|
|
3060
|
+
var DialogPortal = SheetPrimitive.Portal;
|
|
3061
|
+
var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
|
|
3062
|
+
ref,
|
|
3063
|
+
className: cn("dy-fixed dy-inset-0 dy-z-50 dy-bg-black/40 dy-backdrop-blur-[2px] data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0", className),
|
|
3064
|
+
...props
|
|
3065
|
+
}));
|
|
3066
|
+
DialogOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
3067
|
+
var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
|
|
3068
|
+
const { resolvedTheme, themeClassName } = useAdminTheme();
|
|
3069
|
+
return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
3070
|
+
className: themeClassName,
|
|
3071
|
+
"data-theme": resolvedTheme,
|
|
3072
|
+
children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
|
|
3073
|
+
ref,
|
|
3074
|
+
className: cn("dy-fixed dy-left-[50%] dy-top-[50%] dy-z-50 dy-grid dy-w-full dy-max-w-lg dy-translate-x-[-50%] dy-translate-y-[-50%] dy-gap-4 dy-border dy-bg-background dy-p-6 dy-shadow-2xl dy-duration-200 data-[state=open]:dy-animate-in data-[state=closed]:dy-animate-out data-[state=closed]:dy-fade-out-0 data-[state=open]:dy-fade-in-0 data-[state=closed]:dy-zoom-out-95 data-[state=open]:dy-zoom-in-95 data-[state=closed]:dy-slide-out-to-left-1/2 data-[state=closed]:dy-slide-out-to-top-[48%] data-[state=open]:dy-slide-in-from-left-1/2 data-[state=open]:dy-slide-in-from-top-[48%] sm:dy-rounded-xl", className),
|
|
3075
|
+
...props,
|
|
3076
|
+
children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
|
|
3077
|
+
className: "dy-absolute dy-right-4 dy-top-4 dy-rounded-sm dy-opacity-70 dy-ring-offset-background dy-transition-opacity hover:dy-opacity-100 focus:dy-outline-none focus:dy-ring-2 focus:dy-ring-ring focus:dy-ring-offset-2 disabled:dy-pointer-events-none data-[state=open]:dy-bg-accent data-[state=open]:dy-text-muted-foreground",
|
|
3078
|
+
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
3079
|
+
className: "dy-sr-only",
|
|
3080
|
+
children: "Close"
|
|
3081
|
+
})]
|
|
3082
|
+
})]
|
|
3083
|
+
})]
|
|
3084
|
+
}) });
|
|
3085
|
+
});
|
|
3086
|
+
DialogContent.displayName = SheetPrimitive.Content.displayName;
|
|
3087
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
3088
|
+
className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
|
|
3089
|
+
...props
|
|
3090
|
+
});
|
|
3091
|
+
DialogHeader.displayName = "DialogHeader";
|
|
3092
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
3093
|
+
className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
|
|
3094
|
+
...props
|
|
3095
|
+
});
|
|
3096
|
+
DialogFooter.displayName = "DialogFooter";
|
|
3097
|
+
var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
|
|
3098
|
+
ref,
|
|
3099
|
+
className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
|
|
3100
|
+
...props
|
|
3101
|
+
}));
|
|
3102
|
+
DialogTitle.displayName = SheetPrimitive.Title.displayName;
|
|
3103
|
+
var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
|
|
3104
|
+
ref,
|
|
3105
|
+
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
3106
|
+
...props
|
|
3107
|
+
}));
|
|
3108
|
+
DialogDescription.displayName = SheetPrimitive.Description.displayName;
|
|
3109
|
+
//#endregion
|
|
3009
3110
|
//#region src/components/ui/tabs.tsx
|
|
3010
3111
|
var Tabs = TabsPrimitive.Root;
|
|
3011
3112
|
var TabsList = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.List, {
|
|
@@ -9680,7 +9781,7 @@ function CollectionListPage({ slug }) {
|
|
|
9680
9781
|
const allAvailableColumns = React$1.useMemo(() => {
|
|
9681
9782
|
if (!schema) return [];
|
|
9682
9783
|
return [
|
|
9683
|
-
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
|
|
9784
|
+
...schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
|
|
9684
9785
|
"id",
|
|
9685
9786
|
"createdAt",
|
|
9686
9787
|
"updatedAt"
|
|
@@ -9688,7 +9789,7 @@ function CollectionListPage({ slug }) {
|
|
|
9688
9789
|
}, [schema]);
|
|
9689
9790
|
const defaultListColumns = React$1.useMemo(() => {
|
|
9690
9791
|
if (!schema) return [];
|
|
9691
|
-
const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9792
|
+
const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9692
9793
|
const configuredColumns = Array.isArray(schema.admin?.defaultColumns) ? schema.admin.defaultColumns : [];
|
|
9693
9794
|
return configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
|
|
9694
9795
|
}, [schema]);
|
|
@@ -9887,7 +9988,7 @@ function CollectionListPage({ slug }) {
|
|
|
9887
9988
|
key: "id",
|
|
9888
9989
|
label: "ID"
|
|
9889
9990
|
},
|
|
9890
|
-
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((f) => ({
|
|
9991
|
+
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").filter((f) => !!f.name).map((f) => ({
|
|
9891
9992
|
key: f.name,
|
|
9892
9993
|
label: f.label || f.name
|
|
9893
9994
|
})),
|
|
@@ -9962,7 +10063,7 @@ function CollectionListPage({ slug }) {
|
|
|
9962
10063
|
}
|
|
9963
10064
|
const columns = React$1.useMemo(() => {
|
|
9964
10065
|
if (!schema) return [];
|
|
9965
|
-
const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
10066
|
+
const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9966
10067
|
const fieldByName = new Map(allDisplayFields.map((field) => [field.name, field]));
|
|
9967
10068
|
const configuredColumns = localPreference.columns.filter((col) => col.visible).map((col) => col.name);
|
|
9968
10069
|
const visibleColumnNames = configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
|
|
@@ -10212,6 +10313,38 @@ function CollectionListPage({ slug }) {
|
|
|
10212
10313
|
})
|
|
10213
10314
|
]
|
|
10214
10315
|
});
|
|
10316
|
+
if (isImportOpen && schema) {
|
|
10317
|
+
const collectionTitle = schema.labels?.plural || schema.slug;
|
|
10318
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
10319
|
+
className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
|
|
10320
|
+
children: [
|
|
10321
|
+
/* @__PURE__ */ jsx("div", {
|
|
10322
|
+
className: "dy-flex dy-items-center dy-gap-3",
|
|
10323
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
10324
|
+
variant: "ghost",
|
|
10325
|
+
size: "sm",
|
|
10326
|
+
className: "dy-h-8 dy-px-2 dy-gap-1.5 dy-text-xs dy-text-muted-foreground hover:dy-text-foreground",
|
|
10327
|
+
onClick: () => setIsImportOpen(false),
|
|
10328
|
+
children: [
|
|
10329
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "dy-h-3.5 dy-w-3.5" }),
|
|
10330
|
+
"Back to ",
|
|
10331
|
+
collectionTitle
|
|
10332
|
+
]
|
|
10333
|
+
})
|
|
10334
|
+
}),
|
|
10335
|
+
/* @__PURE__ */ jsx(PageHeader, {
|
|
10336
|
+
title: `Import CSV — ${collectionTitle}`,
|
|
10337
|
+
description: `Upload a CSV file to bulk-import records into the ${collectionTitle} collection.`,
|
|
10338
|
+
icon: FileUp
|
|
10339
|
+
}),
|
|
10340
|
+
/* @__PURE__ */ jsx(CsvImporter, {
|
|
10341
|
+
slug,
|
|
10342
|
+
schema,
|
|
10343
|
+
onClose: () => setIsImportOpen(false)
|
|
10344
|
+
})
|
|
10345
|
+
]
|
|
10346
|
+
});
|
|
10347
|
+
}
|
|
10215
10348
|
return /* @__PURE__ */ jsxs("div", {
|
|
10216
10349
|
className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
|
|
10217
10350
|
children: [
|
|
@@ -10485,12 +10618,6 @@ function CollectionListPage({ slug }) {
|
|
|
10485
10618
|
componentProps: collectionComponentProps
|
|
10486
10619
|
})
|
|
10487
10620
|
]
|
|
10488
|
-
}),
|
|
10489
|
-
/* @__PURE__ */ jsx(CsvImporterDialog, {
|
|
10490
|
-
open: isImportOpen,
|
|
10491
|
-
onOpenChange: setIsImportOpen,
|
|
10492
|
-
slug,
|
|
10493
|
-
schema
|
|
10494
10621
|
})
|
|
10495
10622
|
]
|
|
10496
10623
|
});
|
|
@@ -12578,6 +12705,18 @@ function GlobalEditorPage() {
|
|
|
12578
12705
|
//#region src/pages/setup/setup-prompt.tsx
|
|
12579
12706
|
var GUIDE_URL = "https://www.dyrected.com/guide";
|
|
12580
12707
|
var DOCS_URL = "https://docs.dyrected.com";
|
|
12708
|
+
var steps = [
|
|
12709
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12710
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12711
|
+
"Your Dyrected credentials are already in the prompt. Give them to the AI when it asks at Stage 4.",
|
|
12712
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12713
|
+
];
|
|
12714
|
+
var stepsNoCredentials = [
|
|
12715
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12716
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12717
|
+
"When the AI reaches Stage 4, it will ask for your Site ID, Site API key, and Base URL.",
|
|
12718
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12719
|
+
];
|
|
12581
12720
|
function normalizeTechStack(techStack) {
|
|
12582
12721
|
if (!techStack) return void 0;
|
|
12583
12722
|
if (techStack === "next") return "nextjs";
|
|
@@ -12593,154 +12732,116 @@ function buildGuideUrl(config) {
|
|
|
12593
12732
|
if (config.baseUrl) url.searchParams.set("endpoint", config.baseUrl);
|
|
12594
12733
|
return url.toString();
|
|
12595
12734
|
}
|
|
12735
|
+
function buildPrompt(config) {
|
|
12736
|
+
const { siteId, apiKey, baseUrl } = config;
|
|
12737
|
+
if (!(siteId && apiKey && baseUrl)) return GENERATE_CMS_PROMPT;
|
|
12738
|
+
const placeholder = `Ask me for the following in one message:
|
|
12739
|
+
|
|
12740
|
+
- Site ID
|
|
12741
|
+
- Site API key
|
|
12742
|
+
- Base URL
|
|
12743
|
+
|
|
12744
|
+
Wait for my reply.`;
|
|
12745
|
+
const replacement = `Use the following credentials:
|
|
12746
|
+
|
|
12747
|
+
- Site ID: ${siteId}
|
|
12748
|
+
- Site API key: ${apiKey}
|
|
12749
|
+
- Base URL: ${baseUrl}`;
|
|
12750
|
+
return GENERATE_CMS_PROMPT.replace(placeholder, replacement);
|
|
12751
|
+
}
|
|
12596
12752
|
function SetupPromptUI({ config }) {
|
|
12753
|
+
const [copied, setCopied] = useState(false);
|
|
12597
12754
|
const guideUrl = buildGuideUrl(config);
|
|
12598
|
-
const
|
|
12755
|
+
const hasCredentials = !!(config.siteId && config.apiKey && config.baseUrl);
|
|
12756
|
+
const guideSteps = hasCredentials ? steps : stepsNoCredentials;
|
|
12757
|
+
const promptText = buildPrompt(config);
|
|
12758
|
+
async function copyPrompt() {
|
|
12759
|
+
await navigator.clipboard.writeText(promptText);
|
|
12760
|
+
setCopied(true);
|
|
12761
|
+
window.setTimeout(() => setCopied(false), 1800);
|
|
12762
|
+
}
|
|
12599
12763
|
return /* @__PURE__ */ jsxs("div", {
|
|
12600
|
-
className: "dy-mx-auto dy-max-w-
|
|
12601
|
-
children: [
|
|
12602
|
-
|
|
12603
|
-
|
|
12604
|
-
/* @__PURE__ */ jsx("
|
|
12605
|
-
className: "dy-
|
|
12606
|
-
|
|
12607
|
-
}),
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12614
|
-
|
|
12615
|
-
|
|
12616
|
-
|
|
12617
|
-
|
|
12618
|
-
|
|
12619
|
-
|
|
12620
|
-
|
|
12621
|
-
|
|
12622
|
-
className: "dy-max-w-2xl dy-space-y-4",
|
|
12623
|
-
children: [/* @__PURE__ */ jsx("h1", {
|
|
12624
|
-
className: "dy-font-serif dy-text-4xl dy-font-bold dy-leading-[0.98] dy-tracking-tight sm:dy-text-5xl lg:dy-text-6xl",
|
|
12625
|
-
children: "Let the guide do the heavy lifting."
|
|
12626
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
12627
|
-
className: "dy-max-w-xl dy-text-base dy-leading-7 dy-text-muted-foreground sm:dy-text-lg",
|
|
12628
|
-
children: "Get a guided path tailored to your project, whether you are building with an AI coding tool or wiring up the SDK yourself."
|
|
12629
|
-
})]
|
|
12630
|
-
})]
|
|
12631
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12632
|
-
className: "dy-flex dy-flex-col dy-gap-3 sm:dy-flex-row sm:dy-items-center",
|
|
12633
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
12634
|
-
asChild: true,
|
|
12635
|
-
size: "lg",
|
|
12636
|
-
className: "dy-h-12 dy-bg-primary dy-px-6 dy-text-primary-foreground hover:dy-bg-primary/90",
|
|
12637
|
-
children: /* @__PURE__ */ jsxs("a", {
|
|
12638
|
-
href: guideUrl,
|
|
12639
|
-
target: "_blank",
|
|
12640
|
-
rel: "noopener noreferrer",
|
|
12641
|
-
children: [
|
|
12642
|
-
/* @__PURE__ */ jsx(Compass, { className: "dy-h-4 dy-w-4" }),
|
|
12643
|
-
"Open guided setup",
|
|
12644
|
-
/* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-4 dy-w-4" })
|
|
12645
|
-
]
|
|
12646
|
-
})
|
|
12647
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
12648
|
-
asChild: true,
|
|
12649
|
-
size: "lg",
|
|
12650
|
-
variant: "ghost",
|
|
12651
|
-
className: "dy-h-12 dy-text-card-foreground hover:dy-bg-muted hover:dy-text-card-foreground",
|
|
12652
|
-
children: /* @__PURE__ */ jsxs("a", {
|
|
12653
|
-
href: DOCS_URL,
|
|
12654
|
-
target: "_blank",
|
|
12655
|
-
rel: "noopener noreferrer",
|
|
12656
|
-
children: [/* @__PURE__ */ jsx(BookOpen, { className: "dy-h-4 dy-w-4" }), "Browse developer docs"]
|
|
12657
|
-
})
|
|
12658
|
-
})]
|
|
12659
|
-
})]
|
|
12660
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
12661
|
-
className: "dy-relative dy-flex dy-items-end lg:dy-justify-end",
|
|
12662
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
12663
|
-
className: "dy-w-full dy-max-w-sm dy-rounded-2xl dy-border dy-border-border dy-bg-background/90 dy-p-5 dy-text-foreground dy-shadow-lg dy-backdrop-blur-sm",
|
|
12664
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
12665
|
-
className: "dy-mb-5 dy-flex dy-items-center dy-justify-between",
|
|
12666
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
12667
|
-
className: "dy-text-xs dy-font-bold dy-uppercase dy-tracking-[0.12em] dy-text-muted-foreground",
|
|
12668
|
-
children: "Context included"
|
|
12669
|
-
}), /* @__PURE__ */ jsx(Code2, { className: "dy-h-4 dy-w-4 dy-text-primary" })]
|
|
12670
|
-
}), /* @__PURE__ */ jsxs("dl", {
|
|
12671
|
-
className: "dy-space-y-4 dy-text-sm",
|
|
12672
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
12673
|
-
className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
|
|
12674
|
-
children: [/* @__PURE__ */ jsx("dt", {
|
|
12675
|
-
className: "dy-text-muted-foreground",
|
|
12676
|
-
children: "Tech stack"
|
|
12677
|
-
}), /* @__PURE__ */ jsx("dd", {
|
|
12678
|
-
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12679
|
-
children: stack ?? "Choose in guide"
|
|
12680
|
-
})]
|
|
12681
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12682
|
-
className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
|
|
12683
|
-
children: [/* @__PURE__ */ jsx("dt", {
|
|
12684
|
-
className: "dy-text-muted-foreground",
|
|
12685
|
-
children: "Site"
|
|
12686
|
-
}), /* @__PURE__ */ jsx("dd", {
|
|
12687
|
-
className: "dy-max-w-[180px] dy-truncate dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12688
|
-
children: config.siteId || "Not provided"
|
|
12689
|
-
})]
|
|
12690
|
-
})]
|
|
12691
|
-
})]
|
|
12692
|
-
})
|
|
12764
|
+
className: "dy-mx-auto dy-max-w-3xl dy-space-y-10 dy-px-4 dy-py-8",
|
|
12765
|
+
children: [
|
|
12766
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12767
|
+
className: "dy-space-y-2",
|
|
12768
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
12769
|
+
className: "dy-text-2xl dy-font-semibold dy-tracking-tight dy-text-foreground",
|
|
12770
|
+
children: "Set up Dyrected"
|
|
12771
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
12772
|
+
className: "dy-text-sm dy-leading-6 dy-text-muted-foreground",
|
|
12773
|
+
children: "Copy the prompt below and paste it into your AI builder. It handles the setup in stages."
|
|
12774
|
+
})]
|
|
12775
|
+
}),
|
|
12776
|
+
/* @__PURE__ */ jsx("ol", {
|
|
12777
|
+
className: "dy-space-y-3",
|
|
12778
|
+
children: guideSteps.map((step, index) => /* @__PURE__ */ jsxs("li", {
|
|
12779
|
+
className: "dy-flex dy-gap-3 dy-text-sm",
|
|
12780
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
12781
|
+
className: "dy-flex dy-h-6 dy-w-6 dy-shrink-0 dy-items-center dy-justify-center dy-rounded-full dy-bg-muted dy-text-xs dy-font-semibold dy-tabular-nums dy-text-foreground",
|
|
12782
|
+
children: index + 1
|
|
12783
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
12784
|
+
className: "dy-leading-6 dy-text-muted-foreground",
|
|
12785
|
+
children: step
|
|
12693
12786
|
})]
|
|
12694
|
-
})
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
|
|
12698
|
-
children: [/* @__PURE__ */ jsxs("a", {
|
|
12699
|
-
href: guideUrl,
|
|
12700
|
-
target: "_blank",
|
|
12701
|
-
rel: "noopener noreferrer",
|
|
12702
|
-
className: "dy-group dy-flex dy-items-start dy-gap-4 dy-rounded-xl dy-border dy-bg-card dy-p-5 dy-transition-colors hover:dy-border-primary/60 hover:dy-bg-primary/[0.04] focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring",
|
|
12787
|
+
}, index))
|
|
12788
|
+
}),
|
|
12789
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12790
|
+
className: "dy-overflow-hidden dy-rounded-xl dy-border dy-border-border dy-bg-card",
|
|
12703
12791
|
children: [
|
|
12704
|
-
/* @__PURE__ */ jsx("div", {
|
|
12705
|
-
className: "dy-rounded-lg dy-bg-primary/15 dy-p-2.5 dy-text-foreground",
|
|
12706
|
-
children: /* @__PURE__ */ jsx(Sparkles, { className: "dy-h-5 dy-w-5" })
|
|
12707
|
-
}),
|
|
12708
12792
|
/* @__PURE__ */ jsxs("div", {
|
|
12709
|
-
className: "dy-
|
|
12710
|
-
children: [/* @__PURE__ */ jsx("
|
|
12711
|
-
className: "dy-font-semibold dy-text-
|
|
12712
|
-
children: "
|
|
12713
|
-
}), /* @__PURE__ */
|
|
12714
|
-
className: "dy-mt-
|
|
12715
|
-
children: "
|
|
12793
|
+
className: "dy-flex dy-items-center dy-justify-between dy-gap-4 dy-border-b dy-border-border dy-px-4 dy-py-3",
|
|
12794
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
12795
|
+
className: "dy-text-xs dy-font-semibold dy-uppercase dy-tracking-[0.12em] dy-text-muted-foreground",
|
|
12796
|
+
children: "Dyrected setup prompt"
|
|
12797
|
+
}), hasCredentials && /* @__PURE__ */ jsxs("p", {
|
|
12798
|
+
className: "dy-mt-0.5 dy-text-xs dy-text-muted-foreground",
|
|
12799
|
+
children: ["Credentials pre-filled for ", config.siteName || config.siteId]
|
|
12800
|
+
})] }), /* @__PURE__ */ jsxs("button", {
|
|
12801
|
+
type: "button",
|
|
12802
|
+
onClick: copyPrompt,
|
|
12803
|
+
className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-rounded-lg dy-border dy-border-border dy-bg-background dy-px-3 dy-py-1.5 dy-text-xs dy-font-semibold dy-text-foreground dy-transition-colors hover:dy-bg-muted",
|
|
12804
|
+
children: [copied ? /* @__PURE__ */ jsx(Check, { className: "dy-h-3.5 dy-w-3.5 dy-text-primary" }) : /* @__PURE__ */ jsx(Copy, { className: "dy-h-3.5 dy-w-3.5" }), copied ? "Copied" : "Copy prompt"]
|
|
12716
12805
|
})]
|
|
12717
12806
|
}),
|
|
12718
|
-
/* @__PURE__ */ jsx(
|
|
12807
|
+
/* @__PURE__ */ jsx("pre", {
|
|
12808
|
+
className: "dy-max-h-64 dy-overflow-y-auto dy-p-4 dy-text-[11px] dy-leading-5 dy-text-muted-foreground",
|
|
12809
|
+
children: /* @__PURE__ */ jsx("code", { children: promptText })
|
|
12810
|
+
}),
|
|
12811
|
+
/* @__PURE__ */ jsx("div", {
|
|
12812
|
+
className: "dy-border-t dy-border-border dy-px-4 dy-py-3",
|
|
12813
|
+
children: /* @__PURE__ */ jsxs("p", {
|
|
12814
|
+
className: "dy-text-xs dy-text-muted-foreground",
|
|
12815
|
+
children: ["Paste this into the AI builder or code agent that can edit the website code.", !hasCredentials && " The prompt will ask for your Dyrected details at the right stage."]
|
|
12816
|
+
})
|
|
12817
|
+
})
|
|
12719
12818
|
]
|
|
12720
|
-
}),
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
rel: "noopener noreferrer",
|
|
12724
|
-
className: "dy-group dy-flex dy-items-start dy-gap-4 dy-rounded-xl dy-border dy-bg-card dy-p-5 dy-transition-colors hover:dy-border-foreground/30 hover:dy-bg-muted/40 focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring",
|
|
12819
|
+
}),
|
|
12820
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12821
|
+
className: "dy-flex dy-flex-col dy-gap-2 sm:dy-flex-row",
|
|
12725
12822
|
children: [
|
|
12726
|
-
/* @__PURE__ */
|
|
12727
|
-
|
|
12728
|
-
|
|
12823
|
+
/* @__PURE__ */ jsxs("a", {
|
|
12824
|
+
href: guideUrl,
|
|
12825
|
+
target: "_blank",
|
|
12826
|
+
rel: "noopener noreferrer",
|
|
12827
|
+
className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-text-sm dy-text-muted-foreground dy-underline-offset-4 hover:dy-text-foreground hover:dy-underline",
|
|
12828
|
+
children: ["Full guide", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
|
|
12729
12829
|
}),
|
|
12730
|
-
/* @__PURE__ */
|
|
12731
|
-
className: "dy-
|
|
12732
|
-
|
|
12733
|
-
|
|
12734
|
-
children: "Need implementation detail?"
|
|
12735
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
12736
|
-
className: "dy-mt-1 dy-text-sm dy-leading-6 dy-text-muted-foreground",
|
|
12737
|
-
children: "Use the docs for SDK APIs, framework integrations, configuration, and production reference."
|
|
12738
|
-
})]
|
|
12830
|
+
/* @__PURE__ */ jsx("span", {
|
|
12831
|
+
className: "dy-hidden dy-text-muted-foreground sm:dy-inline",
|
|
12832
|
+
"aria-hidden": "true",
|
|
12833
|
+
children: "·"
|
|
12739
12834
|
}),
|
|
12740
|
-
/* @__PURE__ */
|
|
12835
|
+
/* @__PURE__ */ jsxs("a", {
|
|
12836
|
+
href: DOCS_URL,
|
|
12837
|
+
target: "_blank",
|
|
12838
|
+
rel: "noopener noreferrer",
|
|
12839
|
+
className: "dy-inline-flex dy-items-center dy-gap-1.5 dy-text-sm dy-text-muted-foreground dy-underline-offset-4 hover:dy-text-foreground hover:dy-underline",
|
|
12840
|
+
children: ["Developer docs", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
|
|
12841
|
+
})
|
|
12741
12842
|
]
|
|
12742
|
-
})
|
|
12743
|
-
|
|
12843
|
+
})
|
|
12844
|
+
]
|
|
12744
12845
|
});
|
|
12745
12846
|
}
|
|
12746
12847
|
//#endregion
|
|
@@ -13384,8 +13485,7 @@ function buildProviderStartUrl(baseUrl, providerId) {
|
|
|
13384
13485
|
}
|
|
13385
13486
|
function resolveAdminAuthCollection(collections, collectionSlug) {
|
|
13386
13487
|
if (!collections) return void 0;
|
|
13387
|
-
|
|
13388
|
-
return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.auth);
|
|
13488
|
+
return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.slug === collectionSlug) ?? collections.find((collection) => collection.auth);
|
|
13389
13489
|
}
|
|
13390
13490
|
function readToken(value) {
|
|
13391
13491
|
if (!value || typeof value !== "object" || !("token" in value)) return null;
|