mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
feat: implement mod queue
This commit is contained in:
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "حساب Bitsocial",
|
"bitsocial_account": "حساب Bitsocial",
|
||||||
"p2p_options": "خيارات P2P",
|
"p2p_options": "خيارات P2P",
|
||||||
"purge": "حذف نهائي",
|
"purge": "حذف نهائي",
|
||||||
"purge_confirm": "سيؤدي الحذف النهائي إلى إزالة هذا المحتوى وجميع الردود عليه من قاعدة البيانات بشكل دائم. متابعة؟"
|
"purge_confirm": "سيؤدي الحذف النهائي إلى إزالة هذا المحتوى وجميع الردود عليه من قاعدة البيانات بشكل دائم. متابعة؟",
|
||||||
|
"mod_queue": "قائمة انتظار الإشراف",
|
||||||
|
"moderation_queue": "قائمة انتظار الإشراف",
|
||||||
|
"queue_is_empty": "قائمة الانتظار فارغة",
|
||||||
|
"approve": "الموافقة",
|
||||||
|
"reject": "الرفض",
|
||||||
|
"waiting": "في الانتظار",
|
||||||
|
"filter_by_board": "تصفية حسب اللوحة",
|
||||||
|
"mod_queue_alert_threshold": "عتبة تنبيه قائمة انتظار الإشراف",
|
||||||
|
"mod_queue_alert_threshold_tip": "إظهار مؤشر أحمر وامض عندما تكون العناصر في الانتظار لأكثر من هذا الوقت",
|
||||||
|
"no_content": "لا يوجد محتوى",
|
||||||
|
"view": "عرض",
|
||||||
|
"excerpt": "مقتطف"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial অ্যাকাউন্ট",
|
"bitsocial_account": "Bitsocial অ্যাকাউন্ট",
|
||||||
"p2p_options": "P2P বিকল্প",
|
"p2p_options": "P2P বিকল্প",
|
||||||
"purge": "সর্বনাশ",
|
"purge": "সর্বনাশ",
|
||||||
"purge_confirm": "পার্জ করা এই সামগ্রী এবং এর সমস্ত উত্তরকে ডাটাবেস থেকে স্থায়ীভাবে সরিয়ে দেবে। চালিয়ে যান?"
|
"purge_confirm": "পার্জ করা এই সামগ্রী এবং এর সমস্ত উত্তরকে ডাটাবেস থেকে স্থায়ীভাবে সরিয়ে দেবে। চালিয়ে যান?",
|
||||||
|
"mod_queue": "মডারেশন সারি",
|
||||||
|
"moderation_queue": "মডারেশন সারি",
|
||||||
|
"queue_is_empty": "সারি খালি",
|
||||||
|
"approve": "অনুমোদন করুন",
|
||||||
|
"reject": "প্রত্যাখ্যান করুন",
|
||||||
|
"waiting": "অপেক্ষা করছে",
|
||||||
|
"filter_by_board": "বোর্ড অনুযায়ী ফিল্টার করুন",
|
||||||
|
"mod_queue_alert_threshold": "মডারেশন সারি সতর্কতা থ্রেশহোল্ড",
|
||||||
|
"mod_queue_alert_threshold_tip": "আইটেমগুলি এই সময়ের চেয়ে বেশি অপেক্ষা করলে একটি ঝলমলে লাল সূচক দেখান",
|
||||||
|
"no_content": "কোনো বিষয়বস্তু নেই",
|
||||||
|
"view": "দেখুন",
|
||||||
|
"excerpt": "উদ্ধৃতি"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Účet Bitsocial",
|
"bitsocial_account": "Účet Bitsocial",
|
||||||
"p2p_options": "Možnosti P2P",
|
"p2p_options": "Možnosti P2P",
|
||||||
"purge": "vymazat",
|
"purge": "vymazat",
|
||||||
"purge_confirm": "Vymazání trvale odstraní tento obsah a všechny jeho odpovědi z databáze. Pokračovat?"
|
"purge_confirm": "Vymazání trvale odstraní tento obsah a všechny jeho odpovědi z databáze. Pokračovat?",
|
||||||
|
"mod_queue": "Fronta moderování",
|
||||||
|
"moderation_queue": "Fronta moderování",
|
||||||
|
"queue_is_empty": "Fronta je prázdná",
|
||||||
|
"approve": "Schválit",
|
||||||
|
"reject": "Odmítnout",
|
||||||
|
"waiting": "Čeká",
|
||||||
|
"filter_by_board": "Filtrovat podle desky",
|
||||||
|
"mod_queue_alert_threshold": "Práh upozornění fronty moderování",
|
||||||
|
"mod_queue_alert_threshold_tip": "Zobrazit blikající červený indikátor, když položky čekají déle než tento čas",
|
||||||
|
"no_content": "Žádný obsah",
|
||||||
|
"view": "Zobrazit",
|
||||||
|
"excerpt": "Výňatek"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-konto",
|
"bitsocial_account": "Bitsocial-konto",
|
||||||
"p2p_options": "P2P-indstillinger",
|
"p2p_options": "P2P-indstillinger",
|
||||||
"purge": "slet",
|
"purge": "slet",
|
||||||
"purge_confirm": "Sletning fjerner permanent dette indhold og alle dets svar fra databasen. Fortsætte?"
|
"purge_confirm": "Sletning fjerner permanent dette indhold og alle dets svar fra databasen. Fortsætte?",
|
||||||
|
"mod_queue": "Moderationskø",
|
||||||
|
"moderation_queue": "Moderationskø",
|
||||||
|
"queue_is_empty": "Køen er tom",
|
||||||
|
"approve": "Godkend",
|
||||||
|
"reject": "Afvis",
|
||||||
|
"waiting": "Venter",
|
||||||
|
"filter_by_board": "Filtrer efter tavle",
|
||||||
|
"mod_queue_alert_threshold": "Tærskel for moderationskø-alarm",
|
||||||
|
"mod_queue_alert_threshold_tip": "Vis en blinkende rød indikator, når elementer venter længere end denne tid",
|
||||||
|
"no_content": "Intet indhold",
|
||||||
|
"view": "Vis",
|
||||||
|
"excerpt": "Uddrag"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-Konto",
|
"bitsocial_account": "Bitsocial-Konto",
|
||||||
"p2p_options": "P2P-Optionen",
|
"p2p_options": "P2P-Optionen",
|
||||||
"purge": "löschen",
|
"purge": "löschen",
|
||||||
"purge_confirm": "Das Löschen entfernt diesen Inhalt und alle Antworten dauerhaft aus der Datenbank. Fortfahren?"
|
"purge_confirm": "Das Löschen entfernt diesen Inhalt und alle Antworten dauerhaft aus der Datenbank. Fortfahren?",
|
||||||
|
"mod_queue": "Moderations-Warteschlange",
|
||||||
|
"moderation_queue": "Moderations-Warteschlange",
|
||||||
|
"queue_is_empty": "Warteschlange ist leer",
|
||||||
|
"approve": "Genehmigen",
|
||||||
|
"reject": "Ablehnen",
|
||||||
|
"waiting": "Wartend",
|
||||||
|
"filter_by_board": "Nach Forum filtern",
|
||||||
|
"mod_queue_alert_threshold": "Schwellenwert für Moderations-Warteschlangen-Alarm",
|
||||||
|
"mod_queue_alert_threshold_tip": "Einen blinkenden roten Indikator anzeigen, wenn Elemente länger als diese Zeit warten",
|
||||||
|
"no_content": "Kein Inhalt",
|
||||||
|
"view": "Anzeigen",
|
||||||
|
"excerpt": "Auszug"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Λογαριασμός Bitsocial",
|
"bitsocial_account": "Λογαριασμός Bitsocial",
|
||||||
"p2p_options": "Επιλογές P2P",
|
"p2p_options": "Επιλογές P2P",
|
||||||
"purge": "εκκαθάριση",
|
"purge": "εκκαθάριση",
|
||||||
"purge_confirm": "Η εκκαθάριση θα αφαιρέσει μόνιμα αυτό το περιεχόμενο και όλες τις απαντήσεις του από τη βάση δεδομένων. Συνέχεια;"
|
"purge_confirm": "Η εκκαθάριση θα αφαιρέσει μόνιμα αυτό το περιεχόμενο και όλες τις απαντήσεις του από τη βάση δεδομένων. Συνέχεια;",
|
||||||
|
"mod_queue": "Ουρά Συντονισμού",
|
||||||
|
"moderation_queue": "Ουρά Συντονισμού",
|
||||||
|
"queue_is_empty": "Η ουρά είναι άδεια",
|
||||||
|
"approve": "Έγκριση",
|
||||||
|
"reject": "Απόρριψη",
|
||||||
|
"waiting": "Αναμονή",
|
||||||
|
"filter_by_board": "Φίλτρο ανά σανίδα",
|
||||||
|
"mod_queue_alert_threshold": "Όριο ειδοποίησης ουράς συντονισμού",
|
||||||
|
"mod_queue_alert_threshold_tip": "Εμφάνιση αναβοσβήνοντος κόκκινου δείκτη όταν τα στοιχεία περιμένουν περισσότερο από αυτόν τον χρόνο",
|
||||||
|
"no_content": "Χωρίς περιεχόμενο",
|
||||||
|
"view": "Προβολή",
|
||||||
|
"excerpt": "Απόσπασμα"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,5 +253,17 @@
|
|||||||
"bitsocial_account": "Bitsocial Account",
|
"bitsocial_account": "Bitsocial Account",
|
||||||
"p2p_options": "P2P options",
|
"p2p_options": "P2P options",
|
||||||
"purge": "purge",
|
"purge": "purge",
|
||||||
"purge_confirm": "Purging permanently removes this content and all its replies from the database. Continue?"
|
"purge_confirm": "Purging permanently removes this content and all its replies from the database. Continue?",
|
||||||
|
"mod_queue": "Mod Queue",
|
||||||
|
"moderation_queue": "Moderation Queue",
|
||||||
|
"queue_is_empty": "Queue is empty",
|
||||||
|
"approve": "Approve",
|
||||||
|
"reject": "Reject",
|
||||||
|
"waiting": "Waiting",
|
||||||
|
"filter_by_board": "Filter by board",
|
||||||
|
"mod_queue_alert_threshold": "Mod queue alert threshold",
|
||||||
|
"mod_queue_alert_threshold_tip": "Show a blinking red indicator when items are waiting for longer than this time",
|
||||||
|
"no_content": "No content",
|
||||||
|
"view": "View",
|
||||||
|
"excerpt": "Excerpt"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Cuenta Bitsocial",
|
"bitsocial_account": "Cuenta Bitsocial",
|
||||||
"p2p_options": "Opciones P2P",
|
"p2p_options": "Opciones P2P",
|
||||||
"purge": "purgar",
|
"purge": "purgar",
|
||||||
"purge_confirm": "Purgar eliminará permanentemente este contenido y todas sus respuestas de la base de datos. ¿Continuar?"
|
"purge_confirm": "Purgar eliminará permanentemente este contenido y todas sus respuestas de la base de datos. ¿Continuar?",
|
||||||
|
"mod_queue": "Cola de Moderación",
|
||||||
|
"moderation_queue": "Cola de Moderación",
|
||||||
|
"queue_is_empty": "La cola está vacía",
|
||||||
|
"approve": "Aprobar",
|
||||||
|
"reject": "Rechazar",
|
||||||
|
"waiting": "Esperando",
|
||||||
|
"filter_by_board": "Filtrar por foro",
|
||||||
|
"mod_queue_alert_threshold": "Umbral de alerta de cola de moderación",
|
||||||
|
"mod_queue_alert_threshold_tip": "Mostrar un indicador rojo parpadeante cuando los elementos están esperando más de este tiempo",
|
||||||
|
"no_content": "Sin contenido",
|
||||||
|
"view": "Ver",
|
||||||
|
"excerpt": "Extracto"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "حساب Bitsocial",
|
"bitsocial_account": "حساب Bitsocial",
|
||||||
"p2p_options": "گزینههای P2P",
|
"p2p_options": "گزینههای P2P",
|
||||||
"purge": "پاکسازی",
|
"purge": "پاکسازی",
|
||||||
"purge_confirm": "پاکسازی این محتوا و تمام پاسخهای آن را به طور دائم از پایگاه داده حذف میکند. ادامه دهید؟"
|
"purge_confirm": "پاکسازی این محتوا و تمام پاسخهای آن را به طور دائم از پایگاه داده حذف میکند. ادامه دهید؟",
|
||||||
|
"mod_queue": "صف انتظار نظارت",
|
||||||
|
"moderation_queue": "صف انتظار نظارت",
|
||||||
|
"queue_is_empty": "صف خالی است",
|
||||||
|
"approve": "تایید",
|
||||||
|
"reject": "رد",
|
||||||
|
"waiting": "در انتظار",
|
||||||
|
"filter_by_board": "فیلتر بر اساس تابلو",
|
||||||
|
"mod_queue_alert_threshold": "آستانه هشدار صف انتظار نظارت",
|
||||||
|
"mod_queue_alert_threshold_tip": "نمایش نشانگر قرمز چشمکزن زمانی که موارد بیش از این زمان در انتظار هستند",
|
||||||
|
"no_content": "بدون محتوا",
|
||||||
|
"view": "مشاهده",
|
||||||
|
"excerpt": "گزیده"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-tili",
|
"bitsocial_account": "Bitsocial-tili",
|
||||||
"p2p_options": "P2P-asetukset",
|
"p2p_options": "P2P-asetukset",
|
||||||
"purge": "poistaa",
|
"purge": "poistaa",
|
||||||
"purge_confirm": "Poistaminen poistaa pysyvästi tämän sisällön ja kaikki sen vastaukset tietokannasta. Jatketaanko?"
|
"purge_confirm": "Poistaminen poistaa pysyvästi tämän sisällön ja kaikki sen vastaukset tietokannasta. Jatketaanko?",
|
||||||
|
"mod_queue": "Moderaatiojono",
|
||||||
|
"moderation_queue": "Moderaatiojono",
|
||||||
|
"queue_is_empty": "Jono on tyhjä",
|
||||||
|
"approve": "Hyväksy",
|
||||||
|
"reject": "Hylkää",
|
||||||
|
"waiting": "Odottaa",
|
||||||
|
"filter_by_board": "Suodata taulun mukaan",
|
||||||
|
"mod_queue_alert_threshold": "Moderaatiojonon hälytyskynnys",
|
||||||
|
"mod_queue_alert_threshold_tip": "Näytä vilkkuva punainen indikaattori, kun kohteet odottavat pidempään kuin tämä aika",
|
||||||
|
"no_content": "Ei sisältöä",
|
||||||
|
"view": "Näytä",
|
||||||
|
"excerpt": "Ote"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Account ng Bitsocial",
|
"bitsocial_account": "Account ng Bitsocial",
|
||||||
"p2p_options": "Mga Opsyon ng P2P",
|
"p2p_options": "Mga Opsyon ng P2P",
|
||||||
"purge": "purga",
|
"purge": "purga",
|
||||||
"purge_confirm": "Ang pag-purge ay permanenteng mag-aalis ng nilalamang ito at lahat ng mga tugon nito mula sa database. Magpatuloy?"
|
"purge_confirm": "Ang pag-purge ay permanenteng mag-aalis ng nilalamang ito at lahat ng mga tugon nito mula sa database. Magpatuloy?",
|
||||||
|
"mod_queue": "Moderasyon Queue",
|
||||||
|
"moderation_queue": "Moderasyon Queue",
|
||||||
|
"queue_is_empty": "Walang laman ang queue",
|
||||||
|
"approve": "Aprubahan",
|
||||||
|
"reject": "Tanggihan",
|
||||||
|
"waiting": "Naghihintay",
|
||||||
|
"filter_by_board": "I-filter ayon sa board",
|
||||||
|
"mod_queue_alert_threshold": "Moderasyon queue alert threshold",
|
||||||
|
"mod_queue_alert_threshold_tip": "Magpakita ng kumikislap na pulang indicator kapag ang mga item ay naghihintay nang mas mahaba kaysa sa oras na ito",
|
||||||
|
"no_content": "Walang nilalaman",
|
||||||
|
"view": "Tingnan",
|
||||||
|
"excerpt": "Sipi"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Compte Bitsocial",
|
"bitsocial_account": "Compte Bitsocial",
|
||||||
"p2p_options": "Options P2P",
|
"p2p_options": "Options P2P",
|
||||||
"purge": "purger",
|
"purge": "purger",
|
||||||
"purge_confirm": "La purge supprime définitivement ce contenu et toutes ses réponses de la base de données. Continuer?"
|
"purge_confirm": "La purge supprime définitivement ce contenu et toutes ses réponses de la base de données. Continuer?",
|
||||||
|
"mod_queue": "File de Modération",
|
||||||
|
"moderation_queue": "File de Modération",
|
||||||
|
"queue_is_empty": "La file est vide",
|
||||||
|
"approve": "Approuver",
|
||||||
|
"reject": "Rejeter",
|
||||||
|
"waiting": "En attente",
|
||||||
|
"filter_by_board": "Filtrer par forum",
|
||||||
|
"mod_queue_alert_threshold": "Seuil d'alerte de la file de modération",
|
||||||
|
"mod_queue_alert_threshold_tip": "Afficher un indicateur rouge clignotant lorsque les éléments attendent plus longtemps que ce temps",
|
||||||
|
"no_content": "Aucun contenu",
|
||||||
|
"view": "Voir",
|
||||||
|
"excerpt": "Extrait"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "חשבון Bitsocial",
|
"bitsocial_account": "חשבון Bitsocial",
|
||||||
"p2p_options": "אפשרויות P2P",
|
"p2p_options": "אפשרויות P2P",
|
||||||
"purge": "למחוק",
|
"purge": "למחוק",
|
||||||
"purge_confirm": "מחיקה תסיר לצמיתות את התוכן הזה ואת כל התגובות שלו מהמסד הנתונים. להמשיך?"
|
"purge_confirm": "מחיקה תסיר לצמיתות את התוכן הזה ואת כל התגובות שלו מהמסד הנתונים. להמשיך?",
|
||||||
|
"mod_queue": "תור ניהול",
|
||||||
|
"moderation_queue": "תור ניהול",
|
||||||
|
"queue_is_empty": "התור ריק",
|
||||||
|
"approve": "אשר",
|
||||||
|
"reject": "דחה",
|
||||||
|
"waiting": "ממתין",
|
||||||
|
"filter_by_board": "סנן לפי לוח",
|
||||||
|
"mod_queue_alert_threshold": "סף התרעה של תור ניהול",
|
||||||
|
"mod_queue_alert_threshold_tip": "הצג אינדיקטור אדום מהבהב כאשר פריטים ממתינים יותר מזמן זה",
|
||||||
|
"no_content": "אין תוכן",
|
||||||
|
"view": "הצג",
|
||||||
|
"excerpt": "תקציר"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial खाता",
|
"bitsocial_account": "Bitsocial खाता",
|
||||||
"p2p_options": "P2P विकल्प",
|
"p2p_options": "P2P विकल्प",
|
||||||
"purge": "स्थायी रूप से हटाएं",
|
"purge": "स्थायी रूप से हटाएं",
|
||||||
"purge_confirm": "स्थायी रूप से हटाने से यह सामग्री और इसकी सभी प्रतिक्रियाएं डेटाबेस से स्थायी रूप से हट जाएंगी। जारी रखें?"
|
"purge_confirm": "स्थायी रूप से हटाने से यह सामग्री और इसकी सभी प्रतिक्रियाएं डेटाबेस से स्थायी रूप से हट जाएंगी। जारी रखें?",
|
||||||
|
"mod_queue": "मॉडरेटर कतार",
|
||||||
|
"moderation_queue": "मॉडरेटर कतार",
|
||||||
|
"queue_is_empty": "कतार खाली है",
|
||||||
|
"approve": "अनुमोदन करें",
|
||||||
|
"reject": "अस्वीकार करें",
|
||||||
|
"waiting": "प्रतीक्षा कर रहा है",
|
||||||
|
"filter_by_board": "बोर्ड के अनुसार फ़िल्टर करें",
|
||||||
|
"mod_queue_alert_threshold": "मॉडरेटर कतार सतर्कता सीमा",
|
||||||
|
"mod_queue_alert_threshold_tip": "जब आइटम इस समय से अधिक समय तक प्रतीक्षा कर रहे हों तो एक चमकता हुआ लाल संकेतक दिखाएं",
|
||||||
|
"no_content": "कोई सामग्री नहीं",
|
||||||
|
"view": "देखें",
|
||||||
|
"excerpt": "अंश"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial fiók",
|
"bitsocial_account": "Bitsocial fiók",
|
||||||
"p2p_options": "P2P beállítások",
|
"p2p_options": "P2P beállítások",
|
||||||
"purge": "törlés",
|
"purge": "törlés",
|
||||||
"purge_confirm": "A törlés véglegesen eltávolítja ezt a tartalmat és az összes válaszát az adatbázisból. Folytatás?"
|
"purge_confirm": "A törlés véglegesen eltávolítja ezt a tartalmat és az összes válaszát az adatbázisból. Folytatás?",
|
||||||
|
"mod_queue": "Moderációs Sor",
|
||||||
|
"moderation_queue": "Moderációs Sor",
|
||||||
|
"queue_is_empty": "A sor üres",
|
||||||
|
"approve": "Jóváhagyás",
|
||||||
|
"reject": "Elutasítás",
|
||||||
|
"waiting": "Várakozás",
|
||||||
|
"filter_by_board": "Szűrés tábla szerint",
|
||||||
|
"mod_queue_alert_threshold": "Moderációs sor riasztási küszöb",
|
||||||
|
"mod_queue_alert_threshold_tip": "Villogó piros jelző megjelenítése, amikor az elemek ennél hosszabb ideig várakoznak",
|
||||||
|
"no_content": "Nincs tartalom",
|
||||||
|
"view": "Megtekintés",
|
||||||
|
"excerpt": "Kivonat"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Akun Bitsocial",
|
"bitsocial_account": "Akun Bitsocial",
|
||||||
"p2p_options": "Opsi P2P",
|
"p2p_options": "Opsi P2P",
|
||||||
"purge": "hapus",
|
"purge": "hapus",
|
||||||
"purge_confirm": "Menghapus akan menghapus konten ini dan semua balasannya secara permanen dari database. Lanjutkan?"
|
"purge_confirm": "Menghapus akan menghapus konten ini dan semua balasannya secara permanen dari database. Lanjutkan?",
|
||||||
|
"mod_queue": "Antrian Moderasi",
|
||||||
|
"moderation_queue": "Antrian Moderasi",
|
||||||
|
"queue_is_empty": "Antrian kosong",
|
||||||
|
"approve": "Setujui",
|
||||||
|
"reject": "Tolak",
|
||||||
|
"waiting": "Menunggu",
|
||||||
|
"filter_by_board": "Filter berdasarkan papan",
|
||||||
|
"mod_queue_alert_threshold": "Ambang peringatan antrian moderasi",
|
||||||
|
"mod_queue_alert_threshold_tip": "Tampilkan indikator merah berkedip ketika item menunggu lebih lama dari waktu ini",
|
||||||
|
"no_content": "Tidak ada konten",
|
||||||
|
"view": "Lihat",
|
||||||
|
"excerpt": "Kutipan"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Account Bitsocial",
|
"bitsocial_account": "Account Bitsocial",
|
||||||
"p2p_options": "Opzioni P2P",
|
"p2p_options": "Opzioni P2P",
|
||||||
"purge": "elimina",
|
"purge": "elimina",
|
||||||
"purge_confirm": "L'eliminazione rimuoverà permanentemente questo contenuto e tutte le sue risposte dal database. Continuare?"
|
"purge_confirm": "L'eliminazione rimuoverà permanentemente questo contenuto e tutte le sue risposte dal database. Continuare?",
|
||||||
|
"mod_queue": "Coda Moderazione",
|
||||||
|
"moderation_queue": "Coda di Moderazione",
|
||||||
|
"queue_is_empty": "La coda è vuota",
|
||||||
|
"approve": "Approva",
|
||||||
|
"reject": "Rifiuta",
|
||||||
|
"waiting": "In attesa",
|
||||||
|
"filter_by_board": "Filtra per board",
|
||||||
|
"mod_queue_alert_threshold": "Soglia di allerta coda moderazione",
|
||||||
|
"mod_queue_alert_threshold_tip": "Mostra un indicatore rosso lampeggiante quando gli elementi attendono più di questo tempo",
|
||||||
|
"no_content": "Nessun contenuto",
|
||||||
|
"view": "Visualizza",
|
||||||
|
"excerpt": "Estratto"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocialアカウント",
|
"bitsocial_account": "Bitsocialアカウント",
|
||||||
"p2p_options": "P2Pオプション",
|
"p2p_options": "P2Pオプション",
|
||||||
"purge": "削除",
|
"purge": "削除",
|
||||||
"purge_confirm": "削除すると、このコンテンツとそのすべての返信がデータベースから永続的に削除されます。続行しますか?"
|
"purge_confirm": "削除すると、このコンテンツとそのすべての返信がデータベースから永続的に削除されます。続行しますか?",
|
||||||
|
"mod_queue": "モデレーションキュー",
|
||||||
|
"moderation_queue": "モデレーションキュー",
|
||||||
|
"queue_is_empty": "キューは空です",
|
||||||
|
"approve": "承認",
|
||||||
|
"reject": "拒否",
|
||||||
|
"waiting": "待機中",
|
||||||
|
"filter_by_board": "ボードでフィルター",
|
||||||
|
"mod_queue_alert_threshold": "モデレーションキューのアラート閾値",
|
||||||
|
"mod_queue_alert_threshold_tip": "アイテムがこの時間より長く待機している場合、点滅する赤いインジケーターを表示",
|
||||||
|
"no_content": "コンテンツなし",
|
||||||
|
"view": "表示",
|
||||||
|
"excerpt": "抜粋"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial 계정",
|
"bitsocial_account": "Bitsocial 계정",
|
||||||
"p2p_options": "P2P 옵션",
|
"p2p_options": "P2P 옵션",
|
||||||
"purge": "삭제",
|
"purge": "삭제",
|
||||||
"purge_confirm": "삭제하면 이 콘텐츠와 모든 답글이 데이터베이스에서 영구적으로 제거됩니다. 계속하시겠습니까?"
|
"purge_confirm": "삭제하면 이 콘텐츠와 모든 답글이 데이터베이스에서 영구적으로 제거됩니다. 계속하시겠습니까?",
|
||||||
|
"mod_queue": "관리자 대기열",
|
||||||
|
"moderation_queue": "관리자 대기열",
|
||||||
|
"queue_is_empty": "대기열이 비어 있습니다",
|
||||||
|
"approve": "승인",
|
||||||
|
"reject": "거부",
|
||||||
|
"waiting": "대기 중",
|
||||||
|
"filter_by_board": "게시판별 필터",
|
||||||
|
"mod_queue_alert_threshold": "관리자 대기열 알림 임계값",
|
||||||
|
"mod_queue_alert_threshold_tip": "항목이 이 시간보다 오래 대기 중일 때 깜빡이는 빨간색 표시기 표시",
|
||||||
|
"no_content": "콘텐츠 없음",
|
||||||
|
"view": "보기",
|
||||||
|
"excerpt": "요약"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial खाते",
|
"bitsocial_account": "Bitsocial खाते",
|
||||||
"p2p_options": "P2P पर्याय",
|
"p2p_options": "P2P पर्याय",
|
||||||
"purge": "हटवा",
|
"purge": "हटवा",
|
||||||
"purge_confirm": "पर्ज करणे या सामग्रीला आणि त्याच्या सर्व प्रतिक्रियांना डेटाबेसमधून कायमस्वरूपी काढून टाकेल. पुढे जाऊ?"
|
"purge_confirm": "पर्ज करणे या सामग्रीला आणि त्याच्या सर्व प्रतिक्रियांना डेटाबेसमधून कायमस्वरूपी काढून टाकेल. पुढे जाऊ?",
|
||||||
|
"mod_queue": "मॉडरेशन रांग",
|
||||||
|
"moderation_queue": "मॉडरेशन रांग",
|
||||||
|
"queue_is_empty": "रांग रिकामी आहे",
|
||||||
|
"approve": "मंजूर करा",
|
||||||
|
"reject": "नकार द्या",
|
||||||
|
"waiting": "प्रतीक्षा करत आहे",
|
||||||
|
"filter_by_board": "बोर्डनुसार फिल्टर करा",
|
||||||
|
"mod_queue_alert_threshold": "मॉडरेशन रांग सतर्कता मर्यादा",
|
||||||
|
"mod_queue_alert_threshold_tip": "जेव्हा आयटम या वेळेपेक्षा जास्त वेळ प्रतीक्षा करत असतात तेव्हा एक चमकणारा लाल सूचक दाखवा",
|
||||||
|
"no_content": "सामग्री नाही",
|
||||||
|
"view": "पहा",
|
||||||
|
"excerpt": "उतारा"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-account",
|
"bitsocial_account": "Bitsocial-account",
|
||||||
"p2p_options": "P2P-opties",
|
"p2p_options": "P2P-opties",
|
||||||
"purge": "verwijderen",
|
"purge": "verwijderen",
|
||||||
"purge_confirm": "Verwijderen verwijdert deze inhoud en alle antwoorden ervan permanent uit de database. Doorgaan?"
|
"purge_confirm": "Verwijderen verwijdert deze inhoud en alle antwoorden ervan permanent uit de database. Doorgaan?",
|
||||||
|
"mod_queue": "Moderatie Wachtrij",
|
||||||
|
"moderation_queue": "Moderatie Wachtrij",
|
||||||
|
"queue_is_empty": "Wachtrij is leeg",
|
||||||
|
"approve": "Goedkeuren",
|
||||||
|
"reject": "Afwijzen",
|
||||||
|
"waiting": "Wachten",
|
||||||
|
"filter_by_board": "Filteren op bord",
|
||||||
|
"mod_queue_alert_threshold": "Drempelwaarde voor moderatiewachtrijwaarschuwing",
|
||||||
|
"mod_queue_alert_threshold_tip": "Toon een knipperende rode indicator wanneer items langer dan deze tijd wachten",
|
||||||
|
"no_content": "Geen inhoud",
|
||||||
|
"view": "Bekijken",
|
||||||
|
"excerpt": "Uittreksel"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-konto",
|
"bitsocial_account": "Bitsocial-konto",
|
||||||
"p2p_options": "P2P-alternativer",
|
"p2p_options": "P2P-alternativer",
|
||||||
"purge": "slette",
|
"purge": "slette",
|
||||||
"purge_confirm": "Sletting fjerner permanent dette innholdet og alle svarene fra databasen. Fortsette?"
|
"purge_confirm": "Sletting fjerner permanent dette innholdet og alle svarene fra databasen. Fortsette?",
|
||||||
|
"mod_queue": "Modereringskø",
|
||||||
|
"moderation_queue": "Modereringskø",
|
||||||
|
"queue_is_empty": "Køen er tom",
|
||||||
|
"approve": "Godkjenn",
|
||||||
|
"reject": "Avvis",
|
||||||
|
"waiting": "Venter",
|
||||||
|
"filter_by_board": "Filtrer etter tavle",
|
||||||
|
"mod_queue_alert_threshold": "Terskel for modereringskø-varsel",
|
||||||
|
"mod_queue_alert_threshold_tip": "Vis en blinkende rød indikator når elementer venter lenger enn denne tiden",
|
||||||
|
"no_content": "Ingen innhold",
|
||||||
|
"view": "Vis",
|
||||||
|
"excerpt": "Utdrag"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Konto Bitsocial",
|
"bitsocial_account": "Konto Bitsocial",
|
||||||
"p2p_options": "Opcje P2P",
|
"p2p_options": "Opcje P2P",
|
||||||
"purge": "usuń",
|
"purge": "usuń",
|
||||||
"purge_confirm": "Usunięcie trwale usunie tę zawartość i wszystkie odpowiedzi z bazy danych. Kontynuować?"
|
"purge_confirm": "Usunięcie trwale usunie tę zawartość i wszystkie odpowiedzi z bazy danych. Kontynuować?",
|
||||||
|
"mod_queue": "Kolejka Moderacji",
|
||||||
|
"moderation_queue": "Kolejka Moderacji",
|
||||||
|
"queue_is_empty": "Kolejka jest pusta",
|
||||||
|
"approve": "Zatwierdź",
|
||||||
|
"reject": "Odrzuć",
|
||||||
|
"waiting": "Oczekiwanie",
|
||||||
|
"filter_by_board": "Filtruj według tablicy",
|
||||||
|
"mod_queue_alert_threshold": "Próg alertu kolejki moderacji",
|
||||||
|
"mod_queue_alert_threshold_tip": "Pokaż migający czerwony wskaźnik, gdy elementy czekają dłużej niż ten czas",
|
||||||
|
"no_content": "Brak zawartości",
|
||||||
|
"view": "Zobacz",
|
||||||
|
"excerpt": "Fragment"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Conta Bitsocial",
|
"bitsocial_account": "Conta Bitsocial",
|
||||||
"p2p_options": "Opções P2P",
|
"p2p_options": "Opções P2P",
|
||||||
"purge": "purgar",
|
"purge": "purgar",
|
||||||
"purge_confirm": "Purgar removerá permanentemente este conteúdo e todas as suas respostas do banco de dados. Continuar?"
|
"purge_confirm": "Purgar removerá permanentemente este conteúdo e todas as suas respostas do banco de dados. Continuar?",
|
||||||
|
"mod_queue": "Fila de Moderação",
|
||||||
|
"moderation_queue": "Fila de Moderação",
|
||||||
|
"queue_is_empty": "A fila está vazia",
|
||||||
|
"approve": "Aprovar",
|
||||||
|
"reject": "Rejeitar",
|
||||||
|
"waiting": "Aguardando",
|
||||||
|
"filter_by_board": "Filtrar por quadro",
|
||||||
|
"mod_queue_alert_threshold": "Limite de alerta da fila de moderação",
|
||||||
|
"mod_queue_alert_threshold_tip": "Mostrar um indicador vermelho piscante quando os itens estão aguardando por mais tempo que este tempo",
|
||||||
|
"no_content": "Sem conteúdo",
|
||||||
|
"view": "Ver",
|
||||||
|
"excerpt": "Trecho"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Cont Bitsocial",
|
"bitsocial_account": "Cont Bitsocial",
|
||||||
"p2p_options": "Opțiuni P2P",
|
"p2p_options": "Opțiuni P2P",
|
||||||
"purge": "șterge",
|
"purge": "șterge",
|
||||||
"purge_confirm": "Ștergerea va elimina permanent acest conținut și toate răspunsurile sale din baza de date. Continuați?"
|
"purge_confirm": "Ștergerea va elimina permanent acest conținut și toate răspunsurile sale din baza de date. Continuați?",
|
||||||
|
"mod_queue": "Coadă de Moderare",
|
||||||
|
"moderation_queue": "Coadă de Moderare",
|
||||||
|
"queue_is_empty": "Coada este goală",
|
||||||
|
"approve": "Aprobă",
|
||||||
|
"reject": "Respinge",
|
||||||
|
"waiting": "Așteaptă",
|
||||||
|
"filter_by_board": "Filtrează după panou",
|
||||||
|
"mod_queue_alert_threshold": "Prag de alertă pentru coada de moderare",
|
||||||
|
"mod_queue_alert_threshold_tip": "Afișează un indicator roșu intermitent când elementele așteaptă mai mult decât acest timp",
|
||||||
|
"no_content": "Fără conținut",
|
||||||
|
"view": "Vizualizează",
|
||||||
|
"excerpt": "Fragment"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Аккаунт Bitsocial",
|
"bitsocial_account": "Аккаунт Bitsocial",
|
||||||
"p2p_options": "Опции P2P",
|
"p2p_options": "Опции P2P",
|
||||||
"purge": "удалить",
|
"purge": "удалить",
|
||||||
"purge_confirm": "Удаление навсегда удалит этот контент и все ответы на него из базы данных. Продолжить?"
|
"purge_confirm": "Удаление навсегда удалит этот контент и все ответы на него из базы данных. Продолжить?",
|
||||||
|
"mod_queue": "Очередь Модерации",
|
||||||
|
"moderation_queue": "Очередь Модерации",
|
||||||
|
"queue_is_empty": "Очередь пуста",
|
||||||
|
"approve": "Одобрить",
|
||||||
|
"reject": "Отклонить",
|
||||||
|
"waiting": "Ожидание",
|
||||||
|
"filter_by_board": "Фильтр по доске",
|
||||||
|
"mod_queue_alert_threshold": "Порог предупреждения очереди модерации",
|
||||||
|
"mod_queue_alert_threshold_tip": "Показывать мигающий красный индикатор, когда элементы ждут дольше этого времени",
|
||||||
|
"no_content": "Нет содержимого",
|
||||||
|
"view": "Просмотр",
|
||||||
|
"excerpt": "Выдержка"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Llogaria Bitsocial",
|
"bitsocial_account": "Llogaria Bitsocial",
|
||||||
"p2p_options": "Opsionet P2P",
|
"p2p_options": "Opsionet P2P",
|
||||||
"purge": "fshi",
|
"purge": "fshi",
|
||||||
"purge_confirm": "Fshirja do të heqë përgjithmonë këtë përmbajtje dhe të gjitha përgjigjet e saj nga baza e të dhënave. Vazhdo?"
|
"purge_confirm": "Fshirja do të heqë përgjithmonë këtë përmbajtje dhe të gjitha përgjigjet e saj nga baza e të dhënave. Vazhdo?",
|
||||||
|
"mod_queue": "Radha e Moderimit",
|
||||||
|
"moderation_queue": "Radha e Moderimit",
|
||||||
|
"queue_is_empty": "Radha është e zbrazët",
|
||||||
|
"approve": "Aprovo",
|
||||||
|
"reject": "Refuzo",
|
||||||
|
"waiting": "Duke pritur",
|
||||||
|
"filter_by_board": "Filtro sipas tabelës",
|
||||||
|
"mod_queue_alert_threshold": "Pragu i alarmit të radhës së moderimit",
|
||||||
|
"mod_queue_alert_threshold_tip": "Shfaq një tregues të kuq që blinkon kur elementët po presin më shumë se kjo kohë",
|
||||||
|
"no_content": "Pa përmbajtje",
|
||||||
|
"view": "Shiko",
|
||||||
|
"excerpt": "Fragment"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial-konto",
|
"bitsocial_account": "Bitsocial-konto",
|
||||||
"p2p_options": "P2P-alternativ",
|
"p2p_options": "P2P-alternativ",
|
||||||
"purge": "radera",
|
"purge": "radera",
|
||||||
"purge_confirm": "Raderande tar permanent bort detta innehåll och alla dess svar från databasen. Fortsätta?"
|
"purge_confirm": "Raderande tar permanent bort detta innehåll och alla dess svar från databasen. Fortsätta?",
|
||||||
|
"mod_queue": "Modereringskö",
|
||||||
|
"moderation_queue": "Modereringskö",
|
||||||
|
"queue_is_empty": "Kön är tom",
|
||||||
|
"approve": "Godkänn",
|
||||||
|
"reject": "Avvisa",
|
||||||
|
"waiting": "Väntar",
|
||||||
|
"filter_by_board": "Filtrera efter tavla",
|
||||||
|
"mod_queue_alert_threshold": "Tröskelvärde för modereringskö-varning",
|
||||||
|
"mod_queue_alert_threshold_tip": "Visa en blinkande röd indikator när objekt väntar längre än denna tid",
|
||||||
|
"no_content": "Inget innehåll",
|
||||||
|
"view": "Visa",
|
||||||
|
"excerpt": "Utdrag"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial ఖాతా",
|
"bitsocial_account": "Bitsocial ఖాతా",
|
||||||
"p2p_options": "P2P ఎంపికలు",
|
"p2p_options": "P2P ఎంపికలు",
|
||||||
"purge": "తొలగించు",
|
"purge": "తొలగించు",
|
||||||
"purge_confirm": "పర్జ్ చేయడం ఈ కంటెంట్ మరియు దాని అన్ని ప్రతిస్పందనలను డేటాబేస్ నుండి శాశ్వతంగా తొలగిస్తుంది. కొనసాగించాలా?"
|
"purge_confirm": "పర్జ్ చేయడం ఈ కంటెంట్ మరియు దాని అన్ని ప్రతిస్పందనలను డేటాబేస్ నుండి శాశ్వతంగా తొలగిస్తుంది. కొనసాగించాలా?",
|
||||||
|
"mod_queue": "మోడరేషన్ క్యూ",
|
||||||
|
"moderation_queue": "మోడరేషన్ క్యూ",
|
||||||
|
"queue_is_empty": "క్యూ ఖాళీగా ఉంది",
|
||||||
|
"approve": "ఆమోదించు",
|
||||||
|
"reject": "తిరస్కరించు",
|
||||||
|
"waiting": "వేచి ఉంది",
|
||||||
|
"filter_by_board": "బోర్డ్ ద్వారా ఫిల్టర్ చేయి",
|
||||||
|
"mod_queue_alert_threshold": "మోడరేషన్ క్యూ హెచ్చరిక థ్రెషోల్డ్",
|
||||||
|
"mod_queue_alert_threshold_tip": "అంశాలు ఈ సమయం కంటే ఎక్కువ సమయం వేచి ఉన్నప్పుడు మెరిసే ఎరుపు సూచికను చూపించు",
|
||||||
|
"no_content": "కంటెంట్ లేదు",
|
||||||
|
"view": "చూడు",
|
||||||
|
"excerpt": "ఎక్సెర్ప్ట్"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "บัญชี Bitsocial",
|
"bitsocial_account": "บัญชี Bitsocial",
|
||||||
"p2p_options": "ตัวเลือก P2P",
|
"p2p_options": "ตัวเลือก P2P",
|
||||||
"purge": "ลบ",
|
"purge": "ลบ",
|
||||||
"purge_confirm": "การลบจะลบเนื้อหานี้และคำตอบทั้งหมดออกจากฐานข้อมูลอย่างถาวร ดำเนินการต่อหรือไม่?"
|
"purge_confirm": "การลบจะลบเนื้อหานี้และคำตอบทั้งหมดออกจากฐานข้อมูลอย่างถาวร ดำเนินการต่อหรือไม่?",
|
||||||
|
"mod_queue": "คิวผู้ดูแล",
|
||||||
|
"moderation_queue": "คิวผู้ดูแล",
|
||||||
|
"queue_is_empty": "คิวว่างเปล่า",
|
||||||
|
"approve": "อนุมัติ",
|
||||||
|
"reject": "ปฏิเสธ",
|
||||||
|
"waiting": "กำลังรอ",
|
||||||
|
"filter_by_board": "กรองตามบอร์ด",
|
||||||
|
"mod_queue_alert_threshold": "เกณฑ์การแจ้งเตือนคิวผู้ดูแล",
|
||||||
|
"mod_queue_alert_threshold_tip": "แสดงตัวบ่งชี้สีแดงกะพริบเมื่อรายการรอเกินเวลานี้",
|
||||||
|
"no_content": "ไม่มีเนื้อหา",
|
||||||
|
"view": "ดู",
|
||||||
|
"excerpt": "ข้อความย่อ"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial Hesabı",
|
"bitsocial_account": "Bitsocial Hesabı",
|
||||||
"p2p_options": "P2P Seçenekleri",
|
"p2p_options": "P2P Seçenekleri",
|
||||||
"purge": "temizle",
|
"purge": "temizle",
|
||||||
"purge_confirm": "Temizleme, bu içeriği ve tüm yanıtlarını veritabanından kalıcı olarak kaldıracaktır. Devam edilsin mi?"
|
"purge_confirm": "Temizleme, bu içeriği ve tüm yanıtlarını veritabanından kalıcı olarak kaldıracaktır. Devam edilsin mi?",
|
||||||
|
"mod_queue": "Moderasyon Kuyruğu",
|
||||||
|
"moderation_queue": "Moderasyon Kuyruğu",
|
||||||
|
"queue_is_empty": "Kuyruk boş",
|
||||||
|
"approve": "Onayla",
|
||||||
|
"reject": "Reddet",
|
||||||
|
"waiting": "Bekliyor",
|
||||||
|
"filter_by_board": "Panoya göre filtrele",
|
||||||
|
"mod_queue_alert_threshold": "Moderasyon kuyruğu uyarı eşiği",
|
||||||
|
"mod_queue_alert_threshold_tip": "Öğeler bu süreden daha uzun süre beklediğinde yanıp sönen kırmızı bir gösterge göster",
|
||||||
|
"no_content": "İçerik yok",
|
||||||
|
"view": "Görüntüle",
|
||||||
|
"excerpt": "Alıntı"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Обліковий запис Bitsocial",
|
"bitsocial_account": "Обліковий запис Bitsocial",
|
||||||
"p2p_options": "Опції P2P",
|
"p2p_options": "Опції P2P",
|
||||||
"purge": "видалити",
|
"purge": "видалити",
|
||||||
"purge_confirm": "Видалення назавжди видалить цей контент і всі відповіді на нього з бази даних. Продовжити?"
|
"purge_confirm": "Видалення назавжди видалить цей контент і всі відповіді на нього з бази даних. Продовжити?",
|
||||||
|
"mod_queue": "Черга Модерації",
|
||||||
|
"moderation_queue": "Черга Модерації",
|
||||||
|
"queue_is_empty": "Черга порожня",
|
||||||
|
"approve": "Схвалити",
|
||||||
|
"reject": "Відхилити",
|
||||||
|
"waiting": "Очікування",
|
||||||
|
"filter_by_board": "Фільтр за дошкою",
|
||||||
|
"mod_queue_alert_threshold": "Поріг попередження черги модерації",
|
||||||
|
"mod_queue_alert_threshold_tip": "Показувати мигаючий червоний індикатор, коли елементи чекають довше цього часу",
|
||||||
|
"no_content": "Немає вмісту",
|
||||||
|
"view": "Перегляд",
|
||||||
|
"excerpt": "Витяг"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial اکاؤنٹ",
|
"bitsocial_account": "Bitsocial اکاؤنٹ",
|
||||||
"p2p_options": "P2P اختیارات",
|
"p2p_options": "P2P اختیارات",
|
||||||
"purge": "ختم کرنا",
|
"purge": "ختم کرنا",
|
||||||
"purge_confirm": "پرج کرنا اس مواد اور اس کی تمام جوابات کو ڈیٹا بیس سے مستقل طور پر ہٹا دے گا۔ جاری رکھیں؟"
|
"purge_confirm": "پرج کرنا اس مواد اور اس کی تمام جوابات کو ڈیٹا بیس سے مستقل طور پر ہٹا دے گا۔ جاری رکھیں؟",
|
||||||
|
"mod_queue": "نگرانی کی قطار",
|
||||||
|
"moderation_queue": "نگرانی کی قطار",
|
||||||
|
"queue_is_empty": "قطار خالی ہے",
|
||||||
|
"approve": "منظور کریں",
|
||||||
|
"reject": "مسترد کریں",
|
||||||
|
"waiting": "انتظار کر رہا ہے",
|
||||||
|
"filter_by_board": "بورڈ کے لحاظ سے فلٹر کریں",
|
||||||
|
"mod_queue_alert_threshold": "نگرانی کی قطار کی انتباہ کی حد",
|
||||||
|
"mod_queue_alert_threshold_tip": "جب آئٹمز اس وقت سے زیادہ انتظار کر رہے ہوں تو ایک ٹمٹمانے والا سرخ اشارہ دکھائیں",
|
||||||
|
"no_content": "کوئی مواد نہیں",
|
||||||
|
"view": "دیکھیں",
|
||||||
|
"excerpt": "اقتباس"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Tài khoản Bitsocial",
|
"bitsocial_account": "Tài khoản Bitsocial",
|
||||||
"p2p_options": "Tùy chọn P2P",
|
"p2p_options": "Tùy chọn P2P",
|
||||||
"purge": "xóa",
|
"purge": "xóa",
|
||||||
"purge_confirm": "Xóa sẽ loại bỏ vĩnh viễn nội dung này và tất cả các phản hồi của nó khỏi cơ sở dữ liệu. Tiếp tục?"
|
"purge_confirm": "Xóa sẽ loại bỏ vĩnh viễn nội dung này và tất cả các phản hồi của nó khỏi cơ sở dữ liệu. Tiếp tục?",
|
||||||
|
"mod_queue": "Hàng Đợi Kiểm Duyệt",
|
||||||
|
"moderation_queue": "Hàng Đợi Kiểm Duyệt",
|
||||||
|
"queue_is_empty": "Hàng đợi trống",
|
||||||
|
"approve": "Phê duyệt",
|
||||||
|
"reject": "Từ chối",
|
||||||
|
"waiting": "Đang chờ",
|
||||||
|
"filter_by_board": "Lọc theo bảng",
|
||||||
|
"mod_queue_alert_threshold": "Ngưỡng cảnh báo hàng đợi kiểm duyệt",
|
||||||
|
"mod_queue_alert_threshold_tip": "Hiển thị chỉ báo màu đỏ nhấp nháy khi các mục đang chờ lâu hơn thời gian này",
|
||||||
|
"no_content": "Không có nội dung",
|
||||||
|
"view": "Xem",
|
||||||
|
"excerpt": "Trích đoạn"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,5 +254,17 @@
|
|||||||
"bitsocial_account": "Bitsocial账户",
|
"bitsocial_account": "Bitsocial账户",
|
||||||
"p2p_options": "P2P选项",
|
"p2p_options": "P2P选项",
|
||||||
"purge": "清除",
|
"purge": "清除",
|
||||||
"purge_confirm": "清除将永久删除此内容及其所有回复。继续吗?"
|
"purge_confirm": "清除将永久删除此内容及其所有回复。继续吗?",
|
||||||
|
"mod_queue": "审核队列",
|
||||||
|
"moderation_queue": "审核队列",
|
||||||
|
"queue_is_empty": "队列为空",
|
||||||
|
"approve": "批准",
|
||||||
|
"reject": "拒绝",
|
||||||
|
"waiting": "等待中",
|
||||||
|
"filter_by_board": "按板块筛选",
|
||||||
|
"mod_queue_alert_threshold": "审核队列警报阈值",
|
||||||
|
"mod_queue_alert_threshold_tip": "当项目等待时间超过此时长时显示闪烁的红色指示器",
|
||||||
|
"no_content": "无内容",
|
||||||
|
"view": "查看",
|
||||||
|
"excerpt": "摘要"
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-2
@@ -10,7 +10,7 @@ import useSpecialThemeStore from './stores/use-special-theme-store';
|
|||||||
import useIsMobile from './hooks/use-is-mobile';
|
import useIsMobile from './hooks/use-is-mobile';
|
||||||
import useTheme from './hooks/use-theme';
|
import useTheme from './hooks/use-theme';
|
||||||
import { useDefaultSubplebbits } from './hooks/use-default-subplebbits';
|
import { useDefaultSubplebbits } from './hooks/use-default-subplebbits';
|
||||||
import { getSubplebbitAddress, isPostRoute, isPendingPostRoute } from './lib/utils/route-utils';
|
import { getSubplebbitAddress, isPostRoute, isPendingPostRoute, isModQueueRoute } from './lib/utils/route-utils';
|
||||||
import styles from './app.module.css';
|
import styles from './app.module.css';
|
||||||
import FAQ from './views/faq';
|
import FAQ from './views/faq';
|
||||||
import Home from './views/home';
|
import Home from './views/home';
|
||||||
@@ -18,6 +18,7 @@ import Rules from './views/rules';
|
|||||||
import NotFound from './views/not-found';
|
import NotFound from './views/not-found';
|
||||||
import PendingPost from './views/pending-post';
|
import PendingPost from './views/pending-post';
|
||||||
import Post from './views/post';
|
import Post from './views/post';
|
||||||
|
import ModQueueView from './views/mod-queue';
|
||||||
import { DesktopBoardButtons, MobileBoardButtons } from './components/board-buttons';
|
import { DesktopBoardButtons, MobileBoardButtons } from './components/board-buttons';
|
||||||
import BoardHeader from './components/board-header';
|
import BoardHeader from './components/board-header';
|
||||||
import ChallengeModal from './components/challenge-modal';
|
import ChallengeModal from './components/challenge-modal';
|
||||||
@@ -50,6 +51,7 @@ const BoardLayout = () => {
|
|||||||
|
|
||||||
const isOnPostRoute = isPostRoute(location.pathname);
|
const isOnPostRoute = isPostRoute(location.pathname);
|
||||||
const isOnPendingPostRoute = isPendingPostRoute(location.pathname);
|
const isOnPendingPostRoute = isPendingPostRoute(location.pathname);
|
||||||
|
const isOnModQueueRoute = isModQueueRoute(location.pathname);
|
||||||
|
|
||||||
// Christmas theme
|
// Christmas theme
|
||||||
const { isEnabled: isSpecialEnabled } = useSpecialThemeStore();
|
const { isEnabled: isSpecialEnabled } = useSpecialThemeStore();
|
||||||
@@ -95,7 +97,7 @@ const BoardLayout = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<FeedCacheContainer />
|
<FeedCacheContainer />
|
||||||
{(isOnPostRoute || isOnPendingPostRoute) && <Outlet />}
|
{(isOnPostRoute || isOnPendingPostRoute || isOnModQueueRoute) && <Outlet />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -168,11 +170,17 @@ const App = () => (
|
|||||||
<Route path='/mod/catalog/:timeFilterName?' element={null} />
|
<Route path='/mod/catalog/:timeFilterName?' element={null} />
|
||||||
<Route path='/mod/catalog/:timeFilterName?/settings' element={null} />
|
<Route path='/mod/catalog/:timeFilterName?/settings' element={null} />
|
||||||
|
|
||||||
|
<Route path='/mod/queue' element={<ModQueueView />} />
|
||||||
|
<Route path='/mod/queue/settings' element={<ModQueueView />} />
|
||||||
|
|
||||||
<Route path='/:boardIdentifier' element={null} />
|
<Route path='/:boardIdentifier' element={null} />
|
||||||
<Route path='/:boardIdentifier/settings' element={null} />
|
<Route path='/:boardIdentifier/settings' element={null} />
|
||||||
<Route path='/:boardIdentifier/catalog' element={null} />
|
<Route path='/:boardIdentifier/catalog' element={null} />
|
||||||
<Route path='/:boardIdentifier/catalog/settings' element={null} />
|
<Route path='/:boardIdentifier/catalog/settings' element={null} />
|
||||||
|
|
||||||
|
<Route path='/:boardIdentifier/queue' element={<ModQueueView />} />
|
||||||
|
<Route path='/:boardIdentifier/queue/settings' element={<ModQueueView />} />
|
||||||
|
|
||||||
<Route path='/:boardIdentifier/thread/:commentCid' element={<Post />} />
|
<Route path='/:boardIdentifier/thread/:commentCid' element={<Post />} />
|
||||||
<Route path='/:boardIdentifier/thread/:commentCid/settings' element={<Post />} />
|
<Route path='/:boardIdentifier/thread/:commentCid/settings' element={<Post />} />
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { useAccountComment, useSubscribe } from '@plebbit/plebbit-react-hooks';
|
import { useAccountComment, useSubscribe } from '@plebbit/plebbit-react-hooks';
|
||||||
import useSubplebbitsPagesStore from '@plebbit/plebbit-react-hooks/dist/stores/subplebbits-pages';
|
import useSubplebbitsPagesStore from '@plebbit/plebbit-react-hooks/dist/stores/subplebbits-pages';
|
||||||
import { isAllView, isCatalogView, isModView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
import { isAllView, isCatalogView, isModView, isModQueueView, isPendingPostView, isPostPageView, isSubscriptionsView } from '../../lib/utils/view-utils';
|
||||||
import { useDefaultSubplebbits } from '../../hooks/use-default-subplebbits';
|
import { useDefaultSubplebbits } from '../../hooks/use-default-subplebbits';
|
||||||
import { getBoardPath, isDirectoryBoard } from '../../lib/utils/route-utils';
|
import { getBoardPath, isDirectoryBoard } from '../../lib/utils/route-utils';
|
||||||
import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address';
|
import { useResolvedSubplebbitAddress } from '../../hooks/use-resolved-subplebbit-address';
|
||||||
@@ -26,6 +26,7 @@ interface BoardButtonsProps {
|
|||||||
isInCatalogView?: boolean;
|
isInCatalogView?: boolean;
|
||||||
isInSubscriptionsView?: boolean;
|
isInSubscriptionsView?: boolean;
|
||||||
isInModView?: boolean;
|
isInModView?: boolean;
|
||||||
|
isInModQueueView?: boolean;
|
||||||
isTopbar?: boolean;
|
isTopbar?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ const SubscribeButton = ({ address }: BoardButtonsProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ReturnButton = ({ address, isInAllView, isInSubscriptionsView, isInModView }: BoardButtonsProps) => {
|
const ReturnButton = ({ address, isInAllView, isInSubscriptionsView, isInModView, isInModQueueView }: BoardButtonsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const defaultSubplebbits = useDefaultSubplebbits();
|
const defaultSubplebbits = useDefaultSubplebbits();
|
||||||
@@ -84,6 +85,12 @@ const ReturnButton = ({ address, isInAllView, isInSubscriptionsView, isInModView
|
|||||||
} else if (isInSubscriptionsView) {
|
} else if (isInSubscriptionsView) {
|
||||||
if (params?.timeFilterName) return `/subs/${params.timeFilterName}`;
|
if (params?.timeFilterName) return `/subs/${params.timeFilterName}`;
|
||||||
return `/subs`;
|
return `/subs`;
|
||||||
|
} else if (isInModQueueView) {
|
||||||
|
// If in mod queue view, return to /mod or /:boardIdentifier
|
||||||
|
if (params?.boardIdentifier) {
|
||||||
|
return `/${params.boardIdentifier}`;
|
||||||
|
}
|
||||||
|
return `/mod`;
|
||||||
} else if (isInModView) {
|
} else if (isInModView) {
|
||||||
if (params?.timeFilterName) return `/mod/${params.timeFilterName}`;
|
if (params?.timeFilterName) return `/mod/${params.timeFilterName}`;
|
||||||
return `/mod`;
|
return `/mod`;
|
||||||
@@ -309,6 +316,7 @@ export const MobileBoardButtons = () => {
|
|||||||
const isInPostView = isPostPageView(location.pathname, params);
|
const isInPostView = isPostPageView(location.pathname, params);
|
||||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
|
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
|
||||||
const isInModView = isModView(location.pathname);
|
const isInModView = isModView(location.pathname);
|
||||||
|
const isInModQueueView = isModQueueView(location.pathname);
|
||||||
|
|
||||||
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
|
const accountComment = useAccountComment({ commentIndex: params?.accountCommentIndex as any });
|
||||||
const resolvedAddress = useResolvedSubplebbitAddress();
|
const resolvedAddress = useResolvedSubplebbitAddress();
|
||||||
@@ -334,6 +342,17 @@ export const MobileBoardButtons = () => {
|
|||||||
<AutoButton />
|
<AutoButton />
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
) : isInModQueueView ? (
|
||||||
|
<>
|
||||||
|
<ReturnButton
|
||||||
|
address={subplebbitAddress}
|
||||||
|
isInAllView={isInAllView}
|
||||||
|
isInSubscriptionsView={isInSubscriptionsView}
|
||||||
|
isInModView={isInModView}
|
||||||
|
isInModQueueView={isInModQueueView}
|
||||||
|
/>
|
||||||
|
<RefreshButton />
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{isInCatalogView ? (
|
{isInCatalogView ? (
|
||||||
@@ -419,6 +438,7 @@ export const DesktopBoardButtons = () => {
|
|||||||
const isInPostView = isPostPageView(location.pathname, params);
|
const isInPostView = isPostPageView(location.pathname, params);
|
||||||
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
|
const isInSubscriptionsView = isSubscriptionsView(location.pathname, useParams());
|
||||||
const isInModView = isModView(location.pathname);
|
const isInModView = isModView(location.pathname);
|
||||||
|
const isInModQueueView = isModQueueView(location.pathname);
|
||||||
|
|
||||||
const { filteredCount, searchText } = useCatalogFiltersStore();
|
const { filteredCount, searchText } = useCatalogFiltersStore();
|
||||||
|
|
||||||
@@ -442,6 +462,19 @@ export const DesktopBoardButtons = () => {
|
|||||||
<PostPageStats />
|
<PostPageStats />
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
|
) : isInModQueueView ? (
|
||||||
|
<>
|
||||||
|
[
|
||||||
|
<ReturnButton
|
||||||
|
address={subplebbitAddress}
|
||||||
|
isInAllView={isInAllView}
|
||||||
|
isInSubscriptionsView={isInSubscriptionsView}
|
||||||
|
isInModView={isInModView}
|
||||||
|
isInModQueueView={isInModQueueView}
|
||||||
|
/>
|
||||||
|
] [
|
||||||
|
<RefreshButton />]
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{isInCatalogView ? (
|
{isInCatalogView ? (
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { useAccountSubplebbits } from '@plebbit/plebbit-react-hooks';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { MultisubSubplebbit } from './use-default-subplebbits';
|
||||||
|
|
||||||
|
export const useAccountSubplebbitsWithMetadata = (): MultisubSubplebbit[] => {
|
||||||
|
const { accountSubplebbits } = useAccountSubplebbits();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
return Object.entries(accountSubplebbits || {}).map(([address, sub]) => ({
|
||||||
|
address,
|
||||||
|
title: (sub as any).title,
|
||||||
|
// We can map other fields if needed
|
||||||
|
}));
|
||||||
|
}, [accountSubplebbits]);
|
||||||
|
};
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import useSubplebbitsStore from '@plebbit/plebbit-react-hooks/dist/stores/subplebbits';
|
import useSubplebbitsStore from '@plebbit/plebbit-react-hooks/dist/stores/subplebbits';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import {
|
||||||
|
isAllView,
|
||||||
|
isBoardView,
|
||||||
|
isCatalogView,
|
||||||
|
isHomeView,
|
||||||
|
isModView,
|
||||||
|
isModQueueView,
|
||||||
|
isPendingPostView,
|
||||||
|
isPostPageView,
|
||||||
|
isSettingsView,
|
||||||
|
isSubscriptionsView,
|
||||||
|
isNotFoundView,
|
||||||
|
ParamsType,
|
||||||
|
} from './view-utils';
|
||||||
|
|
||||||
|
export {
|
||||||
|
isAllView,
|
||||||
|
isBoardView,
|
||||||
|
isCatalogView,
|
||||||
|
isHomeView,
|
||||||
|
isModView,
|
||||||
|
isModQueueView,
|
||||||
|
isPendingPostView,
|
||||||
|
isPostPageView,
|
||||||
|
isSettingsView,
|
||||||
|
isSubscriptionsView,
|
||||||
|
isNotFoundView,
|
||||||
|
};
|
||||||
|
export type { ParamsType };
|
||||||
@@ -106,6 +106,7 @@ export const isFeedRoute = (pathname: string): boolean => {
|
|||||||
|
|
||||||
if (normalizedPath.includes('/thread/')) return false;
|
if (normalizedPath.includes('/thread/')) return false;
|
||||||
if (normalizedPath.startsWith('/pending/')) return false;
|
if (normalizedPath.startsWith('/pending/')) return false;
|
||||||
|
if (normalizedPath.includes('/queue')) return false;
|
||||||
|
|
||||||
const pathWithoutSettings = normalizedPath.replace(/\/settings$/, '');
|
const pathWithoutSettings = normalizedPath.replace(/\/settings$/, '');
|
||||||
|
|
||||||
@@ -137,6 +138,11 @@ export const isPendingPostRoute = (pathname: string): boolean => {
|
|||||||
return normalizedPath.startsWith('/pending/');
|
return normalizedPath.startsWith('/pending/');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isModQueueRoute = (pathname: string): boolean => {
|
||||||
|
const normalizedPath = pathname.replace(/\/settings$/, '');
|
||||||
|
return normalizedPath.includes('/queue');
|
||||||
|
};
|
||||||
|
|
||||||
export const getFeedCacheKey = (pathname: string): string | null => {
|
export const getFeedCacheKey = (pathname: string): string | null => {
|
||||||
let normalizedPath = pathname.endsWith('/') ? pathname.slice(0, -1) : pathname;
|
let normalizedPath = pathname.endsWith('/') ? pathname.slice(0, -1) : pathname;
|
||||||
normalizedPath = normalizedPath.replace(/\/settings$/, '');
|
normalizedPath = normalizedPath.replace(/\/settings$/, '');
|
||||||
@@ -150,6 +156,10 @@ export const getFeedCacheKey = (pathname: string): string | null => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (normalizedPath.includes('/queue')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (isFeedRoute(pathname)) {
|
if (isFeedRoute(pathname)) {
|
||||||
return normalizedPath;
|
return normalizedPath;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ export const isModView = (pathname: string): boolean => {
|
|||||||
return pathname === `/mod` || pathname.startsWith(`/mod/`);
|
return pathname === `/mod` || pathname.startsWith(`/mod/`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isModQueueView = (pathname: string): boolean => {
|
||||||
|
return pathname.includes('/queue');
|
||||||
|
};
|
||||||
|
|
||||||
export const isPendingPostView = (pathname: string, params: ParamsType): boolean => {
|
export const isPendingPostView = (pathname: string, params: ParamsType): boolean => {
|
||||||
return pathname === `/pending/${params.accountCommentIndex}` || pathname === `/pending/${params.accountCommentIndex}/settings`;
|
return pathname === `/pending/${params.accountCommentIndex}` || pathname === `/pending/${params.accountCommentIndex}/settings`;
|
||||||
};
|
};
|
||||||
@@ -101,6 +105,7 @@ export const isNotFoundView = (pathname: string, params: ParamsType): boolean =>
|
|||||||
!isPendingPostView(pathname, params) &&
|
!isPendingPostView(pathname, params) &&
|
||||||
!isPostPageView(pathname, params) &&
|
!isPostPageView(pathname, params) &&
|
||||||
!isSettingsView(pathname, params) &&
|
!isSettingsView(pathname, params) &&
|
||||||
!isSubscriptionsView(pathname, params)
|
!isSubscriptionsView(pathname, params) &&
|
||||||
|
!isModQueueView(pathname)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { persist } from 'zustand/middleware';
|
||||||
|
|
||||||
|
interface ModQueueState {
|
||||||
|
alertThresholdHours: number;
|
||||||
|
selectedBoardFilter: string | null;
|
||||||
|
setAlertThresholdHours: (hours: number) => void;
|
||||||
|
setSelectedBoardFilter: (boardAddress: string | null) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useModQueueStore = create<ModQueueState>()(
|
||||||
|
persist(
|
||||||
|
(set) => ({
|
||||||
|
alertThresholdHours: 6,
|
||||||
|
selectedBoardFilter: null,
|
||||||
|
setAlertThresholdHours: (hours) => set({ alertThresholdHours: hours }),
|
||||||
|
setSelectedBoardFilter: (boardAddress) => set({ selectedBoardFilter: boardAddress }),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'mod-queue-storage',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
export default useModQueueStore;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import ModQueueView from './mod-queue';
|
||||||
|
|
||||||
|
export default ModQueueView;
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
.container {
|
||||||
|
padding: 10px;
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alertThresholdSetting {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alertThresholdSetting label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alertThresholdInput {
|
||||||
|
width: 50px;
|
||||||
|
padding: 4px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: var(--input-background-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tableHeader {
|
||||||
|
display: flex;
|
||||||
|
padding: 8px;
|
||||||
|
border-bottom: 2px solid var(--border-color);
|
||||||
|
background: var(--header-background-color);
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boardHeader {
|
||||||
|
width: 50px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.excerptHeader {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeHeader {
|
||||||
|
width: 80px;
|
||||||
|
text-align: right;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actionsHeader {
|
||||||
|
width: 150px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ModQueueRow styles */
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background-color: var(--post-background-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row:hover {
|
||||||
|
background-color: var(--post-highlight-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.board {
|
||||||
|
width: 50px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.excerpt {
|
||||||
|
flex-grow: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.excerpt a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.excerpt a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
width: 80px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--secondary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.time.alert {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
animation: blink 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0% { opacity: 1; }
|
||||||
|
50% { opacity: 0.5; }
|
||||||
|
100% { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
width: 150px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: var(--button-background);
|
||||||
|
color: var(--button-text);
|
||||||
|
font-size: 11px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background: var(--button-hover-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.approve {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reject {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ModQueueBoardFilter styles */
|
||||||
|
.filterContainer {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filterSelect {
|
||||||
|
padding: 4px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
background: var(--input-background-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ModQueueButton styles */
|
||||||
|
.modQueueButton {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 8px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--text-color);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modQueueButton:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modQueueButtonCount {
|
||||||
|
margin-left: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modQueueButtonAlert {
|
||||||
|
color: red;
|
||||||
|
animation: blink 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile Layout */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.tableHeader {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.board {
|
||||||
|
width: auto;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
margin-left: auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.excerpt {
|
||||||
|
width: 100%;
|
||||||
|
margin: 4px 0;
|
||||||
|
white-space: normal;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
width: 100%;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,303 @@
|
|||||||
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useParams, Link } from 'react-router-dom';
|
||||||
|
import { useAccountSubplebbits, useFeed, Comment, usePublishCommentModeration } from '@plebbit/plebbit-react-hooks';
|
||||||
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
|
import { formatDistanceToNow } from 'date-fns';
|
||||||
|
import styles from './mod-queue.module.css';
|
||||||
|
import useModQueueStore from '../../stores/use-mod-queue-store';
|
||||||
|
import { useAccountSubplebbitsWithMetadata } from '../../hooks/use-account-subplebbits-with-metadata';
|
||||||
|
import LoadingEllipsis from '../../components/loading-ellipsis';
|
||||||
|
import { useFeedStateString } from '../../hooks/use-state-string';
|
||||||
|
import { getSubplebbitAddress, getBoardPath } from '../../lib/utils/route-utils';
|
||||||
|
import { useDefaultSubplebbits, MultisubSubplebbit } from '../../hooks/use-default-subplebbits';
|
||||||
|
import { useBoardPath } from '../../hooks/use-resolved-subplebbit-address';
|
||||||
|
import { getHasThumbnail, getCommentMediaInfo } from '../../lib/utils/media-utils';
|
||||||
|
import useFeedResetStore from '../../stores/use-feed-reset-store';
|
||||||
|
|
||||||
|
interface ModQueueViewProps {
|
||||||
|
boardIdentifier?: string; // If provided, shows queue for single board
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ModQueueRowProps {
|
||||||
|
comment: Comment;
|
||||||
|
showBoardColumn?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModQueueRow = ({ comment, showBoardColumn = false }: ModQueueRowProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { alertThresholdHours } = useModQueueStore();
|
||||||
|
const [isModerating, setIsModerating] = useState(false);
|
||||||
|
|
||||||
|
const { content, title, timestamp, subplebbitAddress, cid, threadCid, link, thumbnailUrl, linkWidth, linkHeight } = comment;
|
||||||
|
|
||||||
|
const boardPath = useBoardPath(subplebbitAddress);
|
||||||
|
const timeWaiting = Date.now() / 1000 - timestamp;
|
||||||
|
const isOverThreshold = timeWaiting > alertThresholdHours * 3600;
|
||||||
|
|
||||||
|
const { publishCommentModeration: approve } = usePublishCommentModeration({
|
||||||
|
commentCid: cid,
|
||||||
|
subplebbitAddress,
|
||||||
|
commentModeration: { approved: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { publishCommentModeration: reject } = usePublishCommentModeration({
|
||||||
|
commentCid: cid,
|
||||||
|
subplebbitAddress,
|
||||||
|
commentModeration: { removed: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleApprove = async () => {
|
||||||
|
try {
|
||||||
|
setIsModerating(true);
|
||||||
|
await approve();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
setIsModerating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReject = async () => {
|
||||||
|
try {
|
||||||
|
setIsModerating(true);
|
||||||
|
await reject();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
setIsModerating(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isModerating) {
|
||||||
|
return null; // Or show a loading state / fade out
|
||||||
|
}
|
||||||
|
|
||||||
|
const excerpt = title || content || (getHasThumbnail(getCommentMediaInfo(link, thumbnailUrl, linkWidth, linkHeight), link) ? t('image') : t('no_content'));
|
||||||
|
const postUrl = `/${boardPath}/thread/${threadCid || cid}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.row}>
|
||||||
|
{showBoardColumn && (
|
||||||
|
<div className={styles.board}>
|
||||||
|
<Link to={`/${boardPath}`}>/{boardPath}/</Link>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className={styles.excerpt}>
|
||||||
|
<Link to={postUrl} title={excerpt}>
|
||||||
|
{excerpt}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div className={`${styles.time} ${isOverThreshold ? styles.alert : ''}`}>{formatDistanceToNow(timestamp * 1000, { addSuffix: false })}</div>
|
||||||
|
<div className={styles.actions}>
|
||||||
|
<button className={`${styles.button} ${styles.approve}`} onClick={handleApprove}>
|
||||||
|
{t('approve')}
|
||||||
|
</button>
|
||||||
|
<button className={`${styles.button} ${styles.reject}`} onClick={handleReject}>
|
||||||
|
{t('reject')}
|
||||||
|
</button>
|
||||||
|
<Link to={postUrl} className={styles.button}>
|
||||||
|
{t('view')}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ModQueueBoardFilterProps {
|
||||||
|
subplebbits: MultisubSubplebbit[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const ModQueueBoardFilter = ({ subplebbits }: ModQueueBoardFilterProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { selectedBoardFilter, setSelectedBoardFilter } = useModQueueStore();
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
setSelectedBoardFilter(value === '' ? null : value);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!subplebbits || subplebbits.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.filterContainer}>
|
||||||
|
<label>{t('filter_by_board')}:</label>
|
||||||
|
<select className={styles.filterSelect} value={selectedBoardFilter || ''} onChange={handleChange}>
|
||||||
|
<option value=''>{t('all_boards')}</option>
|
||||||
|
{subplebbits.map((sub) => {
|
||||||
|
const address = sub.address;
|
||||||
|
if (!address) return null;
|
||||||
|
return (
|
||||||
|
<option key={address} value={address}>
|
||||||
|
/{getBoardPath(address, subplebbits)}/
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ModQueueButtonProps {
|
||||||
|
boardIdentifier?: string;
|
||||||
|
isMobile?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ModQueueButton = ({ boardIdentifier, isMobile }: ModQueueButtonProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { alertThresholdHours } = useModQueueStore();
|
||||||
|
const { accountSubplebbits } = useAccountSubplebbits();
|
||||||
|
const accountSubplebbitAddresses = useMemo(() => Object.keys(accountSubplebbits || {}), [accountSubplebbits]);
|
||||||
|
|
||||||
|
const subplebbitAddresses = useMemo(() => {
|
||||||
|
if (boardIdentifier) {
|
||||||
|
return [boardIdentifier];
|
||||||
|
}
|
||||||
|
return accountSubplebbitAddresses;
|
||||||
|
}, [boardIdentifier, accountSubplebbitAddresses]);
|
||||||
|
|
||||||
|
// If specific board, check if user is mod
|
||||||
|
const isModOfBoard = boardIdentifier ? accountSubplebbitAddresses.includes(boardIdentifier) : true;
|
||||||
|
|
||||||
|
// Only fetch if we have addresses to check and permissions
|
||||||
|
const shouldFetch = subplebbitAddresses.length > 0 && isModOfBoard;
|
||||||
|
|
||||||
|
const { feed } = useFeed({
|
||||||
|
subplebbitAddresses: shouldFetch ? subplebbitAddresses : [],
|
||||||
|
modQueue: ['pendingApproval'],
|
||||||
|
postsPerPage: 100, // Fetch enough to check timestamps
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!shouldFetch || subplebbitAddresses.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = feed.length;
|
||||||
|
|
||||||
|
const hasAlert = feed.some((item) => {
|
||||||
|
const timeWaiting = Date.now() / 1000 - item.timestamp;
|
||||||
|
return timeWaiting > alertThresholdHours * 3600;
|
||||||
|
});
|
||||||
|
|
||||||
|
const to = boardIdentifier ? `/${boardIdentifier}/queue` : '/mod/queue';
|
||||||
|
|
||||||
|
if (count === 0) {
|
||||||
|
// If we are on a specific board and the user is a mod, we still show the button
|
||||||
|
// If we are in global mod view, we show it too
|
||||||
|
return (
|
||||||
|
<Link to={to} className={styles.modQueueButton}>
|
||||||
|
[{t('mod_queue')}]
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={to} className={`${styles.modQueueButton} ${hasAlert ? styles.modQueueButtonAlert : ''}`}>
|
||||||
|
[{t('mod_queue')} <span className={styles.modQueueButtonCount}>{count}</span>]
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ModQueueView = ({ boardIdentifier: propBoardIdentifier }: ModQueueViewProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const params = useParams();
|
||||||
|
const { selectedBoardFilter, alertThresholdHours, setAlertThresholdHours } = useModQueueStore();
|
||||||
|
const { accountSubplebbits } = useAccountSubplebbits();
|
||||||
|
const accountSubplebbitAddresses = Object.keys(accountSubplebbits);
|
||||||
|
const defaultSubplebbits = useDefaultSubplebbits();
|
||||||
|
|
||||||
|
const boardIdentifier = propBoardIdentifier || params.boardIdentifier;
|
||||||
|
|
||||||
|
// Resolve boardIdentifier to address if it exists
|
||||||
|
const resolvedAddress = useMemo(() => {
|
||||||
|
if (boardIdentifier) {
|
||||||
|
return getSubplebbitAddress(boardIdentifier, defaultSubplebbits);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}, [boardIdentifier, defaultSubplebbits]);
|
||||||
|
|
||||||
|
// Get metadata for filter dropdown
|
||||||
|
const subplebbitsWithMetadata = useAccountSubplebbitsWithMetadata();
|
||||||
|
|
||||||
|
const subplebbitAddresses = useMemo(() => {
|
||||||
|
if (resolvedAddress) {
|
||||||
|
return [resolvedAddress];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedBoardFilter) {
|
||||||
|
return [selectedBoardFilter];
|
||||||
|
}
|
||||||
|
|
||||||
|
return accountSubplebbitAddresses;
|
||||||
|
}, [resolvedAddress, selectedBoardFilter, accountSubplebbitAddresses]);
|
||||||
|
|
||||||
|
const { feed, hasMore, loadMore, reset } = useFeed({
|
||||||
|
subplebbitAddresses,
|
||||||
|
modQueue: ['pendingApproval'],
|
||||||
|
postsPerPage: 50,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register reset function with feed reset store so refresh button works
|
||||||
|
const setResetFunction = useFeedResetStore((state) => state.setResetFunction);
|
||||||
|
useEffect(() => {
|
||||||
|
setResetFunction(reset);
|
||||||
|
}, [reset, setResetFunction]);
|
||||||
|
|
||||||
|
const loadingStateString = useFeedStateString(subplebbitAddresses) || t('loading');
|
||||||
|
const showBoardColumn = !resolvedAddress && !selectedBoardFilter;
|
||||||
|
|
||||||
|
const Footer = () => {
|
||||||
|
return hasMore ? (
|
||||||
|
<div style={{ padding: '10px', textAlign: 'center' }}>
|
||||||
|
<LoadingEllipsis string={loadingStateString} />
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.header}>
|
||||||
|
<div className={styles.title}>{t('moderation_queue')}</div>
|
||||||
|
<div className={styles.alertThresholdSetting}>
|
||||||
|
<label>
|
||||||
|
{t('mod_queue_alert_threshold')}:
|
||||||
|
<input
|
||||||
|
type='number'
|
||||||
|
min='1'
|
||||||
|
value={alertThresholdHours}
|
||||||
|
onChange={(e) => setAlertThresholdHours(Number(e.target.value))}
|
||||||
|
className={styles.alertThresholdInput}
|
||||||
|
/>{' '}
|
||||||
|
{t('hours')}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!resolvedAddress && <ModQueueBoardFilter subplebbits={subplebbitsWithMetadata} />}
|
||||||
|
|
||||||
|
{feed.length === 0 && !hasMore ? (
|
||||||
|
<div className={styles.empty}>{t('queue_is_empty')}</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className={styles.tableHeader}>
|
||||||
|
{showBoardColumn && <div className={styles.boardHeader}>{t('board')}</div>}
|
||||||
|
<div className={styles.excerptHeader}>{t('excerpt')}</div>
|
||||||
|
<div className={styles.timeHeader}>{t('waiting')}</div>
|
||||||
|
<div className={styles.actionsHeader}>{t('actions')}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Virtuoso
|
||||||
|
useWindowScroll
|
||||||
|
data={feed}
|
||||||
|
totalCount={feed.length}
|
||||||
|
endReached={loadMore}
|
||||||
|
itemContent={(index, comment) => <ModQueueRow key={comment.cid} comment={comment} showBoardColumn={showBoardColumn} />}
|
||||||
|
components={{ Footer }}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModQueueView;
|
||||||
Reference in New Issue
Block a user