Developer Docs

Media Analytics Dashboard โ€” Developer Guide

Overview

The Media Analytics Dashboard provides platform administrators with real-time insights into media upload activity, storage consumption, file type distribution, and processing pipeline health across the Mallnline platform. It renders as one of five sub-tabs within the Admin Dashboard's Analytics section (Revenue | Blog | Media | Search | Alerts).

Component Purpose Location
MediaAnalytics.svelte Full analytics dashboard UI src/lib/components/admin/MediaAnalytics.svelte
GraphQL Queries 4 media subgraph queries src/lib/queries/adminAnalytics.ts
Admin Integration Sub-tab in Analytics panel src/routes/admin/+page.svelte
Unit Tests Utility function coverage tests/mediaAnalytics.test.ts

Architecture

graph TD
    A["Admin +page.svelte"] --> B["Analytics Sub-Tab Switcher"]
    B --> C["RevenueAnalytics"]
    B --> D["BlogAnalytics"]
    B --> E["MediaAnalytics"]
    B --> F2["SearchAnalytics"]
    B --> G2["AlertsAnalytics"]

    E --> F["GET_MEDIA_UPLOADS_BY_DAY"]
    E --> G["GET_MEDIA_TYPE_DISTRIBUTION"]
    E --> H["GET_MEDIA_STORAGE_BY_MALET"]
    E --> I["GET_MEDIA_STATUS_BREAKDOWN"]

    F --> J["media subgraph"]
    G --> J
    H --> J
    I --> J

    E --> K["AdminChart (bar)"]
    E --> L["AdminChart (line)"]
    E --> M["SVG Donut (MIME)"]
    E --> N["SVG Donut (Status)"]

    style E fill:#06b6d4,color:#fff
    style J fill:#dc2626,color:#fff

Data Flow

  1. User selects the Media sub-tab in the Analytics panel
  2. MediaAnalytics.svelte fires 4 parallel Promise.allSettled GraphQL requests
  3. Each response is independently handled (resilient to partial failures)
  4. Data is transformed into chart-ready formats and rendered

Component Props

MediaAnalytics

Prop Type Default Description
malets { maletID: string; name: string }[] [] Available Malets for filter dropdown

GraphQL Queries

GET_MEDIA_UPLOADS_BY_DAY

Daily upload volume with cumulative storage. Used for the bar chart (upload count) and line chart (storage growth).

query GetMediaUploadsByDay($filter: MediaAnalyticsFilter) {
  mediaUploadsByDay(filter: $filter) {
    days { date, count, totalSizeBytes }
    totalUploads
    totalStorageBytes
    periodStart
    periodEnd
  }
}

GET_MEDIA_TYPE_DISTRIBUTION

Files grouped by MIME type โ€” rendered as a donut chart with per-type legend showing count and storage.

query GetMediaTypeDistribution($filter: MediaAnalyticsFilter) {
  mediaTypeDistribution(filter: $filter) {
    mimetype
    count
    totalSizeBytes
  }
}

GET_MEDIA_STORAGE_BY_MALET

Storage leaderboard ranked by total bytes โ€” rendered as a table with medal rankings.

query GetMediaStorageByMalet($limit: Int, $filter: MediaAnalyticsFilter) {
  mediaStorageByMalet(limit: $limit, filter: $filter) {
    maletId
    fileCount
    totalSizeBytes
    averageFileSize
  }
}

GET_MEDIA_STATUS_BREAKDOWN

Processing pipeline health โ€” donut chart showing PENDING / COMPLETE / FAILED distribution.

query GetMediaStatusBreakdown {
  mediaStatusBreakdown {
    status
    count
  }
}

Filter Input

All queries accept MediaAnalyticsFilter:

Field Type Default Description
dateRange MediaAnalyticsDateRange LAST_30_DAYS Preset: LAST_7_DAYS, LAST_30_DAYS, LAST_90_DAYS, LAST_365_DAYS
maletId ID โ€” Optional Malet scope

UI Sections

KPI Cards

Card Source Field Formatting Accent Gradient
Total Uploads totalUploads formatCompact() Cyan #06b6d4 โ†’ #22d3ee
Total Storage totalStorageBytes formatBytes() Teal #14b8a6 โ†’ #2dd4bf
Avg File Size computed formatBytes() Purple #8b5cf6 โ†’ #a78bfa
MIME Types typeDistribution.length raw number Amber #f59e0b โ†’ #fbbf24

Charts

  • Upload Volume: Bar chart via AdminChart component, color #06b6d4 (cyan)
  • Storage Growth: Line chart via AdminChart, color #14b8a6 (teal), Y-axis in KB

Donut Charts

  • File Type Distribution: SVG donut with MIME_COLORS mapping, legend shows MIME subtype + count + storage
  • Processing Health: SVG donut with STATUS_COLORS (green/amber/red), legend shows status + count

Storage Leaderboard

Table with columns: Rank (emoji medals), Malet ID (truncated mono), Files, Total Storage (formatBytes), Avg File Size (formatBytes).


Utility Functions

`formatBytes(bytes: number): string`

Converts raw bytes to human-readable format with appropriate unit:

formatBytes(0)           // "0 B"
formatBytes(1536)        // "1.5 KB"
formatBytes(5242880)     // "5.0 MB"
formatBytes(1073741824)  // "1.0 GB"

MIME Color Map

9 pre-defined colors for common MIME types, with #6b7280 (gray) fallback for unknown types.


Access Control

Media analytics queries require:

  1. @RequirePermission(Permission.MANAGE_ANALYTICS) guard
  2. Runtime assertPlatformAdmin(actor) verification

The admin page is already guarded by the is_privileged / PLATFORM_ADMIN role check.


File Reference

File Purpose
src/lib/components/admin/MediaAnalytics.svelte Dashboard component
src/lib/queries/adminAnalytics.ts GraphQL queries + types (media section)
src/routes/admin/+page.svelte Sub-tab integration
src/lib/docs/media-analytics-api.md Backend API documentation
src/lib/docs/media-analytics-dashboard.md This document
tests/mediaAnalytics.test.ts Unit tests