@dyrected/admin 2.5.48 → 2.5.51
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
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));
|
|
@@ -9,5 +9,5 @@ interface UrlFieldProps {
|
|
|
9
9
|
siblingData: any;
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
|
-
export declare function UrlField({
|
|
12
|
+
export declare function UrlField({ field, disabled }: UrlFieldProps): import("react/jsx-runtime").JSX.Element;
|
|
13
13
|
export {};
|
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`,
|
|
@@ -6683,251 +6794,254 @@ function interpolateUrlPattern(pattern, doc) {
|
|
|
6683
6794
|
}
|
|
6684
6795
|
//#endregion
|
|
6685
6796
|
//#region src/components/forms/fields/url-field.tsx
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
label: ""
|
|
6698
|
-
}
|
|
6699
|
-
};
|
|
6700
|
-
if (typeof val === "string") return {
|
|
6701
|
-
mode: "external",
|
|
6702
|
-
data: {
|
|
6703
|
-
type: "custom",
|
|
6704
|
-
url: val,
|
|
6705
|
-
label: ""
|
|
6706
|
-
}
|
|
6707
|
-
};
|
|
6708
|
-
if (typeof val === "object" && val.type) return {
|
|
6709
|
-
mode: val.type === "internal" ? "internal" : "external",
|
|
6710
|
-
data: val
|
|
6797
|
+
var parseValue = (val) => {
|
|
6798
|
+
if (!val) return {
|
|
6799
|
+
type: "custom",
|
|
6800
|
+
url: ""
|
|
6801
|
+
};
|
|
6802
|
+
if (typeof val === "string") {
|
|
6803
|
+
let url = val;
|
|
6804
|
+
if (url.startsWith("/")) url = `${window.location.origin}${url}`;
|
|
6805
|
+
return {
|
|
6806
|
+
type: "custom",
|
|
6807
|
+
url
|
|
6711
6808
|
};
|
|
6809
|
+
}
|
|
6810
|
+
if (typeof val === "object") {
|
|
6811
|
+
let url = val.url || "";
|
|
6812
|
+
if (url.startsWith("/")) url = `${window.location.origin}${url}`;
|
|
6712
6813
|
return {
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
}
|
|
6814
|
+
type: val.type === "internal" ? "internal" : "custom",
|
|
6815
|
+
url,
|
|
6816
|
+
relationTo: val.relationTo,
|
|
6817
|
+
value: val.value,
|
|
6818
|
+
label: val.label
|
|
6719
6819
|
};
|
|
6820
|
+
}
|
|
6821
|
+
return {
|
|
6822
|
+
type: "custom",
|
|
6823
|
+
url: String(val)
|
|
6720
6824
|
};
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
const
|
|
6825
|
+
};
|
|
6826
|
+
function UrlField({ field, disabled }) {
|
|
6827
|
+
const { client, schemas } = useDyrected();
|
|
6828
|
+
const [openPopover, setOpenPopover] = React$1.useState(false);
|
|
6829
|
+
const [documents, setDocuments] = React$1.useState([]);
|
|
6830
|
+
const [docsLoading, setDocsLoading] = React$1.useState(false);
|
|
6831
|
+
const currentData = parseValue(field.value);
|
|
6832
|
+
const [urlValue, setUrlValue] = React$1.useState(currentData.url);
|
|
6724
6833
|
const [labelValue, setLabelValue] = React$1.useState(currentData.label || "");
|
|
6725
6834
|
const [collectionValue, setCollectionValue] = React$1.useState(currentData.relationTo || "");
|
|
6726
6835
|
const [docValue, setDocValue] = React$1.useState(currentData.value || "");
|
|
6727
|
-
const [resolvedUrlValue, setResolvedUrlValue] = React$1.useState(currentMode === "internal" ? currentData.url || "" : "");
|
|
6728
|
-
const [docSearch, setDocSearch] = React$1.useState("");
|
|
6729
|
-
const collections = schemas?.collections || [];
|
|
6730
6836
|
React$1.useEffect(() => {
|
|
6731
|
-
|
|
6837
|
+
const next = parseValue(field.value);
|
|
6838
|
+
Promise.resolve().then(() => {
|
|
6839
|
+
setUrlValue((prev) => prev === next.url ? prev : next.url);
|
|
6840
|
+
setLabelValue((prev) => prev === next.label ? prev : next.label || "");
|
|
6841
|
+
setCollectionValue((prev) => prev === next.relationTo ? prev : next.relationTo || "");
|
|
6842
|
+
setDocValue((prev) => prev === next.value ? prev : next.value || "");
|
|
6843
|
+
});
|
|
6844
|
+
}, [field.value]);
|
|
6845
|
+
const collections = React$1.useMemo(() => schemas?.collections || [], [schemas?.collections]);
|
|
6846
|
+
React$1.useEffect(() => {
|
|
6847
|
+
if (!client || !schemas?.collections) return;
|
|
6848
|
+
const eligibleCollections = collections.filter((c) => c.admin?.previewUrl);
|
|
6849
|
+
if (eligibleCollections.length === 0) return;
|
|
6850
|
+
let active = true;
|
|
6851
|
+
Promise.resolve().then(() => {
|
|
6852
|
+
if (!active) return;
|
|
6732
6853
|
setDocsLoading(true);
|
|
6733
6854
|
setDocuments([]);
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6855
|
+
});
|
|
6856
|
+
Promise.all(eligibleCollections.map((col) => client.collection(col.slug).find({ limit: 50 }).exec().then((res) => ({
|
|
6857
|
+
collection: col,
|
|
6858
|
+
docs: res.docs || []
|
|
6859
|
+
})).catch((err) => {
|
|
6860
|
+
console.error(`Failed to load documents for ${col.slug}:`, err);
|
|
6861
|
+
return {
|
|
6862
|
+
collection: col,
|
|
6863
|
+
docs: []
|
|
6864
|
+
};
|
|
6865
|
+
}))).then((results) => {
|
|
6866
|
+
if (!active) return;
|
|
6867
|
+
setDocuments(results.flatMap((r) => r.docs.map((doc) => ({
|
|
6868
|
+
...doc,
|
|
6869
|
+
__collectionSlug: r.collection.slug,
|
|
6870
|
+
__collectionLabel: r.collection.labels?.plural || r.collection.slug,
|
|
6871
|
+
__previewUrl: r.collection.admin?.previewUrl
|
|
6872
|
+
}))));
|
|
6873
|
+
}).catch((err) => {
|
|
6874
|
+
console.error("Failed to load documents:", err);
|
|
6875
|
+
}).finally(() => {
|
|
6876
|
+
if (active) setDocsLoading(false);
|
|
6877
|
+
});
|
|
6878
|
+
return () => {
|
|
6879
|
+
active = false;
|
|
6750
6880
|
};
|
|
6751
|
-
|
|
6752
|
-
|
|
6753
|
-
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6881
|
+
}, [
|
|
6882
|
+
client,
|
|
6883
|
+
schemas,
|
|
6884
|
+
collections
|
|
6885
|
+
]);
|
|
6886
|
+
const handleUpdate = (url, label, relationTo, docId) => {
|
|
6887
|
+
const isInternal = !!(relationTo && docId);
|
|
6888
|
+
let cleanedUrl = url;
|
|
6889
|
+
if (isInternal && cleanedUrl.startsWith(window.location.origin)) cleanedUrl = cleanedUrl.substring(window.location.origin.length);
|
|
6890
|
+
const newValue = {
|
|
6891
|
+
type: isInternal ? "internal" : "custom",
|
|
6892
|
+
url: cleanedUrl || void 0,
|
|
6893
|
+
relationTo: isInternal ? relationTo : void 0,
|
|
6894
|
+
value: isInternal ? docId : void 0,
|
|
6895
|
+
label: label || void 0
|
|
6757
6896
|
};
|
|
6758
6897
|
field.onChange(newValue);
|
|
6759
6898
|
};
|
|
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) => {
|
|
6899
|
+
const handleUrlInputChange = (value) => {
|
|
6774
6900
|
setUrlValue(value);
|
|
6775
|
-
|
|
6901
|
+
setCollectionValue("");
|
|
6902
|
+
setDocValue("");
|
|
6903
|
+
handleUpdate(value, labelValue);
|
|
6776
6904
|
};
|
|
6777
|
-
const
|
|
6905
|
+
const handleLabelInputChange = (value) => {
|
|
6778
6906
|
setLabelValue(value);
|
|
6779
|
-
handleUpdate(
|
|
6907
|
+
handleUpdate(urlValue, value, collectionValue, docValue);
|
|
6780
6908
|
};
|
|
6781
|
-
const
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
setResolvedUrlValue("");
|
|
6785
|
-
};
|
|
6786
|
-
const handleDocumentSelect = (docId) => {
|
|
6787
|
-
setDocValue(docId);
|
|
6909
|
+
const handleDocumentSelect = (doc) => {
|
|
6910
|
+
setDocValue(doc.id);
|
|
6911
|
+
setCollectionValue(doc.__collectionSlug);
|
|
6788
6912
|
setOpenPopover(false);
|
|
6789
|
-
const urlPattern =
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6913
|
+
const urlPattern = doc.__previewUrl;
|
|
6914
|
+
let resolvedUrl = void 0;
|
|
6915
|
+
if (urlPattern) {
|
|
6916
|
+
if (typeof urlPattern === "function") resolvedUrl = urlPattern(doc, { locale: "en" });
|
|
6917
|
+
else if (typeof urlPattern === "string") if (urlPattern.includes("{{")) resolvedUrl = urlPattern.replace(/{{(.*?)}}/g, (_, key) => String(doc[key.trim()] || ""));
|
|
6918
|
+
else try {
|
|
6919
|
+
const context = {
|
|
6920
|
+
...doc,
|
|
6921
|
+
siteUrl: window.location.origin
|
|
6922
|
+
};
|
|
6923
|
+
if (urlPattern.includes("+") || urlPattern.includes("?") || urlPattern.includes("==") || urlPattern.includes("siteUrl")) resolvedUrl = jexl.evalSync(urlPattern, context);
|
|
6924
|
+
else resolvedUrl = interpolateUrlPattern(urlPattern, doc);
|
|
6925
|
+
} catch {
|
|
6926
|
+
resolvedUrl = interpolateUrlPattern(urlPattern, doc);
|
|
6927
|
+
}
|
|
6928
|
+
}
|
|
6929
|
+
if (typeof resolvedUrl === "string" && resolvedUrl.startsWith("/")) resolvedUrl = `${window.location.origin}${resolvedUrl}`;
|
|
6930
|
+
const finalUrl = resolvedUrl || "";
|
|
6931
|
+
setUrlValue(finalUrl);
|
|
6932
|
+
handleUpdate(finalUrl, labelValue, doc.__collectionSlug, doc.id);
|
|
6801
6933
|
};
|
|
6802
|
-
const getCollectionDisplayField = (collectionSlug) => {
|
|
6934
|
+
const getCollectionDisplayField = React$1.useCallback((collectionSlug) => {
|
|
6803
6935
|
return collections.find((c) => c.slug === collectionSlug)?.admin?.useAsTitle || "title";
|
|
6804
|
-
};
|
|
6805
|
-
const getDocumentDisplay = (doc, collectionSlug) => {
|
|
6936
|
+
}, [collections]);
|
|
6937
|
+
const getDocumentDisplay = React$1.useCallback((doc, collectionSlug) => {
|
|
6806
6938
|
return doc[getCollectionDisplayField(collectionSlug)] || doc.name || doc.slug || doc.id;
|
|
6807
|
-
};
|
|
6808
|
-
const
|
|
6939
|
+
}, [getCollectionDisplayField]);
|
|
6940
|
+
const filteredDocs = React$1.useMemo(() => {
|
|
6941
|
+
if (!urlValue) return documents;
|
|
6942
|
+
const query = urlValue.toLowerCase();
|
|
6943
|
+
return documents.filter((doc) => {
|
|
6944
|
+
const display = getDocumentDisplay(doc, doc.__collectionSlug).toLowerCase();
|
|
6945
|
+
const slug = String(doc.slug || "").toLowerCase();
|
|
6946
|
+
return display.includes(query) || slug.includes(query);
|
|
6947
|
+
});
|
|
6948
|
+
}, [
|
|
6949
|
+
documents,
|
|
6950
|
+
urlValue,
|
|
6951
|
+
getDocumentDisplay
|
|
6952
|
+
]);
|
|
6953
|
+
const selectedDoc = documents.find((d) => d.id === docValue && d.__collectionSlug === collectionValue);
|
|
6809
6954
|
const selectedCollectionLabel = collections.find((c) => c.slug === collectionValue)?.labels?.singular || collectionValue;
|
|
6810
|
-
return /* @__PURE__ */
|
|
6955
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6811
6956
|
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, {
|
|
6957
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(Popover, {
|
|
6958
|
+
open: openPopover && !disabled,
|
|
6959
|
+
onOpenChange: setOpenPopover,
|
|
6960
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
6961
|
+
asChild: true,
|
|
6962
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
6963
|
+
className: "dy-w-full",
|
|
6964
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
6847
6965
|
type: "text",
|
|
6848
|
-
value:
|
|
6849
|
-
onChange: (e) =>
|
|
6850
|
-
|
|
6966
|
+
value: urlValue,
|
|
6967
|
+
onChange: (e) => handleUrlInputChange(e.target.value),
|
|
6968
|
+
onFocus: () => setOpenPopover(true),
|
|
6969
|
+
placeholder: "Type or paste a URL, or search pages...",
|
|
6851
6970
|
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", {
|
|
6971
|
+
className: "dy-bg-background dy-border-border/50 dy-h-11 dy-w-full"
|
|
6972
|
+
})
|
|
6973
|
+
})
|
|
6974
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
6975
|
+
className: "dy-p-0 dy-w-[var(--radix-popover-trigger-width)] dy-max-h-60 dy-overflow-y-auto",
|
|
6976
|
+
align: "start",
|
|
6977
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
6978
|
+
children: /* @__PURE__ */ jsx(Command$1, {
|
|
6979
|
+
className: "dy-border-none",
|
|
6980
|
+
shouldFilter: false,
|
|
6981
|
+
children: /* @__PURE__ */ jsxs(CommandList, { children: [
|
|
6982
|
+
/* @__PURE__ */ jsx(CommandEmpty, {
|
|
6983
|
+
className: "dy-py-2.5 dy-px-3 dy-text-xs dy-text-muted-foreground",
|
|
6984
|
+
children: docsLoading ? "Loading pages..." : "No matching pages found. Press Enter to use as custom link."
|
|
6985
|
+
}),
|
|
6986
|
+
urlValue && /* @__PURE__ */ jsx(CommandGroup, {
|
|
6987
|
+
heading: "Custom Link",
|
|
6988
|
+
children: /* @__PURE__ */ jsxs(CommandItem, {
|
|
6989
|
+
value: `custom-${urlValue}`,
|
|
6990
|
+
onSelect: () => {
|
|
6991
|
+
handleUrlInputChange(urlValue);
|
|
6992
|
+
setOpenPopover(false);
|
|
6993
|
+
},
|
|
6994
|
+
className: "dy-text-primary",
|
|
6995
|
+
children: [
|
|
6996
|
+
"Use link \"",
|
|
6997
|
+
urlValue,
|
|
6998
|
+
"\""
|
|
6999
|
+
]
|
|
7000
|
+
})
|
|
7001
|
+
}),
|
|
7002
|
+
(() => {
|
|
7003
|
+
const grouped = {};
|
|
7004
|
+
filteredDocs.forEach((doc) => {
|
|
7005
|
+
const key = doc.__collectionLabel;
|
|
7006
|
+
if (!grouped[key]) grouped[key] = [];
|
|
7007
|
+
grouped[key].push(doc);
|
|
7008
|
+
});
|
|
7009
|
+
return Object.entries(grouped).map(([groupName, docs]) => /* @__PURE__ */ jsx(CommandGroup, {
|
|
7010
|
+
heading: groupName,
|
|
7011
|
+
children: docs.map((doc) => /* @__PURE__ */ jsxs(CommandItem, {
|
|
7012
|
+
value: `${doc.__collectionSlug}-${doc.id}-${getDocumentDisplay(doc, doc.__collectionSlug)}`,
|
|
7013
|
+
onSelect: () => handleDocumentSelect(doc),
|
|
7014
|
+
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
7015
|
className: "dy-flex-1",
|
|
6911
|
-
children: getDocumentDisplay(doc,
|
|
7016
|
+
children: getDocumentDisplay(doc, doc.__collectionSlug)
|
|
6912
7017
|
})]
|
|
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
|
-
]
|
|
7018
|
+
}, `${doc.__collectionSlug}-${doc.id}`))
|
|
7019
|
+
}, groupName));
|
|
7020
|
+
})()
|
|
7021
|
+
] })
|
|
6928
7022
|
})
|
|
6929
|
-
]
|
|
6930
|
-
})
|
|
7023
|
+
})]
|
|
7024
|
+
}), selectedDoc && /* @__PURE__ */ jsxs("p", {
|
|
7025
|
+
className: "dy-text-[11px] dy-text-muted-foreground dy-mt-1.5",
|
|
7026
|
+
children: ["Linked to internal page: ", /* @__PURE__ */ jsxs("span", {
|
|
7027
|
+
className: "dy-font-medium dy-text-foreground",
|
|
7028
|
+
children: [
|
|
7029
|
+
selectedCollectionLabel,
|
|
7030
|
+
": ",
|
|
7031
|
+
getDocumentDisplay(selectedDoc, collectionValue)
|
|
7032
|
+
]
|
|
7033
|
+
})]
|
|
7034
|
+
})] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
|
|
7035
|
+
className: "dy-text-xs dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wider dy-block dy-mb-2",
|
|
7036
|
+
children: "Link Label (Optional)"
|
|
7037
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
7038
|
+
type: "text",
|
|
7039
|
+
value: labelValue,
|
|
7040
|
+
onChange: (e) => handleLabelInputChange(e.target.value),
|
|
7041
|
+
placeholder: "e.g., Learn More",
|
|
7042
|
+
disabled,
|
|
7043
|
+
className: "dy-bg-background dy-border-border/50"
|
|
7044
|
+
})] })]
|
|
6931
7045
|
});
|
|
6932
7046
|
}
|
|
6933
7047
|
//#endregion
|
|
@@ -10084,8 +10198,25 @@ function CollectionListPage({ slug }) {
|
|
|
10084
10198
|
}
|
|
10085
10199
|
return true;
|
|
10086
10200
|
};
|
|
10201
|
+
const getPreviewUrl = (item) => {
|
|
10202
|
+
if (!schema?.admin?.previewUrl) return null;
|
|
10203
|
+
let previewUrl = typeof schema.admin.previewUrl === "function" ? schema.admin.previewUrl(item, { locale: "en" }) : schema.admin.previewUrl;
|
|
10204
|
+
if (typeof previewUrl === "string" && previewUrl.includes("{{")) previewUrl = previewUrl.replace(/{{(.*?)}}/g, (_, key) => String(item[key.trim()] || ""));
|
|
10205
|
+
else if (typeof previewUrl === "string") try {
|
|
10206
|
+
const context = {
|
|
10207
|
+
...item,
|
|
10208
|
+
siteUrl: window.location.origin
|
|
10209
|
+
};
|
|
10210
|
+
if (previewUrl.includes("+") || previewUrl.includes("?") || previewUrl.includes("==") || previewUrl.includes("siteUrl")) previewUrl = jexl.evalSync(previewUrl, context);
|
|
10211
|
+
} catch (e) {
|
|
10212
|
+
console.warn("Preview URL eval failed:", e);
|
|
10213
|
+
}
|
|
10214
|
+
if (typeof previewUrl === "string" && previewUrl.startsWith("/")) previewUrl = `${window.location.origin}${previewUrl}`;
|
|
10215
|
+
return typeof previewUrl === "string" ? previewUrl : null;
|
|
10216
|
+
};
|
|
10087
10217
|
const renderLinkedCell = (item, cell) => {
|
|
10088
10218
|
const canDelete = canDeleteRow(item);
|
|
10219
|
+
const previewUrl = getPreviewUrl(item);
|
|
10089
10220
|
return /* @__PURE__ */ jsxs("div", {
|
|
10090
10221
|
className: "dy-flex dy-flex-col dy-gap-1",
|
|
10091
10222
|
children: [/* @__PURE__ */ jsx(Link, {
|
|
@@ -10095,6 +10226,16 @@ function CollectionListPage({ slug }) {
|
|
|
10095
10226
|
}), /* @__PURE__ */ jsxs("div", {
|
|
10096
10227
|
className: "dy-flex dy-items-center dy-gap-2",
|
|
10097
10228
|
children: [
|
|
10229
|
+
previewUrl && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("a", {
|
|
10230
|
+
href: previewUrl,
|
|
10231
|
+
target: "_blank",
|
|
10232
|
+
rel: "noopener noreferrer",
|
|
10233
|
+
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",
|
|
10234
|
+
children: "View"
|
|
10235
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
10236
|
+
className: "dy-text-muted-foreground/40 dy-text-[11px]",
|
|
10237
|
+
children: "|"
|
|
10238
|
+
})] }),
|
|
10098
10239
|
/* @__PURE__ */ jsx(Link, {
|
|
10099
10240
|
to: `/collections/${slug}/edit/${String(item.id)}`,
|
|
10100
10241
|
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 +10260,22 @@ function CollectionListPage({ slug }) {
|
|
|
10119
10260
|
accessorKey: field.name,
|
|
10120
10261
|
header: field.label || field.name,
|
|
10121
10262
|
cell: ({ row }) => {
|
|
10263
|
+
if (field.name === "url") {
|
|
10264
|
+
if (schema?.admin?.previewUrl) {
|
|
10265
|
+
const resolved = getPreviewUrl(row.original);
|
|
10266
|
+
if (resolved) return /* @__PURE__ */ jsx("a", {
|
|
10267
|
+
href: resolved,
|
|
10268
|
+
target: "_blank",
|
|
10269
|
+
rel: "noopener noreferrer",
|
|
10270
|
+
className: "dy-text-xs dy-text-primary hover:dy-underline dy-underline-offset-2 dy-font-medium",
|
|
10271
|
+
children: resolved
|
|
10272
|
+
});
|
|
10273
|
+
}
|
|
10274
|
+
return /* @__PURE__ */ jsx("span", {
|
|
10275
|
+
className: "dy-text-muted-foreground",
|
|
10276
|
+
children: "-"
|
|
10277
|
+
});
|
|
10278
|
+
}
|
|
10122
10279
|
const cell = /* @__PURE__ */ jsx(RenderCell, {
|
|
10123
10280
|
value: row.getValue(field.name),
|
|
10124
10281
|
field,
|
|
@@ -12702,21 +12859,8 @@ function GlobalEditorPage() {
|
|
|
12702
12859
|
});
|
|
12703
12860
|
}
|
|
12704
12861
|
//#endregion
|
|
12705
|
-
//#region src/pages/setup/
|
|
12862
|
+
//#region src/pages/setup/utils.ts
|
|
12706
12863
|
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
12864
|
function normalizeTechStack(techStack) {
|
|
12721
12865
|
if (!techStack) return void 0;
|
|
12722
12866
|
if (techStack === "next") return "nextjs";
|
|
@@ -12749,6 +12893,21 @@ Wait for my reply.`;
|
|
|
12749
12893
|
- Base URL: ${baseUrl}`;
|
|
12750
12894
|
return GENERATE_CMS_PROMPT.replace(placeholder, replacement);
|
|
12751
12895
|
}
|
|
12896
|
+
//#endregion
|
|
12897
|
+
//#region src/pages/setup/setup-prompt.tsx
|
|
12898
|
+
var DOCS_URL = "https://docs.dyrected.com";
|
|
12899
|
+
var steps = [
|
|
12900
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12901
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12902
|
+
"Your Dyrected credentials are already in the prompt. Give them to the AI when it asks at Stage 4.",
|
|
12903
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12904
|
+
];
|
|
12905
|
+
var stepsNoCredentials = [
|
|
12906
|
+
"Paste the prompt into your AI builder — the same one that owns the website code.",
|
|
12907
|
+
"Review the content list the AI sends back. Correct anything missing or wrong, then say \"approved\".",
|
|
12908
|
+
"When the AI reaches Stage 4, it will ask for your Site ID, Site API key, and Base URL.",
|
|
12909
|
+
"Test one real edit in Dyrected. If the change appears on the website, invite the client."
|
|
12910
|
+
];
|
|
12752
12911
|
function SetupPromptUI({ config }) {
|
|
12753
12912
|
const [copied, setCopied] = useState(false);
|
|
12754
12913
|
const guideUrl = buildGuideUrl(config);
|
|
@@ -12760,9 +12919,87 @@ function SetupPromptUI({ config }) {
|
|
|
12760
12919
|
setCopied(true);
|
|
12761
12920
|
window.setTimeout(() => setCopied(false), 1800);
|
|
12762
12921
|
}
|
|
12922
|
+
const currentVersion = "2.5.49";
|
|
12923
|
+
const [latestVersion, setLatestVersion] = useState(() => {
|
|
12924
|
+
if (typeof window === "undefined") return null;
|
|
12925
|
+
return localStorage.getItem("dyrected_latest_release");
|
|
12926
|
+
});
|
|
12927
|
+
useEffect(() => {
|
|
12928
|
+
if (!latestVersion) fetch("https://registry.npmjs.org/@dyrected/core/latest").then((r) => r.json()).then((data) => {
|
|
12929
|
+
if (data?.version) {
|
|
12930
|
+
setLatestVersion(data.version);
|
|
12931
|
+
localStorage.setItem("dyrected_latest_release", data.version);
|
|
12932
|
+
localStorage.setItem("dyrected_latest_release_timestamp", String(Date.now()));
|
|
12933
|
+
}
|
|
12934
|
+
}).catch(() => {});
|
|
12935
|
+
}, [latestVersion]);
|
|
12936
|
+
const hasUpdate = latestVersion && latestVersion !== currentVersion && (() => {
|
|
12937
|
+
const lParts = latestVersion.split(".").map(Number);
|
|
12938
|
+
const cParts = currentVersion.split(".").map(Number);
|
|
12939
|
+
for (let i = 0; i < 3; i++) {
|
|
12940
|
+
const l = lParts[i] || 0;
|
|
12941
|
+
const c = cParts[i] || 0;
|
|
12942
|
+
if (l > c) return true;
|
|
12943
|
+
if (l < c) return false;
|
|
12944
|
+
}
|
|
12945
|
+
return false;
|
|
12946
|
+
})();
|
|
12763
12947
|
return /* @__PURE__ */ jsxs("div", {
|
|
12764
12948
|
className: "dy-mx-auto dy-max-w-3xl dy-space-y-10 dy-px-4 dy-py-8",
|
|
12765
12949
|
children: [
|
|
12950
|
+
/* @__PURE__ */ jsxs("div", {
|
|
12951
|
+
className: "dy-rounded-xl dy-border dy-border-border dy-bg-muted/30 dy-p-5 dy-space-y-3",
|
|
12952
|
+
children: [/* @__PURE__ */ jsx("h2", {
|
|
12953
|
+
className: "dy-text-sm dy-font-semibold dy-text-foreground",
|
|
12954
|
+
children: "System Info & Updates"
|
|
12955
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
12956
|
+
className: "dy-flex dy-flex-col sm:dy-flex-row sm:dy-items-center dy-justify-between dy-gap-4 dy-text-xs",
|
|
12957
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
12958
|
+
className: "dy-space-y-1",
|
|
12959
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
12960
|
+
className: "dy-text-muted-foreground",
|
|
12961
|
+
children: ["Current version: ", /* @__PURE__ */ jsxs("span", {
|
|
12962
|
+
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12963
|
+
children: ["v", currentVersion]
|
|
12964
|
+
})]
|
|
12965
|
+
}), latestVersion && /* @__PURE__ */ jsxs("p", {
|
|
12966
|
+
className: "dy-text-muted-foreground",
|
|
12967
|
+
children: ["Latest release: ", /* @__PURE__ */ jsxs("span", {
|
|
12968
|
+
className: "dy-font-mono dy-font-semibold dy-text-foreground",
|
|
12969
|
+
children: ["v", latestVersion]
|
|
12970
|
+
})]
|
|
12971
|
+
})]
|
|
12972
|
+
}), hasUpdate ? /* @__PURE__ */ jsxs("div", {
|
|
12973
|
+
className: "dy-flex dy-flex-col dy-items-start sm:dy-items-end dy-gap-1.5",
|
|
12974
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
12975
|
+
className: "dy-flex dy-items-center dy-gap-2",
|
|
12976
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
12977
|
+
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",
|
|
12978
|
+
children: "Update available!"
|
|
12979
|
+
}), /* @__PURE__ */ jsxs("a", {
|
|
12980
|
+
href: "https://github.com/Dyrected/dyrected/blob/main/CHANGELOG.md",
|
|
12981
|
+
target: "_blank",
|
|
12982
|
+
rel: "noopener noreferrer",
|
|
12983
|
+
className: "dy-inline-flex dy-items-center dy-gap-1 dy-text-[11px] dy-text-primary dy-underline-offset-4 hover:dy-underline",
|
|
12984
|
+
children: ["View changelog", /* @__PURE__ */ jsx(ArrowUpRight, { className: "dy-h-3 dy-w-3" })]
|
|
12985
|
+
})]
|
|
12986
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
12987
|
+
className: "dy-text-muted-foreground",
|
|
12988
|
+
children: [
|
|
12989
|
+
"Run ",
|
|
12990
|
+
/* @__PURE__ */ jsx("code", {
|
|
12991
|
+
className: "dy-bg-black/5 dark:dy-bg-white/5 dy-px-1 dy-py-0.5 dy-rounded dy-font-mono",
|
|
12992
|
+
children: "npx dyrected upgrade"
|
|
12993
|
+
}),
|
|
12994
|
+
" to update."
|
|
12995
|
+
]
|
|
12996
|
+
})]
|
|
12997
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
12998
|
+
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",
|
|
12999
|
+
children: "Up to date"
|
|
13000
|
+
})]
|
|
13001
|
+
})]
|
|
13002
|
+
}),
|
|
12766
13003
|
/* @__PURE__ */ jsxs("div", {
|
|
12767
13004
|
className: "dy-space-y-2",
|
|
12768
13005
|
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.51",
|
|
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/core": "^2.5.
|
|
68
|
-
"@dyrected/knowledge": "^0.2.
|
|
69
|
-
"@dyrected/sdk": "^2.5.
|
|
67
|
+
"@dyrected/core": "^2.5.51",
|
|
68
|
+
"@dyrected/knowledge": "^0.2.8",
|
|
69
|
+
"@dyrected/sdk": "^2.5.51"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@tanstack/react-query": "^5.0.0",
|