Files
yellow-bank-soal/ADMIN_TRYOUT_RESTRUCTURE_PLAN.md
2026-06-20 01:43:39 +07:00

366 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 |