mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-01 14:19:40 +08:00
feat(admin): adapt new config system (#11360)
feat(server): add test mail api feat(admin): adapt new config system
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { Button } from '@affine/admin/components/ui/button';
|
||||
import { ScrollArea } from '@affine/admin/components/ui/scroll-area';
|
||||
import { Separator } from '@affine/admin/components/ui/separator';
|
||||
import { get } from 'lodash-es';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
import { useCallback, useState } from 'react';
|
||||
@@ -8,17 +7,16 @@ import { useCallback, useState } from 'react';
|
||||
import { Header } from '../header';
|
||||
import { useNav } from '../nav/context';
|
||||
import {
|
||||
ALL_CONFIG,
|
||||
ALL_CONFIGURABLE_MODULES,
|
||||
type ConfigDescriptor,
|
||||
ALL_CONFIG_DESCRIPTORS,
|
||||
ALL_SETTING_GROUPS,
|
||||
type AppConfig,
|
||||
} from './config';
|
||||
import { ConfigInput } from './config-input';
|
||||
import { type ConfigInputProps, ConfigRow } from './config-input-row';
|
||||
import { ConfirmChanges } from './confirm-changes';
|
||||
import { RuntimeSettingRow } from './runtime-setting-row';
|
||||
import { useAppConfig } from './use-app-config';
|
||||
|
||||
export function SettingsPage() {
|
||||
const { appConfig, update, save, updates } = useAppConfig();
|
||||
const { appConfig, update, save, patchedAppConfig, updates } = useAppConfig();
|
||||
const [open, setOpen] = useState(false);
|
||||
const onOpen = useCallback(() => setOpen(true), [setOpen]);
|
||||
|
||||
@@ -28,22 +26,12 @@ export function SettingsPage() {
|
||||
if (disableSave) {
|
||||
return;
|
||||
}
|
||||
save(
|
||||
Object.entries(updates).map(([key, { to }]) => {
|
||||
const splitAt = key.indexOf('.');
|
||||
const [module, field] = [key.slice(0, splitAt), key.slice(splitAt + 1)];
|
||||
return {
|
||||
module,
|
||||
key: field,
|
||||
value: to,
|
||||
};
|
||||
})
|
||||
);
|
||||
save();
|
||||
setOpen(false);
|
||||
}, [save, disableSave, updates]);
|
||||
}, [save, disableSave]);
|
||||
|
||||
return (
|
||||
<div className=" h-screen flex-1 flex-col flex">
|
||||
<div className="h-screen flex-1 flex-col flex">
|
||||
<Header
|
||||
title="Settings"
|
||||
endFix={
|
||||
@@ -59,7 +47,11 @@ export function SettingsPage() {
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<AdminPanel onUpdate={update} appConfig={appConfig} />
|
||||
<AdminPanel
|
||||
onUpdate={update}
|
||||
appConfig={appConfig}
|
||||
patchedAppConfig={patchedAppConfig}
|
||||
/>
|
||||
<ConfirmChanges
|
||||
updates={updates}
|
||||
open={open}
|
||||
@@ -72,58 +64,66 @@ export function SettingsPage() {
|
||||
|
||||
export const AdminPanel = ({
|
||||
appConfig,
|
||||
patchedAppConfig,
|
||||
onUpdate,
|
||||
}: {
|
||||
appConfig: Record<string, any>;
|
||||
onUpdate: (module: string, field: string, value: any) => void;
|
||||
appConfig: AppConfig;
|
||||
patchedAppConfig: AppConfig;
|
||||
onUpdate: (path: string, value: any) => void;
|
||||
}) => {
|
||||
const { currentModule } = useNav();
|
||||
const group = ALL_SETTING_GROUPS.find(
|
||||
group => group.module === currentModule
|
||||
);
|
||||
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { name, module, fields, operations } = group;
|
||||
|
||||
return (
|
||||
<ScrollArea>
|
||||
<div className="flex flex-col h-full gap-3 py-5 px-6 w-full max-w-[800px] mx-auto">
|
||||
{ALL_CONFIGURABLE_MODULES.filter(
|
||||
module => module === currentModule
|
||||
).map(module => {
|
||||
const fields = Object.keys(ALL_CONFIG[module]);
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col gap-5"
|
||||
id={`config-module-${module}`}
|
||||
key={module}
|
||||
>
|
||||
<div className="text-xl font-semibold">{module}</div>
|
||||
{fields.map((field, index) => {
|
||||
// @ts-expect-error allow
|
||||
const { desc, type } = ALL_CONFIG[module][
|
||||
field
|
||||
] as ConfigDescriptor;
|
||||
<ScrollArea className="h-full">
|
||||
<div className="flex flex-col h-full gap-5 py-5 px-6 w-full max-w-[800px] mx-auto">
|
||||
<div className="text-2xl font-semibold">{name}</div>
|
||||
<div className="flex flex-col gap-10" id={`config-module-${module}`}>
|
||||
{fields.map(field => {
|
||||
let desc: string;
|
||||
let props: ConfigInputProps;
|
||||
if (typeof field === 'string') {
|
||||
const descriptor = ALL_CONFIG_DESCRIPTORS[module][field];
|
||||
desc = descriptor.desc;
|
||||
props = {
|
||||
type: descriptor.type,
|
||||
defaultValue: get(appConfig[module], field),
|
||||
field: `${module}/${field}`,
|
||||
desc,
|
||||
onChange: onUpdate,
|
||||
options: [],
|
||||
};
|
||||
} else {
|
||||
const descriptor = ALL_CONFIG_DESCRIPTORS[module][field.key];
|
||||
|
||||
return (
|
||||
<div key={field} className="flex flex-col gap-10">
|
||||
{index !== 0 && <Separator />}
|
||||
<RuntimeSettingRow
|
||||
key={field}
|
||||
id={field}
|
||||
description={desc}
|
||||
orientation={
|
||||
type === 'Boolean' ? 'horizontal' : 'vertical'
|
||||
}
|
||||
>
|
||||
<ConfigInput
|
||||
module={module}
|
||||
field={field}
|
||||
type={type}
|
||||
defaultValue={get(appConfig[module], field)}
|
||||
onChange={onUpdate}
|
||||
/>
|
||||
</RuntimeSettingRow>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
props = {
|
||||
desc: field.desc ?? descriptor.desc,
|
||||
type: field.type ?? descriptor.type,
|
||||
// @ts-expect-error for enum type
|
||||
options: field.options,
|
||||
defaultValue: get(
|
||||
appConfig[module],
|
||||
field.key + (field.sub ? '.' + field.sub : '')
|
||||
),
|
||||
field: `${module}/${field.key}${field.sub ? `/${field.sub}` : ''}`,
|
||||
onChange: onUpdate,
|
||||
};
|
||||
}
|
||||
|
||||
return <ConfigRow key={props.field} {...props} />;
|
||||
})}
|
||||
{operations?.map(Operation => (
|
||||
<Operation key={Operation.name} appConfig={patchedAppConfig} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user