feat: add campaign/partner filters, delete_user action, and fix modal positioning in AdminBulkActions

Add campaign and partner filter dropdowns for user filtering, implement
delete_user bulk action with delete_from_panel checkbox, fix ActionModal
to use createPortal with viewport-fixed positioning and safe area insets.
This commit is contained in:
Fringg
2026-04-24 16:04:20 +03:00
parent 5cfbce0663
commit b01ffe3309
7 changed files with 372 additions and 10 deletions

View File

@@ -2043,12 +2043,18 @@
"assignPromoGroup": "Assign promo group",
"grantSubscription": "Grant subscription",
"setDevices": "Set devices",
"deleteSubscription": "Delete subscriptions"
"deleteSubscription": "Delete subscriptions",
"deleteUser": "Delete users"
},
"deleteSubscription": {
"warning": "Selected subscriptions will be permanently deleted from the bot and RemnaWave panel!",
"hint": "Users will lose VPN access for deleted subscriptions. This action cannot be undone."
},
"deleteUser": {
"warning": "Selected users will be permanently deleted from the bot! All their subscriptions, balance, and data will be lost!",
"hint": "This action cannot be undone. Users will need to restart the bot to create a new account.",
"deleteFromPanel": "Also delete from RemnaWave panel"
},
"params": {
"days": "Number of days",
"tariff": "Select tariff",
@@ -2088,6 +2094,8 @@
"allStatuses": "All statuses",
"allTariffs": "All tariffs",
"allGroups": "All groups",
"allCampaigns": "All campaigns",
"allPartners": "All partners",
"trialOnly": "Trial only",
"tariffsSelected": "{{count}} tariffs",
"selectAll": "Select all",

View File

@@ -3437,6 +3437,113 @@
"zh": "چینی",
"fa": "فارسی"
}
},
"bulkActions": {
"title": "عملیات دسته‌ای",
"subtitle": "مدیریت کاربران",
"selectedCount": "انتخاب شده: {{count}}",
"selectAll": "انتخاب همه",
"deselectAll": "لغو انتخاب همه",
"selectUser": "انتخاب کاربر {{name}}",
"deselectUser": "لغو انتخاب کاربر {{name}}",
"noResults": "کاربری یافت نشد",
"perPage": "در هر صفحه",
"actions": {
"extend": "تمدید اشتراک",
"cancel": "غیرفعال‌سازی اشتراک‌ها",
"activate": "فعال‌سازی اشتراک‌ها",
"changeTariff": "تغییر تعرفه",
"addTraffic": "افزودن ترافیک",
"addBalance": "افزودن موجودی",
"assignPromoGroup": "اختصاص گروه تبلیغاتی",
"grantSubscription": "اعطای اشتراک",
"setDevices": "تنظیم دستگاه‌ها",
"deleteSubscription": "حذف اشتراک‌ها",
"deleteUser": "حذف کاربران"
},
"deleteSubscription": {
"warning": "اشتراک‌های انتخاب شده برای همیشه از ربات و پنل RemnaWave حذف خواهند شد!",
"hint": "کاربران دسترسی VPN اشتراک‌های حذف شده را از دست خواهند داد. این عملیات قابل بازگشت نیست."
},
"deleteUser": {
"warning": "کاربران انتخاب شده برای همیشه از ربات حذف خواهند شد! تمام اشتراک‌ها، موجودی و داده‌های آن‌ها از بین خواهد رفت!",
"hint": "این عملیات قابل بازگشت نیست. کاربران باید ربات را دوباره راه‌اندازی کنند تا حساب جدید بسازند.",
"deleteFromPanel": "همچنین از پنل RemnaWave حذف شود"
},
"params": {
"days": "تعداد روز",
"tariff": "انتخاب تعرفه",
"trafficGb": "حجم ترافیک (GB)",
"balanceRub": "مبلغ (روبل)",
"promoGroup": "گروه تبلیغاتی",
"removePromoGroup": "حذف گروه تبلیغاتی",
"deviceLimit": "تعداد دستگاه"
},
"grantSubscription": {
"warning": "کاربرانی که قبلا اشتراک تعرفه انتخاب شده را دارند رد خواهند شد"
},
"confirm": "اعمال",
"cancel": "انصراف",
"executing": "در حال اجرا...",
"complete": "انجام شد",
"successCount": "موفق: {{count}}",
"errorCount": "خطا: {{count}}",
"progress": {
"processed": "پردازش شده: {{current}} / {{total}}",
"succeeded": "موفق",
"failed": "ناموفق",
"ok": "OK",
"errorGeneric": "خطا",
"doNotClose": "لطفا تا پایان عملیات این پنجره را نبندید",
"summarySuccess": "{{count}} موفق",
"summaryErrors": "{{count}} خطا"
},
"errors": {
"title": "{{count}} خطا — نمایش جزئیات"
},
"filters": {
"search": "جستجو بر اساس شناسه، نام کاربری، ایمیل",
"status": "وضعیت اشتراک",
"tariff": "تعرفه",
"promoGroup": "گروه تبلیغاتی",
"allStatuses": "همه وضعیت‌ها",
"allTariffs": "همه تعرفه‌ها",
"allGroups": "همه گروه‌ها",
"allCampaigns": "همه کمپین‌ها",
"allPartners": "همه شرکا",
"trialOnly": "فقط آزمایشی",
"tariffsSelected": "{{count}} تعرفه",
"selectAll": "انتخاب همه",
"deselectAll": "لغو انتخاب همه"
},
"statuses": {
"active": "فعال",
"expired": "منقضی",
"trial": "آزمایشی",
"limited": "محدود",
"disabled": "غیرفعال"
},
"columns": {
"user": "کاربر",
"status": "وضعیت",
"tariff": "تعرفه",
"balance": "موجودی",
"daysRemaining": "روز",
"promoGroup": "گروه",
"spent": "خرج شده"
},
"subscriptionsSelected": "{{count}} اشتراک انتخاب شده",
"usersSelected": "{{count}} کاربر انتخاب شده",
"expandSubscriptions": "نمایش اشتراک‌ها",
"collapseSubscriptions": "پنهان کردن اشتراک‌ها",
"noSubscriptions": "بدون اشتراک",
"subscriptionTarget": "هدف: اشتراک‌ها",
"userTarget": "هدف: کاربران",
"daysUnit": "روز",
"trafficOf": "از",
"trafficGbUnit": "GB",
"selectAllSubs": "انتخاب همه اشتراک‌ها",
"deselectAllSubs": "لغو انتخاب همه اشتراک‌ها"
}
},
"adminUpdates": {

View File

@@ -3791,12 +3791,18 @@
"assignPromoGroup": "Назначить промогруппу",
"grantSubscription": "Выдать подписку",
"setDevices": "Изменить устройства",
"deleteSubscription": "Удалить подписки"
"deleteSubscription": "Удалить подписки",
"deleteUser": "Удалить пользователей"
},
"deleteSubscription": {
"warning": "Выбранные подписки будут безвозвратно удалены из бота и панели RemnaWave!",
"hint": "Пользователи потеряют доступ к VPN по удалённым подпискам. Это действие нельзя отменить."
},
"deleteUser": {
"warning": "Выбранные пользователи будут безвозвратно удалены из бота! Все их подписки, баланс и данные будут потеряны!",
"hint": "Это действие нельзя отменить. Пользователям придётся заново запустить бота для создания нового аккаунта.",
"deleteFromPanel": "Также удалить из панели RemnaWave"
},
"params": {
"days": "Количество дней",
"tariff": "Выберите тариф",
@@ -3836,6 +3842,8 @@
"allStatuses": "Все статусы",
"allTariffs": "Все тарифы",
"allGroups": "Все группы",
"allCampaigns": "Все кампании",
"allPartners": "Все партнёры",
"trialOnly": "Только триал",
"tariffsSelected": "{{count}} тарифов",
"selectAll": "Выбрать все",

View File

@@ -3436,6 +3436,113 @@
"zh": "中文",
"fa": "波斯语"
}
},
"bulkActions": {
"title": "批量操作",
"subtitle": "用户管理",
"selectedCount": "已选择: {{count}}",
"selectAll": "全选",
"deselectAll": "取消全选",
"selectUser": "选择用户 {{name}}",
"deselectUser": "取消选择用户 {{name}}",
"noResults": "未找到用户",
"perPage": "每页",
"actions": {
"extend": "延长订阅",
"cancel": "停用订阅",
"activate": "激活订阅",
"changeTariff": "更改套餐",
"addTraffic": "添加流量",
"addBalance": "添加余额",
"assignPromoGroup": "分配促销组",
"grantSubscription": "授予订阅",
"setDevices": "设置设备数",
"deleteSubscription": "删除订阅",
"deleteUser": "删除用户"
},
"deleteSubscription": {
"warning": "选中的订阅将从机器人和RemnaWave面板中永久删除",
"hint": "用户将失去已删除订阅的VPN访问权限。此操作无法撤销。"
},
"deleteUser": {
"warning": "选中的用户将从机器人中永久删除!他们的所有订阅、余额和数据将丢失!",
"hint": "此操作无法撤销。用户需要重新启动机器人以创建新账户。",
"deleteFromPanel": "同时从RemnaWave面板删除"
},
"params": {
"days": "天数",
"tariff": "选择套餐",
"trafficGb": "流量 (GB)",
"balanceRub": "金额 (卢布)",
"promoGroup": "促销组",
"removePromoGroup": "移除促销组",
"deviceLimit": "设备数量"
},
"grantSubscription": {
"warning": "已拥有所选套餐订阅的用户将被跳过"
},
"confirm": "应用",
"cancel": "取消",
"executing": "执行中...",
"complete": "完成",
"successCount": "成功: {{count}}",
"errorCount": "错误: {{count}}",
"progress": {
"processed": "已处理: {{current}} / {{total}}",
"succeeded": "成功",
"failed": "失败",
"ok": "OK",
"errorGeneric": "错误",
"doNotClose": "操作进行中请勿关闭此窗口",
"summarySuccess": "{{count}} 成功",
"summaryErrors": "{{count}} 错误"
},
"errors": {
"title": "{{count}} 个错误 — 显示详情"
},
"filters": {
"search": "按ID、用户名、邮箱搜索",
"status": "订阅状态",
"tariff": "套餐",
"promoGroup": "促销组",
"allStatuses": "所有状态",
"allTariffs": "所有套餐",
"allGroups": "所有组",
"allCampaigns": "所有活动",
"allPartners": "所有合作伙伴",
"trialOnly": "仅试用",
"tariffsSelected": "{{count}} 个套餐",
"selectAll": "全选",
"deselectAll": "取消全选"
},
"statuses": {
"active": "活跃",
"expired": "已过期",
"trial": "试用",
"limited": "受限",
"disabled": "已禁用"
},
"columns": {
"user": "用户",
"status": "状态",
"tariff": "套餐",
"balance": "余额",
"daysRemaining": "天数",
"promoGroup": "组",
"spent": "已消费"
},
"subscriptionsSelected": "已选择 {{count}} 个订阅",
"usersSelected": "已选择 {{count}} 个用户",
"expandSubscriptions": "显示订阅",
"collapseSubscriptions": "隐藏订阅",
"noSubscriptions": "无订阅",
"subscriptionTarget": "目标: 订阅",
"userTarget": "目标: 用户",
"daysUnit": "天",
"trafficOf": "/",
"trafficGbUnit": "GB",
"selectAllSubs": "选择所有订阅",
"deselectAllSubs": "取消选择所有订阅"
}
},
"adminUpdates": {