@dyrected/admin 2.5.48 → 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 +27 -0
- package/dist/index.mjs +459 -241
- package/dist/pages/setup/setup-prompt.d.ts +0 -1
- package/dist/pages/setup/utils.d.ts +4 -0
- package/package.json +4 -4
package/dist/admin.css
CHANGED
|
@@ -2901,6 +2901,10 @@
|
|
|
2901
2901
|
background-color: rgb(0 0 0 / 0.4);
|
|
2902
2902
|
}
|
|
2903
2903
|
|
|
2904
|
+
.dy-bg-black\/5{
|
|
2905
|
+
background-color: rgb(0 0 0 / 0.05);
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2904
2908
|
.dy-bg-black\/60{
|
|
2905
2909
|
background-color: rgb(0 0 0 / 0.6);
|
|
2906
2910
|
}
|
|
@@ -2983,6 +2987,10 @@
|
|
|
2983
2987
|
background-color: rgb(16 185 129 / 0.1);
|
|
2984
2988
|
}
|
|
2985
2989
|
|
|
2990
|
+
.dy-bg-green-500\/10{
|
|
2991
|
+
background-color: rgb(34 197 94 / 0.1);
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2986
2994
|
.dy-bg-muted{
|
|
2987
2995
|
background-color: hsl(var(--muted));
|
|
2988
2996
|
}
|
|
@@ -3185,6 +3193,11 @@
|
|
|
3185
3193
|
padding: 1px;
|
|
3186
3194
|
}
|
|
3187
3195
|
|
|
3196
|
+
.dy-px-0{
|
|
3197
|
+
padding-left: 0px;
|
|
3198
|
+
padding-right: 0px;
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3188
3201
|
.dy-px-1{
|
|
3189
3202
|
padding-left: 0.25rem;
|
|
3190
3203
|
padding-right: 0.25rem;
|
|
@@ -3684,6 +3697,11 @@
|
|
|
3684
3697
|
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
|
|
3685
3698
|
}
|
|
3686
3699
|
|
|
3700
|
+
.dy-text-green-600{
|
|
3701
|
+
--tw-text-opacity: 1;
|
|
3702
|
+
color: rgb(22 163 74 / var(--tw-text-opacity, 1));
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3687
3705
|
.dy-text-muted-foreground{
|
|
3688
3706
|
color: hsl(var(--muted-foreground));
|
|
3689
3707
|
}
|
|
@@ -5474,6 +5492,10 @@
|
|
|
5474
5492
|
padding: 0px !important;
|
|
5475
5493
|
}
|
|
5476
5494
|
|
|
5495
|
+
.dark\:dy-bg-white\/5:is(.dy-dark *){
|
|
5496
|
+
background-color: rgb(255 255 255 / 0.05);
|
|
5497
|
+
}
|
|
5498
|
+
|
|
5477
5499
|
.dark\:dy-text-amber-400:is(.dy-dark *){
|
|
5478
5500
|
--tw-text-opacity: 1;
|
|
5479
5501
|
color: rgb(251 191 36 / var(--tw-text-opacity, 1));
|
|
@@ -5489,6 +5511,11 @@
|
|
|
5489
5511
|
color: rgb(52 211 153 / var(--tw-text-opacity, 1));
|
|
5490
5512
|
}
|
|
5491
5513
|
|
|
5514
|
+
.dark\:dy-text-green-400:is(.dy-dark *){
|
|
5515
|
+
--tw-text-opacity: 1;
|
|
5516
|
+
color: rgb(74 222 128 / var(--tw-text-opacity, 1));
|
|
5517
|
+
}
|
|
5518
|
+
|
|
5492
5519
|
.dark\:dy-text-purple-400:is(.dy-dark *){
|
|
5493
5520
|
--tw-text-opacity: 1;
|
|
5494
5521
|
color: rgb(192 132 252 / var(--tw-text-opacity, 1));
|
package/dist/index.mjs
CHANGED
|
@@ -586,7 +586,7 @@ function NavGroup({ label, children, collapsed, defaultExpanded = true }) {
|
|
|
586
586
|
})]
|
|
587
587
|
});
|
|
588
588
|
}
|
|
589
|
-
function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
589
|
+
function ThemeSelector({ collapsed = false, mobile = false, iconOnly = false }) {
|
|
590
590
|
const { resolvedTheme, setTheme, theme } = useAdminTheme();
|
|
591
591
|
const Icon = resolvedTheme === "dark" ? Moon : Sun;
|
|
592
592
|
const options = [
|
|
@@ -611,11 +611,11 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
611
611
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
612
612
|
type: "button",
|
|
613
613
|
variant: "ghost",
|
|
614
|
-
size: mobile || collapsed ? "icon" : "sm",
|
|
615
|
-
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]"),
|
|
616
616
|
title: "Theme",
|
|
617
617
|
"aria-label": "Change admin theme",
|
|
618
|
-
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" })]
|
|
619
619
|
})
|
|
620
620
|
}), /* @__PURE__ */ jsxs(DropdownMenuContent, {
|
|
621
621
|
side: collapsed || mobile ? "bottom" : "top",
|
|
@@ -643,16 +643,16 @@ function ThemeSelector({ collapsed = false, mobile = false }) {
|
|
|
643
643
|
]
|
|
644
644
|
})] });
|
|
645
645
|
}
|
|
646
|
-
function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collapsed, onToggleCollapse, onNavigate }) {
|
|
646
|
+
function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collapsed, onToggleCollapse, onNavigate, updateInfo }) {
|
|
647
647
|
const { client, user } = useDyrected();
|
|
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_")) ?? [];
|
|
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_")) ?? [];
|
|
650
650
|
const uploadCollections = collections.filter((c) => c.upload);
|
|
651
651
|
const groupLabel = (text) => !collapsed ? /* @__PURE__ */ jsx("p", {
|
|
652
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",
|
|
653
653
|
children: text
|
|
654
654
|
}) : /* @__PURE__ */ jsx("div", { className: "dy-my-2 dy-mx-3 dy-h-px dy-bg-border" });
|
|
655
|
-
const branding = schemas?.admin?.branding;
|
|
655
|
+
const branding = (schemas?.admin)?.branding;
|
|
656
656
|
return /* @__PURE__ */ jsxs("div", {
|
|
657
657
|
className: "dy-flex dy-flex-col dy-min-h-screen",
|
|
658
658
|
children: [
|
|
@@ -783,12 +783,17 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
783
783
|
/* @__PURE__ */ jsx(NavItem, {
|
|
784
784
|
to: "/setup",
|
|
785
785
|
icon: Sparkles,
|
|
786
|
-
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
|
+
}),
|
|
787
793
|
active: location.pathname === "/setup",
|
|
788
794
|
collapsed,
|
|
789
795
|
onClick: onNavigate
|
|
790
796
|
}),
|
|
791
|
-
/* @__PURE__ */ jsx(ThemeSelector, { collapsed }),
|
|
792
797
|
!isEmbedded && user && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
793
798
|
asChild: true,
|
|
794
799
|
children: /* @__PURE__ */ jsxs("button", {
|
|
@@ -834,26 +839,99 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
834
839
|
})
|
|
835
840
|
]
|
|
836
841
|
})] }),
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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
|
+
})]
|
|
843
857
|
})
|
|
844
858
|
]
|
|
845
859
|
})
|
|
846
860
|
]
|
|
847
861
|
});
|
|
848
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
|
+
}
|
|
849
921
|
function AdminShell({ children, isEmbedded = false }) {
|
|
850
922
|
const { client, logout, user } = useDyrected();
|
|
851
923
|
const location = useLocation();
|
|
924
|
+
const updateInfo = useUpdateCheck();
|
|
852
925
|
const [collapsed, setCollapsed] = useState(false);
|
|
853
926
|
const [mobileOpen, setMobileOpen] = useState(false);
|
|
854
927
|
useEffect(() => {
|
|
855
|
-
|
|
856
|
-
|
|
928
|
+
if (mobileOpen) {
|
|
929
|
+
const timer = setTimeout(() => {
|
|
930
|
+
setMobileOpen(false);
|
|
931
|
+
}, 0);
|
|
932
|
+
return () => clearTimeout(timer);
|
|
933
|
+
}
|
|
934
|
+
}, [location.pathname, mobileOpen]);
|
|
857
935
|
useEffect(() => {
|
|
858
936
|
document.body.style.overflow = mobileOpen ? "hidden" : "";
|
|
859
937
|
return () => {
|
|
@@ -868,7 +946,7 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
868
946
|
},
|
|
869
947
|
enabled: !!client
|
|
870
948
|
});
|
|
871
|
-
const mobileBranding = schemas?.admin?.branding;
|
|
949
|
+
const mobileBranding = (schemas?.admin)?.branding;
|
|
872
950
|
return /* @__PURE__ */ jsx(BrandingProvider, { children: /* @__PURE__ */ jsxs("div", {
|
|
873
951
|
className: cn("dy-flex dy-w-full dy-relative", isEmbedded ? "dy-h-full dy-min-h-[600px]" : "dy-min-h-screen"),
|
|
874
952
|
children: [
|
|
@@ -881,7 +959,8 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
881
959
|
logout,
|
|
882
960
|
isEmbedded,
|
|
883
961
|
collapsed,
|
|
884
|
-
onToggleCollapse: () => setCollapsed((v) => !v)
|
|
962
|
+
onToggleCollapse: () => setCollapsed((v) => !v),
|
|
963
|
+
updateInfo
|
|
885
964
|
})
|
|
886
965
|
}),
|
|
887
966
|
mobileOpen && /* @__PURE__ */ jsx("div", {
|
|
@@ -901,7 +980,8 @@ function AdminShell({ children, isEmbedded = false }) {
|
|
|
901
980
|
logout,
|
|
902
981
|
isEmbedded,
|
|
903
982
|
collapsed: false,
|
|
904
|
-
onNavigate: () => setMobileOpen(false)
|
|
983
|
+
onNavigate: () => setMobileOpen(false),
|
|
984
|
+
updateInfo
|
|
905
985
|
})]
|
|
906
986
|
}),
|
|
907
987
|
/* @__PURE__ */ jsxs("main", {
|
|
@@ -1029,6 +1109,31 @@ function getStatusLabel(doc) {
|
|
|
1029
1109
|
}
|
|
1030
1110
|
function Dashboard() {
|
|
1031
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
|
+
})();
|
|
1032
1137
|
const { data: schemas, isLoading: isLoadingSchemas } = useQuery({
|
|
1033
1138
|
queryKey: ["schemas"],
|
|
1034
1139
|
queryFn: () => client.getSchemas(),
|
|
@@ -1065,6 +1170,12 @@ function Dashboard() {
|
|
|
1065
1170
|
return (b.updatedAt ? new Date(b.updatedAt).getTime() : 0) - aTime;
|
|
1066
1171
|
}).slice(0, 6);
|
|
1067
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
|
+
}] : [],
|
|
1068
1179
|
...collections.filter((collection) => !collection.upload && !collection.admin?.useAsTitle).map((collection) => ({
|
|
1069
1180
|
key: `title-${collection.slug}`,
|
|
1070
1181
|
title: `${getCollectionLabel(collection)} needs a title field`,
|
|
@@ -6690,244 +6801,228 @@ function UrlField({ schema: _schema, field, disabled, context: _context }) {
|
|
|
6690
6801
|
const [docsLoading, setDocsLoading] = React$1.useState(false);
|
|
6691
6802
|
const parseValue = (val) => {
|
|
6692
6803
|
if (!val) return {
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
type: "custom",
|
|
6696
|
-
url: "",
|
|
6697
|
-
label: ""
|
|
6698
|
-
}
|
|
6804
|
+
type: "custom",
|
|
6805
|
+
url: ""
|
|
6699
6806
|
};
|
|
6700
6807
|
if (typeof val === "string") return {
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
type: "custom",
|
|
6704
|
-
url: val,
|
|
6705
|
-
label: ""
|
|
6706
|
-
}
|
|
6808
|
+
type: "custom",
|
|
6809
|
+
url: val
|
|
6707
6810
|
};
|
|
6708
|
-
if (typeof val === "object"
|
|
6709
|
-
|
|
6710
|
-
|
|
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
|
|
6711
6817
|
};
|
|
6712
6818
|
return {
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
type: "custom",
|
|
6716
|
-
url: String(val),
|
|
6717
|
-
label: ""
|
|
6718
|
-
}
|
|
6819
|
+
type: "custom",
|
|
6820
|
+
url: String(val)
|
|
6719
6821
|
};
|
|
6720
6822
|
};
|
|
6721
|
-
const
|
|
6722
|
-
const [
|
|
6723
|
-
const [urlValue, setUrlValue] = React$1.useState(currentData.url || "");
|
|
6823
|
+
const currentData = parseValue(field.value);
|
|
6824
|
+
const [urlValue, setUrlValue] = React$1.useState(currentData.url);
|
|
6724
6825
|
const [labelValue, setLabelValue] = React$1.useState(currentData.label || "");
|
|
6725
6826
|
const [collectionValue, setCollectionValue] = React$1.useState(currentData.relationTo || "");
|
|
6726
6827
|
const [docValue, setDocValue] = React$1.useState(currentData.value || "");
|
|
6727
|
-
const
|
|
6728
|
-
const [docSearch, setDocSearch] = React$1.useState("");
|
|
6729
|
-
const collections = schemas?.collections || [];
|
|
6828
|
+
const collections = React$1.useMemo(() => schemas?.collections || [], [schemas?.collections]);
|
|
6730
6829
|
React$1.useEffect(() => {
|
|
6731
|
-
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;
|
|
6732
6836
|
setDocsLoading(true);
|
|
6733
6837
|
setDocuments([]);
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
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;
|
|
6750
6863
|
};
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
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
|
|
6757
6877
|
};
|
|
6758
6878
|
field.onChange(newValue);
|
|
6759
6879
|
};
|
|
6760
|
-
const
|
|
6761
|
-
setMode(newMode);
|
|
6762
|
-
if (newMode === "external") {
|
|
6763
|
-
setUrlValue(currentData.url || "");
|
|
6764
|
-
setLabelValue(currentData.label || "");
|
|
6765
|
-
setResolvedUrlValue("");
|
|
6766
|
-
} else {
|
|
6767
|
-
setCollectionValue(currentData.relationTo || "");
|
|
6768
|
-
setDocValue(currentData.value || "");
|
|
6769
|
-
setResolvedUrlValue(currentData.type === "internal" ? currentData.url || "" : "");
|
|
6770
|
-
setLabelValue(currentData.label || "");
|
|
6771
|
-
}
|
|
6772
|
-
};
|
|
6773
|
-
const handleExternalUrlChange = (value) => {
|
|
6880
|
+
const handleUrlInputChange = (value) => {
|
|
6774
6881
|
setUrlValue(value);
|
|
6775
|
-
|
|
6882
|
+
setCollectionValue("");
|
|
6883
|
+
setDocValue("");
|
|
6884
|
+
handleUpdate(value, labelValue);
|
|
6776
6885
|
};
|
|
6777
|
-
const
|
|
6886
|
+
const handleLabelInputChange = (value) => {
|
|
6778
6887
|
setLabelValue(value);
|
|
6779
|
-
handleUpdate(
|
|
6780
|
-
};
|
|
6781
|
-
const handleCollectionChange = (value) => {
|
|
6782
|
-
setCollectionValue(value);
|
|
6783
|
-
setDocValue("");
|
|
6784
|
-
setResolvedUrlValue("");
|
|
6888
|
+
handleUpdate(urlValue, value, collectionValue, docValue);
|
|
6785
6889
|
};
|
|
6786
|
-
const handleDocumentSelect = (
|
|
6787
|
-
setDocValue(
|
|
6890
|
+
const handleDocumentSelect = (doc) => {
|
|
6891
|
+
setDocValue(doc.id);
|
|
6892
|
+
setCollectionValue(doc.__collectionSlug);
|
|
6788
6893
|
setOpenPopover(false);
|
|
6789
|
-
const urlPattern =
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
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);
|
|
6801
6914
|
};
|
|
6802
|
-
const getCollectionDisplayField = (collectionSlug) => {
|
|
6915
|
+
const getCollectionDisplayField = React$1.useCallback((collectionSlug) => {
|
|
6803
6916
|
return collections.find((c) => c.slug === collectionSlug)?.admin?.useAsTitle || "title";
|
|
6804
|
-
};
|
|
6805
|
-
const getDocumentDisplay = (doc, collectionSlug) => {
|
|
6917
|
+
}, [collections]);
|
|
6918
|
+
const getDocumentDisplay = React$1.useCallback((doc, collectionSlug) => {
|
|
6806
6919
|
return doc[getCollectionDisplayField(collectionSlug)] || doc.name || doc.slug || doc.id;
|
|
6807
|
-
};
|
|
6808
|
-
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);
|
|
6809
6935
|
const selectedCollectionLabel = collections.find((c) => c.slug === collectionValue)?.labels?.singular || collectionValue;
|
|
6810
|
-
return /* @__PURE__ */
|
|
6936
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6811
6937
|
className: "dy-space-y-3",
|
|
6812
|
-
children: /* @__PURE__ */ jsxs(
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
children: [
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
disabled,
|
|
6821
|
-
className: "dy-rounded-md",
|
|
6822
|
-
children: "Internal Link"
|
|
6823
|
-
}), /* @__PURE__ */ jsx(TabsTrigger, {
|
|
6824
|
-
value: "external",
|
|
6825
|
-
disabled,
|
|
6826
|
-
className: "dy-rounded-md",
|
|
6827
|
-
children: "External Link"
|
|
6828
|
-
})]
|
|
6829
|
-
}),
|
|
6830
|
-
/* @__PURE__ */ jsxs(TabsContent, {
|
|
6831
|
-
value: "external",
|
|
6832
|
-
className: "dy-space-y-3 dy-mt-3",
|
|
6833
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
6834
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6835
|
-
children: "URL"
|
|
6836
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
6837
|
-
type: "url",
|
|
6838
|
-
value: urlValue,
|
|
6839
|
-
onChange: (e) => handleExternalUrlChange(e.target.value),
|
|
6840
|
-
placeholder: "https://example.com",
|
|
6841
|
-
disabled,
|
|
6842
|
-
className: "dy-border-border/50"
|
|
6843
|
-
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
6844
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6845
|
-
children: "Link Label (Optional)"
|
|
6846
|
-
}), /* @__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, {
|
|
6847
6946
|
type: "text",
|
|
6848
|
-
value:
|
|
6849
|
-
onChange: (e) =>
|
|
6850
|
-
|
|
6947
|
+
value: urlValue,
|
|
6948
|
+
onChange: (e) => handleUrlInputChange(e.target.value),
|
|
6949
|
+
onFocus: () => setOpenPopover(true),
|
|
6950
|
+
placeholder: "Type or paste a URL, or search pages...",
|
|
6851
6951
|
disabled,
|
|
6852
|
-
className: "dy-border-border/50"
|
|
6853
|
-
})
|
|
6854
|
-
})
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
value:
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6880
|
-
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
6885
|
-
|
|
6886
|
-
|
|
6887
|
-
|
|
6888
|
-
|
|
6889
|
-
|
|
6890
|
-
|
|
6891
|
-
|
|
6892
|
-
|
|
6893
|
-
|
|
6894
|
-
|
|
6895
|
-
|
|
6896
|
-
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
6897
|
-
className: "dy-w-full dy-p-0",
|
|
6898
|
-
align: "start",
|
|
6899
|
-
children: /* @__PURE__ */ jsxs(Command$1, { children: [/* @__PURE__ */ jsx(CommandInput, {
|
|
6900
|
-
placeholder: `Search ${selectedCollectionLabel}...`,
|
|
6901
|
-
value: docSearch,
|
|
6902
|
-
onValueChange: setDocSearch
|
|
6903
|
-
}), /* @__PURE__ */ jsxs(CommandList, { children: [/* @__PURE__ */ jsx(CommandEmpty, { children: docsLoading ? "Searching..." : "No documents found." }), /* @__PURE__ */ jsx(CommandGroup, { children: documents.filter((doc) => {
|
|
6904
|
-
if (!docSearch) return true;
|
|
6905
|
-
return getDocumentDisplay(doc, collectionValue).toLowerCase().includes(docSearch.toLowerCase());
|
|
6906
|
-
}).map((doc) => /* @__PURE__ */ jsxs(CommandItem, {
|
|
6907
|
-
value: doc.id,
|
|
6908
|
-
onSelect: () => handleDocumentSelect(doc.id),
|
|
6909
|
-
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", {
|
|
6910
6996
|
className: "dy-flex-1",
|
|
6911
|
-
children: getDocumentDisplay(doc,
|
|
6997
|
+
children: getDocumentDisplay(doc, doc.__collectionSlug)
|
|
6912
6998
|
})]
|
|
6913
|
-
}, doc.id
|
|
6914
|
-
})
|
|
6915
|
-
})
|
|
6916
|
-
|
|
6917
|
-
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
6918
|
-
children: "Link Label (Optional)"
|
|
6919
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
6920
|
-
type: "text",
|
|
6921
|
-
value: labelValue,
|
|
6922
|
-
onChange: (e) => handleInternalLabelChange(e.target.value),
|
|
6923
|
-
placeholder: "e.g., Read More",
|
|
6924
|
-
disabled,
|
|
6925
|
-
className: "dy-bg-background dy-border-border/50"
|
|
6926
|
-
})] })
|
|
6927
|
-
]
|
|
6999
|
+
}, `${doc.__collectionSlug}-${doc.id}`))
|
|
7000
|
+
}, groupName));
|
|
7001
|
+
})()
|
|
7002
|
+
] })
|
|
6928
7003
|
})
|
|
6929
|
-
]
|
|
6930
|
-
})
|
|
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
|
+
})] })]
|
|
6931
7026
|
});
|
|
6932
7027
|
}
|
|
6933
7028
|
//#endregion
|
|
@@ -10084,8 +10179,25 @@ function CollectionListPage({ slug }) {
|
|
|
10084
10179
|
}
|
|
10085
10180
|
return true;
|
|
10086
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
|
+
};
|
|
10087
10198
|
const renderLinkedCell = (item, cell) => {
|
|
10088
10199
|
const canDelete = canDeleteRow(item);
|
|
10200
|
+
const previewUrl = getPreviewUrl(item);
|
|
10089
10201
|
return /* @__PURE__ */ jsxs("div", {
|
|
10090
10202
|
className: "dy-flex dy-flex-col dy-gap-1",
|
|
10091
10203
|
children: [/* @__PURE__ */ jsx(Link, {
|
|
@@ -10095,6 +10207,16 @@ function CollectionListPage({ slug }) {
|
|
|
10095
10207
|
}), /* @__PURE__ */ jsxs("div", {
|
|
10096
10208
|
className: "dy-flex dy-items-center dy-gap-2",
|
|
10097
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
|
+
})] }),
|
|
10098
10220
|
/* @__PURE__ */ jsx(Link, {
|
|
10099
10221
|
to: `/collections/${slug}/edit/${String(item.id)}`,
|
|
10100
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",
|
|
@@ -10119,6 +10241,22 @@ function CollectionListPage({ slug }) {
|
|
|
10119
10241
|
accessorKey: field.name,
|
|
10120
10242
|
header: field.label || field.name,
|
|
10121
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
|
+
}
|
|
10122
10260
|
const cell = /* @__PURE__ */ jsx(RenderCell, {
|
|
10123
10261
|
value: row.getValue(field.name),
|
|
10124
10262
|
field,
|
|
@@ -12702,21 +12840,8 @@ function GlobalEditorPage() {
|
|
|
12702
12840
|
});
|
|
12703
12841
|
}
|
|
12704
12842
|
//#endregion
|
|
12705
|
-
//#region src/pages/setup/
|
|
12843
|
+
//#region src/pages/setup/utils.ts
|
|
12706
12844
|
var GUIDE_URL = "https://www.dyrected.com/guide";
|
|
12707
|
-
var DOCS_URL = "https://docs.dyrected.com";
|
|
12708
|
-
var steps = [
|
|
12709
|
-
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12710
|
-
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12711
|
-
"Your Dyrected credentials are already in the prompt. Give them to the AI when it asks at Stage 4.",
|
|
12712
|
-
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12713
|
-
];
|
|
12714
|
-
var stepsNoCredentials = [
|
|
12715
|
-
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12716
|
-
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12717
|
-
"When the AI reaches Stage 4, it will ask for your Site ID, Site API key, and Base URL.",
|
|
12718
|
-
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12719
|
-
];
|
|
12720
12845
|
function normalizeTechStack(techStack) {
|
|
12721
12846
|
if (!techStack) return void 0;
|
|
12722
12847
|
if (techStack === "next") return "nextjs";
|
|
@@ -12749,6 +12874,21 @@ Wait for my reply.`;
|
|
|
12749
12874
|
- Base URL: ${baseUrl}`;
|
|
12750
12875
|
return GENERATE_CMS_PROMPT.replace(placeholder, replacement);
|
|
12751
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
|
+
];
|
|
12752
12892
|
function SetupPromptUI({ config }) {
|
|
12753
12893
|
const [copied, setCopied] = useState(false);
|
|
12754
12894
|
const guideUrl = buildGuideUrl(config);
|
|
@@ -12760,9 +12900,87 @@ function SetupPromptUI({ config }) {
|
|
|
12760
12900
|
setCopied(true);
|
|
12761
12901
|
window.setTimeout(() => setCopied(false), 1800);
|
|
12762
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
|
+
})();
|
|
12763
12928
|
return /* @__PURE__ */ jsxs("div", {
|
|
12764
12929
|
className: "dy-mx-auto dy-max-w-3xl dy-space-y-10 dy-px-4 dy-py-8",
|
|
12765
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",
|
|
12938
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
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]
|
|
12945
|
+
})]
|
|
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]
|
|
12951
|
+
})]
|
|
12952
|
+
})]
|
|
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" })]
|
|
12966
|
+
})]
|
|
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"
|
|
12981
|
+
})]
|
|
12982
|
+
})]
|
|
12983
|
+
}),
|
|
12766
12984
|
/* @__PURE__ */ jsxs("div", {
|
|
12767
12985
|
className: "dy-space-y-2",
|
|
12768
12986
|
children: [/* @__PURE__ */ jsx("h1", {
|
|
@@ -10,5 +10,4 @@ export interface SetupPromptConfig {
|
|
|
10
10
|
export interface SetupPromptProps {
|
|
11
11
|
config: SetupPromptConfig;
|
|
12
12
|
}
|
|
13
|
-
export declare function buildGuideUrl(config: SetupPromptConfig): string;
|
|
14
13
|
export declare function SetupPromptUI({ config }: SetupPromptProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { SetupPromptConfig } from './setup-prompt';
|
|
2
|
+
export declare function normalizeTechStack(techStack?: string): string | undefined;
|
|
3
|
+
export declare function buildGuideUrl(config: SetupPromptConfig): string;
|
|
4
|
+
export declare function buildPrompt(config: SetupPromptConfig): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dyrected/admin",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.49",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -64,9 +64,9 @@
|
|
|
64
64
|
"tailwind-merge": "^3.5.0",
|
|
65
65
|
"tailwindcss-animate": "^1.0.7",
|
|
66
66
|
"zod": "^3.25.76",
|
|
67
|
-
"@dyrected/
|
|
68
|
-
"@dyrected/
|
|
69
|
-
"@dyrected/
|
|
67
|
+
"@dyrected/knowledge": "^0.2.7",
|
|
68
|
+
"@dyrected/sdk": "^2.5.49",
|
|
69
|
+
"@dyrected/core": "^2.5.49"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@tanstack/react-query": "^5.0.0",
|