@dyrected/admin 2.5.64 → 2.6.0
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 +4 -0
- package/dist/components/forms/fields/join-field.test.d.ts +1 -0
- package/dist/components/ui/data-table.d.ts +4 -2
- package/dist/components/ui/render-cell.test.d.ts +1 -0
- package/dist/index.mjs +378 -191
- package/dist/lib/document-title.d.ts +16 -0
- package/dist/lib/document-title.test.d.ts +1 -0
- package/package.json +4 -4
package/dist/admin.css
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,7 +3,9 @@ import * as React from "react";
|
|
|
3
3
|
interface DataTableProps<TData, TValue> {
|
|
4
4
|
columns: ColumnDef<TData, TValue>[];
|
|
5
5
|
data: TData[];
|
|
6
|
-
|
|
6
|
+
searchPlaceholder?: string;
|
|
7
|
+
searchValue?: string;
|
|
8
|
+
onSearchChange?: (value: string) => void;
|
|
7
9
|
rowSelection?: any;
|
|
8
10
|
onRowSelectionChange?: any;
|
|
9
11
|
bulkActions?: (selectedIds: string[]) => React.ReactNode;
|
|
@@ -12,5 +14,5 @@ interface DataTableProps<TData, TValue> {
|
|
|
12
14
|
initialColumnVisibility?: VisibilityState;
|
|
13
15
|
hideViewButton?: boolean;
|
|
14
16
|
}
|
|
15
|
-
export declare function DataTable<TData, TValue>({ columns, data,
|
|
17
|
+
export declare function DataTable<TData, TValue>({ columns, data, searchPlaceholder, searchValue, onSearchChange, rowSelection: externalRowSelection, onRowSelectionChange, bulkActions, toolbarActions, persistenceKey, initialColumnVisibility, hideViewButton, }: DataTableProps<TData, TValue>): React.JSX.Element;
|
|
16
18
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
|
15
15
|
import { Toaster, toast } from "sonner";
|
|
16
16
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
17
17
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
18
|
-
import { flexRender, getCoreRowModel,
|
|
18
|
+
import { flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
|
19
19
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
20
20
|
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
|
|
21
21
|
import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
@@ -812,10 +812,65 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
812
812
|
const collections = (schemas?.collections)?.filter((c) => !c?.admin?.hidden && !c?.slug.startsWith("platform_")) ?? [];
|
|
813
813
|
const globals = (schemas?.globals)?.filter((g) => !g?.admin?.hidden && !g?.slug.startsWith("platform_")) ?? [];
|
|
814
814
|
const uploadCollections = collections.filter((c) => c.upload);
|
|
815
|
+
const standardCollections = collections.filter((c) => !c.upload && !c.auth);
|
|
816
|
+
const authCollections = collections.filter((c) => !c.upload && c.auth);
|
|
815
817
|
const groupLabel = (text) => !collapsed ? /* @__PURE__ */ jsx("p", {
|
|
816
818
|
className: "dy-px-3 dy-mb-1.5 dy-text-[10px] dy-font-semibold dy-uppercase dy-tracking-widest dy-text-muted-foreground/50",
|
|
817
819
|
children: text
|
|
818
820
|
}) : /* @__PURE__ */ jsx("div", { className: "dy-my-2 dy-mx-3 dy-h-px dy-bg-border" });
|
|
821
|
+
const renderCollectionItem = (col) => {
|
|
822
|
+
const isReadOnly = col.access?.read && !col.access?.create && !col.access?.update && !col.access?.delete;
|
|
823
|
+
const navLabel = /* @__PURE__ */ jsxs("div", {
|
|
824
|
+
className: "dy-flex dy-items-center dy-gap-1.5 dy-min-w-0",
|
|
825
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
826
|
+
className: "dy-truncate",
|
|
827
|
+
children: col.labels?.plural ?? col.label ?? col.slug
|
|
828
|
+
}), !collapsed && /* @__PURE__ */ jsxs("div", {
|
|
829
|
+
className: "dy-flex dy-gap-1 dy-shrink-0",
|
|
830
|
+
children: [
|
|
831
|
+
col.auth && /* @__PURE__ */ jsx(Shield, { className: "dy-h-4 dy-w-4 dy-text-primary/70" }),
|
|
832
|
+
col.shared && /* @__PURE__ */ jsx(Share2, { className: "dy-h-4 dy-w-4 dy-text-purple-500/70" }),
|
|
833
|
+
isReadOnly && /* @__PURE__ */ jsx(Lock, { className: "dy-h-4 dy-w-4 dy-text-muted-foreground/40" })
|
|
834
|
+
]
|
|
835
|
+
})]
|
|
836
|
+
});
|
|
837
|
+
return /* @__PURE__ */ jsx(NavItem, {
|
|
838
|
+
to: `/collections/${col.slug}`,
|
|
839
|
+
icon: resolveAdminIcon(col.admin?.icon, col.auth ? Users : Database),
|
|
840
|
+
label: navLabel,
|
|
841
|
+
active: location.pathname.startsWith(`/collections/${col.slug}`),
|
|
842
|
+
collapsed,
|
|
843
|
+
onClick: onNavigate
|
|
844
|
+
}, col.slug);
|
|
845
|
+
};
|
|
846
|
+
const renderCollectionSection = (sectionCollections, ungroupedLabel) => {
|
|
847
|
+
if (sectionCollections.length === 0) return null;
|
|
848
|
+
const groups = /* @__PURE__ */ new Map();
|
|
849
|
+
const ungrouped = [];
|
|
850
|
+
sectionCollections.forEach((col) => {
|
|
851
|
+
const groupName = col.admin?.group;
|
|
852
|
+
if (groupName) {
|
|
853
|
+
if (!groups.has(groupName)) groups.set(groupName, []);
|
|
854
|
+
groups.get(groupName).push(col);
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
ungrouped.push(col);
|
|
858
|
+
});
|
|
859
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
860
|
+
className: "dy-space-y-1",
|
|
861
|
+
children: [Array.from(groups.entries()).map(([groupName, cols]) => /* @__PURE__ */ jsx(NavGroup, {
|
|
862
|
+
label: groupName,
|
|
863
|
+
collapsed,
|
|
864
|
+
defaultExpanded: true,
|
|
865
|
+
children: cols.map((col) => renderCollectionItem(col))
|
|
866
|
+
}, groupName)), ungrouped.length > 0 && /* @__PURE__ */ jsx(NavGroup, {
|
|
867
|
+
label: ungroupedLabel,
|
|
868
|
+
collapsed,
|
|
869
|
+
defaultExpanded: true,
|
|
870
|
+
children: ungrouped.map((col) => renderCollectionItem(col))
|
|
871
|
+
})]
|
|
872
|
+
});
|
|
873
|
+
};
|
|
819
874
|
const branding = schemas?.admin?.branding;
|
|
820
875
|
const meta = schemas?.admin?.meta;
|
|
821
876
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -870,65 +925,17 @@ function SidebarInner({ schemas, isLoading, location, logout, isEmbedded, collap
|
|
|
870
925
|
collapsed,
|
|
871
926
|
onClick: onNavigate
|
|
872
927
|
}, col.slug))] }),
|
|
873
|
-
(isLoading ||
|
|
928
|
+
(isLoading || standardCollections.length > 0 || authCollections.length > 0) && /* @__PURE__ */ jsx("div", { children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
874
929
|
className: "dy-space-y-1 dy-px-1",
|
|
875
930
|
children: [
|
|
876
931
|
1,
|
|
877
932
|
2,
|
|
878
933
|
3
|
|
879
934
|
].map((i) => /* @__PURE__ */ jsx("div", { className: cn("dy-h-8 dy-rounded-md dy-bg-muted/60 dy-animate-pulse", collapsed ? "dy-mx-1" : "dy-mx-2") }, i))
|
|
880
|
-
}) : (
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
nonUpload.forEach((col) => {
|
|
885
|
-
let g = col.admin?.group;
|
|
886
|
-
if (!g && col.auth) g = "System";
|
|
887
|
-
if (g) {
|
|
888
|
-
if (!groups.has(g)) groups.set(g, []);
|
|
889
|
-
groups.get(g).push(col);
|
|
890
|
-
} else ungrouped.push(col);
|
|
891
|
-
});
|
|
892
|
-
const renderCollectionItem = (col) => {
|
|
893
|
-
const isReadOnly = col.access?.read && !col.access?.create && !col.access?.update && !col.access?.delete;
|
|
894
|
-
const navLabel = /* @__PURE__ */ jsxs("div", {
|
|
895
|
-
className: "dy-flex dy-items-center dy-gap-1.5 dy-min-w-0",
|
|
896
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
897
|
-
className: "dy-truncate",
|
|
898
|
-
children: col.labels?.plural ?? col.label ?? col.slug
|
|
899
|
-
}), !collapsed && /* @__PURE__ */ jsxs("div", {
|
|
900
|
-
className: "dy-flex dy-gap-1 dy-shrink-0",
|
|
901
|
-
children: [
|
|
902
|
-
col.auth && /* @__PURE__ */ jsx(Shield, { className: "dy-h-4 dy-w-4 dy-text-primary/70" }),
|
|
903
|
-
col.shared && /* @__PURE__ */ jsx(Share2, { className: "dy-h-4 dy-w-4 dy-text-purple-500/70" }),
|
|
904
|
-
isReadOnly && /* @__PURE__ */ jsx(Lock, { className: "dy-h-4 dy-w-4 dy-text-muted-foreground/40" })
|
|
905
|
-
]
|
|
906
|
-
})]
|
|
907
|
-
});
|
|
908
|
-
return /* @__PURE__ */ jsx(NavItem, {
|
|
909
|
-
to: `/collections/${col.slug}`,
|
|
910
|
-
icon: resolveAdminIcon(col.admin?.icon, col.auth ? Users : Database),
|
|
911
|
-
label: navLabel,
|
|
912
|
-
active: location.pathname.startsWith(`/collections/${col.slug}`),
|
|
913
|
-
collapsed,
|
|
914
|
-
onClick: onNavigate
|
|
915
|
-
}, col.slug);
|
|
916
|
-
};
|
|
917
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
918
|
-
className: "dy-space-y-1",
|
|
919
|
-
children: [Array.from(groups.entries()).map(([groupName, cols]) => /* @__PURE__ */ jsx(NavGroup, {
|
|
920
|
-
label: groupName,
|
|
921
|
-
collapsed,
|
|
922
|
-
defaultExpanded: true,
|
|
923
|
-
children: cols.map((col) => renderCollectionItem(col))
|
|
924
|
-
}, groupName)), ungrouped.length > 0 && /* @__PURE__ */ jsx(NavGroup, {
|
|
925
|
-
label: "Collections",
|
|
926
|
-
collapsed,
|
|
927
|
-
defaultExpanded: true,
|
|
928
|
-
children: ungrouped.map((col) => renderCollectionItem(col))
|
|
929
|
-
})]
|
|
930
|
-
});
|
|
931
|
-
})() }),
|
|
935
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
936
|
+
className: "dy-space-y-1",
|
|
937
|
+
children: [renderCollectionSection(standardCollections, "Collections"), renderCollectionSection(authCollections, "Auth")]
|
|
938
|
+
}) }),
|
|
932
939
|
globals.length > 0 && /* @__PURE__ */ jsxs("div", { children: [groupLabel("Configuration"), /* @__PURE__ */ jsx("div", {
|
|
933
940
|
className: "dy-space-y-0.5",
|
|
934
941
|
children: globals.map((glob) => /* @__PURE__ */ jsx(NavItem, {
|
|
@@ -1038,7 +1045,7 @@ function isNewerVersion(latest, current) {
|
|
|
1038
1045
|
return false;
|
|
1039
1046
|
}
|
|
1040
1047
|
function useUpdateCheck() {
|
|
1041
|
-
const currentVersion = "2.5.
|
|
1048
|
+
const currentVersion = "2.5.65";
|
|
1042
1049
|
const [updateInfo, setUpdateInfo] = useState(() => {
|
|
1043
1050
|
if (typeof window === "undefined") return null;
|
|
1044
1051
|
const cacheKey = "dyrected_latest_release";
|
|
@@ -1264,7 +1271,7 @@ function getStatusLabel(doc) {
|
|
|
1264
1271
|
}
|
|
1265
1272
|
function Dashboard() {
|
|
1266
1273
|
const { client, components, user } = useDyrected();
|
|
1267
|
-
const currentVersion = "2.5.
|
|
1274
|
+
const currentVersion = "2.5.65";
|
|
1268
1275
|
const [latestVersion, setLatestVersion] = useState(() => {
|
|
1269
1276
|
if (typeof window === "undefined") return null;
|
|
1270
1277
|
return localStorage.getItem("dyrected_latest_release");
|
|
@@ -2238,9 +2245,8 @@ function usePreferences(key, defaultValue) {
|
|
|
2238
2245
|
//#endregion
|
|
2239
2246
|
//#region src/components/ui/data-table.tsx
|
|
2240
2247
|
var EMPTY_VISIBILITY = {};
|
|
2241
|
-
function DataTable({ columns, data,
|
|
2248
|
+
function DataTable({ columns, data, searchPlaceholder, searchValue, onSearchChange, rowSelection: externalRowSelection, onRowSelectionChange, bulkActions, toolbarActions, persistenceKey, initialColumnVisibility, hideViewButton = false }) {
|
|
2242
2249
|
const [sorting, setSorting] = React$1.useState([]);
|
|
2243
|
-
const [columnFilters, setColumnFilters] = React$1.useState([]);
|
|
2244
2250
|
const [columnVisibility, setColumnVisibility] = usePreferences(persistenceKey ? `visibility_${persistenceKey}` : "temp_visibility", initialColumnVisibility ?? EMPTY_VISIBILITY);
|
|
2245
2251
|
const [internalRowSelection, setInternalRowSelection] = React$1.useState({});
|
|
2246
2252
|
const rowSelection = externalRowSelection || internalRowSelection;
|
|
@@ -2249,15 +2255,12 @@ function DataTable({ columns, data, searchKey, rowSelection: externalRowSelectio
|
|
|
2249
2255
|
data,
|
|
2250
2256
|
columns,
|
|
2251
2257
|
onSortingChange: setSorting,
|
|
2252
|
-
onColumnFiltersChange: setColumnFilters,
|
|
2253
2258
|
getCoreRowModel: getCoreRowModel(),
|
|
2254
2259
|
getSortedRowModel: getSortedRowModel(),
|
|
2255
|
-
getFilteredRowModel: getFilteredRowModel(),
|
|
2256
2260
|
onColumnVisibilityChange: setColumnVisibility,
|
|
2257
2261
|
onRowSelectionChange: setRowSelection,
|
|
2258
2262
|
state: {
|
|
2259
2263
|
sorting,
|
|
2260
|
-
columnFilters,
|
|
2261
2264
|
columnVisibility,
|
|
2262
2265
|
rowSelection
|
|
2263
2266
|
}
|
|
@@ -2289,15 +2292,12 @@ function DataTable({ columns, data, searchKey, rowSelection: externalRowSelectio
|
|
|
2289
2292
|
})
|
|
2290
2293
|
})] })]
|
|
2291
2294
|
}),
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
className: "dy-order-2 dy-h-9 dy-w-full sm:dy-order-1 sm:dy-max-w-sm"
|
|
2299
|
-
});
|
|
2300
|
-
})(),
|
|
2295
|
+
onSearchChange ? /* @__PURE__ */ jsx(Input, {
|
|
2296
|
+
placeholder: searchPlaceholder || "Search...",
|
|
2297
|
+
value: searchValue ?? "",
|
|
2298
|
+
onChange: (event) => onSearchChange(event.target.value),
|
|
2299
|
+
className: "dy-order-2 dy-h-9 dy-w-full sm:dy-order-1 sm:dy-max-w-sm"
|
|
2300
|
+
}) : null,
|
|
2301
2301
|
bulkActions && table.getFilteredSelectedRowModel().rows.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
2302
2302
|
className: "dy-order-3 dy-flex dy-w-full dy-items-center dy-gap-2 dy-animate-in dy-slide-in-from-left-2 sm:dy-order-2 sm:dy-w-auto",
|
|
2303
2303
|
children: bulkActions(table.getFilteredSelectedRowModel().rows.map((r) => r.original.id))
|
|
@@ -3058,6 +3058,135 @@ function CsvImporter({ slug, schema, onClose }) {
|
|
|
3058
3058
|
});
|
|
3059
3059
|
}
|
|
3060
3060
|
//#endregion
|
|
3061
|
+
//#region src/lib/document-title.ts
|
|
3062
|
+
var FALLBACK_FIELD_NAMES = [
|
|
3063
|
+
"title",
|
|
3064
|
+
"name",
|
|
3065
|
+
"label",
|
|
3066
|
+
"heading",
|
|
3067
|
+
"email",
|
|
3068
|
+
"subject"
|
|
3069
|
+
];
|
|
3070
|
+
var MAX_TITLE_DEPTH = 8;
|
|
3071
|
+
function findField(collection, fieldName) {
|
|
3072
|
+
if (!collection?.fields || !fieldName) return void 0;
|
|
3073
|
+
return collection.fields.find((field) => field.name === fieldName);
|
|
3074
|
+
}
|
|
3075
|
+
function findNestedField(fields, fieldName) {
|
|
3076
|
+
if (!fields || !fieldName) return void 0;
|
|
3077
|
+
return fields.find((field) => field.name === fieldName);
|
|
3078
|
+
}
|
|
3079
|
+
function resolveCollectionTitleFieldName(collection) {
|
|
3080
|
+
const configured = findField(collection, collection?.admin?.useAsTitle);
|
|
3081
|
+
if (configured?.name) return configured.name;
|
|
3082
|
+
for (const fieldName of FALLBACK_FIELD_NAMES) {
|
|
3083
|
+
const field = findField(collection, fieldName);
|
|
3084
|
+
if (field?.name) return field.name;
|
|
3085
|
+
}
|
|
3086
|
+
return collection?.fields?.find((field) => !!field.name && field.type !== "join" && field.type !== "row")?.name;
|
|
3087
|
+
}
|
|
3088
|
+
function getObjectFallbackTitle(value) {
|
|
3089
|
+
for (const key of FALLBACK_FIELD_NAMES) {
|
|
3090
|
+
const candidate = value[key];
|
|
3091
|
+
if (typeof candidate === "string" && candidate.trim()) return candidate;
|
|
3092
|
+
}
|
|
3093
|
+
const idValue = value.id;
|
|
3094
|
+
if (typeof idValue === "string" && idValue.trim()) return idValue;
|
|
3095
|
+
if (typeof idValue === "number") return String(idValue);
|
|
3096
|
+
return null;
|
|
3097
|
+
}
|
|
3098
|
+
function resolveStructuredTitleFieldName(field) {
|
|
3099
|
+
if (!field?.fields?.length) return void 0;
|
|
3100
|
+
const configured = findNestedField(field.fields, field.admin?.useAsTitle);
|
|
3101
|
+
if (configured?.name) return configured.name;
|
|
3102
|
+
for (const fieldName of FALLBACK_FIELD_NAMES) {
|
|
3103
|
+
const candidate = findNestedField(field.fields, fieldName);
|
|
3104
|
+
if (candidate?.name) return candidate.name;
|
|
3105
|
+
}
|
|
3106
|
+
return field.fields.find((childField) => !!childField.name && childField.type !== "join" && childField.type !== "row")?.name;
|
|
3107
|
+
}
|
|
3108
|
+
function summarizeTitles(values, limit = 3) {
|
|
3109
|
+
const unique = values.filter(Boolean);
|
|
3110
|
+
if (unique.length === 0) return null;
|
|
3111
|
+
if (unique.length <= limit) return unique.join(", ");
|
|
3112
|
+
return `${unique.slice(0, limit).join(", ")} +${unique.length - limit} more`;
|
|
3113
|
+
}
|
|
3114
|
+
function resolveRelationshipValueTitle(value, field, collections, depth) {
|
|
3115
|
+
if (!field || field.type !== "relationship" || depth >= MAX_TITLE_DEPTH) return null;
|
|
3116
|
+
const relatedCollection = collections?.find((collection) => collection.slug === field.relationTo || collection.slug === field.collection);
|
|
3117
|
+
const relatedTitleFieldName = resolveCollectionTitleFieldName(relatedCollection);
|
|
3118
|
+
const relatedTitleField = findField(relatedCollection, relatedTitleFieldName);
|
|
3119
|
+
const resolveOne = (item) => {
|
|
3120
|
+
if (item == null) return null;
|
|
3121
|
+
if (typeof item === "string" || typeof item === "number") return String(item);
|
|
3122
|
+
if (typeof item !== "object" || Array.isArray(item)) return null;
|
|
3123
|
+
const record = item;
|
|
3124
|
+
if (relatedTitleFieldName && relatedTitleField) {
|
|
3125
|
+
const relatedValue = record[relatedTitleFieldName];
|
|
3126
|
+
const resolved = resolveValueTitleInternal(relatedValue, relatedTitleField, collections, depth + 1);
|
|
3127
|
+
if (resolved) return resolved;
|
|
3128
|
+
}
|
|
3129
|
+
return getObjectFallbackTitle(record);
|
|
3130
|
+
};
|
|
3131
|
+
if (Array.isArray(value)) return summarizeTitles(value.map((item) => resolveOne(item)).filter((item) => !!item));
|
|
3132
|
+
return resolveOne(value);
|
|
3133
|
+
}
|
|
3134
|
+
function resolveStructuredObjectTitle(value, field, collections, depth) {
|
|
3135
|
+
if (!field?.fields?.length || depth >= MAX_TITLE_DEPTH) return getObjectFallbackTitle(value);
|
|
3136
|
+
const titleFieldName = resolveStructuredTitleFieldName(field);
|
|
3137
|
+
const titleField = findNestedField(field.fields, titleFieldName);
|
|
3138
|
+
if (titleFieldName && titleField) {
|
|
3139
|
+
const resolved = resolveValueTitleInternal(value[titleFieldName], titleField, collections, depth + 1);
|
|
3140
|
+
if (resolved) return resolved;
|
|
3141
|
+
}
|
|
3142
|
+
return getObjectFallbackTitle(value);
|
|
3143
|
+
}
|
|
3144
|
+
function resolveStructuredArrayTitle(value, field, collections, depth) {
|
|
3145
|
+
if (depth >= MAX_TITLE_DEPTH) return null;
|
|
3146
|
+
return summarizeTitles(value.map((item) => {
|
|
3147
|
+
if (item == null) return null;
|
|
3148
|
+
if (typeof item !== "object" || Array.isArray(item)) return resolveValueTitleInternal(item, void 0, collections, depth + 1);
|
|
3149
|
+
return resolveStructuredObjectTitle(item, field, collections, depth + 1);
|
|
3150
|
+
}).filter((item) => !!item));
|
|
3151
|
+
}
|
|
3152
|
+
function resolveValueTitle(value, field, collections) {
|
|
3153
|
+
return resolveValueTitleInternal(value, field, collections, 0);
|
|
3154
|
+
}
|
|
3155
|
+
function resolveValueTitleInternal(value, field, collections, depth) {
|
|
3156
|
+
if (value == null) return null;
|
|
3157
|
+
if (field?.type === "relationship") {
|
|
3158
|
+
const relationTitle = resolveRelationshipValueTitle(value, field, collections, depth);
|
|
3159
|
+
if (relationTitle) return relationTitle;
|
|
3160
|
+
}
|
|
3161
|
+
if (field?.type === "array" && Array.isArray(value)) {
|
|
3162
|
+
const arrayTitle = resolveStructuredArrayTitle(value, field, collections, depth);
|
|
3163
|
+
if (arrayTitle) return arrayTitle;
|
|
3164
|
+
}
|
|
3165
|
+
if (field?.type === "object" && typeof value === "object" && !Array.isArray(value)) {
|
|
3166
|
+
const objectTitle = resolveStructuredObjectTitle(value, field, collections, depth);
|
|
3167
|
+
if (objectTitle) return objectTitle;
|
|
3168
|
+
}
|
|
3169
|
+
if (Array.isArray(value)) return summarizeTitles(value.map((item) => resolveValueTitleInternal(item, void 0, collections, depth + 1)).filter((item) => !!item));
|
|
3170
|
+
if (typeof value === "string") return value;
|
|
3171
|
+
if (typeof value === "number") return String(value);
|
|
3172
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
3173
|
+
if (typeof value === "object") return getObjectFallbackTitle(value);
|
|
3174
|
+
return null;
|
|
3175
|
+
}
|
|
3176
|
+
function resolveDocumentTitle(args) {
|
|
3177
|
+
const { entry, collection, collections } = args;
|
|
3178
|
+
if (!entry) return "";
|
|
3179
|
+
const titleFieldName = resolveCollectionTitleFieldName(collection);
|
|
3180
|
+
const titleField = findField(collection, titleFieldName);
|
|
3181
|
+
if (titleFieldName && titleField) {
|
|
3182
|
+
const title = resolveValueTitle(entry[titleFieldName], titleField, collections);
|
|
3183
|
+
if (title) return title;
|
|
3184
|
+
}
|
|
3185
|
+
const fallback = getObjectFallbackTitle(entry);
|
|
3186
|
+
if (fallback) return fallback;
|
|
3187
|
+
return String(entry.id ?? "");
|
|
3188
|
+
}
|
|
3189
|
+
//#endregion
|
|
3061
3190
|
//#region src/lib/format.ts
|
|
3062
3191
|
/** Normalize the shorthand string form into the object form. */
|
|
3063
3192
|
function resolveNumberFormat(format) {
|
|
@@ -3409,6 +3538,23 @@ function RenderCell({ value, field, client, schemas }) {
|
|
|
3409
3538
|
children: formatDate(value, field.admin?.format, field.type)
|
|
3410
3539
|
})]
|
|
3411
3540
|
});
|
|
3541
|
+
if (field.type === "icon") {
|
|
3542
|
+
if (!isAdminIconName(value)) return /* @__PURE__ */ jsx("span", {
|
|
3543
|
+
className: "dy-text-muted-foreground",
|
|
3544
|
+
children: "-"
|
|
3545
|
+
});
|
|
3546
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3547
|
+
className: "dy-inline-flex dy-items-center dy-gap-2 dy-text-foreground",
|
|
3548
|
+
children: [/* @__PURE__ */ jsx(resolveAdminIcon(value, Calendar), {
|
|
3549
|
+
className: "dy-h-4 dy-w-4 dy-shrink-0",
|
|
3550
|
+
"aria-hidden": "true"
|
|
3551
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
3552
|
+
className: "dy-text-sm dy-font-medium",
|
|
3553
|
+
title: String(value),
|
|
3554
|
+
children: String(value)
|
|
3555
|
+
})]
|
|
3556
|
+
});
|
|
3557
|
+
}
|
|
3412
3558
|
const relationTo = field.relationTo || field.collection;
|
|
3413
3559
|
if (field.type === "image" || field.type === "relationship" && isUploadCollection(relationTo, schemas)) {
|
|
3414
3560
|
if (!value) return /* @__PURE__ */ jsx("span", {
|
|
@@ -3430,8 +3576,7 @@ function RenderCell({ value, field, client, schemas }) {
|
|
|
3430
3576
|
});
|
|
3431
3577
|
}
|
|
3432
3578
|
if (field.type === "relationship" && typeof value === "object") {
|
|
3433
|
-
const
|
|
3434
|
-
const displayValue = value[(schemas?.collections?.find((c) => c?.slug === relTo))?.admin?.useAsTitle || "title"] || value.name || value.id || "Unknown";
|
|
3579
|
+
const displayValue = resolveValueTitle(value, field, schemas?.collections) || "Unknown";
|
|
3435
3580
|
return /* @__PURE__ */ jsx("div", {
|
|
3436
3581
|
className: "dy-flex dy-items-center dy-gap-2",
|
|
3437
3582
|
children: /* @__PURE__ */ jsx(Badge, {
|
|
@@ -3445,22 +3590,34 @@ function RenderCell({ value, field, client, schemas }) {
|
|
|
3445
3590
|
className: "dy-text-[11px] dy-text-muted-foreground dy-font-mono dy-bg-muted/30 dy-px-1.5 dy-py-0.5 dy-rounded",
|
|
3446
3591
|
children: formatJson(value, field.admin?.format)
|
|
3447
3592
|
});
|
|
3448
|
-
if (Array.isArray(value))
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
className: "dy-
|
|
3456
|
-
children: [
|
|
3457
|
-
"
|
|
3458
|
-
|
|
3459
|
-
"
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3593
|
+
if (Array.isArray(value)) {
|
|
3594
|
+
const structuredTitle = resolveValueTitle(value, field, schemas?.collections);
|
|
3595
|
+
if (structuredTitle) return /* @__PURE__ */ jsx("span", {
|
|
3596
|
+
className: "dy-text-[11px] dy-text-muted-foreground dy-font-medium dy-leading-tight",
|
|
3597
|
+
children: structuredTitle
|
|
3598
|
+
});
|
|
3599
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3600
|
+
className: "dy-flex dy-flex-wrap dy-gap-1",
|
|
3601
|
+
children: [value.slice(0, 2).map((item, i) => /* @__PURE__ */ jsx(Badge, {
|
|
3602
|
+
variant: "outline",
|
|
3603
|
+
className: "dy-text-[10px] dy-px-1.5 dy-h-5",
|
|
3604
|
+
children: typeof item === "object" ? item.title || item.name || item.id : String(item)
|
|
3605
|
+
}, i)), value.length > 2 && /* @__PURE__ */ jsxs("span", {
|
|
3606
|
+
className: "dy-text-[10px] dy-text-muted-foreground",
|
|
3607
|
+
children: [
|
|
3608
|
+
"+",
|
|
3609
|
+
value.length - 2,
|
|
3610
|
+
" more"
|
|
3611
|
+
]
|
|
3612
|
+
})]
|
|
3613
|
+
});
|
|
3614
|
+
}
|
|
3463
3615
|
if (typeof value === "object" && !Array.isArray(value)) {
|
|
3616
|
+
const structuredTitle = resolveValueTitle(value, field, schemas?.collections);
|
|
3617
|
+
if (structuredTitle) return /* @__PURE__ */ jsx("span", {
|
|
3618
|
+
className: "dy-text-[11px] dy-text-muted-foreground dy-font-medium dy-leading-tight",
|
|
3619
|
+
children: structuredTitle
|
|
3620
|
+
});
|
|
3464
3621
|
const entries = Object.entries(value).filter(([, v]) => typeof v !== "object" && v !== null && v !== void 0).slice(0, 3);
|
|
3465
3622
|
if (entries.length > 0) return /* @__PURE__ */ jsxs("span", {
|
|
3466
3623
|
className: "dy-text-[11px] dy-text-muted-foreground dy-font-medium dy-leading-tight",
|
|
@@ -6389,6 +6546,16 @@ function JoinField({ schema, control }) {
|
|
|
6389
6546
|
name: schema.name
|
|
6390
6547
|
})?.docs;
|
|
6391
6548
|
const getLabel = (item) => item[displayField] || item.name || item.slug || item.id;
|
|
6549
|
+
const showCreateButton = schema.admin?.showCreateButton !== false;
|
|
6550
|
+
const showViewButton = schema.admin?.showViewButton !== false;
|
|
6551
|
+
const handleCreateNew = () => {
|
|
6552
|
+
const params = new URLSearchParams({ [onField]: docId });
|
|
6553
|
+
navigate(`/collections/${targetCollection}/new?${params.toString()}`);
|
|
6554
|
+
};
|
|
6555
|
+
const handleViewAll = () => {
|
|
6556
|
+
const params = new URLSearchParams({ where: JSON.stringify({ [onField]: { equals: docId } }) });
|
|
6557
|
+
navigate(`/collections/${targetCollection}?${params.toString()}`);
|
|
6558
|
+
};
|
|
6392
6559
|
if (!docId) return /* @__PURE__ */ jsxs("p", {
|
|
6393
6560
|
className: "dy-text-xs dy-text-muted-foreground/60 dy-italic dy-py-2",
|
|
6394
6561
|
children: [
|
|
@@ -6423,17 +6590,27 @@ function JoinField({ schema, control }) {
|
|
|
6423
6590
|
" found."
|
|
6424
6591
|
]
|
|
6425
6592
|
})
|
|
6426
|
-
}), /* @__PURE__ */ jsxs(
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
"
|
|
6435
|
-
|
|
6436
|
-
|
|
6593
|
+
}), (showCreateButton || showViewButton) && /* @__PURE__ */ jsxs("div", {
|
|
6594
|
+
className: cn("dy-flex dy-items-center dy-gap-3", showCreateButton && showViewButton ? "dy-justify-between" : showCreateButton ? "dy-justify-end" : "dy-justify-start"),
|
|
6595
|
+
children: [showViewButton && /* @__PURE__ */ jsxs(Button, {
|
|
6596
|
+
type: "button",
|
|
6597
|
+
variant: "ghost",
|
|
6598
|
+
size: "sm",
|
|
6599
|
+
className: "dy-h-8 dy-text-[11px] dy-font-semibold dy-rounded-lg dy-text-muted-foreground hover:dy-text-foreground hover:dy-bg-muted/60 dy-transition-all",
|
|
6600
|
+
onClick: handleViewAll,
|
|
6601
|
+
children: [/* @__PURE__ */ jsx(ExternalLink, { className: "dy-w-3 dy-h-3 dy-mr-1.5" }), "View all"]
|
|
6602
|
+
}), showCreateButton && /* @__PURE__ */ jsxs(Button, {
|
|
6603
|
+
type: "button",
|
|
6604
|
+
variant: "outline",
|
|
6605
|
+
size: "sm",
|
|
6606
|
+
className: "dy-h-8 dy-text-[11px] dy-font-bold dy-rounded-lg dy-border-primary/20 hover:dy-bg-primary/5 hover:dy-text-primary dy-transition-all dy-shadow-sm",
|
|
6607
|
+
onClick: handleCreateNew,
|
|
6608
|
+
children: [
|
|
6609
|
+
/* @__PURE__ */ jsx(Plus, { className: "dy-w-3 dy-h-3 dy-mr-1.5" }),
|
|
6610
|
+
"Create new ",
|
|
6611
|
+
targetSchema?.labels?.singular || targetCollection
|
|
6612
|
+
]
|
|
6613
|
+
})]
|
|
6437
6614
|
})]
|
|
6438
6615
|
});
|
|
6439
6616
|
}
|
|
@@ -9798,6 +9975,7 @@ function FormEngineInner({ collection, fields, defaultValues = {}, onSubmit, onC
|
|
|
9798
9975
|
});
|
|
9799
9976
|
const topFields = visibleFields.filter((f) => !f.admin?.tab);
|
|
9800
9977
|
const tabbedFields = visibleFields.filter((f) => !!f.admin?.tab);
|
|
9978
|
+
const showPasswordSection = hasPassword && passwordChangeMode !== null;
|
|
9801
9979
|
let fieldsContent;
|
|
9802
9980
|
const renderFieldColumn = (field) => /* @__PURE__ */ jsx("div", {
|
|
9803
9981
|
className: "dy-min-w-0 dy-px-3 dy-w-full sm:dy-w-[var(--field-w)]",
|
|
@@ -9810,10 +9988,73 @@ function FormEngineInner({ collection, fields, defaultValues = {}, onSubmit, onC
|
|
|
9810
9988
|
documentId
|
|
9811
9989
|
})
|
|
9812
9990
|
}, field.name);
|
|
9991
|
+
const renderChangePasswordSection = () => /* @__PURE__ */ jsxs("div", {
|
|
9992
|
+
className: "dy-rounded-lg dy-border dy-border-border dy-p-5 dy-space-y-4",
|
|
9993
|
+
children: [
|
|
9994
|
+
/* @__PURE__ */ jsxs("div", {
|
|
9995
|
+
className: "dy-flex dy-items-center dy-gap-2 dy-text-sm dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wide",
|
|
9996
|
+
children: [/* @__PURE__ */ jsx(Lock, { className: "dy-h-4 dy-w-4" }), "Change Password"]
|
|
9997
|
+
}),
|
|
9998
|
+
/* @__PURE__ */ jsx("p", {
|
|
9999
|
+
className: "dy-text-xs dy-text-muted-foreground",
|
|
10000
|
+
children: passwordChangeMode === "admin" ? "As an admin, you can reset this user's password without their current password." : "Leave these fields blank to keep the current password unchanged."
|
|
10001
|
+
}),
|
|
10002
|
+
/* @__PURE__ */ jsxs("div", {
|
|
10003
|
+
className: "dy-grid dy-gap-4",
|
|
10004
|
+
children: [
|
|
10005
|
+
passwordChangeMode === "self" && /* @__PURE__ */ jsx(FormField, {
|
|
10006
|
+
control: form.control,
|
|
10007
|
+
name: "oldPassword",
|
|
10008
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
10009
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Current Password" }),
|
|
10010
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
10011
|
+
type: "password",
|
|
10012
|
+
placeholder: "Enter current password",
|
|
10013
|
+
autoComplete: "current-password",
|
|
10014
|
+
...field,
|
|
10015
|
+
value: field.value ?? ""
|
|
10016
|
+
}) }),
|
|
10017
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
10018
|
+
] })
|
|
10019
|
+
}),
|
|
10020
|
+
/* @__PURE__ */ jsx(FormField, {
|
|
10021
|
+
control: form.control,
|
|
10022
|
+
name: "newPassword",
|
|
10023
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
10024
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "New Password" }),
|
|
10025
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
10026
|
+
type: "password",
|
|
10027
|
+
placeholder: "Min. 8 characters",
|
|
10028
|
+
autoComplete: "new-password",
|
|
10029
|
+
...field,
|
|
10030
|
+
value: field.value ?? ""
|
|
10031
|
+
}) }),
|
|
10032
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
10033
|
+
] })
|
|
10034
|
+
}),
|
|
10035
|
+
/* @__PURE__ */ jsx(FormField, {
|
|
10036
|
+
control: form.control,
|
|
10037
|
+
name: "confirmPassword",
|
|
10038
|
+
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
10039
|
+
/* @__PURE__ */ jsx(FormLabel, { children: "Confirm New Password" }),
|
|
10040
|
+
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
10041
|
+
type: "password",
|
|
10042
|
+
placeholder: "Repeat new password",
|
|
10043
|
+
autoComplete: "new-password",
|
|
10044
|
+
...field,
|
|
10045
|
+
value: field.value ?? ""
|
|
10046
|
+
}) }),
|
|
10047
|
+
/* @__PURE__ */ jsx(FormMessage, {})
|
|
10048
|
+
] })
|
|
10049
|
+
})
|
|
10050
|
+
]
|
|
10051
|
+
})
|
|
10052
|
+
]
|
|
10053
|
+
});
|
|
9813
10054
|
const tabOrder = [];
|
|
9814
10055
|
const tabGroups = /* @__PURE__ */ new Map();
|
|
9815
10056
|
const defaultTab = defaultTabLabel || collection.charAt(0).toUpperCase() + collection.slice(1);
|
|
9816
|
-
if (tabbedFields.length > 0 && topFields.length > 0) {
|
|
10057
|
+
if (tabbedFields.length > 0 && (topFields.length > 0 || showPasswordSection)) {
|
|
9817
10058
|
tabGroups.set(defaultTab, [...topFields]);
|
|
9818
10059
|
tabOrder.push(defaultTab);
|
|
9819
10060
|
}
|
|
@@ -9881,12 +10122,15 @@ function FormEngineInner({ collection, fields, defaultValues = {}, onSubmit, onC
|
|
|
9881
10122
|
}, tab);
|
|
9882
10123
|
})
|
|
9883
10124
|
})
|
|
9884
|
-
}), tabOrder.map((tab) => /* @__PURE__ */
|
|
10125
|
+
}), tabOrder.map((tab) => /* @__PURE__ */ jsxs(TabsContent, {
|
|
9885
10126
|
value: tab,
|
|
9886
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
10127
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
9887
10128
|
className: "dy--mx-3 dy-flex dy-flex-wrap dy-gap-y-6 dy-pt-2",
|
|
9888
10129
|
children: tabGroups.get(tab).map(renderFieldColumn)
|
|
9889
|
-
})
|
|
10130
|
+
}), tab === defaultTab && showPasswordSection && /* @__PURE__ */ jsx("div", {
|
|
10131
|
+
className: "dy-pt-6",
|
|
10132
|
+
children: renderChangePasswordSection()
|
|
10133
|
+
})]
|
|
9890
10134
|
}, tab))]
|
|
9891
10135
|
})
|
|
9892
10136
|
});
|
|
@@ -9956,69 +10200,7 @@ function FormEngineInner({ collection, fields, defaultValues = {}, onSubmit, onC
|
|
|
9956
10200
|
})]
|
|
9957
10201
|
}),
|
|
9958
10202
|
fieldsContent,
|
|
9959
|
-
|
|
9960
|
-
className: "dy-rounded-lg dy-border dy-border-border dy-p-5 dy-space-y-4",
|
|
9961
|
-
children: [
|
|
9962
|
-
/* @__PURE__ */ jsxs("div", {
|
|
9963
|
-
className: "dy-flex dy-items-center dy-gap-2 dy-text-sm dy-font-semibold dy-text-muted-foreground dy-uppercase dy-tracking-wide",
|
|
9964
|
-
children: [/* @__PURE__ */ jsx(Lock, { className: "dy-h-4 dy-w-4" }), "Change Password"]
|
|
9965
|
-
}),
|
|
9966
|
-
/* @__PURE__ */ jsx("p", {
|
|
9967
|
-
className: "dy-text-xs dy-text-muted-foreground",
|
|
9968
|
-
children: passwordChangeMode === "admin" ? "As an admin, you can reset this user's password without their current password." : "Leave these fields blank to keep the current password unchanged."
|
|
9969
|
-
}),
|
|
9970
|
-
/* @__PURE__ */ jsxs("div", {
|
|
9971
|
-
className: "dy-grid dy-gap-4",
|
|
9972
|
-
children: [
|
|
9973
|
-
passwordChangeMode === "self" && /* @__PURE__ */ jsx(FormField, {
|
|
9974
|
-
control: form.control,
|
|
9975
|
-
name: "oldPassword",
|
|
9976
|
-
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
9977
|
-
/* @__PURE__ */ jsx(FormLabel, { children: "Current Password" }),
|
|
9978
|
-
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
9979
|
-
type: "password",
|
|
9980
|
-
placeholder: "Enter current password",
|
|
9981
|
-
autoComplete: "current-password",
|
|
9982
|
-
...field,
|
|
9983
|
-
value: field.value ?? ""
|
|
9984
|
-
}) }),
|
|
9985
|
-
/* @__PURE__ */ jsx(FormMessage, {})
|
|
9986
|
-
] })
|
|
9987
|
-
}),
|
|
9988
|
-
/* @__PURE__ */ jsx(FormField, {
|
|
9989
|
-
control: form.control,
|
|
9990
|
-
name: "newPassword",
|
|
9991
|
-
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
9992
|
-
/* @__PURE__ */ jsx(FormLabel, { children: "New Password" }),
|
|
9993
|
-
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
9994
|
-
type: "password",
|
|
9995
|
-
placeholder: "Min. 8 characters",
|
|
9996
|
-
autoComplete: "new-password",
|
|
9997
|
-
...field,
|
|
9998
|
-
value: field.value ?? ""
|
|
9999
|
-
}) }),
|
|
10000
|
-
/* @__PURE__ */ jsx(FormMessage, {})
|
|
10001
|
-
] })
|
|
10002
|
-
}),
|
|
10003
|
-
/* @__PURE__ */ jsx(FormField, {
|
|
10004
|
-
control: form.control,
|
|
10005
|
-
name: "confirmPassword",
|
|
10006
|
-
render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
|
|
10007
|
-
/* @__PURE__ */ jsx(FormLabel, { children: "Confirm New Password" }),
|
|
10008
|
-
/* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, {
|
|
10009
|
-
type: "password",
|
|
10010
|
-
placeholder: "Repeat new password",
|
|
10011
|
-
autoComplete: "new-password",
|
|
10012
|
-
...field,
|
|
10013
|
-
value: field.value ?? ""
|
|
10014
|
-
}) }),
|
|
10015
|
-
/* @__PURE__ */ jsx(FormMessage, {})
|
|
10016
|
-
] })
|
|
10017
|
-
})
|
|
10018
|
-
]
|
|
10019
|
-
})
|
|
10020
|
-
]
|
|
10021
|
-
}),
|
|
10203
|
+
showPasswordSection && tabbedFields.length === 0 && renderChangePasswordSection(),
|
|
10022
10204
|
!hideSubmit && /* @__PURE__ */ jsx("div", {
|
|
10023
10205
|
className: "dy-flex dy-justify-end dy-gap-4",
|
|
10024
10206
|
children: !readOnly && /* @__PURE__ */ jsx(Button, {
|
|
@@ -10962,6 +11144,8 @@ function CollectionListPage({ slug }) {
|
|
|
10962
11144
|
const [isImportOpen, setIsImportOpen] = React$1.useState(false);
|
|
10963
11145
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
10964
11146
|
const whereParam = searchParams.get("where");
|
|
11147
|
+
const searchParam = searchParams.get("search") || "";
|
|
11148
|
+
const debouncedSearch = useDebouncedValue(searchParam.trim(), 250);
|
|
10965
11149
|
const rules = React$1.useMemo(() => {
|
|
10966
11150
|
if (!whereParam) return [];
|
|
10967
11151
|
try {
|
|
@@ -11134,7 +11318,8 @@ function CollectionListPage({ slug }) {
|
|
|
11134
11318
|
"collection",
|
|
11135
11319
|
slug,
|
|
11136
11320
|
page,
|
|
11137
|
-
whereParam
|
|
11321
|
+
whereParam,
|
|
11322
|
+
debouncedSearch
|
|
11138
11323
|
],
|
|
11139
11324
|
queryFn: () => {
|
|
11140
11325
|
const queryParams = {
|
|
@@ -11145,6 +11330,7 @@ function CollectionListPage({ slug }) {
|
|
|
11145
11330
|
if (whereParam) try {
|
|
11146
11331
|
queryParams.where = JSON.parse(whereParam);
|
|
11147
11332
|
} catch {}
|
|
11333
|
+
if (debouncedSearch) queryParams.search = debouncedSearch;
|
|
11148
11334
|
return client.collection(slug).find(queryParams).exec();
|
|
11149
11335
|
},
|
|
11150
11336
|
enabled: !!client
|
|
@@ -11639,7 +11825,7 @@ function CollectionListPage({ slug }) {
|
|
|
11639
11825
|
}),
|
|
11640
11826
|
/* @__PURE__ */ jsx(PageHeader, {
|
|
11641
11827
|
title: schema.labels?.plural || schema.slug,
|
|
11642
|
-
description: `Manage your ${schema.labels?.plural || schema.slug} entries and update content.`,
|
|
11828
|
+
description: schema.admin?.description || `Manage your ${schema.labels?.plural || schema.slug} entries and update content.`,
|
|
11643
11829
|
icon: resolveAdminIcon(schema.admin?.icon, schema.auth ? Users : Database),
|
|
11644
11830
|
children: /* @__PURE__ */ jsxs("div", {
|
|
11645
11831
|
className: "dy-flex dy-items-center dy-gap-2 dy-w-full sm:dy-w-auto",
|
|
@@ -11821,7 +12007,16 @@ function CollectionListPage({ slug }) {
|
|
|
11821
12007
|
}) : /* @__PURE__ */ jsx(DataTable, {
|
|
11822
12008
|
columns,
|
|
11823
12009
|
data: response?.docs || [],
|
|
11824
|
-
|
|
12010
|
+
searchPlaceholder: `Search ${schema.labels?.plural || schema.slug}...`,
|
|
12011
|
+
searchValue: searchParam,
|
|
12012
|
+
onSearchChange: (value) => {
|
|
12013
|
+
setSearchParams((prev) => {
|
|
12014
|
+
if (value.trim()) prev.set("search", value);
|
|
12015
|
+
else prev.delete("search");
|
|
12016
|
+
return prev;
|
|
12017
|
+
}, { replace: true });
|
|
12018
|
+
setPage(1);
|
|
12019
|
+
},
|
|
11825
12020
|
onRowSelectionChange: setRowSelection,
|
|
11826
12021
|
rowSelection,
|
|
11827
12022
|
hideViewButton: true,
|
|
@@ -12590,20 +12785,6 @@ function PreviewPaneWithNav({ previewUrl, data, mode, collectionSlug, documentId
|
|
|
12590
12785
|
onFieldFocus: handleFieldFocus
|
|
12591
12786
|
});
|
|
12592
12787
|
}
|
|
12593
|
-
function getEntryTitle(entry, schema) {
|
|
12594
|
-
if (!entry) return "";
|
|
12595
|
-
const titleField = schema?.admin?.useAsTitle || "title";
|
|
12596
|
-
if (entry[titleField]) return String(entry[titleField]);
|
|
12597
|
-
for (const f of [
|
|
12598
|
-
"title",
|
|
12599
|
-
"name",
|
|
12600
|
-
"label",
|
|
12601
|
-
"heading",
|
|
12602
|
-
"email",
|
|
12603
|
-
"subject"
|
|
12604
|
-
]) if (entry[f]) return String(entry[f]);
|
|
12605
|
-
return String(entry.id);
|
|
12606
|
-
}
|
|
12607
12788
|
function EditEntryPage() {
|
|
12608
12789
|
const { slug, id } = useParams();
|
|
12609
12790
|
const [searchParams] = useSearchParams();
|
|
@@ -12756,12 +12937,10 @@ function EditEntryPage() {
|
|
|
12756
12937
|
slug,
|
|
12757
12938
|
debouncedSearchQuery
|
|
12758
12939
|
],
|
|
12759
|
-
queryFn:
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
return qb.exec();
|
|
12764
|
-
},
|
|
12940
|
+
queryFn: () => client.collection(slug).find({
|
|
12941
|
+
limit: 50,
|
|
12942
|
+
search: debouncedSearchQuery || void 0
|
|
12943
|
+
}).exec(),
|
|
12765
12944
|
enabled: !!client && !!slug && isEdit && switcherOpen
|
|
12766
12945
|
});
|
|
12767
12946
|
const syncPreviewData = useState(() => (next) => {
|
|
@@ -12928,7 +13107,11 @@ function EditEntryPage() {
|
|
|
12928
13107
|
className: "dy-flex dy-items-center dy-gap-1 dy-text-base dy-font-serif dy-font-bold dy-tracking-tight dy-text-foreground hover:dy-bg-muted/80 dy-px-2 dy-py-1 dy-rounded-lg dy-transition-all dy-outline-none dy-min-w-0",
|
|
12929
13108
|
children: [/* @__PURE__ */ jsx("span", {
|
|
12930
13109
|
className: "dy-truncate dy-max-w-[150px] sm:dy-max-w-none dy-inline-block",
|
|
12931
|
-
children: isEdit && entry ?
|
|
13110
|
+
children: isEdit && entry ? resolveDocumentTitle({
|
|
13111
|
+
entry,
|
|
13112
|
+
collection: schema,
|
|
13113
|
+
collections: schemas?.collections
|
|
13114
|
+
}) : "..."
|
|
12932
13115
|
}), /* @__PURE__ */ jsx(ChevronDown, { className: "dy-h-4 dy-w-4 dy-text-muted-foreground/80 dy-shrink-0" })]
|
|
12933
13116
|
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
12934
13117
|
align: "start",
|
|
@@ -12952,7 +13135,11 @@ function EditEntryPage() {
|
|
|
12952
13135
|
className: "dy-cursor-pointer dy-py-2 dy-px-3 dy-rounded-lg",
|
|
12953
13136
|
children: /* @__PURE__ */ jsx("span", {
|
|
12954
13137
|
className: "dy-text-sm dy-text-foreground",
|
|
12955
|
-
children:
|
|
13138
|
+
children: resolveDocumentTitle({
|
|
13139
|
+
entry: sibling,
|
|
13140
|
+
collection: schema,
|
|
13141
|
+
collections: schemas?.collections
|
|
13142
|
+
})
|
|
12956
13143
|
})
|
|
12957
13144
|
}, sibling.id)) }) })]
|
|
12958
13145
|
})
|
|
@@ -14809,7 +14996,7 @@ function SetupPromptUI({ config }) {
|
|
|
14809
14996
|
setCopied(true);
|
|
14810
14997
|
window.setTimeout(() => setCopied(false), 1800);
|
|
14811
14998
|
}
|
|
14812
|
-
const currentVersion = "2.5.
|
|
14999
|
+
const currentVersion = "2.5.65";
|
|
14813
15000
|
const [latestVersion, setLatestVersion] = useState(() => {
|
|
14814
15001
|
if (typeof window === "undefined") return null;
|
|
14815
15002
|
return localStorage.getItem("dyrected_latest_release");
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Field } from '@dyrected/core';
|
|
2
|
+
type SchemaCollection = {
|
|
3
|
+
slug: string;
|
|
4
|
+
admin?: {
|
|
5
|
+
useAsTitle?: string;
|
|
6
|
+
};
|
|
7
|
+
fields?: Field[];
|
|
8
|
+
};
|
|
9
|
+
export declare function resolveCollectionTitleFieldName(collection: SchemaCollection | undefined): string | undefined;
|
|
10
|
+
export declare function resolveValueTitle(value: unknown, field: Field | undefined, collections?: SchemaCollection[]): string | null;
|
|
11
|
+
export declare function resolveDocumentTitle(args: {
|
|
12
|
+
entry: Record<string, unknown> | null | undefined;
|
|
13
|
+
collection: SchemaCollection | undefined;
|
|
14
|
+
collections?: SchemaCollection[];
|
|
15
|
+
}): string;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dyrected/admin",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
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.
|
|
68
|
-
"@dyrected/
|
|
69
|
-
"@dyrected/
|
|
67
|
+
"@dyrected/core": "^2.6.0",
|
|
68
|
+
"@dyrected/sdk": "^2.6.0",
|
|
69
|
+
"@dyrected/knowledge": "^0.2.15"
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"@tanstack/react-query": "^5.0.0",
|