Enhance documentation and admin UI: Add detailed implementation guidelines in CLAUDE.md, introduce a referrer index in README.md, and update admin UI translations for improved user experience. Update package dependencies for better functionality and performance.
This commit is contained in:
@@ -7,6 +7,9 @@ export const getBaseUrl = () =>
|
||||
process.env.NEXT_PUBLIC_RUSTYCMS_API_URL || "http://127.0.0.1:3000";
|
||||
|
||||
const STORAGE_KEY = "rustycms_admin_api_key";
|
||||
const PER_PAGE_KEY = "rustycms_per_page";
|
||||
const DEFAULT_PER_PAGE = 25;
|
||||
const PER_PAGE_OPTIONS = [10, 25, 50, 100] as const;
|
||||
|
||||
/** Client-side only: key set by login when no env key. */
|
||||
let clientApiKey: string | null = null;
|
||||
@@ -38,6 +41,47 @@ export function syncStoredApiKey(): void {
|
||||
if (stored) clientApiKey = stored;
|
||||
}
|
||||
|
||||
/** Items per page for content lists (stored in localStorage). */
|
||||
export function getPerPage(): number {
|
||||
if (typeof window === "undefined") return DEFAULT_PER_PAGE;
|
||||
const v = localStorage.getItem(PER_PAGE_KEY);
|
||||
const n = v ? parseInt(v, 10) : NaN;
|
||||
return PER_PAGE_OPTIONS.includes(n as (typeof PER_PAGE_OPTIONS)[number])
|
||||
? n
|
||||
: DEFAULT_PER_PAGE;
|
||||
}
|
||||
|
||||
export function setPerPage(n: number): void {
|
||||
if (typeof window === "undefined") return;
|
||||
if (PER_PAGE_OPTIONS.includes(n as (typeof PER_PAGE_OPTIONS)[number])) {
|
||||
localStorage.setItem(PER_PAGE_KEY, String(n));
|
||||
}
|
||||
}
|
||||
|
||||
export { PER_PAGE_OPTIONS, DEFAULT_PER_PAGE };
|
||||
|
||||
/** Clear API key and all rustycms_* localStorage (e.g. for shared devices). */
|
||||
export function clearSession(): void {
|
||||
setApiKey(null);
|
||||
if (typeof window === "undefined") return;
|
||||
const keys: string[] = [];
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const k = localStorage.key(i);
|
||||
if (k?.startsWith("rustycms_")) keys.push(k);
|
||||
}
|
||||
keys.forEach((k) => localStorage.removeItem(k));
|
||||
}
|
||||
|
||||
/** Check backend health (GET /health). */
|
||||
export async function fetchHealth(): Promise<{ ok: boolean; status?: number }> {
|
||||
try {
|
||||
const res = await fetch(`${getBaseUrl()}/health`, { cache: "no-store" });
|
||||
return { ok: res.ok, status: res.status };
|
||||
} catch {
|
||||
return { ok: false };
|
||||
}
|
||||
}
|
||||
|
||||
const getHeaders = (): HeadersInit => {
|
||||
const headers: HeadersInit = {
|
||||
"Content-Type": "application/json",
|
||||
@@ -68,11 +112,19 @@ export type FieldDefinition = {
|
||||
description?: string;
|
||||
collection?: string;
|
||||
collections?: string[];
|
||||
/** Optional whitelist of allowed slugs for reference fields. Only these slugs are valid. */
|
||||
allowedSlugs?: string[];
|
||||
/** Optional whitelist of allowed content types (collections). Only these collections are valid (intersection with collection/collections). */
|
||||
allowedCollections?: string[];
|
||||
enum?: unknown[];
|
||||
default?: unknown;
|
||||
items?: FieldDefinition;
|
||||
/** Optional section key for grouping fields in the admin UI (collapsible blocks). */
|
||||
section?: string;
|
||||
/** Optional hint for admin UI (e.g. "textarea" for string → multi-line input, "code" for code field with syntax highlighting). */
|
||||
widget?: string;
|
||||
/** When widget is "code", language for syntax highlighting: "css", "javascript", "json", "html". */
|
||||
codeLanguage?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
@@ -221,6 +273,25 @@ export async function fetchEntry<T = Record<string, unknown>>(
|
||||
return res.json();
|
||||
}
|
||||
|
||||
/** Referrer: an entry that references another (from GET .../referrers). */
|
||||
export type Referrer = {
|
||||
collection: string;
|
||||
slug: string;
|
||||
field: string;
|
||||
locale?: string | null;
|
||||
};
|
||||
|
||||
export async function fetchReferrers(
|
||||
collection: string,
|
||||
slug: string
|
||||
): Promise<Referrer[]> {
|
||||
const url = `${getBaseUrl()}/api/content/${encodeURIComponent(collection)}/${encodeURIComponent(slug)}/referrers`;
|
||||
const res = await fetch(url, { headers: getHeaders() });
|
||||
if (!res.ok) return [];
|
||||
const data = await res.json();
|
||||
return Array.isArray(data) ? data : [];
|
||||
}
|
||||
|
||||
export async function createEntry(
|
||||
collection: string,
|
||||
data: Record<string, unknown>,
|
||||
|
||||
Reference in New Issue
Block a user