Implement support ticket system with role request and bug report functionalities
CI / Backend (build + test) (push) Successful in 1m18s
CI / Frontend (lint + typecheck + build) (push) Successful in 31s

- Introduced a new support ticket system allowing users to submit bug reports and role requests.
- Implemented endpoints for creating, updating, and managing support tickets, including file attachments.
- Enhanced Telegram bot integration to handle role requests directly within the bot, enabling admins to approve or reject requests without accessing the website.
- Updated database schema to include support ticket entities and their relationships.
- Improved API documentation to reflect new support ticket endpoints and their usage.
- Added necessary localization for support ticket features in both Russian and English.
This commit is contained in:
Leonid Pershin
2026-07-14 06:49:05 +03:00
parent 14b64a3140
commit b5630b2685
98 changed files with 4463 additions and 6 deletions
+98
View File
@@ -49,6 +49,7 @@ const resources = {
dashboard: 'Мои конфиги',
instructions: 'Инструкции',
news: 'Новости',
support: 'Поддержка',
settings: 'Настройки',
admin: 'Админка',
logout: 'Выйти',
@@ -121,6 +122,42 @@ const resources = {
empty: 'Пока нет новостей.',
},
support: {
title: 'Поддержка',
empty: 'У вас пока нет обращений.',
reportBug: 'Сообщить об ошибке',
requestRole: 'Запросить роль',
submit: 'Отправить',
messageLabel: 'Опишите проблему или предложение',
attachmentsLabel: 'Скриншоты (необязательно, до 5)',
filesSelected: '{{count}} файл(ов) выбрано',
existingRole: 'Существующая роль',
newRole: 'Новая роль',
selectRole: 'Выберите роль',
newRoleName: 'Название роли',
newRoleMaxConfigs: 'Количество конфигов (-1 — без лимита)',
newRoleMaxIpLimit: 'Количество IP (-1 — без лимита)',
justification: 'Обоснование',
ticketCreated: 'Обращение отправлено.',
roleRequestPending: 'У вас уже есть необработанная заявка на роль.',
reply: 'Ответить',
replyPlaceholder: 'Написать комментарий…',
reopen: 'Переоткрыть',
reopened: 'Тикет переоткрыт.',
lastActivity: 'Последняя активность: {{date}}',
requestedExistingRole: 'Запрошена роль: {{role}}',
requestedNewRole: 'Запрошена новая роль «{{name}}» (конфигов: {{configs}}, IP: {{ip}})',
type: {
BugReport: 'Ошибка/предложение',
RoleRequest: 'Заявка на роль',
},
status: {
Open: 'Открыт',
Resolved: 'Решён',
Closed: 'Закрыт',
},
},
settings: {
changePassword: 'Сменить пароль',
currentPassword: 'Текущий пароль',
@@ -159,6 +196,7 @@ const resources = {
nodes: 'Ноды',
apps: 'Приложения',
news: 'Новости',
support: 'Поддержка',
audit: 'Аудит',
},
users: {
@@ -289,6 +327,17 @@ const resources = {
deleted: 'Новость удалена.',
confirmDelete: 'Удалить новость?',
},
support: {
empty: 'Обращений пока нет.',
resolve: 'Решено',
resolved: 'Тикет отмечен как решённый.',
close: 'Закрыть',
closed: 'Тикет закрыт.',
approve: 'Одобрить',
approved: 'Заявка одобрена, роль выдана.',
reject: 'Отклонить',
rejected: 'Заявка отклонена.',
},
audit: {
time: 'Время',
action: 'Действие',
@@ -356,6 +405,7 @@ const resources = {
dashboard: 'My configs',
instructions: 'Instructions',
news: 'News',
support: 'Support',
settings: 'Settings',
admin: 'Admin',
logout: 'Log out',
@@ -428,6 +478,42 @@ const resources = {
empty: 'No news yet.',
},
support: {
title: 'Support',
empty: 'You have no tickets yet.',
reportBug: 'Report a bug',
requestRole: 'Request a role',
submit: 'Submit',
messageLabel: 'Describe the issue or suggestion',
attachmentsLabel: 'Screenshots (optional, up to 5)',
filesSelected: '{{count}} file(s) selected',
existingRole: 'Existing role',
newRole: 'New role',
selectRole: 'Select a role',
newRoleName: 'Role name',
newRoleMaxConfigs: 'Max configs (-1 = unlimited)',
newRoleMaxIpLimit: 'Max IPs (-1 = unlimited)',
justification: 'Justification',
ticketCreated: 'Ticket submitted.',
roleRequestPending: 'You already have a pending role request.',
reply: 'Reply',
replyPlaceholder: 'Write a comment…',
reopen: 'Reopen',
reopened: 'Ticket reopened.',
lastActivity: 'Last activity: {{date}}',
requestedExistingRole: 'Requested role: {{role}}',
requestedNewRole: 'Requested new role "{{name}}" (configs: {{configs}}, IPs: {{ip}})',
type: {
BugReport: 'Bug/suggestion',
RoleRequest: 'Role request',
},
status: {
Open: 'Open',
Resolved: 'Resolved',
Closed: 'Closed',
},
},
settings: {
changePassword: 'Change password',
currentPassword: 'Current password',
@@ -466,6 +552,7 @@ const resources = {
nodes: 'Nodes',
apps: 'Apps',
news: 'News',
support: 'Support',
audit: 'Audit',
},
users: {
@@ -596,6 +683,17 @@ const resources = {
deleted: 'Post deleted.',
confirmDelete: 'Delete this post?',
},
support: {
empty: 'No tickets yet.',
resolve: 'Resolve',
resolved: 'Ticket marked as resolved.',
close: 'Close',
closed: 'Ticket closed.',
approve: 'Approve',
approved: 'Request approved, role granted.',
reject: 'Reject',
rejected: 'Request rejected.',
},
audit: {
time: 'Time',
action: 'Action',