Add Sync Rights button to SecurityRoleManager for top-level orgs
Button is only visible when organization.hasParent is false. Calls POST /api/security/roles/sync-rights then reloads the roles table.
Gate Support/Settings by rights, fix Network copy, loading on tab switch, nav divider
- Network card: updated description to use dynamic branch title label - Support card: fixed 404 by changing href /help → /support; gated by isSupport + VIEW_SUP...
Extract RoleRightsSyncService and add sync-rights endpoint
- RoleRightsSyncService: centralizes role rights sync logic for both OrgRole and **************** tables; startup and on-demand - DataLoader: delegates to Rol...
Make role rights DTOs enum-driven and add security model rights sync
- SecurityRoleDTO.fromOrgRole(): enumerate all RoleRightType values with DB settings as lookup — new rights appear with NOT_SPECIFIED automatically - ********...
Add membership type chip and promote/demote to Membership Status card, remove session timeout field
Add native updateMemberType and ensureTeamMemberRow queries to MemberRepository
Support chat UX — name updates, titles, notification count, datagrid
- TicketChat fires onVisitorNameChanged when NAME_CHANGED WS event arrives - SupportTicketWindow dispatches tool:title with requestorName on load and on name ...
Render system events as friendly text in visitor support chat
NAME_CHANGED system events no longer show raw JSON in the chat bubble; they display as a centered italic pill ("Changes name to {name}"). Other system events ar...
Show AG Grid loading overlay instead of empty state on leads page
Initialize loading state to true so the grid shows "Loading leads..." until the first fetch completes, preventing a flash of "No leads found".
Use getOrganizationByIdWithFeatures in AppAvailabilityInterceptor
Resolves LazyInitializationException on /api/security/leads and all other CRM/POS-gated paths. The interceptor called org.getFeatures() after the transaction cl...
Add findByIdWithFeatures to eagerly load Organization.features
JOIN FETCH prevents LazyInitializationException when features are accessed outside a transaction (e.g. in AppAvailabilityInterceptor).
Show city and subdivision in ticket visitor geo row
Display as "City, Region, Country (IP)" — nulls are filtered so it degrades gracefully when only country data is available
Expose city and subdivision in visitor geo lookup
- Extend GeoResult record with city and subdivision fields - Switch SupportTicketService.toDTO() to use GeoLookupService (IP-level lookup) instead of country-...
Add tab URL params to /account page for deep linking and refresh persistence
Tab state is now synced to **************** so links to specific tabs work and the correct tab stays selected on page refresh.
Build error in GeoLookupService and add NATS publish for agent messages
- Fix Optional vs List type mismatch in **************** - Inject NatsMessageService into MediaController - Publish to chat.session.{guid} after agent creates a...
Correct message sides in history and handle visitor name change events
- Use messageType=VISITOR_MESSAGE from API to determine left/right in history load - Add NAME_CHANGED system event rendering in SystemMessage and TicketChat
Real-time chat delivery, message sides, notifications, and name sync
- Keep NATS subscription alive on client unsubscribe to avoid breaking agent real-time delivery - Tag visitor messages with messageType=VISITOR_MESSAGE in getMe...
**************** uses instanceof for MEMBER type
Hibernate TYPE(m) = :type returns 0 results when bound to the base Member class in JOINED inheritance. For MEMBER type, fetch all and filter with !(m instanceof...
Resolve Members tab showing empty due to Hibernate TYPE() base-class issue
Hibernate's TYPE(m) = :type JPQL filter returns 0 results when the bound parameter is the base Member class (JOINED inheritance). This affects the members-subsc...
Enable Hibernate SQL logging to diagnose members query returning 0
Temporarily enabled org.hibernate.SQL=DEBUG to see what SQL the TYPE() JPQL query generates for the members-subscribers endpoint.
Show visitor flag, country, and IP in ticket header
- Add visitorIpAddress, visitorCountryCode, visitorCountryName to SupportTicketDTO type - Render flag emoji + country name + IP address row in TicketHeader for ...
Show visitor flag and location in support ticket header
- Inject PublicChatVisitorRepository and GeoLiteLocationRepository into SupportTicketService - Populate visitorIpAddress, visitorCountryCode, visitorCountryName...
Add diagnostic logging to getMembersAndSubscribers endpoint
Logs orgId, query result count, and per-member isActive status to help diagnose why Members tab shows empty list.
Tag visitor messages as VISITOR_MESSAGE type, add senderName to GET messages
- PublicChatService: set messageType=VISITOR_MESSAGE so frontend can distinguish visitor echoes from agent responses on the STOMP topic - MediaController.getM...
Treat VISITOR_MESSAGE type as always-from-them in TicketChat
Visitor messages published via PublicChatService carry messageType=VISITOR_MESSAGE. Explicitly mark these as author='them' regardless of memberId so they always...
Skip VISITOR_MESSAGE echoes in LiveSupportPanel STOMP handler
Visitor messages are now tagged messageType=VISITOR_MESSAGE by the backend. Skip these in the STOMP subscription so the visitor's own messages don't re-appear o...
Replace native WebSocket with STOMP/SockJS in LiveSupportPanel
- Add @stomp/stompjs and sockjs-client packages - Connect to media.{domain}/ws/public-chat via SockJS+STOMP instead of raw WebSocket to api.{domain} which was...
Fix end-to-end public chat real-time via STOMP/NATS
- Remove internalAuth requirement from PublicChatWebSocketInterceptor so visitors can connect directly using only their sessionToken - Include visitor display...
Add senderName to ChatMessageDto for support chat display names
Wire up status filter and auto-seed required templates on list
- EmailTemplateController.list() now accepts ?status= param and filters using the existing findByOrgIdAndStatus repository query - Auto-seeds required templat...
Auto-open support ticket popup on NEW_TICKET NATS notification
When a new support ticket arrives, the backend now sends a NEW_TICKET STOMP message in addition to PENDING_COUNT. The SupportCountContext handles it by dispatch...
Three support/chat issues — NATS relay, auto-popup, topic fallback
1. Switch SupportNotificationService and SupportStompRelayController from JetStream to core NATS — the CHAT_MESSAGES stream only covers chat.> so JetStrea...
Allow god-mode users to provision ownerless orgs; prefer FQDNs in domain resolution
Always trigger provision-theme on branding save; let backend resolve domain server-side
Add @Transactional to provision-theme for lazy domain loading; remove hardcoded domain from provision request
Write contact form description as chat message on public ticket creation
The description was only stored on the ticket entity and never appeared in the chat window. Added writeTextMessage() helper and call it after the system event s...
Separate ticket number/badges row from title in TicketHeader
Title was sharing a nowrap flex row with the ticket number and two badges, causing it to be cut off. Now ticket number and badges occupy their own compact row, ...
Add /contact-confirmed page with animated hero, timeline, and CTAs
Replace inline success message on contact form with a dedicated premium confirmation page: animated SVG checkmark with particle burst, 'What Happens Next' 3-ste...
Handle tickets key in support ticket list response
MediaService returns { tickets: [...], totalElements } but the frontend only checked for data.content, causing the list to always render empty.
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.