mono/packages/ui/src/components/variables/VariablesEditor.tsx
2026-03-21 20:18:25 +01:00

104 lines
4.3 KiB
TypeScript

import React, { useEffect, useState, useCallback } from 'react';
import { VariableBuilder } from './VariableBuilder';
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import { translate } from '@/i18n';
const STORAGE_KEY = 'variables-editor-playground';
const SYSTEM_VARIABLE_SCHEMA: Record<string, { label: string, description?: string }> = {
showAuthor: { label: translate("Show Author"), description: translate("Toggle the display of the author name.") },
showDate: { label: translate("Show Date"), description: translate("Toggle the display of the publish date.") },
showCategories: { label: translate("Show Categories"), description: translate("Toggle the display of the category paths.") },
showActions: { label: translate("Show Actions"), description: translate("Toggle the display of the top-right page actions menu.") },
showParent: { label: translate("Show Parent Path"), description: translate("Toggle the display of the parent page path above the title.") },
showTitle: { label: translate("Show Title"), description: translate("Toggle the display of the page title block.") },
showToc: { label: translate("Show Table of Contents"), description: translate("Toggle the display of the side table of contents.") },
showLastUpdated: { label: translate("Show Last Updated"), description: translate("Toggle the display of the last updated footer.") },
showFooter: { label: translate("Show Global Footer"), description: translate("Toggle the display of the global app footer site-wide.") },
};
const defaultOnLoad = async (): Promise<Record<string, any>> => {
try {
const stored = localStorage.getItem(STORAGE_KEY);
return stored ? JSON.parse(stored) : {};
} catch { return {}; }
};
const defaultOnSave = async (data: Record<string, any>): Promise<void> => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
};
export interface VariablesEditorProps {
onLoad?: () => Promise<Record<string, any>>;
onSave?: (data: Record<string, any>) => Promise<void>;
inheritedData?: Record<string, any>;
variableSchema?: Record<string, { label: string, description?: string }>;
}
export const VariablesEditor: React.FC<VariablesEditorProps> = ({
onLoad = defaultOnLoad,
onSave = defaultOnSave,
inheritedData = {},
variableSchema
}) => {
const [variables, setVariables] = useState<Record<string, any>>({});
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const loadVariables = useCallback(async () => {
setLoading(true);
try {
const data = await onLoad();
setVariables(data || {});
} catch (error) {
console.error("Failed to fetch variables", error);
toast.error(translate("Failed to load variables"));
} finally {
setLoading(false);
}
}, [onLoad]);
useEffect(() => {
loadVariables();
}, [loadVariables]);
const handleSave = async (builderVariables: Record<string, any>) => {
setSaving(true);
try {
await onSave(builderVariables);
setVariables(builderVariables);
toast.success(translate("Variables saved successfully"));
} catch (error) {
console.error("Failed to save variables", error);
toast.error(translate("Failed to save variables"));
} finally {
setSaving(false);
}
};
const mergedSchema = React.useMemo(() => ({ ...SYSTEM_VARIABLE_SCHEMA, ...variableSchema }), [variableSchema]);
if (loading) {
return (
<div className="h-full flex items-center justify-center py-8">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
</div>
);
}
return (
<div className="h-[600px] flex flex-col gap-4">
<div className="flex-1 min-h-0">
<VariableBuilder
initialData={variables}
inheritedData={inheritedData}
onSave={handleSave}
isSaving={saving}
variableSchema={mergedSchema}
/>
</div>
</div>
);
};