Corp/docs/completed/REACTIONS_FROM_DATABASE.md
Игорь Надеин 48631f43fd Реорганизация документации и скриптов проекта
- Создана структура docs/ с категориями: completed, guides, architecture, diagnostic, in-progress, reports
- Перемещено 47+ MD файлов из корня проекта в docs/
- Удалено 6 устаревших/дублирующихся файлов
- Создана структура backend/scripts/ для тестов и утилит
- Перемещено 35 Python скриптов в backend/scripts/
- Создана структура backend/docs/ для технической документации
- Перемещено 12 MD файлов backend в backend/docs/
- Перемещены LDAP тестовые данные в backend/tests/fixtures/
- Добавлены README файлы для навигации
- Добавлены правила в .github/copilot-instructions.md для размещения документации

Результат:
- Корень проекта: только README.md
- Корень backend/: только manage.py и Django приложения
- Вся документация организована в структурированные папки
2025-12-26 13:49:51 +03:00

9.9 KiB
Raw Blame History

Система управления реакциями из БД

Обзор

Система доступных реакций теперь полностью управляется через базу данных вместо жёсткого кодирования в JavaScript.

Архитектура

Backend

Модель AvailableReaction

# communications/models.py
class AvailableReaction(models.Model):
    emoji = models.CharField(max_length=10, unique=True)
    name = models.CharField(max_length=50)
    order = models.IntegerField(default=0)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

Поля:

  • emoji - Unicode эмодзи (👍, ❤️, и т.д.)
  • name - Человекочитаемое название ("Лайк", "Сердце")
  • order - Порядок отображения (меньше = выше)
  • is_active - Вкл/выкл реакцию без удаления
  • created_at - Дата добавления

API Endpoint

GET /api/v1/communications/reactions/available/

Response:

{
  "ok": true,
  "reactions": [
    {
      "emoji": "👍",
      "name": "Лайк",
      "order": 1
    },
    {
      "emoji": "❤️",
      "name": "Сердце",
      "order": 2
    }
  ]
}

Требования:

  • Требуется авторизация (@login_required)
  • Возвращает только активные реакции (is_active=True)
  • Отсортировано по полю order

Admin-панель

# communications/admin.py
@admin.register(AvailableReaction)
class AvailableReactionAdmin(admin.ModelAdmin):
    list_display = ('emoji', 'name', 'order', 'is_active', 'created_at')
    list_editable = ('order', 'is_active')
    ordering = ('order', 'created_at')

Возможности:

  • Добавление/удаление реакций через admin
  • Редактирование порядка прямо в списке
  • Быстрое включение/выключение реакций
  • Поиск по эмодзи и названию

Frontend

ReactionsConfig (Синглтон)

// static/js/config/reactionsConfig.js
import reactionsConfig from './config/reactionsConfig.js';

// Загрузка из API
await reactionsConfig.load();

// Получить массив эмодзи
const emojis = reactionsConfig.getEmojis(); // ['👍', '❤️', ...]

// Проверить доступность
if (reactionsConfig.isAvailable('👍')) { ... }

// Получить название
const name = reactionsConfig.getName('👍'); // "Лайк"

Особенности:

  • Загружается один раз при инициализации чата
  • Кэширует результат (повторные вызовы .load() возвращают кэш)
  • Fallback на дефолтные реакции при ошибке API
  • Promise-based (поддержка async/await)

Использование в chat-detail-enhanced.js

// До инициализации компонентов загружаем реакции
await reactionsConfig.load();
const availableEmojis = reactionsConfig.getEmojis();

// Передаём в MessageContextMenu
const contextMenu = new MessageContextMenu({
    currentUserId: meId,
    emojis: availableEmojis,  // ← Из БД!
    onReactionSelect: async (messageId, emoji) => {
        await reactions.addReaction(messageId, emoji);
    }
});

Инициализация

1. Создание миграции

cd backend
python manage.py makemigrations communications
python manage.py migrate communications

2. Добавление дефолтных реакций

python manage.py init_reactions

Эта команда создаст 8 стандартных реакций:

  • 👍 Лайк
  • ❤️ Сердце
  • 😂 Смех
  • 😮 Удивление
  • 😢 Грусть
  • 🙏 Спасибо
  • 👏 Аплодисменты
  • 🔥 Огонь

3. Проверка

python check_reactions.py

Управление реакциями

Через Admin-панель

  1. Перейти в /admin/communications/availablereaction/
  2. Добавить новую реакцию:
    • Emoji: вставить эмодзи (Ctrl+V)
    • Name: название на русском
    • Order: порядковый номер
    • Is active: ✓
  3. Сохранить

