import { isEqual } from "lodash-es"; import { HelpCircleIcon } from "lucide-react"; import { observer } from "mobx-react-lite"; 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 { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; import { workspaceStore } from "@/store"; import { workspaceSettingNamePrefix } from "@/store/common"; import { WorkspaceSetting_Key, WorkspaceSetting_StorageSetting, WorkspaceSetting_StorageSetting_S3Config, WorkspaceSetting_StorageSetting_StorageType, } from "@/types/proto/api/v1/workspace_service"; import { useTranslate } from "@/utils/i18n"; const StorageSection = observer(() => { const t = useTranslate(); const [workspaceStorageSetting, setWorkspaceStorageSetting] = useState( WorkspaceSetting_StorageSetting.fromPartial( workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.STORAGE)?.storageSetting || {}, ), ); useEffect(() => { setWorkspaceStorageSetting( WorkspaceSetting_StorageSetting.fromPartial( workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.STORAGE)?.storageSetting || {}, ), ); }, [workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.STORAGE)]); const allowSaveStorageSetting = useMemo(() => { if (workspaceStorageSetting.uploadSizeLimitMb <= 0) { return false; } const origin = WorkspaceSetting_StorageSetting.fromPartial( workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.STORAGE)?.storageSetting || {}, ); if (workspaceStorageSetting.storageType === WorkspaceSetting_StorageSetting_StorageType.LOCAL) { if (workspaceStorageSetting.filepathTemplate.length === 0) { return false; } } else if (workspaceStorageSetting.storageType === WorkspaceSetting_StorageSetting_StorageType.S3) { if ( workspaceStorageSetting.s3Config?.accessKeyId.length === 0 || workspaceStorageSetting.s3Config?.accessKeySecret.length === 0 || workspaceStorageSetting.s3Config?.endpoint.length === 0 || workspaceStorageSetting.s3Config?.region.length === 0 || workspaceStorageSetting.s3Config?.bucket.length === 0 ) { return false; } } return !isEqual(origin, workspaceStorageSetting); }, [workspaceStorageSetting, workspaceStore.state]); const handleMaxUploadSizeChanged = async (event: React.FocusEvent) => { let num = parseInt(event.target.value); if (Number.isNaN(num)) { num = 0; } const update: WorkspaceSetting_StorageSetting = { ...workspaceStorageSetting, uploadSizeLimitMb: num, }; setWorkspaceStorageSetting(update); }; const handleFilepathTemplateChanged = async (event: React.FocusEvent) => { const update: WorkspaceSetting_StorageSetting = { ...workspaceStorageSetting, filepathTemplate: event.target.value, }; setWorkspaceStorageSetting(update); }; const handlePartialS3ConfigChanged = async (s3Config: Partial) => { const update: WorkspaceSetting_StorageSetting = { ...workspaceStorageSetting, s3Config: WorkspaceSetting_StorageSetting_S3Config.fromPartial({ ...workspaceStorageSetting.s3Config, ...s3Config, }), }; setWorkspaceStorageSetting(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: WorkspaceSetting_StorageSetting_StorageType) => { const update: WorkspaceSetting_StorageSetting = { ...workspaceStorageSetting, storageType: storageType, }; setWorkspaceStorageSetting(update); }; const saveWorkspaceStorageSetting = async () => { await workspaceStore.upsertWorkspaceSetting({ name: `${workspaceSettingNamePrefix}${WorkspaceSetting_Key.STORAGE}`, storageSetting: workspaceStorageSetting, }); toast.success("Updated"); }; return (
{t("setting.storage-section.current-storage")}
{ handleStorageTypeChanged(value as WorkspaceSetting_StorageSetting_StorageType); }} className="flex flex-row gap-4" >
{t("setting.system-section.max-upload-size")}

{t("setting.system-section.max-upload-size-hint")}

{workspaceStorageSetting.storageType !== WorkspaceSetting_StorageSetting_StorageType.DATABASE && (
{t("setting.storage-section.filepath-template")}
)} {workspaceStorageSetting.storageType === WorkspaceSetting_StorageSetting_StorageType.S3 && ( <>
Access key id
Access key secret
Endpoint
Region
Bucket
Use Path Style handleS3ConfigUsePathStyleChanged({ target: { checked } } as any)} />
)}
{t("setting.storage-section.use-thumbnails-for-s3-images")} setWorkspaceStorageSetting({ ...workspaceStorageSetting, useThumbnailsForS3Images: checked, }) } />
); }); export default StorageSection;