Skip to content

feat(dashboard): real stats, system info panel, indexes and caching - #26

Merged
antosubash merged 14 commits into
mainfrom
feature/xenodochial-chaum
Apr 15, 2026
Merged

antosubash merged 14 commits into
mainfrom
feature/xenodochial-chaum

Conversation

@antosubash

Copy link
Copy Markdown
Owner

Summary

Replaces the placeholder dashboard with a data-rich overview showing real user/product counts and system information.

  • 4 stat cards with live data: Total Users, Active Users (7d), Products, Modules — replacing hardcoded placeholder values
  • System info panel: loaded modules with status badges, Python version, health check results with color-coded indicators
  • Backend stats engine (stats.py): queries users_user and products_product tables, reads module list from app.state.modules, runs health checks concurrently via asyncio.gather
  • 30-second TTL cache with asyncio.Lock to prevent concurrent coroutine stampedes
  • DB indexes: ix_users_user_last_login_at and ix_products_product_is_active with Alembic migration and guard tests in each owning module
  • Removed: in-memory product event counters (handlers.py deleted), event bus subscriptions from dashboard module
  • i18n: new keys for stat cards and system info in English and Spanish

Changes

Area Files
Stats backend modules/dashboard/dashboard/stats.py (new), endpoints/api.py, endpoints/views.py
Frontend modules/dashboard/dashboard/pages/Home.tsx (rewritten)
Module config module.py, pyproject.toml (added Users dependency)
i18n locales/en.json, locales/es.json
Indexes modules/users/users/models.py, modules/products/products/models.py, migration
Framework app_builder.py (store modules on app.state)
Tests test_dashboard.py (rewritten), index guards in test_models.py and test_products.py
Cleanup handlers.py (deleted)

Test plan

  • 11 dashboard tests pass (module meta, stats function, API endpoint, auth)
  • 29 integration tests pass
  • 2 index guard tests pass (users + products)
  • Ruff lint clean
  • Manual verification: login page shows sample accounts, dashboard loads with real data

- Cache module list on app.state.modules at startup instead of calling
  discover_modules() on every request (expensive entry-point rescan)
- Parallelize health checks with asyncio.gather instead of sequential loop
- Extract health status color map in Home.tsx, type accent as union
- Use typed literal unions for HealthCheck.status and SystemModule.status
- Deduplicate test setup with shared pytest fixture for stats call
- Add index on User.last_login_at (used by active users 7d query)
- Add index on Product.is_active (used by product count query)
- Add Alembic migration for both indexes
- Cache fetch_dashboard_stats result for 30 seconds to avoid
  repeated DB round-trips on rapid page loads
- Expose invalidate_stats_cache() for test isolation
Move User.last_login_at index test to users/tests/test_models.py and
Product.is_active index test to products/tests/test_products.py so
each module owns its own schema guarantees.
- Add asyncio.Lock to prevent concurrent coroutines from bypassing the
  TTL check and duplicating DB queries
- Return .copy() of cached dict to prevent caller mutation
- Remove unused `welcome` prop from Home.tsx Props interface
- Remove unnecessary JSX section comments
- Align _has_index_on helper pattern in products tests
- ruff format on stats.py and migration file
- biome format on generated i18n files (double→single quotes)
- Trim test_models.py to 298 lines (was 307, cap is 300)
- Remove dead welcome prop and section comments from Home.tsx
- biome format Home.tsx (collapse multi-line imports)
- biome check i18n generated files (double→single quotes, organize imports)
- ruff fix migration (remove unused sqlalchemy import, sort imports)
- ruff format test_models.py
@antosubash
antosubash merged commit 2cc3c17 into main Apr 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant