Ticker Announcements System
Real-time header announcements with acknowledgment tracking, rich text modals, and per-user/entity alert views.
Overview
The Ticker system provides organization-wide announcements via the admin header bar. Features include:
- Sliding Announcements - Animated ticker in header with rotation
- Acknowledgment Tracking - Per-user acknowledgment for important messages
- Rich Text Modals - Long-form announcements requiring modal interaction
- Alert Views - Staff/participant detail pages show targeted alerts
- Bootstrap Alert Styling - Color-coded by type (warning, system, announcement)
Architecture
┌─────────────────────────────────────────────────────────┐
│ Admin Header │
│ ┌─────────────────────────────────────────────────┐ │
│ │ RABS: [⚠️ Important Update - Click to Read ACK] │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ ticker_messages table │
│ - type: announcement | warning | system | success │
│ - target: all | staff | participants │
│ - requires_ack: boolean │
│ - is_rich_text: boolean │
│ - rich_content: HTML (for modals) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ ticker_acknowledgments table │
│ - message_id + user_id (unique) │
│ - acknowledged_at timestamp │
└─────────────────────────────────────────────────────────┘
Message Types & Colors
| Type | Color | Use Case |
|---|---|---|
warning / urgent | Red (alert-danger) | Critical alerts, safety issues |
system | Yellow (alert-warning) | System maintenance, required actions |
announcement | Blue (alert-primary) | General announcements |
success | Green (alert-success) | Positive news, achievements |
Acknowledgment Flow
Simple Message (requires_ack + no modal)
┌─────────────────────────────────────────────────────────┐
│ ⚠️ Staff meeting tomorrow at 2pm [✓ ACK] │
└─────────────────────────────────────────────────────────┘
│
▼ Click ACK button
│
POST /api/v1/ticker/messages/:id/acknowledge
│
▼
Message removed from ticker
Rich Text Message (requires_ack + is_rich_text)
┌─────────────────────────────────────────────────────────┐
│ ⚠️ New Policy Update [Click to Read & Acknowledge] │
└─────────────────────────────────────────────────────────┘
│
▼ Click anywhere on alert
│
┌────────────────────────────────┐
│ Modal Opens (Large) │
│ ┌────────────────────────────┐ │
│ │ New Policy Update (header) │ │
│ ├────────────────────────────┤ │
│ │ │ │
│ │ Rich HTML Content │ │
│ │ - Formatted text │ │
│ │ - Lists, tables │ │
│ │ - Links │ │
│ │ │ │
│ ├────────────────────────────┤ │
│ │ [I have read and acknowledge│ │
│ │ this] │ │
│ └────────────────────────────┘ │
└────────────────────────────────┘
Key Point: Rich text messages with requires_ack=true have NO ACK button in the ticker. Users MUST open the modal and click the acknowledge button to confirm they've read the content.
Database Schema
core_system.ticker_messages
CREATE TABLE core_system.ticker_messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
type TEXT NOT NULL DEFAULT 'announcement',
target TEXT NOT NULL DEFAULT 'all', -- 'all', 'staff', 'participants'
text TEXT NOT NULL, -- Ticker display text (or title for rich)
icon TEXT, -- Optional icon class
requires_ack BOOLEAN DEFAULT false,
priority INTEGER DEFAULT 0,
starts_at TIMESTAMP,
expires_at TIMESTAMP,
is_active BOOLEAN DEFAULT true,
is_rich_text BOOLEAN DEFAULT false, -- If true, opens modal
rich_content TEXT, -- HTML content for modal
created_by UUID,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
core_system.ticker_acknowledgments
CREATE TABLE core_system.ticker_acknowledgments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
message_id UUID REFERENCES core_system.ticker_messages(id),
user_id UUID NOT NULL,
acknowledged_at TIMESTAMP DEFAULT NOW(),
UNIQUE(message_id, user_id)
);
API Endpoints
Public (Authenticated)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/ticker/messages | Get active announcements for current user |
| POST | /api/v1/ticker/messages/:id/acknowledge | Acknowledge a message |
Admin Only
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/ticker/messages?all=true | Get all messages (including inactive) |
| POST | /api/v1/ticker/messages | Create new announcement |
| PUT | /api/v1/ticker/messages/:id | Update announcement |
| DELETE | /api/v1/ticker/messages/:id | Deactivate announcement |
| GET | /api/v1/ticker/messages/:id/acknowledgments | View who acknowledged |
Alerts (Per Entity)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/ticker/alerts/staff/:staffId | Alerts for staff member |
| GET | /api/v1/ticker/alerts/participant/:id | Alerts for participant |
Frontend Components
admin/src/js/shared/ticker.js
initTicker()- Initialize ticker and staff counterrenderCurrentMessage()- Render current message with animationshowMessageModal()- Open modal for rich text messagesacknowledgeMessage()- Send ACK to APIrotateNext()- Slide to next message
Admin Settings
Location: App Settings → Ticker section
Features:
- Create/edit/delete announcements
- "Requires Modal" checkbox for rich text
- Summernote rich text editor (loaded from CDN)
- Preview modal button
- View acknowledgment counts
Alerts Tab (Staff/Participant Detail)
Both staff and participant detail pages have an "Alerts" tab showing:
- Pending Count - Messages requiring acknowledgment
- Acknowledged Count - Already acknowledged
- Alert List - All targeted announcements with status
┌─────────────────────────────────────────────────────────┐
│ Alerts │
├─────────────────────────────────────────────────────────┤
│ [2 pending] [5 acknowledged] │
│ │
│ ⚠️ announcement | staff Jan 7, 2026 │
│ Important: New safety protocol in effect │
│ ✓ Acknowledged Jan 7, 2026 3:45 PM │
│ │
│ ⚠️ warning | all Jan 6, 2026 │
│ System maintenance tonight 10pm-2am │
│ ⏱️ Awaiting acknowledgment │
└─────────────────────────────────────────────────────────┘
Note: Alerts lookup uses the staff member's linked user_id from core_hr.staff to match acknowledgments.
Animation
Slide Transition
- Messages slide down when appearing (translateY with opacity)
- Messages slide up when rotating out
- 0.25s ease-in/out transitions
- 6 second rotation interval (configurable)
Pause on Hover
- Rotation pauses when mouse hovers over ticker
- Resumes when mouse leaves
Configuration
Environment Variables
None required - uses existing database.
Rotation Timing
// In ticker.js
const state = {
rotationMs: 6000 // 6 seconds between messages
};
Refresh Interval
Messages refresh every 2 minutes to pick up new announcements.
Best Practices
- Use rich text for policies - Anything requiring detailed reading
- Set expiration dates - Don't leave old announcements lingering
- Priority ordering - Higher priority shows first
- Target appropriately - Use 'staff' or 'participants' to reduce noise
- Check acknowledgment rates - Follow up on low acknowledgment