mirror of
https://github.com/kyantech/Palmr.git
synced 2025-11-03 05:23:19 +00:00
feat: implement file size input component and update settings configuration
- Added a new FileSizeInput component to handle file size configurations in a user-friendly manner. - Updated SettingsInput to integrate the FileSizeInput for maxFileSize and maxTotalStoragePerUser settings. - Revised environment schema to remove MAX_FILESIZE validation, ensuring flexibility in configuration. - Adjusted localization files to remove byte references in descriptions for clarity across multiple languages.
This commit is contained in:
@@ -39,7 +39,7 @@ const defaultConfigs = [
|
|||||||
// Storage Configurations
|
// Storage Configurations
|
||||||
{
|
{
|
||||||
key: "maxFileSize",
|
key: "maxFileSize",
|
||||||
value: process.env.MAX_FILESIZE || "1073741824", // default 1GiB in bytes
|
value: "1073741824", // default 1GiB in bytes
|
||||||
type: "bigint",
|
type: "bigint",
|
||||||
group: "storage",
|
group: "storage",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ const envSchema = z.object({
|
|||||||
S3_REGION: z.string().optional(),
|
S3_REGION: z.string().optional(),
|
||||||
S3_BUCKET_NAME: z.string().optional(),
|
S3_BUCKET_NAME: z.string().optional(),
|
||||||
S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"),
|
S3_FORCE_PATH_STYLE: z.union([z.literal("true"), z.literal("false")]).default("false"),
|
||||||
MAX_FILESIZE: z.string().min(1),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const env = envSchema.parse(process.env);
|
export const env = envSchema.parse(process.env);
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "أقصى حجم للملف",
|
"title": "أقصى حجم للملف",
|
||||||
"description": "الحد الأقصى لحجم الملف المسموح به للرفع (بالبايت)"
|
"description": "الحد الأقصى لحجم الملف المسموح به للرفع "
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "أقصى تخزين لكل مستخدم",
|
"title": "أقصى تخزين لكل مستخدم",
|
||||||
"description": "الحد الإجمالي للتخزين لكل مستخدم (بالبايت)"
|
"description": "الحد الإجمالي للتخزين لكل مستخدم "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Maximale Dateigröße",
|
"title": "Maximale Dateigröße",
|
||||||
"description": "Maximal erlaubte Dateigröße für Uploads (in Bytes)"
|
"description": "Maximal erlaubte Dateigröße für Uploads"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Maximaler Speicher pro Benutzer",
|
"title": "Maximaler Speicher pro Benutzer",
|
||||||
"description": "Gesamtspeicherlimit pro Benutzer (in Bytes)"
|
"description": "Gesamtspeicherlimit pro Benutzer"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Maximum File Size",
|
"title": "Maximum File Size",
|
||||||
"description": "Maximum allowed file size for uploads (in bytes)"
|
"description": "Maximum allowed file size for uploads"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Maximum Storage Per User",
|
"title": "Maximum Storage Per User",
|
||||||
"description": "Total storage limit per user (in bytes)"
|
"description": "Total storage limit per user"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Tamaño máximo de archivo",
|
"title": "Tamaño máximo de archivo",
|
||||||
"description": "Tamaño máximo permitido para subir archivos (en bytes)"
|
"description": "Tamaño máximo permitido para subir archivos"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Almacenamiento máximo por usuario",
|
"title": "Almacenamiento máximo por usuario",
|
||||||
"description": "Límite total de almacenamiento por usuario (en bytes)"
|
"description": "Límite total de almacenamiento por usuario"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -402,11 +402,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Taille Maximale de Fichier",
|
"title": "Taille Maximale de Fichier",
|
||||||
"description": "Taille maximale autorisée pour les fichiers (en octets)"
|
"description": "Taille maximale autorisée pour les fichiers"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Stockage Maximum par Utilisateur",
|
"title": "Stockage Maximum par Utilisateur",
|
||||||
"description": "Limite totale de stockage par utilisateur (en octets)"
|
"description": "Limite totale de stockage par utilisateur"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "अधिकतम फाइल आकार",
|
"title": "अधिकतम फाइल आकार",
|
||||||
"description": "अपलोड के लिए अधिकतम अनुमत फाइल आकार (बाइट में)"
|
"description": "अपलोड के लिए अधिकतम अनुमत फाइल आकार"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "प्रति उपयोगकर्ता अधिकतम स्टोरेज",
|
"title": "प्रति उपयोगकर्ता अधिकतम स्टोरेज",
|
||||||
"description": "प्रति उपयोगकर्ता कुल स्टोरेज सीमा (बाइट में)"
|
"description": "प्रति उपयोगकर्ता कुल स्टोरेज सीमा"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Dimensione Massima File",
|
"title": "Dimensione Massima File",
|
||||||
"description": "Dimensione massima consentita per i caricamenti (in byte)"
|
"description": "Dimensione massima consentita per i caricamenti"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Archiviazione Massima per Utente",
|
"title": "Archiviazione Massima per Utente",
|
||||||
"description": "Limite totale di archiviazione per utente (in byte)"
|
"description": "Limite totale di archiviazione per utente"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "最大ファイルサイズ",
|
"title": "最大ファイルサイズ",
|
||||||
"description": "アップロード可能な最大ファイルサイズ(バイト単位)"
|
"description": "アップロード可能な最大ファイルサイズ"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "ユーザーごとの最大ストレージ",
|
"title": "ユーザーごとの最大ストレージ",
|
||||||
"description": "ユーザーごとの総ストレージ制限(バイト単位)"
|
"description": "ユーザーごとの総ストレージ制限"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "최대 파일 크기",
|
"title": "최대 파일 크기",
|
||||||
"description": "업로드 가능한 최대 파일 크기(바이트 단위)"
|
"description": "업로드 가능한 최대 파일 크기"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "사용자당 최대 스토리지",
|
"title": "사용자당 최대 스토리지",
|
||||||
"description": "사용자당 총 스토리지 제한(바이트 단위)"
|
"description": "사용자당 총 스토리지 제한"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Maximum Bestandsgrootte",
|
"title": "Maximum Bestandsgrootte",
|
||||||
"description": "Maximum toegestane bestandsgrootte voor uploads (in bytes)"
|
"description": "Maximum toegestane bestandsgrootte voor uploads"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Maximum Opslag Per Gebruiker",
|
"title": "Maximum Opslag Per Gebruiker",
|
||||||
"description": "Totale opslaglimiet per gebruiker (in bytes)"
|
"description": "Totale opslaglimiet per gebruiker"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Tamanho Máximo do Arquivo",
|
"title": "Tamanho Máximo do Arquivo",
|
||||||
"description": "Tamanho máximo permitido para uploads (em bytes)"
|
"description": "Tamanho máximo permitido para uploads"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Armazenamento Máximo por Usuário",
|
"title": "Armazenamento Máximo por Usuário",
|
||||||
"description": "Limite total de armazenamento por usuário (em bytes)"
|
"description": "Limite total de armazenamento por usuário"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Максимальный размер файла",
|
"title": "Максимальный размер файла",
|
||||||
"description": "Максимальный размер файла для загрузки (в байтах)"
|
"description": "Максимальный размер файла для загрузки"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Максимальное хранилище для пользователя",
|
"title": "Максимальное хранилище для пользователя",
|
||||||
"description": "Общий лимит хранилища для каждого пользователя (в байтах)"
|
"description": "Общий лимит хранилища для каждого пользователя"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "Maksimum Dosya Boyutu",
|
"title": "Maksimum Dosya Boyutu",
|
||||||
"description": "Yüklemeye izin verilen maksimum dosya boyutu (bayt cinsinden)"
|
"description": "Yüklemeye izin verilen maksimum dosya boyutu"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "Kullanıcı Başına Maksimum Depolama",
|
"title": "Kullanıcı Başına Maksimum Depolama",
|
||||||
"description": "Kullanıcı başına toplam depolama sınırı (bayt cinsinden)"
|
"description": "Kullanıcı başına toplam depolama sınırı"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
@@ -399,11 +399,11 @@
|
|||||||
},
|
},
|
||||||
"maxFileSize": {
|
"maxFileSize": {
|
||||||
"title": "最大文件大小",
|
"title": "最大文件大小",
|
||||||
"description": "允许上传的最大文件大小(以字节为单位)"
|
"description": "允许上传的最大文件大小"
|
||||||
},
|
},
|
||||||
"maxTotalStoragePerUser": {
|
"maxTotalStoragePerUser": {
|
||||||
"title": "每个用户的最大存储量",
|
"title": "每个用户的最大存储量",
|
||||||
"description": "每个用户的总存储限制(以字节为单位)"
|
"description": "每个用户的总存储限制"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
|
|||||||
142
apps/web/src/app/settings/components/file-size-input.tsx
Normal file
142
apps/web/src/app/settings/components/file-size-input.tsx
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
|
||||||
|
export interface FileSizeInputProps {
|
||||||
|
value: string; // valor em bytes
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
error?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Unit = "MB" | "GB" | "TB";
|
||||||
|
|
||||||
|
const UNIT_MULTIPLIERS: Record<Unit, number> = {
|
||||||
|
MB: 1024 * 1024,
|
||||||
|
GB: 1024 * 1024 * 1024,
|
||||||
|
TB: 1024 * 1024 * 1024 * 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
function bytesToHumanReadable(bytes: string): { value: string; unit: Unit } {
|
||||||
|
const numBytes = parseInt(bytes, 10);
|
||||||
|
|
||||||
|
// Se for 0 ou inválido, retorna 0 GB
|
||||||
|
if (!numBytes || numBytes <= 0) {
|
||||||
|
return { value: "0", unit: "GB" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica TB (com tolerância para valores próximos)
|
||||||
|
if (numBytes >= UNIT_MULTIPLIERS.TB) {
|
||||||
|
const tbValue = numBytes / UNIT_MULTIPLIERS.TB;
|
||||||
|
if (tbValue === Math.floor(tbValue)) {
|
||||||
|
return {
|
||||||
|
value: tbValue.toString(),
|
||||||
|
unit: "TB",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica GB (com tolerância para valores próximos)
|
||||||
|
if (numBytes >= UNIT_MULTIPLIERS.GB) {
|
||||||
|
const gbValue = numBytes / UNIT_MULTIPLIERS.GB;
|
||||||
|
if (gbValue === Math.floor(gbValue)) {
|
||||||
|
return {
|
||||||
|
value: gbValue.toString(),
|
||||||
|
unit: "GB",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verifica MB
|
||||||
|
if (numBytes >= UNIT_MULTIPLIERS.MB) {
|
||||||
|
const mbValue = numBytes / UNIT_MULTIPLIERS.MB;
|
||||||
|
return {
|
||||||
|
value: mbValue === Math.floor(mbValue) ? mbValue.toString() : mbValue.toFixed(2),
|
||||||
|
unit: "MB",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Para valores menores que 1MB, converte para MB com decimais
|
||||||
|
const mbValue = numBytes / UNIT_MULTIPLIERS.MB;
|
||||||
|
return {
|
||||||
|
value: mbValue.toFixed(3),
|
||||||
|
unit: "MB",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function humanReadableToBytes(value: string, unit: Unit): string {
|
||||||
|
const numValue = parseFloat(value);
|
||||||
|
if (isNaN(numValue) || numValue <= 0) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.floor(numValue * UNIT_MULTIPLIERS[unit]).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FileSizeInput({ value, onChange, disabled = false, error }: FileSizeInputProps) {
|
||||||
|
const [displayValue, setDisplayValue] = useState("");
|
||||||
|
const [selectedUnit, setSelectedUnit] = useState<Unit>("GB");
|
||||||
|
|
||||||
|
// Inicializar os valores quando o componente monta ou o value muda
|
||||||
|
useEffect(() => {
|
||||||
|
if (value && value !== "0") {
|
||||||
|
const { value: humanValue, unit } = bytesToHumanReadable(value);
|
||||||
|
setDisplayValue(humanValue);
|
||||||
|
setSelectedUnit(unit);
|
||||||
|
} else {
|
||||||
|
setDisplayValue("");
|
||||||
|
setSelectedUnit("GB");
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
const handleValueChange = (newValue: string) => {
|
||||||
|
// Só permitir números e ponto decimal
|
||||||
|
const sanitizedValue = newValue.replace(/[^0-9.]/g, "");
|
||||||
|
|
||||||
|
// Prevenir múltiplos pontos decimais
|
||||||
|
const parts = sanitizedValue.split(".");
|
||||||
|
const finalValue = parts.length > 2 ? parts[0] + "." + parts.slice(1).join("") : sanitizedValue;
|
||||||
|
|
||||||
|
setDisplayValue(finalValue);
|
||||||
|
|
||||||
|
if (finalValue === "" || finalValue === "0") {
|
||||||
|
onChange("0");
|
||||||
|
} else {
|
||||||
|
const bytesValue = humanReadableToBytes(finalValue, selectedUnit);
|
||||||
|
onChange(bytesValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUnitChange = (newUnit: Unit) => {
|
||||||
|
setSelectedUnit(newUnit);
|
||||||
|
|
||||||
|
if (displayValue && displayValue !== "0") {
|
||||||
|
const bytesValue = humanReadableToBytes(displayValue, newUnit);
|
||||||
|
onChange(bytesValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={displayValue}
|
||||||
|
onChange={(e) => handleValueChange(e.target.value)}
|
||||||
|
placeholder="0"
|
||||||
|
className="flex-1"
|
||||||
|
disabled={disabled}
|
||||||
|
aria-invalid={!!error}
|
||||||
|
/>
|
||||||
|
<select
|
||||||
|
value={selectedUnit}
|
||||||
|
onChange={(e) => handleUnitChange(e.target.value as Unit)}
|
||||||
|
className="w-20 rounded-md border border-input bg-transparent px-3 py-2 text-sm"
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<option value="MB">MB</option>
|
||||||
|
<option value="GB">GB</option>
|
||||||
|
<option value="TB">TB</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -52,6 +52,7 @@ export function SettingsGroup({ group, configs, form, isCollapsed, onToggleColla
|
|||||||
config={config}
|
config={config}
|
||||||
error={form.formState.errors.configs?.[config.key]}
|
error={form.formState.errors.configs?.[config.key]}
|
||||||
register={form.register}
|
register={form.register}
|
||||||
|
setValue={form.setValue}
|
||||||
smtpEnabled={form.watch("configs.smtpEnabled")}
|
smtpEnabled={form.watch("configs.smtpEnabled")}
|
||||||
watch={form.watch}
|
watch={form.watch}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { UseFormRegister, UseFormWatch } from "react-hook-form";
|
import { UseFormRegister, UseFormSetValue, UseFormWatch } from "react-hook-form";
|
||||||
|
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { createFieldTitles } from "../constants";
|
import { createFieldTitles } from "../constants";
|
||||||
import { Config } from "../types";
|
import { Config } from "../types";
|
||||||
|
import { FileSizeInput } from "./file-size-input";
|
||||||
import { LogoInput } from "./logo-input";
|
import { LogoInput } from "./logo-input";
|
||||||
|
|
||||||
export interface ConfigInputProps {
|
export interface ConfigInputProps {
|
||||||
config: Config;
|
config: Config;
|
||||||
register: UseFormRegister<any>;
|
register: UseFormRegister<any>;
|
||||||
watch: UseFormWatch<any>;
|
watch: UseFormWatch<any>;
|
||||||
|
setValue: UseFormSetValue<any>;
|
||||||
error?: any;
|
error?: any;
|
||||||
smtpEnabled?: string;
|
smtpEnabled?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SettingsInput({ config, register, watch, error, smtpEnabled }: ConfigInputProps) {
|
export function SettingsInput({ config, register, watch, setValue, error, smtpEnabled }: ConfigInputProps) {
|
||||||
const t = useTranslations();
|
const t = useTranslations();
|
||||||
const FIELD_TITLES = createFieldTitles(t);
|
const FIELD_TITLES = createFieldTitles(t);
|
||||||
const isSmtpField = config.group === "email" && config.key !== "smtpEnabled";
|
const isSmtpField = config.group === "email" && config.key !== "smtpEnabled";
|
||||||
@@ -31,9 +33,7 @@ export function SettingsInput({ config, register, watch, error, smtpEnabled }: C
|
|||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
register(`configs.${config.key}`).onChange({
|
setValue(`configs.${config.key}`, value, { shouldDirty: true });
|
||||||
target: { value },
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{error && <p className="text-danger text-xs mt-1">{error.message}</p>}
|
{error && <p className="text-danger text-xs mt-1">{error.message}</p>}
|
||||||
@@ -41,6 +41,26 @@ export function SettingsInput({ config, register, watch, error, smtpEnabled }: C
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special input for file size configurations
|
||||||
|
if (config.key === "maxFileSize" || config.key === "maxTotalStoragePerUser") {
|
||||||
|
const value = watch(`configs.${config.key}`);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-2">
|
||||||
|
<label className="block text-sm font-semibold">{friendlyLabel}</label>
|
||||||
|
<FileSizeInput
|
||||||
|
value={value || "0"}
|
||||||
|
onChange={(value) => {
|
||||||
|
setValue(`configs.${config.key}`, value, { shouldDirty: true });
|
||||||
|
}}
|
||||||
|
disabled={isDisabled}
|
||||||
|
error={error}
|
||||||
|
/>
|
||||||
|
{error && <p className="text-danger text-xs mt-1">{error.message}</p>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export interface SettingsGroupProps {
|
|||||||
export interface ConfigInputProps {
|
export interface ConfigInputProps {
|
||||||
config: Config;
|
config: Config;
|
||||||
register: UseFormReturn<any>["register"];
|
register: UseFormReturn<any>["register"];
|
||||||
|
setValue: UseFormReturn<any>["setValue"];
|
||||||
error?: any;
|
error?: any;
|
||||||
smtpEnabled?: string;
|
smtpEnabled?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user