Изменение порядка:

  • В списке реакций отредактировать поле "Order"
  • Нажать "Сохранить" внизу страницы

Отключение реакции:

  • Снять галочку "Is active"
  • Нажать "Сохранить"

Программно

from communications.models import AvailableReaction

# Добавить новую реакцию
AvailableReaction.objects.create(
    emoji='🎉',
    name='Праздник',
    order=9,
    is_active=True
)

# Изменить порядок
reaction = AvailableReaction.objects.get(emoji='👍')
reaction.order = 1
reaction.save()

# Отключить реакцию
reaction.is_active = False
reaction.save()

# Удалить реакцию (не рекомендуется, лучше is_active=False)
reaction.delete()

Data Flow

[БД] AvailableReaction
  ↓
[Backend API] /api/v1/communications/reactions/available/
  ↓
[Frontend] reactionsConfig.load()
  ↓
[Cache] reactionsConfig.reactions
  ↓
[Component] MessageContextMenu({ emojis: [...] })
  ↓
[UI] Контекстное меню с реакциями

Преимущества

  1. Централизованное управление - одно место для изменений
  2. Без deploy - изменения через admin без перезапуска
  3. Гибкость - разные реакции для разных чатов (будущее)
  4. Локализация - названия реакций на нужном языке
  5. Аналитика - можно отслеживать популярность реакций
  6. Валидация - можно проверять доступность эмодзи перед использованием

Миграция со старого подхода

Было (hardcoded):

const contextMenu = new MessageContextMenu({
    emojis: ['👍', '❤️', '😂', '😮', '😢', '🙏', '👏', '🔥']
});

Стало (из БД):

await reactionsConfig.load();
const contextMenu = new MessageContextMenu({
    emojis: reactionsConfig.getEmojis()
});

Совместимость

  • Fallback - если API недоступен, используются дефолтные реакции
  • Кэширование - одна загрузка на сессию чата
  • Promise-safe - множественные вызовы .load() возвращают один промис

Расширения

Реакции по категориям чата

class AvailableReaction(models.Model):
    ...
    chat_types = models.JSONField(
        default=list,
        help_text="['personal', 'group', 'department']"
    )

Кастомные реакции

class AvailableReaction(models.Model):
    ...
    is_custom = models.BooleanField(default=False)
    uploaded_by = models.ForeignKey('employees.Employee', ...)
    image = models.ImageField(...)  # Для не-эмодзи реакций

Статистика

class ReactionStats(models.Model):
    reaction = models.ForeignKey(AvailableReaction, ...)
    usage_count = models.IntegerField(default=0)
    last_used = models.DateTimeField(...)

Troubleshooting

Реакции не загружаются

  1. Проверить консоль браузера: [ReactionsConfig] Loading...
  2. Проверить Network tab: /api/v1/communications/reactions/available/
  3. Проверить авторизацию (требуется @login_required)
  4. Проверить наличие реакций в БД: python check_reactions.py

Старые реакции всё ещё показываются

  1. Очистить кэш браузера (Ctrl+Shift+Delete)
  2. Hard reload (Ctrl+Shift+R)
  3. Проверить что используется новый chat-detail-enhanced.js

Ошибка "reactionsConfig is not defined"

  1. Проверить импорт в chat-detail-enhanced.js:
    import reactionsConfig from './config/reactionsConfig.js';
    
  2. Проверить что файл существует: static/js/config/reactionsConfig.js

Производительность

  • Запросов к БД: 1 на загрузку страницы чата
  • Кэш frontend: Да (весь сеанс)
  • Кэш backend: Можно добавить Redis (будущее)
  • Размер ответа: ~200-500 байт (8 реакций)
  • Время загрузки: <50ms

Тестирование

# Проверка БД
python check_reactions.py

# Проверка API (через curl, нужна авторизация)
curl -X GET http://localhost:9000/api/v1/communications/reactions/available/ \
     -H "Cookie: sessionid=YOUR_SESSION"

# Проверка frontend (открыть консоль браузера)
# Должны увидеть:
# [ReactionsConfig] ✓ Loaded reactions from API: [...]

Команды управления

# Инициализация дефолтных реакций
python manage.py init_reactions

# Проверка состояния
python check_reactions.py

# Сброс порядка (будущее)
python manage.py reset_reaction_order

# Импорт из JSON (будущее)
python manage.py import_reactions reactions.json