Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Announcement

Announcement is a system-wide messaging feature that allows administrators to broadcast important information to targeted user groups. Announcements support priority levels, user targeting, and pinning capabilities to ensure critical messages reach the right users.

Core Concept

An Announcement represents a broadcast message with:

  • Title and Content: Message headline and body text
  • Priority Level: Visual importance indicator (Journal, Info, Warning, Urgent)
  • User Targeting: Specify which user groups should see the announcement
  • Pinning: Pin important announcements to the top of the list
  • Persistence: All announcements are stored permanently for historical reference

Data Model

pub struct Announcement {
    pub id: i64,
    pub title: String,
    pub content: String,
    pub user_group: Vec<i32>,           // Target user groups
    pub user_extra_groups: Vec<i32>,    // Target extra user groups
    pub is_pinned: bool,                // Whether pinned to top
    pub priority: AnnouncementPriority, // Visual importance
    pub created_at: PrimitiveDateTime,
    pub updated_at: PrimitiveDateTime,
}

Priority Levels

Announcements have four priority levels that indicate message importance:

  • Journal: Routine informational messages (default priority)
  • Info: General information that users should be aware of
  • Warning: Important messages requiring user attention
  • Urgent: Critical messages that need immediate attention

Priority levels are purely visual indicators—they don’t affect targeting or delivery. Frontend implementations should style these differently to draw appropriate attention.

User Targeting

Announcements use a flexible targeting system based on user groups:

Targeting Logic

An announcement is visible to a user if either condition is true:

  1. User’s primary user_group matches any group in announcement’s user_group array
  2. User’s user_extra_groups has any overlap with announcement’s user_extra_groups array

This OR-based logic allows administrators to target announcements broadly or narrowly:

  • Broadcast to all: Include all possible user groups
  • Target specific roles: Specify only relevant user groups
  • Mixed targeting: Combine primary and extra groups for fine-grained control

Empty Targeting

If both user_group and user_extra_groups are empty arrays, the announcement won’t be visible to any users. This can be useful for drafting announcements before activating them.

Announcement Lifecycle

1. Creation

Administrators create announcements through AdminCreateAnnouncement:

Process:

  1. Admin specifies title, content, targeting, priority, and pin status
  2. Announcement is inserted into database
  3. AnnouncementCreatedEvent is published to RabbitMQ
  4. Event hook can trigger side effects (cache invalidation, push notifications)

Permissions: SuperAdmin, Moderator

Event System: Creation triggers an internal event for extensibility. Currently, the event hook is a placeholder for future features like real-time push notifications or cache updates.

2. Display

Users retrieve announcements through NotificationService::ListAnnouncements:

Behavior:

  • Returns announcements targeted to the requesting user
  • Sorted by pinned status first (pinned on top), then by creation date (newest first)
  • Limited to 20 announcements per request
  • No pagination—shows the 20 most relevant announcements

Targeting Query: Uses PostgreSQL array operators (= ANY() for primary group, && for array overlap) with GIN indexes for performance.

Single Announcement: Users can also fetch a specific announcement by ID via GetAnnouncement, useful for detail pages or deep links.

3. Updates

Administrators can edit existing announcements through AdminEditAnnouncement:

Editable Fields: All fields (title, content, targeting, priority, pinning) can be modified

Effect: Changes are immediate—users will see updated content on next fetch

No History: The system doesn’t track edit history. If audit trail is needed, it’s handled through the admin operation logging system.

4. Deletion

Administrators can permanently remove announcements through AdminDeleteAnnouncement:

Permissions: SuperAdmin, Moderator

Effect: Hard delete from database—no soft delete or archiving

Use Cases:

  • Removing outdated announcements
  • Cleaning up test announcements
  • Deleting announcements posted in error

User Operations

List Announcements

Service: NotificationService::ListAnnouncements

Retrieves all announcements targeted to the current user, ordered by relevance (pinned first, then newest).

Response: Returns up to 20 announcements. No pagination—users see the most important/recent messages.

Targeting: Automatically filtered based on user’s group membership—no need to specify groups in request.

Get Single Announcement

Service: NotificationService::GetAnnouncement

Fetches a specific announcement by ID.

Use Case: Detail pages, direct links, or refreshing a single announcement without fetching the entire list.

Access Control: No additional access control beyond targeting—if an announcement exists and targets the user, they can retrieve it by ID.

Admin Operations

All admin operations require SuperAdmin or Moderator roles and are exposed through NotificationManageService.

Create Announcement

Operation: AdminCreateAnnouncement

Broadcasts a new message to users.

Parameters:

  • title: Message headline
  • content: Full message body (supports long text, formatting handled by frontend)
  • user_group: Array of primary user group IDs to target
  • user_extra_groups: Array of extra user group IDs to target
  • is_pinned: Whether to pin to top of list
  • priority: Visual importance indicator

Returns: New announcement ID

Event: Triggers AnnouncementCreatedEvent for extensibility (future push notifications, cache invalidation)

List Announcements

Operation: AdminListAnnouncements

Retrieves all announcements (not filtered by user targeting) for management purposes.

Pagination: Uses limit and offset for pagination

