Files
AFFiNE-Mirror/packages/frontend/admin/src/modules/settings/use-app-config.ts
T
forehalo dad858014f feat(admin): adapt new config system (#11360)
feat(server): add test mail api

feat(admin): adapt new config system
2025-04-01 15:00:10 +00:00

112 lines
2.7 KiB
TypeScript

import { useMutation } from '@affine/admin/use-mutation';
import { useQuery } from '@affine/admin/use-query';
import { notify } from '@affine/component';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { UserFriendlyError } from '@affine/error';
import {
appConfigQuery,
type UpdateAppConfigInput,
updateAppConfigMutation,
} from '@affine/graphql';
import { cloneDeep, get, merge, set } from 'lodash-es';
import { useCallback, useState } from 'react';
import type { AppConfig } from './config';
export { type UpdateAppConfigInput };
export type AppConfigUpdates = Record<string, { from: any; to: any }>;
export const useAppConfig = () => {
const {
data: { appConfig },
mutate,
} = useQuery({
query: appConfigQuery,
});
const { trigger } = useMutation({
mutation: updateAppConfigMutation,
});
const [updates, setUpdates] = useState<AppConfigUpdates>({});
const [patchedAppConfig, setPatchedAppConfig] = useState<AppConfig>(() =>
cloneDeep(appConfig)
);
const save = useAsyncCallback(async () => {
const updateInputs: UpdateAppConfigInput[] = Object.entries(updates).map(
([key, value]) => {
const splitIndex = key.indexOf('.');
const module = key.slice(0, splitIndex);
const field = key.slice(splitIndex + 1);
return {
module,
key: field,
value: value.to,
};
}
);
try {
const savedUpdates = await trigger({
updates: updateInputs,
});
await mutate(prev => {
return { appConfig: merge({}, prev, savedUpdates) };
});
setUpdates({});
notify.success({
title: 'Saved',
message: 'Settings have been saved successfully.',
});
} catch (e) {
const error = UserFriendlyError.fromAny(e);
notify.error({
title: 'Failed to save',
message: error.message,
});
console.error(e);
}
}, [updates, mutate, trigger]);
const update = useCallback(
(path: string, value: any) => {
const [module, field, subField] = path.split('/');
const key = `${module}.${field}`;
const from = get(appConfig, key);
setUpdates(prev => {
const to = subField
? set(prev[key]?.to ?? { ...from }, subField, value)
: value;
return {
...prev,
[key]: {
from,
to,
},
};
});
setPatchedAppConfig(prev => {
return set(
prev,
`${module}.${field}${subField ? `.${subField}` : ''}`,
value
);
});
},
[appConfig]
);
return {
appConfig: appConfig as AppConfig,
patchedAppConfig,
update,
save,
updates,
};
};