feat(config): admin Configuration page (registry-driven)
New admin-only Configuration page that renders the system_config registry grouped (Email/SMTP first), with per-field save/reset, write-only encrypted secret fields (disabled with a hint when TOKEN_ENCRYPTION_KEY is unset), and a Send-test-email button. New 'config' page + sidebar nav item + header title; api methods and EN/HU/DE strings.
This commit is contained in:
parent
48cb6a5dbd
commit
a71257f33f
12 changed files with 311 additions and 2 deletions
|
|
@ -440,6 +440,24 @@ export interface AppNotification {
|
|||
created_at: string | null;
|
||||
}
|
||||
|
||||
// Admin Configuration page: one DB-overridable setting (registry entry on the backend).
|
||||
export interface ConfigItem {
|
||||
key: string;
|
||||
type: "int" | "str" | "bool";
|
||||
group: string;
|
||||
secret: boolean;
|
||||
min: number | null;
|
||||
max: number | null;
|
||||
is_set: boolean; // a DB override row exists (else using the env/config default)
|
||||
value?: string | number | boolean; // non-secret: effective value
|
||||
default?: string | number | boolean; // non-secret: env/config default
|
||||
default_is_set?: boolean; // secret: whether an env default exists
|
||||
}
|
||||
export interface SystemConfigData {
|
||||
groups: Record<string, ConfigItem[]>;
|
||||
secrets_manageable: boolean;
|
||||
}
|
||||
|
||||
export const api = {
|
||||
me: (): Promise<Me> => req("/api/me"),
|
||||
accounts: (): Promise<Account[]> => req("/api/me/accounts"),
|
||||
|
|
@ -548,6 +566,14 @@ export const api = {
|
|||
// --- quota usage ---
|
||||
myUsage: (): Promise<MyUsage> => req("/api/quota/my-usage"),
|
||||
adminQuota: (days = 30): Promise<AdminQuota> => req(`/api/quota/admin?days=${days}`),
|
||||
// --- admin: system configuration ---
|
||||
adminConfig: (): Promise<SystemConfigData> => req("/api/admin/config"),
|
||||
setConfig: (key: string, value: string | number | boolean): Promise<SystemConfigData> =>
|
||||
req(`/api/admin/config/${key}`, { method: "PATCH", body: JSON.stringify({ value }) }),
|
||||
resetConfig: (key: string): Promise<SystemConfigData> =>
|
||||
req(`/api/admin/config/${key}`, { method: "DELETE" }),
|
||||
testEmail: (): Promise<{ sent: boolean; to: string }> =>
|
||||
req("/api/admin/config/test-email", { method: "POST" }),
|
||||
schedulerStatus: (): Promise<SchedulerStatus> => req("/api/admin/scheduler"),
|
||||
updateSchedulerJob: (jobId: string, intervalMinutes: number): Promise<{ id: string; interval_minutes: number }> =>
|
||||
req(`/api/admin/scheduler/jobs/${jobId}`, {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ export const PAGES = [
|
|||
"playlists",
|
||||
"settings",
|
||||
"scheduler",
|
||||
"config",
|
||||
"notifications",
|
||||
] as const;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue