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

@@ -6,6 +6,30 @@
export const getBaseUrl = () =>
process.env.NEXT_PUBLIC_RUSTYCMS_API_URL || "http://127.0.0.1:3000";
/**
* Recursively collapse absolute asset URLs to relative paths so the admin
* keeps and displays /api/assets/... and the backend stores relative.
*/
export function collapseAssetUrlsForAdmin(
value: unknown,
baseUrl: string
): unknown {
const prefix = `${baseUrl.replace(/\/+$/, "")}/api/assets/`;
if (typeof value === "string") {
if (value.startsWith(prefix)) return `/api/assets/${value.slice(prefix.length)}`;
return value;
}
if (Array.isArray(value)) return value.map((v) => collapseAssetUrlsForAdmin(v, baseUrl));
if (value != null && typeof value === "object") {
const out: Record<string, unknown> = {};
for (const [k, v] of Object.entries(value)) {
out[k] = collapseAssetUrlsForAdmin(v, baseUrl);
}
return out;
}
return value;
}
const STORAGE_KEY = "rustycms_admin_api_key";
const PER_PAGE_KEY = "rustycms_per_page";
const DEFAULT_PER_PAGE = 25;
@@ -133,6 +157,8 @@ export type SchemaDefinition = {
description?: string;
tags?: string[];
category?: string;
/** Optional order of field names for admin UI. Fields not listed appear after. */
fieldOrder?: string[];
fields: Record<string, FieldDefinition>;
extends?: string | string[];
reusable?: boolean;
@@ -155,6 +181,13 @@ export async function fetchCollections(): Promise<CollectionsResponse> {
return res.json();
}
/** All type names (including reusable). Use for extends dropdown. */
export async function fetchSchemaNames(): Promise<{ names: string[] }> {
const res = await fetch(`${getBaseUrl()}/api/schemas`, { headers: getHeaders() });
if (!res.ok) throw new Error(`Schema names: ${res.status}`);
return res.json();
}
export async function fetchSchema(
collection: string
): Promise<SchemaDefinition> {
@@ -166,6 +199,18 @@ export async function fetchSchema(
return res.json();
}
/** Raw schema as stored on disk (own fields + extends, unresolved). Use for type editor. */
export async function fetchSchemaRaw(
name: string
): Promise<SchemaDefinition> {
const res = await fetch(
`${getBaseUrl()}/api/schemas/${encodeURIComponent(name)}/raw`,
{ headers: getHeaders() }
);
if (!res.ok) throw new Error(`Schema raw ${name}: ${res.status}`);
return res.json();
}
export async function createSchema(
schema: SchemaDefinition
): Promise<SchemaDefinition> {