@dyrected/admin 2.5.47 → 2.5.49
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 +59 -119
- package/dist/index.mjs +801 -509
- package/dist/pages/setup/setup-prompt.d.ts +0 -1
- package/dist/pages/setup/utils.d.ts +4 -0
- 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);
|
|
@@ -159,18 +158,12 @@ function DyrectedProvider({ children, apiKey: initialApiKey, baseUrl: initialBas
|
|
|
159
158
|
schemas
|
|
160
159
|
]);
|
|
161
160
|
const logout = useCallback(() => {
|
|
162
|
-
localStorage.removeItem("dyrected_url");
|
|
163
|
-
localStorage.removeItem("dyrected_key");
|
|
164
|
-
localStorage.removeItem("dyrected_site_id");
|
|
165
161
|
localStorage.removeItem("dyrected_token");
|
|
166
162
|
localStorage.removeItem("dyrected_admin_auth_collection");
|
|
167
|
-
|
|
168
|
-
setApiKey(void 0);
|
|
169
|
-
setSiteId(void 0);
|
|
163
|
+
if (client) client.clearToken();
|
|
170
164
|
setAuthCollectionSlug(null);
|
|
171
165
|
setUser(null);
|
|
172
|
-
|
|
173
|
-
}, []);
|
|
166
|
+
}, [client]);
|
|
174
167
|
return /* @__PURE__ */ jsx(DyrectedContext.Provider, {
|
|
175
168
|
value: {
|
|
176
169
|
client,
|
|
@@ -593,7 +586,7 @@ function NavGroup({ label, children, collapsed, defaultExpanded = true }) {
|
|
|
593
586
|
})]
|
|
594
587
|
});
|
|
595
588
|
}
|
|
596
|
-
function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
589
|
+
function ThemeSelector({ collapsed = false, mobile = false, iconOnly = false }) {
|
|
597
590
|
const { resolvedTheme, setTheme, theme } = useAdminTheme();
|
|
598
591
|
const Icon = resolvedTheme === "dark" ? Moon : Sun;
|
|
599
592
|
const options = [
|
|
@@ -618,11 +611,11 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
618
611
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
619
612
|
type: "button",
|
|
620
613
|
variant: "ghost",
|
|
621
|
-
size: mobile || collapsed ? "icon" : "sm",
|
|
622
|
-
className: cn("dy-text-muted-foreground hover:dy-bg-accent hover:dy-text-foreground", collapsed || mobile ? "dy-h-
|
|
614
|
+
size: mobile || collapsed || iconOnly ? "icon" : "sm",
|
|
615
|
+
className: cn("dy-text-muted-foreground hover:dy-bg-accent hover:dy-text-foreground", collapsed || mobile || iconOnly ? "dy-h-7 dy-w-7 dy-px-0 dy-justify-center" : "dy-h-7 dy-w-full dy-justify-start dy-px-2.5 dy-text-[11px]"),
|
|
623
616
|
title: "Theme",
|
|
624
617
|
"aria-label": "Change admin theme",
|
|
625
|
-
children: [/* @__PURE__ */ jsx(Icon, { className: "dy-h-3.5 dy-w-3.5" }), !collapsed && !mobile && /* @__PURE__ */ jsx("span", { children: "Theme" })]
|
|
618
|
+
children: [/* @__PURE__ */ jsx(Icon, { className: "dy-h-3.5 dy-w-3.5" }), !collapsed && !mobile && !iconOnly && /* @__PURE__ */ jsx("span", { children: "Theme" })]
|
|
626
619
|
})
|
|
627
620
|
}), /* @__PURE__ */ jsxs(DropdownMenuContent, {
|
|
628
621
|
side: collapsed || mobile ? "bottom" : "top",
|
|
@@ -642,7 +635,7 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
642
635
|
const OptionIcon = option.icon;
|
|
643
636
|
return /* @__PURE__ */ jsxs(DropdownMenuRadioItem, {
|
|
644
637
|
value: option.value,
|
|
645
|
-
className: "dy-cursor-pointer",
|
|
638
|
+
className: "dy-cursor-pointer dy-space-x-2",
|
|
646
639
|
children: [/* @__PURE__ */ jsx(OptionIcon, { className: "dy-h-4 dy-w-4" }), option.label]
|
|
647
640
|
}, option.value);
|
|
648
641
|
})
|
|
@@ -650,16 +643,16 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
650
643
|
]
|
|
651
644
|
})] });
|
|
652
645
|
}
|
|
653
|
-
function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collapsed, onToggleCollapse, onNavigate }) {
|
|
646
|
+
function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collapsed, onToggleCollapse, onNavigate, updateInfo }) {
|
|
654
647
|
const { client, user } = useDyrected();
|
|
655
|
-
const collections = schemas?.collections?.filter((c) => !c?.admin?.hidden && !c?.slug.startsWith("platform_")) ?? [];
|
|
656
|
-
const globals = schemas?.globals?.filter((g) => !g?.admin?.hidden && !g?.slug.startsWith("platform_")) ?? [];
|
|
648
|
+
const collections = (schemas?.collections)?.filter((c) => !c?.admin?.hidden && !c?.slug.startsWith("platform_")) ?? [];
|
|
649
|
+
const globals = (schemas?.globals)?.filter((g) => !g?.admin?.hidden && !g?.slug.startsWith("platform_")) ?? [];
|
|
657
650
|
const uploadCollections = collections.filter((c) => c.upload);
|
|
658
651
|
const groupLabel = (text) => !collapsed ? /* @__PURE__ */ jsx("p", {
|
|
659
652
|
className: "dy-px-3 dy-mb-1.5 dy-text-[10px] dy-font-semibold dy-uppercase dy-tracking-widest dy-text-muted-foreground/50",
|
|
660
653
|
children: text
|
|
661
654
|
}) : /* @__PURE__ */ jsx("div", { className: "dy-my-2 dy-mx-3 dy-h-px dy-bg-border" });
|
|
662
|
-
const branding = schemas?.admin?.branding;
|
|
655
|
+
const branding = (schemas?.admin)?.branding;
|
|
663
656
|
return /* @__PURE__ */ jsxs("div", {
|
|
664
657
|
className: "dy-flex dy-flex-col dy-min-h-screen",
|
|
665
658
|
children: [
|
|
@@ -790,12 +783,17 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
790
783
|
/* @__PURE__ */ jsx(NavItem, {
|
|
791
784
|
to: "/setup",
|
|
792
785
|
icon: Sparkles,
|
|
793
|
-
label:
|
|
786
|
+
label: /* @__PURE__ */ jsxs("div", {
|
|
787
|
+
className: "dy-flex dy-items-center dy-justify-between dy-w-full dy-min-w-0",
|
|
788
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
789
|
+
className: "dy-truncate",
|
|
790
|
+
children: "Setup & Help"
|
|
791
|
+
}), updateInfo?.hasUpdate && /* @__PURE__ */ jsx("span", { className: "dy-h-1.5 dy-w-1.5 dy-rounded-full dy-bg-primary dy-shrink-0 dy-ml-2" })]
|
|
792
|
+
}),
|
|
794
793
|
active: location.pathname === "/setup",
|
|
795
794
|
collapsed,
|
|
796
795
|
onClick: onNavigate
|
|
797
796
|
}),
|
|
798
|
-
/* @__PURE__ */ jsx(ThemeSelector, { collapsed }),
|
|
799
797
|
!isEmbedded && user && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
800
798
|
asChild: true,
|
|
801
799
|
children: /* @__PURE__ */ jsxs("button", {
|
|
@@ -841,26 +839,99 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
841
839
|
})
|
|
842
840
|
]
|
|
843
841
|
})] }),
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
842
|
+
/* @__PURE__ */ jsxs("div", {
|
|
843
|
+
className: cn("dy-flex dy-items-center dy-gap-1.5 dy-w-full dy-mt-1", collapsed ? "dy-flex-col dy-items-center" : "dy-flex-row dy-justify-between"),
|
|
844
|
+
children: [onToggleCollapse && !isEmbedded && /* @__PURE__ */ jsx("button", {
|
|
845
|
+
onClick: onToggleCollapse,
|
|
846
|
+
className: cn("dy-group/btn dy-flex dy-h-7 dy-items-center dy-gap-2 dy-rounded-md dy-px-2.5 dy-text-[11px] dy-font-medium dy-text-muted-foreground/45 dy-transition-colors hover:dy-bg-accent/40 hover:dy-text-muted-foreground focus-visible:dy-outline-none focus-visible:dy-ring-2 focus-visible:dy-ring-ring", collapsed ? "dy-justify-center dy-px-2 dy-w-full" : "dy-flex-1"),
|
|
847
|
+
title: collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
848
|
+
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
849
|
+
children: collapsed ? /* @__PURE__ */ jsx(PanelLeftOpen, { className: "dy-h-3.5 dy-w-3.5" }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(PanelLeftClose, { className: "dy-h-3.5 dy-w-3.5 dy-transition-transform dy-group-hover/btn:dy--translate-x-0.5" }), /* @__PURE__ */ jsx("span", {
|
|
850
|
+
className: "dy-truncate",
|
|
851
|
+
children: "Collapse"
|
|
852
|
+
})] })
|
|
853
|
+
}), /* @__PURE__ */ jsx(ThemeSelector, {
|
|
854
|
+
collapsed,
|
|
855
|
+
iconOnly: !collapsed
|
|
856
|
+
})]
|
|
850
857
|
})
|
|
851
858
|
]
|
|
852
859
|
})
|
|
853
860
|
]
|
|
854
861
|
});
|
|
855
862
|
}
|
|
863
|
+
function isNewerVersion(latest, current) {
|
|
864
|
+
if (latest === current) return false;
|
|
865
|
+
const lParts = latest.split(".").map(Number);
|
|
866
|
+
const cParts = current.split(".").map(Number);
|
|
867
|
+
for (let i = 0; i < 3; i++) {
|
|
868
|
+
const l = lParts[i] || 0;
|
|
869
|
+
const c = cParts[i] || 0;
|
|
870
|
+
if (l > c) return true;
|
|
871
|
+
if (l < c) return false;
|
|
872
|
+
}
|
|
873
|
+
return false;
|
|
874
|
+
}
|
|
875
|
+
function useUpdateCheck() {
|
|
876
|
+
const currentVersion = "2.5.49";
|
|
877
|
+
const [updateInfo, setUpdateInfo] = useState(() => {
|
|
878
|
+
if (typeof window === "undefined") return null;
|
|
879
|
+
const cacheKey = "dyrected_latest_release";
|
|
880
|
+
const cacheTimeKey = "dyrected_latest_release_timestamp";
|
|
881
|
+
const cachedVersion = localStorage.getItem(cacheKey);
|
|
882
|
+
const cachedTimestamp = localStorage.getItem(cacheTimeKey);
|
|
883
|
+
if (cachedVersion && cachedTimestamp && Date.now() - Number(cachedTimestamp) < 1440 * 60 * 1e3) return {
|
|
884
|
+
latestVersion: cachedVersion,
|
|
885
|
+
hasUpdate: isNewerVersion(cachedVersion, currentVersion)
|
|
886
|
+
};
|
|
887
|
+
return null;
|
|
888
|
+
});
|
|
889
|
+
useEffect(() => {
|
|
890
|
+
let cancelled = false;
|
|
891
|
+
const cacheKey = "dyrected_latest_release";
|
|
892
|
+
const cacheTimeKey = "dyrected_latest_release_timestamp";
|
|
893
|
+
const oneDay = 1440 * 60 * 1e3;
|
|
894
|
+
const cachedVersion = localStorage.getItem(cacheKey);
|
|
895
|
+
const cachedTimestamp = localStorage.getItem(cacheTimeKey);
|
|
896
|
+
if (cachedVersion && cachedTimestamp && Date.now() - Number(cachedTimestamp) < oneDay) return;
|
|
897
|
+
async function fetchLatest() {
|
|
898
|
+
try {
|
|
899
|
+
const res = await fetch("https://registry.npmjs.org/@dyrected/core/latest");
|
|
900
|
+
if (!res.ok) return;
|
|
901
|
+
const latest = (await res.json())?.version;
|
|
902
|
+
if (latest) {
|
|
903
|
+
localStorage.setItem(cacheKey, latest);
|
|
904
|
+
localStorage.setItem(cacheTimeKey, String(Date.now()));
|
|
905
|
+
if (!cancelled) setUpdateInfo({
|
|
906
|
+
latestVersion: latest,
|
|
907
|
+
hasUpdate: isNewerVersion(latest, currentVersion)
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
} catch (err) {
|
|
911
|
+
console.error("Failed to check for updates:", err);
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
fetchLatest();
|
|
915
|
+
return () => {
|
|
916
|
+
cancelled = true;
|
|
917
|
+
};
|
|
918
|
+
}, [currentVersion]);
|
|
919
|
+
return updateInfo;
|
|
920
|
+
}
|
|
856
921
|
function AdminShell({ children, isEmbedded = false }) {
|
|
857
922
|
const { client, logout, user } = useDyrected();
|
|
858
923
|
const location = useLocation();
|
|
924
|
+
const updateInfo = useUpdateCheck();
|
|
859
925
|
const [collapsed, setCollapsed] = useState(false);
|
|
860
926
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
861
927
|
useEffect(() => {
|
|
862
|
-
|
|
863
|
-
|
|
928
|
+
if (mobileOpen) {
|
|
929
|
+
const timer = setTimeout(() => {
|
|
930
|
+
setMobileOpen(false);
|
|
931
|
+
}, 0);
|
|
932
|
+
return () => clearTimeout(timer);
|
|
933
|
+
}
|
|
934
|
+
}, [location.pathname, mobileOpen]);
|
|
864
935
|
useEffect(() => {
|
|
865
936
|
document.body.style.overflow = mobileOpen ? "hidden" : "";
|
|
866
937
|
return () => {
|
|
@@ -875,7 +946,7 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
875
946
|
},
|
|
876
947
|
enabled: !!client
|
|
877
948
|
});
|
|
878
|
-
const mobileBranding = schemas?.admin?.branding;
|
|
949
|
+
const mobileBranding = (schemas?.admin)?.branding;
|
|
879
950
|
return /* @__PURE__ */ jsx(BrandingProvider, { children: /* @__PURE__ */ jsxs("div", {
|
|
880
951
|
className: cn("dy-flex dy-w-full dy-relative", isEmbedded ? "dy-h-full dy-min-h-[600px]" : "dy-min-h-screen"),
|
|
881
952
|
children: [
|
|
@@ -888,7 +959,8 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
888
959
|
logout,
|
|
889
960
|
isEmbedded,
|
|
890
961
|
collapsed,
|
|
891
|
-
onToggleCollapse: () => setCollapsed((v) => !v)
|
|
962
|
+
onToggleCollapse: () => setCollapsed((v) => !v),
|
|
963
|
+
updateInfo
|
|
892
964
|
})
|
|
893
965
|
}),
|
|
894
966
|
mobileOpen && /* @__PURE__ */ jsx("div", {
|
|
@@ -908,7 +980,8 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
908
980
|
logout,
|
|
909
981
|
isEmbedded,
|
|
910
982
|
collapsed: false,
|
|
911
|
-
onNavigate: () => setMobileOpen(false)
|
|
983
|
+
onNavigate: () => setMobileOpen(false),
|
|
984
|
+
updateInfo
|
|
912
985
|
})]
|
|
913
986
|
}),
|
|
914
987
|
/* @__PURE__ */ jsxs("main", {
|
|
@@ -941,7 +1014,7 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
941
1014
|
className: "dy-ml-auto dy-flex dy-items-center dy-gap-1.5",
|
|
942
1015
|
children: [/* @__PURE__ */ jsx(ThemeSelector, { mobile: true }), user && /* @__PURE__ */ jsx("div", {
|
|
943
1016
|
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",
|
|
944
|
-
children: (user.name || user.email || "?")
|
|
1017
|
+
children: (user.name || user.email || "?").charAt(0).toUpperCase()
|
|
945
1018
|
})]
|
|
946
1019
|
})
|
|
947
1020
|
]
|
|
@@ -1036,6 +1109,31 @@ function getStatusLabel(doc) {
|
|
|
1036
1109
|
}
|
|
1037
1110
|
function Dashboard() {
|
|
1038
1111
|
const { client, components, user } = useDyrected();
|
|
1112
|
+
const currentVersion = "2.5.49";
|
|
1113
|
+
const [latestVersion, setLatestVersion] = useState(() => {
|
|
1114
|
+
if (typeof window === "undefined") return null;
|
|
1115
|
+
return localStorage.getItem("dyrected_latest_release");
|
|
1116
|
+
});
|
|
1117
|
+
useEffect(() => {
|
|
1118
|
+
if (!latestVersion) fetch("https://registry.npmjs.org/@dyrected/core/latest").then((r) => r.json()).then((data) => {
|
|
1119
|
+
if (data?.version) {
|
|
1120
|
+
setLatestVersion(data.version);
|
|
1121
|
+
localStorage.setItem("dyrected_latest_release", data.version);
|
|
1122
|
+
localStorage.setItem("dyrected_latest_release_timestamp", String(Date.now()));
|
|
1123
|
+
}
|
|
1124
|
+
}).catch(() => {});
|
|
1125
|
+
}, [latestVersion]);
|
|
1126
|
+
const hasUpdate = latestVersion && latestVersion !== currentVersion && (() => {
|
|
1127
|
+
const lParts = latestVersion.split(".").map(Number);
|
|
1128
|
+
const cParts = currentVersion.split(".").map(Number);
|
|
1129
|
+
for (let i = 0; i < 3; i++) {
|
|
1130
|
+
const l = lParts[i] || 0;
|
|
1131
|
+
const c = cParts[i] || 0;
|
|
1132
|
+
if (l > c) return true;
|
|
1133
|
+
if (l < c) return false;
|
|
1134
|
+
}
|
|
1135
|
+
return false;
|
|
1136
|
+
})();
|
|
1039
1137
|
const { data: schemas, isLoading: isLoadingSchemas } = useQuery({
|
|
1040
1138
|
queryKey: ["schemas"],
|
|
1041
1139
|
queryFn: () => client.getSchemas(),
|
|
@@ -1072,6 +1170,12 @@ function Dashboard() {
|
|
|
1072
1170
|
return (b.updatedAt ? new Date(b.updatedAt).getTime() : 0) - aTime;
|
|
1073
1171
|
}).slice(0, 6);
|
|
1074
1172
|
const attentionItems = [
|
|
1173
|
+
...hasUpdate ? [{
|
|
1174
|
+
key: "dyrected-update",
|
|
1175
|
+
title: `A system update is available (v${latestVersion})`,
|
|
1176
|
+
description: "Please notify your developer or site administrator to apply this update.",
|
|
1177
|
+
to: "/setup"
|
|
1178
|
+
}] : [],
|
|
1075
1179
|
...collections.filter((collection) => !collection.upload && !collection.admin?.useAsTitle).map((collection) => ({
|
|
1076
1180
|
key: `title-${collection.slug}`,
|
|
1077
1181
|
title: `${getCollectionLabel(collection)} needs a title field`,
|
|
@@ -2073,59 +2177,6 @@ var Checkbox = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__
|
|
|
2073
2177
|
}));
|
|
2074
2178
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
2075
2179
|
//#endregion
|
|
2076
|
-
//#region src/components/ui/dialog.tsx
|
|
2077
|
-
var Dialog = DialogPrimitive.Root;
|
|
2078
|
-
var DialogTrigger = DialogPrimitive.Trigger;
|
|
2079
|
-
var DialogPortal = DialogPrimitive.Portal;
|
|
2080
|
-
var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
|
|
2081
|
-
ref,
|
|
2082
|
-
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),
|
|
2083
|
-
...props
|
|
2084
|
-
}));
|
|
2085
|
-
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
2086
|
-
var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
|
|
2087
|
-
const { resolvedTheme, themeClassName } = useAdminTheme();
|
|
2088
|
-
return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
2089
|
-
className: themeClassName,
|
|
2090
|
-
"data-theme": resolvedTheme,
|
|
2091
|
-
children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
|
|
2092
|
-
ref,
|
|
2093
|
-
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),
|
|
2094
|
-
...props,
|
|
2095
|
-
children: [children, /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
|
|
2096
|
-
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",
|
|
2097
|
-
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
2098
|
-
className: "dy-sr-only",
|
|
2099
|
-
children: "Close"
|
|
2100
|
-
})]
|
|
2101
|
-
})]
|
|
2102
|
-
})]
|
|
2103
|
-
}) });
|
|
2104
|
-
});
|
|
2105
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
2106
|
-
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2107
|
-
className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
|
|
2108
|
-
...props
|
|
2109
|
-
});
|
|
2110
|
-
DialogHeader.displayName = "DialogHeader";
|
|
2111
|
-
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2112
|
-
className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
|
|
2113
|
-
...props
|
|
2114
|
-
});
|
|
2115
|
-
DialogFooter.displayName = "DialogFooter";
|
|
2116
|
-
var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Title, {
|
|
2117
|
-
ref,
|
|
2118
|
-
className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
|
|
2119
|
-
...props
|
|
2120
|
-
}));
|
|
2121
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
2122
|
-
var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, {
|
|
2123
|
-
ref,
|
|
2124
|
-
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
2125
|
-
...props
|
|
2126
|
-
}));
|
|
2127
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
2128
|
-
//#endregion
|
|
2129
2180
|
//#region src/components/ui/progress.tsx
|
|
2130
2181
|
var Progress = React$1.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(ProgressPrimitive.Root, {
|
|
2131
2182
|
ref,
|
|
@@ -2171,39 +2222,72 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2171
2222
|
const [parsedRows, setParsedRows] = React$1.useState([]);
|
|
2172
2223
|
const [mapping, setMapping] = React$1.useState({});
|
|
2173
2224
|
const [validatedData, setValidatedData] = React$1.useState([]);
|
|
2225
|
+
const [isDragging, setIsDragging] = React$1.useState(false);
|
|
2226
|
+
const [fileError, setFileError] = React$1.useState(null);
|
|
2227
|
+
const [confirmedSkip, setConfirmedSkip] = React$1.useState(false);
|
|
2174
2228
|
const [totalRows, setTotalRows] = React$1.useState(0);
|
|
2175
2229
|
const [processedCount, setProcessedCount] = React$1.useState(0);
|
|
2176
2230
|
const [successCount, setSuccessCount] = React$1.useState(0);
|
|
2177
2231
|
const [failedRows, setFailedRows] = React$1.useState([]);
|
|
2232
|
+
const [retryableRows, setRetryableRows] = React$1.useState([]);
|
|
2178
2233
|
const importableFields = React$1.useMemo(() => {
|
|
2179
2234
|
return schema.fields.filter((f) => f.name !== "id" && f.name !== "createdAt" && f.name !== "updatedAt" && f.type !== "row" && f.type !== "join" && !f.admin?.hidden);
|
|
2180
2235
|
}, [schema]);
|
|
2181
2236
|
const requiredFields = React$1.useMemo(() => {
|
|
2182
2237
|
return importableFields.filter((f) => f.required);
|
|
2183
2238
|
}, [importableFields]);
|
|
2184
|
-
const
|
|
2185
|
-
|
|
2186
|
-
if (!
|
|
2187
|
-
|
|
2239
|
+
const processFile = (file) => {
|
|
2240
|
+
setFileError(null);
|
|
2241
|
+
if (!(file.type === "text/csv" || file.name.toLowerCase().endsWith(".csv"))) {
|
|
2242
|
+
setFileError(`Unsupported file type: "${file.name}". Please upload a CSV file.`);
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
Papa.parse(file, {
|
|
2188
2246
|
header: true,
|
|
2189
2247
|
skipEmptyLines: "greedy",
|
|
2190
2248
|
complete: (results) => {
|
|
2191
2249
|
const headers = results.meta.fields || [];
|
|
2250
|
+
const rows = results.data;
|
|
2251
|
+
if (rows.length === 0) {
|
|
2252
|
+
setFileError("This CSV file has no importable rows. Please upload a file with at least one data row.");
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2192
2255
|
setCsvHeaders(headers);
|
|
2193
|
-
setParsedRows(
|
|
2256
|
+
setParsedRows(rows);
|
|
2194
2257
|
const initialMapping = {};
|
|
2195
2258
|
headers.forEach((header) => {
|
|
2196
|
-
|
|
2197
|
-
initialMapping[header] = match ? match.name : "__ignore__";
|
|
2259
|
+
initialMapping[header] = importableFields.find((f) => f.name?.toLowerCase() === header.toLowerCase() || f.label?.toLowerCase() === header.toLowerCase())?.name ?? "__ignore__";
|
|
2198
2260
|
});
|
|
2199
2261
|
setMapping(initialMapping);
|
|
2200
2262
|
setStep("map");
|
|
2201
2263
|
},
|
|
2202
2264
|
error: (error) => {
|
|
2203
|
-
|
|
2265
|
+
setFileError(`Failed to parse CSV: ${error.message}`);
|
|
2204
2266
|
}
|
|
2205
2267
|
});
|
|
2206
2268
|
};
|
|
2269
|
+
const handleFileChange = (e) => {
|
|
2270
|
+
const selectedFile = e.target.files?.[0];
|
|
2271
|
+
if (selectedFile) processFile(selectedFile);
|
|
2272
|
+
e.target.value = "";
|
|
2273
|
+
};
|
|
2274
|
+
const handleDragOver = (e) => {
|
|
2275
|
+
e.preventDefault();
|
|
2276
|
+
e.stopPropagation();
|
|
2277
|
+
setIsDragging(true);
|
|
2278
|
+
};
|
|
2279
|
+
const handleDragLeave = (e) => {
|
|
2280
|
+
e.preventDefault();
|
|
2281
|
+
e.stopPropagation();
|
|
2282
|
+
setIsDragging(false);
|
|
2283
|
+
};
|
|
2284
|
+
const handleDrop = (e) => {
|
|
2285
|
+
e.preventDefault();
|
|
2286
|
+
e.stopPropagation();
|
|
2287
|
+
setIsDragging(false);
|
|
2288
|
+
const file = e.dataTransfer.files?.[0];
|
|
2289
|
+
if (file) processFile(file);
|
|
2290
|
+
};
|
|
2207
2291
|
const handleMapChange = (header, fieldName) => {
|
|
2208
2292
|
setMapping((prev) => ({
|
|
2209
2293
|
...prev,
|
|
@@ -2318,18 +2402,21 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2318
2402
|
isValid
|
|
2319
2403
|
};
|
|
2320
2404
|
}));
|
|
2405
|
+
setConfirmedSkip(false);
|
|
2321
2406
|
setStep("preview");
|
|
2322
2407
|
};
|
|
2323
|
-
const startImport = async () => {
|
|
2408
|
+
const startImport = async (rows = validatedData) => {
|
|
2324
2409
|
setStep("importing");
|
|
2325
|
-
setTotalRows(
|
|
2410
|
+
setTotalRows(rows.length);
|
|
2326
2411
|
setProcessedCount(0);
|
|
2327
2412
|
setSuccessCount(0);
|
|
2328
2413
|
setFailedRows([]);
|
|
2414
|
+
setRetryableRows([]);
|
|
2329
2415
|
let success = 0;
|
|
2330
2416
|
const failures = [];
|
|
2331
|
-
|
|
2332
|
-
|
|
2417
|
+
const apiFailures = [];
|
|
2418
|
+
for (let i = 0; i < rows.length; i++) {
|
|
2419
|
+
const rowResult = rows[i];
|
|
2333
2420
|
setProcessedCount(i + 1);
|
|
2334
2421
|
if (!rowResult.isValid) {
|
|
2335
2422
|
failures.push({
|
|
@@ -2359,17 +2446,24 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2359
2446
|
success++;
|
|
2360
2447
|
setSuccessCount(success);
|
|
2361
2448
|
} catch (error) {
|
|
2449
|
+
const message = error.message || "Failed to create entry";
|
|
2362
2450
|
failures.push({
|
|
2363
2451
|
row: rowResult.rowNumber,
|
|
2364
2452
|
data: rowResult.data,
|
|
2365
|
-
error:
|
|
2453
|
+
error: message
|
|
2366
2454
|
});
|
|
2367
2455
|
setFailedRows([...failures]);
|
|
2456
|
+
apiFailures.push(rowResult);
|
|
2368
2457
|
}
|
|
2369
2458
|
}
|
|
2459
|
+
setRetryableRows(apiFailures);
|
|
2370
2460
|
queryClient.invalidateQueries({ queryKey: ["collection", slug] });
|
|
2371
2461
|
setStep("complete");
|
|
2372
2462
|
};
|
|
2463
|
+
const handleRetryFailed = () => {
|
|
2464
|
+
setValidatedData(retryableRows);
|
|
2465
|
+
startImport(retryableRows);
|
|
2466
|
+
};
|
|
2373
2467
|
const downloadFailedCsv = () => {
|
|
2374
2468
|
if (failedRows.length === 0) return;
|
|
2375
2469
|
const headers = [...csvHeaders, "Import Error"];
|
|
@@ -2401,14 +2495,17 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2401
2495
|
return /* @__PURE__ */ jsxs("div", {
|
|
2402
2496
|
className: "dy-space-y-6",
|
|
2403
2497
|
children: [
|
|
2404
|
-
step === "upload" && /* @__PURE__ */
|
|
2498
|
+
step === "upload" && /* @__PURE__ */ jsxs("div", {
|
|
2405
2499
|
className: "dy-space-y-4",
|
|
2406
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
2407
|
-
className: "dy-text-center dy-py-10 dy-border-2 dy-border-dashed dy-border-
|
|
2500
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
2501
|
+
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"),
|
|
2502
|
+
onDragOver: handleDragOver,
|
|
2503
|
+
onDragLeave: handleDragLeave,
|
|
2504
|
+
onDrop: handleDrop,
|
|
2408
2505
|
children: /* @__PURE__ */ jsxs("label", {
|
|
2409
2506
|
className: "dy-cursor-pointer dy-block dy-space-y-4 dy-px-6",
|
|
2410
2507
|
children: [
|
|
2411
|
-
/* @__PURE__ */ jsx(Upload, { className: "dy-h-10 dy-w-10 dy-mx-auto dy-text-muted-foreground" }),
|
|
2508
|
+
/* @__PURE__ */ jsx(Upload, { className: cn("dy-h-10 dy-w-10 dy-mx-auto", isDragging ? "dy-text-primary" : "dy-text-muted-foreground") }),
|
|
2412
2509
|
/* @__PURE__ */ jsxs("div", {
|
|
2413
2510
|
className: "dy-space-y-1",
|
|
2414
2511
|
children: [/* @__PURE__ */ jsx("p", {
|
|
@@ -2427,7 +2524,10 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2427
2524
|
})
|
|
2428
2525
|
]
|
|
2429
2526
|
})
|
|
2430
|
-
})
|
|
2527
|
+
}), fileError && /* @__PURE__ */ jsxs("div", {
|
|
2528
|
+
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",
|
|
2529
|
+
children: [/* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }), fileError]
|
|
2530
|
+
})]
|
|
2431
2531
|
}),
|
|
2432
2532
|
step === "map" && /* @__PURE__ */ jsxs("div", {
|
|
2433
2533
|
className: "dy-space-y-4",
|
|
@@ -2531,19 +2631,22 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2531
2631
|
})]
|
|
2532
2632
|
}),
|
|
2533
2633
|
/* @__PURE__ */ jsx("div", {
|
|
2534
|
-
className: "dy-
|
|
2634
|
+
className: "dy-overflow-x-auto dy-overflow-y-auto dy-max-h-[60vh] dy-border dy-border-border dy-rounded-xl",
|
|
2535
2635
|
children: /* @__PURE__ */ jsxs("table", {
|
|
2536
|
-
className: "dy-w-
|
|
2537
|
-
children: [/* @__PURE__ */ jsx("thead", {
|
|
2538
|
-
className: "dy-
|
|
2539
|
-
children:
|
|
2540
|
-
className: "dy-
|
|
2541
|
-
children: "
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2636
|
+
className: "dy-min-w-max dy-w-full dy-text-left dy-border-collapse",
|
|
2637
|
+
children: [/* @__PURE__ */ jsx("thead", {
|
|
2638
|
+
className: "dy-sticky dy-top-0 dy-z-10",
|
|
2639
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
2640
|
+
className: "dy-border-b dy-border-border dy-bg-muted/40 dy-text-xs dy-font-semibold dy-text-muted-foreground",
|
|
2641
|
+
children: [/* @__PURE__ */ jsx("th", {
|
|
2642
|
+
className: "dy-p-3 dy-w-16",
|
|
2643
|
+
children: "Row"
|
|
2644
|
+
}), importableFields.filter((f) => Object.values(mapping).includes(f.name)).map((f) => /* @__PURE__ */ jsx("th", {
|
|
2645
|
+
className: "dy-p-3",
|
|
2646
|
+
children: f.label || f.name
|
|
2647
|
+
}, f.name))]
|
|
2648
|
+
})
|
|
2649
|
+
}), /* @__PURE__ */ jsx("tbody", {
|
|
2547
2650
|
className: "dy-text-sm",
|
|
2548
2651
|
children: previewRows.map((rowResult) => /* @__PURE__ */ jsxs("tr", {
|
|
2549
2652
|
className: "dy-border-b dy-border-border hover:dy-bg-muted/20",
|
|
@@ -2565,6 +2668,39 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2565
2668
|
})]
|
|
2566
2669
|
})
|
|
2567
2670
|
}),
|
|
2671
|
+
totalErrors > 0 && totalErrors < validatedData.length && /* @__PURE__ */ jsxs("label", {
|
|
2672
|
+
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",
|
|
2673
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
2674
|
+
type: "checkbox",
|
|
2675
|
+
className: "dy-mt-0.5 dy-accent-amber-500",
|
|
2676
|
+
checked: confirmedSkip,
|
|
2677
|
+
onChange: (e) => setConfirmedSkip(e.target.checked)
|
|
2678
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
2679
|
+
className: "dy-text-xs dy-text-amber-700 dark:dy-text-amber-400",
|
|
2680
|
+
children: [
|
|
2681
|
+
"I understand that ",
|
|
2682
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
2683
|
+
totalErrors,
|
|
2684
|
+
" row",
|
|
2685
|
+
totalErrors !== 1 ? "s" : ""
|
|
2686
|
+
] }),
|
|
2687
|
+
" with validation errors will be skipped. Only the ",
|
|
2688
|
+
validatedData.length - totalErrors,
|
|
2689
|
+
" valid row",
|
|
2690
|
+
validatedData.length - totalErrors !== 1 ? "s" : "",
|
|
2691
|
+
" will be imported."
|
|
2692
|
+
]
|
|
2693
|
+
})]
|
|
2694
|
+
}),
|
|
2695
|
+
totalErrors === validatedData.length && /* @__PURE__ */ jsxs("div", {
|
|
2696
|
+
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",
|
|
2697
|
+
children: [
|
|
2698
|
+
/* @__PURE__ */ jsx(AlertCircle, { className: "dy-h-4 dy-w-4 dy-shrink-0" }),
|
|
2699
|
+
"All ",
|
|
2700
|
+
totalErrors,
|
|
2701
|
+
" rows have validation errors. Fix your CSV and re-upload before importing."
|
|
2702
|
+
]
|
|
2703
|
+
}),
|
|
2568
2704
|
/* @__PURE__ */ jsxs("div", {
|
|
2569
2705
|
className: "dy-flex dy-justify-between dy-pt-4",
|
|
2570
2706
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
@@ -2572,14 +2708,17 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2572
2708
|
onClick: () => setStep("map"),
|
|
2573
2709
|
children: "Back"
|
|
2574
2710
|
}), /* @__PURE__ */ jsxs(Button, {
|
|
2575
|
-
onClick: startImport,
|
|
2711
|
+
onClick: () => startImport(),
|
|
2576
2712
|
variant: "default",
|
|
2577
2713
|
className: "dy-gap-2",
|
|
2714
|
+
disabled: totalErrors === validatedData.length || totalErrors > 0 && !confirmedSkip,
|
|
2578
2715
|
children: [
|
|
2579
2716
|
/* @__PURE__ */ jsx(Play, { className: "dy-h-4 dy-w-4" }),
|
|
2580
2717
|
" Start Import (",
|
|
2581
2718
|
validatedData.length - totalErrors,
|
|
2582
|
-
"
|
|
2719
|
+
" Row",
|
|
2720
|
+
validatedData.length - totalErrors !== 1 ? "s" : "",
|
|
2721
|
+
")"
|
|
2583
2722
|
]
|
|
2584
2723
|
})]
|
|
2585
2724
|
})
|
|
@@ -2657,12 +2796,27 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2657
2796
|
failedRows.length,
|
|
2658
2797
|
" rows)"
|
|
2659
2798
|
]
|
|
2660
|
-
}), /* @__PURE__ */ jsxs(
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2799
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
2800
|
+
className: "dy-flex dy-items-center dy-gap-2",
|
|
2801
|
+
children: [retryableRows.length > 0 && /* @__PURE__ */ jsxs(Button, {
|
|
2802
|
+
size: "sm",
|
|
2803
|
+
variant: "outline",
|
|
2804
|
+
className: "dy-h-8 dy-text-xs dy-gap-1.5",
|
|
2805
|
+
onClick: handleRetryFailed,
|
|
2806
|
+
children: [
|
|
2807
|
+
/* @__PURE__ */ jsx(RotateCcw, { className: "dy-h-3.5 dy-w-3.5" }),
|
|
2808
|
+
" Retry ",
|
|
2809
|
+
retryableRows.length,
|
|
2810
|
+
" Failed Row",
|
|
2811
|
+
retryableRows.length !== 1 ? "s" : ""
|
|
2812
|
+
]
|
|
2813
|
+
}), /* @__PURE__ */ jsxs(Button, {
|
|
2814
|
+
size: "sm",
|
|
2815
|
+
variant: "outline",
|
|
2816
|
+
className: "dy-h-8 dy-text-xs dy-gap-1.5",
|
|
2817
|
+
onClick: downloadFailedCsv,
|
|
2818
|
+
children: [/* @__PURE__ */ jsx(Download, { className: "dy-h-3.5 dy-w-3.5" }), " Download Errors CSV"]
|
|
2819
|
+
})]
|
|
2666
2820
|
})]
|
|
2667
2821
|
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
2668
2822
|
className: "dy-h-[180px] dy-border dy-border-border dy-rounded-xl",
|
|
@@ -2707,27 +2861,6 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
2707
2861
|
});
|
|
2708
2862
|
}
|
|
2709
2863
|
//#endregion
|
|
2710
|
-
//#region src/components/ui/csv-importer-dialog.tsx
|
|
2711
|
-
function CsvImporterDialog({ open, onOpenChange, slug, schema }) {
|
|
2712
|
-
const title = schema.labels?.singular || schema.slug || slug;
|
|
2713
|
-
return /* @__PURE__ */ jsx(Dialog, {
|
|
2714
|
-
open,
|
|
2715
|
-
onOpenChange,
|
|
2716
|
-
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
2717
|
-
className: "sm:dy-max-w-2xl",
|
|
2718
|
-
children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Import CSV Data" }), /* @__PURE__ */ jsxs(DialogDescription, { children: [
|
|
2719
|
-
"Import records into the ",
|
|
2720
|
-
title,
|
|
2721
|
-
" collection."
|
|
2722
|
-
] })] }), /* @__PURE__ */ jsx(CsvImporter, {
|
|
2723
|
-
slug,
|
|
2724
|
-
schema,
|
|
2725
|
-
onClose: () => onOpenChange(false)
|
|
2726
|
-
})]
|
|
2727
|
-
})
|
|
2728
|
-
});
|
|
2729
|
-
}
|
|
2730
|
-
//#endregion
|
|
2731
2864
|
//#region src/components/ui/render-cell.tsx
|
|
2732
2865
|
function RenderCell({ value, field, client, schemas }) {
|
|
2733
2866
|
if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", {
|
|
@@ -2943,14 +3076,14 @@ function MediaGrid({ items, baseUrl, onDelete, slug }) {
|
|
|
2943
3076
|
}
|
|
2944
3077
|
//#endregion
|
|
2945
3078
|
//#region src/components/ui/sheet.tsx
|
|
2946
|
-
var Sheet =
|
|
2947
|
-
var SheetPortal =
|
|
2948
|
-
var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3079
|
+
var Sheet = SheetPrimitive.Root;
|
|
3080
|
+
var SheetPortal = SheetPrimitive.Portal;
|
|
3081
|
+
var SheetOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
|
|
2949
3082
|
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),
|
|
2950
3083
|
...props,
|
|
2951
3084
|
ref
|
|
2952
3085
|
}));
|
|
2953
|
-
SheetOverlay.displayName =
|
|
3086
|
+
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
2954
3087
|
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", {
|
|
2955
3088
|
variants: { side: {
|
|
2956
3089
|
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",
|
|
@@ -2965,11 +3098,11 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
|
|
|
2965
3098
|
return /* @__PURE__ */ jsx(SheetPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
2966
3099
|
className: themeClassName,
|
|
2967
3100
|
"data-theme": resolvedTheme,
|
|
2968
|
-
children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(
|
|
3101
|
+
children: [/* @__PURE__ */ jsx(SheetOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
|
|
2969
3102
|
ref,
|
|
2970
3103
|
className: cn(sheetVariants({ side }), className),
|
|
2971
3104
|
...props,
|
|
2972
|
-
children: [children, /* @__PURE__ */ jsxs(
|
|
3105
|
+
children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
|
|
2973
3106
|
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",
|
|
2974
3107
|
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
2975
3108
|
className: "dy-sr-only",
|
|
@@ -2979,7 +3112,7 @@ var SheetContent = React$1.forwardRef(({ side = "right", className, children, ..
|
|
|
2979
3112
|
})]
|
|
2980
3113
|
}) });
|
|
2981
3114
|
});
|
|
2982
|
-
SheetContent.displayName =
|
|
3115
|
+
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
|
2983
3116
|
var SheetHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2984
3117
|
className: cn("dy-flex dy-flex-col dy-space-y-2 dy-text-center sm:dy-text-left", className),
|
|
2985
3118
|
...props
|
|
@@ -2990,18 +3123,18 @@ var SheetFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
|
2990
3123
|
...props
|
|
2991
3124
|
});
|
|
2992
3125
|
SheetFooter.displayName = "SheetFooter";
|
|
2993
|
-
var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3126
|
+
var SheetTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
|
|
2994
3127
|
ref,
|
|
2995
3128
|
className: cn("dy-text-lg dy-font-semibold dy-text-foreground", className),
|
|
2996
3129
|
...props
|
|
2997
3130
|
}));
|
|
2998
|
-
SheetTitle.displayName =
|
|
2999
|
-
var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
3131
|
+
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
|
3132
|
+
var SheetDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
|
|
3000
3133
|
ref,
|
|
3001
3134
|
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
3002
3135
|
...props
|
|
3003
3136
|
}));
|
|
3004
|
-
SheetDescription.displayName =
|
|
3137
|
+
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
3005
3138
|
//#endregion
|
|
3006
3139
|
//#region src/components/ui/toggle.tsx
|
|
3007
3140
|
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", {
|
|
@@ -3032,6 +3165,59 @@ var Toggle = React$1.forwardRef(({ className, variant, size, ...props }, ref) =>
|
|
|
3032
3165
|
}));
|
|
3033
3166
|
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
3034
3167
|
//#endregion
|
|
3168
|
+
//#region src/components/ui/dialog.tsx
|
|
3169
|
+
var Dialog = SheetPrimitive.Root;
|
|
3170
|
+
var DialogTrigger = SheetPrimitive.Trigger;
|
|
3171
|
+
var DialogPortal = SheetPrimitive.Portal;
|
|
3172
|
+
var DialogOverlay = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Overlay, {
|
|
3173
|
+
ref,
|
|
3174
|
+
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),
|
|
3175
|
+
...props
|
|
3176
|
+
}));
|
|
3177
|
+
DialogOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
3178
|
+
var DialogContent = React$1.forwardRef(({ className, children, ...props }, ref) => {
|
|
3179
|
+
const { resolvedTheme, themeClassName } = useAdminTheme();
|
|
3180
|
+
return /* @__PURE__ */ jsx(DialogPortal, { children: /* @__PURE__ */ jsxs("div", {
|
|
3181
|
+
className: themeClassName,
|
|
3182
|
+
"data-theme": resolvedTheme,
|
|
3183
|
+
children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(SheetPrimitive.Content, {
|
|
3184
|
+
ref,
|
|
3185
|
+
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),
|
|
3186
|
+
...props,
|
|
3187
|
+
children: [children, /* @__PURE__ */ jsxs(SheetPrimitive.Close, {
|
|
3188
|
+
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",
|
|
3189
|
+
children: [/* @__PURE__ */ jsx(X, { className: "dy-h-4 dy-w-4" }), /* @__PURE__ */ jsx("span", {
|
|
3190
|
+
className: "dy-sr-only",
|
|
3191
|
+
children: "Close"
|
|
3192
|
+
})]
|
|
3193
|
+
})]
|
|
3194
|
+
})]
|
|
3195
|
+
}) });
|
|
3196
|
+
});
|
|
3197
|
+
DialogContent.displayName = SheetPrimitive.Content.displayName;
|
|
3198
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
3199
|
+
className: cn("dy-flex dy-flex-col dy-space-y-1.5 dy-text-center sm:dy-text-left", className),
|
|
3200
|
+
...props
|
|
3201
|
+
});
|
|
3202
|
+
DialogHeader.displayName = "DialogHeader";
|
|
3203
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
3204
|
+
className: cn("dy-flex dy-flex-col-reverse sm:dy-flex-row sm:dy-justify-end sm:dy-space-x-2", className),
|
|
3205
|
+
...props
|
|
3206
|
+
});
|
|
3207
|
+
DialogFooter.displayName = "DialogFooter";
|
|
3208
|
+
var DialogTitle = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Title, {
|
|
3209
|
+
ref,
|
|
3210
|
+
className: cn("dy-text-lg dy-font-semibold dy-leading-none dy-tracking-tight", className),
|
|
3211
|
+
...props
|
|
3212
|
+
}));
|
|
3213
|
+
DialogTitle.displayName = SheetPrimitive.Title.displayName;
|
|
3214
|
+
var DialogDescription = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(SheetPrimitive.Description, {
|
|
3215
|
+
ref,
|
|
3216
|
+
className: cn("dy-text-sm dy-text-muted-foreground", className),
|
|
3217
|
+
...props
|
|
3218
|
+
}));
|
|
3219
|
+
DialogDescription.displayName = SheetPrimitive.Description.displayName;
|
|
3220
|
+
//#endregion
|
|
3035
3221
|
//#region src/components/ui/tabs.tsx
|
|
3036
3222
|
var Tabs = TabsPrimitive.Root;
|
|
3037
3223
|
var TabsList = React$1.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.List, {
|
|
@@ -6615,244 +6801,228 @@ function UrlField({ schema: _schema, field, disabled, context: _context }) {
|
|
|
6615
6801
|
const [docsLoading, setDocsLoading] = React$1.useState(false);
|
|
6616
6802
|
const parseValue = (val) => {
|
|
6617
6803
|
if (!val) return {
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
type: "custom",
|
|
6621
|
-
url: "",
|
|
6622
|
-
label: ""
|
|
6623
|
-
}
|
|
6804
|
+
type: "custom",
|
|
6805
|
+
url: ""
|
|
6624
6806
|
};
|
|
6625
6807
|
if (typeof val === "string") return {
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
type: "custom",
|
|
6629
|
-
url: val,
|
|
6630
|
-
label: ""
|
|
6631
|
-
}
|
|
6808
|
+
type: "custom",
|
|
6809
|
+
url: val
|
|
6632
6810
|
};
|
|
6633
|
-
if (typeof val === "object"
|
|
6634
|
-
|
|
6635
|
-
|
|
6811
|
+
if (typeof val === "object") return {
|
|
6812
|
+
type: val.type === "internal" ? "internal" : "custom",
|
|
6813
|
+
url: val.url || "",
|
|
6814
|
+
relationTo: val.relationTo,
|
|
6815
|
+
value: val.value,
|
|
6816
|
+
label: val.label
|
|
6636
6817
|
};
|
|
6637
6818
|
return {
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
type: "custom",
|
|
6641
|
-
url: String(val),
|
|
6642
|
-
label: ""
|
|
6643
|
-
}
|
|
6819
|
+
type: "custom",
|
|
6820
|
+
url: String(val)
|
|
6644
6821
|
};
|
|
6645
6822
|
};
|
|
6646
|
-
const
|
|
6647
|
-
const [
|
|
6648
|
-
const [urlValue, setUrlValue] = React$1.useState(currentData.url || "");
|
|
6823
|
+
const currentData = parseValue(field.value);
|
|
6824
|
+
const [urlValue, setUrlValue] = React$1.useState(currentData.url);
|
|
6649
6825
|
const [labelValue, setLabelValue] = React$1.useState(currentData.label || "");
|
|
6650
6826
|
const [collectionValue, setCollectionValue] = React$1.useState(currentData.relationTo || "");
|
|
6651
6827
|
const [docValue, setDocValue] = React$1.useState(currentData.value || "");
|
|
6652
|
-
const
|
|
6653
|
-
const [docSearch, setDocSearch] = React$1.useState("");
|
|
6654
|
-
const collections = schemas?.collections || [];
|
|
6828
|
+
const collections = React$1.useMemo(() => schemas?.collections || [], [schemas?.collections]);
|
|
6655
6829
|
React$1.useEffect(() => {
|
|
6656
|
-
if (
|
|
6830
|
+
if (!client || !schemas?.collections) return;
|
|
6831
|
+
const eligibleCollections = collections.filter((c) => c.admin?.previewUrl);
|
|
6832
|
+
if (eligibleCollections.length === 0) return;
|
|
6833
|
+
let active = true;
|
|
6834
|
+
Promise.resolve().then(() => {
|
|
6835
|
+
if (!active) return;
|
|
6657
6836
|
setDocsLoading(true);
|
|
6658
6837
|
setDocuments([]);
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6838
|
+
});
|
|
6839
|
+
Promise.all(eligibleCollections.map((col) => client.collection(col.slug).find({ limit: 50 }).exec().then((res) => ({
|
|
6840
|
+
collection: col,
|
|
6841
|
+
docs: res.docs || []
|
|
6842
|
+
})).catch((err) => {
|
|
6843
|
+
console.error(`Failed to load documents for ${col.slug}:`, err);
|
|
6844
|
+
return {
|
|
6845
|
+
collection: col,
|
|
6846
|
+
docs: []
|
|
6847
|
+
};
|
|
6848
|
+
}))).then((results) => {
|
|
6849
|
+
if (!active) return;
|
|
6850
|
+
setDocuments(results.flatMap((r) => r.docs.map((doc) => ({
|
|
6851
|
+
...doc,
|
|
6852
|
+
__collectionSlug: r.collection.slug,
|
|
6853
|
+
__collectionLabel: r.collection.labels?.plural || r.collection.slug,
|
|
6854
|
+
__previewUrl: r.collection.admin?.previewUrl
|
|
6855
|
+
}))));
|
|
6856
|
+
}).catch((err) => {
|
|
6857
|
+
console.error("Failed to load documents:", err);
|
|
6858
|
+
}).finally(() => {
|
|
6859
|
+
if (active) setDocsLoading(false);
|
|
6860
|
+
});
|
|
6861
|
+
return () => {
|
|
6862
|
+
active = false;
|
|
6675
6863
|
};
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6864
|
+
}, [
|
|
6865
|
+
client,
|
|
6866
|
+
schemas,
|
|
6867
|
+
collections
|
|
6868
|
+
]);
|
|
6869
|
+
const handleUpdate = (url, label, relationTo, docId) => {
|
|
6870
|
+
const isInternal = !!(relationTo && docId);
|
|
6871
|
+
const newValue = {
|
|
6872
|
+
type: isInternal ? "internal" : "custom",
|
|
6873
|
+
url: url || void 0,
|
|
6874
|
+
relationTo: isInternal ? relationTo : void 0,
|
|
6875
|
+
value: isInternal ? docId : void 0,
|
|
6876
|
+
label: label || void 0
|
|
6682
6877
|
};
|
|
6683
6878
|
field.onChange(newValue);
|
|
6684
6879
|
};
|
|
6685
|
-
const
|
|
6686
|
-
setMode(newMode);
|
|
6687
|
-
if (newMode === "external") {
|
|
6688
|
-
setUrlValue(currentData.url || "");
|
|
6689
|
-
setLabelValue(currentData.label || "");
|
|
6690
|
-
setResolvedUrlValue("");
|
|
6691
|
-
} else {
|
|
6692
|
-
setCollectionValue(currentData.relationTo || "");
|
|
6693
|
-
setDocValue(currentData.value || "");
|
|
6694
|
-
setResolvedUrlValue(currentData.type === "internal" ? currentData.url || "" : "");
|
|
6695
|
-
setLabelValue(currentData.label || "");
|
|
6696
|
-
}
|
|
6697
|
-
};
|
|
6698
|
-
const handleExternalUrlChange = (value) => {
|
|
6880
|
+
const handleUrlInputChange = (value) => {
|
|
6699
6881
|
setUrlValue(value);
|
|
6700
|
-
|
|
6882
|
+
setCollectionValue("");
|
|
6883
|
+
setDocValue("");
|
|
6884
|
+
handleUpdate(value, labelValue);
|
|
6701
6885
|
};
|
|
6702
|
-
const
|
|
6886
|
+
const handleLabelInputChange = (value) => {
|
|
6703
6887
|
setLabelValue(value);
|
|
6704
|
-
handleUpdate(
|
|
6705
|
-
};
|
|
6706
|
-
const handleCollectionChange = (value) => {
|
|
6707
|
-
setCollectionValue(value);
|
|
6708
|
-
setDocValue("");
|
|
6709
|
-
setResolvedUrlValue("");
|
|
6888
|
+
handleUpdate(urlValue, value, collectionValue, docValue);
|
|
6710
6889
|
};
|
|
6711
|
-
const handleDocumentSelect = (
|
|
6712
|
-
setDocValue(
|
|
6890
|
+
const handleDocumentSelect = (doc) => {
|
|
6891
|
+
setDocValue(doc.id);
|
|
6892
|
+
setCollectionValue(doc.__collectionSlug);
|
|
6713
6893
|
setOpenPopover(false);
|
|
6714
|
-
const urlPattern =
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6894
|
+
const urlPattern = doc.__previewUrl;
|
|
6895
|
+
let resolvedUrl = void 0;
|
|
6896
|
+
if (urlPattern) {
|
|
6897
|
+
if (typeof urlPattern === "function") resolvedUrl = urlPattern(doc, { locale: "en" });
|
|
6898
|
+
else if (typeof urlPattern === "string") if (urlPattern.includes("{{")) resolvedUrl = urlPattern.replace(/{{(.*?)}}/g, (_, key) => String(doc[key.trim()] || ""));
|
|
6899
|
+
else try {
|
|
6900
|
+
const context = {
|
|
6901
|
+
...doc,
|
|
6902
|
+
siteUrl: window.location.origin
|
|
6903
|
+
};
|
|
6904
|
+
if (urlPattern.includes("+") || urlPattern.includes("?") || urlPattern.includes("==") || urlPattern.includes("siteUrl")) resolvedUrl = jexl.evalSync(urlPattern, context);
|
|
6905
|
+
else resolvedUrl = interpolateUrlPattern(urlPattern, doc);
|
|
6906
|
+
} catch {
|
|
6907
|
+
resolvedUrl = interpolateUrlPattern(urlPattern, doc);
|
|
6908
|
+
}
|
|
6909
|
+
}
|
|
6910
|
+
if (typeof resolvedUrl === "string" && resolvedUrl.startsWith("/")) resolvedUrl = `${window.location.origin}${resolvedUrl}`;
|
|
6911
|
+
const finalUrl = resolvedUrl || "";
|
|
6912
|
+
setUrlValue(finalUrl);
|
|
6913
|
+
handleUpdate(finalUrl, labelValue, doc.__collectionSlug, doc.id);
|
|
6726
6914
|
};
|
|
6727
|
-
const getCollectionDisplayField = (collectionSlug) => {
|
|
6915
|
+
const getCollectionDisplayField = React$1.useCallback((collectionSlug) => {
|
|
6728
6916
|
return collections.find((c) => c.slug === collectionSlug)?.admin?.useAsTitle || "title";
|
|
6729
|
-
};
|
|
6730
|
-
const getDocumentDisplay = (doc, collectionSlug) => {
|
|
6917
|
+
}, [collections]);
|
|
6918
|
+
const getDocumentDisplay = React$1.useCallback((doc, collectionSlug) => {
|
|
6731
6919
|
return doc[getCollectionDisplayField(collectionSlug)] || doc.name || doc.slug || doc.id;
|
|
6732
|
-
};
|
|
6733
|
-
const
|
|
6920
|
+
}, [getCollectionDisplayField]);
|
|
6921
|
+
const filteredDocs = React$1.useMemo(() => {
|
|
6922
|
+
if (!urlValue) return documents;
|
|
6923
|
+
const query = urlValue.toLowerCase();
|
|
6924
|
+
return documents.filter((doc) => {
|
|
6925
|
+
const display = getDocumentDisplay(doc, doc.__collectionSlug).toLowerCase();
|
|
6926
|
+
const slug = String(doc.slug || "").toLowerCase();
|
|
6927
|
+
return display.includes(query) || slug.includes(query);
|
|
6928
|
+
});
|
|
6929
|
+
}, [
|
|
6930
|
+
documents,
|
|
6931
|
+
urlValue,
|
|
6932
|
+
getDocumentDisplay
|
|
6933
|
+
]);
|
|
6934
|
+
const selectedDoc = documents.find((d) => d.id === docValue && d.__collectionSlug === collectionValue);
|
|
6734
6935
|
const selectedCollectionLabel = collections.find((c) => c.slug === collectionValue)?.labels?.singular || collectionValue;
|
|
6735
|
-
return /* @__PURE__ */
|
|
6936
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6736
6937
|
className: "dy-space-y-3",
|
|
6737
|
-
children: /* @__PURE__ */ jsxs(
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
children: [
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
disabled,
|
|
6746
|
-
className: "dy-rounded-md",
|
|
6747
|
-
children: "Internal Link"
|
|
6748
|
-
}), /* @__PURE__ */ jsx(TabsTrigger, {
|
|
6749
|
-
value: "external",
|
|
6750
|
-
disabled,
|
|
6751
|
-
className: "dy-rounded-md",
|
|
6752
|
-
children: "External Link"
|
|
6753
|
-
})]
|
|
6754
|
-
}),
|
|
6755
|
-
/* @__PURE__ */ jsxs(TabsContent, {
|
|
6756
|
-
value: "external",
|
|
6757
|
-
className: "dy-space-y-3 dy-mt-3",
|
|
6758
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
6759
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6760
|
-
children: "URL"
|
|
6761
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
6762
|
-
type: "url",
|
|
6763
|
-
value: urlValue,
|
|
6764
|
-
onChange: (e) => handleExternalUrlChange(e.target.value),
|
|
6765
|
-
placeholder: "https://example.com",
|
|
6766
|
-
disabled,
|
|
6767
|
-
className: "dy-border-border/50"
|
|
6768
|
-
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
6769
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6770
|
-
children: "Link Label (Optional)"
|
|
6771
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
6938
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(Popover, {
|
|
6939
|
+
open: openPopover && !disabled,
|
|
6940
|
+
onOpenChange: setOpenPopover,
|
|
6941
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
6942
|
+
asChild: true,
|
|
6943
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
6944
|
+
className: "dy-w-full",
|
|
6945
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
6772
6946
|
type: "text",
|
|
6773
|
-
value:
|
|
6774
|
-
onChange: (e) =>
|
|
6775
|
-
|
|
6947
|
+
value: urlValue,
|
|
6948
|
+
onChange: (e) => handleUrlInputChange(e.target.value),
|
|
6949
|
+
onFocus: () => setOpenPopover(true),
|
|
6950
|
+
placeholder: "Type or paste a URL, or search pages...",
|
|
6776
6951
|
disabled,
|
|
6777
|
-
className: "dy-border-border/50"
|
|
6778
|
-
})
|
|
6779
|
-
})
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
6789
|
-
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
value:
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
6822
|
-
className: "dy-w-full dy-p-0",
|
|
6823
|
-
align: "start",
|
|
6824
|
-
children: /* @__PURE__ */ jsxs(Command$1, { children: [/* @__PURE__ */ jsx(CommandInput, {
|
|
6825
|
-
placeholder: `Search ${selectedCollectionLabel}...`,
|
|
6826
|
-
value: docSearch,
|
|
6827
|
-
onValueChange: setDocSearch
|
|
6828
|
-
}), /* @__PURE__ */ jsxs(CommandList, { children: [/* @__PURE__ */ jsx(CommandEmpty, { children: docsLoading ? "Searching..." : "No documents found." }), /* @__PURE__ */ jsx(CommandGroup, { children: documents.filter((doc) => {
|
|
6829
|
-
if (!docSearch) return true;
|
|
6830
|
-
return getDocumentDisplay(doc, collectionValue).toLowerCase().includes(docSearch.toLowerCase());
|
|
6831
|
-
}).map((doc) => /* @__PURE__ */ jsxs(CommandItem, {
|
|
6832
|
-
value: doc.id,
|
|
6833
|
-
onSelect: () => handleDocumentSelect(doc.id),
|
|
6834
|
-
children: [/* @__PURE__ */ jsx(Check, { className: cn("dy-mr-2 dy-h-4 dy-w-4", docValue === doc.id ? "dy-opacity-100" : "dy-opacity-0") }), /* @__PURE__ */ jsx("span", {
|
|
6952
|
+
className: "dy-bg-background dy-border-border/50 dy-h-11 dy-w-full"
|
|
6953
|
+
})
|
|
6954
|
+
})
|
|
6955
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
6956
|
+
className: "dy-p-0 dy-w-[var(--radix-popover-trigger-width)] dy-max-h-60 dy-overflow-y-auto",
|
|
6957
|
+
align: "start",
|
|
6958
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
6959
|
+
children: /* @__PURE__ */ jsx(Command$1, {
|
|
6960
|
+
className: "dy-border-none",
|
|
6961
|
+
shouldFilter: false,
|
|
6962
|
+
children: /* @__PURE__ */ jsxs(CommandList, { children: [
|
|
6963
|
+
/* @__PURE__ */ jsx(CommandEmpty, {
|
|
6964
|
+
className: "dy-py-2.5 dy-px-3 dy-text-xs dy-text-muted-foreground",
|
|
6965
|
+
children: docsLoading ? "Loading pages..." : "No matching pages found. Press Enter to use as custom link."
|
|
6966
|
+
}),
|
|
6967
|
+
urlValue && /* @__PURE__ */ jsx(CommandGroup, {
|
|
6968
|
+
heading: "Custom Link",
|
|
6969
|
+
children: /* @__PURE__ */ jsxs(CommandItem, {
|
|
6970
|
+
value: `custom-${urlValue}`,
|
|
6971
|
+
onSelect: () => {
|
|
6972
|
+
handleUrlInputChange(urlValue);
|
|
6973
|
+
setOpenPopover(false);
|
|
6974
|
+
},
|
|
6975
|
+
className: "dy-text-primary",
|
|
6976
|
+
children: [
|
|
6977
|
+
"Use link \"",
|
|
6978
|
+
urlValue,
|
|
6979
|
+
"\""
|
|
6980
|
+
]
|
|
6981
|
+
})
|
|
6982
|
+
}),
|
|
6983
|
+
(() => {
|
|
6984
|
+
const grouped = {};
|
|
6985
|
+
filteredDocs.forEach((doc) => {
|
|
6986
|
+
const key = doc.__collectionLabel;
|
|
6987
|
+
if (!grouped[key]) grouped[key] = [];
|
|
6988
|
+
grouped[key].push(doc);
|
|
6989
|
+
});
|
|
6990
|
+
return Object.entries(grouped).map(([groupName, docs]) => /* @__PURE__ */ jsx(CommandGroup, {
|
|
6991
|
+
heading: groupName,
|
|
6992
|
+
children: docs.map((doc) => /* @__PURE__ */ jsxs(CommandItem, {
|
|
6993
|
+
value: `${doc.__collectionSlug}-${doc.id}-${getDocumentDisplay(doc, doc.__collectionSlug)}`,
|
|
6994
|
+
onSelect: () => handleDocumentSelect(doc),
|
|
6995
|
+
children: [/* @__PURE__ */ jsx(Check, { className: cn("dy-mr-2 dy-h-4 dy-w-4", docValue === doc.id && collectionValue === doc.__collectionSlug ? "dy-opacity-100" : "dy-opacity-0") }), /* @__PURE__ */ jsx("span", {
|
|
6835
6996
|
className: "dy-flex-1",
|
|
6836
|
-
children: getDocumentDisplay(doc,
|
|
6997
|
+
children: getDocumentDisplay(doc, doc.__collectionSlug)
|
|
6837
6998
|
})]
|
|
6838
|
-
}, doc.id
|
|
6839
|
-
})
|
|
6840
|
-
})
|
|
6841
|
-
|
|
6842
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6843
|
-
children: "Link Label (Optional)"
|
|
6844
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
6845
|
-
type: "text",
|
|
6846
|
-
value: labelValue,
|
|
6847
|
-
onChange: (e) => handleInternalLabelChange(e.target.value),
|
|
6848
|
-
placeholder: "e.g., Read More",
|
|
6849
|
-
disabled,
|
|
6850
|
-
className: "dy-bg-background dy-border-border/50"
|
|
6851
|
-
})] })
|
|
6852
|
-
]
|
|
6999
|
+
}, `${doc.__collectionSlug}-${doc.id}`))
|
|
7000
|
+
}, groupName));
|
|
7001
|
+
})()
|
|
7002
|
+
] })
|
|
6853
7003
|
})
|
|
6854
|
-
]
|
|
6855
|
-
})
|
|
7004
|
+
})]
|
|
7005
|
+
}), selectedDoc && /* @__PURE__ */ jsxs("p", {
|
|
7006
|
+
className: "dy-text-[11px] dy-text-muted-foreground dy-mt-1.5",
|
|
7007
|
+
children: ["Linked to internal page: ", /* @__PURE__ */ jsxs("span", {
|
|
7008
|
+
className: "dy-font-medium dy-text-foreground",
|
|
7009
|
+
children: [
|
|
7010
|
+
selectedCollectionLabel,
|
|
7011
|
+
": ",
|
|
7012
|
+
getDocumentDisplay(selectedDoc, collectionValue)
|
|
7013
|
+
]
|
|
7014
|
+
})]
|
|
7015
|
+
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
7016
|
+
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
7017
|
+
children: "Link Label (Optional)"
|
|
7018
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
7019
|
+
type: "text",
|
|
7020
|
+
value: labelValue,
|
|
7021
|
+
onChange: (e) => handleLabelInputChange(e.target.value),
|
|
7022
|
+
placeholder: "e.g., Learn More",
|
|
7023
|
+
disabled,
|
|
7024
|
+
className: "dy-bg-background dy-border-border/50"
|
|
7025
|
+
})] })]
|
|
6856
7026
|
});
|
|
6857
7027
|
}
|
|
6858
7028
|
//#endregion
|
|
@@ -9706,7 +9876,7 @@ function CollectionListPage({ slug }) {
|
|
|
9706
9876
|
const allAvailableColumns = React$1.useMemo(() => {
|
|
9707
9877
|
if (!schema) return [];
|
|
9708
9878
|
return [
|
|
9709
|
-
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
|
|
9879
|
+
...schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((field) => field.name),
|
|
9710
9880
|
"id",
|
|
9711
9881
|
"createdAt",
|
|
9712
9882
|
"updatedAt"
|
|
@@ -9714,7 +9884,7 @@ function CollectionListPage({ slug }) {
|
|
|
9714
9884
|
}, [schema]);
|
|
9715
9885
|
const defaultListColumns = React$1.useMemo(() => {
|
|
9716
9886
|
if (!schema) return [];
|
|
9717
|
-
const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9887
|
+
const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9718
9888
|
const configuredColumns = Array.isArray(schema.admin?.defaultColumns) ? schema.admin.defaultColumns : [];
|
|
9719
9889
|
return configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
|
|
9720
9890
|
}, [schema]);
|
|
@@ -9913,7 +10083,7 @@ function CollectionListPage({ slug }) {
|
|
|
9913
10083
|
key: "id",
|
|
9914
10084
|
label: "ID"
|
|
9915
10085
|
},
|
|
9916
|
-
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").map((f) => ({
|
|
10086
|
+
...schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join").filter((f) => !!f.name).map((f) => ({
|
|
9917
10087
|
key: f.name,
|
|
9918
10088
|
label: f.label || f.name
|
|
9919
10089
|
})),
|
|
@@ -9988,7 +10158,7 @@ function CollectionListPage({ slug }) {
|
|
|
9988
10158
|
}
|
|
9989
10159
|
const columns = React$1.useMemo(() => {
|
|
9990
10160
|
if (!schema) return [];
|
|
9991
|
-
const allDisplayFields = schema.fields.filter((f) => f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
10161
|
+
const allDisplayFields = schema.fields.filter((f) => f.name && f.name !== "password" && !f.admin?.hidden && f.type !== "row" && f.type !== "join");
|
|
9992
10162
|
const fieldByName = new Map(allDisplayFields.map((field) => [field.name, field]));
|
|
9993
10163
|
const configuredColumns = localPreference.columns.filter((col) => col.visible).map((col) => col.name);
|
|
9994
10164
|
const visibleColumnNames = configuredColumns.length > 0 ? configuredColumns : allDisplayFields.slice(0, 3).map((field) => field.name);
|
|
@@ -10009,8 +10179,25 @@ function CollectionListPage({ slug }) {
|
|
|
10009
10179
|
}
|
|
10010
10180
|
return true;
|
|
10011
10181
|
};
|
|
10182
|
+
const getPreviewUrl = (item) => {
|
|
10183
|
+
if (!schema?.admin?.previewUrl) return null;
|
|
10184
|
+
let previewUrl = typeof schema.admin.previewUrl === "function" ? schema.admin.previewUrl(item, { locale: "en" }) : schema.admin.previewUrl;
|
|
10185
|
+
if (typeof previewUrl === "string" && previewUrl.includes("{{")) previewUrl = previewUrl.replace(/{{(.*?)}}/g, (_, key) => String(item[key.trim()] || ""));
|
|
10186
|
+
else if (typeof previewUrl === "string") try {
|
|
10187
|
+
const context = {
|
|
10188
|
+
...item,
|
|
10189
|
+
siteUrl: window.location.origin
|
|
10190
|
+
};
|
|
10191
|
+
if (previewUrl.includes("+") || previewUrl.includes("?") || previewUrl.includes("==") || previewUrl.includes("siteUrl")) previewUrl = jexl.evalSync(previewUrl, context);
|
|
10192
|
+
} catch (e) {
|
|
10193
|
+
console.warn("Preview URL eval failed:", e);
|
|
10194
|
+
}
|
|
10195
|
+
if (typeof previewUrl === "string" && previewUrl.startsWith("/")) previewUrl = `${window.location.origin}${previewUrl}`;
|
|
10196
|
+
return typeof previewUrl === "string" ? previewUrl : null;
|
|
10197
|
+
};
|
|
10012
10198
|
const renderLinkedCell = (item, cell) => {
|
|
10013
10199
|
const canDelete = canDeleteRow(item);
|
|
10200
|
+
const previewUrl = getPreviewUrl(item);
|
|
10014
10201
|
return /* @__PURE__ */ jsxs("div", {
|
|
10015
10202
|
className: "dy-flex dy-flex-col dy-gap-1",
|
|
10016
10203
|
children: [/* @__PURE__ */ jsx(Link, {
|
|
@@ -10020,6 +10207,16 @@ function CollectionListPage({ slug }) {
|
|
|
10020
10207
|
}), /* @__PURE__ */ jsxs("div", {
|
|
10021
10208
|
className: "dy-flex dy-items-center dy-gap-2",
|
|
10022
10209
|
children: [
|
|
10210
|
+
previewUrl && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("a", {
|
|
10211
|
+
href: previewUrl,
|
|
10212
|
+
target: "_blank",
|
|
10213
|
+
rel: "noopener noreferrer",
|
|
10214
|
+
className: "dy-text-[11px] dy-text-muted-foreground hover:dy-text-foreground dy-underline-offset-2 hover:dy-underline dy-transition-colors dy-duration-150",
|
|
10215
|
+
children: "View"
|
|
10216
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
10217
|
+
className: "dy-text-muted-foreground/40 dy-text-[11px]",
|
|
10218
|
+
children: "|"
|
|
10219
|
+
})] }),
|
|
10023
10220
|
/* @__PURE__ */ jsx(Link, {
|
|
10024
10221
|
to: `/collections/${slug}/edit/${String(item.id)}`,
|
|
10025
10222
|
className: "dy-text-[11px] dy-text-muted-foreground hover:dy-text-foreground dy-underline-offset-2 hover:dy-underline dy-transition-colors dy-duration-150",
|
|
@@ -10044,6 +10241,22 @@ function CollectionListPage({ slug }) {
|
|
|
10044
10241
|
accessorKey: field.name,
|
|
10045
10242
|
header: field.label || field.name,
|
|
10046
10243
|
cell: ({ row }) => {
|
|
10244
|
+
if (field.name === "url") {
|
|
10245
|
+
if (schema?.admin?.previewUrl) {
|
|
10246
|
+
const resolved = getPreviewUrl(row.original);
|
|
10247
|
+
if (resolved) return /* @__PURE__ */ jsx("a", {
|
|
10248
|
+
href: resolved,
|
|
10249
|
+
target: "_blank",
|
|
10250
|
+
rel: "noopener noreferrer",
|
|
10251
|
+
className: "dy-text-xs dy-text-primary hover:dy-underline dy-underline-offset-2 dy-font-medium",
|
|
10252
|
+
children: resolved
|
|
10253
|
+
});
|
|
10254
|
+
}
|
|
10255
|
+
return /* @__PURE__ */ jsx("span", {
|
|
10256
|
+
className: "dy-text-muted-foreground",
|
|
10257
|
+
children: "-"
|
|
10258
|
+
});
|
|
10259
|
+
}
|
|
10047
10260
|
const cell = /* @__PURE__ */ jsx(RenderCell, {
|
|
10048
10261
|
value: row.getValue(field.name),
|
|
10049
10262
|
field,
|
|
@@ -10238,6 +10451,38 @@ function CollectionListPage({ slug }) {
|
|
|
10238
10451
|
})
|
|
10239
10452
|
]
|
|
10240
10453
|
});
|
|
10454
|
+
if (isImportOpen && schema) {
|
|
10455
|
+
const collectionTitle = schema.labels?.plural || schema.slug;
|
|
10456
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
10457
|
+
className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
|
|
10458
|
+
children: [
|
|
10459
|
+
/* @__PURE__ */ jsx("div", {
|
|
10460
|
+
className: "dy-flex dy-items-center dy-gap-3",
|
|
10461
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
10462
|
+
variant: "ghost",
|
|
10463
|
+
size: "sm",
|
|
10464
|
+
className: "dy-h-8 dy-px-2 dy-gap-1.5 dy-text-xs dy-text-muted-foreground hover:dy-text-foreground",
|
|
10465
|
+
onClick: () => setIsImportOpen(false),
|
|
10466
|
+
children: [
|
|
10467
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "dy-h-3.5 dy-w-3.5" }),
|
|
10468
|
+
"Back to ",
|
|
10469
|
+
collectionTitle
|
|
10470
|
+
]
|
|
10471
|
+
})
|
|
10472
|
+
}),
|
|
10473
|
+
/* @__PURE__ */ jsx(PageHeader, {
|
|
10474
|
+
title: `Import CSV — ${collectionTitle}`,
|
|
10475
|
+
description: `Upload a CSV file to bulk-import records into the ${collectionTitle} collection.`,
|
|
10476
|
+
icon: FileUp
|
|
10477
|
+
}),
|
|
10478
|
+
/* @__PURE__ */ jsx(CsvImporter, {
|
|
10479
|
+
slug,
|
|
10480
|
+
schema,
|
|
10481
|
+
onClose: () => setIsImportOpen(false)
|
|
10482
|
+
})
|
|
10483
|
+
]
|
|
10484
|
+
});
|
|
10485
|
+
}
|
|
10241
10486
|
return /* @__PURE__ */ jsxs("div", {
|
|
10242
10487
|
className: "dy-space-y-6 dy-animate-in lg:dy-space-y-8",
|
|
10243
10488
|
children: [
|
|
@@ -10511,12 +10756,6 @@ function CollectionListPage({ slug }) {
|
|
|
10511
10756
|
componentProps: collectionComponentProps
|
|
10512
10757
|
})
|
|
10513
10758
|
]
|
|
10514
|
-
}),
|
|
10515
|
-
/* @__PURE__ */ jsx(CsvImporterDialog, {
|
|
10516
|
-
open: isImportOpen,
|
|
10517
|
-
onOpenChange: setIsImportOpen,
|
|
10518
|
-
slug,
|
|
10519
|
-
schema
|
|
10520
10759
|
})
|
|
10521
10760
|
]
|
|
10522
10761
|
});
|
|
@@ -12601,9 +12840,8 @@ function GlobalEditorPage() {
|
|
|
12601
12840
|
});
|
|
12602
12841
|
}
|
|
12603
12842
|
//#endregion
|
|
12604
|
-
//#region src/pages/setup/
|
|
12843
|
+
//#region src/pages/setup/utils.ts
|
|
12605
12844
|
var GUIDE_URL = "https://www.dyrected.com/guide";
|
|
12606
|
-
var DOCS_URL = "https://docs.dyrected.com";
|
|
12607
12845
|
function normalizeTechStack(techStack) {
|
|
12608
12846
|
if (!techStack) return void 0;
|
|
12609
12847
|
if (techStack === "next") return "nextjs";
|
|
@@ -12619,154 +12857,209 @@ function buildGuideUrl(config) {
|
|
|
12619
12857
|
if (config.baseUrl) url.searchParams.set("endpoint", config.baseUrl);
|
|
12620
12858
|
return url.toString();
|
|
12621
12859
|
}
|
|
12860
|
+
function buildPrompt(config) {
|
|
12861
|
+
const { siteId, apiKey, baseUrl } = config;
|
|
12862
|
+
if (!(siteId && apiKey && baseUrl)) return GENERATE_CMS_PROMPT;
|
|
12863
|
+
const placeholder = `Ask me for the following in one message:
|
|
12864
|
+
|
|
12865
|
+
- Site ID
|
|
12866
|
+
- Site API key
|
|
12867
|
+
- Base URL
|
|
12868
|
+
|
|
12869
|
+
Wait for my reply.`;
|
|
12870
|
+
const replacement = `Use the following credentials:
|
|
12871
|
+
|
|
12872
|
+
- Site ID: ${siteId}
|
|
12873
|
+
- Site API key: ${apiKey}
|
|
12874
|
+
- Base URL: ${baseUrl}`;
|
|
12875
|
+
return GENERATE_CMS_PROMPT.replace(placeholder, replacement);
|
|
12876
|
+
}
|
|
12877
|
+
//#endregion
|
|
12878
|
+
//#region src/pages/setup/setup-prompt.tsx
|
|
12879
|
+
var DOCS_URL = "https://docs.dyrected.com";
|
|
12880
|
+
var steps = [
|
|
12881
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12882
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12883
|
+
"Your Dyrected credentials are already in the prompt. Give them to the AI when it asks at Stage 4.",
|
|
12884
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12885
|
+
];
|
|
12886
|
+
var stepsNoCredentials = [
|
|
12887
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12888
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12889
|
+
"When the AI reaches Stage 4, it will ask for your Site ID, Site API key, and Base URL.",
|
|
12890
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12891
|
+
];
|
|
12622
12892
|
function SetupPromptUI({ config }) {
|
|
12893
|
+
const [copied, setCopied] = useState(false);
|
|
12623
12894
|
const guideUrl = buildGuideUrl(config);
|
|
12624
|
-
const
|
|
12895
|
+
const hasCredentials = !!(config.siteId && config.apiKey && config.baseUrl);
|
|
12896
|
+
const guideSteps = hasCredentials ? steps : stepsNoCredentials;
|
|
12897
|
+
const promptText = buildPrompt(config);
|
|
12898
|
+
async function copyPrompt() {
|
|
12899
|
+
await navigator.clipboard.writeText(promptText);
|
|
12900
|
+
setCopied(true);
|
|
12901
|
+
window.setTimeout(() => setCopied(false), 1800);
|
|
12902
|
+
}
|
|
12903
|
+
const currentVersion = "2.5.49";
|
|
12904
|
+
const [latestVersion, setLatestVersion] = useState(() => {
|
|
12905
|
+
if (typeof window === "undefined") return null;
|
|
12906
|
+
return localStorage.getItem("dyrected_latest_release");
|
|
12907
|
+
});
|
|
12908
|
+
useEffect(() => {
|
|
12909
|
+
if (!latestVersion) fetch("https://registry.npmjs.org/@dyrected/core/latest").then((r) => r.json()).then((data) => {
|
|
12910
|
+
if (data?.version) {
|
|
12911
|
+
setLatestVersion(data.version);
|
|
12912
|
+
localStorage.setItem("dyrected_latest_release", data.version);
|
|
12913
|
+
localStorage.setItem("dyrected_latest_release_timestamp", String(Date.now()));
|
|
12914
|
+
}
|
|
12915
|
+
}).catch(() => {});
|
|
12916
|
+
}, [latestVersion]);
|
|
12917
|
+
const hasUpdate = latestVersion && latestVersion !== currentVersion && (() => {
|
|
12918
|
+
const lParts = latestVersion.split(".").map(Number);
|
|
12919
|
+
const cParts = currentVersion.split(".").map(Number);
|
|
12920
|
+
for (let i = 0; i < 3; i++) {
|
|
12921
|
+
const l = lParts[i] || 0;
|
|
12922
|
+
const c = cParts[i] || 0;
|
|
12923
|
+
if (l > c) return true;
|
|
12924
|
+
if (l < c) return false;
|
|
12925
|
+
}
|
|
12926
|
+
return false;
|
|
12927
|
+
})();
|
|
12625
12928
|
return /* @__PURE__ */ jsxs("div", {
|
|
12626
|
-
className: "dy-mx-auto dy-max-w-
|
|
12627
|
-
children: [
|
|
12628
|
-
|
|
12629
|
-
|
|
12630
|
-
/* @__PURE__ */ jsx("
|
|
12631
|
-
className: "dy-
|
|
12632
|
-
|
|
12633
|
-
}),
|
|
12634
|
-
|
|
12635
|
-
className: "dy-absolute dy-inset-y-0 dy-right-[12%] dy-w-40 dy-skew-x-[-12deg] dy-bg-card",
|
|
12636
|
-
"aria-hidden": "true"
|
|
12637
|
-
}),
|
|
12638
|
-
/* @__PURE__ */ jsxs("div", {
|
|
12639
|
-
className: "dy-relative dy-grid dy-min-h-[340px] dy-gap-10 dy-p-7 sm:dy-p-10 lg:dy-grid-cols-[1.35fr_0.65fr] lg:dy-p-12",
|
|
12929
|
+
className: "dy-mx-auto dy-max-w-3xl dy-space-y-10 dy-px-4 dy-py-8",
|
|
12930
|
+
children: [
|
|
12931
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12932
|
+
className: "dy-rounded-xl dy-border dy-border-border dy-bg-muted/30 dy-p-5 dy-space-y-3",
|
|
12933
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
12934
|
+
className: "dy-text-sm dy-font-semibold dy-text-foreground",
|
|
12935
|
+
children: "System Info & Updates"
|
|
12936
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
12937
|
+
className: "dy-flex dy-flex-col sm:dy-flex-row sm:dy-items-center dy-justify-between dy-gap-4 dy-text-xs",
|
|
12640
12938
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
12641
|
-
className: "dy-
|
|
12642
|
-
children: [/* @__PURE__ */ jsxs("
|
|
12643
|
-
className: "dy-
|
|
12644
|
-
children: [/* @__PURE__ */ jsxs("
|
|
12645
|
-
className: "dy-
|
|
12646
|
-
children: [
|
|
12647
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12648
|
-
className: "dy-max-w-2xl dy-space-y-4",
|
|
12649
|
-
children: [/* @__PURE__ */ jsx("h1", {
|
|
12650
|
-
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",
|
|
12651
|
-
children: "Let the guide do the heavy lifting."
|
|
12652
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
12653
|
-
className: "dy-max-w-xl dy-text-base dy-leading-7 dy-text-muted-foreground sm:dy-text-lg",
|
|
12654
|
-
children: "Get a guided path tailored to your project, whether you are building with an AI coding tool or wiring up the SDK yourself."
|
|
12655
|
-
})]
|
|
12939
|
+
className: "dy-space-y-1",
|
|
12940
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
12941
|
+
className: "dy-text-muted-foreground",
|
|
12942
|
+
children: ["Current version: ", /* @__PURE__ */ jsxs("span", {
|
|
12943
|
+
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12944
|
+
children: ["v", currentVersion]
|
|
12656
12945
|
})]
|
|
12657
|
-
}), /* @__PURE__ */ jsxs("
|
|
12658
|
-
className: "dy-
|
|
12659
|
-
children: [/* @__PURE__ */
|
|
12660
|
-
|
|
12661
|
-
|
|
12662
|
-
className: "dy-h-12 dy-bg-primary dy-px-6 dy-text-primary-foreground hover:dy-bg-primary/90",
|
|
12663
|
-
children: /* @__PURE__ */ jsxs("a", {
|
|
12664
|
-
href: guideUrl,
|
|
12665
|
-
target: "_blank",
|
|
12666
|
-
rel: "noopener noreferrer",
|
|
12667
|
-
children: [
|
|
12668
|
-
/* @__PURE__ */ jsx(Compass, { className: "dy-h-4 dy-w-4" }),
|
|
12669
|
-
"Open guided setup",
|
|
12670
|
-
/* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-4 dy-w-4" })
|
|
12671
|
-
]
|
|
12672
|
-
})
|
|
12673
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
12674
|
-
asChild: true,
|
|
12675
|
-
size: "lg",
|
|
12676
|
-
variant: "ghost",
|
|
12677
|
-
className: "dy-h-12 dy-text-card-foreground hover:dy-bg-muted hover:dy-text-card-foreground",
|
|
12678
|
-
children: /* @__PURE__ */ jsxs("a", {
|
|
12679
|
-
href: DOCS_URL,
|
|
12680
|
-
target: "_blank",
|
|
12681
|
-
rel: "noopener noreferrer",
|
|
12682
|
-
children: [/* @__PURE__ */ jsx(BookOpen, { className: "dy-h-4 dy-w-4" }), "Browse developer docs"]
|
|
12683
|
-
})
|
|
12946
|
+
}), latestVersion && /* @__PURE__ */ jsxs("p", {
|
|
12947
|
+
className: "dy-text-muted-foreground",
|
|
12948
|
+
children: ["Latest release: ", /* @__PURE__ */ jsxs("span", {
|
|
12949
|
+
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12950
|
+
children: ["v", latestVersion]
|
|
12684
12951
|
})]
|
|
12685
12952
|
})]
|
|
12686
|
-
}), /* @__PURE__ */
|
|
12687
|
-
className: "dy-
|
|
12688
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
12689
|
-
className: "dy-
|
|
12690
|
-
children: [/* @__PURE__ */
|
|
12691
|
-
className: "dy-
|
|
12692
|
-
children:
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12697
|
-
className: "dy-
|
|
12698
|
-
children: [/* @__PURE__ */
|
|
12699
|
-
className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
|
|
12700
|
-
children: [/* @__PURE__ */ jsx("dt", {
|
|
12701
|
-
className: "dy-text-muted-foreground",
|
|
12702
|
-
children: "Tech stack"
|
|
12703
|
-
}), /* @__PURE__ */ jsx("dd", {
|
|
12704
|
-
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12705
|
-
children: stack ?? "Choose in guide"
|
|
12706
|
-
})]
|
|
12707
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12708
|
-
className: "dy-flex dy-items-center dy-justify-between dy-gap-4",
|
|
12709
|
-
children: [/* @__PURE__ */ jsx("dt", {
|
|
12710
|
-
className: "dy-text-muted-foreground",
|
|
12711
|
-
children: "Site"
|
|
12712
|
-
}), /* @__PURE__ */ jsx("dd", {
|
|
12713
|
-
className: "dy-max-w-[180px] dy-truncate dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12714
|
-
children: config.siteId || "Not provided"
|
|
12715
|
-
})]
|
|
12716
|
-
})]
|
|
12953
|
+
}), hasUpdate ? /* @__PURE__ */ jsxs("div", {
|
|
12954
|
+
className: "dy-flex dy-flex-col dy-items-start sm:dy-items-end dy-gap-1.5",
|
|
12955
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
12956
|
+
className: "dy-flex dy-items-center dy-gap-2",
|
|
12957
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
12958
|
+
className: "dy-inline-flex dy-items-center dy-gap-1 dy-rounded-full dy-bg-primary/10 dy-px-2.5 dy-py-0.5 dy-text-[11px] dy-font-medium dy-text-primary",
|
|
12959
|
+
children: "Update available!"
|
|
12960
|
+
}), /* @__PURE__ */ jsxs("a", {
|
|
12961
|
+
href: "https://github.com/Dyrected/dyrected/blob/main/CHANGELOG.md",
|
|
12962
|
+
target: "_blank",
|
|
12963
|
+
rel: "noopener noreferrer",
|
|
12964
|
+
className: "dy-inline-flex dy-items-center dy-gap-1 dy-text-[11px] dy-text-primary dy-underline-offset-4 hover:dy-underline",
|
|
12965
|
+
children: ["View changelog", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3 dy-w-3" })]
|
|
12717
12966
|
})]
|
|
12718
|
-
})
|
|
12967
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
12968
|
+
className: "dy-text-muted-foreground",
|
|
12969
|
+
children: [
|
|
12970
|
+
"Run ",
|
|
12971
|
+
/* @__PURE__ */ jsx("code", {
|
|
12972
|
+
className: "dy-bg-black/5 dark:dy-bg-white/5 dy-px-1 dy-py-0.5 dy-rounded dy-font-mono",
|
|
12973
|
+
children: "npx dyrected upgrade"
|
|
12974
|
+
}),
|
|
12975
|
+
" to update."
|
|
12976
|
+
]
|
|
12977
|
+
})]
|
|
12978
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
12979
|
+
className: "dy-inline-flex dy-items-center dy-gap-1 dy-rounded-full dy-bg-green-500/10 dy-px-2.5 dy-py-0.5 dy-text-[11px] dy-font-medium dy-text-green-600 dark:dy-text-green-400",
|
|
12980
|
+
children: "Up to date"
|
|
12719
12981
|
})]
|
|
12720
|
-
})
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
|
|
12728
|
-
|
|
12982
|
+
})]
|
|
12983
|
+
}),
|
|
12984
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12985
|
+
className: "dy-space-y-2",
|
|
12986
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
12987
|
+
className: "dy-text-2xl dy-font-semibold dy-tracking-tight dy-text-foreground",
|
|
12988
|
+
children: "Set up Dyrected"
|
|
12989
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
12990
|
+
className: "dy-text-sm dy-leading-6 dy-text-muted-foreground",
|
|
12991
|
+
children: "Copy the prompt below and paste it into your AI builder. It handles the setup in stages."
|
|
12992
|
+
})]
|
|
12993
|
+
}),
|
|
12994
|
+
/* @__PURE__ */ jsx("ol", {
|
|
12995
|
+
className: "dy-space-y-3",
|
|
12996
|
+
children: guideSteps.map((step, index) => /* @__PURE__ */ jsxs("li", {
|
|
12997
|
+
className: "dy-flex dy-gap-3 dy-text-sm",
|
|
12998
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
12999
|
+
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",
|
|
13000
|
+
children: index + 1
|
|
13001
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
13002
|
+
className: "dy-leading-6 dy-text-muted-foreground",
|
|
13003
|
+
children: step
|
|
13004
|
+
})]
|
|
13005
|
+
}, index))
|
|
13006
|
+
}),
|
|
13007
|
+
/* @__PURE__ */ jsxs("div", {
|
|
13008
|
+
className: "dy-overflow-hidden dy-rounded-xl dy-border dy-border-border dy-bg-card",
|
|
12729
13009
|
children: [
|
|
12730
|
-
/* @__PURE__ */ jsx("div", {
|
|
12731
|
-
className: "dy-rounded-lg dy-bg-primary/15 dy-p-2.5 dy-text-foreground",
|
|
12732
|
-
children: /* @__PURE__ */ jsx(Sparkles, { className: "dy-h-5 dy-w-5" })
|
|
12733
|
-
}),
|
|
12734
13010
|
/* @__PURE__ */ jsxs("div", {
|
|
12735
|
-
className: "dy-
|
|
12736
|
-
children: [/* @__PURE__ */ jsx("
|
|
12737
|
-
className: "dy-font-semibold dy-text-
|
|
12738
|
-
children: "
|
|
12739
|
-
}), /* @__PURE__ */
|
|
12740
|
-
className: "dy-mt-
|
|
12741
|
-
children: "
|
|
13011
|
+
className: "dy-flex dy-items-center dy-justify-between dy-gap-4 dy-border-b dy-border-border dy-px-4 dy-py-3",
|
|
13012
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
13013
|
+
className: "dy-text-xs dy-font-semibold dy-uppercase dy-tracking-[0.12em] dy-text-muted-foreground",
|
|
13014
|
+
children: "Dyrected setup prompt"
|
|
13015
|
+
}), hasCredentials && /* @__PURE__ */ jsxs("p", {
|
|
13016
|
+
className: "dy-mt-0.5 dy-text-xs dy-text-muted-foreground",
|
|
13017
|
+
children: ["Credentials pre-filled for ", config.siteName || config.siteId]
|
|
13018
|
+
})] }), /* @__PURE__ */ jsxs("button", {
|
|
13019
|
+
type: "button",
|
|
13020
|
+
onClick: copyPrompt,
|
|
13021
|
+
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",
|
|
13022
|
+
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"]
|
|
12742
13023
|
})]
|
|
12743
13024
|
}),
|
|
12744
|
-
/* @__PURE__ */ jsx(
|
|
13025
|
+
/* @__PURE__ */ jsx("pre", {
|
|
13026
|
+
className: "dy-max-h-64 dy-overflow-y-auto dy-p-4 dy-text-[11px] dy-leading-5 dy-text-muted-foreground",
|
|
13027
|
+
children: /* @__PURE__ */ jsx("code", { children: promptText })
|
|
13028
|
+
}),
|
|
13029
|
+
/* @__PURE__ */ jsx("div", {
|
|
13030
|
+
className: "dy-border-t dy-border-border dy-px-4 dy-py-3",
|
|
13031
|
+
children: /* @__PURE__ */ jsxs("p", {
|
|
13032
|
+
className: "dy-text-xs dy-text-muted-foreground",
|
|
13033
|
+
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."]
|
|
13034
|
+
})
|
|
13035
|
+
})
|
|
12745
13036
|
]
|
|
12746
|
-
}),
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
rel: "noopener noreferrer",
|
|
12750
|
-
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",
|
|
13037
|
+
}),
|
|
13038
|
+
/* @__PURE__ */ jsxs("div", {
|
|
13039
|
+
className: "dy-flex dy-flex-col dy-gap-2 sm:dy-flex-row",
|
|
12751
13040
|
children: [
|
|
12752
|
-
/* @__PURE__ */
|
|
12753
|
-
|
|
12754
|
-
|
|
13041
|
+
/* @__PURE__ */ jsxs("a", {
|
|
13042
|
+
href: guideUrl,
|
|
13043
|
+
target: "_blank",
|
|
13044
|
+
rel: "noopener noreferrer",
|
|
13045
|
+
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",
|
|
13046
|
+
children: ["Full guide", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
|
|
12755
13047
|
}),
|
|
12756
|
-
/* @__PURE__ */
|
|
12757
|
-
className: "dy-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
children: "Need implementation detail?"
|
|
12761
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
12762
|
-
className: "dy-mt-1 dy-text-sm dy-leading-6 dy-text-muted-foreground",
|
|
12763
|
-
children: "Use the docs for SDK APIs, framework integrations, configuration, and production reference."
|
|
12764
|
-
})]
|
|
13048
|
+
/* @__PURE__ */ jsx("span", {
|
|
13049
|
+
className: "dy-hidden dy-text-muted-foreground sm:dy-inline",
|
|
13050
|
+
"aria-hidden": "true",
|
|
13051
|
+
children: "·"
|
|
12765
13052
|
}),
|
|
12766
|
-
/* @__PURE__ */
|
|
13053
|
+
/* @__PURE__ */ jsxs("a", {
|
|
13054
|
+
href: DOCS_URL,
|
|
13055
|
+
target: "_blank",
|
|
13056
|
+
rel: "noopener noreferrer",
|
|
13057
|
+
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",
|
|
13058
|
+
children: ["Developer docs", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3.5 dy-w-3.5" })]
|
|
13059
|
+
})
|
|
12767
13060
|
]
|
|
12768
|
-
})
|
|
12769
|
-
|
|
13061
|
+
})
|
|
13062
|
+
]
|
|
12770
13063
|
});
|
|
12771
13064
|
}
|
|
12772
13065
|
//#endregion
|
|
@@ -13410,8 +13703,7 @@ function buildProviderStartUrl(baseUrl, providerId) {
|
|
|
13410
13703
|
}
|
|
13411
13704
|
function resolveAdminAuthCollection(collections, collectionSlug) {
|
|
13412
13705
|
if (!collections) return void 0;
|
|
13413
|
-
|
|
13414
|
-
return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.auth);
|
|
13706
|
+
return collections.find((collection) => collection.slug === "__admins") ?? collections.find((collection) => collection.slug === collectionSlug) ?? collections.find((collection) => collection.auth);
|
|
13415
13707
|
}
|
|
13416
13708
|
function readToken(value) {
|
|
13417
13709
|
if (!value || typeof value !== "object" || !("token" in value)) return null;
|