fix(mod-queue): improve alert threshold input validation and add i18n for view selector

This commit is contained in:
plebeius
2026-01-25 16:56:48 +08:00
parent f5c3ccd1f9
commit d86637200b
36 changed files with 182 additions and 38 deletions
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "تم الإرسال",
"hours": "ساعات",
"minutes": "دقائق",
"alert_threshold": "عتبة التنبيه"
"alert_threshold": "عتبة التنبيه",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "জমা দেওয়া হয়েছে",
"hours": "ঘণ্টা",
"minutes": "মিনিট",
"alert_threshold": "সতর্কতা থ্রেশহোল্ড"
"alert_threshold": "সতর্কতা থ্রেশহোল্ড",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Odesláno",
"hours": "hodin",
"minutes": "minut",
"alert_threshold": "Práh upozornění"
"alert_threshold": "Práh upozornění",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Indsendt",
"hours": "timer",
"minutes": "minutter",
"alert_threshold": "Alarmtærskel"
"alert_threshold": "Alarmtærskel",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Eingereicht",
"hours": "Stunden",
"minutes": "Minuten",
"alert_threshold": "Alarmschwellenwert"
"alert_threshold": "Alarmschwellenwert",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Υποβλήθηκε",
"hours": "ώρες",
"minutes": "λεπτά",
"alert_threshold": "Όριο ειδοποίησης"
"alert_threshold": "Όριο ειδοποίησης",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+3
View File
@@ -263,6 +263,9 @@
"alert_threshold": "Alert threshold",
"hours": "hours",
"minutes": "minutes",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed",
"no_content": "No content",
"excerpt": "Excerpt",
"publishing": "Publishing",
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Enviado",
"hours": "horas",
"minutes": "minutos",
"alert_threshold": "Umbral de alerta"
"alert_threshold": "Umbral de alerta",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "ارسال شده",
"hours": "ساعت",
"minutes": "دقیقه",
"alert_threshold": "آستانه هشدار"
"alert_threshold": "آستانه هشدار",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Lähetetty",
"hours": "tuntia",
"minutes": "minuuttia",
"alert_threshold": "Hälytyskynnys"
"alert_threshold": "Hälytyskynnys",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Isinumite",
"hours": "oras",
"minutes": "minuto",
"alert_threshold": "Alert threshold"
"alert_threshold": "Alert threshold",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Soumis",
"hours": "heures",
"minutes": "minutes",
"alert_threshold": "Seuil d'alerte"
"alert_threshold": "Seuil d'alerte",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "נשלח",
"hours": "שעות",
"minutes": "דקות",
"alert_threshold": "סף התרעה"
"alert_threshold": "סף התרעה",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "सबमिट किया गया",
"hours": "घंटे",
"minutes": "मिनट",
"alert_threshold": "सतर्कता सीमा"
"alert_threshold": "सतर्कता सीमा",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Beküldve",
"hours": "óra",
"minutes": "perc",
"alert_threshold": "Riasztási küszöb"
"alert_threshold": "Riasztási küszöb",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Dikirim",
"hours": "jam",
"minutes": "menit",
"alert_threshold": "Ambang peringatan"
"alert_threshold": "Ambang peringatan",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Inviato",
"hours": "ore",
"minutes": "minuti",
"alert_threshold": "Soglia di allerta"
"alert_threshold": "Soglia di allerta",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "送信済み",
"hours": "時間",
"minutes": "分",
"alert_threshold": "アラート閾値"
"alert_threshold": "アラート閾値",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "제출됨",
"hours": "시간",
"minutes": "분",
"alert_threshold": "알림 임계값"
"alert_threshold": "알림 임계값",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "सबमिट केले",
"hours": "तास",
"minutes": "मिनिटे",
"alert_threshold": "सतर्कता मर्यादा"
"alert_threshold": "सतर्कता मर्यादा",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Ingediend",
"hours": "uur",
"minutes": "minuten",
"alert_threshold": "Drempelwaarde voor waarschuwing"
"alert_threshold": "Drempelwaarde voor waarschuwing",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Sendt inn",
"hours": "timer",
"minutes": "minutter",
"alert_threshold": "Terskel for varsel"
"alert_threshold": "Terskel for varsel",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Przesłane",
"hours": "godzin",
"minutes": "minut",
"alert_threshold": "Próg alertu"
"alert_threshold": "Próg alertu",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Enviado",
"hours": "horas",
"minutes": "minutos",
"alert_threshold": "Limite de alerta"
"alert_threshold": "Limite de alerta",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Trimis",
"hours": "ore",
"minutes": "minute",
"alert_threshold": "Prag de alertă"
"alert_threshold": "Prag de alertă",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Отправлено",
"hours": "часов",
"minutes": "минут",
"alert_threshold": "Порог предупреждения"
"alert_threshold": "Порог предупреждения",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Dërguar",
"hours": "orë",
"minutes": "minuta",
"alert_threshold": "Pragu i alarmit"
"alert_threshold": "Pragu i alarmit",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Inskickat",
"hours": "timmar",
"minutes": "minuter",
"alert_threshold": "Tröskelvärde för varning"
"alert_threshold": "Tröskelvärde för varning",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "సమర్పించబడింది",
"hours": "గంటలు",
"minutes": "నిమిషాలు",
"alert_threshold": "హెచ్చరిక థ్రెషోల్డ్"
"alert_threshold": "హెచ్చరిక థ్రెషోల్డ్",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "ส่งแล้ว",
"hours": "ชั่วโมง",
"minutes": "นาที",
"alert_threshold": "เกณฑ์การแจ้งเตือน"
"alert_threshold": "เกณฑ์การแจ้งเตือน",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Gönderildi",
"hours": "saat",
"minutes": "dakika",
"alert_threshold": "Uyarı eşiği"
"alert_threshold": "Uyarı eşiği",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Відправлено",
"hours": "годин",
"minutes": "хвилин",
"alert_threshold": "Поріг попередження"
"alert_threshold": "Поріг попередження",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "جمع کرایا گیا",
"hours": "گھنٹے",
"minutes": "منٹ",
"alert_threshold": "انتباہ کی حد"
"alert_threshold": "انتباہ کی حد",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "Đã gửi",
"hours": "giờ",
"minutes": "phút",
"alert_threshold": "Ngưỡng cảnh báo"
"alert_threshold": "Ngưỡng cảnh báo",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+4 -1
View File
@@ -269,5 +269,8 @@
"submitted": "已提交",
"hours": "小时",
"minutes": "分钟",
"alert_threshold": "警报阈值"
"alert_threshold": "警报阈值",
"modQueue.viewLabel": "View",
"modQueue.compact": "Compact",
"modQueue.feed": "Feed"
}
+43 -4
View File
@@ -230,10 +230,47 @@ const ImageSizeOptions = () => {
);
};
const MAX_ALERT_THRESHOLD = 10000; // Maximum threshold value in minutes (~166 hours)
const ModQueueAlertThreshold = () => {
const { t } = useTranslation();
const { alertThresholdValue, alertThresholdUnit, setAlertThreshold } = useModQueueStore();
const handleThresholdChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value.trim();
// Handle empty input - allow it temporarily for better UX
if (inputValue === '') {
return;
}
// Parse safely
const parsedValue = parseInt(inputValue, 10);
// Default to 1 if invalid or NaN
if (isNaN(parsedValue) || parsedValue < 1) {
setAlertThreshold(1, alertThresholdUnit);
return;
}
// Convert to minutes for clamping, then convert back to current unit
const valueInMinutes = alertThresholdUnit === 'hours' ? parsedValue * 60 : parsedValue;
const clampedMinutes = Math.min(valueInMinutes, MAX_ALERT_THRESHOLD);
const finalValue = alertThresholdUnit === 'hours' ? Math.round(clampedMinutes / 60) : clampedMinutes;
setAlertThreshold(finalValue, alertThresholdUnit);
};
const handleThresholdBlur = (e: React.FocusEvent<HTMLInputElement>) => {
const inputValue = e.target.value.trim();
// If empty or invalid, restore to current value or default to 1
if (inputValue === '' || isNaN(parseInt(inputValue, 10))) {
const safeValue = alertThresholdValue >= 1 ? alertThresholdValue : 1;
setAlertThreshold(safeValue, alertThresholdUnit);
}
};
return (
<div className={styles.modQueueControls}>
<label>
@@ -243,7 +280,8 @@ const ModQueueAlertThreshold = () => {
min='1'
step='1'
value={alertThresholdValue}
onChange={(e) => setAlertThreshold(Number(e.target.value), alertThresholdUnit)}
onChange={handleThresholdChange}
onBlur={handleThresholdBlur}
className={styles.alertThresholdInput}
/>
<select
@@ -268,14 +306,15 @@ const ModQueueAlertThreshold = () => {
};
const ModQueueViewSelector = () => {
const { t } = useTranslation();
const { viewMode, setViewMode } = useModQueueStore();
return (
<div className={styles.modQueueControls}>
<label>
View:
{t('modQueue.viewLabel')}:
<select value={viewMode} onChange={(e) => setViewMode(e.target.value as 'compact' | 'feed')}>
<option value='compact'>Compact</option>
<option value='feed'>Feed</option>
<option value='compact'>{t('modQueue.compact')}</option>
<option value='feed'>{t('modQueue.feed')}</option>
</select>
</label>
</div>