- Real-time updates (Laravel Reverb): live operator queue, live ticket
  chat/detail updates for operator and client, periodic fallback refresh
  with a visible countdown as a backstop for dropped websocket connections.
- SLA automation rules (Admin > Automatyzacja SLA): act on a ticket after
  N minutes of customer silence (change priority/status/team/assignee),
  evaluated every 15 minutes, reusing TicketService's own setters so
  automated changes get the same history/notification/broadcast a manual
  change would.
- New notification: every operator on a matching team gets notified when
  a new ticket lands in one of their subcategories.
- BookStack knowledge-base sidebar now also shown on the client's own
  ticket view (previously operator-only); suggestions everywhere now load
  in after first paint instead of blocking it.
- Client ticket view: shows assigned operator + team; page widened to
  match the operator's.
- Notification bell shows unread only; read notifications disappear
  instead of just dimming.
- Stats dashboard: sectioned layout, new breakdowns (by subcategory, CSAT
  by team/operator, top clients, client x subcategory cross-tab).
- Mobile: nav dropdowns (theme/notifications/profile) now expand full
  width instead of overflowing off-screen below 640px.
- Fixed two bugs that silently disabled all real-time updates (missing
  CSRF header on Echo's private-channel auth; a script-load-order race
  that could miss the livewire:init event) and the mariadb healthcheck
  (world-writable credentials file on this stack's NFS mount).
- Assorted test-suite fixes (roles virtual attribute needs the roles
  table seeded; a few missing seeds/wrong assertions found along the way).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 20:43:05 +02:00
parent def7c70887
commit 0b06687ea1
64 changed files with 3613 additions and 168 deletions

View File

@@ -3,6 +3,91 @@
All notable changes to this project are documented in this file. Format loosely
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [1.1.2] - 2026-07-22
### Added
- **Real-time updates (Laravel Reverb)** — the operator ticket queue now
updates live: new tickets appear, status/priority/team/assignee changes
and new replies re-sort/refresh the affected row, and closed/deleted/
reassigned-away tickets disappear, all without a manual refresh. The
ticket message thread is now "live chat": a reply from either side
appears for the other party instantly. Clients also see status/priority/
team/assignee changes and new history entries on their own ticket live.
Backed by two private channels (`operator.queue`, `ticket.{id}`) and two
broadcast events (`TicketQueueChanged`, `TicketMessagePosted`), sent
synchronously (no queue worker needed, consistent with how e-mail
notifications already work in this app).
- **Periodic fallback refresh** — since a websocket connection can drop
silently (backgrounded tab, network blip), the operator queue and both
ticket-detail views also poll themselves every 3060 seconds regardless
of broadcasting, with a small visible countdown badge so it's clear the
page is still refreshing on its own.
- **SLA automation rules** (Admin > Automatyzacja SLA) — configurable rules
that act on a ticket after N minutes of customer silence (optionally
scoped to a priority/category/team): change priority, status, team, or
assignee. Reuses the same `TicketService` setters a manual operator
action would, so automated changes get the same history entry,
notification, and (now) live broadcast as a human doing it. A new
scheduled command (`automation:run-rules`, every 15 minutes) evaluates
all enabled rules; each rule only fires once per ticket until a fresh
reply or a close/reopen resets it.
- **New notification: ticket landed in your team** — every operator on a
team whose subcategories match a newly created ticket now gets notified
(enabled by default; toggle like any other trigger in Admin > Szablony
e-mail).
- **BookStack knowledge-base sidebar on the client's own ticket view** —
previously only shown to operators; clients now see the same
category/subcategory-matched suggestions on their ticket page that they
saw while creating it.
- **Operator ticket view / client ticket view now show the assigned
operator and team** in the "Status i priorytet" card (client side).
- **Stats dashboard**: new breakdowns — tickets by subcategory, CSAT
average by team and by operator, top 10 clients by ticket volume (+ one
"Goście" bucket for guest submissions), and a client × subcategory
cross-tab (top 10 clients × top 5 subcategories, rest folded into
"Inne"). The whole dashboard is now organized into labeled sections
(Podsumowanie / Rozkład zgłoszeń / Obciążenie / Klienci / Ocena obsługi /
Trend) instead of one flat wall of cards.
### Changed
- BookStack suggestions (ticket-creation wizards, guest landing page,
operator/client ticket views) now load in a beat after the page's first
paint (`wire:init`) instead of blocking the initial render on BookStack's
API response.
- The notification bell shows **unread notifications only** — reading one
(by clicking it or "mark all as read") now removes it from the list
instead of just dimming it.
- The client ticket-view page is now the same width as the operator's
(1180px, up from 920px) — the main message-thread column is unaffected.
- Mobile: the theme/notifications/profile-menu dropdowns in the top nav
now expand to the full screen width below 640px instead of a fixed
narrow width that could overflow off-screen.
### Fixed
- Two bugs that silently disabled all real-time updates from the moment
Reverb was first wired in: (1) the Echo client never sent a CSRF token
when authorizing private channels, so every subscription attempt was
rejected by the app's own CSRF middleware; (2) the Echo setup script
(loaded as a deferred ES module) raced against Livewire's own
synchronously-loaded bootstrap script and could miss the `livewire:init`
event entirely, silently skipping the operator-queue subscription.
- The `mariadb` container's healthcheck was failing (`Access denied ...
using password: NO`) because its auto-generated credentials file had
world-writable permissions (an artifact of this stack's NFS-backed bind
mount) and MariaDB's client refuses to read credentials from a file
anyone can modify — the healthcheck now passes.
- Several pre-existing test-suite gaps found while working in this area:
`User::roles` (a virtual attribute backed by the `roles`/`role_user`
pivot, not a plain column) needs the `roles` table seeded before
assigning a role by key — now seeded automatically for every test in
`Tests\TestCase`. A handful of other tests were missing
`NotificationSetting`/`ReplyQuickAction` seed data, asserting a stale set
of default-enabled notification triggers, or using the wrong Notification
Fake assertion for a real (non-guest) recipient.
## [1.1.0] - 2026-07-22
### Added