14 KiB
Admin UI Redesign - Implementation Plan
Overview
This plan outlines the migration from the current scattered admin structure to a clean, hierarchy-driven navigation centered on Tryouts.
Guiding Principles
- One main page per domain - Features live under their parent, not as separate menu items
- URL reflects depth - Path structure shows relationship (
/admin/tryout/{id}/questions) - Tree as map - Hierarchy tree shows structure; drill-down shows details
- Consistent naming - Use "Tryout" instead of "Exam" throughout
1. URL Structure
New URL Scheme
| Old Route | New Route | Description |
|---|---|---|
/admin/exams |
/admin/tryouts |
Hierarchy tree (main entry) |
/admin/student-attempts |
/admin/tryout/{tryout_id}/attempts |
Attempts filtered by tryout |
| - | /admin/tryout/{tryout_id}/questions |
Questions filtered by tryout |
| - | /admin/tryout/{tryout_id}/questions/{question_id}/workspace |
Question workspace |
| - | /admin/tryout/{tryout_id}/questions/{question_id}/workspace/{tab} |
Workspace tabs |
| - | /admin/tryout/{tryout_id}/normalization |
Normalization settings for this tryout |
/admin/questions |
/admin/questions |
Global question list (kept) |
| (none) | /admin/import-tryout |
Import tryout modal/page |
Note: Import is tryout-level, not question-level. Import button lives on
/admin/tryoutspage header.
Hierarchy Depth Convention
/admin/tryouts → Level 0: Root
/admin/tryout/{tryout_id} → Level 1: Entity
/admin/tryout/{tryout_id}/attempts → Level 2: Related data
/admin/tryout/{tryout_id}/questions → Level 2: Related data
/admin/tryout/{tryout_id}/questions/{id} → Level 3: Specific item
/admin/tryout/{tryout_id}/questions/{id}/workspace → Level 4: Detail view
2. Navigation Structure
Proposed Navigation
Questions
├── /admin/questions # Global question list
└── /admin/tryout/*/questions/*/workspace # Direct link from tree
Tryouts
├── /admin/tryouts # Tree: Website → Tryout → Stat → Actions + Import button
├── /admin/tryout/*/attempts # Filtered attempts
├── /admin/tryout/*/questions # Questions in this tryout
├── /admin/tryout/*/normalization # Normalization settings
└── /admin/import-tryout # Import modal/page
Reports
├── /admin/reports # Dashboard
├── /admin/item-statistics
└── /admin/calibration-status
Settings
├── /admin/settings
├── /admin/websites
└── /admin/password
Navigation Item Definition
ADMIN_NAV_ITEMS = (
("Dashboard", "/admin/dashboard", ("/admin/dashboard",)),
("Questions", "/admin/questions", (
"/admin/questions",
"/admin/tryout/*/questions/*/workspace", # Pattern for direct links
)),
("Tryouts", "/admin/tryouts", (
"/admin/tryouts",
"/admin/tryout/*/attempts",
"/admin/tryout/*/questions",
"/admin/tryout/*/normalization",
"/admin/import-tryout",
)),
("Reports", "/admin/reports", (
"/admin/reports",
"/admin/item-statistics",
"/admin/calibration-status",
)),
("Settings", "/admin/settings", (
"/admin/settings",
"/admin/websites",
"/admin/password",
)),
("Logout", "/admin/logout", ("/admin/logout",)),
)
3. Tryouts Tree Structure
Visual Design
┌─ Tryouts ───────────────────────────────────────────────────────────────────┐
│ │
│ [+ Import Tryout] │
│ │
│ 🌐 Website A │
│ │ │
│ ├─ 📋 132380 - UTBK 2024 [●] │
│ │ └─ [Expanded on click] │
│ │ │
│ ├─ 📋 132381 - SIMAK UI [✓] │
│ │ │
│ └─ 📋 132382 - PAS Semester 1 [○] │
│ │
│ 🌐 Website B │
│ └─ ... │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Expanded Tryout View:
┌─ 📋 132380 - UTBK 2024 ─────────────────────────────────────────────────────┐
│ │
│ ┌─ Stat Card ─────────────────────────────────────────────────────────┐ │
│ │ 👥 150 participants │ NM: 672 avg │ NN: 505 avg │ │
│ │ ✓ 98% completion │ 📐 Calibration: ████████░░ 85% (17/20) │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ [📝 Questions (20)] [👥 Attempts (150)] [📐 Normalization] [⚙ Settings]│
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Legend:
[●] Partial (50-89% calibrated)
[✓] Ready (≥90% calibrated)
[○] Needs Data (<50% calibrated)
Import Button Location
- Location: Header of
/admin/tryoutspage - Label: "[+ Import Tryout]" or "[Import Tryout JSON]"
- Behavior: Opens import modal/page
- Why: Import is tryout-level operation (imports questions WITH tryout context)
Stat Card Components
| Field | Source | Display |
|---|---|---|
| Participants | TryoutStats.participant_count |
👥 {count} |
| Avg NM | AVG(Session.NM) where completed |
📊 {value} avg |
| Avg NN | AVG(Session.NN) where completed |
📈 {value} avg |
| Completion Rate | completed / participants * 100 |
✓ {percentage}% |
| Calibration | calibrated_items / total_items |
📐 Progress bar + {count}/{total} |
Action Buttons
| Action | Target URL | Icon |
|---|---|---|
| Questions | /admin/tryout/{id}/questions |
📝 |
| Attempts | /admin/tryout/{id}/attempts |
👥 |
| Normalization | /admin/tryout/{id}/normalization |
📐 |
| Settings | /admin/tryout/{id}/settings (or modal) |
⚙ |
4. Page Specifications
4.1 /admin/tryouts (Main Tree)
Purpose: Primary navigation entry, shows structure at a glance
Default State:
- Websites expanded
- Tryouts collapsed
- Shows calibration indicator dot next to each tryout
Interactions:
- Click tryout → expand/collapse
- Expanded tryout shows stat card + action buttons
- Actions navigate to filtered views
4.2 /admin/tryout/{tryout_id}/questions
Purpose: View all questions in a specific tryout
Behavior:
- Shows only original/imported questions (basis items)
- Pre-filtered by
tryout_id - Links to workspace for AI variant generation
Table Columns:
| Column | Description |
|---|---|
| ID | Question internal ID |
| Stem Preview | First 100 chars of question text |
| Difficulty | Current difficulty level |
| Calibration | P-value or IRT-b indicator |
| Variants | Count of generated variants |
| Actions | [View] [Workspace] |
4.3 /admin/tryout/{tryout_id}/questions/{question_id}/workspace
Purpose: Generate and manage question variants
Tabs:
| Tab | Purpose |
|---|---|
| Generate | AI variant generation interface |
| Review | Review generated variants |
| Batch | Batch generation options |
Access Pattern:
- Opens from question list or tree direct link
- Context: knows parent tryout, parent question
4.4 /admin/tryout/{tryout_id}/attempts
Purpose: View student attempts for specific tryout
Current Implementation: Already exists at /admin/student-attempts → migrate URL
Enhancements:
- Pre-filtered by
tryout_id(no dropdown needed on this page) - Stat card from parent tryout shown at top
4.5 /admin/tryout/{tryout_id}/normalization
Purpose: Configure normalization settings for a specific tryout
Settings (per-tryout):
| Setting | Type | Default | Description |
|---|---|---|---|
| Mode | Select | Auto | Auto (calculate from data) or Manual (fixed values) |
| Rataan | Number | 500 | Target mean for normalization |
| SB | Number | 100 | Target standard deviation |
| Recalculate | Button | - | Re-run normalization on existing sessions |
Formula: NN = 500 + 100 × ((NM - Rataan) / SB)
UI:
- Simple form with current values
- "Recalculate" button triggers normalization job
- Shows last normalization timestamp
4.6 /admin/import-tryout
Purpose: Import tryout data (questions + metadata) from JSON
Access: Via "[+ Import Tryout]" button on /admin/tryouts page
Behavior:
- Opens modal or dedicated page
- Upload JSON file or paste JSON content
- Preview import before confirming
- Creates new tryout with questions
URL Convention: Not under specific tryout (it's creating a new one)
5. Deprecations
Routes to Remove
| Route | Reason |
|---|---|
/admin/exams |
Renamed to /admin/tryouts |
/admin/student-attempts |
URL changed to /admin/tryout/{id}/attempts |
/admin/templates |
AI uses basis items directly |
/admin/basis-items |
Merge into question workspace |
/admin/hierarchy |
Tree IS the hierarchy |
/admin/question-quality |
Merged into tryout stat card |
Legacy Redirects
LEGACY_URL_MAP = {
"/admin/exams": "/admin/tryouts",
"/admin/student-attempts": "/admin/tryouts", # Or redirect to tryouts with guidance
"/admin/hierarchy": "/admin/tryouts",
"/admin/question-quality": "/admin/tryouts",
# Templates and basis-items: 404 (removed)
}
6. Implementation Phases
Phase 1: Foundation
- Rename
/admin/exams→/admin/tryouts(keep old route for now) - Implement tree structure in
/admin/tryouts - Move
TryoutStatsinfo into tree stat cards - Add calibration indicator dots
Phase 2: URL Migration
- Create
/admin/tryout/{id}/attempts(redirect from old route) - Create
/admin/tryout/{id}/questions - Update navigation items
Phase 3: Workspace Integration
- Create question workspace route
- Implement workspace tabs
- Connect workspace to tree and question list
Phase 4: Cleanup
- Add legacy redirects
- Remove deprecated routes
- Update all hardcoded links in views
Phase 5: Polish
- Review all pages for consistency
- Update documentation
- Test all navigation paths
7. Open Questions
-
Normalization settings- RESOLVED: Move under tryout context as/admin/tryout/{id}/normalization -
Import questions page- RESOLVED: Import is tryout-level. Button on/admin/tryoutsheader, not a separate page. -
Tryout settings - What settings are actually needed? (Scoring mode, time limits, selection criteria?)
-
Global questions page - Is
/admin/questions(unfiltered) still useful, or should every question access go through tryout context? -
Templates deprecation - Confirm that
/admin/templatesis truly unused and can be safely removed? -
Legacy routes for deleted pages - Should
/admin/templatesand/admin/basis-itemsredirect somewhere or return 404?
8. Files to Modify
Primary Changes
app/admin_web.py- Major route restructuring- Navigation definition in
admin_web.py - Legacy URL map
Likely Additions
- Static assets for tree expansion/collapse (if not using existing)
Documentation Updates
ADMIN_UI_REDESIGN_PLAN.md- Update to reflect final structurePROJECT_UNDERSTANDING.md- Update route documentation
9. Changelog
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2026-06-17 | Initial draft based on discussion |
| 1.1 | 2026-06-17 | - Move normalization to /admin/tryout/{id}/normalization- Move import button to /admin/tryouts header- Add normalization page spec (4.5) - Rename import page spec (4.6) - Update navigation and action buttons |