366 lines
14 KiB
Markdown
366 lines
14 KiB
Markdown
# 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
|
||
1. **One main page per domain** - Features live under their parent, not as separate menu items
|
||
2. **URL reflects depth** - Path structure shows relationship (`/admin/tryout/{id}/questions`)
|
||
3. **Tree as map** - Hierarchy tree shows structure; drill-down shows details
|
||
4. **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/tryouts` page 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
|
||
|
||
```python
|
||
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/tryouts` page
|
||
- **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
|
||
|
||
```python
|
||
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 `TryoutStats` info 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
|
||
|
||
1. ~~Normalization settings~~ - **RESOLVED**: Move under tryout context as `/admin/tryout/{id}/normalization`
|
||
|
||
2. ~~Import questions page~~ - **RESOLVED**: Import is tryout-level. Button on `/admin/tryouts` header, not a separate page.
|
||
|
||
3. **Tryout settings** - What settings are actually needed? (Scoring mode, time limits, selection criteria?)
|
||
|
||
4. **Global questions page** - Is `/admin/questions` (unfiltered) still useful, or should every question access go through tryout context?
|
||
|
||
5. **Templates deprecation** - Confirm that `/admin/templates` is truly unused and can be safely removed?
|
||
|
||
6. **Legacy routes for deleted pages** - Should `/admin/templates` and `/admin/basis-items` redirect 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 structure
|
||
- `PROJECT_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`<br>- Move import button to `/admin/tryouts` header<br>- Add normalization page spec (4.5)<br>- Rename import page spec (4.6)<br>- Update navigation and action buttons |
|