import { create } from "@bufbuild/protobuf"; import { isEqual } from "lodash-es"; import React, { useEffect, useMemo, useState } from "react"; import { toast } from "react-hot-toast"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Switch } from "@/components/ui/switch"; import { useInstance } from "@/contexts/InstanceContext"; import { InstanceSetting_Key, InstanceSetting_StorageSetting, InstanceSetting_StorageSetting_S3Config, InstanceSetting_StorageSetting_S3ConfigSchema, InstanceSetting_StorageSetting_StorageType, InstanceSetting_StorageSettingSchema, InstanceSettingSchema, } from "@/types/proto/api/v1/instance_service_pb"; import { useTranslate } from "@/utils/i18n"; import SettingGroup from "./SettingGroup"; import SettingRow from "./SettingRow"; import SettingSection from "./SettingSection"; const StorageSection = () => { const t = useTranslate(); const { storageSetting: originalSetting, updateSetting, fetchSetting } = useInstance(); const [instanceStorageSetting, setInstanceStorageSetting] = useState(originalSetting); useEffect(() => { setInstanceStorageSetting(originalSetting); }, [originalSetting]); const allowSaveStorageSetting = useMemo(() => { if (instanceStorageSetting.uploadSizeLimitMb <= 0) { return false; } if (instanceStorageSetting.storageType === InstanceSetting_StorageSetting_StorageType.LOCAL) { if (instanceStorageSetting.filepathTemplate.length === 0) { return false; } } else if (instanceStorageSetting.storageType === InstanceSetting_StorageSetting_StorageType.S3) { if ( instanceStorageSetting.s3Config?.accessKeyId.length === 0 || instanceStorageSetting.s3Config?.accessKeySecret.length === 0 || instanceStorageSetting.s3Config?.endpoint.length === 0 || instanceStorageSetting.s3Config?.region.length === 0 || instanceStorageSetting.s3Config?.bucket.length === 0 ) { return false; } } return !isEqual(originalSetting, instanceStorageSetting); }, [instanceStorageSetting, originalSetting]); const handleMaxUploadSizeChanged = async (event: React.FocusEvent) => { let num = parseInt(event.target.value); if (Number.isNaN(num)) { num = 0; } const update = create(InstanceSetting_StorageSettingSchema, { ...instanceStorageSetting, uploadSizeLimitMb: BigInt(num), }); setInstanceStorageSetting(update); }; const handleFilepathTemplateChanged = async (event: React.FocusEvent) => { const update = create(InstanceSetting_StorageSettingSchema, { ...instanceStorageSetting, filepathTemplate: event.target.value, }); setInstanceStorageSetting(update); }; const handlePartialS3ConfigChanged = async (s3Config: Partial) => { const existingS3Config = instanceStorageSetting.s3Config; const s3ConfigInit = { accessKeyId: existingS3Config?.accessKeyId ?? "", accessKeySecret: existingS3Config?.accessKeySecret ?? "", endpoint: existingS3Config?.endpoint ?? "", region: existingS3Config?.region ?? "", bucket: existingS3Config?.bucket ?? "", usePathStyle: existingS3Config?.usePathStyle ?? false, ...s3Config, }; const update = create(InstanceSetting_StorageSettingSchema, { storageType: instanceStorageSetting.storageType, filepathTemplate: instanceStorageSetting.filepathTemplate, uploadSizeLimitMb: instanceStorageSetting.uploadSizeLimitMb, s3Config: create(InstanceSetting_StorageSetting_S3ConfigSchema, s3ConfigInit), }); setInstanceStorageSetting(update); }; const handleS3ConfigAccessKeyIdChanged = async (event: React.FocusEvent) => { handlePartialS3ConfigChanged({ accessKeyId: event.target.value }); }; const handleS3ConfigAccessKeySecretChanged = async (event: React.FocusEvent) => { handlePartialS3ConfigChanged({ accessKeySecret: event.target.value }); }; const handleS3ConfigEndpointChanged = async (event: React.FocusEvent) => { handlePartialS3ConfigChanged({ endpoint: event.target.value }); }; const handleS3ConfigRegionChanged = async (event: React.FocusEvent) => { handlePartialS3ConfigChanged({ region: event.target.value }); }; const handleS3ConfigBucketChanged = async (event: React.FocusEvent) => { handlePartialS3ConfigChanged({ bucket: event.target.value }); }; const handleS3ConfigUsePathStyleChanged = (event: React.ChangeEvent) => { handlePartialS3ConfigChanged({ usePathStyle: event.target.checked, }); }; const handleStorageTypeChanged = async (storageType: InstanceSetting_StorageSetting_StorageType) => { const update = create(InstanceSetting_StorageSettingSchema, { ...instanceStorageSetting, storageType: storageType, }); setInstanceStorageSetting(update); }; const saveInstanceStorageSetting = async () => { try { await updateSetting( create(InstanceSettingSchema, { name: `instance/settings/${InstanceSetting_Key[InstanceSetting_Key.STORAGE]}`, value: { case: "storageSetting", value: instanceStorageSetting, }, }), ); await fetchSetting(InstanceSetting_Key.STORAGE); toast.success("Updated"); } catch (error: any) { toast.error(error.message); console.error(error); } }; return (
{ handleStorageTypeChanged(Number(value) as InstanceSetting_StorageSetting_StorageType); }} className="flex flex-row gap-4" >
{instanceStorageSetting.storageType !== InstanceSetting_StorageSetting_StorageType.DATABASE && ( )}
{instanceStorageSetting.storageType === InstanceSetting_StorageSetting_StorageType.S3 && ( handleS3ConfigUsePathStyleChanged({ target: { checked } } as any)} /> )}
); }; export default StorageSection;