feat(web): add data retention settings to admin UI

This commit is contained in:
SnapOtter
2026-06-13 16:39:22 +08:00
parent 2520cdd556
commit 3016571c2b
22 changed files with 256 additions and 0 deletions
@@ -686,6 +686,52 @@ function SystemSection() {
</button>
</SettingRow>
<div className="pt-4 border-t border-border">
<h4 className="text-sm font-semibold text-foreground mb-3">
{t.settings.dataRetention.title}
</h4>
</div>
<SettingRow
label={t.settings.dataRetention.fileMaxAgeHours}
description={t.settings.dataRetention.fileMaxAgeHoursDesc}
>
<input
type="number"
value={settings.tempFileMaxAgeHours || "72"}
onChange={(e) => updateSetting("tempFileMaxAgeHours", e.target.value)}
aria-label={t.settings.dataRetention.fileMaxAgeHours}
className="px-3 py-1.5 rounded-lg border border-border bg-background text-sm text-foreground w-24"
min={1}
max={8760}
/>
</SettingRow>
<SettingRow
label={t.settings.dataRetention.jobsRetentionDays}
description={t.settings.dataRetention.jobsRetentionDaysDesc}
>
<input
type="number"
value={settings.jobsRetentionDays || "30"}
onChange={(e) => updateSetting("jobsRetentionDays", e.target.value)}
aria-label={t.settings.dataRetention.jobsRetentionDays}
className="px-3 py-1.5 rounded-lg border border-border bg-background text-sm text-foreground w-24"
min={0}
/>
</SettingRow>
<SettingRow
label={t.settings.dataRetention.auditRetentionDays}
description={t.settings.dataRetention.auditRetentionDaysDesc}
>
<input
type="number"
value={settings.auditRetentionDays || "0"}
onChange={(e) => updateSetting("auditRetentionDays", e.target.value)}
aria-label={t.settings.dataRetention.auditRetentionDays}
className="px-3 py-1.5 rounded-lg border border-border bg-background text-sm text-foreground w-24"
min={0}
/>
</SettingRow>
<div className="flex items-center gap-3 pt-2">
<button
type="button"
+10
View File
@@ -2913,6 +2913,16 @@ export const ar: TranslationKeys = {
startupCleanup: "تنظيف عند بدء التشغيل",
startupCleanupDescription: "تنظيف الملفات المؤقتة القديمة عند بدء تشغيل الخادم",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "تحليلات المنتج",
description: "مشاركة بيانات الاستخدام المجهولة للمساعدة في تحسين SnapOtter.",
+10
View File
@@ -2938,6 +2938,16 @@ export const de: TranslationKeys = {
startupCleanup: "Bereinigung beim Start",
startupCleanupDescription: "Alte temporaere Dateien beim Serverstart bereinigen",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Produktanalytik",
description: "Anonyme Nutzungsdaten teilen, um SnapOtter zu verbessern.",
+10
View File
@@ -2897,6 +2897,16 @@ export const en = {
startupCleanup: "Startup Cleanup",
startupCleanupDescription: "Clean up old temporary files when the server starts",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Product Analytics",
description: "Share anonymous usage data to help improve SnapOtter.",
+10
View File
@@ -2916,6 +2916,16 @@ export const es: TranslationKeys = {
startupCleanup: "Limpieza al inicio",
startupCleanupDescription: "Limpia archivos temporales antiguos cuando el servidor arranca",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analitica del producto",
description: "Comparte datos de uso anonimos para ayudar a mejorar SnapOtter.",
+10
View File
@@ -2936,6 +2936,16 @@ export const fr: TranslationKeys = {
startupCleanup: "Nettoyage au demarrage",
startupCleanupDescription: "Nettoie les anciens fichiers temporaires au demarrage du serveur",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analytique produit",
description: "Partagez des donnees d'utilisation anonymes pour aider a ameliorer SnapOtter.",
+10
View File
@@ -2909,6 +2909,16 @@ export const hi: TranslationKeys = {
startupCleanup: "स्टार्टअप क्लीनअप",
startupCleanupDescription: "सर्वर शुरू होने पर पुरानी अस्थायी फाइलें साफ करें",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "प्रोडक्ट एनालिटिक्स",
description: "SnapOtter को बेहतर बनाने में मदद के लिए गुमनाम उपयोग डेटा शेयर करें।",
+10
View File
@@ -2925,6 +2925,16 @@ export const id: TranslationKeys = {
startupCleanup: "Pembersihan Saat Startup",
startupCleanupDescription: "Bersihkan file sementara lama saat server dimulai",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analitik Produk",
description: "Bagikan data penggunaan anonim untuk membantu meningkatkan SnapOtter.",
+10
View File
@@ -2930,6 +2930,16 @@ export const it: TranslationKeys = {
startupCleanup: "Pulizia all'avvio",
startupCleanupDescription: "Pulisce i vecchi file temporanei all'avvio del server",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analisi del prodotto",
description: "Condividi dati di utilizzo anonimi per contribuire a migliorare SnapOtter.",
+10
View File
@@ -2882,6 +2882,16 @@ export const ja: TranslationKeys = {
startupCleanup: "起動時クリーンアップ",
startupCleanupDescription: "サーバー起動時に古い一時ファイルをクリーンアップ",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "プロダクト分析",
description: "匿名の使用データを共有してSnapOtterの改善にご協力ください。",
+10
View File
@@ -2867,6 +2867,16 @@ export const ko: TranslationKeys = {
startupCleanup: "시작 시 정리",
startupCleanupDescription: "서버 시작 시 오래된 임시 파일 정리",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "제품 분석",
description: "익명 사용 데이터를 공유하여 SnapOtter 개선에 도움을 주세요.",
+10
View File
@@ -2928,6 +2928,16 @@ export const nl: TranslationKeys = {
startupCleanup: "Opruimen bij opstarten",
startupCleanupDescription: "Oude tijdelijke bestanden opruimen wanneer de server start",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Productanalyse",
description: "Deel anonieme gebruiksgegevens om SnapOtter te verbeteren.",
+10
View File
@@ -2934,6 +2934,16 @@ export const pl: TranslationKeys = {
startupCleanup: "Czyszczenie przy uruchomieniu",
startupCleanupDescription: "Usuwanie starych plików tymczasowych przy uruchomieniu serwera",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analityka",
description: "Udostępnianie anonimowych danych o użytkowaniu w celu ulepszenia SnapOtter.",
+10
View File
@@ -2927,6 +2927,16 @@ export const ptBR: TranslationKeys = {
startupCleanup: "Limpeza na inicializacao",
startupCleanupDescription: "Limpa arquivos temporarios antigos quando o servidor inicia",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Analitica do produto",
description: "Compartilhe dados de uso anonimos para ajudar a melhorar o SnapOtter.",
+10
View File
@@ -2927,6 +2927,16 @@ export const ru: TranslationKeys = {
startupCleanup: "Очистка при запуске",
startupCleanupDescription: "Удалять старые временные файлы при запуске сервера",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Аналитика",
description: "Отправка анонимных данных об использовании для улучшения SnapOtter.",
+10
View File
@@ -2923,6 +2923,16 @@ export const sv: TranslationKeys = {
startupCleanup: "Rensning vid start",
startupCleanupDescription: "Rensa gamla temporara filer nar servern startar",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Produktanalys",
description: "Dela anonym anvandningsdata for att forbaattra SnapOtter.",
+10
View File
@@ -2901,6 +2901,16 @@ export const th: TranslationKeys = {
startupCleanup: "ล้างตอนเริ่มต้น",
startupCleanupDescription: "ล้างไฟล์ชั่วคราวเก่าเมื่อเซิร์ฟเวอร์เริ่มทำงาน",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "การวิเคราะห์ผลิตภัณฑ์",
description: "แบ่งปันข้อมูลการใช้งานแบบไม่ระบุตัวตนเพื่อช่วยปรับปรุง SnapOtter",
+10
View File
@@ -2930,6 +2930,16 @@ export const tr: TranslationKeys = {
startupCleanup: "Başlangıç Temizliği",
startupCleanupDescription: "Sunucu başladığında eski geçici dosyaları temizle",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Ürün Analitiği",
description:
+10
View File
@@ -2927,6 +2927,16 @@ export const uk: TranslationKeys = {
startupCleanup: "Очищення при запуску",
startupCleanupDescription: "Видаляти старі тимчасові файли при запуску сервера",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Аналітика",
description: "Надсилання анонімних даних про використання для поліпшення SnapOtter.",
+10
View File
@@ -2923,6 +2923,16 @@ export const vi: TranslationKeys = {
startupCleanup: "Dọn dẹp khi khởi động",
startupCleanupDescription: "Dọn dẹp tệp tạm cũ khi máy chủ khởi động",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "Phân tích sản phẩm",
description: "Chia sẻ dữ liệu sử dụng ẩn danh để giúp cải thiện SnapOtter.",
+10
View File
@@ -2853,6 +2853,16 @@ export const zhCN: TranslationKeys = {
startupCleanup: "启动时清理",
startupCleanupDescription: "服务器启动时清理旧的临时文件",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "产品分析",
description: "分享匿名使用数据,帮助改进 SnapOtter。",
+10
View File
@@ -2851,6 +2851,16 @@ export const zhTW: TranslationKeys = {
startupCleanup: "啟動清理",
startupCleanupDescription: "伺服器啟動時清理舊的暫存檔案",
},
dataRetention: {
title: "Data Retention",
fileMaxAgeHours: "Processing file retention (hours)",
fileMaxAgeHoursDesc: "How long to keep uploaded and processed files. Default: 72 hours.",
jobsRetentionDays: "Job record retention (days)",
jobsRetentionDaysDesc: "How long to keep job metadata. 0 = keep forever. Default: 30 days.",
auditRetentionDays: "Audit log retention (days)",
auditRetentionDaysDesc:
"How long to keep audit log entries. 0 = keep forever. Default: forever.",
},
analytics: {
heading: "產品分析",
description: "分享匿名使用資料以協助改進SnapOtter。",