Skip to content

v1.12 — Chat with context-bound discussions + CalDAV

Choose a tag to compare

@dripips dripips released this 12 May 22:05

v1.12 — Chat that knows context

Чат в HRMS теперь живёт двумя слоями:

  1. Standalone direct messages на `/conversations` (как Telegram-lite)
  2. Context-bound discussions прямо на странице сущности (Leave Request / Job Applicant) — обсуждение прикреплено к конкретному артефакту, без переключения вкладок

💬 Standalone chat

  • `/conversations` — список с unread-badge в sidebar nav
  • `/conversations/new` — multi-recipient selector
  • Composer: Enter=send, Shift+Enter=newline
  • Live broadcast через Turbo Streams — новое сообщение прилетает в открытые вкладки участников без F5
  • Read-tracking (last_read_at) → unread-каунтер обнуляется при открытии

🎯 Context-bound discussions (главная фича)

  • Открой `/leave_requests/123` → внизу страницы дискуссия с HR + manager + employee автоматически
  • `/job_applicants/456` → recruiter + HR могут обсуждать кандидата inline
  • `Conversation.discussion_for(target, viewer)` — idempotent: 1 тред на 1 сущность, новые участники подтягиваются автоматически
  • В общем `/conversations` context-bound треды получают tag `🌴 Leave #123` со ссылкой на сущность
  • Pivot из «ещё один Slack»: discussion привязан к артефакту → видно зачем вообще писать сообщение

📅 CalDAV subscribe feed

`GET /api/v1/me/calendar.ics?token=` — подписываемый feed для Google Calendar / Outlook / Apple Calendar:

  • Интервью пользователя (interviewer = current_user, ±диапазон 30d/180d)
  • Дни рождения сотрудников (для HR/manager/superadmin, ≤90d вперёд)
  • Без cancelled/no_show
  • Bearer auth через `?token=...` query-param (Google Calendar не умеет Authorization header — поэтому fallback)

Migrations

  • `conversations` (with polymorphic `targetable`, unique partial index)
  • `conversation_participants` (composite unique)
  • `messages` (conversation_id + created_at)

i18n

  • +22 keys × 3 locales → 2355/2355/2355

Quality

  • 120 examples, 0 failures (1 pre-existing pending)
  • Rubocop: 0 offenses
  • Zeitwerk: clean