Sorting: Returns announcements in creation order (newest first)

Use Case: Admin dashboard showing all system announcements regardless of targeting

Edit Announcement

Operation: AdminEditAnnouncement

Updates an existing announcement.

Parameters: All fields can be modified (same as creation)

Returns: Updated announcement object

Effect: Changes are immediate—users see updated content on next fetch

Delete Announcement

Operation: AdminDeleteAnnouncement

Permanently removes an announcement from the database.

Parameters: Announcement ID

Returns: Empty response on success

Warning: Hard delete with no recovery mechanism. Ensure announcement should be permanently removed.

Pinning Behavior

Pinned announcements always appear at the top of the list, regardless of creation date:

Sorting Order:

  1. Pinned announcements (ordered by creation date, newest first)
  2. Unpinned announcements (ordered by creation date, newest first)

Use Cases:

  • Pin urgent system maintenance notices
  • Keep important policy changes visible
  • Highlight time-sensitive information

Frontend Consideration: Pinned announcements should be visually distinct (e.g., pin icon, different background) to indicate their importance.

Database Schema

Key schema details (from 20250814171450_create_entities_for_notification_module.sql):

Table: notification.announcement

id                BIGSERIAL PRIMARY KEY
title             TEXT NOT NULL
content           TEXT NOT NULL
user_group        INTEGER[] NOT NULL
user_extra_groups INTEGER[] NOT NULL
is_pinned         BOOLEAN NOT NULL DEFAULT FALSE
priority          announcement_priority NOT NULL DEFAULT 'journal'
created_at        TIMESTAMP NOT NULL DEFAULT NOW()
updated_at        TIMESTAMP NOT NULL DEFAULT NOW()

Indexes:

  • GIN index on user_group: Fast targeting queries
  • GIN index on user_extra_groups: Fast targeting queries
  • B-tree index on is_pinned: Efficient pinned-first sorting
  • B-tree index on priority: Potential future priority-based queries

No Foreign Key: User groups are stored as integer arrays with no foreign key constraint, providing flexibility for group management.

Event System

The announcement system uses internal events for lifecycle hooks:

Event: AnnouncementCreatedEvent

  • Published by: ManageService::AdminCreateAnnouncement
  • Consumed by: Internal AnnouncementEventHook (extensibility placeholder)
  • Route: notification.announcement_created on notification exchange
  • Payload: announcement_id, created_at timestamp

Current Implementation: The event hook is a placeholder. Future implementations might:

  • Invalidate frontend caches
  • Send push notifications to targeted users
  • Trigger webhooks for external integrations
  • Log analytics events

Frontend Integration Points

User Announcement Display

List View:

  1. Call ListAnnouncements on page load
  2. Display announcements with priority-based styling:
    • Urgent: Red/high-contrast styling
    • Warning: Yellow/amber styling
    • Info: Blue/neutral styling
    • Journal: Default/subtle styling
  3. Show pinned announcements with visual indicator (pin icon)
  4. Limit display to 20 announcements (no pagination needed)

Detail View:

  1. Provide “Read More” links using announcement ID
  2. Call GetAnnouncement to fetch full content
  3. Display full message with timestamp and priority indicator

Real-time Updates: Consider polling ListAnnouncements periodically (e.g., every 5 minutes) or implementing WebSocket for real-time announcement delivery.

Admin Management UI

Create Form:

  • Title input (required)
  • Content textarea (supports long text)
  • User group multi-select (checkboxes or dropdown)
  • Extra user groups multi-select
  • Priority dropdown (Journal, Info, Warning, Urgent)
  • Pin checkbox

List View:

  • Table showing all announcements
  • Columns: ID, Title, Priority, Pinned, Target Groups, Created, Updated
  • Edit and delete actions
  • Pagination controls (limit/offset)

Edit Form:

  • Pre-populate with existing values
  • Allow modification of all fields
  • Show last updated timestamp

Design Decisions

Why No Read Tracking?

Announcements don’t track which users have read them:

  • Simplicity: Avoids per-user state management
  • Broadcast Nature: Announcements are informational, not actionable
  • Scalability: No need to store read state for thousands of users
  • Use Case: For messages requiring acknowledgment, use notification systems with explicit confirmation flows

Why Hard Delete Instead of Soft Delete?

Announcements are permanently deleted rather than archived:

  • Clean Data: Old announcements clutter management UI
  • No Recovery Need: If an announcement needs to persist, don’t delete it
  • Admin Control: Admins have full control over lifecycle
  • Audit Trail: Admin operation logging provides deletion records if needed

Why Limit to 20 Announcements?

User-facing list is capped at 20 without pagination:

  • Relevance: Users don’t need to see dozens of old announcements
  • Performance: Keeps queries fast with simple sorting
  • UX: Encourages admins to keep announcements current
  • Workaround: For historical access, provide search/filter in admin panel

Why OR-Based Targeting?

Users see announcements if they match either primary group or extra groups:

  • Flexibility: Allows broad or narrow targeting
  • Ease of Use: Simpler than complex boolean logic
  • Common Use Case: “Show to all premium users OR all beta testers”
  • Empty Arrays: Provide draft mode (not visible to anyone)

See Also: