Enhance admin UI and schema management: Introduce generic handling for image/asset URL fields, ensuring explicit widget usage for image previews. Update translations for new UI elements and implement field ordering in schema definitions. Add functionality for managing field extensions and improve asset filtering in the admin UI.

This commit is contained in:
Peter Meier
2026-03-14 00:08:52 +01:00
parent 084a1d9e2a
commit 11d46049d1
23 changed files with 662 additions and 117 deletions

View File

@@ -196,12 +196,9 @@ function SlugField({
);
}
/** True if this string field is used for image/asset URLs (by description or name). */
function isImageUrlField(def: FieldDefinition, name: string): boolean {
const desc = def.description && String(def.description).toLowerCase();
if (desc && (desc.includes("image") || desc.includes("asset"))) return true;
if (name === "image" || name === "imageUrl" || name === "asset") return true;
return false;
/** True only when the schema explicitly requests image/asset URL UI via widget (no heuristics). */
function isImageUrlField(def: FieldDefinition): boolean {
return def.widget === "imageUrl" || def.widget === "assetUrl";
}
function assetPreviewUrl(value: string | undefined): string | null {
@@ -593,6 +590,16 @@ export function ContentForm({
}, [isDirty, handleSubmit]);
const fields = schema.fields ?? {};
const order = schema.fieldOrder;
const orderedFieldEntries: [string, FieldDefinition][] = order?.length
? [
...order.filter((n) => n in fields).map((n) => [n, fields[n] as FieldDefinition] as [string, FieldDefinition]),
...Object.keys(fields)
.filter((n) => !order.includes(n))
.map((n) => [n, fields[n] as FieldDefinition] as [string, FieldDefinition]),
]
: (Object.entries(fields) as [string, FieldDefinition][]);
const slugParam = locale ? `?_locale=${locale}` : "";
const showSlugField = !isEdit && !(fields._slug != null);
@@ -621,7 +628,7 @@ export function ContentForm({
}
currentTitle = null;
};
for (const [name, def] of Object.entries(fields)) {
for (const [name, def] of orderedFieldEntries) {
const fd = def as FieldDefinition;
if (fd.type === "object" && fd.fields) {
flush();
@@ -737,7 +744,7 @@ export function ContentForm({
</CollapsibleSection>
),
)
: Object.entries(fields).map(([name, def]) =>
: orderedFieldEntries.map(([name, def]) =>
(def as FieldDefinition).type === "object" &&
(def as FieldDefinition).fields ? (
<ObjectFieldSet
@@ -1488,7 +1495,7 @@ function Field({
);
}
if (type === "string" && isImageUrlField(def, name)) {
if (type === "string" && isImageUrlField(def)) {
return (
<Controller
name={name}